SystemVerilog Initialize multi dimensional parameterized array in - verilog

I am trying to initialize a multi dimensional parameterized array in SystemVerilog which I have described as below:
...
parameter INPUT_WIDTH = 16;
parameter NUM_ELEMENTS = 4;
...
reg signed [INPUT_WIDTH-1 : 0 ] ss_res_reg[NUM_ELEMENTS-1:0];
I want to initialize the ss_res_reg to zero on every falling edge of rst so:
always_ff #(posedge clk or negedge rst) begin
if(~rst) begin
ss_res_reg <= '{NUM_ELEMENTS{NUM_ELEMENTS{1'b0}}};
end else begin
ss_res_reg <= ss_res;
end
end
The problem is with this line ss_res_reg <= '{NUM_ELEMENTS{INPUT_WIDTH{1'b0}}};. If I change it to ss_res_reg <= '{NUM_ELEMENTS{16'b0}}; it works perfectly fine. However, when I want to use the INPUT_WIDTH parameter, Xilinx tool gives me the following error: syntax error near {. I also tried ss_res_reg <= '{NUM_ELEMENTS{16{1'b0}}}; and got the same error. Does anyone know what am I doing wrong?

You can use the default label in an assignment pattern to assign all elements of an unpacked array having any number of dimensions:
always_ff #(posedge clk or negedge rst) begin
if(~rst) begin
ss_res_reg <= '{default:'0};
end else begin
ss_res_reg <= ss_res;
end
end
'0 means fill the packed array with 0's

