计算机组成原理实验 - 实验五:CPU寄存器组的设计

实验内容

实验要求:用VDH语言设计CPU寄存器组,其包括4个8位通用寄存器(R0~R3)和一个8位专用寄存器PC, R0-R3&PC 操作方式见下表格,之后要将PC和R0-R3(其中一个)输出并用4个数码管显示。 R0-R3:

寄存器 控制信号 RA1 RA0 Wr Rd 操作
R0 0 0 0 1 写入
R0 0 0 1 0 读出
R1 0 1 0 1 写入
R1 0 1 1 0 读出
R2 1 0 0 1 写入
R2 1 0 1 0 读出
R3 1 1 0 1 写入
R3 11 1 0 读出

RA控制R0~R3的选择,Wr和Rd控制输入和输出。

PC

寄存器 控制信号 M1 M0 操作
PC 0 0 置数
PC 0 1 加一计数
PC 1 0 减一计数
PC 1 1 保持

reset为低电平有效的PC清零信号。

实验代码

顶层设计 exp5

module exp5(
	input clk,
	input [3:0] KEY_C,
	input clr, //K[0]
	output [3:0] KEY_R,
	output [7:0] seg,
	output [2:0] sel,
	
	input [1:0] M,RA, // k[6:7] K[2:3]
	input wr,rd,reset, // K[4] k[5] k[8]
	
	output [7:0] PC,res,
	
	output [7:0] R0,R1,R2,R3,
	output [15:0] key_out
);

keymodule(clk,KEY_C,clr,KEY_R,key_out);

CPU_register_group(M,RA,key_out[7:0],wr,rd,reset,clk,PC,res,R0,R1,R2,R3);

segment_displays( clk,{key_out,PC,res},seg,sel);


endmodule

CPU寄存器 CPU_register_group

注:l用于分频,clk_alt是分频时钟信号。仿真时设置clk_alt<=l[0],实验时clk_alt<=l[9],l[9]可能还是太快了,可以设置的更高。

module CPU_register_group(
	input [1:0] M,RA,
	input [7:0] D,
	input wr,rd,reset,
	input clk,
	output reg [7:0] PC,res,
	output reg[7:0] R0,R1,R2,R3
);


reg clk_alt;
reg [9:0] l;

always@(negedge clk) //分频
begin
	l<=l+1;
	clk_alt<=l[9];
end

always @(negedge clk_alt or negedge reset) //处理PC的值
begin
	if(!reset)
		PC = 0;
	else
	begin
		case(M)
		0:PC = D;
		1:PC=PC+1;
		2:PC=PC-1;
		default:PC = PC;
		endcase
	end
end

always @(negedge clk) //处理寄存器的值
begin
	case(RA)
	0:begin
		if(wr==0&&rd==1)
			R0=D;
		else if(wr==1&&rd==0)
			res=R0;
	end
	1:begin
		if(wr==0&&rd==1)
			R1=D;
		else if(wr==1&&rd==0)
			res=R1;
	end
	2:begin
		if(wr==0&&rd==1)
			R2=D;
		else if(wr==1&&rd==0)
			res=R2;
	end
	3:begin
		if(wr==0&&rd==1)
			R3=D;
		else if(wr==1&&rd==0)
			res=R3;
	end
	endcase

end

endmodule

矩阵键盘 keymodule

注:COUNT_MAX用于防抖,当其小于10左右会出现抬起抖动读取,建议在实验时设置为100或1000;在仿真时设置为1。

module keymodule(
	input clk,
	input [3:0] KEY_C,
	input clr,
	output reg[3:0] KEY_R,
	output reg[15:0] out
);

parameter COUNT_MAX = 32'd1000; //没有按键按下的延迟时间

reg [1:0] cnt = 2'd0;
reg [4:0] num =5'd16;
reg [31:0] count_num=COUNT_MAX;

initial
	KEY_R = 4'b1110;

