计算机组成原理实验 - 实验五: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 |