Using parameter for continuous assignment in verilog? - verilog

Can you use a parameter value for assignment in verilog? Can I somehow define the width of a parameter variable?
Ex:
module mymodule #(parameter type =2)
(...
output [(3+type)-1:0] out);
wire [2:0] rate;
...
assign out = {rate, {1'b0{type}} };
endmodule
Lets just say type=2. Then I would want out to be of bit-length 5. rate is still of bit-length 3 (lets just say it is 3'b100), when I assign out I want it to be 100 000.
Similarly if type=6. Then I would want out to be of bit-length 9. rate is still of bit-length 3 (again lets say its 3'b100), when I assign out I want it to be 100 000000.
I don't get any syntax errors but when I try to simulate it I get:
"error: Concatenation operand "type" has indefinite width"
How would you guys approach a design problem like this one?

You have the repetition operator backward. Should be
{type{1'b0}}, not {1'b0{type}}
I'm surprised you don't see any syntax error from that.

Related

Verilog assign statement result check

new to Verilog (well, SystemVerilog really, but I found that for the very basic keywords like assign and initialize I am able to learn from Verilog resources as well). I am following example 2 on this link chipverify example 2. It's simple so I'll write it down. I feel as if they've made a mistake, but since I am a newbie it's hard to know if my feeling is correct or not.
module xyz (input [3:0] x, //let x='hC or x='b1100 for this example's purposes
input y, //y is a 1bit scalar y='h1 = 'b1
output [4:0] z);
//case 8
assign z = {3{y}};
endmodule
For case 8, they are saying that z will result in z='b00111. I don't think it's correct! Following their case 3, where z only got bits [4:1] assigned,it stated that the reaming bit will be undriven and thus result in high impedance Z. Shouldn't the result of case 8 then be z ='bZZ111 and not z='b00111?
Let me know, thanks! =)
From section 10.7 (Assignment extension and truncation) in IEEE Std 1800-2017 (the SystemVerilog standard),
When the right-hand side evaluates to fewer bits than the left-hand side, the right-hand side value is padded to the size of the
left-hand side.
In your case, {3{y}} is an unsigned value, so it is 0-padded to 5 bits, that is 5'b00111, and then assigned to z.

Delay associated with xor of 1023 10 bit vectors in Verilog

I am somewhat new to verilog and I have a question that is confusing me .
I have a number of constant parameters , specifically nearly 1023 of them c0 , c1,c2 ..... c1022, each one being 10 bit in length . I also have a vector r[1022:0] , which is 1023 bits in length . My task is to compute ci*r[i] where i varies from 0 to 1022 and finally take the xor of the 1023 10 bit vectors that i get.When I do this in simulation , verilog generates the output at time 0 for the assign statement . How can verilog generate the output at time 0 ? Will there be no delay associated with these 1023 xors?
Also, if I need to do this succinctly , is there a short form that I can use or do I need to manually write c0 *r[0] ^ c1 *r[1] ......^ c[1022]*r[1022] which is synthesizable ?
A Verilog simulator will execute whatever legal syntax you give it—the tool knows nothing about what the implementation eventually looks like. It's up to you to feed timing constraints to the synthesis tool and it tells you if it can fit the logic to meet the constraints (or you might have to run another tool to see if it meets timing constraints).
Since you named your parameters c0, c1, c2, ..., you might as well named them czero, cone, ctwo, ... which gives you no options for shortcuts.
If you tool supports SystemVerilog, you can write your parameter as an array and then use the array xor reduction operator
parameter [9:0] C[1023] = {10'h123, 10'h234, ...};
assign out = C.xor() with (item*r[item.index]);
If you synthesis tool does not support this SystemVerilog syntax you, you can pack the parameter values into a single vector and use an indexed part select in Verilog.
parameter [10220-1:0] C = {10'h123, 10'h234, ...};
function [9:0] xor_reduction (input [1022:0] r);
integer I;
begin
xor_reduction = 0;
for(I=0;I<1023;I=I+1)
xor_reduction = xor_refuction ^ (r[1022-I]*C[I-:10]);
end
endfunction
assign out = xor_reduction(r);

What values will be assigned to variables.[Need to Understand the program Logic]

I am a beginner in Verilog.I need to understand the logic of a testcase but I am having difficulty because of the logic of these variables.
Are these 'define F and G of integer types.I read that parameter are constants.
'define F 32
'define G 0
module M(...);
parameter pMaxPacketsSize =1024;
localparam pTotalBits=3*'G;
localparam pForcePktSize=(pMaxPacketsSize-'F);
localparam pLastPacketSize =((pTotalBits-1)%(pForcePktSize))+1;
localparam pNumTransactions=((pTotalBits-1)/(pForcePktSize))+1;
localparam pPortSize=(pNumTransactions>1)?pMaxPacketsSize:((((pTotalBits-1)/32)+1)*32)+'F;
As G is defined to be 0,
what will be the value of ForcePacketsize.I attempted binary subtraction and arrived at 128(7 bits)[Is this Correct?].[0-32].Are all these operations needs to be performed in binary arithmetic.I want to know the value of these parameters(pForcePktSize,pLastPacketSize,PNumTransactions).
One more statement I want to understand is this:
wire[pPortSize-1:0]D;
wire[pNumTransactions-1:0] t;
assign t=1'b1<<D[14:0];
I know it is of type :[size][radix][value] means 1 in binary then left shifting,but how this is being assigned to array(will t be 100000000000000 14 zeroes and then 1)
I tried to run online on some IDE's but get error that I give up.
`define in verilog is the same thing as #define in c. It defines a text macro. `G and `F instantiate macros and get replaced by their context in the program before parsing.
So, in your case
localparam pTotalBits=3*'G;
localparam pForcePktSize=(pMaxPacketsSize-'F);
will be replaced with
localparam pTotalBits=3*0;
localparam pForcePktSize=(pMaxPacketsSize-32);
The replacement is textual and instantiations of the macros just got replaced with their definitions. There is no type associated with macro definition.

Using real parameter to determine counter sizes

I am trying to make my debounce code more modular by passing in parameters that are the frequency and the desired bounce time to eliminate button/switch bounce. This is how I approached it:
module debounceCounter
#(
parameter CLOCK_FREQUENCY_Hz = 50_000_000,
parameter BOUNCE_TIME_s = 0.003
)
(
input wire sysClk, reset,
input wire i_async,
output reg o_sync
);
/* include tasks/functions */
`include "clog2.v"
/* constants */
parameter [(clog2(BOUNCE_TIME_s * CLOCK_FREQUENCY_Hz + 0.5) - 1) : 0]
MAX_COUNT = BOUNCE_TIME_s * CLOCK_FREQUENCY_Hz;
Synthesis using Xilinx ISE 14.7 Throws this error:
Xst:850 - "../../rtl/verilog/debounceCounter.v" line0: Unsupported real
constant
How can I get around this issue so that I can determine the counter size and max count value based on parameters being passed in from code above this module in the heirarchy? A majority of my code has sizes of variables and such determined by frequency generics, so not being able to use methods like VHDL has proven to create problems in my designs.
Seems to work fine on Vivado 2016.3 (the oldest I have available). I think the problem is that 2014.7 is too old to support this. You didn't show the contents of the `include, but I'm assuming its the one from AR# 44586. If so, it should take and return integers and it will truncate the real floating point values for you. Floating point arithmetic is fine to use in Verilog/SystemVerilog testbenches and parameters.
How can I get around this issue so that I can determine the counter
size and max count value based on parameters being passed in from code
above this module in the heirarchy?
Update to a recent version. 2017.1 or 2017.3 are working good for me. I tested the following on 2016.3 and it also worked fine.
Try using SystemVerilog (.sv) which supports the $clog2() system function natively without the `include. Not sure when .sv started working, but probably needs 2015+.
Verify that your version of clog2 in the clog2.v header matches the following
NOTE: There is another pretty serious bug in the code you posted.
When you want to get the MSB required to hold a constant expression "x" the pattern should be $clog2((x)+1)-1. You have only added 0.5 instead of 1. This causes there to not be enough bits whenever the result of the floating point expression "x" falls between 2^n and (2^n + 0.5). For example, what you have erronously computes the constant as 17'h0 instead of 18'h4_0000 for the the frequency 87381333 but it still appears to work for your example at 50Mhz. Murphy's law says you will accidentally fall into this narrow bad range at the worst possible time, but never during testing :).
For reference, this is what I tested, with the `include expanded inline:
`timescale 1ns / 1ps
module debounceCounter
#(
//parameter CLOCK_FREQUENCY_Hz = 50_000_000,
parameter CLOCK_FREQUENCY_Hz = 87381333, // whoops
parameter BOUNCE_TIME_s = 0.003
)
(
input wire sysClk, reset,
input wire i_async,
output reg o_sync
);
/* include tasks/functions */
//`include "clog2.v"
function integer clog2;
input integer value;
begin
value = value-1;
for (clog2=0; value>0; clog2=clog2+1)
value = value>>1;
end
endfunction
/* constants */
//parameter [(clog2(BOUNCE_TIME_s * CLOCK_FREQUENCY_Hz + 0.5) - 1) : 0] // <- BUG!!! 0.5 should 1
parameter [(clog2(BOUNCE_TIME_s * CLOCK_FREQUENCY_Hz + 1) - 1) : 0]
MAX_COUNT = BOUNCE_TIME_s * CLOCK_FREQUENCY_Hz;
initial
$display("MAX_COUNT %d", MAX_COUNT);
endmodule
Type Real is not synthesizable. Draw/Create your design before you translate into/write HDL and you will realize this. Ask yourself, "What does a real synthesize to in gates?"
For those tools (e.g. Synplify) that do "support" Type Real, it is just a vendor interpretation, and as such is impossible to "support" since it is not defined as part of any HDL standard. The implication: If you had a simulator that interprets Type Real one way, and your synthesizer (likely) interprets it another way, you will get sim/syn mismatches. You may get away with them, depending on what you are trying to accomplish, but, it would still be considered poor design practice.
Behavioral code, for modeling and use in testbenches, as stated above, a different story as it is not synthesized.

How does the synthesizer decides on bitwdith for intermediate results?

Consider the following module:
module power(input [11-1:0] xi,xq,output [22-1:0] y);
assign y = xi*xi + xq*xq;
endmodule
I know that my single assignment is actually decomposed of 3 steps: 2 squares and one addition. My question is how would the synthesizer decides on the bitwidth of the intermediate steps xi*xi and xq*xq?
I noticed that when running logic equivelance circuit (lec) for the above code, it causes trouble and could only be solved by decomposing the single assignment into three assignments as follows:
module power(input [11-1:0] xi,xq,output [22-1:0] yy);
wire [21-1:0] pi,pq;
assign pi = xi*xi;
assign pq = xq*xq;
assign yy = pi+pq;
endmodule
Here's how your simulator decides on bitwdith for intermediate results.
Verilog Simulation
This expression - assign y = xi*xi + xq*xq; - is an example of a context determined expression. A Verilog simulator takes the widest of all the nets or variables in the expression and uses that. So, in your code, the widest is y at 22 bits wide, so Verilog will use 22 bits throughout.
VHDL Simulation
The behaviour of a VHDL simulator depends on the package used. If you use the numeric_std package, as is recommended, then you would need to obey the following rules:
The width of the sum should be the same as the wider of the two operands.
The width of the product should be the sum of the widths of the operands.
Therefore, your code would compile if translated directly into VHDL:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity power is
port (xi, xq : in signed(11-1 downto 0);
y : out signed(22-1 downto 0));
end entity power;
architecture A of power is
begin
y <= xi*xi + xq*xq;
end architecture A;
Shouldn't everything be signed?
Given the names of your module (power) and inputs (xi and xq) and having spent 25 years designing radio systems, shouldn't they be signed? Shouldn't your Verilog be:
module power(input signed [11-1:0] xi,xq,output signed [22-1:0] y);
assign y = xi*xi + xq*xq;
endmodule
That is why I chose the signed type from numeric_std, not the unsigned type.
Synthesis
Well, I've waffled on about simulators, but you asked about synthesis. And, to be frank, I don't know what a synthesiser would do. But, given the job of a synthesiser is to design a logic circuit that behaves exactly like the simulation, you would think that any self-respecting synthesiser would use the same bit-widths as the simulator. So, I'm pretty sure that's your answer.

Resources