Verilog net to reg assignment - verilog

I have an input port from_LS(511:0). This is declared as wire in my module. I am assigning this to a set of 32 registers ilb(0:31), each of which are 1 nits long. I was trying to use the for loop to do this.
integer i;
genvar j;
initial
begin
count1 = 0;
count2=0;
flush_ctrl=0;
buffer_bit=0;
a=(hmic_ctrl[1]) + (hmic_ctrl[2]*2) + (hmic_ctrl[3]*4);
//assigning data from LS to ilb
for (i=0;i<=31;i=i+1)
ilb[i]=from_LS[511-(16*i) : 511-(16*(i-1))];
ilb[0]= from_LS[511:496];
ilb[1]= from_LS[495:480];
ilb[2]= from_LS[479:464];
ilb[3]= from_LS[463:448];
ilb[4]= from_LS[447:432];
ilb[5]= from_LS[431:416];
ilb[6]= from_LS[415:400];
ilb[7]= from_LS[399:384];
ilb[8]= from_LS[383:368];
ilb[9]= from_LS[367:352];
ilb[10]= from_LS[351:336];
ilb[11]= from_LS[335:320];
ilb[12]= from_LS[319:304];
ilb[13]= from_LS[303:288];
ilb[14]= from_LS[287:272];
ilb[15]= from_LS[271:256];
ilb[16]= from_LS[255:240];
ilb[17]= from_LS[239:224];
ilb[18]= from_LS[223:208];
ilb[19]= from_LS[207:192];
ilb[20]= from_LS[191:176];
ilb[21]= from_LS[175:160];
ilb[22]= from_LS[159:144];
ilb[23]= from_LS[143:128];
ilb[24]= from_LS[127:112];
ilb[25]= from_LS[111:96];
ilb[26]= from_LS[95:80];
ilb[27]= from_LS[79:64];
ilb[28]= from_LS[63:48];
ilb[29]= from_LS[47:32];
ilb[30]= from_LS[31:16];
ilb[31]= from_LS[15:0];
pctr(
.clk(clk),
.reset(0),
.offset(branch_ctrl[13:1]),
.mux_select(branch_ctrl[0]),
.pc1(pc)
);
end
I was getting the error that I should not use a variable index. The error is :
# ** Error: C:/Modeltech_pe_edu_10.0/examples/COMP ARC/inst_line_buf.v(55): Range must be bounded by constant expressions.
So i wrote down the following:
ilb[0]= from_LS[511:496];
ilb[1]= from_LS[495:480];
ilb[2]= from_LS[479:464];
....
ilb[31]= from_LS[15:0];
But i guess there must be a better way to do this. Could anyone tell me how?

The orginal verilog doesnt allow this kind of expression as it wanted to assure that the width is always right (it is, but in earlier times compilers werent as good :-).
Verilog 2001 offers some solution with +: you can specify the width
e.g. from_LS[ 511-(16*i) +:16 ] in your loop.
EDIT: Another solution would be to put another loop inside, which copies 16 bits bit by bit.

You should include more code (at least up to the always block containing that loop for the sensitivity list) and the exact error you're getting.
Does it work if you change integer i to genvar i and wrap the for in generate and endgenerate?

Related

Warning: Inferring latch for variable 'w_addra_t' (in Verilog/SystemVerilog with FOR loop)

