Compilation errors due to operands in if statement - verilog

This is a system verilog file .The below code when run gives an error "Illegal operand for constant expression" at "if(m_val !==0) and if(div_val)"
Have tried without generating statements but still the same error. Any help on what is wrong with the code?
logic m_ref_clk,mul_ref_clk,div_ref_clk,mixed_ref_clk;
real clk_period = ((1.0/(freq*BASE_GHz_CLK_FREQ))*1s);
generate
if(m_val !== 0) begin
if(div_val == 0)begin
initial begin
clk_period = clk_period*m_val;
forever begin
#(clk_period) mul_ref_clk = ~mul_ref_clk;
end
end
end
end
endgenerate
assign multiply_clk = mul_ref_clk;

Generate statements are evaluated during elaboration which occurs before t = 0 in a simulation. Therefore normal variables (updated dynamically as the RTL runs) can't be used a arguments to generate statements.
Elaboration from 1800 2012 section 3:
Elaboration occurs after parsing the source code and before simulation;
and it involves expanding instantiations, computing parameter values, resolving hierarchical names,
establishing net connectivity and in general preparing the design for simulation.
Generate statements from IEEE 1800 2012 section 27:
Generate schemes are evaluated during elaboration of the design. Although generate schemes use syntax that
is similar to behavioral statements, it is important to recognize that they do not execute at simulation time.
They are evaluated at elaboration time, and the result is determined before simulation begins. Therefore, all
expressions in generate schemes shall be constant expressions, deterministic at elaboration time. For more
details on elaboration, see 3.12

Related

syntax error, unexpected '=', expecting IDENTIFIER

I'm creating a sudoku game in verilog(2001) to eventually be put onto an FPGA, I found code for it in java and have been trying to convert it but have run into some errors.
Here's the link for the java code
www.geeksforgeeks.org/program-sudoku-generator
I have very little verilog experience and am learning as I go.
task automatic removeKDigits()
reg count = K;
while (count != 0)
begin
integer cellId = randomGenerator(N*N-1);
// System.out.println(cellId);
// extract coordinates i and j
i = (cellId/N);
j = cellId%9;
// System.out.println(i+" "+j);
if (mat[i][j] != 0)
begin
count = count-1;
mat[i][j] = 0;
end
else
count=count;
end
endtask
K is the amount of digits to be removed from the mat[i][j] board, N=9 since its a 9x9 sudoku board. For the lines containing "count=count-1" and "count=count" I'm getting the error
syntax error, unexpected '=', expecting IDENTIFIER
what does it mean? how do I fix it?
Unfortunately, it's unlikely you'll be able to port java code to synthesizable Verilog code, without at least a decent knowledge of the principles behind RTLs (Register transfer languages).
Programming languages like Java are a high level descriptions of some logic, that will get converted into machine instructions, and run on a processor. They operate sequentially, one line at a time, in a particular order.
RTLs on the other hand, describe actual hardware. They tend to operate in parallel, on a trigger, typically a clock. Instead of 'variables', you tend to work with 'registers' representing actual flip flops, and the Verilog programme will describe the transfer of data between these registers.
As for the actual issues with your code, it's impossible to point out the errors, because it simply isn't Verilog.
I recommend this answer: https://stackoverflow.com/a/5121853/10719567, for a more eloquent description of the differences between programming languages and RTLs, and why it's not that easy to port between the two.

Can I use generate-endgenerate block inside initial in SystemVerilog?

For e.g.
initial
begin
generate
for(genvar i; i < 4; i++)
//Code
endgenerate
end //initial
I'm getting error using QuestaSim with the concept. "Near generate: syntax error, unexpected generate "
No. generate blocks are evaluated during elaboration time. While initial,always and other procedural blocks start at zero simulation time, that is, run-time. Referring to Systemverilog IEEE 1800-2012 :
Generate schemes are evaluated during elaboration of the design.
Although generate schemes use syntax that is similar to behavioral
statements, it is important to recognize that they do not execute at
simulation time.
They are evaluated at elaboration time, and the
result is determined before simulation begins. Therefore, all
expressions in generate schemes shall be constant expressions,
deterministic at elaboration time.
In Verilog, instantiating a module means adding extra hardware to the board.
This hardware must be added before simulation starts(i.e. at compile time). You can not add/remove hardware during run time. You can either conditionally instantiate a module or multiply instantiate it, but never at run time.
Refer generate block syntax error question for an idea about your error. Also, refer this question for generate and genvar understanding. Referring IEEE 1800-2012 Chapter 27 for more information.
EDIT:
To create and pass multiple interface instances, the total number of interface instances must be governed by some parameter or macro. You can use this parameter in for loop in generate block to create distinct instances and set each of them using different key as follows:
// Generate multiple instances of interface
genvar i;
generate
for(i=0;i<NUM_OF_INTERFACES;i++)
begin
// Generate clk with different period for each instance
always #(i+1) clk[i] = ~clk[i];
inter in(clk[i]); // Create multiple instances here
initial
begin
// Set each and every instance
uvm_config_db#(virtual inter)::set(null,"*",$sformatf("in_%0d",i),in);
end
end
endgenerate
A complete example is created at EDAPlayground Multiple Interface link. Creating multiple instances can be referred from this question.

