synthesizable way to load initial values in verilog - file

I would like to write a module that uses some coefficients that are loaded from a file.
For example:
reg [3:0] coeffs[0:1];
reg [6:0] ans;
always #(posedge clk) begin
if (!reset) begin
coeffs[0] <= 3;
coeffs[1] <= 2;
ans <= 0;
end
else begin
ans <= coeffs[0] * coeffs[1];
end
end
I would like to replace the values 3 and 2 by values that I can modify in a file, and provide the file during synthesis.
Obviously, this file will only assign initial values to the registers.
I don't want it to be a block ram, I want it to be like independent registers.
Just to clarify, I need the solution to be very generic, because I intent to use it in many modules that are doing the same thing, but with a different number of coefficients.
Meaning, in the end I wish to have a generic module that receives as a parameter a file name that stores the coefficients, and the number of coefficients and their width, and generates a code using those parameters.
I have tried readmemh but I understood it is only synthesizable to initiate a memory.
Any suggestions?
Thanks.

Here's a suggestion: put the statements initialising the array coeffs in an include file, eg
coeffs.v:
coeffs[0] <= 3;
coeffs[1] <= 2;
code:
reg [3:0] coeffs[0:1];
reg [6:0] ans;
always #(posedge clk) begin
if (!reset) begin
`include "coeffs.v"
ans <= 0;
end
else begin
ans <= coeffs[0] * coeffs[1];
end
end
An include file is included at compile time. So, your synthesiser will insert the contents of the file in the right place in the design. You could then manage the files using your operating system.

I am happy to stand corrected, but apart from 'Trickery' (Include files, define files, running a script generating such before synthesis) I am not aware of any method where you can load plain numbers from a file for synthesis.
I admit it a is problem waiting for a solution.
If only to prevent major embarrassment when your chip comes back from the manufacturer and you find the boot-rom is completely empty.... As if that ever happened where I worked (rolls eyes) Fixing requires only a single (contact) layer change but the lower layer masks are the most expensive).

Using parameter to pass the initial value is better option.
module A
#( parameter INITIAL_VALUE_COEFFS_0 = 3,
parameter INITIAL_VALUE_COEFFS_1 = 2)
( /* ignore it */ );
reg [3:0] coeffs[0:1];
reg [6:0] ans;
always #(posedge clk) begin
if (!reset) begin
coeffs[0] <= INITIAL_VALUE_COEFFS_0;
coeffs[1] <= INITIAL_VALUE_COEFFS_1;
ans <= 0;
end
else begin
ans <= coeffs[0] * coeffs[1];
end
end
endmodule

Related

Verilog/SystemVerilog inferred latch in case statement

I am having trouble understanding why my code have a latch
logic [1:0] lru_list [0:3];
always_comb begin
if(reset) begin
lru_list[0] = 0;
lru_list[1] = 0;
lru_list[2] = 0;
lru_list[3] = 0;
end
else begin
case({access, update, access_index_i < 4})
3'b101: begin
lru_list[0] = lru_list[0] + 1;
lru_list[1] = lru_list[1] + 1;
lru_list[2] = lru_list[2] + 1;
lru_list[3] = lru_list[3] + 1;
lru_list[access_index_i] = 0;
end
3'b011: begin
lru_list[0] = lru_list[0];
lru_list[1] = lru_list[1];
lru_list[2] = lru_list[2];
lru_list[3] = lru_list[3];
lru_list[access_index_i] = 0;
end
default: begin
lru_list[0] = lru_list[0];
lru_list[1] = lru_list[1];
lru_list[2] = lru_list[2];
lru_list[3] = lru_list[3];
end
endcase
end
end // always_comb
In the case statement, I have a default case which will catch all the unmatched values. I have also set each index in the array a value. I don't understand where I am implicitly setting my array a implicit value.
I thought it might have to do with lru_list[access_index_i] = 0;, but commenting those two lines out will still give me the save error.
Here is what I would start with.
First add a sensitivity list to the always statement. You have a "reset" if in there so it sounds like you want the always # (posedge clk or posedge reset). I know you are using always_comb, but I would be curious to know if that actually does remove the issue or not. It would be telling.
EDIT: So I just realized you are doing operations on the LHS variables using the same variables on the RHS. You need to clock this. Otherwise when you combinatorially enter the counting state, it can never resolve as it is always adding in an infinite loop. Do the always # (posedge clk or posedge reset) and you will get better results I think.
Second, and probably more important, it looks like you are using access_index_i < 4 and trying to extract a bit from it to make up the least significant bit of your concatenated vector {access, update, access_index_i < 4}. If you are shifting to the right, I think the logic would insert 4'b0000 in the result and I am guessing it is not really a bit to begin with, so I am wondering what bit actually gets used during the 3'b101 case as it would be addressed by {bit,bit,vector}. Seems like you would want to say {bit,bit,vector[4]} or something to that effect. You might actually be using the least significant 3 bits of the your access_index_i to address your combinational statement.
EDIT: Responding to your comment below. You can, (And this is what I do) break the problem into two parts, the combinatorial and the clocked.
reg [3:0] my_sig;
wire [3:0] my_sig_wire;
always # (posedge clk)
begin
my_sig <= my_sig_wire;
end
always (*)
begin
if(reset)
begin
my_sig_wire = 4'b0000; // This will also reset the clocked version
end
else
begin
my_sig_wire = my_sig; // This is okay, because no matter
// how much I alter my_sig_wire, my_sig will
// only change on the clock pulse. So
// we avoid the infinite loop problem
my_sig_wire[index] = 1'b0; // Tweak one of the signals for fun.
// on the next clock, my_sig is updated!
end
end
Combinatorial blocks define there output purely based on inputs, there is no state.
Sequential elements (flip-flops) contain state and therefore outputs can be based on inputs and state, or just state.
Your default statement:
default: begin
lru_list[0] = lru_list[0];
Is maintaining state by holding a value and therefore can not be combinatorial. You have not defined a flip-flop (#(posedge clk)) so a latch has been inferred to hold the state.

Why is this variable not considered a constant?

The following is code I wrote is a test bench to simulate a decoder (Verilog HDL). It converts [15:0]IR to [25:0]ControlWord. Literal is a byproduct that is watched as well.
All values from 0-65535 need to be tested for the 16-bit IR variable. In the beginning of the loop, I distinctly assign IR to be 0, but Quartus is telling me that:
Warning (10855): Verilog HDL warning at controluni_tb.v(20): initial value for variable IR should be constant
and as a result I get the following:
Error (10119): Verilog HDL Loop Statement error at controluni_tb.v(23): loop with non-constant loop condition must terminate within 250 iterations
The code for my test bench module is as follows:
module controluni_tb;
reg [15:0]IR;
reg clock;
wire [25:0]ControlWord;
wire [15:0] literal;
Total_Control_Unit_2 dut (IR,ControlWord,literal);
initial
begin
clock <= 1'b0;
end
initial
begin
IR <= 16'b0;
end
initial
begin
forever
begin
#1 IR <= IR + 16'b1;
end
end
initial
#65535 $finish;
endmodule
Your code has no errors. initial blocks and system functions ($finish) is used for simulation (not synthesis). That error is related to synthesis. I edited your code for more readability (your clock is always zero!) :
module controluni_tb;
reg [15:0]IR;
reg clock;
wire [25:0]ControlWord;
wire [15:0] literal;
Total_Control_Unit_2 dut (IR,ControlWord,literal);
initial begin
clock = 1'b0;
end
initial begin
IR = 16'b0;
forever #1 IR = IR + 16'b1;
end
initial begin
#65535 $finish;
end
endmodule
Instead of using a forever loop, why not just use a for loop for IR? Then the problem is completely bounded.
initial begin
for (IR = 0; IR <= 65535; IR++);
$finish;
end

Concatenation operator in System verilog in a loop

I am trying to do the following : concat = {concat[7:0],clk} inside a forever loop as below :
bit [7:0] concat;
concat = 0;
forever begin
#(posedge clk);
concat = {concat[7:0],clk};
end
I wanted to know what value will it contain after 8 clock iterations at any point of time, if the initial value of concat = 0.
Can it be different from 'hAA or 'h55 at any point of time?
You can not just write concat = 0; you should either assign concat = 0; or
initial begin
concat = 0;
end
Forever can not be used like that, the only two top levels you're allowed are initial and always. You want some thing like the following for a simulation:
initial begin
forever begin
#(posedge clk);
concat = {concat[6:0],clk};
end
end
If you are writing for synthesis then you might want to imply a flip-flop:
always #(posedge clk) begin
concat = {concat[6:0],clk};
end
Once you have fixed your RTL it should be easy to try out on EDA Playground.
Since you have #(posdege clk), clk will always be 1 (or x) when evaluating the RHS of the assignment. So concat will be 'h00, 'h01, 'h03, 'h07, 'h17, ...
Also note that if any other thread tries to read concat on the same positive edge of clk, you have a race condition, so please use a NBA to make the assignment.

How can I use a prepared module in a loop in Verilog?

I am trying to generate 128 parellel XOR gates, and then connecting their outputs to 64 XOR gates in Verilog. I use a module that prepared named "EXOR". My problem is: When I put this module "EXOR" into the loop, program gives syntax error "unexpected token: 'EXOR'". And I want to name the gates exor0, exor1, ... .
How can I solve it?
initial begin
for (i=0; i<128 ; i=i +1 )
EXOR exor[i](.I1(m[2*i]), .I2(m[2*i+1]), .o(t[i]));
end
initial begin
for (i=0; i<64 ; i=i +1 )
EXOR exor[i+128](.I1(t[2*i]), .I2(t[2*i+1]), .o(f[i]));
end
initial begin
for (i=0; i<32 ; i=i +1 )
EXOR exor[i+192](.I1(f[2*i]), .I2(f[2*i+1]), .o(g[i]));
end
To elaborate on Munkymorgy's answer what you're looking for here is a generate loop. 'initial' and 'always' blocks are used for "runtime" constructs. Since you're trying to create an array on instances you want something interpreted at elaboration time.
genvar i;
generate
for (i = 0; i < 64; i = i + 1) begin : gen_loop
EXOR exor(.I1(m[2 * i]), .I2(m[2 * i + 1], .o(t[i]));
end
endgenerate
Two things:
1) The loop variable has to be declared as a 'genvar'
2) The for loop needs to be named. This will be used in the hierarchical name of the instance.

SAS: Dynamically Setting a Variable Name

In this block of SAS data step code I am setting a Table from an SQL query called TEST_Table. This table contains multiple columns including a larger section of columns titled PREFIX_1 to PREFIX_20. Each column starts with PREFIX_ and then an incrementing number from 1 to 20.
What I would like to do is iteratively cycle through each column and analyze the value of that column.
Below is an example of what I am trying to go for. As you can see I would like to create a variable that increases on each iteration and then I use that count value as a part of the variable name I am checking.
data TEST_Data;
set TEST_Table;
retain changing_number;
changing_number=1;
do while(changing_number<=20);
if PREFIX_changing_number='BAD_IDENTIFIER' then do;
PREFIX_changing_number='This is a bad part';
end;
end;
run;
How would be the best way to do this in SAS? I know I can do it by simply checking each value individually from 1 to 20.
if PREFIX_1 = 'BAD_IDENTIFIER' then do;
PREFIX_1 = 'This is a bad part';
end;
if PREFIX_2 = ...
But that would be really obnoxious as later I will be doing the same thing with a set of over 40 columns.
Ideas?
SOLUTION
data TEST_Data;
set TEST_Table;
array SC $ SC1-SC20;
do i=1 to dim(SC);
if SC{i}='xxx' then do;
SC{i}="bad part";
end;
end;
run;
Thank you for suggesting Arrays :)
You need to look up Array processing in SAS. Simply put, you can do something like this:
data TEST_Data;
set TEST_Table;
*retain changing_number; Remove this - even in your code it does nothing useful;
array prefixes prefix:; *one of a number of ways to do this;
changing_number=1;
do while(changing_number<=20);
if prefixes[changing_number]='BAD_IDENTIFIER' then do;
prefixes[changing_number]='This is a bad part';
end;
end;
run;
A slightly better loop is:
do changing_number = 1 to dim(prefixes);
... loop ...
end;
As that's all in one step, and it is flexible with the number of array elements (dim = number of elements in the array).

Resources