The error lies in the fact that you can not replicate unpacked array elements.
There is a simple solution:
if(~rst)
for (integer i=0; i<NUM_ELEMENTS; i++)
ss_res_reg[i] <= {INPUT_WIDTH{1'b0}};

Related

Find Maximum Number present in Verilog array

I have tried writing a small verilog module that will find the maximum of 10 numbers in an array. At the moment I am just trying to verify the correctness of the module without going into specific RTL methods that will to do such a task.
I am just seeing a a couple of registers when I am synthesizing this module. Nothing more that that. Ideally the output should be 7 which is at index 4 but I am seeing nothing neither on FPGA board or in the test bench. What I am doing wrong with this ?
module findmaximum(input clk,rst,output reg[3:0]max, output reg[3:0]index);
reg [3:0]corr_Output[0:9];
always#(posedge clk or posedge rst)
if(rst)
begin
corr_Output[0]=0;
corr_Output[1]=0;
corr_Output[2]=0;
corr_Output[3]=0;
corr_Output[4]=0;
corr_Output[5]=0;
corr_Output[6]=0;
corr_Output[7]=0;
corr_Output[8]=0;
corr_Output[9]=0;
end
else
begin
corr_Output[0]=0;
corr_Output[1]=0;
corr_Output[2]=0;
corr_Output[3]=0;
corr_Output[4]=7;
corr_Output[5]=0;
corr_Output[6]=0;
corr_Output[7]=0;
corr_Output[8]=0;
corr_Output[9]=0;
end
integer i;
always#(posedge clk or posedge rst)
if(rst)
begin
max=0;
index=0;
end
else
begin
max = corr_Output[0];
for (i = 0; i <= 9; i=i+1)
begin
if (corr_Output[i] > max)
begin
max = corr_Output[i];
index = i;
end
end
end
endmodule
Looking are your code, the only possible outputs are max=0,index=0 and a clock or two after reset max=7,index=4. Therefore, your synthesizer is likely optimizing the code with equivalent behavior with simpler logic.
For your find max logic to be meaningful, you need to change the values of corr_Output periodically. This can be done via input writes, LFSR (aka pseudo random number generator), and or other logic.
Other issues:
Synchronous logic (updated on a clock edge) should be assigned by with non-blocking (<=). Combinational logic should be assigned with blocking (=). When this guideline is not followed there is a risk of behavior differences between simulation and synthesis. In the event you need to compare with intermediate values (like your original max and index), then you need to separate the logic into two always blocks like bellow. See code bellow.
Also, FPGAs tend to have limited asynchronous reset support. Use synchronous reset instead by removing the reset from the sensitivity list.
always#(posedge clk) begin
if (rst) begin
max <= 4'h0;
index <= 4'h0;
end
else begin
max <= next_max;
index <= next_index;
end
always #* begin
next_max = corr_Output[0];
next_index = 4'h0;
for (i = 1; i <= 9; i=i+1) begin // <-- start at 1, not 0 (0 is same a default)
if (corr_Output[i] > next_max) begin
next_max = corr_Output[i];
next_index = i;
end
end
end

Using a for loop inside a clocked process: "Cannot generate logic"

I would like to generate a number of statements inside a clocked process, seen below:
parameter C_INPUT_LENGTH = 32;
parameter C_OUTPUT_NUM_BITS = 5;
reg [C_OUTPUT_NUM_BITS-1:0] address;
reg [C_INPUT_LENGTH-1:0] vector_i;
always#(posedge clk) begin
if(rst) begin
address <= 0;
end
else begin
if (vector_i[0] == 1) begin
address <= 0;
end
if (vector_i[1] == 1) begin
address <= 1;
end
...
if (vector_i[C_INPUT_LENGTH-1] == 1) begin
address <= C_INPUT_LENGTH-1;
end
end
end // always# (posedge clk)
I did so like this:
integer forcount;
always#(posedge clk) begin
if(rst) begin
address <= 0;
end
else begin
for (forcount = 0;forcount <= C_INPUT_LENGTH-1 ;forcount = forcount + 1) begin
if (vector_i[forcount] == 1) begin <--
address <= forcount;
end
end
end
end // always# (posedge clk)
Xilinx vivado (2014.1) gives the following error, referring to the line indicated above:
[Synth 8-903] failed to generate logic
I've done this before using a similar method in the past and it has worked, what am I doing wrong? How do I generate these if statements?
According to Xilinx, this is a known bug documented under CR 801365. The use of an integer as a loop counter causes this issue in some cases. It's due to be fixed in vivado 2014.3.
The solution is to replace the integer with a signal type reg of appropriate size.
Is your input vector_i one-hot? The code you wrote doesn't guarantee that address will only be written to one value. Try this:
for (forcount = 0;forcount <= C_INPUT_LENGTH-1 ;forcount = forcount + 1) begin
if (vector_i[forcount] == 1) begin
address <= forcount;
break;
end
end
Adding the break statement will break out of the for loop the first time the condition is true. Note that this will generate some carry-chain logic and you might get better results with a case statement.
As a temporary work-around, you could consider using a generate statement.
For example:
genvar i;
always #(posedge clk) begin
if (rst) begin
address <= 0;
end else begin
generate
for (i = 0; i < C_INPUT_LENGTH; i = i + 1) begin: foreach_input
if (vector_i[i]) address <= i;
end
endgenerate
end // if (rst)
end // always #(posedge clk)
edit: oh, never mind -- I missed the bit above where Xilinx's recommended workaround is to simply use a dimensioned variable rather than "integer" for the iterator. That would be easier!

SystemVerilog: Parameter used in concatenation gives error with irun

Cadence irun gives error for below code, where fifo_depth_base2 is parameter as below:
ncvlog: *E,NONOWD (buff_mgr.v,17|46): Illegal use of a constant without an explicit width specification [4.1.14(IEEE)].
I can understand this error, but my question is how would I otherwise assign it for parameterized design.
// rd pointer and read logic
always #(posedge clk or posedge rst) begin
if(rst) rd_ptr <= 0;
else begin
case({flush, rd})
2'b10, 2'b11: rd_ptr <= {fifo_depth_base2{'b0}}; // error here
...
endcase
end
end
You are missing a 1 before 'b0. The simulator doesn't know the bit size of 'b0 because it is not specified.
{fifo_depth_base2{'b0}}; should be {fifo_depth_base2{ 1'b0}};
With SystemVerilog you can use: rd_ptr <= '0;, where '0 means fill zeros

cannot use an input for if statement in Verilog

I am trying to pass an integer value to a module, but the IF statement does not work with the parameter. It throws the following error. I am new to Verilog so I have no idea how to make this work.
Error (10200): Verilog HDL Conditional Statement error at clock_divider.v(17):
cannot match operand(s) in the condition to the corresponding edges in the enclosing
event control of the always construct
clock_divider.v module
module clock_divider (clockHandler, clk, rst_n, clk_o);
parameter DIV_CONST = 10000000 ; // 1 second
parameter DIV_CONST_faster = 10000000 / 5;
input clockHandler;
input clk;
input rst_n;
output reg clk_o;
reg [31:0] div;
reg en;
integer div_helper = 0;
always # (posedge clk or negedge rst_n)
begin
if(clockHandler == 0)
begin div_helper = DIV_CONST;
end
else
begin div_helper = DIV_CONST_faster;
end
if (!rst_n)
begin div <= 0;
en <= 0;
end
else
begin
if (div == div_helper)
begin div <= 0;
en <= 1;
end
else
begin div <= div + 1;
en <= 0;
end
end
end
always # (posedge clk or negedge rst_n)
begin
if (!rst_n)
begin
clk_o <= 1'b0;
end
else if (en)
clk_o <= ~clk_o;
end
endmodule
main.v module
reg clockHandler = 1;
// 7-seg display mux
always # (*)
begin
case (SW[2:0])
3'b000: hexdata <= 16'h0188;
3'b001: hexdata <= register_A ;
3'b010: hexdata <= program_counter ;
3'b011: hexdata <= instruction_register ;
3'b100: hexdata <= memory_data_register_out ;
3'b111: hexdata <= out;
default: hexdata <= 16'h0188;
endcase
if(SW[8] == 1)
begin
clockHandler = 1;
end
else
begin
clockHandler = 0;
end
end
HexDigit d0(HEX0,hexdata[3:0]);
HexDigit d1(HEX1,hexdata[7:4]);
HexDigit d2(HEX2,hexdata[11:8]);
HexDigit d3(HEX3,hexdata[15:12]);
clock_divider clk1Hzfrom50MHz (
clockHandler,
CLOCK_50,
KEY[3],
clk_1Hz
);
It's my understanding that the first statement in a verilog always block must be the if(reset) term if you're using an asynchronous reset.
So the flop construct should always look like this:
always # (posedge clk or negedge rst_n) begin
if(~rst_n) begin
...reset statements...
end else begin
...all other statements...
end
end
So for your case you should move the if(clockHandler==0) block inside the else statement, because it is not relevant to the reset execution. Even better would be to move it into a separate combinational always block, since mixing blocking and nonblocking statements inside an always block is generally not a good idea unless you really know what you're doing. I think it is fine in your case though.
To add to Tim's answer - the original code (around line 17, anyway) is valid Verilog.
What it's saying is "whenever there's a rising edge on clk or a falling edge on rst_n, check clockHandler and do something" (by the way, get rid of the begin/ends; they're redundant and verbose). The problem comes when you want to implement this in real hardware, so the error message is presumably from a synthesiser, which needs more than valid Verilog. The synth suspects that it has to build a synchronous element of some sort, but it can't (or won't, to be precise) handle the case where clockHandler is examined on an edge of both clk and rst_n. Follow the rules for synthesis templates, and you won't get this problem.
is this a compilation error or synthesis error? i used the same code to see if it compiles fine, and i din get errors.. Also, it is recommended to use "<=" inside synchronous blocks rather than "="
You're using the same flop construct for two different things. Linearly in code this causes a slipping of states. I always place everything within one construct if the states rely on that clock or that reset, otherwise you require extra steps to make sure more than one signal isn't trying to change your state.
You also don't need the begin/end when it comes to the flop construct, Verilog knows how to handle that for you. I believe Verilog is okay with it though, but I generally don't do that. You also don't have to use it when using a single statement within a block.
So your first module would look like this (if I missed a block somewhere just let me know):
clock_divider.v module (edited)
module clock_divider (clockHandler, clk, rst_n, clk_o);
parameter DIV_CONST = 10000000 ; // 1 second
parameter DIV_CONST_faster = 10000000 / 5;
input clockHandler;
input clk;
input rst_n;
output reg clk_o;
reg [31:0] div;
reg en;
integer div_helper = 0;
always # (posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
div <= 0;
en <= 0;
clk_o <= 1'b0;
end
else if(en)
begin
clk_o <= ~ clk_o;
if(clockHandler == 0)
begin
div_helper = DIV_CONST;
end
else
begin
div_helper = DIV_CONST_faster;
end
else
begin
if (div == div_helper)
begin
div <= 0;
en <= 1;
end
end
else
begin
div <= div + 1;
en <= 0;
end
end
end
end module
If that clk_o isn't meant to be handled at the same time those other operations take place, then you can separate everything else with a general 'else' statement. Just be sure to nest that second construct as an if-statement to check your state.
And also remember to add always # (posedge clk or negedge rst_n) to your main.v module as Tim mentioned.

Verilog generate/genvar in an always block

I'm trying to get a module to pass the syntax check in ISE 12.4, and it gives me an error I don't understand. First a code snippet:
parameter ROWBITS = 4;
reg [ROWBITS-1:0] temp;
genvar c;
generate
always #(posedge sysclk) begin
for (c = 0; c < ROWBITS; c = c + 1) begin: test
temp[c] <= 1'b0;
end
end
endgenerate
When I try a syntax check, I get the following error message:
ERROR:HDLCompiler:731 - "test.v" Line 46: Procedural assignment to a
non-register <c> is not permitted.
I really don't understand why it's complaining. "c" isn't a wire, it's a genvar. This should be the equivalent of the completely legal syntax:
reg [3:0] temp;
always #(posedge sysclk) begin
temp[0] <= 1'b0;
temp[1] <= 1'b0;
temp[2] <= 1'b0;
temp[3] <= 1'b0;
end
Please, no comments about how it'd be easier to write this without the generate. This is a reduced example of a much more complex piece of code involving multiple ifs and non-blocking assignments to "temp". Also, don't just tell me there are newer versions of ISE, I already know that. OTOH, if you know it's fixed in a later version of ISE, please let me know which version you know works.
You need to reverse the nesting inside the generate block:
genvar c;
generate
for (c = 0; c < ROWBITS; c = c + 1) begin: test
always #(posedge sysclk) begin
temp[c] <= 1'b0;
end
end
endgenerate
Technically, this generates four always blocks:
always #(posedge sysclk) temp[0] <= 1'b0;
always #(posedge sysclk) temp[1] <= 1'b0;
always #(posedge sysclk) temp[2] <= 1'b0;
always #(posedge sysclk) temp[3] <= 1'b0;
In this simple example, there's no difference in behavior between the four always blocks and a single always block containing four assignments, but in other cases there could be.
The genvar-dependent operation needs to be resolved when constructing the in-memory representation of the design (in the case of a simulator) or when mapping to logic gates (in the case of a synthesis tool). The always #posedge doesn't have meaning until the design is operating.
Subject to certain restrictions, you can put a for loop inside the always block, even for synthesizable code. For synthesis, the loop will be unrolled. However, in that case, the for loop needs to work with a reg, integer, or similar. It can't use a genvar, because having the for loop inside the always block describes an operation that occurs at each edge of the clock, not an operation that can be expanded statically during elaboration of the design.
You don't need a generate bock if you want all the bits of temp assigned in the same always block.
parameter ROWBITS = 4;
reg [ROWBITS-1:0] temp;
always #(posedge sysclk) begin
for (integer c=0; c<ROWBITS; c=c+1) begin: test
temp[c] <= 1'b0;
end
end
Alternatively, if your simulator supports IEEE 1800 (SytemVerilog), then
parameter ROWBITS = 4;
reg [ROWBITS-1:0] temp;
always #(posedge sysclk) begin
temp <= '0; // fill with 0
end
end
If you do not mind having to compile/generate the file then you could use a pre processing technique. This gives you the power of the generate but results in a clean Verilog file which is often easier to debug and leads to less simulator issues.
I use RubyIt to generate verilog files from templates using ERB (Embedded Ruby).
parameter ROWBITS = <%= ROWBITS %> ;
always #(posedge sysclk) begin
<% (0...ROWBITS).each do |addr| -%>
temp[<%= addr %>] <= 1'b0;
<% end -%>
end
Generating the module_name.v file with :
$ ruby_it --parameter ROWBITS=4 --outpath ./ --file ./module_name.rv
The generated module_name.v
parameter ROWBITS = 4 ;
always #(posedge sysclk) begin
temp[0] <= 1'b0;
temp[1] <= 1'b0;
temp[2] <= 1'b0;
temp[3] <= 1'b0;
end
Within a module, Verilog contains essentially two constructs: items and statements. Statements are always found in procedural contexts, which include anything in between begin..end, functions, tasks, always blocks and initial blocks. Items, such as generate constructs, are listed directly in the module. For loops and most variable/constant declarations can exist in both contexts.
In your code, it appears that you want the for loop to be evaluated as a generate item but the loop is actually part of the procedural context of the always block. For a for loop to be treated as a generate loop it must be in the module context. The generate..endgenerate keywords are entirely optional(some tools require them) and have no effect. See this answer for an example of how generate loops are evaluated.
//Compiler sees this
parameter ROWBITS = 4;
reg [ROWBITS-1:0] temp;
genvar c;
always #(posedge sysclk) //Procedural context starts here
begin
for (c = 0; c < ROWBITS; c = c + 1) begin: test
temp[c] <= 1'b0; //Still a genvar
end
end
for verilog just do
parameter ROWBITS = 4;
reg [ROWBITS-1:0] temp;
always #(posedge sysclk) begin
temp <= {ROWBITS{1'b0}}; // fill with 0
end
To put it simply, you don't use generate inside an always process, you use generate to create a parametrized process or instantiate particular modules, where you can combine if-else or case. So you can move this generate and crea a particular process or an instantiation e.g.,
module #(
parameter XLEN = 64,
parameter USEIP = 0
)
(
input clk,
input rstn,
input [XLEN-1:0] opA,
input [XLEN-1:0] opB,
input [XLEN-1:0] opR,
input en
);
generate
case(USEIP)
0:begin
always #(posedge clk or negedge rstn)
begin
if(!rstn)
begin
opR <= '{default:0};
end
else
begin
if(en)
opR <= opA+opB;
else
opR <= '{default:0};
end
end
end
1:begin
superAdder #(.XLEN(XLEN)) _adder(.clk(clk),.rstm(rstn), .opA(opA), .opB(opB), .opR(opR), .en(en));
end
endcase
endmodule

Resources