FPGA—— based on ZYNQ ECO development board marquee

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:

  1. 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.

  2. module led_sy2(...): defines a module named led_sy2. The module has three input signals: clk (clock signal), rst_n (asynchronous reset signal), and an output register led (4 bits wide LED lights).

  3. parameter: Four parameters are defined here, namely LEDL, s1, s2, s3, respectively representing four different status LED lights.

  4. parameter delay = 50_000_000: A parameter named delay 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).

  5. reg: Defines three register variables c_state (current state), n_state (next state) and count (counter).

  6. 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.

  7. if(!rst_n): This is an asynchronous reset condition. When rst_n is 0, it indicates the reset state.

  8. else: Indicates the situation when the reset condition is not met.

  9. case(c_state): This is a case statement that performs corresponding operations based on the value of c_state.

  10. In the case statement, the next state n_state is determined based on the value of count. If count is equal to delay - 1 (that is, the maximum value of delay count - 1), switch to the next state, otherwise keep the current state.

  11. always @(*): This is a combinational logic process block. When any signal related to it changes, the code in this block will be executed.

  12. In the always @(*) block, set the value of the output led respectively according to the current state c_state. According to different states, led is assigned to different 4-digit binary numbers.

  13. The third always @(posedge clk) block is used to control the value of the counter count. 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.