• 【FPGA】verilog语法的学习与应用 —— 位操作 | 参数化设计


    【FPGA】verilog语法的学习与应用 —— 位操作 | 参数化设计

    学习新语法,争做新青年

    计数器实验升级,让8个LED灯每个0.5s的速率循环闪烁,流水灯ahh好久不见~ 去年光这个就把我折磨够呛。。我肉眼可见的脱发就是从那时候开始的。。在那两个月我直接掉了10斤啊喂~ (没节食、没运动、没失恋哈哈哈

    • 产生0.5s周期的计数器

    1. version 1 - 移位法

    1.1 设计输入

    module led_run(
        Clk,
        Reset_n,
        Led
    );
        input Clk;
        input Reset_n;
        output reg[7:0]  Led;
        
        reg[24:0] counter;
        
        always@(posedge Clk or negedge Reset_n)
        if(!Reset_n)
            counter <= 0;
        else if(counter == 24999999)
            counter <= 0;
        else
            counter <= counter + 1'b1; 
        
        always@(posedge Clk or negedge Reset_n)
        if(!Reset_n)
            Led <= 8'b0000_0001;
        else if(counter == 24999999) begin
            if(Led == 8'b1000_0000)
                Led <= 8'b0000_0001;
            else
                Led <= Led << 1;
        end
        else 
            Led <= Led; //当然了,时序逻辑中不加这句话默认保持状态
    endmodule
    

    1.2 功能仿真

    为了避免仿真跑的时间太长,我们ba0.5s替换为0.05s,所以我们姑且把24999999999替换为24999,也就是500ms→500ums。

    `timescale 1ns/1ns
    
    module led_run_tb();
        //激励信号
        reg Clk;
        reg Reset_n;
        wire[7:0] Led;
        
     led_run led_run_inst(  //例化
        //连线
        .Clk(Clk),
        .Reset_n(Reset_n),
        .Led(Led)
    );
        initial Clk = 1;
        always #10 Clk = ~Clk; //一个周期20ns
        
        initial begin
            Reset_n = 0;
            #201;
            Reset_n = 1;
            #4000000; //8*500us = 40000000ns
            $stop;
        end
        
    endmodule
    
    image-20220920092850196

    1.3 板子调试

    别忘了把时间调回来啊喂!不然可看不出流水了~

    是的,我写完这句话就忘调了。。不愧是我

    2. version 2 - 循环移位

    改进移位

    module led_run1(
        Clk,
        Reset_n,
        Led
    );
        input Clk;
        input Reset_n;
        output reg[7:0]  Led;
        
        reg[24:0] counter;
        
        always@(posedge Clk or negedge Reset_n)
        if(!Reset_n)
            counter <= 0;
        else if(counter == 25'd24999999)
        //else if(counter == 25'd24999) 
            counter <= 0;
        else
            counter <= counter + 1'b1; 
        
        always@(posedge Clk or negedge Reset_n)
        if(!Reset_n)
            Led <= 8'b0000_0001;
        else if(counter == 25'd24999999) 
        //else if(counter == 25'd24999) 
            Led <= {Led[6:0], Led[7]};
        else 
            Led <= Led; //当然了,时序逻辑中不加这句话默认保持状态
    endmodule
    
    • Led <= {Led[6:0], Led[7]};
      • {}:位拼接
      • 循环移位

    虽然。。这种写法用的也不多~

    那我们来仿真一下,test bench把例化时名称改一下就ok

    没问题~~

    3. version 3 - 3-8译码器

    引入3-8译码器的逻辑

    模块中调用模块:把文件拷贝过来 → Add files即可

    image-20220921101453857

    这里例化模块和test bench中是一模一样的方法~ 我我我悟了!

    `timescale 1ns/1ns
    
    module led_flash_tb();
        //激励信号
        reg Clk;
        reg Reset_n;
        wire[7:0] Led;
        
     led_run2 led_run_inst(  //例化
        //连线
        .Clk(Clk),
        .Reset_n(Reset_n),
        .Led(Led)
    );
        initial Clk = 1;
        always #10 Clk = ~Clk; //一个周期20ns
        
        initial begin
            Reset_n = 0;
            #201;
            Reset_n = 1;
            #4000000; //8*500ms = 40000000ns
            $stop;
        end
        
    endmodule
    
    • 由于现在Led是由底层模块驱动的,我们在底层已经定义为reg型了,所以顶层要去掉

    4. 参数化设计

    是的,你看到了,我转头就忘了把时间改回来了~

    啊这就相当于C语言中的**#define定义常量**

    我们在led_run中添加 ——

        parameter MCNT = 25'd24999;
    

    并在led_run_tb中这样写:

         led_run led_run_inst(  //例化
            //连线
            .Clk(Clk),
            .Reset_n(Reset_n),
            .Led(Led)
        );    
        defparam led_run_inst.MCNT = 24999;
    

    或者在led_run_tb中这样来写

        led_run2
        #(
            .MCNT(24999)
        )
    	led_run_inst(  //例化
            //连线
            .Clk(Clk),
            .Reset_n(Reset_n),
            .Led(Led)
        );
    

    让4个LED灯以不同的频率进行闪烁

    0.1s, 0.2s, 0.3s, 0.4s…

    image-20220921111113398

    led_flash.v

    module led_flash (
        //端口
        Clk,
        Reset_n, //复位
        Led
    );
        //端口定义
        input Clk;
        input Reset_n;
        output reg Led;
        
        parameter MCNT = 24999999;
        reg[24:0] counter;
        
        always@(posedge Clk or negedge Reset_n)
        if(!Reset_n) 
            counter <= 0;
    	else if(counter == MCNT) 
            counter <= 0;
        else     
            counter <= counter + 1'd1;
            
        always@(posedge Clk or negedge Reset_n)
        if(!Reset_n) 
            Led <=0;
        else if(counter == MCNT) 
            Led <= !Led;
    
    endmodule
    
    

    led_run_8_test.v

    `timescale 1ns / 1ps
    
    module led_run_8_test(
            //端口
            Clk,
            Reset_n, //复位
            Led
        );
        
         //端口定义
         input Clk;
         input Reset_n;
         output[3:0] Led;    
         
        led_flash led_flash_inst0(
            .Clk(Clk),
            .Reset_n(Reset_n), 
            .Led(Led[0])
        );
        defparam led_flash_inst0.MCNT = 2499999;//0.1s
        
         led_flash led_flash_inst1(
            .Clk(Clk),
            .Reset_n(Reset_n), 
            .Led(Led[1])
        );
        defparam led_flash_inst1.MCNT = 4999999;//0.2s
    
        
        led_flash led_flash_inst2(
            .Clk(Clk),
            .Reset_n(Reset_n), 
            .Led(Led[2])
        );
        defparam led_flash_inst2.MCNT = 7499999; //0.3s 150ms = 150000000ns/20ns = 7500000
    
        
         led_flash led_flash_inst3(
            .Clk(Clk),
            .Reset_n(Reset_n), 
            .Led(Led[3])
        );
        defparam led_flash_inst3.MCNT = 9999999; //0.4s 200ms = 200000000/20ns = 10000000
    
       
    endmodule
    

    添加约束文件

    右击,手动设置为target

    image-20220921112522635

    复制之前自动生成的代码,并稍作改动,然后下载到板子上就okk啦~ 就是为了巩固一下参数化设计~~

  • 相关阅读:
    MTO与MTS下的需求不汇总及在排产中的应用
    流體小球加載動畫
    阿宇NVR如何关闭相机的声光警戒音
    VScode mac 一次编辑多行
    【AUTOSAR-CanIf】-2.4-对接收的L-PDU进行数据CheckSum校验
    ubuntu配置yolov5环境
    Java手写双向广度优先和双向广度优先应用拓展案例
    布隆过滤器Moudule安装
    DEVC++崩溃问题暨C语言c++软件相关软件安装教程
    如何避免osg绘制场景时因Z冲突导致绘制重影或不正常
  • 原文地址:https://blog.csdn.net/qq_54851255/article/details/126962676