`timescale 1 ns/10 ps
module datapath(
input wire clk, reset, mod, [1:0] mode, [31:0] ins,
output reg i_flag, r_flag, rz, [31:0] y,
// y holds the result register value
// Zero Flag register
// Flag for keeping track when the processor reads instructions
// i_flag is 1 when an instruction has been completed
output reg [6:0] pc, [31:0] ir);
// Program Counter for keeping track of code blocks,
// for selecting instructions and
// for tracking Adresses of registers
reg [4:0] rs1, rs2, rd;
reg [2:0] func1;
reg [6:0] func2;
reg [31:0] x [0:15];
reg [31:0] s;// s For signed arithematic, ir for the current instruction
reg [31:0] imm;// For handling I-Type Instructions
reg [31:0] i_mem [0:127];// This Processor can store 128 lines of code
reg [6:0] inst;// inst keeps track of the final line of instruction written
integer i;
//--------------------------------------------------------------------------
always@(posedge clk, posedge reset)begin
if(reset)begin
for(i=0;i<=127;i=i+1)begin
i_mem[i]<=0;
end
for(i=0;i<=15;i=i+1)begin
x[i]<=0;
end
ir<=0;
pc<=0;
inst<=0;
y<=32'h00000000;
r_flag<=0;
i_flag<=0;
s<=32'h00000000;
rz<=0;
rs1<=0;
rs2<=0;
rd<=0;
func1<=0;
func2<=0;
imm<=0;
end
else begin
if(mod==1)begin// mod = 1 is for implementing the instructions
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
if(r_flag==1)begin
r_flag<=0;
inst<=pc;
pc = 1;
end
//if(pc>inst)pc<=1;// Infinite looped processor
i_flag <= 1;
ir<=i_mem[pc];
if(mode==2'b01)begin// R-Type Instructions
//rd <= ir[11:7]
rd[0] = ir[7];
rd[1] = ir[8];
rd[2] = ir[9];
rd[3] = ir[10];
rd[4] = ir[11];
//func1 <= ir[14:12]
func1[0] = ir[12];
func1[1] = ir[13];
func1[2] = ir[14];
//rs1 <= ir[19:15]
rs1[0] = ir[15];
rs1[1] = ir[16];
rs1[2] = ir[17];
rs1[3] = ir[18];
rs1[4] = ir[19];
//ir[24:20]
rs2[0] = ir[20];
rs2[1] = ir[21];
rs2[2] = ir[22];
rs2[3] = ir[23];
rs2[4] = ir[24];
//ir[31:25]
func2[0] = ir[25];
func2[1] = ir[26];
func2[2] = ir[27];
func2[3] = ir[28];
func2[4] = ir[29];
func2[5] = ir[30];
func2[6] = ir[31];
if(func1==3'b000) x[rd] <= (x[rs1] + x[rs2]);// ADD
else if(func1==3'b001) x[rd] <= (x[rs1] + ((~x[rs2])+1));// SUB
else if(func1==3'b010) x[rd] <= (x[rs1] | x[rs2]);// OR
else if(func1==3'b011) x[rd] <= ((~x[rs1]) & x[rs2]) | (x[rs1] & (~x[rs2]));// XOR
else if(func1==3'b100) x[rd] <= (x[rs1] & x[rs2]);// AND
else if(func1==3'b101)begin// SLT
if((x[rs1]<0) & (x[rs2]<0))begin
if(((~x[rs1])+1) < ((~x[rs2])+1)) x[rd] <= 1;
else if(((~x[rs1])+1) == ((~x[rs2])+1)) x[rd] <= 0;
else x[rd] <= 0;
end
if((x[rs1]<0) & (x[rs2]>0))begin
if(((~x[rs1])+1) < x[rs2]) x[rd] <= 1;
else if(((~x[rs1])+1) == x[rs2]) x[rd] <= 0;
else x[rd] <= 0;
end
if((x[rs1]>0) & (x[rs2]<0))begin
if(x[rs1] < ((~x[rs2])+1)) x[rd] <= 1;
else if(x[rs1] == ((~x[rs2])+1)) x[rd] <= 0;
else x[rd] <= 0;
end
if((x[rs1]>0) & (x[rs2]>0))begin
if(x[rs1] < x[rs2]) x[rd] <= 1;
else if(x[rs1] == x[rs2]) x[rd] <= 0;
else x[rd] <= 0;
end
end
if(func1==3'b110)begin// SLTU
if(x[rs1] < x[rs2]) x[rd] <= 1;
else if(x[rs2]==x[rs1]) x[rd] <= 0;
else x[rd] <= 0;
end
// Extra function added for better accessibility
if(func1==3'b111)begin// NOT
x[rd] <= ~(x[rs1]);
if(x[rd] == 0)rz<=1;
end
end
else if(mode==2'b10)begin// I-Type Instructions
//rd <= ir[11:7]
rd[0] = ir[7];
rd[1] = ir[8];
rd[2] = ir[9];
rd[3] = ir[10];
rd[4] = ir[11];
//func1 <= ir[14:12]
func1[0] = ir[12];
func1[1] = ir[13];
func1[2] = ir[14];
//rs1 <= ir[19:15]
rs1[0] = ir[15];
rs1[1] = ir[16];
rs1[2] = ir[17];
rs1[3] = ir[18];
rs1[4] = ir[19];
//imm <= ir[31:20]
imm[0] = ir[20];
imm[1] = ir[21];
imm[2] = ir[22];
imm[3] = ir[23];
imm[4] = ir[24];
imm[5] = ir[25];
imm[6] = ir[26];
imm[7] = ir[27];
imm[8] = ir[28];
imm[9] = ir[29];
imm[10] = ir[30];
imm[11] = ir[31];
s <= 0;
if(func1 == 3'b000) x[rd] <= x[rs1] + imm;// ADDi
else if(func1 == 3'b001) x[rd] <= x[rs1] | imm;// ORi
else if(func1 == 3'b010) x[rd] <= x[rs1] & imm;// ANDi
else if(func1 == 3'b011)begin// SLTi
s <= imm;
if((x[rs1]<0) & (s<0))begin
if(((~x[rs1])+1) < ((~s)+1)) x[rd] <= 1;
else if(((~x[rs1])+1) == ((~s)+1)) x[rd] <= 0;
else x[rd] <= 0;
end
if((x[rs1]<0) & (s>0))begin
if(((~x[rs1])+1) < s) x[rd] <= 1;
else if(((~x[rs1])+1) == s) x[rd] <= 0;
else x[rd] <= 0;
end
if((x[rs1]>0) & (s<0))begin
if(x[rs1] < ((~s)+1)) x[rd] <= 1;
else if(x[rs1] == ((~s)+1)) x[rd] <= 0;
else x[rd] <= 0;
end
if((x[rs1]>0) & (s>0))begin
if(x[rs1] < s) x[rd] <= 1;
else if(x[rs1] == s) x[rd] <= 0;
else x[rd] <= 0;
end
end
end
else if(mode==2'b11)begin// J-Type Instructions
//rd <= ir[11:7]
rd[0] = ir[7];
rd[1] = ir[8];
rd[2] = ir[9];
rd[3] = ir[10];
rd[4] = ir[11];
//imm <= imm+ir[31:12]
imm[0] = ir[12];
imm[1] = ir[13];
imm[2] = ir[14];
imm[3] = ir[15];
imm[4] = ir[16];
imm[5] = ir[17];
imm[6] = ir[18];
imm[7] = ir[19];
imm[8] = ir[20];
imm[9] = ir[21];
imm[10] = ir[22];
imm[11] = ir[23];
imm[12] = ir[24];
imm[13] = ir[25];
imm[14] = ir[26];
imm[15] = ir[27];
imm[16] = ir[28];
imm[17] = ir[29];
imm[18] = ir[30];
imm[19] = ir[31];
//Load the new memory address
//The PC can only hold a 7-bit long memory address
pc[0] = imm[0];
pc[1] = imm[1];
pc[2] = imm[2];
pc[3] = imm[3];
pc[4] = imm[4];
pc[5] = imm[5];
pc[6] = imm[6];
end
end
else begin// mod = 0 is for reading instructions
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
if(r_flag==0)begin
pc<=inst;
r_flag<=1;
end
i_mem[pc]<=ins;
end
pc<=pc+1;
end
if(x[rd]==0)rz<=1;
else rz<=0;
y = x[rd][31:0];
end
always@*begin
x[0] = 0;
end
endmodule
//============================================================================
问题是,我尝试过循环、间接赋值,但没有任何效果。如果我将数组中的一个寄存器传递给 y,则输出很好,但行 y <= x[rd];或 y=x[rd] 不返回存储在寄存器中的正确值。 我能做些什么来修复它? 我尝试了多种方法,包括将 x 作为输出,但 verilog 不允许将数组作为输出。其余的代码很好。我测试了它。我没有足够的声誉来发布图片。 感谢您抽出宝贵时间。
答案 0 :(得分:0)
那里有很多代码,看起来你在阻塞和非阻塞赋值方面一团糟。
您询问了 y
。在您的情况下,我注意到您的块中有两个语句:
y <= 0;
...
y = x[rd][31:0];
在这个特殊的组合中,第一个语句将获胜,y
将是 0。原因是第一个语句将赋值安排到稍后的时间,而第二个语句立即执行。您也应该在第二种情况下使用 <=
。实际上,看起来您应该在块中仅使用非阻塞赋值。不要混合使用。
一般建议是将庞大的 always 块拆分为较小的任务并分别调试每个任务。