Is the array part select +: with variable start synthesizable by Vivado? - verilog

If I have a vector and I want to read a part of it starting somewhere. Can I use the syntax vector[staring_point +: output_length] with starting_point being an integer? Is it synthesizable?
If I write a code like this:
module my_mod(
input logic din,
input logic clk,
input logic[2:0] start_ptr,
output logic[3:0] dout);
logic[10:0] vector = 0;
always_ff#(posedge clk) vector <= {vector[9:0], din}; --shift register
always_comb dout <= vector[start_ptr +: 4];
endmodule
The design is just this and the input and output are bounded to GPIOs.
I'm expecting a mux for each output bit. Surprisingly Vivado will synthesize 1FF and 1LUTRAM that is an SRL16 so a shift register with integrated mux, but the primitive has only one output and the "dout" signal is driven only with the first bit.
The other 3bits are buffered to 0.
Is the syntax +: correct? Is that consistent or it's a bug of Vivado?

I cleaned code and built in Vivado 2020.2 As pointed out some outputs are inappropriately tied off in synthesis.
Cleaned up code:
module my_mod(
input logic din,
input logic clk,
input logic[2:0] start_ptr,
output logic[3:0] dout);
logic[10:0] vector;
always_ff#(posedge clk)
vector <= {vector[9:0], din}; //shift register
always_comb
dout = vector[start_ptr +: 4];
endmodule
And the RTL that the code infers:
Vivado is not doing the right thing (its a bug). This is worth reporting to Xilinx. The +: operator is capable of generating a mux/barrel shifter. How: Change the code to infer regs instead of SRL's (added a RTL reset) then it infers the design intent.
module my_mod(
input logic din,
input logic clk,
input logic[2:0] start_ptr,
input logic rst,
output logic[3:0] dout);
logic[10:0] vector;
always_ff#(posedge clk)
if(rst)
vector <= 0;
else
vector <= {vector[9:0], din}; //shift register
always_comb
dout = vector[start_ptr +: 4];
endmodule
To stay closer to what you posted (no reset) you can use the right shift operator. This also infers the mux as intended. This does not give an initial value of 0, in the reg, so you need to add the reset if you need an initial value.
module my_mod(
input logic din,
input logic clk,
input logic[2:0] start_ptr,
output logic[3:0] dout);
logic[10:0] vector;
always_ff#(posedge clk)
vector <= {vector[9:0], din}; //shift register
always_comb
dout = vector >> start_ptr ;
endmodule
Here is the RTL view of the design using the shift operator (>>).
At one point I was thinking Xilinx intended for the +: and -: operators to be used at elaboration time only, for example in a generate loop. If that were the case then Xilinx should state that in the synthesis guide UG901 (they do not). Also Vivado infers the combinational logic for a design with registers, why should it not work with SRL's?
To me its a bug.
Good catch.

Related

Edge triggered flip flop behaving like a transparent latch when sensitivity list has two rising edges

Trying this on a Terasic DE10-Lite, programmed with Quartus Prime Lite Edition.
SW[0] is a switch. LEDR[0] is an LED. KEY[0] is a push button. The push button is active low.
I want to model a flip flop that stores SW[0] in register r0 and displays it in LEDR[0] when KEY[0] delivers a rising edge.
The following works as expected:
module flipfloptest (
input [9:0] SW,
input [1:0] KEY,
output [9:0] LEDR);
reg r0;
assign LEDR[0] = r0;
always #(posedge(~KEY[0]))
r0 <= SW[0];
endmodule
I now add another push button, KEY[1], to the sensitivity list with the intention that pushing either down will set the flip flop.
module flipfloptest (
input [9:0] SW,
input [1:0] KEY,
output [9:0] LEDR);
reg r0;
assign LEDR[0] = r0;
always #(posedge(~KEY[0]) or posedge(~KEY[1]))
r0 <= SW[0];
endmodule
This behaves like a latch (i.e. no longer edge triggered). LEDR[0] immediately reflects the state of SW[0] without the need to press either KEY[0] or KEY[1]. Pressing one or both does not affect behavior in any way.
Clearly, I don't understand the meaning of this sensitivity list. What is the correct interpretation?
More context: I can get the desired behavior using a clock and state machine as shown below. My question is why the sensitivity list isn't behaving intuitively.
module flipfloptest (
input MAX10_CLK1_50,
input [9:0] SW,
input [1:0] KEY,
output [9:0] LEDR);
reg [1:0] tic0, tic1;
reg r0;
assign LEDR[0] = r0;
always #(posedge MAX10_CLK1_50) begin
case (tic0)
0: tic0 = (~KEY[0])?1:0;
1: tic0 = (~KEY[0])?2:0;
2: tic0 = (~KEY[0])?2:0;
endcase
case (tic1)
0: tic1 = (~KEY[1])?1:0;
1: tic1 = (~KEY[1])?2:0;
2: tic1 = (~KEY[1])?2:0;
endcase
if (tic0==1 | tic1==1)
r0 <= SW[0];
end
endmodule
Synthesis tools only recognize certain Verilog coding patterns. Refer to synthesizable constructs. The documentation for your Quartus tool set should describe what coding styles are supported.
Your 1st and 3rd code examples adhere to the synthesizable coding style, whereas your 2nd example does not. You should look at the log files that your synthesis tools created: there should be messages in there warning you about unintended latches.
The code in your 2nd example is unusual. Perhaps your synthesis tool did not know what to do with it, and it just decided to give you a latch. Unfortunately for you, that is not how your code simulates.
This code:
always #(posedge(~KEY[0]) or posedge(~KEY[1]))
r0 <= SW[0];
can be simplified as:
always #(negedge KEY[0] or negedge KEY[1])
r0 <= SW[0];
r0 will be updated with SW[0] every time you get a negedge of either KEY[0] or KEY[1]. That does not behave like a latch. But, as I said, this code does not adhere to typical synthesis coding style.