I have an inferred latch problem after synthesis when I designed a simple dual port RAM block. Due to large code size, I have just embedded this always block code as follows:
integer i;
always_latch
begin
for (i=0;i<NUM_RAMS;i=i+1) begin
if (ena_t == 1) begin
w_addra_t[i] = w_addra[i];
end
else begin
w_addra_t[bank_addra[i]] = w_addra[i];
end
end
end
My RAM block includes NUM_RAMS numbers of banks. The addresses of respective input data are stored in w_addra.
Data with given w_addra addresses are scrambled into w_addra_t depend on the values of respective bank_addra (depend on access pattern) when ena_t = 0.
I tried to replace for loop with if...else, switch...case, generate but the problem is same. With different always block in my code that the left-side is with only w_addra_t[i] in both if.else of ena_t, there is no error.
I would like to get your suggestion if you have any idea. I did look for similar issue but getting no results.
Thanks very much :)
My guess is the entries for bank_addra are not guaranteed to be unique. If two or more entries hold the same values then an index hole is created for w_addra_t; which will infer a latch.
Here are three possible solution:
Functionally guaranteed that bank_addra entries will have unique values, then the synthesizer should not infer a latch. This can be challenging.
Move the address variation from the LHS to the RHS so that each index of w_addra_t is guaranteed to be assigned a value. Ex change w_addra_t[bank_addra[i]] = w_addra[i]; to w_addra_t[i] = w_addra[bank_addra_lookup[i]];.
Assign all entries of w_addra_t to a known value (constant, flip-flop, or deterministic value) before other logic. You can put this default assignment at the top of your always block (option 1 example) or above the logic where the latches were about to be inferred (option 2 example). This is the simplest solution to implement assuming it still satisfies relational requirements with your other code.
// NOTE: SystemVerilog supports full array assignments (Verilog requires a for-loop)
always_comb
begin
w_addra_t = '{default:'0}; // <-- default assignment : option 1
if (ena_t == 1) begin
w_addra_t = w_addra;
end
else begin
w_addra_t = w_addra_t_ff; // <-- default assignment : option 2
for (i=0;i<NUM_RAMS;i=i+1) begin
w_addra_t[bank_addra[i]] = w_addra[i];
end
end
end
always_ff #(posedge clk) begin
w_addra_t_ff <= w_addra_t; // assuming w_addra_t should hold it current values
end
TL;DR
always_latch is a SystemVerilog keyword to identify explicit latches. Some tools will auto-waive the warning when the keyword is used, but will throw an error/warning if the keyword is used and a latch is not detected.
If you know it should be combinational logic, then use the always_comb SystemVerilog keyword. With always_comb, if the synthesis detects a latch then it should report an error.
Read related question:
What is inferred latch and how it is created when it is missing else statement in if condition. Can anybody explain briefly?
I don't know if it will solve your problem by changing to
int i
always_comb
instead. Perhaps the tool gets sad when you use a 4-state variable like integer?

Proper way to use a bus in a for loop in SystemVerilog?

I'm trying to make a module in SystemVerilog that can find the dot product between two vectors with up to 8 8-bit values. I'm trying to make it flexible for vectors of different length, so I have an input called EN that's 3 bits and determines the number of multiplications to perform.
So, if EN == 3'b101, the first five values of each vector will be multiplied and added together, then output as a 32-bit value. Right now, I'm trying to do that like:
int acc = 0;
always_comb
begin
for(int i = 0; i < EN; i++) begin
acc += A[i] * B[i];
end
end
assign OUT = acc;
Where A and B are the two input vectors. However, SystemVerilog is telling me there's an illegal comparison being performed between i and EN.
So my questions are:
1) Is this the proper way to have a variable vector "length" in SystemVerilog?
2) If so, what's the proper way to iterate n times where n is the value on a bus?
Thank you!
I have to guess here, but I'm assuming it's a synthesizer complaining about that code. The synthesizer I use accepts your code with minor modifications, but maybe not all do since the loop can't be unrolled statically (notice I have input logic [2:0] EN, maybe input int EN does not work due to having too big a max number of cycles). Your loop per se (question #2) is fine.
int acc;
always_comb
begin
// If acc is not reset always_comb tries to update on its old value and puts
// it in sensitivity list, halting simulation... also no initialization to variable
// used in always_comb is allowed.
acc = 0;
...
This is a somewhat decent reason to complain about your otherwise perfectly good code, and the tool does not make the assumption that it is "reasonable" to generate all possible loops in this specific case (if EN was an unsigned integer your chip would be stupidly huge after all): you can force the tool to infer all possibilities with something that looks like the following:
module test (
input int A[8],
input int B[8],
input logic [2:0] EN,
output int OUT
);
int acc[8]; // 8 accumulators
always_comb begin
acc[0] = A[0] * B[0]; // acc[-1] does not exist, different formula!
for (int i = 1; i < 8; i++) begin
// Each partial sum builds on previous one.
acc[i] = acc[i-1] + (A[i] * B[i]);
end
end
assign OUT = acc[EN]; // EN used as selector for a multiplexer on partial sums
endmodule: test
The above module is an explicit description of the "parallel loop" my synthesizer infers.
Regarding your question #1, the answer is "it depends". In hardware there is no variable length, so unless you fix the number of iterations as a parameter as opposed to an input you either have a maximum size and ignore some values or you iterate over multiple cycles using pointers to some memory. If you want to have a variable vector length in a test (not going to silicon) then you can declare a "dynamic array" that you can resize at will (IEEE 1800-2017, 7.5: Dynamic arrays):
int dyn_vec[];
As a final side note, int bad integer good for everything that is not testbench in order to catch X values and avoid RTL-synthesis mismatch.

Interpreting concatenation operator with comparator

