时序逻辑电路 计数器的实现
1 D触发器
分析:
特性:输出端Q只在CK处于上升沿的时候变化
图中波形的形成过程:
- 当D处于高电平时,CK未处于上升沿时,Q仍处于低电平
- 当CK来到上升沿,Q需要根据D发生变化,由于D是高电平,所以Q要从低电平变化成高电平
- D从高电平变化成低电平,但是此时CK未来到上升沿,所以Q不随着D变化(虽然D变了,Q仍保持刚刚的状态——存储功能)
- CK来到上升沿,此时D又恢复了高电平,所以Q不变
; 2 计数器
原理:加法器基本结构图
这样就能实现 每一个时序上升沿,计数器结果都加1
今天我们的任务是:
设计一个以1秒频率闪烁的LED灯(亮灭各500ms)
怎么知道500ms亮,500ms灭呢?
- 我们就需要一个计数器, 计数到什么时候到了500ms
- 时钟的频率我们设置为
50MHz 20ns
,也就是两个上升沿(一个周期)的时间是20ns
- 每到一个上升沿,计数器的值加一次
- 由于500ms亮和灭,所以我们需要计数器计数 500ms/20ns = 25000000次
- 而一个四位计数器肯定计数不了这么多的值,那么需要多少位呢?
- 源代码
module led_flash(
clk,
reset_n,//reset是复位信号, _n 表示低电平有效,也就是低电平时复位
led
);
input clk;
input reset_n;
output reg led;
reg [24:0] counter;//25位计数器
always@(posedge clk or negedge reset_n) //当clk处于上升沿或者reset处于下降沿的时候下面的代码就生效
if(!reset_n) // if(reset_n == 0)
counter
仿真代码
`timescale 1ns / 1ps
module led_flash_tb(
);
reg clk;
reg reset_n;
wire led;
led_flash UUT(
.clk(clk),
.reset_n(reset_n),
.led(led)
);
initial clk = 1;
always #10 clk =! clk;
initial begin
reset_n = 0;
#201; //避开上升沿
reset_n = 1;
#20_0000_0000; // 2s
end
endmodule
- 仿真
从仿真的结果看
比预想的500ms 多了 20ns
原因是这里如果想计数2500_0000次,应该写2499_9999
这里 以计数到4为例,如果要计数到4的话,实际上不是计数了4次,而是5次
- 0-1
- 1-2
- 2-3
- 3-4
- 4-0
所以应该改为 2500_0000-1
改过之后 就可以了
改过之后 就可以了
Original: https://blog.csdn.net/Living_Amethyst/article/details/127821308
Author: Living_Amethyst
Title: 【FPGA】时序逻辑电路——基于计数器实现一个以1秒频率闪烁的LED灯
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/659467/
转载文章受原作者版权保护。转载请注明原作者出处!