module RingCounter(
input logic Clock,
input logic Reset,
output logic [3:0] Count
);
always_ff #(posedge Clock, posedge Reset)
begin
if (Reset)
Count <= 4’d1;
else
Count <= {Count[2:0], Count[3]};
end
endmodule
I have the working code above for a 4-bit ring counter in SystemVerilog, but I am unsure how one line of it works as it wasn't clearly explained in the lecture.
Count <= {Count[2:0], Count[3]};
Any help on explaining exactly what this line does would be much appreciated.
The curly braces, {}, are the concatenation operator. They concatenate multiple bits into a bus.
On the left hand side of the nonblocking assignment (<=), you have Count, which is a short-hand way of writing the 4-bit bus: Count[3:0].
On the right hand side of the assignment, you have the 3-bit signal Count[2:0] concatenated with the 1-bit signal Count[3].
Another way to write the RHS is as 4 separate bits in the following order:
{Count[2], Count[1], Count[0], Count[3]}
Another way to write the LHS is as 4 separate bits in the following order:
{Count[3], Count[2], Count[1], Count[0]}
Therefore, the assignment sets the new Count[3] to the old Count[2], etc.
Refer to IEEE Std 1800-2017, section 11.4.12 Concatenation operators.
Related
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.
I'm having trouble finding direct answers to how FPGA-level LUTs are accessed/implemented in simple modules (I'll provide an example below). Referring to the top answer on this post, https://electronics.stackexchange.com/questions/163961/creating-a-verilog-code-for-4-bit-multiplier-using-lookup-table, the type of LUT I'm trying to understand is the first one listed (FPGA-level).
For example, let's say I had the following module:
module RightRotation
{
input logic clk
input logic [2:0] din
output logic [2:0] dout
};
always#(clk) begin
dout[0] <= din[2];
dout[1] <= din[0];
dout[2] <= din[1];
end
endmodule
If I were to implement this module with a FPGA-level LUT with 3 inputs and 1 output, how many lookups would it take (for instance, is a value looked up every time a value is assigned with a nonblocking statement in the always#)? How would this answer change if I had 4, or 5, or 6 inputs?
After fixing syntax errors, Vivado produces these results for utilization and implementation.
N inputs would use N flops in your design.
Vendor datasheets can help understand look up tables, CLBs, slices etc.
Example here:
https://www.xilinx.com/support/documentation/user_guides/ug474_7Series_CLB.pdf
How to count the number of flip-flops generated or used in the Verilog code without using any tool?
You count the number of bits on the LHS of non-blocking assignments inside an always # (pos/neg_edge ...). (The 'non-blocking' adjective is superfluous as you should only have non-blocking assignments inside an # (pos/neg_edge clock) section.)
The following code produces 12 registers:
reg [7:0] my_byte1,my_byte2;
...
always #(posedge clock)
begin
my_byte1 <= something_which_is_8_bits_wide;
my_byte2[3:0]<= something_else_which_is_4_bits_wide;
end
module counter (clk,rst,enable,count);
input clk, rst, enable;
output [3:0] count;
reg [3:0] count;
always # (posedge clk or posedge rst)
if (rst) begin
count <= 0;
end else begin : COUNT
while (enable) begin
count <= count + 1;
disable COUNT;
end
end
endmodule
(Source: http://www.asic-world.com/verilog/verilog_one_day2.html#While)
From what I have learnt, <= is a relational operator and it will return 1 if true and 0 if false, but where does it return in this code?
In the context of your code, <= is not a relational operator, it is an assignment operator. There are two types of assignment in Verilog:
blocking : =
non-blocking : <=
In a Verilog design, you
always use blocking assignments for combinational logic
always use non_blocking assignments for sequential logic
If you do not, you simulation will be indeterminate - it will not necessarily behave the same way every time you run it. Which, of course, is not good.
So, why is that? Well, to start you must learn that Verilog has 4 scheduling regions:
from prev time step
|
ACTIVE
|
INACTIVE
|
NBA
|
POSTPONED
|
V
to next time step
Blocking assignments are executed in the ACTIVE region. However, while the right-hand side of a non-blocking assignment is evaluated in the ACTIVE region, the assignment does not occur until the NBA region. This is key to why you need to use them for sequential logic.
So, why do you need to use non-blocking assignments for sequential logic? The reason is because the delay between evaluation of the right-hand side and assignment of the left hand side enables a Verilog simulation to be determinate, ie to behave the same way every time you run it. This delay means that the behaviour of the simulation does not depend on the order in which the always blocks are executed, which it would if only blocking assignments were used.
A simple analogy to the delay between evaluating the right-hand side of a non-blocking assignment and assigning the left-hand side is the clock-to-Q delay of a real flip-flop. In a real flip-flop, there is always a small delay (clock-to-Q delay) between the D input being sampled (by the clock) and the Q output being driven. This is vital to the correct operation of real sequential logic. For example, if there were no clock-to-Q delay in a real flip-flop instead of it taking exactly 4 clocks for the D input of the first flip-flop in a 4-stage shift register to get to the Q output of the fourth flip-flop, it could take any number of clocks between 1 and 4: its behaviour would also be indeterminate.
I am trying to make a counter in verilog and I want to know how to split the sequential part from the combinational one.
I have this module, it works fine, but I don't know how to split it?
module counter4bits(
input clk_i,
input rst_n_i,
input enable_i,
input up_down_i,
output reg[3:0] val_o);
always#(posedge clk_i) begin
if (rst_n_i == 1)
val_o <= 0;
else if(enable_i == 1)
val_o <= val_o + 1;
end
endmodule
One way is to make always #(*) blocks for the combinational parts using blocking assignments (=), and make always #(posedge clk_i) blocks for the sequential parts using non-blocking assignments (<=) to simple reg.
The blocking assignment (=) in combinational gives faster simulation and predictable behavior even if explicit sensitivity lists line #(rst_n_i or enable_i or ...) are used instead of #(*). The non-blocking assignment (<=) in sequential logic gives the expected flip-flop behavior where the next value depends on the previous value.
The code will then look like:
module counter4bits(
... input/output with no change
reg [3:0] val_nxt; // Not flip-flop but used in always #(*) thus reg
always #(*) begin
if (rst_n_i == 1)
val_nxt = 0;
else if(enable_i == 1)
val_nxt = val_o + 1;
end
always #(posedge clk_i)
val_o <= val_nxt;
endmodule
Why do you want to split the combinational and sequential logic.
The code you have written is good style for the power optimization.
With your style of code the tool can understand the flip flop value will change on enable_i hence the tools are intelligent enough to put a clock gate for flop using enable_i which will reduce the power.