How to constrain a counter reg size in verilog for ise synthesis? - verilog

I want to declare a counter reg in function of some parameters. I did it in this way :
parameter clk_freq = 95000; // clock frequency in kHz
parameter debounce_per_ms = 20;
localparam MAX_COUNT = ((debounce_per_ms * clk_freq)) + 1;
reg [$ln(MAX_COUNT)/$ln(2):0] count;
This work well in simulation with icarus but ISE 14.7 don't want to synthesize it. That give this error:
WARNING:HDLCompiler:1499 - "/src/button_deb.v" Line 4: Empty module <button_deb> remains a black box.
If I define the count like this :
reg [22:0] count;
ISE synthesize it well. If someone have a clue ?

This worked for me, although I'd swear I used functions like $log, $log10, $ceil and the like in the past with no problems.
module param_with_log2 (
input wire clk,
output wire d
);
function integer log2;
input integer value;
begin
value = value-1;
for (log2=0; value>0; log2=log2+1)
value = value>>1;
end
endfunction
parameter clk_freq = 95000; // clock frequency in kHz
parameter debounce_per_ms = 20;
localparam MAX_COUNT = ((debounce_per_ms * clk_freq)) + 1;
localparam integer UPPER = log2(MAX_COUNT);
reg [UPPER:0] count;
always #(posedge clk)
count <= count + 1;
assign d = count[UPPER];
endmodule
XST seems to have a problem with using constant functions: they only can be at the right side of a parameter declaration expression (as I suggested in my first comment). Credits and more information here:
http://www.beyond-circuits.com/wordpress/2008/11/constant-functions/
Notice too that UPPER is declared as localparam integer so we can use it inside a register definition upper bound expression. Credits go to the owner of this post: http://forums.xilinx.com/t5/Synthesis/XST-and-clog2/m-p/244440/highlight/true#M6609
(the module is just a phony module to have something that I can symthesize without the fear that the synthesizer will wipe all my code. It doesn't perform any kind of debouncing)

Related

what will be a good way to write 10bits decoder?

I am trying to write a 10 bits binary to thermal decoder.
For a 4 bits decoder, it is relative straightforward as shown below. However, for 10 bits, is there a smarter way to do it instead of write 1000 line code.
module decoder(in,out);
input [3:0] in;
output [15:0] out;
// input enable;
reg [15:0] out;
always #(in) begin
casez(in)
4'h1: out=16'b0000000000000001;
4'h2: out=16'b0000000000000011;
4'h3: out=16'b0000000000000111;
4'h4: out=16'b0000000000001111;
4'h5: out=16'b0000000000011111;
4'h6: out=16'b0000000000111111;
4'h7: out=16'b0000000001111111;
4'h8: out=16'b0000000011111111;
4'h9: out=16'b0000000111111111;
4'hA: out=16'b0000001111111111;
4'hB: out=16'b0000011111111111;
4'hC: out=16'b0000111111111111;
4'hD: out=16'b0001111111111111;
4'hE: out=16'b0011111111111111;
4'hF: out=16'b0111111111111111;
default: out=16'h0000;
endcase
end
endmodule
Yes, you could make this module fully parametrizable by using an unrollable for-loop. This loop would check for each bit of the out signal, if the loop-index is still smaller than the binary input signal.
The code would look like this:
module decoder #(
parameter IN_W = 10,
parameter OUT_W = 1 << IN_W
)
(
input [IN_W-1:0] in,
output reg [OUT_W-1:0] out
);
integer i;
always #* begin
// Use an unrollable loop.
for (i = 0; i < OUT_W; i++) begin
// (in < i) returns a 1-bit value
out[i] = (in < i);
end
end
endmodule
As you probably noticed, I also changed the way the ports are declared. In Verilog 2001—and also in more recent (System)Verilog versions—the port list and port declaration may be combined. This newer syntax, also known as ANSI-style, has the benefit that you don't need to add as much boilerplate code.

How can you output a constant value in Verilog?

I am trying to output an array of 1280 bits, each 10 bits long, with the numbers 0->128.
I heard localparam may be the best option, but it seems like a strange request, so I'm wondering if anyone with experience may be able to help me.
Thanks
You can create a function that provides a constant value to a localparam or any other signal.
wire [1279:0] signal;
assign signal = pattern(0);
function [1279:0] pattern(input arg); // Verilog requires at least one argument to a function
integer i;
begin
for (i=0;i<128;i=i+1)
pattern[i*10 +:10] = i;
end
endfunction
SystemVerilog:
wire [1279:0] signal;
assign signal = pattern();
function bit [1279:0] pattern();
for (int i=0;i<128;i++)
pattern[i*10 +:10] = i;
endfunction
You can use a for-loop in an initial or reset statement:
reg [0:1279] big_vector;
integer i;
// here you need an initial
// or a reset section
for (i=0; i<128; i=i+1)
big_vector[ i*128 +: 10] = i;
If you do not touch/change big_vector the synthesis tool will convert it to a constant.

Unexpected behaviour using the ternary operator (Verilog)

