FPGA------ 基于 ZYNQ ECO开发板 跑马灯

目录

always语句

赋值语句(阻塞赋值语句和非阻塞赋值语句)

位拼接运算符

跑马灯


always语句

在Verilog中,always语句是用来描述组合逻辑或时序逻辑的重要语句。它的声明格式如下:

always @(<敏感信号列表>) <语句块>

<敏感信号列表>中可以包含各种信号,如输入端口、寄存器或者其他内部信号,用于指定在这些信号发生变化时,<语句块>需要执行。

always语句中,<语句块>可以是一系列的逻辑语句,用来描述所需的行为。这些语句可以是组合逻辑的赋值语句,或者是时序逻辑的if语句、case语句等。

然而,需要注意的是,always语句必须与时序控制结合使用,以确保其在仿真过程中能够正常工作。如果一个always语句没有明确的时序控制,可能会导致仿真死锁的情况。就像所给出的例子always i = ~i;,该语句没有指定敏感信号,因此在仿真过程中会发生死锁。

为了解决这个问题,我们应该使用时序控制结构,如posedge(上升沿触发)或negedge(下降沿触发)来指定敏感信号。例如,如果你想要一个always语句在时钟的上升沿触发时执行,你可以这样写:

always @(posedge clk) i <= ~i;

这样,always语句将在时钟的上升沿触发时执行,并将i的值取反并赋给i

总结一下,为了确保always语句能够正常工作,在使用时必须结合适当的时序控制结构,以明确指定敏感信号。这样可以避免引发仿真死锁的情况。

赋值语句(阻塞赋值语句和非阻塞赋值语句)

在Verilog中,有两种不同的赋值语句:阻塞(blocking)赋值语句和非阻塞(non-blocking)赋值语句。

阻塞赋值语句使用等号(=)进行赋值操作,例如 b = a;。当执行阻塞赋值语句时,该语句将立即执行,并且在赋值完成之前不会执行下一条语句。这意味着阻塞赋值语句按照顺序逐个执行,是串行执行的。硬件电路中,阻塞赋值语句会导致电路的并行性受限,因为下一步操作必须等待当前赋值语句完成。因此,在可综合风格的模块中,建议使用阻塞赋值语句。

非阻塞赋值语句使用非阻塞赋值符(<=),例如 b <= a;。与阻塞赋值不同,非阻塞赋值语句在执行时不会立即执行赋值操作,而是在整个 always 块的末尾才会执行。这意味着非阻塞赋值语句的执行是并行的,多个非阻塞赋值语句可以同时执行。在硬件电路中,非阻塞赋值语句能够保持并行性,因为每个赋值语句的执行不会相互影响。因此,非阻塞赋值语句在时序逻辑中非常有用。

需要注意的是,在仿真过程中,阻塞赋值和非阻塞赋值的行为是不同的。阻塞赋值在执行时会立即赋值,而非阻塞赋值在执行时会将赋值操作推迟到下一个时间步。因此,在时序逻辑中使用非阻塞赋值可以更准确地模拟出电路的行为,而在组合逻辑中使用阻塞赋值则更直观和方便。

总结一下,阻塞赋值语句使用等号进行赋值,是串行执行的;非阻塞赋值语句使用非阻塞赋值符进行赋值,是并行执行的。在可综合风格的模块中,建议使用非阻塞赋值语句,而在组合逻辑中使用阻塞赋值语句更为方便。

位拼接运算符

位拼接运算符可以将多个信号的指定位拼接在一起,用于进行运算操作或者生成新的信号。位拼接运算符使用一对大括号({})来表示。

位拼接运算符的语法如下:

{信号1的某几位, 信号2的某几位, ..., 信号n的某几位}

其中,每个信号后面的方括号([])用于指定要拼接的位的范围。例如,a[3:0]表示信号a的4个低位,w[3'b101]表示一个3位宽的信号,具体值为二进制101。

需要注意的是,在位拼接表达式中,所有被拼接的信号都必须明确指定要拼接的位数。也就是说,不允许直接拼接一个没有指明位数的信号。例如,{a, b[3:0], w, 3'b101}中,信号abw都指定了要拼接的位数,而3'b101表示一个3位宽的二进制常数。

另外,还可以在位拼接表达式中使用具体的位值,如1'b1表示一个1位宽的常量1,1'b0表示一个1位宽的常量0。

总结一下,位拼接运算符可以将多个信号的指定位拼接在一起,生成新的信号。在位拼接表达式中,需要明确指定每个信号要拼接的位数,并且可以使用具体的位值。

跑马灯

`timescale 1ns / 1ps

module led_sy2(
    input           clk,
    input           rst_n,
    output  reg [3:0]    led
    );
    //assign led = 4'b1100;
    parameter LEDL = 0; //第一个灯
    parameter s1 = 1;//第二个灯
    parameter s2 = 2;//第三个灯
    parameter s3 = 3;//第四个灯
    
    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需要一个endcase来结束
         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

这段代码是一个Verilog HDL的模块,名为led_sy2。下面对代码进行详细的解释:

  1. timescale 1ns / 1ps:这是一个timescale指令,用于定义仿真中的时间单位。这里指定1纳秒为时间单位,1皮秒为时间精度。

  2. module led_sy2(...):定义了一个名为led_sy2的模块。该模块有三个输入信号:clk(时钟信号)、rst_n(异步复位信号),以及一个输出寄存器led(4位宽的LED灯)。

  3. parameter:这里定义了四个参数,分别为LEDLs1s2s3,分别表示四个不同状态的LED灯。

  4. parameter delay = 50_000_000:定义了一个名为delay的参数,赋值为50000000,即延迟计数的值。该值约等于1秒(因为timescale中指定了1纳秒为时间单位)。

  5. reg:定义了三个寄存器变量c_state(当前状态)、n_state(下一个状态)和count(计数器)。

  6. always @(posedge clk):这是一个时钟触发的过程块。当时钟的上升沿触发时,这个块中的代码将被执行。

  7. if(!rst_n):这是一个异步复位条件,当rst_n为0时,表示复位状态。

  8. else:表示当复位条件不满足时的情况。

  9. case(c_state):这是一个case语句,根据c_state的值来执行相应的操作。

  10. case语句中,根据count的值来确定下一个状态n_state。如果count等于delay - 1(即延迟计数的最大值-1),则切换到下一个状态,否则保持当前状态。

  11. always @(*):这是一个组合逻辑过程块,当任何与其相关的信号发生变化时,这个块中的代码将被执行。

  12. always @(*)块中,根据当前状态c_state来分别设置输出led的值。根据不同的状态,将led赋值为不同的4位二进制数。

  13. 第三个always @(posedge clk)块用于控制计数器count的值。在每个时钟上升沿触发时,检查复位条件和计数器是否达到最大值,并根据情况进行设置。

总结:这段代码实现了一个状态机,用于控制4个LED灯的状态变化。通过计数器和延迟值来控制状态切换的时间,通过case语句来确定下一个状态,并根据当前状态设置输出LED的值。

注意:语句中一定要考虑到所有情况,否则容易卡死在某个不明位置。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

0X78

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值