Icarus Verilog simulation : Scope index expression is not constant: i

I am simulating a 16 bit MIPS netlist in Icarus Verilog.
This is the error i get in testbench
mips_16_core_top_tb_0.v:144: error: Scope index expression is not constant: i
mips_16_core_top_tb_0.v:144: error: Unable to bind wire/reg/memory `uut.register_file_inst.reg_array[i]' in `mips_16_core_top_tb_0_v.display_all_regs'
Related code :
task display_all_regs;
begin
$display("display_all_regs:");
$display("------------------------------");
$display("R0\tR1\tR2\tR3\tR4\tR5\tR6\tR7");
for(i=0; i<8; i=i+1)
$write("%d\t",uut.register_file_inst.reg_array[i]); <--- error points to this line
$display("\n------------------------------");
end
endtask
I do get this same error when i simulate the RTL too but i still get the vcd file dumped out.In case of the netlist,I dont even get the vcd file generated.
Would be glad to hear your thoughts.
Your code looks fine, and I've just tested cross-module variable indexing of arrays in Icarus (the current version, from git) and it works.
I suspect your problem is that you're compiling mips_16_core_top_tb_0.v by itself - Icarus will give this message if you do. All source files need to be compiled together in Icarus. Some other simulators will allow you to compile this file by itself, and then only check for errors during elaboration (ie. when you run the simulation), but the way Icarus does it is how Verilog was originally intended to be used.
Your index in register[index] must be constant in this situation. In reg_array[i], i is a variable and not fixed. To simulate using this code you must remodel the design so that it doesn't require a variable indexed register. It may be a simulator-specific lack of support for this feature. If that is the case, you should try a different simulator.

Verilog always block

I just want to use some if else statement in verilog.
So I have to use always block.
integer count,index;
reg a=0;
always#(a) begin
a=1;
for(count=0;count<7;count=count+1) begin
index=4*count;
if((significand[index]==1'b0)&&(significand[index+1]==1'b0)&&
(significand[ind‌​ex+2]==1'b0) &&(significand[index+3]==1'b0))
lzero=lzero+1;
end
end
This code does make some sense now. I was able to get the correct simulation result, but I failed to get the correct synthesis on the board. Please help
This is a very typical problem with people who know how to program in C or C++ but forget that Verilog and VHDL are not the same as those.
EVERY signal line of Verilog code inside the ALWAYS block are 'executed' at the same time. The same goes with the combinatorial logic outside of the ALWAYS block.
In your code, both the
assign a=1'b1;
assign a=1'b0;
Will happen at the same time, no matter what.
The only way to change that is to put the last line inside your always block,after the end statement of the for loop.
One page that will give you some help on understanding the difference between C and Verilog is the page:EE-Times: The C Programmers Guide to Verilog
Neither assign 1'b1; nor assign 1'b0; are valid assignments. If you want to constantly drive some net with 1'b1, then you have to write something like assign myvar = 1'b1;.
Also, if your intent was to actually assign to a, then always block doesn't make sense since a is the only thing in its sensitivity list meaning that that block must be executed whenever a changes its value. Since a will essentially never change its value, that block should never be executed.
It is hard to help you out unless you provide a minimal working example demonstrating your problem. The only thing that I can recommend is to use ternary operator in assign right hand side statement. That way you can model a behavioural logic without using always block. For example:
assign a = (b == 1'b1 ? c : 1'b0);
Hope it helps.
UPDATE:
Your second code example is neither complete nor legal as well. You cannot have two combinatorial assignments for the same net.
However, a sensitivity list in always block is now a star, which is Verilog 2001 notation to include all right hand side operands into a sensitivity list automatically. In your case, the block will get executed every time significand or lzero changes.

What is the point of a "plain" begin-end block?

I'm reading some third party Verilog, and found this:
function [31:0] factorial;
input [3:0] operand;
reg [3:0] index;
begin
factorial = operand ? 1 : 0;
for(index = 2; index <= operand; index = index + 1)
factorial = index * factorial;
end
endfunction
It seems that the begin and end keywords are redundant here. Are they? What is their use?
I don't know about the general case, but in this specific case:
If a function contains more than one statement, the statements must be
enclosed in a begin-end or fork-join block.
Source: Verilog Golden Reference Guide
Both answers are correct. If the Verilog task or function had multiple statements, they were also required to have begin-end statements. Starting in SystemVerilog-2005, we removed the requirement to put begin-end inside of something that already had a begin-end. Most of us on the committee thought it was silly to require a begin-end inside of something that was already going to have endfunction/endtask. I mean, come-on! Don't you think a compiler could figure out that when it got the endtask/endfunction statement that it was at the end of the task or function?? Removing the begin-end from tasks and functions cuts out a surprising amount of useless code. Score another point for SystemVerilog!
According to the SystemVerilog extension (IEEE Standard 1800-2009), begin/end are optional inside a function. However, your toolset (simulator, etc.) must be capable of understanding this syntax, which was introduced in 2005.

Resources