本文最后更新于 481 天前,其中的信息可能已经有所发展或是发生改变。
译码器
译码器的指令系统表如下图所示。
译码器做起来其实不难,当编码符合要求的时候,把相应的汇编符号输出设为1就行了。
R1、R2代表操作寄存器的地址,可以为A、B或C寄存器中的任何一个,地址分别为00、01和10。
所谓”符合要求“,可以举个例子。比如NOT的编码是0101 R1XX
,R1代表寄存器1的地址,XX是通配符,所以可以做匹配IR[7-:4]==4'b0101
,而且应为寄存器地址的地方不能是11。(话说也没多少人会在这个位置传进11吧……除了喜欢点一杯炒饭的测试工程师)
特别注意的是,有三种MOV指令。这里定义第一种MOV指令为MOVA,第二种为MOVB,第三种为MOVC。我先使用1100匹配进MOV,然后再区分MOVA、MOVB和MOVC。
module decoder (EN,IR,MOVA,MOVB,MOVC,ADD,SUB,AND,NOT,RSR,RSL,JMP,JZ,JC,IN,OUT,NOP,HALT);
input EN;
input[7:0] IR;
output MOVA,MOVB,MOVC,ADD,SUB,AND,NOT,RSR,RSL,JMP,JZ,JC,IN,OUT,NOP,HALT;
reg MOVA,MOVB,MOVC,ADD,SUB,AND,NOT,RSR,RSL,JMP,JZ,JC,IN,OUT,NOP,HALT;
always @(IR,EN) begin
if(EN==1'b1) begin
if (IR[7-:4]==4'b1100) begin //MOV
if(IR[3-:2]==2'b11) begin //MOVB 11R2
MOVA=1'b1;
MOVB=1'b0;
MOVC=1'b0;
end
else if (IR[1-:2]==2'b11) begin //MOVC R1111
MOVA=1'b0;
MOVB=1'b0;
MOVC=1'b1;
end
else begin //MOVA R1R2
MOVA=1'b1;
MOVB=1'b0;
MOVC=1'b0;
end
end
else begin
MOVA=1'b0;
MOVB=1'b0;
MOVC=1'b0;
end
if (IR[7-:4]==4'b1001 && IR[3-:2]!=2'b11 && IR[1-:2]!=2'b11) begin //ADD
ADD=1'b1;
end
else ADD=1'b0;
if (IR[7-:4]==4'b0110 && IR[3-:2]!=2'b11 && IR[1-:2]!=2'b11) begin //SUB
SUB=1'b1;
end
else SUB=1'b0;
if (IR[7-:4]==4'b1011 && IR[3-:2]!=2'b11 && IR[1-:2]!=2'b11) begin //AND
AND=1'b1;
end
else AND=1'b0;
if (IR[7-:4]==4'b0101 && IR[3-:2]!=2'b11) begin //NOT
NOT=1'b1;
end
else NOT=1'b0;
if (IR[7-:4]==4'b1010 && IR[1-:2]==2'b00 && IR[3-:2]!=2'b11) begin //RSR
RSR=1'b1;
end
else RSR=1'b0;
if (IR[7-:4]==4'b1010 && IR[1-:2]==2'b11 && IR[3-:2]!=2'b11) begin //RSL
RSL=1'b1;
end
else RSL=1'b0;
if (IR[7:0]==8'b0011_0000) begin //JMP
JMP=1'b1;
end
else JMP=1'b0;
if (IR[7:0]==8'b0011_0001) begin //JZ
JZ=1'b1;
end
else JZ=1'b0;
if (IR[7:0]==8'b0011_0010) begin //JC
JC=1'b1;
end
else JC=1'b0;
if (IR[7-:4]==4'b0010 && IR[3-:2]!=2'b11) begin //IN
IN=1'b1;
end
else IN=1'b0;
if (IR[7-:4]==4'b0100 && IR[3-:2]!=2'b11) begin //OUT
OUT=1'b1;
end
else OUT=1'b0;
if (IR[7:0]==8'b0111_0000) begin //NOP
NOP=1'b1;
end
else NOP=1'b0;
if (IR[7:0]==8'b1000_0000) begin //HALT
HALT=1'b1;
end
else HALT=1'b0;
end
else begin
MOVA=1'b0;
MOVB=1'b0;
MOVC=1'b0;
ADD=1'b0;
SUB=1'b0;
AND=1'b0;
NOT=1'b0;
RSR=1'b0;
RSL=1'b0;
JMP=1'b0;
JZ=1'b0;
JC=1'b0;
IN=1'b0;
OUT=1'b0;
NOP=1'b0;
HALT=1'b0;
end
end
endmodule //decoder
ALU
我之前想复杂了,完全不需要设计RCA,因为Cf指的是最高位的进位或借位(即溢出),而不是逐位取进位或借位,所以可以直接使用拼接解决。怪不得从网上找了一堆资料没发现如何找借位
这样就没有之前那么难了,把ppt里的东西直接翻译出来就行了, 源代码如下。
module ALU2 (M,S,A,B,t,Cf,Zf);
input M;//算术运算指示
input [3:0] S;//运算类型
input [7:0] A,B;//参与运算的数字
output [7:0] t;//输出结果
output Cf,Zf;//是否进位,是否为0
reg [7:0] t;
reg Cf,Zf;
reg [7:0] temp1;
always @(M,S,A,B) begin
if (M==1'b0) begin //不进行算术运算
if(S==4'b1100) t[7:0]=A[7:0];
else t=8'b0;
Cf=1'b0;
Zf=1'b0;
end
else begin//进行算术运算
case (S)
4'b1001: begin //ADD
{Cf,t}=A+B;
if (t==8'b0) begin
Zf=1'b1;
end
else Zf=1'b0;
end
4'b0110: begin //SUB
{Cf,t}=B-A;
if(t==8'b0) Zf=1'b1;
else Zf=1'b0;
end
4'b1011: begin //AND
// t=A&&B;
t[0]=A[0]&&B[0];
t[1]=A[1]&&B[1];
t[2]=A[2]&&B[2];
t[3]=A[3]&&B[3];
t[4]=A[4]&&B[4];
t[5]=A[5]&&B[5];
t[6]=A[6]&&B[6];
t[7]=A[7]&&B[7];
Cf=0;
Zf=0;
end
4'b0101: begin
t=~B; //NOT
Cf=0;
Zf=0;
end
4'b1010: begin
t=B;
Cf=0;
Zf=0;
end
4'b0100: begin
t=B;
Cf=0;
Zf=0;
end
4'b1100: begin
t=A;
Cf=0;
Zf=0;
end
default: begin
Cf=0;
Zf=0;
t=8'b0;
end
endcase
end
end
endmodule //ALU2
本文代码仿真所使用的波形文件可从此处获取,使用Quartus II 13.0 SP1生成。2021/12/06已更新本人验收用波形,数据较多。
评论