0
\$\begingroup\$

I'm very new to Verilog and I've tried to create single-cycle 32bit MIPS processor.
Instructions I want to implement are

add, and, addi, addu.qb, addu_s.qb, beq, jal, jr, lw, or, slt, sub, sw

but I slightly changed the encoding in instruction jr ( opcode = 6'b000111 ).

The processor should look like this:

processor structure

I've created that structure in Verilog and also translated a little program to hexa instructions which I want to run in this processor, so I can say if the processor works correctly or not. The problem is when I want to simulate processor in gtkwave and basically debug it, almost all of my "variables" shows their values as "xxxxxx" (picture below) and I don't know why. I would appreciate a little help. I've tried also Google but unfortunately didn't help.

gtkwave example

Also below you can find my code describing cpu, instruction and data memory and testbench. Components I'm using in cpu description are correct, only problem is with the simulation.
Thank you for your advice.

module cpu ( input clk, reset, output [31:0] PC, address_to_mem, data_to_mem, input [31:0] instruction, data_from_mem, output WE )
wire Zero, c32, c32_1, c0, c0_1, PCSrcBeq_true, PCSrcJal, PCSrcJr, RegWrite, MemToReg, MemWrite, ALUSrc, RegDst, Branch; 
 wire [3:0] ALUControl;
 wire [4:0] shamt;
 wire [5:0] opCode, funct;
 wire [15:0] in;
 wire [31:0] SignImm, SrcB, ALUOut, ResultMult, PCPlus4, PCBranch, DataIn,four, Rt, Rd, mux_regf_result, thirty_one, res, rd1, rd2, WD3, Result, PCJal, WriteReg;
 reg [31:0] PC_reset;
 always @(posedge reset )
 begin
 if ( reset )
 PC_reset <= 0;
 end
 assign PC = PC_reset;
 assign thirty_one = 31; 
 assign four = 4;
 mux_4_1 mux_instmem ( rd1, Result, PCBranch, PCPlus4, PCSrcJr, PCSrcJal, PCSrcBeq_true, DataIn ); 
 register_32_bit PC_reg ( DataIn, clk, PC );
 adder_32bit adder_PC ( PC, four, c0_1, PCPlus4, c32_1 );
 register_file reg_file ( instruction[25:21], instruction[20:16], res[4:0], RegWrite, clk, WD3, rd1, rd2 );
 assign data_to_mem = rd2;
 controlUnit control_unit ( instruction[31:26], instruction[5:0], instruction[10:6], RegWrite, RegDst, ALUSrc, Branch, MemWrite, MemToReg, PCSrcJal, PCSrcJr, ALUControl );
 assign WE = MemWrite;
 mux_2_1 mux_left_up_regf ( WriteReg, thirty_one, PCSrcJal, res );
 mux_2_1 mux_left_down_regf ( Result, PCPlus4, PCSrcJal, WD3 );
 assign Rt = instruction[20:16];
 assign Rd = instruction[15:11];
 multiplexor_2_1 mux_regf ( Rt, Rd, RegDst, WriteReg );
 ext_to_32bit sign_ext ( instruction[15:0], SignImm ); 
 multiplier mult_by4 ( SignImm, ResultMult );
 adder_32bit adder ( ResultMult, PCPlus4, c0, PCBranch, c32 ); 
 multiplexor_2_1 mux_alu ( rd2, SignImm, ALUSrc, SrcB ); 
 alu_32bit alu_right ( rd1, SrcB, ALUControl, Zero, ALUOut );
 assign address_to_mem = ALUOut;
 mux_2_1 mux_datamem ( ALUOut, data_from_mem, MemToReg, Result );
 assign PCJal[31:28] = PCPlus4[31:28];
 assign PCJal[27:2] = instruction[25:0];
 assign PCJal[1:0] = 0;
 assign PCSrcBeq_true = Zero & Branch;
endmodule

data memory

module datamemory ( input clk, we, input [31:0] address, wd, output [31:0] rd );
reg [31:0] mem[63:0];
initial begin
 $readmemh("./memfile_data.hex",mem,0,63);
end
assign rd=mem[address[31:2]]; //word aligned
always @(posedge clk)
 if (we)
 mem[address[31:2]]<=wd;
endmodule

instruction memory

module instructionmemory(input [5:0] address, output[31:0] rd);
reg [31:0] mem[63:0];
initial begin
 $readmemh("./memfile_text.hex",mem,0,63);
end
assign rd=mem[address]; //word aligned
endmodule

top

module top_module(input clk, reset, output[31:0] data_to_mem, address_to_mem, output write_enable);
wire [31:0] pc, instruction, data_from_mem;
instructionmemory imemory(pc[7:2], instruction);
datamemory dmemory(clk, write_enable, address_to_mem, data_to_mem, data_from_mem);
cpu mipsCPU (clk, reset, pc, instruction, write_enable, address_to_mem, data_to_mem, data_from_mem );
endmodule

testbench

module testbench();
reg clk, reset;
wire[31:0] data_to_mem, address_to_mem;
wire memwrite;
top_module simulation(clk, reset, data_to_mem, address_to_mem, memwrite);
initial begin
 $dumpfile("sim");
 $dumpvars;
 reset<=1; #2; reset<=0;
 #80 $finish;
end
always begin
 clk<=1; #1; clk<=0; #1;
end
endmodule

EDIT: register code

module register_32_bit(input [31:0] datain,
 input clk, reset,
 output reg [31:0] dataout);
always @ ( posedge clk or posedge reset ) 
begin
 if ( reset )
 dataout <= 0;
 else
 dataout <= datain;
end
endmodule

reg_file code

module register_file( input[4:0] a1, a2, a3,
 input we3, clk, reset,
 input[31:0] wd3,
 output reg [31:0] rd1, rd2 );
reg [31:0] reg_file[31:0];
always@ ( posedge clk or posedge reset )
 if ( reset ) begin
 reg_file[0] <= 0;
 ......
 reg_file[31] <= 0;
 end
 else begin
 if ( we3 )
 if ( a3 != 0 ) 
 reg_file[a3] <= wd3;
 else
 reg_file[a3] <= 0; //register 0ドル has always to be 0
end
always @ ( a1 or a2 )
begin
 if ( a1 == 0 )
 rd1 <= 0;
 else if ( a2 == 0 )
 rd2 <= 0;
 else if ( a1 != 0 )
 rd1 <= reg_file[a1];
 else if ( a2 != 0 )
 rd2 <= reg_file[a2]; 
end
endmodule
dim
16.4k3 gold badges44 silver badges86 bronze badges
asked Nov 10, 2019 at 16:46
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

An X means a register is not initialized.

You have NOT provided the code for the registers or register banks. Thus the code most likely to cause your problem is missing.

However some of the code you did provide is wrong. This does not work:

always @(posedge reset )
begin
 if ( reset )
 PC_reset <= 0;
end
assign PC = PC_reset;
register_32_bit PC_reg ( DataIn, clk, PC );

I also noticed the reset missing from register_file.

There are a few basic code templates which you have to follow each and every time you make a register. The most standard one is:

always @(posedge clock or posedge reset )
begin
 if (reset)
 reg <= 0;
 else
 begin
 // your clocked code e.g.
 reg <= reg + 1;
 end // clocked 
end // always 

Thus the reset and clock of your registers all have to be in the same always block and all assignments to the register(s) have to be in there too.

Start with converting all your register to that format and then check again what your MIPS does.

answered Nov 10, 2019 at 18:29
\$\endgroup\$
1
  • \$\begingroup\$ No, this is wrong: always @ ( a1 or a2 ) for combinatorial circuits use always @( * ) and blocking assignments: rd1 = reg_file[a1]; I can't help you with the rest. \$\endgroup\$ Commented Nov 11, 2019 at 6:01

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.