📄 control.v
字号:
/*乘法控制版,注意相应数据通路中要把clock导入。 无ldr,str push,pop,*/
module control(op2,op3,op4,op5,Rz3,Rz4,Rx2,Ry2,pc_in,IR2_in,mp1_sel,mp2_sel,mp3_pre_sel,mp3_sel,
aluop,IR3_in,x3_in,y3_in,rw,z4_in,mp4_sel,Rz_in,
Rz2,mp3_post_sel,z4_sel,md3_sel,stack_sel,clk);
input [5:0]op2,op3,op4,op5;
input [4:0]Rz3,Rz4,Rx2,Ry2,
Rz2;//无需Rz5
input clk;//新加,只为乘法设置
output mp3_post_sel;//新加
output [1:0]md3_sel;//新加
reg [1:0]md3_sel;
output [1:0]stack_sel;//新加,需多一个4选1
reg [1:0]stack_sel;
/*IR2_control*/
output pc_in;
output IR2_in;/*pc_in, IR3_in , x3_in, y3_in,z4_in合成一个!? */
output mp1_sel;
output [1:0]mp2_sel;
output mp3_pre_sel;
output [1:0]mp3_sel;
/*IR3_control*/
output [3:0]aluop;
output z4_sel; //新加,需多一个2选1
output IR3_in,x3_in,y3_in;
/*IR4_control*/
output rw;
output z4_in;
output [1:0]mp4_sel;
/*IR5_control*/
output Rz_in;
/*new control for multiplex and divide*///新加接口
Delay_Counter con(clk,m_in,m_out);
assign op3_mul_div =~op3[3]&op3[2]&~op3[1];//multi and divide 0x010x
assign m_in = op3_mul_div;
assign IR2_in=~m_out;
assign IR3_in =~m_out;
assign x3_in =~m_out;
assign y3_in = ~m_out;
assign z4_in = ~m_out;
assign pc_in=~m_out;
reg [1:0]mp2_sel;
reg [1:0]mp3_sel;
reg [1:0]mp4_sel;
//*-----------------------------------------------IR2_control------------------------------------*//
assign op2_ldr = op2[5]&op2[4]&~op2[3]&~op2[2]&~op2[1]&~op2[0];//LDR(110000)
assign op2_str = op2[5]&op2[4]&~op2[3]&~op2[2]&~op2[1]&op2[0];//str(110001)
assign op2_push = op2[5]&~op2[4]&op2[3]&op2[2]&~op2[1]&~op2[0];//push(101100)
assign op2_not = ~op2[5]&~op2[4]&op2[3]&~op2[2]&op2[1]&op2[0];//not (001011)
assign mp1_sel = op2_str||op2_push; //mp1_sel为STR或是push时为1将Rz段送入作为地址
//assign mp1_sel = op2[5]&op2[4]&~op2[3]&~op2[2]&~op2[1]&op2[0];//mp1_sel为STR时为1将Rz段送入作为地址
/*mp2_sel冲突情况:1.op2读出指令,op3回写指令2.op2读出,op4回写*/
//wire op2_read_in; //op2中要读出寄存器的指令
//wire op3_write_in; //op3中要写入寄存器的指令
//wire op4_write_in; //op4中要写入寄存器的指令
//assign op2_read_in = ~op2[5]||(op2[4]&~op2[3]&~op2[2]&~op2[1]);//算术逻辑或LDR或STR
/*写入地址和Rx冲突,Rx一直输入alu*/
always @(1)
begin
if((~op2[5]||op2_str||op2_ldr)&&~op3[5]&&Rx2==Rz3) //Rx2和Rz3冲突。(str,ldr,或算术)01时代表读取alu输出,一条相关,只前传alu输出结果
mp2_sel <= 2'b01;
else if((~op2[5]||op2_str||op2_ldr)&&~op4[5]&&Rx2==Rz4) //Rx2和Rz3冲突,10时代表两条相关,且不一条相关(一条两条同时发生时取一条)
mp2_sel <= 2'b10;
else if(op2_push) //11时为push,取出stack
mp2_sel <= 2'b11;
else mp2_sel <= 2'b00;
end
/*写入地址和Ry输入alu的一路冲突*/
always @(1)
begin
if((~op2[5]&~op2[4])/*&&(op2!=op2_not)*/&&~op3[5]&&Ry2==Rz3) //只有第一类中的非立即数(无not)指令会把Ry一路真正取入alu ,01时代表读取alu输出,一条相关
mp3_sel <= 2'b01;
else if((~op2[5]&~op2[4])/*&&(op2!=op2_not)*/&&~op4[5]&&Ry2==Rz4) //10时代表两条相关,且不一条相关(一条两条同时发生时取一条),选择z4_out
mp3_sel <= 2'b10;
else if(~op2[5]&op2[4]&op2[3]) //为逻辑或移位的立即数运算,选择(011),有符号扩展在mp3_pre_sel中
mp3_sel <= 2'b11;
else mp3_sel <= 2'b00;
end
/*写入地址和Ry保存值的一路冲突*/
always
begin
if(mp1_sel&&~op3[5]&&Rz2==Rz3) //即为str或push时,这时Rz3不是和Ry2冲突,而是和Rz2冲突,为1,选不一般的,否则不选前传
md3_sel <= 2'b01;
else if(mp1_sel&&~op4[5]&&Rz2==Rz4) //两条相关
md3_sel <= 2'b10;
else md3_sel <= 2'b00;
end
assign mp3_pre_sel = (~op2[5]&op2[4]&~op2[3])||op2_str||op2_ldr;//当op2为算术立即数运算或LDR或STR,选1,进行有符号扩展(无符号运算仍进行有符号扩展?)
assign mp3_post_sel = op2[5]&~op2[4]&op2[3]&op2[2]&~op2[1]&~op2[0];//还是push时为1,选出数字4而不是mp3_out
//*-----------------------------------------------IR3_control------------------------------------*//
assign aluop[3:0] = {4{~op3[5]}}&op3[3:0];//为算术逻辑运算为后四位,否则为加法0000
assign z4_sel = op3[5]&~op3[4]&op3[3]&op3[2]&~op3[1]&op3[0];//为pop时为1(101101),选直接的stack值的输出,而非alu输出结果。
//*-----------------------------------------------IR4_control------------------------------------*//
assign rw = (op4[5]&op4[4]&~op4[3]&~op4[2]&~op4[1]&op4[0])||
(op4[5]&~op4[4]&op4[3]&op4[2]&~op4[1]&~op4[0]);//为str或push时为1写入,其他时刻读出,但不一定可被选出,load时被选出,any jump不能写入;//为str时为1写入,其他时刻读出,但不一定可以被选出,load时被选出
always @(1)
begin
if((op4[5]&op4[4]&~op4[3]&~op4[2]&~op4[1]&~op4[0])||
(op4[5]&~op4[4]&op4[3]&op4[2]&~op4[1]&op4[0]))//00为LDR时读出内存线,为pop时也需要读出
mp4_sel <= 2'b00;
else if(op4[5]&op4[4]&~op4[3]&~op4[2]&op4[1]&~op4[0])//LDH为01读出LH4
mp4_sel <= 2'b01;
else if(op4[5]&op4[4]&~op4[3]&~op4[2]&op4[1]&op4[0])//LDL为10读出LO4
mp4_sel <= 2'b10;
else mp4_sel <= 2'b11;
end
//*-----------------------------------------------IR5_control------------------------------------*//
assign Rz_in = ~((op5[5]&op5[4]&~op5[3]&~op5[2]&~op5[1]&op5[0]) //110001 str
||(op5[5]&~op5[4]&op5[3]&~op5[2]&op5[1]&op5[0]) //101011 nop
||(op5[5]&~op5[4]&op5[3]&op5[2]&~op5[1]&~op5[0]) //101100 push
||(op5[5]&~op5[4]&~op5[3]));//为STR或push or nop!or any jump时为0,不准写入,其他时刻可以。
always @(1)
begin
if(op5[5]&~op5[4]&op5[3]&op5[2]&~op5[1]&op5[0])//为pop时为01,读入stack-4的值(101101)
stack_sel <= 2'b01;
else if(op5[5]&~op5[4]&op5[3]&op5[2]&~op5[1]&~op5[0])//为push时为10,读入z5输出值,其实这时z5并不能被写入寄存器堆
stack_sel <= 2'b10;
else
stack_sel <= 2'b00; //其他情况直接写入原值
end
endmodule
module Delay_Counter(clk,in,out);
input clk;
input in;
output out;
reg [1:0]Temp;
reg out;
always @(negedge clk)
begin
if(in==0)
begin
Temp=2'b00;
out=0;
end
else if(Temp==2'b00)
begin
Temp=2'b01;
out=1;
end
else if(Temp==2'b01)
begin
Temp=2'b10;
out=1;
end
else
begin
Temp=2'b00;
out=0;
end
end
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -