Output port missing in generated Verilog code from MyHDL - verilog

I am trying to generate a verilog module from the following MyHDL module:
top.py:
from myhdl import *
from counter import Counter
def Top(clkIn, leds):
counter = Counter(clkIn, leds)
return counter
clkIn = Signal(bool(0))
leds = intbv(0)[8:0]
toVerilog(Top, clkIn, leds)
and,
counter.py:
from myhdl import *
def Counter(clk, count):
c = Signal(modbv(0)[8:0])
#always(clk.posedge)
def logic():
c.next = c + 1
#always_comb
def outputs():
count.next = c
return logic, outputs
However, in the generated file's module definition, (lines 1-3)
top.v:
module top (
clkIn
);
input clkIn;
reg [7:0] counter_c;
always #(posedge clkIn) begin: TOP_COUNTER_LOGIC
counter_c <= (counter_c + 1);
end
assign count = counter_c;
endmodule
leds[7:0] are missing. Even though these LEDs are unused I need them for my synthesizer to assign them to the proper pins on the development board. Why is MyHDL omitting them? and how can I make it include them?

Change leds = intbv(0)[8:0] into leds = Signal(intbv(0)[8:0]).
Module (output) ports need to be declared as Signal.

In your module top design, you didn't declare leds as an output. On clkIn is defined and it is an input. Most synthesizers will check that logic is driving outputs or some other visible, or kept logic. If the synthesizer determines that there is no possible way for you tell that leds is present in the design externally, it may just optimize it away as well as any dedicated logic driving it, away.
If this is Altera, there is a qsf assignment called virtual pins which could be assigned to leds, to keep it. But the easy thing to do is add leds to the module top pin definition and assign it as an out.
Per the comment from Alper, you don't assign Count to anything. That needs to be fixed.
Also, you don't initialize counter in the Counter definition. This might work in synthesis because the logic will either init to zeros, or some other definitive value, but in simulation, the value may (probably/will) remain unknown. Get a reset signal if you can.

Related

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.

Counting of different channels diverge and jumps

