一、设计目标
每隔10ms,让led灯的一个8状态执行一次(每个状态的变化时间小一点,方便测试,比如设置为10us)。对于这里10ms,并非是8个状态完成后再间隔10ms,而是10ms为一个周期,即为一个循环。
二、设计思路
按照8状态可循环设计思路,但是由于需要间隔时间,故加入标志为EN,EN的作用即是控制counter和counter2是否计数,因为在间隔时间以内,我们只能使counter0计数,因此必须使counter和counter2停止计数。那么可以使用EN为1或0来进行控制。
三、设计代码
module counter_led6(clk,reset_n,ctrl,Time,led
);
input clk;
input reset_n;
input [7:0] ctrl;
input [31:0] Time;
output reg led;
reg [31:0]counter;
reg EN;
reg [2:0]counter2;
reg [18:0] counter0;
always@(posedge clk or negedge reset_n)
if(!reset_n)
counter0 <=0;
else if(counter0 == 500000 -1)
counter0 <=0;
else
counter0 <= counter0 + 1'b1;
always@(posedge clk or negedge reset_n)
if(!reset_n)
EN <=0;
else if(counter0 == 0)
EN <=1;
//这里的if语句之所以有两个条件,是为了防止第7个状态丢失
else if((counter2 == 7)&&(counter == Time -1))
EN <=0;
always@(posedge clk or negedge reset_n)
if(!reset_n)
counter <=0;
else if(EN)begin
if(counter == Time -1)
counter <=0;
else
counter <= counter + 1'b1;
end
always@(posedge clk or negedge reset_n)
if(!reset_n)
counter2 <=0;
else if(counter == Time -1)
counter2 <= counter2 + 1'b1;
always@(posedge clk or negedge reset_n)
if(!reset_n)
led <=0;
else case(counter2)
3'b000:led <= ctrl[0];
3'b001:led <= ctrl[1];
3'b010:led <= ctrl[2];
3'b011:led <= ctrl[3];
3'b100:led <= ctrl[4];
3'b101:led <= ctrl[5];
3'b110:led <= ctrl[6];
3'b111:led <= ctrl[7];
default:led <= led;
endcase
endmodule
四、测试代码
`timescale 1ns / 1ns
module counter_led6_tb;
reg clk;
reg reset_n;
reg [7:0]ctrl;
reg [31:0]Time;
wire led;
counter_led6 counter_led6_inst(
.led(led),
.clk(clk),
.ctrl(ctrl),
.reset_n(reset_n),
.Time(Time)
);
initial clk=1;
always #10 clk=~clk;
initial begin
ctrl =0;
reset_n=0;
Time=0;
#201;
Time=25000;
reset_n=~reset_n;
ctrl=8'b11100110;
#2000000000;
$stop;
end
endmodule
五、仿真波形
根据波形可知,10ms一个周期,8个状态和一个间隔已经实现。