【FPGA】verilog语法的学习与应用 —— 位操作 | 参数化设计
  JKTajTC4XWSY 2023年11月15日 25 0


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

学习新语法,争做新青年

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

  • 产生0.5s周期的计数器


文章目录

  • 【FPGA】verilog语法的学习与应用 —— 位操作 | 参数化设计
  • 1. version 1 - 移位法
  • 1.1 设计输入
  • 1.2 功能仿真
  • 1.3 板子调试
  • 2. version 2 - 循环移位
  • 3. version 3 - 3-8译码器
  • 4. 参数化设计
  • 添加约束文件


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


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

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即可


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

这里例化模块和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…


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

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


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

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


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月15日 0

暂无评论

推荐阅读
JKTajTC4XWSY