FPGA实验1 流水灯
时钟频率与时钟周期计算
\[f=\frac{1}{T}
\]
f是频率 T是周期 时钟周期的计算 1s=1000ms=1000000us=1000000000ns
对于100kHz=100000Hz f= 1000000000/100000 =10000ns
8MHz = 8000kHz=8000000Hz f=1000000000/8000000=125ns
| 时钟频率 | 时钟周期 |
|---|---|
| 100kHz | 10_000ns |
| 1MHz | 1_000ns |
| 8MHz | 125ns |
| 50MHz | 20ns |
| 100MHz | 10ns |
| 125MHz | 8ns |
| 150MHz | 6.667ns |
| 200MHz | 5ns |
led 流水灯 每隔0.2s 闪
20ns对应输入的时钟频率为50MHz (不同开发板,或者硬件设计可能有不同)
0.2s/20ns = 1000_0000
//计数器 counter:0-9999999 (10000000) 通过转换二进制 得到位宽
/*
计数器 counter 一般计数器都是从0开始,例如计数器要计数10000,则需要写成10000-1
计数器 counter-1
16b'0010_0111_0001_0000 = 16d'1_0000
*/
//1001_1000_1001_0110_1000_0000 位宽24 reg [23:0] 位宽N reg [N-1:0]
reg [23:0] counter;
//电路设计 高电平点亮,低电平熄灭
//计数器对系统时钟计数,计时0.2秒
always @(posedge sys_clk or negedge sys_rst_n) begin //检测时钟的上升沿和复位的下降沿
if (!sys_rst_n) //当sys_rst_n 处于复位状态时,计数器重置0 复位信号低有效
counter <= 24'd0;
else if (counter < 24'd1000_0000-1'b1) //计数器开始计数,从0-9999999,自加
counter <= counter + 1'b1;
else
counter <= 24'd0;//计数器达到计数值,置0,
end
//通过移位寄存器控制IO口的高低电平,从而改变LED的显示状态
//0001->0010->0100->1000->0001
always @(posedge sys_clk or negedge sys_rst_n) begin //检测时钟的上升沿和复位的下降沿
if (!sys_rst_n) //当sys_rst_n 处于复位状态时,led1亮,置1
led <= 4'b0001;
else if(counter == 24'd1000_0000-1'b1) //当计数器计数到指定值时,进行操作
led[3:0] <= {led[2:0],led[3]}; //把高位赋给低位进行交换
else
led <= led;
end
计数器模板
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
cnt<= 0;
end
else if(加 1 条件) begin
if(结束条件)
cnt<= 0;
else
cnt<= cnt + 1;
end
end
assign 加 1 条件 = ;
assign 结束条件 = 加 1 条件&&cnt==(计数个数)-1;
/*
工作时钟是 50MHz,时钟周期即 20ns,当计数器计数到 1_000_000_000/20=50_000_000个
1s 计数器计数 50_000_000个周期
*/
parameter Count_MAX = 50_000_000 ; //计数器计数总周期个数
reg [N:0] cnt;//计数变量 N为位宽
//计算 1 秒次数的计数器命名为 cnt0
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
cnt<= 0;
end
else if(add_cnt) begin
if(end_cnt)
cnt<= 0;
else
cnt<= cnt + 1;
end
end
//加 1 条件 add_cnt = 1 则默认为加1条件一直有效
//什么是加1条件 触发条件 根据实际情况
assign add_cnt = 1 ;
assign end_cnt = add_cnt && cnt==(Count_MAX)-1;
reg [25:0] cnt0;
//计数器cnt0:计数1s 加1条件add_cnt0,结束条件end_cnt0
wire add_cnt0 ;
wire end_cnt0 ;
reg [2:0] cnt2;//可以存储8个状态 计数5s
//计数器cnt2:计数5s 加1条件add_cnt2,结束条件end_cnt2
wire add_cnt2 ;
wire end_cnt2 ;
//计数器计数1s
always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n) begin
cnt0 <= 0;
end
else if(add_cnt0) begin
if(end_cnt0)
cnt0 <= 0;
else
cnt0 <= cnt0 + 1;
end
end
assign add_cnt0 = 1 ; //一直处于加1状态
assign end_cnt0 = add_cnt0 && cnt0== 50_000_000 - 1 ; //根据时钟频率计算出 1s需要多少个时钟周期
//计数器计数5s
always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n) begin
cnt2 <= 0;
end
else if(add_cnt2) begin
if(end_cnt2)
cnt2 <= 0;
else
cnt2 <= cnt2 + 1;
end
end
assign add_cnt2 = end_cnt0; //该计数器的加1条件是 1s计数器结束 准备进行下一个1s计数器
assign end_cnt2 = add_cnt2 && cnt2== 5 -1; //根据5s计数器计算出 5s需要多少个1s的计数器
