在开发板中,有一个内置的时钟周期,为100MHZ,我们需要使用这样一个时钟信号来设计一个1HZ的流水灯(使用8个led灯),也就是一秒钟有一个灯是亮起的,依次从左到右。
另外还有一个低有效的复位使能端、一个同步保持使能(有效时流水灯亮起状况不变)
首先,1HZ和100MHZ的时钟周期需要进行转换,然后利用新的时钟信号进行led灯信号变更即可。
思路是这样的,既然是100MHZ,也就是时钟周期,那么我们就需要进行计数,当计数到10^8时,才是一个新的时钟信号的一个周期;但是我们知道时钟信号是会有一个高低电平翻转的,也就是说当计数到10^8的一半时,需要有一个信号翻转。
分频就是将原来高频率的周期转变为低频率的周期,通过计数的方式
一个周期包含一次翻转,即在一个周期中,时钟信号有一半时间是1,一半时间是0,才能有上升沿与下降沿检测出来
`timescale 1ns / 1ps
module divider(
input rst_n_i, //一个低有效的复位使能
input clk_i,
output reg clk_o
);
reg [28:0]cnt = 'b0;
always@(posedge clk_i or negedge rst_n_i) begin
if(rst_n_i == 1'b0) //复位使能有效
cnt <= 'b0;
else if(cnt == 9999_9999) //一个周期
cnt <= 'b000;
else //计数器递增
cnt <= cnt + 1'b1;
if(cnt <= 4999_9999 && rst_n_i) //翻转
clk_o <= 1'b1;
else
clk_o <= 1'b0;
end
endmodule
当数到1e8,即0~9999 9999时,分频后的周期过去了一个,就是说在相同的时间内,小周期进行了1e8次,大周期才进一次,每次周期都包含0和1的部分,都是1在周期前半部分,0在周期后半部分.
cnt的位数与被记录的数字(分频大小)有关,分频越大,cnt位数越多
即cnt连接新旧周期,cnt的值确定大周期此时的值,cnt所记录到的最大值决定分频的倍数
cnt与其所能达到的最大值之间的比值,表示大周期此时进行到的百分比
在一半之前,表示大周期还没到一半,大周期此时值为1
此时clk_o信号就是1HZ信号
`timescale 1ns / 1ps
module flowLED(
input clk_i,
input rst_n_i, //低有效
input en_i, //高有效
output reg [7:0]led
);
reg [2:0]middle='b000; //中间变量计数器
always@(posedge clk_i or negedge rst_n_i) begin
if(rst_n_i == 1'b0) //复位使能
begin
middle <= 3'b000;
led <=8'b0000_0000;
end
else if(en_i == 1'b0) //保持使能
led <= led;
else if(middle >= 'b111)
middle <= 1'b0;
else
middle <= middle +1'b1;
case(middle)
3'b000: led = 8'b0000_0001;
3'b001: led = 8'b0000_0010;
3'b010: led = 8'b0000_0100;
3'b011: led = 8'b0000_1000;
3'b100: led = 8'b0001_0000;
3'b101: led = 8'b0010_0000;
3'b110: led = 8'b0100_0000;
3'b111: led = 8'b1000_0000;
endcase
end
endmodule
利用新的时钟信号,设置一个计数器来控制led灯中亮起的部分(其实属于一个38译码器)