网络知识 娱乐 【FPGA】用Verilog语言实现流水灯实验

【FPGA】用Verilog语言实现流水灯实验

目录

  • 一、模块框图
  • 二、波形图
    • 1、时钟与复位信号
    • 2、计数器
    • 3、脉冲信号
    • 4、输出信号
    • 5、理想结果
  • 三、代码部分
    • 1、Verilog代码
      • (1)法1:拼接运算符
      • (2)法2:移位运算符,再取反
    • 2、tb仿真代码
  • 四、仿真波形

一、模块框图

在这里插入图片描述
包含两个输入信号:系统时钟(sys_clk)以及复位信号(sys_rst_n)。
一个输出信号:led_out (因有4个led灯组成流水灯,故位宽为4,每一个比特位控制一个led灯)

二、波形图

1、时钟与复位信号

在这里插入图片描述

2、计数器

因每一个流水灯点亮的时间为0.5s,板子频率为50Mhz(20ns)
0.5s = 5X10^8ns
故计数个数为 (5X10^8)/ 20 = 2.5x10^7
在这里插入图片描述

3、脉冲信号

当计数器计数到最大值减一时,保持一个时钟周期的高脉冲,其余时刻保持低电平
在这里插入图片描述

4、输出信号

当复位信号有效时,对其赋初值为 4’b1110 (第一个灯亮,其余三个灭),并在第一个周期内保持
检测到脉冲标志信号时,值变为4’b1101(第二个灯亮,其余三个灭),并在这一周期内保持
后面同理
在这里插入图片描述

5、理想结果

与led_out波形相对应,间隔为0.5s
在这里插入图片描述

三、代码部分

1、Verilog代码

(1)法1:拼接运算符

在这里插入图片描述

module water_led
#(
  parameter CNT_MAX = 25'd24_999_999   //声明计数最大值参数,24999999二进制为25位
)
(
input wire       sys_clk,
input wire       sys_rst_n,

output reg [3:0] led_out   //端口列表
);
reg [24:0] cnt;
reg cnt_flag;      //声明寄存器

always@(posedge sys_clk or negedge sys_rst_n)     //计数器赋值
    if(sys_rst_n == 1'b0)
	    cnt <= 25'd0;
	 else if (cnt == CNT_MAX)
	    cnt <= 25'd0;
	 else
	    cnt <= cnt + 25'd1;
		 
always@(posedge sys_clk or negedge sys_rst_n)    //脉冲标志信号赋值
    if(sys_rst_n == 1'b0)
	     cnt_flag <= 1'b0;
	 else if (cnt == (CNT_MAX - 25'd1 ))
	     cnt_flag <= 1'b1;
	 else
	     cnt_flag <= 1'b0;
		  
always@(posedge sys_clk or negedge sys_rst_n)  //输出信号赋值
    if(sys_rst_n == 1'b0)
	     led_out <= 4'b1110
	 else if(cnt_flag == 1'b1)
	 led_out <= {led_out[2:0],led_out[3]};   //拼接运算符(例如上一状态为1110,现状态为1101,将上一状态的后三位110放在现状态的前三位,
	 else                                    //上一状态的第一位1放在现状态的最后一位,再将110与1进行拼接运算,即可得到现状态1101)
	     led_out <=  led_out;
		 
endmodule

其中拼接运算符详情见下:
在这里插入图片描述

(2)法2:移位运算符,再取反

先添加led_out_reg [3:0]寄存器
在这里插入图片描述
将输出信号赋值部分的代码进行如下修改,再进行取反
在这里插入图片描述

2、tb仿真代码

在这里插入图片描述

`timescale 1ns/1ns
module tb_water_led();  //端口列表
reg sys_clk;
reg sys_rst_n;

wire [3:0] led_out;     //变量声明

initial
    begin
	    sys_clk = 1'b1;              //赋初值
		 sys_rst_n <= 1'b0;
		 #20
		 sys_rst_n <= 1'b1;
	 end
	 
always #10 sys_clk = ~sys_clk;       //生成时钟

water_led                 //实例化
#(
     .CNT_MAX(25'd24)
)
water_led_inst
(
     .sys_clk(sys_clk),
	  .sys_rst_n(sys_rst_n),
	  
	  .led_out(led_out)
);

endmodule

四、仿真波形

在这里插入图片描述
经分析,与开始手动绘制的波形图吻合,结果正确,此处不再上传上版验证结果。