Table of Contents
always statement
Assignment statements (blocking assignment statements and non-blocking assignment statements)
bit concatenation operator
marquee
always statement
In Verilog, the always
statement is an important statement used to describe combinational logic or sequential logic. Its declaration format is as follows:
always @(
can contain various signals, such as input ports, registers or other internal signals, which are used to specify when these signals change,
Need to be executed.
In the always
statement,
can be a series of logical statements that describe the desired behavior. These statements can be assignment statements of combinational logic, or if
statements, case
statements of sequential logic, etc.
However, it should be noted that the always
statement must be used in conjunction with timing control to ensure that it works properly during simulation. If an always
statement does not have clear timing control, it may lead to a simulation deadlock situation. Just like the example given always i = ~i;
, this statement does not specify a sensitive signal, so a deadlock will occur during the simulation.
To solve this problem, we should use timing control structures such as posedge
(rising edge trigger) or negedge
(falling edge trigger) to specify sensitive signals. For example, if you want an always
statement to be executed when triggered by the rising edge of the clock, you can write:
always @(posedge clk) i <= ~i;
In this way, the always
statement will be executed when triggered by the rising edge of the clock, and the value of i
will be inverted and assigned to i
.
To summarize, in order to ensure that the always
statement works properly, it must be used in conjunction with appropriate timing control structures to clearly specify sensitive signals. This can avoid situations that cause simulation deadlock.
Assignment statement (blocking assignment statement and non-blocking assignment statement)
In Verilog, there are two different Assignment statements: blocking (blocking) assignment statements and non-blocking (non-blocking) assignment statements.
Blocking assignment statements use the equal sign (=) to perform assignment operations, such as b = a;
. When a blocking assignment statement is executed, the statement is executed immediately, and the next statement is not executed until the assignment is completed. This means that blocking assignment statements are executed one by one in order and are executed serially. In hardware circuits, blocking assignment statements will limit the parallelism of the circuit because the next operation must wait for the completion of the current assignment statement. Therefore, in synthesizable style modules, it is recommended to use blocking assignment statements.
Non-blocking assignment statements use the non-blocking assignment operator (<=), such as b <= a;
. Unlike blocking assignments, non-blocking assignment statements will not perform the assignment immediately when executed, but will be executed at the end of the entire always
block. This means that the execution of non-blocking assignment statements is parallel, and multiple non-blocking assignment statements can be executed simultaneously. In hardware circuits, non-blocking assignment statements maintain parallelism because the execution of each assignment statement does not affect each other. Therefore, non-blocking assignment statements are very useful in sequential logic.
It should be noted that during simulation, the behavior of blocking assignment and non-blocking assignment is different. Blocking assignment will assign the value immediately when executed, while non-blocking assignment will postpone the assignment operation to the next time step when executed. Therefore, using non-blocking assignments in sequential logic can more accurately simulate the behavior of the circuit, while using blocking assignments in combinational logic is more intuitive and convenient.
To summarize, blocking assignment statements use the equal sign to assign values and are executed serially; non-blocking assignment statements use non-blocking assignment symbols to assign values and are executed in parallel. In synthesizable style modules, it is recommended to use non-blocking assignment statements, while it is more convenient to use blocking assignment statements in combinational logic.
bit splicing operator
The Bit concatenation operator can concatenate the specified bits of multiple signals together to perform operations or generate new signals. The bit concatenation operator is represented by a pair of curly braces ({}).
The syntax of the bit concatenation operator is as follows:
{Some digits of signal 1, certain digits of signal 2, ..., certain digits of signal n}
Among them, the square brackets ([]) after each signal are used to specify the range of bits to be spliced. For example, a[3:0]
represents the 4 low-order bits of signal a
, and w[3'b101]
represents a 3-bit wide signal. , the specific value is binary 101.
It should be noted that in bit splicing expressions, all spliced signals must explicitly specify the number of bits to be spliced. In other words, it is not allowed to directly splice a signal without specifying the number of bits. For example, in {a, b[3:0], w, 3'b101}
, the signals a
, b
, w
both specify the number of bits to be spliced, and 3'b101
represents a 3-bit wide binary constant.
In addition, you can also use specific bit values in bit splicing expressions, such as 1'b1
represents a 1-bit wide constant 1, 1'b0
represents a 1-bit Width constant 0.
To summarize, the bit splicing operator can splice the specified bits of multiple signals together to generate a new signal. In bit-splicing expressions, the number of bits to be spliced for each signal needs to be explicitly specified, and specific bit values can be used.
Marquee
`timescale 1ns / 1ps module led_sy2( input clk, input rst_n, output reg [3:0] led ); //assign led = 4'b1100; parameter LEDL = 0; //The first light parameter s1 = 1;//The second light parameter s2 = 2;//The third light parameter s3 = 3;//The fourth light parameter delay = 50_000_000; reg [2:0] c_state,n_state; reg [31:0] count ; always @(posedge clk) if(!rst_n) c_state <= 0; else c_state <= n_state; always @(*) if(!rst_n) n_state = LEDL; else begin case(c_state) LEDL: begin if(count == delay -1) n_state = s1; else n_state = LEDL; end s1: begin if(count == delay -1) n_state = s2; else n_state = s1; end s2: begin if(count == delay -1) n_state = s3; else n_state = s2; end s3: begin if(count == delay -1) n_state = LEDL; else n_state = s3; end endcase //case requires an endcase to end end always @(posedge clk) if(!rst_n) led <= 0; else begin case(c_state) LEDL: begin led<=4'b0001; end s1: begin led<=4'b0010; end s2: begin led<=4'b0100; end s3: begin led<=4'b1000; end endcase end always @(posedge clk) if(!rst_n) count <= 0; else if(count == delay -1) count<=0; else count <= count + 1; endmodule
This code is a Verilog HDL module named led_sy2
. The code is explained in detail below:
-
timescale 1ns / 1ps
: This is a timescale directive used to define the time unit in simulation. Here, 1 nanosecond is specified as the time unit and 1 picosecond is the time precision. -
module led_sy2(...)
: defines a module namedled_sy2
. The module has three input signals:clk
(clock signal),rst_n
(asynchronous reset signal), and an output registerled
(4 bits wide LED lights). -
parameter
: Four parameters are defined here, namelyLEDL
,s1
,s2
,s3
, respectively representing four different status LED lights. -
parameter delay = 50_000_000
: A parameter nameddelay
is defined and assigned a value of 50000000, which is the value of the delay count. This value is approximately equal to 1 second (because timescale specifies 1 nanosecond as the time unit). -
reg
: Defines three register variablesc_state
(current state),n_state
(next state) andcount
(counter). -
always @(posedge clk)
: This is a clock-triggered procedure block. When triggered by the rising edge of the clock, the code in this block will be executed. -
if(!rst_n)
: This is an asynchronous reset condition. Whenrst_n
is 0, it indicates the reset state. -
else
: Indicates the situation when the reset condition is not met. -
case(c_state)
: This is acase
statement that performs corresponding operations based on the value ofc_state
. -
In the
case
statement, the next staten_state
is determined based on the value ofcount
. Ifcount
is equal todelay - 1
(that is, the maximum value of delay count - 1), switch to the next state, otherwise keep the current state. -
always @(*)
: This is a combinational logic process block. When any signal related to it changes, the code in this block will be executed. -
In the
always @(*)
block, set the value of the outputled
respectively according to the current statec_state
. According to different states,led
is assigned to different 4-digit binary numbers. -
The third
always @(posedge clk)
block is used to control the value of the countercount
. When triggered on each rising clock edge, check the reset condition and whether the counter reaches the maximum value, and set it accordingly.
Summary: This code implements a state machine to control the state changes of 4 LED lights. Use counters and delay values to control the time of state switching, use case
statements to determine the next state, and set the value of the output LED according to the current state.
Note: All situations must be considered in the statement, otherwise it is easy to get stuck in an unknown position.