Generate instance with different string parameters in verilog - verilog

When I was config pll_reconfig module in Quartus II, the generate for statement in design have to specify different string parameter (filenames) to different instances.
I have tried these code:
genvar i;
generate
for (i=0; i<2; i=i+1) begin:u
rom #($sformatf("mif%d.mif",i)) U(
//signals connected.
);
end
endgenerate
It is said that the code is not synthesizable.
How can I specify variable string parameter in generate for block?

I had a similar problem but on a system that did not support $sformatf. My solution is a little dirty but may help others:
genvar i;
generate
for (i=0; i<10; i=i+1)
begin
mymodule #(.NAME("NAME0" + i) instance(.RESET(mreset) ... );
end
endgenerate
This works, I believe, by treating the string "NAME0" as a number (a 40-bit number). By adding i, you just increase the value by i and the result is the last ASCII char changes. Luckily '0' + i gives you '1', '2', '3' etc
The obvious flaw is this only works for 0-9, however there is a simple extension using divide and modulo arithmatic:
mymodule #(.NAME("NAME00" + (256 * (i / 10)) + (i % 10) ) ) ...
As a side note, I ran into issues using string concatenation {"NAME", i} because Verilog was treating i as 32-bit value so the string ends up as:
NAME 1
due to the extra 'unwanted' 24 bits which equate to 3 null characters

Related

