在开发板中,有一个内置的时钟周期,为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译码器)