//根据按钮的列扫描信号和行输入信号判断按钮是否被按下
always  @(posedge clk,posedge clr)
begin
	if(clr)
	begin
		cnt<=2'b0;
		out<=16'h0000;
		count_num<=COUNT_MAX; //让下一次就能读取
	end
	else
	begin
		if(KEY_C==4'b1111)
		begin
			//num = 5'd16;
			cnt = cnt + 1'b1;
			case (cnt)
				2'b00:	KEY_R <= 4'b1110;
				2'b01:	KEY_R <= 4'b1101;
				2'b10:	KEY_R <= 4'b1011;
				2'b11:	KEY_R <= 4'b0111;         
			endcase
			//计数分频防止位移过快
			if(count_num < COUNT_MAX)
				count_num = count_num + 1'b1;
		end
		else 
		begin 
		  case ({KEY_C, KEY_R})
			 8'b_1110_1011: num = 5'd0;
			 8'b_0111_0111: num = 5'd1;
			 8'b_0111_1011: num = 5'd2;
			 8'b_0111_1101: num = 5'd3;
			 
			 8'b_1011_0111: num = 5'd4;
			 8'b_1011_1011: num = 5'd5;
			 8'b_1011_1101: num = 5'd6;
			 8'b_1101_0111: num = 5'd7;  
			 
			 8'b_1101_1011: num = 5'd8;
			 8'b_1101_1101: num = 5'd9;
			 8'b_0111_1110: num = 5'd10;
			 8'b_1011_1110: num = 5'd11;  
			 
			 8'b_1101_1110: num = 5'd12;
			 8'b_1110_1110: num = 5'd13;
			 8'b_1110_0111: num = 5'd14;
			 8'b_1110_1101: num = 5'd15;  
		  endcase
		  if(count_num >= COUNT_MAX) //没有按键按下的空闲时间够长(防抖)
			begin
				count_num = 32'b0;
				//移位	
				out=out<<4;
				out[3:0] = num[3:0];
			end
		end //end KER_R!=4'b1111
	end //end if(clr) else
	
end //end always
endmodule

数码管输出 segment_displays

module segment_displays(
	input clk,
	input [31:0] N,
	output reg [7:0] seg,
	output reg [2:0] sel
);
	
reg [3:0] num;

always@(posedge clk)
begin
	sel=sel+1;
	case(sel)
		3'b000:num=N[31:28];
		3'b001:num=N[27:24];
		3'b010:num=N[23:20];
		3'b011:num=N[19:16];
		3'b100:num=N[15:12];
		3'b101:num=N[11:8];
		3'b110:num=N[7:4];
		3'b111:num=N[3:0];
	endcase
end
always@(num)
begin
	case(num)
		4'h0:seg=8'b00111111;	//"0"
		4'h1:seg=8'b00000110;	//"1"
		4'h2:seg=8'b01011011;	//"2"
		4'h3:seg=8'b01001111;	//"3”
		4'h4:seg=8'b01100110;	//"4"
		4'h5:seg=8'b01101101;	//"5"
		4'h6:seg=8'b01111101;	//"6"
		4'h7:seg=8'b00000111;	//"8"
		4'h8:seg=8'b01111111;	//"8"
		4'h9:seg=8'b01101111;	//"9"
		4'hA:seg=8'b01110111;	//"A"
		4'hB:seg=8'b01111100;	//"b"
		4'hC:seg=8'b00111001;	//"c"
		4'hD:seg=8'b01011110;	//"d"
		4'hE:seg=8'b01111001;	//"E"
		4'hF:seg=8'b01110001;	//"F"
		default:seg=8'b00000000;	//"dark"
	endcase
end
	
endmodule

仿真波形

仿真波形

引脚配置

信号 输出/输出 引脚 信号 输出/输出 引脚
KEY_C[3] Input PIN_AE14 rd Input PIN_AC5
KEY_C[2] Input PIN_AF13 reset Input PIN_AA10
KEY_C[1] Input PIN_AD12 seg[7] Output PIN_M21
KEY_C[0] Input PIN_AD11 seg[6] Output PIN_G12
KEY_R[3] Output PIN_AE11 seg[5] Output PIN_G14
KEY_R[2] Output PIN_AF11 seg[4] Output PIN_G15
KEY_R[1] Output PIN_AE12 seg[3] Output PIN_G18
KEY_R[0] Output PIN_AE13 seg[2] Output PIN_F18
M[1] Input PIN_AF12 seg[1] Output PIN_G17
M[0] Input PIN_AG12 seg[0] Output PIN_G16
RA[1] Input PIN_AA8 sel[2] Output PIN_G9
RA[0] Input PIN_AB8 sel[1] Output PIN_D22
clk Input PIN_A14 sel[0] Output PIN_C22
clr Input PIN_AH12 wr Input PIN_AE4

解释说明

RTL