要求采用原理图输入方式设计顶层文件,实现 ALU 与寄存器组的集成。将 8 位 ALU 和寄存器组设计文件分别进行编译,将 ALU 和寄存器组设计文件生成两个模块符号。新建一个原理图设计文件,调入 ALU 和寄存器组的符号模块,把这两个模块进行连接,加上输入端和输出端,实现二者的集成。
ALU 的输入数据可来自寄存器组中指定的通用寄存器 R0~R3,也可来自 8 位的 PC 寄存器。ALU的输出可存放到指定的通用寄存器 R0~R3,也可存放到 8 位的 PC 寄存器寄。可通过一个控制信号 Sout 来控制将某一个通用寄存器 R0~R3 的数据输出给 ALU 的输入端,还是将 8 位 PC 寄存器的数据输出给 ALU 的输入端。
4 个通用寄存器 R0~R3 以及 PC 可通过 8 位数据输入引脚接收外部输入的 8 位数据 Data,也可接收来自 ALU 的运算结果。可通过一个控制信号 Sin 来控制寄存器接收的数据是来自外部数据引脚还是 ALU 的输出。
4 个通用存器 R0~R3 的输出连接到两个七段数码管显示,PC 的输出也连接到两个七段数码管显 示。
ALU与寄存器组集成的结构框图
一、实验分析与设计
由实验内容可将程序分为四个部分:外部输入模块、CPU寄存器组模块、ALU计算模块,外部显示模块。
外部输入模块:由矩阵键盘输入值八位值D。由于需要多次读取键盘值,此处采用状态机实现:读取值1——等待(当前按键松开,避免重复读取)——读取值2——等待。读取两次键盘,共八位,存入D中。可参照本专栏文章
CPU寄存器组模块:由Sin控制存入值T为外部输入值D还是ALU计算值F。M、RA等控制寄存器组。由Sout控制输出值CA为通用寄存器值R还是专用寄存器值PC。可参照本专栏文章
ALU计算模块:计算的输入值为寄存器组的输出值CA,计算后输出值为F。可参照本专栏文章
外部显示模块:将外部输入值D,寄存器输出值CA,ALU计算输出值F显示在数码管上。通过SEL控制动态扫描。
二、程序代码
顶层模块
module sy6(clk,key_R,key_C,D,Sin,M,RESET,RA,Wr,Rd,Sout,CA,Cin,S,Sel,Wt,Overflow,F,SEL,code);
input clk;
input[3:0]key_R;
output [3:0]key_C;
output [7:0]D;
input Sin;
input [1:0]M;
input RESET;
input [1:0]RA;
input Wr,Rd;
input Sout;
output [7:0]CA;
input Cin;
input [2:0]S;
input Sel,Wt;
output Overflow;
output [7:0]F;
output [2:0]SEL;
output [7:0]code;
sy6_input s1(clk,key_R,key_C,D); //获取键盘输入的值到D
sy6_CPURegister s2(clk,Sin,D,F,M,RESET,RA,Wr,Rd,Sout,CA); //输入外部值D或ALU计算值F,输出寄存器组的值CA
sy6_ALU s3(clk,Cin,CA,S,Sel,Wt,Overflow,F); //输入来自寄存器组的值CA,计算得值F
sy6_show s4(clk,D,CA,F,SEL,code); //输出D,CA,F的值
endmodule
外部输入模块
module sy6_input(clk,key_R,key_C,D);
input clk;
input[3:0]key_R;
output reg[3:0]key_C;
output reg[7:0]D;
reg flag;
reg [1:0]row;
reg [3:0]Q;
always @(posedge clk)
begin
if(key_R==4'b1111)
flag=0;
else
flag=1;
if(flag==0)
row=row+1;
end
always @(posedge clk)
begin
case(row)
0:key_C=4'b1110;
1:key_C=4'b1101;
2:key_C=4'b1011;
3:key_C=4'b0111;
endcase
end
always @(posedge clk)
begin
case({key_C,key_R})
8'b11101110:Q=4'hd;
8'b11101101:Q=4'hf;
8'b11101011:Q=4'h0;
8'b11100111:Q=4'he;
8'b11011110:Q=4'hc;
8'b11011101:Q=4'h9;
8'b11011011:Q=4'h8;
8'b11010111:Q=4'h7;
8'b10111110:Q=4'hb;
8'b10111101:Q=4'h6;
8'b10111011:Q=4'h5;
8'b10110111:Q=4'h4;
8'b01111110:Q=4'ha;
8'b01111101:Q=4'h3;
8'b01111011:Q=4'h2;
8'b01110111:Q=4'h1;
endcase
end
reg [1:0]state=2'b00;
integer k = 0;
//状态机实现读取多次值
always @(posedge clk)
begin
if(state == 2'b00 && flag) //取值1
begin
k = 0;
D[7:4] = Q;
state = 2'b01;
end
else if(state == 2'b01) //等待
begin
if(k > 100000) state = 2'b10;
else k = k + 1;
end
else if(state == 2'b10 && flag) //取值2
begin
k = 0;
D[3:0] = Q;
state = 2'b11;
end
else if(state == 2'b11) //等待
begin
if(k > 100000) state = 2'b00;
else k = k + 1;
end
end
endmodule
CPU寄存器组模块
module sy6_CPURegister(clk,Sin,D,F,M,RESET,RA,Wr,Rd,Sout,CA);
input clk,Sin;
input [7:0]D,F;
input [1:0]M;
input RESET;
input [1:0]RA;
input Wr,Rd;
input Sout;
output reg[7:0]CA;
reg [7:0]T,R,R0,R1,R2,R3,PC;
//输入值
always@(Sin)
begin
if(Sin) T =F;
else T = D;
end
//通用寄存器
always@(RA,Wr,Rd)
begin
if(!Wr & Rd)
begin
case(RA)
2'b00 : R0 = T;
2'b01 : R1 = T;
2'b10 : R2 = T;
2'b11 : R3 = T;
endcase
end
else if(Wr & !Rd)
begin
case(RA)
2'b00 : R = R0;
2'b01 : R = R1;
2'b10 : R = R2;
2'b11 : R = R3;
endcase
end
end
//分频,实现PC加一、减一
reg clk1 = 0;
integer k = 0;
always@(posedge clk)
begin
if(k < 100000) k = k + 1;
else
begin
k = 0;
clk1 = ~clk1;
end
end
//PC
always@(negedge clk1)
begin
if(!RESET) PC = 8'd0;
else
begin
case(M)
2'b00 : PC = PC;
2'b01 : PC = PC + 1'b1;
2'b10 : PC = PC - 1'b1;
2'b11 : PC = T;
endcase
end
end
//输出值
always@(posedge clk)
begin
if(Sout) CA = PC;
else CA = R;
end
endmodule
ALU计算模块
module sy6_ALU(clk,Cin,D,S,Sel,Wt,Overflow,F);
input clk,Cin;
input[7:0] D;
input[2:0] S;
input Sel,Wt;
output Overflow;
output reg[7:0]F;
reg Overflow = 0;
reg[8:0] A,B,FT;
//输入
always@(posedge Wt)
begin
if(Sel == 0)
begin
A[7:0] = D;
A[8] = D[7];
end
else
begin
B[7:0] = D;
B[8] = D[7];
end
end
//计算
always@(S)
begin
Overflow = 0;
case(S)
3'd0: FT = 9'd0;
3'd1: FT = A & B;
3'd2: FT = A | B;
3'd3: FT = A ^ B;
3'd4:
begin
FT = A + B + Cin;
if(FT[8] ^ FT[7]) Overflow = 1;
end
3'd5: FT[7:0] = {A[6:0],1'b0};
3'd6: FT[7:0] = {1'b0,A[7:1]};
3'd7: FT = A >> 1;
default: FT = 9'd0;
endcase
F = FT[7:0];
end
endmodule
外部显示模块
module sy6_show(clk,D,CA,F,SEL,code);
input clk;
input [7:0]D,CA,F;
output reg[2:0]SEL;
output reg[7:0]code;
reg[4:0]Data;
always@(posedge clk)
begin
if(SEL < 3'b111) SEL = SEL + 1;
else SEL = 3'b000;
end
reg showno=0;
always@(SEL)
begin
case(SEL)
3'b000 : begin showno = 0;Data = D[7:4];end
3'b001 : begin showno = 0;Data = D[3:0];end
3'b010 : showno = 1; //空一位,不显示
3'b011 : begin showno = 0;Data = CA[7:4];end
3'b100 : begin showno = 0;Data = CA[3:0];end
3'b101 : showno = 1; //空一位,不显示
3'b110 : begin showno = 0;Data = F[7:4];end
3'b111 : begin showno = 0;Data = F[3:0];end
endcase
end
always @(Data)
begin
if(showno) code = 8'h00;
else
case(Data)
4'd0 : code = 8'h3f;
4'd1 : code = 8'h06;
4'd2 : code = 8'h5b;
4'd3 : code = 8'h4f;
4'd4 : code = 8'h66;
4'd5 : code = 8'h6d;
4'd6 : code = 8'h7d;
4'd7 : code = 8'h07;
4'd8 : code = 8'h7f;
4'd9 : code = 8'h6f;
4'd10: code = 8'h77;
4'd11: code = 8'h7c;
4'd12: code = 8'h39;
4'd13: code = 8'h5e;
4'd14: code = 8'h79;
4'd15: code = 8'h71;
default : code = 8'bx;
endcase
end
endmodule
标签:begin,code,end,计算机,clk,CA,实验,input,运算器
From: https://blog.csdn.net/gwlCSDN/article/details/140604129