5.2 FPGA:基于verilog的LED流水灯设计(多种方法)

目录

设计目标:8个LED灯以每0.5s的速率进行循环闪烁

方法1:移位法实现

设计模块

仿真代码

实验结果

 方法2:循环移位方法

 设计模块

方法3:使用三八译码器实现流水灯

顶层模块

底层模块


设计目标:8个LED灯以每0.5s的速率进行循环闪烁

当仿真时时间长,可以减小设计代码的计数次数,对分析移位功能没有影响。

方法1:移位法实现

设计模块

module led_run(
    Clk,
    Reset_n,
    led
);
    input Clk;
    input Reset_n;
    output reg [7:0]led;
    
    reg [24:0] counter;

    always@(podedge Clk or negedge Reset_n)
    if(!Reset_n)
        counter <= 0;
    else if(counter == 24999999)
        counter <= 0;
    else
        counter <= counter + 1'd1;

    always@(podedge 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;
        

endmoduule

仿真代码

`timescale 1ns/1ns

module led_run_tb();

    reg Clk;
    reg Reset_n;
    wire [7:0]led;

    led_run led_run(
        .Clk(Clk),
        .Reset_n(Reset_n),
        .led(led)
    );

    initial Clk = 1;
    always #10 Clk = ~Clk;

    initial begin
        Reset_n = 0;
        #201;
        Reset_n = 1;
        #4000000000; //延时4s
        $stop;
    end

endmodule

实验结果

 方法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 == 24999999)
    else if(counter == 24999) //500us
        counter <= 0;
    else
        counter <= counter + 1'd1;
        
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        led = 8'b0000_0001;
 //   else if(counter == 24999999)begin
    else if(counter == 24999)
        led <= {led[6:0],led[7]};    //位拼接
    else
        led <= led;
    
endmodule

方法3:使用三八译码器实现流水灯

知识点:1.计数器记满清零。2. 模块间的调用。

在当前模块中调用三八译码器模块,将38译码器的设计模块添加到当前文件夹中,在led_run2.v中通过接口调用三八译码器。

将led_run2.v中的 led 接到三八译码器的 out 端口上时,led 不能再定义为 reg 型,因为三八译码器底层已经将out定义为reg型。底层已经定义了reg型,顶层就不能再定义reg型。 led是由底层模块驱动的,顶层只能定义为wire型。

顶层模块

module led_run2(
    Clk,
    Reset_n,
    led
);
    input Clk;
    input Reset_n;
    output  [7:0] led;
    
    reg [24:0] counter;
    reg [2:0] counter1; //二进制8个状态,3位
    
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        counter <= 0;
//    else if(counter == 24999999)
    else if(counter == 24999) //500us
        counter <= 0;
    else
        counter <= counter + 1'd1;
        
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        counter1 <= 0;
 //   else if(counter == 24999999)
    else if(counter == 24999)
        counter1 <= counter1 + 1'b1;

    decoder_3_8 decoder_3_8(
        .a(counter1[2]),    //counter1[2] 是最高位
        .b(counter1[1]),
        .c(counter1[0]),
        .out(led)       //底层已将out定义为reg型,所以顶层不能再定义成reg型
    );
    
endmodule

底层模块

module decoder_3_8(
    a,
    b,
    c,
    out
);

input a;
input b;
input c;
output reg [7:0] out;
// 2种写法:reg [7:0] out;

//以always块描述的信号赋值,被赋值对象必须定义为reg类型
//{a,b,c}拼接成了一个三位信号

always@(*)begin
    case({a,b,c})
        3'b000: out = 8'b0000_0001;
        3'b001: out = 8'b0000_0010;
        3'b010: out = 8'b0000_0100;
        3'b011: out = 8'b0000_1000;
        3'b100: out = 8'b0001_0000;
        3'b101: out = 8'b0010_0000;
        3'b110: out = 8'b0100_0000;
        3'b111: out = 8'b1000_0000;
    endcase
end

endmodule

defparam写法不能在testbench中生效

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值