Our professor gave us this skeleton for a case statement, and so far no one is able to understand what it's doing.
always#(*)
begin
case(state)
3'b000:{nout, nstate} = (in)?(in=1):(in=0)
endcase
end
More insight:
This is being implemented as a button debouncer.
nout is the output of the next state: a single bit
nstate is the next state: 3 bits
in is also 1 bit wide
My understanding is that the concatenation operator will append nout to nstate resulting in 4 bits. (ie: if nout is 1 and nstate is 010, this part of the statement will produce 1010)
On the other side of the equality assignment we have a simple comparator, which upon further inspection, doesn't seem to do anything...
It's basically saying
if(in == 1) {
in = 1;
} else {
in = 0;
}
With that understanding, we're assigning a single bit to nout and nstate?
This understanding doesn't make any sense to me. I've compared my notes with 2 other classmates whom wrote the exact same thing so I'm thinking either we don't understand the code or there's an error.
Further insight:
Upon researching further, I've found the state diagram appear in multiple places, which makes me fairly confident that this is a common Moore Machine.
i hope that you did not cut and paste those expressions correctly.
3'b000:{nout, nstate} = (in)?(in=1):(in=0);
The above statement is a complete mess. Most likely it will fail any linting. It might be ok syntactically, but makes no sense logically and makes such code unreadable and not maintainable. It has to look like the following:
3'b000:{nout, nstate} = (in)?(1'b1):(1'b0);
The left hand side concat represents a signal with lower 3 bit associated with nstate, and upper n bits with nout. The right hand side ternary operator produces either one bit '1' or 1 bit '0' (actually id does the same int the original expression, because 'in' is 1 bit wide. Verilog will extend the rhs one bit to the size of the lhs and add missing '0's. As a result nout will be 0 and nstate will be either 3'b000 or 3'b001, depending on the value of in.

module selection in verilog

I have a group of modules, say module_1, module_2, ... module_N. They perform similar yet different logic operations (out = logic_n). However, since the N is very large (thousands), it is unfeasible to use them in a higher level module by manually instantiate them. I was trying to write a python code for this. I was also wondering is that possible to use parameterized module for this purpose? What I mean is something like.
module module_generic(in, out)
parameter module_number;
case (module_number)
0 : out = logic_1;
1 : out = logic_2;
...
N : out = logic_N;
endcase
endmodule
By doing this, I can use generate statement to easily generate the code in the higher level module. Has anyone try this method before? Can it behave like the way I want? After synthesis, is it equivalent to the brute-force solution?
Something like this?
module module_generic#(
parameter module_number = 0
)(
input logic in,
output logic out);
generate
case (module_number)
0 : assign out = in;
//1 : assign out = logic_2;
//...
//N : assign out = logic_N;
endcase
endgenerate
endmodule
This module can now be instantiated in your code with different inputs for parameter module_number. Unless a lot of the same code is used for each logic_X I don't really understand why you would want to do this. Nevertheless, as far as I could understand from your question, this should do it.
Edit in reply to comment:
Generate is used to generate repeated and conditional parts of the code based on some parameter (e.g. in a parameterized module). For example:
generate
if(INPUT_PARAMETER)
assign out = in;
else //Tie low
assign out = 0;
endgenerate
or
genvar N;
generate
for(N = 0; N < INPUT_PARAMETER; N++) begin :la_someModule
someModule(.out(out[N]), .in(in[N]));
end
endgenerate
or both. (Take note of the label la_someModule. It is very smart to include this when using generate for , it simplifies debugging.)
Specifically answering the question you have asked here is hard. You have not provided enough information for me to understand what you need.

Why is "gen_srl16" used in a standard "SRL16E" instantiation?

I've got this code snip. It's a standard instantiation, but why is gen_srl16 used? I always thought SRL16E srl16e (... should be enough.
genvar i;
generate
for (i=0;i<WIDTH;i=i+1)
begin :
gen_srl16
SRL16E srl16e(
.Q(dataout[i]),
.A0(a[0]),.A1(a[1]),.A2(a[2]),.A3(a[3]),
.CE(write),.CLK(clk),.D(datain[i])); // CE -clock enable
end
endgenerate
In this situation gen_srl16 is just a name of a generate for-loop. It has nothing to do with submodule instantiation.
Following Verilog spec (IEEE Std 1800-2012, ch. 27.4):
Generate blocks in loop generate constructs can be named or unnamed (...) If the generate block is named, it is a declaration of an array of generate block instances. The index values in this array are the values assumed by the genvar during elaboration. This can be a sparse array because the genvar values do not have to form a contiguous range of integers. The array is considered to be declared even if the loop generate scheme resulted in no instances of the generate block.

Resources