Electrical – Verilog RAM module with Register File & Testbench

fpgaramverilog

I am designing a RAM module with testbench in Verilog. It is suppose to access a register file (.dat) in the testbench and run it through an ALU module. There are 4 modules (memory.v, alu.v, toplevel.v and testbench.v).

My problem is that when I run the ModelSIM I am not getting the expected results.

`timescale 1ns/1ps

module testbench_lab3_reg();

reg clk;            
reg [4:0] Read_address;
reg [4:0] Write_address;
reg read_en; 
reg write_en;
wire [15:0] DataOut;
reg [15:0] memory [0:15];

assign DataOut = (read_en) ? memory[Read_address] : memory[Write_address];

lab3_reg dut(.clk(clk), .Read_address(Read_address), .Write_address(Write_address), .read_en(read_en), .write_en(write_en), .DataOut(DataOut));

always
begin
    clk = 1; #10; clk = 0; #10;
end

initial begin
$readmemb("memfile.dat", memory);

Read_address = 5'b00000; Write_address = 5'b01001; read_en = 1;  write_en = 0; #20;
Read_address = 5'b00000; Write_address = 5'b01001; read_en = 0;  write_en = 1; #20;

Read_address = 5'b00001; Write_address = 5'b01010; read_en = 1;  write_en = 0; #20;
Read_address = 5'b00001; Write_address = 5'b01010; read_en = 0;  write_en = 1; #20;

Read_address = 5'b00010; Write_address = 5'b01011; read_en = 1;  write_en = 0; #20;
Read_address = 5'b00010; Write_address = 5'b01011; read_en = 0;  write_en = 1; #20;

Read_address = 5'b00011; Write_address = 5'b01100; read_en = 1;  write_en = 0; #20;
Read_address = 5'b00011; Write_address = 5'b01100; read_en = 0;  write_en = 1; #20;

Read_address = 5'b00100; Write_address = 5'b01101; read_en = 1;  write_en = 0; #20;
Read_address = 5'b00100; Write_address = 5'b01101; read_en = 0;  write_en = 1; #20;

Read_address = 5'b01001; Write_address = 5'b00000; read_en = 1;  write_en = 0; #20;
Read_address = 5'b01010; Write_address = 5'b00000; read_en = 1;  write_en = 0; #20;
Read_address = 5'b01011; Write_address = 5'b00000; read_en = 1;  write_en = 0; #20;
Read_address = 5'b01100; Write_address = 5'b00000; read_en = 1;  write_en = 0; #20;
Read_address = 5'b01101; Write_address = 5'b00000; read_en = 1;  write_en = 0; #20;

$stop; 

end
endmodule

I know my ALU works because I tested it using a MegaWizard generated RAM. The following is my ram module:

module memory(
input clk,
 input [15:0] write_data,
input [4:0] raddress,
input [4:0] waddress,
input read_enable,
input write_enable,
 output [15:0] read_data);
reg [15:0] memory [0:15];
 reg [15:0] data_out;

assign read_data = data_out;

always @(posedge clk) 
 begin
    if (write_enable) 
        memory[waddress] <= write_data;
      if (read_enable)
            data_out <= memory[raddress];
end

endmodule

The following is my top level module, which instantiates the ALU and the RAM:

module lab3_reg(
            input clk,
            input [4:0] Read_address,
            input [4:0] Write_address,
            input read_en,
            input write_en,
            output [15:0] DataOut
            );


wire zero;
wire signed [3:0] y;
alu inst1(DataOut [12:9], DataOut [8:5], DataOut [15:13], y, zero);

wire signed [15:0] y_signed;
assign y_signed = y;

wire [15:0] data;
assign data = DataOut;
memory inst2(clk, y_signed, Read_address, Write_address, read_en, write_en, data);

endmodule

I'm pretty sure the problem is with my testbench, but I've been racking my brains over this, so any help would be awesome.

memfile.dat

0100000111100000
1100000111100000
1111111000000000
0001111111100000
0010000111100000
0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000

Best Answer

May be I misunderstand something, but where is inputs for your ALU module? So I think, the first problem in your structure is, in the case you haven't inputs for ALU you write into the memory unknown values (U or Z, what you have on ALU output) when write_en is active;

The second problem is in the module lab3_reg you have incorrect assignment in line assign data = DataOut;, it should be assign DataOut = data; because data is output of internal module you have "X" on the port (multiple drivers);

And last problem is in the tesbench testbench_lab3_reg module, there you also have bad assignment assign DataOut = (read_en) ? memory[Read_address] : memory[Write_address]; in this line. DataOut is output of your top module, but in the line you assign another value, in the case you also will get "X" on the wire.

Try to fix the mistakes in the assignments logic to correct and then I think your module will work well.

P.S. By the way, what do you want to get by the follow assignment assign DataOut = (read_en) ? memory[Read_address] : memory[Write_address]; when DataOut is output? If you want to use bidirectional bus you should declare it like inout in modules.