刷题推荐
链接: Verilog刷题
1,实验简介
时序逻辑电路分为很多种。本次实验以最常用的计数器为例学习简单的时序逻辑电路设计。此次设计一个二进制计数器,使开发板上的LED1状态每500ms翻转一次。开发板上晶振为50MHZ,也就是说时钟周期为20ns,可以计算出500ms = 500_000_000ns/20ns = 25_000_000,即需要计数器计数25_000_000,也就是需要一个至少25位的寄存器(225 > 25_000_000 > 224)。
2,实验环境
vivado 2019.1
黑金AX7035开发板
3,实验原理
计数器的核心元件是触发器,基本功能是对脉冲进行技术,其所能记忆脉冲最大的数目称为该计数器的模/值。计数器常用在分频、定时等。计数器种类很多,按计数方式可以分为二进制计数器、十进制计数器等;按触发器的时钟脉冲信号来源分为同步计数器和异步计数器。按计数器增减分为加法计数器、减法计数器和可逆计数器。
开发板LED硬件电路如图所示
可以看出控制端输出低电平时LED亮。只需要每当计数器值记满后翻转LED控制端即可。
4,程序设计
由上面分析可以得到计数器模块的接口图及接口功能描述
接口名称 | I/O | 功能描述 |
---|---|---|
sys_clk | I | 模块工作时钟50MHZ |
rst_n | I | 模块复位 |
led | I | LED |
4.1,vivado工程创建【跳过】
4.2,编写计数器的Verilog代码
`timescale 1ns / 1ps
module counter
(
input sys_clk,
input rst_n,
output led
);
parameter count = 24_999_999;
reg led;
reg [24:0] cnt;
assign rst = ~rst_n;
always@(posedge sys_clk or posedge rst)
begin
if(rst)
cnt <= 25'd0;
else if(cnt == count)
cnt <= 25'd0;
else
cnt <= cnt +1'b1;
end
always@(posedge sys_clk or posedge rst)
begin
if(rst)
led <= 1'b1;
else if(cnt == count)
led <= ~led;
else
led <= led;
end
endmodule
4.3,vivado仿真验证
1,编写仿真程序,control+s保存好代码;
仿真激励产生一个周期为20ns的时钟sys_clk和复位信号,并例化了counter.v
`timescale 1ns / 1ns
`define CLOCK_PERIOD 20
module vtf_counter();
reg sys_clk;
reg rst_n;
wire led;
//defparam counter.count = 24_999;
counter counter(
.sys_clk(sys_clk),
.rst_n(rst_n),
.led(led)
);
initial sys_clk = 1;
always #(`CLOCK_PERIOD/2)
sys_clk =~sys_clk;
initial begin
rst_n = 1'b0;
#(`CLOCK_PERIOD * 200 + 1);
rst_n = 1'b1;
#2000000000;
$stop;
end
endmodule
可以看到如图所示的波形。可以看出输入信号sys_clk和rst_n每一时刻的状态与仿真文件的赋值一致,输出信号led与理论一致。最终得出逻辑代码复核既定的设计要求。
4.4,添加XDC管脚约束文件【跳过】
因为是时序逻辑电路,需要对时钟约束。具体约束过程第一个实验有讲到。
4.5,下载和Flash固化【跳过】
想加快上电后程序启动,可以在xdc文件添加以下几行代码,目的是为了提高SPI FLASH的读写时钟,其中前面两条设置QSPI FLASH的数据宽度和配置模式,后面一条是配置速度,这个值越大,速度越快。修改好的xdc文件需要重新编译,再次重新生成bit和bin文件。
set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]
set_property CONFIG_MODE SPIx4 [current_design]
set_property BITSTREAM.CONFIG.CONFIGRATE 50 [current_design]