以下代码虽经本人检查,但仅移位逻辑经过仔细验收,仅供参考。
多路开关
多路开关做起来还是很简单的,一个case语句就能搞定。记得加default,防止生成锁存器。
module mux (MADD,A,B,C,OUT);
input[1:0] MADD;
input[7:0] A,B,C;
output[7:0] OUT;
reg[7:0] OUT;
always @(MADD,A,B,C) begin
case (MADD)
2'b00: OUT=A;
2'b01: OUT=B;
2'b10: OUT=C;
default: OUT=8'b0;
endcase
end
endmodule //mux
移位逻辑
这个应该也不算很难。我将输入的三个FBUS、FLBUS和FRBUS合成一个BUS,这样用case语句一起处理或许优雅一些(?)
可以参考下面这张图进行设计。其他情况直接全输出高阻,不用管别的,以防多路输出冲突。
module Shift_Register (F_BUS,FL_BUS,FR_BUS,a,W,Cf);
input F_BUS,FL_BUS,FR_BUS;
input[7:0] a;
output[7:0] W;
output Cf;
reg[7:0] W;
reg Cf;
wire[2:0] BUS;
assign BUS = {F_BUS,FL_BUS,FR_BUS};
always @(BUS) begin
case (BUS)
3'b100: begin
W = a;
Cf = 0;
end
3'b010: begin
W = {a[6:0],a[7]};
Cf = a[7];
end
3'b001: begin
W = {a[0],a[7:1]};
Cf = a[0];
end
default: begin
W = 8'bZZZZZZZZ;
Cf = 0;
end
endcase
end
endmodule //Shift_Register
控制信号产生逻辑
正常来说,如果希望用直接assign这种比较优雅的写法,你需要逐个摸清控制命令的运行模式,即每种IR对应的各个控制信号的值,列个表,然后找每个控制信号在什么命令输入的时候值为1。
要不然,就用一堆条件语句,只是省掉了反查的过程,还是得分析,也不优雅。
但是,老师把这个表已经列出来了,省下了大把的时间:
我们只需查找每一列输出信号对应的输入信号就行了。规定的信号针脚和表中的控制信号可能有所不同,可以参阅下面的源代码,我在注释中写了一些对应关系。
但是请注意,这里并没有包含所有的指令,比如INPUT。
空白的区域不清楚怎么搞,但我是在这部分输出了0。JZ/JC(T)指的是JZ&&Z或JC&&C,这两种输出是等效的,虽然判断条件看起来不同;相对的,JZ/JC(F)就是JZ&&(~Z)或JC&&(~C)。
源代码如下,部分难以使用几个输入或表示的,我才会使用always语句。
后面整合的时候会知道,MOVB和MOVC的时候,要指定内存地址,需要将C寄存器中的数值输出,所以REG_RA(RAA)的always块中,不能因为MOVB中有一个固定的11就不作为条件;相反,为了将C忠实地输出,需要将三个MOV全都加进去;REG_WA(RWBA)也一样。
此外,上表没有包含NOP的指令输出,经测试只需要REG_WE=1即禁止读写即可,防止总线上数据污染寄存器。
module control_signal (MOVA,MOVB,MOVC,ADD,SUB,AND1,NOT1,RSR,RSL,JMP,JZ,Z,JC,C,IN1,OUT1,NOP,HALT,IR,SM,REG_RA,REG_WA,MADD,ALU_S,PC_LD,PC_INC,REG_WE,RAM_XL,RAM_DL,ALU_M,SHI_FBUS,SHI_FLBUS,SHI_FRBUS,IR_LD,CF_EN,ZF_EN,SM_EN,IN_EN,OUT_EN);
input MOVA,MOVB,MOVC,ADD,SUB,AND1,NOT1,RSR,RSL,JMP,JZ,Z,JC,C,IN1,OUT1,NOP,HALT,SM;
// MOVA,MOVB,MOVC,ADD,SUB,AND, NOT, RSR,RSL,JMP,JZ-T,JC-T,IN, OUT, NOP,HALT,SM
input[7:0] IR;
output[1:0] REG_RA,REG_WA,MADD;
// RAA, RWBA, MADD
output[3:0] ALU_S;
// S
output PC_LD,PC_INC,REG_WE,RAM_XL,RAM_DL,ALU_M,SHI_FBUS,SHI_FLBUS,SHI_FRBUS,IR_LD,CF_EN,ZF_EN,SM_EN,IN_EN,OUT_EN;
// LD PC,IN PC, /WE, XL, DL, M, F-BUS, FL-BUS, FR-BUS, LD IR, SM,
reg[1:0] MADD,REG_RA,REG_WA;
reg[3:0] ALU_S;
assign RAM_DL = (~SM)||MOVC||JMP||(JZ&&Z)||(JC&&C); //取指,MOVC,JMP,JZT,JCT
assign RAM_XL = MOVB&&(~SM); //MOVB
assign PC_LD = JMP||(JZ&&Z)||(JC&&C); //JMP,JZT,JCT
assign PC_INC = (~SM)||(JZ&&~Z)||(JC&&~C); //取指,JZF,JCF
assign IR_LD = (~SM); //取指
assign SHI_FBUS = ADD||SUB||AND1||NOT1||OUT1||MOVA||MOVB; //ADD,SUB,AND,NOT,OUT,MOVA,MOVB
assign SHI_FLBUS = RSL; //RSL
assign SHI_FRBUS = RSR; //RSR
assign ALU_M = ADD||SUB||AND1||NOT1||RSR||RSL||OUT1;
assign REG_WE = (~SM)||OUT1||MOVB||JMP||JZ||JC||HALT||NOP;
assign CF_EN = ADD||SUB||RSR||RSL;
assign ZF_EN = ADD||SUB;
assign SM_EN = ~HALT;
assign IN_EN = IN1;
assign OUT_EN = OUT1;
always @(SM,MOVB,MOVC) begin //MADD
if(~SM) MADD=2'b0;
else if(MOVB) MADD=2'b10;
else if(MOVC) MADD=2'b01;
else MADD=2'b0; //不锁存只能这样了吧?
end
always @(ADD,SUB,AND1,NOT1,RSR,RSL,OUT1,MOVA,MOVB) begin //ALU_S
if(ADD||SUB||AND1||NOT1||RSR||RSL||OUT1||MOVA||MOVB) ALU_S[3:0]=IR[7-:4];
else ALU_S=4'b0;
end
always @(ADD,SUB,AND1,MOVA,MOVB,MOVC) begin //RAA
if(ADD||SUB||AND1||MOVA||MOVB||MOVC) REG_RA=IR[1-:2];
else REG_RA=2'b0;
end
always @(ADD,SUB,AND1,NOT1,RSR,RSL,IN1,OUT1,MOVA,MOVB,MOVC) begin//RWBA
if(ADD||SUB||AND1||NOT1||RSR||RSL||IN1||OUT1||MOVA||MOVB||MOVC) REG_WA=IR[3-:2];
else REG_WA=2'b0;
end
endmodule
照例,下面提供三个部件仿真时使用的波形文件,使用Quartus Prime 21.1生成:下载链接。