计算机组成原理实验 - 实验六:运算器设计

实验内容

将算术逻辑单元与寄存器组集成,设计简单的运算器。

Sin,Sout:

Sin Sout 寄存器输入信号 寄存器输出信号
0 0 键盘输入 PC
0 1 键盘输入 res,即R[RA]
1 0 ALU计算结果输入 PC
1 1 ALU计算结果输入 res,即R[RA]

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清零信号。

ALU:

控制信号 s2 s1 s0 实现功能
000 F清零
001 A与B逻辑乘(&)
010 A与B逻辑加(|)
011 A与B逻辑异或(^)
100 A与B算数加
101 A逻辑左移一位
110 A逻辑右移一位
111 A算数右移一位

实验代码

顶层设计

注:实验和仿真时要对应的修改bdf中的Parameter的值!

bdf

CPU寄存器 CPU_register_group

注:l用于分频,clk_alt是分频时钟信号。

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;

parameter wei = 9;

always@(negedge clk) //分频
begin
	l<=l+1;
	clk_alt<=l[wei];
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。

注:因为clr绑定在按钮上,而按键按下为低电平,所以清理信号低电平有效,改为!clr。

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,negedge 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

ALU的暂存器组 midware

module midware(
	input clk,
	input [7:0]in,
	input sel,
	input wt,
	output reg [7:0] X,
	output reg [7:0] Y
);
	
always @(posedge clk)
begin
	if(wt)
		if(!sel)
			X = in[7:0];
		else	
			Y = in[7:0];
end
	
endmodule

ALU运算器

注:cin绑定在按键上,所以改为!cin。

module ALU(
	input clk,
	input [2:0] s,
	input cin,
	input [7:0] A,
	input [7:0] B,
	output reg overflow,
	output reg [7:0] F
);

reg [8:0] C;

