initializing an array in Verilog

T

tuclogicguy

Guest
I am trying to figure out how to initialize an array in Verilog. I am
coding a function that uses a lookup table with 512 entries. This was
easy to do in VHDL; I just coded an array constant with initial values
for every location (wrote a C program to generate the VHDL array
constant statement and all its values) and used an integer signal as an
index into the array. Now I am trying to convert this design to
Verilog. I currently have something working using a $readmemh statement
in an initial block, but I need something that is synthesizable. I'm
beginning to think that the only practical way of doing this in Verilog
is with a big case statement. Any comments/suggestions?

Thanks,
Charles Bailey
 
What I've seen in some fpga ip is using parameters for the reset value of either the whole array or byte by byte. Then the reset block is written to use the parameter value

Let's you write a generic array that resets to zero, for example , unless you specifically set the initial value when you instance it

Stephen
 
StephenOC wrote:
What I've seen in some fpga ip is using parameters for the reset value of either the whole array or byte by byte. Then the reset block is written to use the parameter value

Let's you write a generic array that resets to zero, for example , unless you specifically set the initial value when you instance it

Stephen

Depends on your synthesis tools. Xilinx XST allows you to initialize
any variable in an initial block. So for example:

reg [7:0] ramp_array [0:255];
integer i;
initial for (i = 0;i < 256;i = i + 1) ramp_array = i;

Or for a smaller array of random stuff:

reg [7:0] small_array [0:7];

initial begin
small_array[0] = 8'h22;
small_array[1] = 8'h42;
small_array[2] = 8'h57;
small_array[3] = 8'h10;
small_array[4] = 8'h09;
small_array[5] = 8'h11;
small_array[6] = 8'h99;
small_array[7] = 8'hAF;
end

And my favorite for larger arrays of random stuff, using an external
file with the initial values:

reg [7:0] large_array [0:1023];

initial $readmemh ("Large_Array_Values.txt", large_array);

All this works in XST, and probably a lot of other synthesis tools
these days.

--
Gabor
 
On Wednesday, December 17, 2014 1:02:45 PM UTC-8, tuclogicguy wrote:
What about for ASICs? I can't depend on an initial statement getting
executed magically during power-on. The values have to be already built
into the logic. I'm coming to the conclusion that Verilog simply
doesn't have a way to declare an array of constants.

If you're designing an ASIC, you work with the vendor to understand what Verilog idioms translate into what kind of hardware. This is an area of HDL where you don't have the option of ignoring the underlying hardware implementation.

For example, on-chip, your array could be implemented as raw flops set appropriately as you come out of reset, or as a masked-ROM, programmable EEPROM, EFUSES, or one of several different kinds of RAM. What you end up choosing will depend on how confident you are of these bits (changing the ROM or flops will involve changing a metal layer and no patches for units already in the field), how large the blob of data is, and what's available in your process (EEPROM or EFUSES might not be available or require voltages you don't want to devote pins to).

But it's unfair to say this is a limitation of Verilog.

-JohnG
 
What about for ASICs? I can't depend on an initial statement getting
executed magically during power-on. The values have to be already built
into the logic. I'm coming to the conclusion that Verilog simply
doesn't have a way to declare an array of constants.

Charles Bailey
 
tuclogicguy wrote:
What about for ASICs? I can't depend on an initial statement getting
executed magically during power-on. The values have to be already built
into the logic. I'm coming to the conclusion that Verilog simply
doesn't have a way to declare an array of constants.

Charles Bailey

Maybe you should ask your synthesis tool supplier. In Xilinx,
the code I showed using $readmemh works for synthesis. If you
never assign the reg outside the initial block a reasonable
synthesis tool should understand this to be a ROM.

Other than that you could go back to your C program and output
code like:

wire [7:0] small_ROM [0:7];

assign small_ROM[0] = 8'h22;
assign small_ROM[1] = 8'h42;
assign small_ROM[2] = 8'h57;
assign small_ROM[3] = 8'h10;
assign small_ROM[4] = 8'h09;
assign small_ROM[5] = 8'h11;
assign small_ROM[6] = 8'h99;
assign small_ROM[7] = 8'hAF;

If you don't like to have clutter pasted into your
other code, you can `include the generated file.
That also prevents the C code from trashing your
code edits.

--
Gabor
 
Thanks to all who have responded.
I should note that I'm trying to synthesize this logic with yosys.

;
initial $readmemh ("Large_Array_Values.txt", large_array);
I tried that but yosys gave an error on the $readmemh system task.

;
initial begin
small_array[0] = 8'h22;
small_array[1] = 8'h42;
small_array[2] = 8'h57;
small_array[3] = 8'h10;
small_array[4] = 8'h09;
small_array[5] = 8'h11;
small_array[6] = 8'h99;
small_array[7] = 8'hAF;
end
followed by:
yout = small_array[index];

That worked. yosys recognized and processed the initial block and then
optimized the logic the best it could. And, the results were better
(about 26%) than my first attempt, which used a big case statement to
compute the output.
 

Welcome to EDABoard.com

Sponsor

Back
Top