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

JYelton
35.7k34 gold badges149 silver badges282 bronze badges
asked Aug 30, 2014 at 6:52
\$\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
answered Aug 30, 2014 at 9:30
\$\endgroup\$
2
  • \$\begingroup\$ thank you mark ... So it means that array (which is row_data) passing is not permissible in verilog ? \$\endgroup\$ 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\$ Commented Sep 1, 2014 at 1:36

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.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.