always@(posedge clk)
begin
	case(s)
		3'b000: //F清零
		begin 
			overflow=0; 
			F=0;
		end
		3'b001: //逻辑乘
		begin
			overflow=0;
			F=A&B;
		end
		3'b010: //逻辑加
		begin
			overflow=0;
			F=A|B;
		end
		3'b011: //逻辑异或
		begin
			overflow=0;
			F=A^B;
		end
		3'b100: //算术加
		begin
			C = {A[7],A[7:0]}+{B[7],B[7:0]} + !cin;
			F = C[7:0];
			overflow = C[8]^C[7];
		end
		3'b101: //逻辑左移
		begin
			overflow=0;
			F = {A[6:0],1'b0};
		end
		3'b110: //逻辑右移
		begin
			overflow=0;
			F = {1'b0,A[7:1]};
		end
		3'b111: //算数右移
		begin
			overflow=0;
			F = {A[7],A[7:1]};
		end
	endcase
end

endmodule

仿真波形

仿真波形

引脚配置

Node Name Direction Location I/O Bark - - - -
cin Input PIN_AH8 3 B3_N1 PIN_AH8 2.5 V (default) 8mA (default)
clk Input PIN_A14 8 B8_N0 PIN_A14 2.5 V (default) 8mA (default)
clr Input PIN_AH7 3 B3_N2 PIN_AH7 2.5 V (default) 8mA (default)
key_c[3] PIN_AE14 3 B3_N0 PIN_AE14 2.5 V (default) 8mA (default)
key_c[2] PIN_AF13 3 B3_N1 PIN_AF13 2.5 V (default) 8mA (default)
key_c[1] PIN_AD12 3 B3_N3 PIN_AD12 2.5 V (default) 8mA (default)
key_c[0] PIN_AD11 3 B3_N3 PIN_AD11 2.5 V (default) 8mA (default)
key_out[3] PIN_E24 6 B6_N0 PIN_E24 2.5 V (default) 8mA (default) 2 (default)
key_out[2] PIN_F22 7 B7_N0 PIN_F22 2.5 V (default) 8mA (default) 2 (default)
key_out[1] PIN_E22 7 B7_N0 PIN_E22 2.5 V (default) 8mA (default) 2 (default)
key_out[0] PIN_F21 7 B7_N0 PIN_F21 2.5 V (default) 8mA (default) 2 (default)
key_r[3] PIN_AE11 3 B3_N0 PIN_AE11 2.5 V (default) 8mA (default) 2 (default)
key_r[2] PIN_AF11 3 B3_N1 PIN_AF11 2.5 V (default) 8mA (default) 2 (default)
key_r[1] PIN_AE12 3 B3_N0 PIN_AE12 2.5 V (default) 8mA (default) 2 (default)
key_r[0] PIN_AE13 3 B3_N0 PIN_AE13 2.5 V (default) 8mA (default) 2 (default)
LED_seg[7] PIN_M21 6 B6_N1 PIN_M21 2.5 V (default) 8mA (default) 2 (default)
LED_seg[6] PIN_G12 8 B8_N2 PIN_G12 2.5 V (default) 8mA (default) 2 (default)
LED_seg[5] PIN_G14 8 B8_N0 PIN_G14 2.5 V (default) 8mA (default) 2 (default)
LED_seg[4] PIN_G15 7 B7_N3 PIN_G15 2.5 V (default) 8mA (default) 2 (default)
LED_seg[3] PIN_G18 7 B7_N2 PIN_G18 2.5 V (default) 8mA (default) 2 (default)
LED_seg[2] PIN_F18 7 B7_N1 PIN_F18 2.5 V (default) 8mA (default) 2 (default)
LED_seg[1] PIN_G17 7 B7_N2 PIN_G17 2.5 V (default) 8mA (default) 2 (default)
LED_seg[0] PIN_G16 7 B7_N3 PIN_G16 2.5 V (default) 8mA (default) 2 (default)
LED_sel[2] PIN_G9 8 B8_N3 PIN_G9 2.5 V (default) 8mA (default) 2 (default)
LED_sel[1] PIN_D22 7 B7_N0 PIN_D22 2.5 V (default) 8mA (default) 2 (default)
LED_sel[0] PIN_C22 7 B7_N1 PIN_C22 2.5 V (default) 8mA (default) 2 (default)
M[1] Input PIN_AA10 3 B3_N1 PIN_AA10 2.5 V (default) 8mA (default)
M[0] Input PIN_U8 2 B2_N3 PIN_U8 2.5 V (default) 8mA (default)
overflow PIN_AE8 3 B3_N3 PIN_AE8 2.5 V (default) 8mA (default) 2 (default)
RA[1] PIN_AF12 3 B3_N1 PIN_AF12 2.5 V (default) 8mA (default)
RA[0] PIN_AG12 3 B3_N0 PIN_AG12 2.5 V (default) 8mA (default)
rd Input PIN_AH6 3 B3_N2 PIN_AH6 2.5 V (default) 8mA (default)
reset Input PIN_AE3 2 B2_N3 PIN_AE3 2.5 V (default) 8mA (default)
s[2] Input PIN_AA8 2 B2_N1 PIN_AA8 2.5 V (default) 8mA (default)
s[1] Input PIN_AB8 2 B2_N3 PIN_AB8 2.5 V (default) 8mA (default)
s[0] Input PIN_AE4 2 B2_N3 PIN_AE4 2.5 V (default) 8mA (default)
sel Input PIN_AD4 2 B2_N3 PIN_AD4 2.5 V (default) 8mA (default)
sin Input PIN_AH12 3 B3_N1 PIN_AH12 2.5 V (default) 8mA (default)
sout Input PIN_AF14 3 B3_N0 PIN_AF14 2.5 V (default) 8mA (default)
wr Input PIN_AF5 3 B3_N2 PIN_AF5 2.5 V (default) 8mA (default)
wt Input PIN_AC5 2 B2_N3 PIN_AC5 2.5 V (default) 8mA (default)