0
\$\begingroup\$

What is wrong with following Verilog code where I am trying to pass a one-dimensional array?

module stimulus;             
wire [3:0] max,med,min;                  
reg[3:0] row_data[0:2];               
reg cin;               
sorting_three sr(max,med,min,row_data,cin);      // line no.27      
initial begin              
row_data[0]=4'b0010;            
row_data[1]=4'b1001;                 
row_data[2]=4'b1010;              
cin=1'b0;                      
end                   
endmodule   

It's giving an error like:

ERROR:HDLCompiler:251 - "stimulus.v" Line 27. Cannot access memory row_data directly ERROR:HDLCompiler:598 - "stimulus.v" Line 21. Module stimulus ignored due to previous errors

\$\endgroup\$

1 Answer 1

5
\$\begingroup\$

There seems to be a problem in the port declaration for module sorting_three. You're trying to pass an argument that can't exist.

Looks like module stimulus must be a test bench for module sorting_three, since module stimulus does not have any input or output ports.

Test bench module stimulus declares memory row_data as a 1-dimensional array of 4-bit registers, first address 0 last address 2. So this memory must have two address bits and four data bits. Initial values are declared in the initial block. This seems to be used as read-only memory, there's nothing to indicate that the values would ever be changed from the initial values when the circuit is synthesized.

But how does that row_data memory connect to module sorting_three?

Verilog is a hardware synthesis language. The read-only memory row_data must connect to module sorting_three through its 2-bit address port and its 4-bit data port. There is no such thing as the address of the row_data array "in memory", there's only the RTL code that describes the hardware. If you've come from a software programming background, this is the trickiest thing about learning Verilog or VHDL: thinking about what hardware circit you want to synthesize instead of describing its runtime behavior.

The test bench has to declare not only that the row_data memory array exists somewhere in the hardware, but also declare the wires that connect to the memory's address and data ports:

reg  [3:0] row_data[0:2];  // read-only memory, 4-bit data x 2-bit address
wire [1:0] row_data_address; // driven by module sorting_three
wire [3:0] row_data_dout; // driven by row_data[row_data_address]
assign row_data_dout = row_data[row_data_address];

The declaration for sorting_three should look like this (note I'm using Verilog 2001 style port declarations for readability):

module sorting_three_Memory (
    output reg  [3:0] max,
    output reg  [3:0] med,
    output reg  [3:0] min,
    output reg  [1:0] row_data_address, // drives row_data address
    input  wire [3:0] row_data_dout, // driven by row_data data out
    input  wire cin // clock
    );

Inside module sorting_three, the output port row_data_address must be driven to 2'b00, 2'b01, or 2'b10 to select one element of row_data on each clock cycle. Then, on the next clock cycle, valid data from row_data should be available from row_data_dout.

If the module needed to be able to write into the memory as well as read, then the memory needs to use additional ports for data_in and write_enable.

If the module was accessing off-chip memory, then additional clock cycles (known as "wait states") might be needed before valid data became available. But for on-chip memory inside an FPGA, usually single cycle access.

Alternative without synchronous memory access

Since there are only three addresses, and they seem to be read-only, you could pass them all individually instead of packing them into row_data memory:

module sorting_three_noMemory (
    output reg  [3:0] max,
    output reg  [3:0] med,
    output reg  [3:0] min,
    input  wire [3:0] row_data_0, // example 4'b0010
    input  wire [3:0] row_data_1, // example 4'b1001
    input  wire [3:0] row_data_2, // example 4'b1010
    input  wire cin
    );

However Verilog doesn't support a port declaration like input wire [3:0] row_data_array [0:2], that's not something that could be synthesized in hardware.

No clock in testbench

A second problem is this test bench doesn't seem to be driving a clock. I usually use something like this to generate a testbench clock for simulation:

localparam CLK_FREQ_HZ = 50_000_000;
localparam CLK_PERIOD_NS = 1_000_000_000 / CLK_FREQ_HZ;
always begin 
    #(CLK_PERIOD_NS/2.0); 
    clk=1; 
    #(CLK_PERIOD_NS/2.0); 
    clk=0; 
end
\$\endgroup\$
2
  • \$\begingroup\$ thank you mark ... So it means that array (which is row_data) passing is not permissible in verilog ? \$\endgroup\$
    – SW.
    Commented Aug 31, 2014 at 6:43
  • \$\begingroup\$ The way you "pass an array" in hardware is by connecting to the memory's address and data ports. Otherwise the module literally has no physical connection to the memory. Verilog's syntax does not support passing a reference to the memory without explicitly connecting the memory's address and data ports to the module's ports. \$\endgroup\$
    – MarkU
    Commented Sep 1, 2014 at 1:36

Your Answer

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

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