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
1 Answer 1
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
-
\$\begingroup\$ thank you mark ... So it means that array (which is row_data) passing is not permissible in verilog ? \$\endgroup\$SW.– SW.2014年08月31日 06:43:21 +00:00Commented 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– MarkU2014年09月01日 01:36:56 +00:00Commented Sep 1, 2014 at 1:36