I'm trying to realize a counting module. My basic setup:
FPGA (Digilent's Arty with Xilinx Artix-35T) with two BNC cables attached to IO ports connected to a signal generator and via USB/UART to the PC for reading out. My signal generator produces with, say, 1 Hz some TTL signal.
I now want to count the amount of events in channel 1, in channel 2 and the coincidences of channels 1 and 2. While the basic principle works, I see channels 1 and 2 separate, even though they have the same input (via BNC-T connector). Also, sometimes one of the output channels jumps - in either direction, see figure.
The violet channel ("Channel 1") has a different slope than green ("Channel 2"). Also the coincidences make here two little lossy jumps.
My sequential counting code looks like
reg [15:0] coinciInt [(numCoincidences -1):0]; // internally store events
always #(posedge clk or posedge reset) // every time the clock rises...
begin
signalDelay <= signal; // delayed signal for not counting the same event twice
if(reset) // reset
begin
for(i=0;i<numCoincidences;i=i+1)
coinciInt[i] <= 16'b0;
end
else // No reset
begin
for(i=1;i<numCoincidences;i=i+1) // loop through all coincidence possibilities:
begin
if( ((signal & i) == i) && ((signalDelay & i) != i) ) // only if signal give coincidence, but did not give before, it's a coincidence
begin // "(signal & i) == i" means that "signal" is checked if bitmask of "i" is contained:
// ((0011 & 0010) == 0010) is true, since 0011 & 0010 = 0010 == 0010
coinciInt[i] <= coinciInt[i] + 1'b1; // the i-th coincidence triggered, store it
end
end
end
end // end of always
assign coinci = coinciInt; // the output variable is called coinci, so assign to this one
Please note that all events are in the register coinci - coincidences as well as 'single events'. Ideally, coinci[1] should store events of channel 1, coinci[2] these of channel 2 and coinci[3] coincidences between 1 and 2, since channels are labelled by 1,2,4,8,...,2^n and coincidences by the respective sum. coinci[0] is used for some kind of checksum, but that's off-topic now.
Are there any ideas for the missing counts? For the different slopes?
Thank you very much
Edit 1
#Brian Magnuson pointed to the meta stability issue. Using multi-buffered inputs solved the issue of diverging channels. That works nicely. Although I don't fully understand the reason for this, I also did not see any jumps in the coincidence channel so far. You probably save me a lot of time, thanks!
I would suspect a meta-stability problem. Your incoming pulses on ch1/ch2 are probably not synchronized with the system clock you are using. See here.
Because of this you are probably sometimes catching the counter updates 'mid-stride' so to speak which will cause unexpected behavior.
To fix this you can flop the inputs twice (called a dual-rank synchronizer) before feeding them into the rest of your logic. Usually multi-bit synchronization requires a bit more careful handling but in your case each bit can be treated independently.

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.

verilog changing random seed

How do I change the seed for $urandom_range every time I am starting a new simulation. I tried so many things non worked.
always#(posedge tb_rd_clkh)
begin
$random(9);
tbo9_ready_toggle_q <= $urandom_range(0, 1);
end
You can change the seed using a flag like this:
irun -seed seed_number
Or you can use a random seed:
irun -seed random
I'm pretty sure every tool (Questa and VCS) has an option to do this. If you don't set a seed, it will default to 1.
Set the seed value by using the conventional way before accessing the range of random numbers using urandom_range
seed = 2;
void'($urandom(seed));
Here the above code snippet will set the seed value to 2 for uramdom_range too and every time you run, random number generator creates the same sequence as long as the seed is same, you can find a working example at the EDA-Playground
UPDATE:
For your question how to set seed for urandom_range insde always block? A more generalized way as per SV LRM IEEE 1800 - 2012 Section 18.13.3 srandom()
The srandom() method allows manually seeding the RNG of objects or
threads.
Thus by making use of it created a simplified self contained example to show how to set seed inside always block
module dut(input clk,output reg [31:0] out);
integer seed;
assign seed = 10;
always # (posedge clk)
begin
$srandom(seed);
out <= $urandom_range (10,1);
$display ("out = %d",out);
end
endmodule
You may want to try this out, the above example with tb can be found in the link.
Solution to your question
In your code snippet you have to change $random(9) to $srandom(9) were 9 is the seed value

Width independent functions

Is it possible to write a function that can detect the input data width automatically? For example, consider the parity function below:
function parity;
input [31:0] data;
parity = ^ data;
endfunction
When parity(data) is called, the input data should be limited to 32 bits.
Alternatively, one could write a macro, such as `PARITY(data) in which the system function $bits can detect the width of data and make the macro width-independent. Is it possible to have the same flexibility for functions?
Edit: I need my code to be synthesizable.
You can create a parameterized function. See section 13.8 in the LRM. It looks like the function must be declared inside a class like this:
virtual class C #(parameter WIDTH=32);
static function parity (input [WIDTH-1:0] data);
parity=^data;
endfunction
endclass
Then when you call the function parameterized it with the bits task:
assign parity_bit = C#($bits(data))::parity(data);
Working example on EDA Playground.
You can use macros. The function can be declared like:
`define PARITY(FUNC_name, WIDTH) \
function FUNC_name (input [WIDTH-1:0] data); \
begin \
FUNC_name = ^ data; \
end \
endfunction
and you can call it with:
`PARITY(parity, 32);
assign parity_bit = parity(data);
This code is synthesizable in xilinx, altera and synopsys tools
It is possible using unbounded arrays.
Unfortunately SystemVerilog doesn't have decent support for unbounded arrays. The LRM seems to equate unbounded with dynamic, which suggests it's going to be almost impossible to create something synthesisable. VHDL has unbounded arrays which are supported by tools and incredibly useful so it's a pity that SystemVerilog didn't include this feature properly.
Here is an example:
function automatic logic parity(input logic data[]);
logic p = 0;
for (int i=0; i<data.size(); i++)
p ^= data[i];
return p;
//return = ^data; <--- not allowd on unpacked arrays?
endfunction
logic [7:0] data_in;
logic result;
logic data_in_unpacked [] = new[$bits(data_in)];
always_comb begin
// Convert to unpacked array (better way to do this?)
for (int i=0; i<$bits(data_in); i++)
data_in_unpacked[i] = data_in[i];
result = parity(data_in_unpacked);
end
This is running on Modelsim on EDAPlayground here: http://www.edaplayground.com/x/3tS
EDIT 1: Updated the code - I just realised it's possible to call new[] at initialisation and thus statically, so in theory synthesis tools could support this. It would be interesting to synthesise this and see...
EDIT 2: Thought I'd try synthesising and unsurprisingly Quartus doesn't like this:
Error (10170): Verilog HDL syntax error at testing.sv(10) near text "]"; expecting an operand
Error (10170): Verilog HDL syntax error at testing.sv(18) near text "]"; expecting an operand
Error (10112): Ignored design unit "my_parity" at testing.sv(2) due to previous errors
Interesting question. According to my knowledge, I don't think that's possible. I would also stay away from macros (even more problems). I can propose a synthesizable workaround:
When calling your function parity on widths lesser than your defined width pad your data with 0's like this: assign my_parity_bits = parity({16'd0, my_data}); Hopefully, synthesis tool would ignore those 0's but you will have to check it yourself.
If you want to perform such operation on large data buses in a convenient way you will have to write some more Verilog. E.g. a module that would accept a WIDTH parameter and actual data as an input vector. To do this, I would advise you to write a generic module that does exactly what your function parity does. Then, write a module which will be a parity wrapper. Inside this wrapper I would perform math operations on input WIDTH parameter to determine number of parity modules needed for input data and instantiate those modules in a generate loop.
Remember that Verilog is a hardware description language, thus such limitations. Think about what your code will synthesize into when writing RTL.
Quick update on using the paramaterized virtual class idea posted above. Stack overflow won't let me leave comments so I had to post a new answer. I just wanted to add that I tried this in Vivado, and it appears to work correctly in synthesis. Using nguthrie's solution above, I can do
logic [7:0] data;
assign data = {sw, btn};
assign led[0] = C#($bits(data))::parity(data);
This is in Vivado 2021

Resources