Best way to optionally register inputs

I have a systemverilog module with a LOT of input signals of varying sizes. I want to optionally register them before use. Here is my desired criteria for the code that does this optional registering:
I should only need to write out the assignments once (no duplicate code)
I should not need to use any macros (I don't want scoping issues)
Here's a minimal reproducible example of my current solution:
module optional_register #(
parameter bit REGISTER_INPUTS=1
)(
input wire clk,
input wire a_in,
input wire b_in,
input wire c_in,
input wire d_in,
output logic a_out,
output logic b_out,
output logic c_out,
output logic d_out
);
function assign_inputs();
a_out <= a_in;
b_out <= b_in;
c_out <= c_in;
d_out <= d_in;
endfunction
generate if (REGISTER_INPUTS) begin
always_ff # (posedge clk)
assign_inputs();
end else begin
always_comb
assign_inputs();
end endgenerate
endmodule
This code synthesizes correctly in Vivado 2020.2 with both the registers on and off. But I am worried that the non-blocking assignments in the function are technically invalid, according to The IEEE Std for Verilog (1364-2001), section "10.3.4 Function rules" which states:
A function shall not have any nonblocking assignments.
So my concern is that this won't work in other synthesizers, and may cause unexpected behavior in simulation. Can anyone speak to this?
Any other ideas?
This is SystemVerilog code, you should be using the IEEE 1800-2017 LRM.
Nonblocking assignments are allowed inside function as long as LHS target is not a variable with an automatic lifetime. Do not use NBA to assign to argument outputs or the return value of a function with a static lifetime because their current values get copied out before the NBA updates happens.
You should declare your function with no return value.
function void assign_inputs();
Using NBAs in combinational logic is not the best for simulation performance, but is usually OK functionality wise.

How to write this for loop conditions in Verilog design correctly?

I want to write a module in Verilog that outputs the same 32-bit input at positive clock edge. However, I have some trouble with the loop conditions.
module if_id (
input clk
,input [31:0] in
,output reg [31:0] out
);
always#(posedge clk)
out <= in;
endmodule
you don't need to write looping code if your intention is to register a 32bit value . But if u need to write it in array mode u need to use genvar variable in your code. By the way int isn't supported in verilog variants . migrate to System-verilog for more number of data types.

How to assign initial value to an input reg: Design compiler delete the assignment

I'm newbie in ASIC design. I have a design with for example two inputs a ,b. I'm using the following code for initialize these two signals. But the Design compiler generating a warning that the register "a" is a constant and will be removed. When I'm trying to do post-synthesis simulation these two signals are all 'z'. So how can I apply initial signal assignment to avoid such a problem?
always #(posedge(clk) or posedge (rst)) begin
if (rst) begin
a<=4d'5;
b <=4'd10;
end
end
While describing hardware system, you need to consider that input signals to your module comes from another module/system and their values are decided by that signals. Inputs to any module can only be wire type.
You can think of a module as a box that has inputs and outputs. The values of output signals are decided by input signal + logic inside the box. However, the module cannot decide what its inputs should be. It is only possible if there is feedback, and even in that case it would depend on other signals that are outside of the module's control.
As a result, output signals can be declared as output reg but the same is not true for inputs. However there is solution to your problem, I think what you want can be designed using the following method:
module your_module(
input clk,
input rst,
//other inputs and outputs that you might need
input [3:0] a,
input [3:0] b
);
//define registers
reg [3:0] a_register;
reg [3:0] b_register;
/*
These registers are defined to make it possible to
to give any value to that logics when posedge rst
is detected, otherwise you can use them as your
input logics
*/
//use initial block if you need
always#(posedge clk or posedge rst) begin
if(rst) begin
a_register <= 4'd5;
b_register <= 4'd10;
end
else
begin
a_register <= a;
b_register <= b;
// and use a_register and b_register as you want to use a and b
end
end
endmodule

