计数器
计数器(每500ms状态翻转一次)
对应输出LED状态 (每500ms切换一次)
FPGA系统时钟为50Mhz对应周期为20ns
500ms = 500x106ns = 25*106 个FPGA时钟周期
25_000_000(D) ——》25(bit)
逻辑设计 counter
module counter(clk50m,rst_n,led); //端口列表
input clk50m; //50Mhz 系统时钟
input rst_n; //全局复位
output reg led; //led输出
reg [24:0]cnt; //计数器 在 alway 里赋值的 都要写成寄存器类型
//25 000 000次计数器——满载清零,复位清零,时钟上沿计一次
always@(posedge clk50m or negedge rst_n) //时序逻辑的常见形式 以时钟上升沿 和复位信号低电平 为敏感列表
if(rst_n == 1'b0) //复位时
cnt <= 25d'0;
else if(cnt == 25'd24_999_999) //计满时
cnt <= 25d'0;
else //时钟上沿来临时
cnt <= cnt + 1'd1;
//老师这里写的是加上 1'b1 我感觉没什么区别 你十进制加1和二进制加1不都一样吗?
//led的随计数器计满 变化状态
always@(posedge clk50m or negedge rst_n)
if(rst_n == 0) 复位时
led <= 1'b1;
else if(cnt == 25'd24_999_999) //计数器计满时
led <= ~led;
else //时钟沿来临时 对于 led 也就是闲时
led <= led
endmodule
testbench仿真 counter_tb
`timmecale 1ns/1ns //步长与精确度
module counter_tb
reg clk50m1;
reg rst_n1;
wire led1; //3定义桌子上的激励信号和观测信号 激励reg 观测wire
counter u1( //1改名
.clk50m(clk50m1), //2加点 加括号
.rst_n(rst_n1),
.led(led1) //4把3定义的填写在括号里
);
//开始激励~~~
initial clk50m1 = 1; //设置上电时钟初始状态为高
always #10 clk50m1 = ~ckl50m1 ;//每10ns翻转一次
//这里模拟出 FPGA的50m时钟 10ns高+10ns低=20ns = 1/50M
initial begin
rst_n1 = 1'b0;
#200*20;
rst_n1 = 1'b1; //这里模拟出FPGA上电复位时间 为200个时钟周期
#2000_000_000; //延时2000ms 以便观测到
$stop;
//停止模拟
end
endmodule
前仿真
为了速度这里删除了 时钟信号的波形图
红色部分就是我们写的上电复位过程
经过了 上电复位 + 500ms 的时间 LED信号翻转为了低电平
分析代码所对应电路
——》分析 :如何做到的 计数器 从0计数到24 999 999 再清零 这样周 而复始呢
——》我们设定:二选一多路器接收到有效电平时 输出“0”那个输入端。否则 输出另一个,比较器的输入与24 999 999相比较 到了 就输出一个有效电平
——》假设一开始,刚上电,寄存器输入D为0,经过时钟上升沿输出,0小于24999999 所以,比较器的输出是无效电平 ,所以2选1多路器也就接到了无效电平,输出0+1=1。这个1进入寄存器,当下次时钟上升沿来临时,分两路,一路传给比较器进行比较,判断是否达到了 24 999 999 ,发现并没有,比较器输出无效电平。另一路经过加法器 +1=2 进入2选1多路器,在传给寄存器 ,再输出,再比较,直到到了 24999 999 比较器输出了有效电平。
传给二选一多路器,这时候二选一多路器 就输出0 把这个0 传给了 寄存器。计数器也就清零了~
(刚刚学,只能分析成这个德行,估计还是错的~)
分析与综合后选左下角的这个,双击,软件也会帮你自动生成电路的!