当前位置: 首页 > article >正文

05 06 Verilog基础语法与应用讲解

05. 1. 位操作

计数器实验升级,设计8个LED灯以每个0.5s的速率循环闪烁(跑马灯)

1.1 方法1:使用移位操作符<<来控制led灯的循环亮灭

设计代码

  1. Verilog中,判断操作的时候不加位宽限定是可以的,比如if(counter == 24999999)或者if(counter == 25’d24999999)都可以,但是在赋值的时候要加,比如counter <= counter + 1’d1;(赋0可以不加)

  2. [7:0] led,led有八个,所以用8'b0000_0001来代表八个led,使用移位操作符<<来控制led灯的循环亮灭。

module led_run(
    clk,
    rstn,
    led
);
    input clk;
    input rstn;
    output reg[7:0]  led;
    
    reg[25:0] counter;
    
    always@(posedge clk or negedge rstn)
    if(!rstn)
        counter <= 0;
    else if(counter == 24999999)
    //else if(counter == 24999)
        counter <= 0;
    else
        counter <= counter + 1'd1;
        
    always@(posedge clk or negedge rstn)
    if(!rstn)
        led <= 8'b0000_0001;
    else if(counter == 24999999)begin
    //else if(counter == 24999)begin
        if(led == 8'b1000_0000)
            led <= 8'b0000_0001;
        else
            led <= led << 1;
    end
    else
        led <= led;
        
endmodule

仿真代码:

`timescale 1ns/1ns

module led_run_tb();

    reg clk;
    reg rstn;
    wire[7:0] led;
    
    led_run led_run(
        .clk(clk),
        .rstn(rstn),
        .led(led)
    );
    
    initial clk = 1;
    always #10 clk = !clk;
    
    initial begin
        rstn = 0;
        #201;
        rstn = 1;
        #4000000;
        $stop;
    end

endmodule

仿真波形:

1.2 方法2:利用位拼接{led[6:0], led[7]}实现循环移位

设计代码

该方法应用场景不多,了解即可。

module led_run_1(
    clk,
    rstn,
    led
);
    input clk;
    input rstn;
    output reg[7:0]  led;
    
    reg[25:0] counter;
    
    always@(posedge clk or negedge rstn)
    if(!rstn)
        counter <= 0;
    else if(counter == 24999999)
    //else if(counter == 24999)
        counter <= 0;
    else
        counter <= counter + 1'd1;
        
    always@(posedge clk or negedge rstn)
    if(!rstn)
        led <= 8'b0000_0001;
    else if(counter == 24999999)begin
    //else if(counter == 24999)
        led <= {led[6:0], led[7]};
    else
        led <= led;
        
endmodule

1.3 方法3:调用其他模块

设计代码

思路:用计数器产生8种状态,然后再把这8种状态拿去用三八译码器译码,就刚好能够去对应点亮8个led灯。

  1. 调用了底层模块3_8译码器后(3位输入[2:0],八位输出8'b0000_0001),顶层led_run_2的输出led的数据类型需要由reg变为wire形(或者不写wire)
  2. 模块的调用与tb里的调用方式一样,做好对应端口的连接即可。
module led_run_2(
    clk,
    rstn,
    led
);
    input clk;
    input rstn;
    output wire[7:0]  led; //注意1
    
    reg[25:0] counter;
    
    always@(posedge clk or negedge rstn)
    if(!rstn)
        counter <= 0;
    else if(counter == 24999999)
    //else if(counter == 24999)
        counter <= 0;
    else
        counter <= counter + 1'd1;
        
        
    reg[2:0] counter2;
    
    always@(posedge clk or negedge rstn)
    if(!rstn)
        counter2 <= 0;
    else if(counter == 24999999)
    //else if(counter == 24999)
        counter2 <= counter2 + 1'd1;
       
    decoder_3_8 decoder_3_8( //注意2
        .a(counter2[2]),
        .b(counter2[1]),
        .c(counter2[0]),
        .out(led)
);
          
        
endmodule

调用方法:

05. 2. 参数化设计

设计代码

  1. 将24999999用参数代替,好处1是增加代码复用性与可读性。好处2是我们可以在板级验证的时候使用24999999,在写tb做调试的时候将参数改为2499,节约仿真时间
module led_run(
    clk,
    rstn,
    led
);

    parameter MCNT = 25'd24999999; //注意1
    input clk;
    input rstn;
    output reg[7:0]  led;
    
    reg[25:0] counter;
    
    always@(posedge clk or negedge rstn)
    if(!rstn)
        counter <= 0;
    else if(counter == MCNT)
    //else if(counter == 24999)
        counter <= 0;
    else
        counter <= counter + 1'd1;
        
    always@(posedge clk or negedge rstn)
    if(!rstn)
        led <= 8'b0000_0001;
    else if(counter == MCNT)begin
    //else if(counter == 24999)begin
        if(led == 8'b1000_0000)
            led <= 8'b0000_0001;
        else
            led <= led << 1;
    end
    else
        led <= led;
        
endmodule

仿真代码

  1. 写法一,修改例化后的模块参数,defparam led_run_inst.MCNT = 2499;
  2. 写法二,例化前修改module,led_run里的参数
`timescale 1ns/1ns

module led_run_tb();

    reg clk;
    reg rstn;
    wire[7:0] led;
    
    
    led_run led_run_inst(
        .clk(clk),
        .rstn(rstn),
        .led(led)
    );
    defparam led_run_inst.MCNT = 2499; //写法一
    
    initial clk = 1;
    always #10 clk = !clk;
    
    initial begin
        rstn = 0;
        #201;
        rstn = 1;
        #4000000;
        $stop;
    end

endmodule

`timescale 1ns/1ns

module led_run_tb();

    reg clk;
    reg rstn;
    wire[7:0] led;
    
    
    led_run //写法二
    #(
        .MCNT(2499)
      )
    led_run_inst(
        .clk(clk),
        .rstn(rstn),
        .led(led)
    );
  
    
    initial clk = 1;
    always #10 clk = !clk;
    
    initial begin
        rstn = 0;
        #201;
        rstn = 1;
        #4000000;
        $stop;
    end

endmodule

仿真波形

06 使用参数化的设计实现模块的重用

让八个led灯分别以不同的频率闪烁

思路:使用八个led灯闪烁模块,为了简化,我们分别以0.1s,0.2s,0.3s,0.4s让四个led闪烁。

1.设计代码

  1. 先构建一个led闪烁的设计代码,再给与不同的计数参数例化4次即可
module led_run8(
    clk,
    rstn,
    led
);
    parameter MCNT = 24999999;
    input clk;
    input rstn;
    output led;
    
    reg[25:0] counter;
    reg led;
    always@(posedge clk or negedge rstn)
    if(!rstn)
        counter <= 0;
    else if(counter == MCNT)
        counter <= 0;
    else
        counter <= counter + 1'd1;
        
    always@(posedge clk or negedge rstn)
    if(!rstn)
        led <= 0;
    else if(counter == MCNT)
        led <= !led;

endmodule
  1.  例化4个模块,使用参数化的设计实现模块的重用
module led_run8_test(
    clk,
    rstn,
    led
);
    input clk;
    input rstn;
    output wire[3:0] led;
    
    
    led_run8 led_run8_inst0(
        .clk(clk),
        .rstn(rstn),
        .led(led[0])
    );
    defparam led_run8_inst0.MCNT = 25'd2499999;
    
    
    led_run8 led_run8_inst1(
        .clk(clk),
        .rstn(rstn),
        .led(led[1])
    );
    defparam led_run8_inst1.MCNT = 25'd4999999;
    
    
    led_run8 led_run8_inst2(
        .clk(clk),
        .rstn(rstn),
        .led(led[2])
    );
    defparam led_run8_inst2.MCNT = 25'd7499999;
    
    
    led_run8 led_run8_inst3(
        .clk(clk),
        .rstn(rstn),
        .led(led[3])
    );
    defparam led_run8_inst3.MCNT = 25'd9999999;
    



endmodule

 2.仿真代码

`timescale 1ns/1ns

module led_run8_test_tb();

    reg clk;
    reg rstn;
    wire[3:0] led;
    
    
    led_run8_test led_run8_test_inst(
        .clk(clk),
        .rstn(rstn),
        .led(led)
    );
    
    initial clk = 1;
    always #10 clk = !clk;
    
    initial begin
        rstn = 0;
        #201;
        rstn = 1;
        #400000000;
        $stop;
    end

endmodule

 3.仿真波形

4.布置引脚(通过代码来布置引脚)

 

 

到此布置引脚就布置好了,后续生成bit流文件,打开硬件管理器之后就可以板级验证了。


http://www.kler.cn/a/232071.html

相关文章:

  • PostgreSQL TRUNCATE TABLE
  • C++创建型设计模式体现出的面向对象设计原则
  • FreeSWITCH chat 得到的是 Error! Message Not Sent
  • Linux驱动开发第2步_“物理内存”和“虚拟内存”的映射
  • 如何在 Ubuntu 上安装 Jellyfin 媒体服务器
  • python:用 sklearn 构建 K-Means 聚类模型
  • 【Django-ninja】在django ninja中处理异常
  • Java代码实现基数排序算法(附带源码)
  • 计算机设计大赛 深度学习 机器视觉 人脸识别系统 - opencv python
  • TCP 传输控制协议
  • JenkinsGitLab完成自动化构建部署
  • 2024.2.6
  • 二叉树中的最大路径和
  • mysql学习打卡day22
  • 20240204金融读报1分钟小得
  • 23种设计模式之单例模式
  • Java+微信小程序实现智慧家政系统 JAVA+Vue+SpringBoot+MySQL
  • JVM体系
  • automative
  • 阿里云游戏服务器多少钱一个月?
  • Netty的常用组件及线程模型设计(一)
  • Redis(02)——事务管理
  • 摘录笔记——2024年2月5日
  • 【RPA】浅谈RPA技术及其应用
  • 设计模式2-对象池模式
  • 机器人学、机器视觉与控制 上机笔记(第一版译文版 2.1章节)