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.
Related
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?
I want to pass a parameter to a function and use it as a parameter (e.g. to select bits) but I don't know how to tell the function that this input is a constant.
For example, if I wanted to do this:
assign foo = bar[MY_PARAM:0];
I want to write my_function so that I could do this:
assign foo = my_function(bar, MY_PARAM);
In my case I need to do a little more that just select bits but not too much, and I'll want it to work for inputs of different bit widths.
If I just wanted to select a bit I could use the function below and I'd hope for a solution of similar form but I can't work out the syntax:
function my_function;
input [3:0] data, my_bit;
begin
my_function = data[my_bit];
end
endfunction
As per Silicon1602's answer, the code I'd need for this would be:
virtual class myClass#(parameter LOCAL_PARAM);
static function [LOCAL_PARAM:0] my_function;
input [LOCAL_PARAM:0] data;
begin
my_function = data[LOCAL_PARAM:0];
end
endfunction
endclass
assign foo = myClass#(MY_PARAM)::my_function(bar);
At first I forgot about the [LOCAL_PARAM] part and was just getting 1-bit back.
The SystemVerilog LRM has a section on your particular case: 13.8 Parameterized tasks and functions. It says:
SystemVerilog provides a way to create parameterized tasks and functions, also known as parameterized subroutines. [...] The way to implement parameterized subroutines is through the use of static methods in parameterized classes (see 8.10 and 8.25).
In your case, you should declare your function like this:
virtual class myClass#(parameter MY_PARAM);
static function my_function;
input [MY_PARAM-1:0] data, my_bit;
begin
my_function = data[my_bit];
end
endfunction
endclass
You could then call your function like this:
assign my_function_output = myClass#(MY_PARAM)::my_function(data, my_bit);
Please note that you may declare multiple functions in your abstract class. So, if you have a whole bunch of functions which all depend on a parameter in the same way, you could all declare them in the same class.
Some additional information on the virtual and static keyword in the aforementioned context:
Section 8.10 of the LRM talks about static methods.
A static method is subject to all the class scoping and access rules, but behaves like a regular subroutine that can be called outside the class, even with no class instantiation. A static method has no access to non-static members (class properties or methods), but it can directly access static class properties or call static methods of the same class.
By using the virtual keyword for the class declaration, you show the compiler that this is an abstract class (see Section 8.21 in the LRM). Creating an object of a virtual class causes a compilation error. This enforces strict static usage of the method.
Since the question was also tagged as 'verilog', a similar trick could be played in a simple verilog. You can use parameterized modules to achieve the same effect. For example:
module util#(
parameter int W = 10)();
function funct;
input [W-1:0] inp;
funct = inp;
endfunction
endmodule
module top(out, in);
parameter W = 8;
output wire [W-1:0] out;
input wire [W-1:0] in;
util#(W) u1(); // inst util module with a parameter
assign out = u1.funct(in); // call the function
initial #1 $finish;
endmodule
By default, all functions declared within a module are static.
You can use macro expansion to achieve this. I wanted a function that would check different test stimulus. The simulation arrays of 'bus' signals (or multi-bit values) and this was my 'parameter'.
`define MY_FUNCTION(LOCAL_PARAM) \
function my_function_``LOCAL_PARAM``; \
input [LOCAL_PARAM:0] data, my_bit; \
begin \
my_function_``LOCAL_PARAM`` = data[my_bit]; \
end \
endfunction \
Later...
`MY_FUNCTION(10)
my_function_10 (data_ten, my_bit); // Really my_bit is size $clog of LOCAL_PARAM.
Like Serge's answer, this works with Verilog (2001). Also, you can use tasks and then the entire module net is available. The macro call is equivalent the module instantiation with a parameter. It is basically like the elaboration phase.
Probably the module solution has more valid syntax and constructs. However, a macro of a function can achieve a similar result for simulation and could be suitable for some synthesis cases.
I am learning Verilog at the moment by using Yosys to synthesize code to an iCE40 development board. I am stuck at using parameters in verilog. I have the following code:
module tst;
parameter clkspd=12000000;
parameter baudrate=115200;
localparam bitperiod=$floor(clkspd/baudrate-0.5);
localparam bittmrwidth=$clog2(bitperiod);
//localparam bittmrwidth=$clog2(103);
initial begin
$display("Hello World!");
$display("width=%d",bittmrwidth);
end
endmodule
When I compile the code with :
yosys -p 'synth_ice40 -top tst -blif tst.blif' tst.v
I get an error:
ERROR: Failed to evaluate system function `\$clog2' with non-constant value at tst.v:5.
However if I use the commented out line, everything work as expected.
How can I calculate "bittmrwidth" with the given parameters ?
I don't have yosys installed, but when I run your code on another simulator, I get this error:
System function call $clog2 must have an integral argument.
This is consistent with the IEEE Std 1800-2012, section 20.8.1 Integer math functions, which states for $clog2:
The argument can be an integer or an arbitrary sized vector value.
The $floor function returns a real result type, according to section 20.8.2 Real math functions. Simply cast the $floor output to an integer type with $rtoi. The following code runs without errors for me:
module tst;
parameter clkspd=12000000;
parameter baudrate=115200;
localparam bitperiod = $rtoi($floor(clkspd/baudrate-0.5));
localparam bittmrwidth=$clog2(bitperiod);
initial begin
$display("Hello World!");
$display("width=%d",bittmrwidth);
end
endmodule
/*
Output:
Hello World!
width= 7
*/
My original code used a cast operator, but apparently yosys does not yet support it, according to the Comment below. Here was my original line:
localparam bitperiod = int'($floor(clkspd/baudrate-0.5));
I am trying to get yosys to synthesize my design to structural verilog for a tool which doesn't understand the syntax {A, B} to specify the concatenation of values A and B.
So for example when yosys generates statements like
assign C = {A,B};
assign {D,E} = F;
the tool chokes. I thought of using the splitnets pass to eliminate multibit wires, but the multibit ports still cause yosys to generate the {} syntax. Even running splitnets -ports leaves some assignments like
assign {A, B} = {C, D}
I was finally able to get these assignments to disappear using an additional run of opt. But this seems to be a very messy way of eliminating the {} construct.
Is there some nicer way to eliminate this construct without splitting all the input ports?
There is no universally applicable way to do that. The {..} operator is part of verilog and thus the verilog back-end uses it when appropriate.
However, in the example you gave all cells in the verilog output have single-bit in- and outputs, so the {..} operator is not needed for assigning cell ports, only for assigning wires to each other.
I've used the following script (executed in your rtl/ directory) as a baseline:
read_verilog aes_128.v table.v round.v
hierarchy -top aes_128
proc; flatten; synth
# opt_clean -purge
write_verilog -noattr -noexpr out.v
This will produce a Verilog file with the following assignments in it that use the {..} operator:
$ grep '{' out.v
assign \a1.S4_0.in = { key[23:0], key[31:24] };
assign { \a1.k0a [31:25], \a1.k0a [23:0] } = { key[127:121], key[119:96] };
assign \a1.v0 = { key[127:121], \a1.k0a [24], key[119:96] };
However, the signals a1.S4_0.in, a1.k0a, and a1.v0 are only present in the design because yosys tries to preserve as many of the original signal names as possible, to make it easier to debug the design.
Un-commenting the opt_clean -purge command will let yosys remove those signals, yielding an output file that does not use the {..} operator:
$ grep -c '{' out.v
0
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?