2
\$\begingroup\$

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
\$\endgroup\$
2
  • 1
    \$\begingroup\$ "I am not getting the expected results". Care to elaborate? \$\endgroup\$ Mar 12, 2017 at 23:15
  • \$\begingroup\$ Yeah. Sorry. So, when I run the simulation in ModelSIM, those last five lines in the testbench module are suppose to read addresses 9 - 13, which should contain the results of the data contained in the 'memfile.dat' file being inputted into the alu/memory modules. The vectors contained in the 'memfile.dat' correspond to the inputs for the ALU, the first five of which have some numerical significance, while the rest of the vectors are 0's which I'm guessing would be used to store the data. I'll post the 'memfile.dat' in the my original posting. \$\endgroup\$ Mar 12, 2017 at 23:24

1 Answer 1

2
\$\begingroup\$

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.

\$\endgroup\$
2
  • \$\begingroup\$ Thanks for the reply. The inputs for the ALU module are coming from "memfile.dat", where the first three binary digits are the select bits, the next four digits are the first input, and the following four digits are the second input. The last five digits will always be zero. I will be looking at doing the changes you have suggested and will get back to you. Thanks. \$\endgroup\$ Mar 13, 2017 at 2:07
  • 1
    \$\begingroup\$ @davlovsky make a note that if you want to bring some data to module you should use port with INPUT direction rather than OUTPUT port. In the case you described you should take the data for ALU inputs from data port, which is output from the memory. Please, check directions of your port in each module. I think there has a big mess. \$\endgroup\$
    – Roman
    Mar 13, 2017 at 2:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.