How can i make my verilog shifter more general?

Here i have a shifter but as of rite now it only works for up to 3 bits. I've been looking and i can't find out how to make it work for up to 8 bits.
module shifter(a,b,out);
input [7:0] a, b;
output [7:0] out;
wire [7:0] out1, out2, out3;
mux_8b_2to1 first(a[7:0], {a[3:0],a[7:4]}, b[2], out1);
mux_8b_2to1 second(out1[7:0], {out1[5:0],out1[7:6]}, b[1], out2);
mux_8b_2to1 third(out2[7:0], {out2[6:0],out2[7]}, b[0], out);
endmodule
What you have is a Barrel Shifter. Two ways to make it more generic are make it a functional model (still synthesis-able) or structural model with a generate block. Both approaches follow IEEE Std 1364-2001 (aka Verilog-2001).
The functional generic approach for a barrel shifter only needs a down-shifter. The general function is out = {in,in} >> (WIDTH-shift) where leftover bits can be ignored. To protect for double-roll (i.e. shift > WIDTH ), use the mod operator on the shift (WIDTH-(shift%WIDTH)).
module barrel_shifter_functional #( parameter CTRL=3, parameter WIDTH=CTRL**2 )
( input wire [WIDTH-1:0] in,
input wire [ CTRL-1:0] shift,
output wire [WIDTH-1:0] out );
assign out = {2{in}} >> (WIDTH-(shift%WIDTH));
endmodule
The structural generic approach for a barrel shifter needs a generate block. The for loop in the generate block will unravel at compile time, not run time like a for loop like in an always block. To keep it generic also have have the 2-to-1 mux have a parametrized width. FYI, you can use the generate block with functional code too, for example comment out the mux_2to1 instantiation and uncomment the assign statement below it. Learn more about the generate block by reading IEEE Std 1800-2012 ยง 27. Generate constructs.
module barrel_shifter_structeral #( parameter CTRL=3, parameter WIDTH=CTRL**2 )
( input wire [WIDTH-1:0] in,
input wire [ CTRL-1:0] shift,
output wire [WIDTH-1:0] out );
wire [WIDTH-1:0] tmp [CTRL:0];
assign tmp[CTRL] = in;
assign out = tmp[0];
genvar i;
generate
for (i = 0; i < CTRL; i = i + 1) begin : mux
mux_2to1 #(.WIDTH(WIDTH)) g(
.in0(tmp[i+1]),
.in1({tmp[i+1][WIDTH-(2**i)-1:0],tmp[i+1][WIDTH-1:WIDTH-(2**i)]}),
.sel(shift[i]),
.out(tmp[i]) );
// assign tmp[i] = shift[i] ? {tmp[i+1][WIDTH-(2**i)-1:0],tmp[i+1][WIDTH-1:WIDTH-(2**i)]} : tmp[i+1];
end : mux
endgenerate
endmodule
module mux_2to1 #( parameter WIDTH=8 )
( input wire [WIDTH-1:0] in0, in1,
input wire sel,
output wire [WIDTH-1:0] out );
assign out = sel ? in1 : in0;
endmodule
Both examples are functionally equivalent and synthesize provided CTRL is less than or equal to the ceiling of log2(WIDTH). Synthesis will likely give different results. The generate method will exclusively use 2-to-1 muxes while the pure functional method will depend on the quality of the optimizer.
Working example # http://www.edaplayground.com/s/6/500
I've used the >> and << operators to generate a synthetizable design using ISEWebPack, as this:
module shifter(
input wire [7:0] a,
input wire [7:0] b,
input wire leftright, // 0=shift right, 1=shift left
output reg [7:0] out
);
always #* begin
if (leftright==0)
out = a>>b;
else
out = a<<b;
end
endmodule
This way, the symthesis tool will know that you want to implement a shifter and can use its own macros to best synthetize it:
Synthesizing Unit <shifter>.
Related source file is "shifter.v".
Found 8-bit shifter logical right for signal <out$shift0002> created at line 30.
Found 8-bit shifter logical left for signal <out$shift0003> created at line 32.

Resources