Hello I am implementing a simple single cycle 32-bit mips processor in verilog. I have successfully compiled all the modules however my output waveform displays XX for all inputs/outputs. These are my register file, cpu module and cpu testbench whihch is where I suspect my problem is but I cant find it. I also have a fetch instructions module, control, alu control and adder module.
module regsFile( rgr1,rgr2,write,rgw1,rgw1data,clk,reset,rg1data,rg2data);
input [4:0] rgr1;
input [4:0] rgr2;
input [4:0] rgw1;
input [31:0] rgw1data;
input clk;
input reset;
input write;
output reg [31:0] rg1data;
output reg [31:0] rg2data;
reg [31:0] regMem [31:0]; // register memory
assign rg1data = regMem[rgr1];
assign rg2data = regMem[rgr2];
always @(rgr1 or rgr2)
begin
rg1data = regMem[rgr1];
rg2data = regMem[rgr2];
end
always @(posedge write)
begin
if(rgw1 == 5'b0) regMem[0] = 5'b0;
else regMem[rgw1] = rgw1data;
end
///write to register
integer i;
initial
begin
// $monitor("%d %d %d %d ", regMem[0],regMem[1],regMem[2],regMem[3]);
//set all register values to reg number
for( i = 0; i < 32; i = i + 1 )
regMem[i] = i;
end
always @(posedge clk or negedge reset)
begin
regMem[0] = 32'b0; //register 0 is hardwired to zero;
if(reset == 1'b0)
begin
regMem[0] = 32'b0;
// set all registers to their defaults
for( i = 0; i < 32; i = i + 1 )
regMem[i] = i;
end
else if(write == 1'b1 && rgw1 != 5'd0) //$zero register is hardwired to zero
regMem[rgw1] = rgw1data;
end
endmodule
module mips32(dataBus,clk,reset,ReadWrite,memOpDone,addressBus);
output reg [31:0] addressBus;
inout [31:0] dataBus;
input clk,reset,memOpDone;
output reg ReadWrite;
reg [2:0] stage;
parameter IF = 3'd0;
parameter ID = 3'd1;
parameter EX = 3'd2;
parameter MEM = 3'd3;
parameter WB = 3'd4;
/* PC_regs */
reg [31:0] pc;
wire [31:0] pc_next;
reg [31:0] NextAdd;
wire pcOverflow;
/* fetch stage*/
reg [31:0] fetchPC;
wire [31:0] fetchedInst;
/* instruction fields */
reg [31:0] instruction;
wire [5:0] opcode;
wire [4:0] rs;
wire [4:0] rd;
wire [4:0] rt;
wire [15:0] addrim; //address offset / immediate
wire [31:0] immediate;
wire [25:0] instidx; // jump address distination shifted to left two bits <add 00 at lsb in execute>
wire [4:0] sa; // shift amount for shift instructions
wire [5:0] fn;
wire [4:0] rgw;
/*Control Unit */
wire contDstReg;
wire contJmp;
wire contBranch;
wire contMemRead;
wire contMemtoReg;
wire contALUSrc;
wire contRegWrite;
wire contMemWrite;
wire [1:0] contAluop;
/*register File */
reg RegWrite;
wire [31:0] rdata1;
wire [31:0] rdata2;
reg [31:0] rgwdata;
/* ALU */
reg [1:0 ]aluOp;
reg [31:0] data1;
reg [31:0] data2;
reg [31:0] imm;
reg aluSrc;
wire [3:0] aluCtrl;
wire [31:0] result;
wire zero;
wire overflow;
/**/
reg MemopInProg;
reg [31:0] MemData;
assign dataBus = ReadWrite ? MemData : 32'bz;
assign opcode = instruction[31:26];
assign rs = instruction[25:21];
assign rt = instruction[20:16];
assign rd = instruction[15:11];
assign addrim = instruction[15:0];
assign instidx = instruction[25:0];
assign sa = instruction[10:6];
assign fn = instruction[5:0];
assign rgw = contDstReg ? rd : rt;
// assign immediate = {{16{1'b0}}, addrim};
assign immediate = addrim;
addsub32 NexTinst(.A(pc), .B(NextAdd), .sos(1'b0), .Sum(pc_next), .carry(pcOverflow));
Imem fetchIns(.pc(pc),.instruction(fetchedInst)); // fetch the next instruction
control controlUnit(.Opcode(opcode),.RegDst(contDstReg),.jump(contJmp),.branch(contBranch),.MemRead(contMemRead),
.MemToReg(contMemtoReg),
.ALUop(contAluop),
.MemWrite(contMemWrite),
.ALUsrc(contALUSrc),
.RegWrite(contRegWrite),
.reset(reset)
);
regsFile RegisterFile (
.rgr1(rs),
.rgr2(rt),
.write(RegWrite), //output from control unit
.rgw1(rgw),
.rgw1data(rgwdata),
.clk(clk),
.reset(reset),
.rg1data(rdata1),
.rg2data(rdata2)
);
aluCtrl aluControl (
.aluOp(aluOp),
.fn(fn),
.aluCtrl(aluCtrl)
);
alu alu0(
.aluSrc(aluSrc),
.A(data1),
.B(data2),
.imm(imm),
.aluCtrl(aluCtrl),
.result(result),
.zero(zero),
.overflow(overflow)
);
always @(posedge clk or negedge reset)
begin
if(reset == 1'b0)
begin
pc <= 32'b0;
stage <= IF;
NextAdd <= 32'd4; // the added amount to the address
ReadWrite <= 1'bz;
MemData <= 32'b0;
data1 <= 0;
data2 <= 0;
end
else
case(stage)
IF:
begin
RegWrite <= 1'b0;
instruction <= fetchedInst;
stage <= ID;
ReadWrite <= 1'bz;
data1 <= 0;
data2 <= 0;
end
ID:
begin
aluOp <= contAluop;
aluSrc <= contALUSrc;
data1 <= rdata1;
data2 <= rdata2;
imm <= immediate;
ReadWrite <= 1'bz;
stage <= EX;
end
EX:
begin
ReadWrite <= 1'bz;
if(contJmp == 1'b1)
begin
pc <= instidx << 2;
stage <= IF;
end
else if (contBranch == 1'b1)
begin
if(zero == 1'b0) // zero means $r1 and $r2 condition is satisfied
NextAdd <= addrim << 2;
pc <= pc_next;
stage <= IF;
end
else if (contMemRead == 1'b1 | contMemWrite == 1'b1) stage <= MEM;
else if (contRegWrite == 1'b1)
begin
stage <= WB;
rgwdata <= result;
/* // already accounted for it using assign
if (contDstReg == 1'b0)
rgw <= rt;//the register to write into
else rgw <= rd;
*/
end
else
begin
NextAdd <= 4'd4;
pc <= pc_next;
stage <= IF;
end
end
MEM:
begin
data1 <= 0;
data2 <= 0;
if (MemopInProg == 1'b1)
begin
if (memOpDone == 1'b1)
begin
MemopInProg <= 1'b0;
if(contMemtoReg == 1'b1)
begin
rgwdata <= dataBus;
stage <= WB;
/* // already accounted for it using assign
if (contDstReg == 1'b1)
rgw <= rd;//the register to write into
else rgw <= rt;
*/
end
else
begin
stage <= IF;
NextAdd <= 4'd4;
pc <= pc_next;
end
end
end
else if(contMemWrite == 1'b1)
begin
addressBus <= rdata1;
MemData <= rdata2;
ReadWrite <= 1'b1;
MemopInProg <= 1'b1;
stage <= MEM;
end
else if (contMemRead == 1'b1)
begin
addressBus <= rdata1;
ReadWrite <= 1'b0;
MemopInProg <= 1'b1;
stage <= MEM;
end
end
WB:
begin
data1 <= 0;
data2 <= 0;
ReadWrite <= 1'bz;
RegWrite <= 1'b1;
stage <= IF;
pc <= pc_next;
end
default:
begin
stage <= IF;
pc <= pc_next;
RegWrite <= 1'b0;
end
endcase
end
endmodule
module mips32_TB;
reg clk,reset;
reg memOpDone;
wire [31:0] dataBus;
wire [31:0] addressBus;
wire memRWPin;
reg [31:0] MemData;
/* instance */
mips32 MipsCpu( //cpu input/output pins
.dataBus(dataBus),
.clk(clk),
.reset(reset),
.ReadWrite(memRWPin), // 1: write, 0: read
.memOpDone(memOpDone),
.addressBus(addressBus)
);
assign dataBus = memRWPin ? 32'bz : MemData;
/*Initializing inputs*/
initial
begin
//initialize here
clk = 0;
reset = 1;
end
/*Monitor values*/
initial
begin
// $display ("\t\ttime,\t\tPC,\tstage,\trt:d,\trs:d,\trd:d,\timm,\talusrc\tRegister File");
// $monitor ("%d, %d, %d, %d:%d, %d:%d, %d:%d,%d %d %p", $time, MipsCpu.pc, MipsCpu.stage,MipsCpu.rt,MipsCpu.rdata1,MipsCpu.rs,MipsCpu.rdata2,MipsCpu.rd, MipsCpu.rgwdata,MipsCpu.imm ,MipsCpu.aluSrc,MipsCpu.RegisterFile.regMem);
$display ("\t\ttime,\tPC,\tstage,\tRegister File");
$monitor ("%d, %d, %d, %p", $time, MipsCpu.pc, MipsCpu.stage,MipsCpu.RegisterFile.regMem);
end
//Generate clock
always
#1 clk = ~clk;
event reset_done;
/*Generating input values */
task rst();
begin
@(negedge clk);
reset = 0;
#5
@(negedge clk);
begin
reset = 1;
->reset_done;
end
end
endtask
initial
begin
#1 rst();
end
always @(posedge clk)
begin
#1
if(memRWPin == 1'b1)
begin
/* write from cpu to memory */
#1
$display ("Memory Access TO address: %d , data: %d", addressBus, dataBus);
MemData <= dataBus;
#1
memOpDone <= 1'b1;
#3
memOpDone <= 1'b0;
end
else if(memRWPin == 1'b0)
begin
/* write from memory to cpu */
// MemData <= 32'd302;
#1
$display ("Memory Access FROM address:%d , data: %d", addressBus,dataBus);
memOpDone <= 1'b1;
#3
memOpDone <= 1'b0;
end
end
initial
begin
@(reset_done)
begin
#500; // wait for a while let the instructions in mipsIM.txt run
$stop;
end
end
endmodule
I guess the problem is you assign more than one values to rg1data and rg2data. delete the following lines:
assign rg1data = regMem[rgr1];
assign rg2data = regMem[rgr2];
And use nonblocking assignment in always block like this(the result may show up one cycle later):
always @(rgr1 or rgr2)
begin
rg1data <= regMem[rgr1];
rg2data <= regMem[rgr2];
end
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.