Symbol ";" at the end of `define statement

With some simulators(for ex. VCS) the following code is passing and with some of them it brings to compilation error( for ex. Xcelium):
For example:
`define MAX_SIZE 8;
Who knows what is the reason that some simulators passing with ";" symbol at the end?
Best Regards,
The reason has to do with whether to tool is interpreting the code as Verilog or SystemVerilog. Verilog does not have the concept of a null statement, while SystemVerilog does:
module top;
;
endmodule
When you put a ; at the end of a macro and put one at the end of the statement that uses the macro, you wind up with a null statement.
`defne MAX_SIZE 8;
A = `MAX_SIZE;
This gets intrpreted as
A = 8; ;
So it depends on whether that null statement makes sense in the context where it appears.
begin
; // allowed here
case (expr)
1: A = 8;
2: A = 16; ; // null statement not allowed here
endcase
B = 8; ; // allowed here
end
Verilog text macros are used for text substitutions. In your case ; is a part of the macro definition. It will be placed in the text as is, for example:
`define MAX_SIZE 8;
...
assign abc = `MAX_SIZE
The last statement does not contain explicit semicolon. It is supplied by the macro when its text gets substituted there and will look like assign abc = 8;
answering the comment
It is not a good practice to use the ; in macro definition. Verilog is very strict about semicolons ad there are other issues as well. For example, if one puts a semicolon after a such macro, as in the comment, compilation will fail because of the double ;;
`assign abc = `MAX_SIZE;
The other example of failing compilation is declaration:
reg[`MAX_SIZE-1:0] ctrl;
Now, the semicolon from the MAX_SIZE would stay in the way.
The best way to avoid issues in verilog with macros: do not use semicolon in macro definition, in particular when you define constants:
`define MAX_SIZE 8
However, even a better way to define constants is to use parameters. parameter MAX_SIZE = 8;

Shifter output is always 0 when using concatenation and case

I have the following code:
module shifter(
input[7:0] in,
input[1:0] amt,
output logic[7:0] out
);
always_comb case(amt)
2'h0: out = in;
2'h1: out = {{in[6:0]}, 0};
2'h2: out = {{in[5:0]}, 0, 0};
2'h3: out = {{in[4:0]}, 0, 0, 0};
default: out = in;
endcase
endmodule
It describes a simple shifter which takes in the amount of shifts through the amt input. The problem is that no matter what the value of amt is (except 0), out is always 0 as seen on this waveform from a test:
Am I concatenating wrong? Examples I've seen online are similar to this, however.
Try constraining the size of the 0 to 1'b0 in 2'h1: out = {{in[6:0]}, 0};. What happens is that you are assigning a concatenation of in[6:0] and 32-bit (default width) 0, so only LSBs of the 0 goes to the out.
Also, default is redundant since you've described all the possible cases for amt.
The code you wrote is illegal according to the IEEE 1800-2017 LRM section 11.4.12 Concatenation operators:
Unsized constant numbers shall not be allowed in concatenations. This
is because the size of each operand in the concatenation is needed to
calculate the complete size of the concatenation
The tool you are using has a bug and did not catch this error, which is very difficult to find on your own.

verilog generate loop assign to iterator width mismatch

I am using a generate loop to instantiate a paramaterizable number of modules, and I want to assign some of the inputs to the module based on the loop iteration. Unfortunately I'm running into issues with synthesis where design compiler says there's an error because the port width doesn't match. Here's what I'm trying to do:
genvar k;
generate
for(k = 0; k < `NUM/2; ++k) begin
cmp2 cmps(
.a (arr[k]),
.b (arr[k+1]),
.a_idx (k), //gives errors about port width mismatch
.b_idx (k+1), //but I can't get it to work any other way
.data_out(data[k]),
.idx_out (idx[k])
);
end
endgenerate
I've also tried using localparams in the loop and assigning a_idx and b_idx to the localparam but I still get the same error under synthesis.
I've tried something like .a_idx((k)[bit_width-1:0]), but that doesn't work either.
Any ideas?
k and k+1 are 32-bit wide, which causes the width mismatch.
Depending on what your synthesis tool supports, you might want to try the following:
Bit slicing:
.a_idx (k[0 +: bit_width])
Cast to bit_width-wide logic:
typedef logic[bit_width-1:0] logicN_t;
// .... //
.a_idx (logicN_t'(k)),
.b_idx (logicN_t'(k+1)),
// .... //

Declaring an array of constant with Verilog

first i want to apologize for my ignorance,this question may be stupid for many of you..but i am a newbie in the domain of Hw dev
I am trying to turn a software function into a hardware accelerator...
in the C code we use an array of integer to calculate a certain value as shown here
uint k[64] = {
0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,
0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,
0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,
0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,
0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070,
0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,
0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
};
as you see here am gonna use it to calculate t1
$ t1 = h + EP1(e) + CH(e,f,g) + k[i] + m[i];
however am not certain how to declare this array without using registers, i have a verilog file in whitch it uses localparam to declare a constant. so i wonder could i use it with this vector as below ?
localparam [31:0] k[63:0] =
{0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,
0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,
0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,
0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,
0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070,
0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,
0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
};
Yes you can. However, 0x is not verilog syntax, use 32'h (or just 'h if you want it less strongly typed) instead.
localparam logic [31:0] k[63:0] =
{
32'h428a2f98,32'h71374491,32'hb5c0fbcf,32'he9b5dba5,32'h3956c25b,32'h59f111f1,32'h923f82a4,32'hab1c5ed5,
32'hd807aa98,32'h12835b01,32'h243185be,32'h550c7dc3,32'h72be5d74,32'h80deb1fe,32'h9bdc06a7,32'hc19bf174,
32'he49b69c1,32'hefbe4786,32'h0fc19dc6,32'h240ca1cc,32'h2de92c6f,32'h4a7484aa,32'h5cb0a9dc,32'h76f988da,
32'h983e5152,32'ha831c66d,32'hb00327c8,32'hbf597fc7,32'hc6e00bf3,32'hd5a79147,32'h06ca6351,32'h14292967,
32'h27b70a85,32'h2e1b2138,32'h4d2c6dfc,32'h53380d13,32'h650a7354,32'h766a0abb,32'h81c2c92e,32'h92722c85,
32'ha2bfe8a1,32'ha81a664b,32'hc24b8b70,32'hc76c51a3,32'hd192e819,32'hd6990624,32'hf40e3585,32'h106aa070,
32'h19a4c116,32'h1e376c08,32'h2748774c,32'h34b0bcb5,32'h391c0cb3,32'h4ed8aa4a,32'h5b9cca4f,32'h682e6ff3,
32'h748f82ee,32'h78a5636f,32'h84c87814,32'h8cc70208,32'h90befffa,32'ha4506ceb,32'hbef9a3f7,32'hc67178f2
};
You might be better off going with an integer type rather than localparam. Logic types are 4-state, which is more expensive on the simulator and since you are using it as a constant value (I assume), you should be fine with integer.
integer k[64] = {
32'h428a2f98,32'h71374491,32'hb5c0fbcf,32'he9b5dba5,32'h3956c25b,32'h59f111f1,32'h923f82a4,32'hab1c5ed5,
32'hd807aa98,32'h12835b01,32'h243185be,32'h550c7dc3,32'h72be5d74,32'h80deb1fe,32'h9bdc06a7,32'hc19bf174,
32'he49b69c1,32'hefbe4786,32'h0fc19dc6,32'h240ca1cc,32'h2de92c6f,32'h4a7484aa,32'h5cb0a9dc,32'h76f988da,
32'h983e5152,32'ha831c66d,32'hb00327c8,32'hbf597fc7,32'hc6e00bf3,32'hd5a79147,32'h06ca6351,32'h14292967,
32'h27b70a85,32'h2e1b2138,32'h4d2c6dfc,32'h53380d13,32'h650a7354,32'h766a0abb,32'h81c2c92e,32'h92722c85,
32'ha2bfe8a1,32'ha81a664b,32'hc24b8b70,32'hc76c51a3,32'hd192e819,32'hd6990624,32'hf40e3585,32'h106aa070,
32'h19a4c116,32'h1e376c08,32'h2748774c,32'h34b0bcb5,32'h391c0cb3,32'h4ed8aa4a,32'h5b9cca4f,32'h682e6ff3,
32'h748f82ee,32'h78a5636f,32'h84c87814,32'h8cc70208,32'h90befffa,32'ha4506ceb,32'hbef9a3f7,32'hc67178f2
};

Using an array of parameters to generate modules

I have a module which stores a bitmap of different characters, that I am planning on using to display text on a matrix. Currently, the bitmap is populated with a memory initialization file, and this file is passed in as a parameter (I have confirmed this working in Quartus and ModelSim).
In order to actually have a lookup table for all the characters, I wanted to make a separate module which has instantiations of the all bitmaps, and selects the correct one based on a character code. These bitmap instantiations are created in a generate block, and they take the correct filename from an array. However, ModelSim doesn't like this. My code is as follows:
module mem_char_disp_lib(
output logic pixel,
input logic [4:0] x,
input logic [5:0] y,
input logic [6:0] code,
input logic clk
);
localparam CHAR_NUM = 26;
logic [CHAR_NUM-1:0] alphabet;
const var [CHAR_NUM-1:0] BITMAPS = {
"/mem/char/A.hex",
"/mem/char/B.hex",
"/mem/char/C.hex",
// ... a lot more declarations here...
"/mem/char/X.hex",
"/mem/char/Y.hex",
"/mem/char/Z.hex"
};
genvar i;
generate
for (i=0; i<CHAR_NUM; i=i+1) begin : mem_char_disp_blocks
mem_char_disp #(.BITMAP(BITMAPS[i])) block (
.pixel(alphabet[i]),
.x, .y, .clk,
.code(i),
.data(1'b0),
.write_en(1'b0)
);
end
endgenerate
always_comb
pixel = alphabet[code];
endmodule
The error ModelSim is giving me is:
The expression for a parameter actual associated with the parameter name ('BITMAP') for the module instance ('block') must be constant.
(referring to the line inside the for loop)
I am not sure why this doesn't work. On a hardware level, it seems like I'm just making a lot of copies of a module, and slightly tweaking each one with a constant parameter known at compile-time. Is there some basic syntax that I'm missing?
Edit: I have also tried the following code, which seems to give a runtime error:
for (i=0; i<CHAR_NUM; i=i+1) begin : mem_char_disp_blocks
parameter [CHAR_NUM-1:0] BITMAPS = {
"/mem/char/A.hex",
// more elements...
"/mem/char/Z.hex"
};
mem_char_disp #(.BITMAP(BITMAPS[i])) block (
.pixel(alphabet[i]),
.x, .y, .clk,
.code(i),
.data(1'b0),
.write_en(1'b0) );
end
The error is Module parameter 'BITMAP' not found for override. (One of these errors for each of the generated modules; CHAR_NUM total.) This doesn't make sense to me, since instantiating a single one directly works just fine (e.g. mem_char_disp #(.BITMAP("/mem/char/A.hex") block /* ... */).
A const variable is not a constant - it is a write-once variable that gets initialized at runtime when the variable gets allocated. You need to us a parameter or localparam to assign to another parameter as you discovered in your update. You also need to fix the dimensions of the array
parameter bit [1:15*8] BITMAPS[26] = {
"/mem/char/A.hex", // 15 8-bit chars
// more elements...
"/mem/char/Z.hex" // 26 elements
};
Can't help you with your last error without seeing the declaration of the module mem_char_disp

Resources