In the following Verilog module, I'd like to understand why the blocking assignment using concatenation doesn't give the same result as the 2 commented out blocking assignments.
When I run the program on the FPGA, it gives the expected result with the 2 blocking assignments (the leds blink), but not with the blocking assignment using concatenation (the leds stay off).
Bonus points for answers pointing to the Verilog specification explaining what is at play here!
/* Every second, the set of leds that are lit will change */
module blinky(
input clk,
output [3:0] led
);
reg [3:0] count = 0;
reg [27:0] i = 0;
localparam [27:0] nTicksPerSecond = 100000000;
assign led = {count[3],count[2],count[1],count[0]};
always # (posedge(clk)) begin
// This works:
//count = i==nTicksPerSecond ? (count + 1) : count;
//i = i==nTicksPerSecond ? 0 : i+1;
// But this doesn't:
{count,i} = i==nTicksPerSecond ?
{count+1, 28'b0 } :
{count , i+1};
end
endmodule
PS: I use Vivado 2018.2
The reason is because the widths of count+1 and i+1 are both 32 bits. An unsized number is 32 bits wide (1800-2017 LRM section 5.7.1) and the width of the addition operator is the size of the largest operand (LRM section 11.6.1). To make your code work, add a proper size to your numeric literals
{count,i} = i==nTicksPerSecond ?
{count+4'd1, 28'b0 } :
{count , i+28'd1};
A simpler way to write this code is
always # (posedge clk)
if (i== nTicksPerSecond)
begin
count <= count + 1;
i <= 0;
end
else
begin
i <= i + 1;
end

Verilog : Variable index is not supported in signal

I get an error saying 'Index is not supported in signal'. From what I can see the error is on the left hand side of the non-blocking assignment. Why does the code below give an error and is there a way to work around it?
...
parameter width = 32;
parameter size = 3;
input clk, reset;
input [width*size-1:0] A;
input [width*size-1:0] B;
output [width*size-1:0] result;
reg signed [width*size-1:0] partials;
reg signed [width-1:0] temp;
reg signed [width-1:0] currenta;
reg signed [width-1:0] currentb;
wire signed [width-1:0] temp1wire;
...
integer k = 0;
always # (posedge clk)
begin
currenta[width-1:0] <= A[width*k +: width];
k = k+1
currentb[width-1:0] <= B[width*k +: width];
partials[width*k +: width] <= temp1wire;
end
Add Add1(clk, temp1wire, currenta, currentb);
...
This code is part of a sequential block that does vector addition and saves the result at partials[width*k +: width].
I found this on the Xilinx forum:
"XST works fine with the indexed part-select operator "+:" if it is on the right-hand side (RHS) of the assignment. It also works fine when it is on the left-hand side (LHS) AND the starting index is a constant. Your case uses a variable as the starting index on the LHS and that what XST doesn't like although it's legal."
k needs to be clamped or wrapped around after reaching size-1.
Wrapping around can be done with the mod operator (%); example:k = (k+1)%size. % may not synthesize optimally (check your synthesizer), so a if-statement is a functional alternative if(k==SIZE-1) k = 0; else k=k+1;
Suggestions:
It is generally recommenced to keep parameters as uppercase, this way you can easily identity parameters form signal names. Putting a blocking assignment inside a sequential block is legal, but most design rules recommend separating combinational logic from sequential assignments. I would prefer writing your code like the following:
// $clog is IEEE1364-2005 § 17.11, some synthesizers support it, others don't
reg [$clog2(SIZE):0] k=0, next_k;
always #* begin
if (k==SIZE-1) begin
next_k = 0; // wrap around
// next_k = k; // clamp
end
else begin
next_k = k+1;
end
end
always # (posedge clk)
begin
currenta[WIDTH-1:0] <= A[WIDTH*k +: WIDTH];
currentb[WIDTH-1:0] <= A[WIDTH*next_k +: WIDTH];
partials[WIDTH*next_k +: WIDTH] <= temp1wire;
k <= next_k;
end

How to dynamically reverse the bit position in verilog?

wire [9:0] data_reg;
reg [3:0] Reverse_Count = 8; //This register is derived in logic and I need to use it in following logic in order to reverse the bit position.
assign data_reg[9:0] = 10'h88; // Data Register
genvar i;
for (i=0; i< Reverse_Count; i=i+1)
assign IReg_swiz[i] = IReg[Reverse_Count - 1 -i];
This is generating syntax error. May I know how to do this in verilog
If you'd have Reverse_Count as constant, your task boils down to just wire mix-up, which is essentially free in HDL.
In your case, the task can be nicely reduced to first mirroring wide data and then shifting by Reverse_Count to get LBS bit on its position, which itself is done just by a row of N-to-1 multiplexers.
integer i;
reg [9:0] reversed;
wire [9:0] result;
// mirror bits in wide 10-bit value
always #*
for(i=0;i<10;i=i+1)
reversed[i] = data_reg[9-i];
// settle LSB on its place
assign result = reversed>>(10-Reverse_Count);
Reverse_Count is not a constant, ie it is not a parameter or localparam.
This means that the generate statement you would be creating and destroying hardware as required, this is not allowed in verilog as it would not be possible in hardware.
The Bus that your reversing should have a fixed width at compile time, it should be possible to declare Reverse_Count as a parameter.
Since the value of Reverse_Count dunamic, you cannot use a generate statement. You can use an always block with for-loop. To be synthesizable, the for-loop needs able to static unroll. To decide which bits reverse, use an if condition to compare the indexing value and Reverse_Count
Example:
parameter MAX = 10;
reg [MAX-1:0] IReg_swiz;
integer i;
always #* begin
for (i=0; i < MAX ; i=i+1) begin
if (i < Reverse_Count) begin
IReg_swiz[i] = IReg[Reverse_Count - 1 -i];
end
else begin
// All bits need to be assigned or complex latching logic will be inferred.
IReg_swiz[i] = IReg[i]; // Other values okay depending on your requirements.
end
end
end

Resources