完成任务: 在流水灯基础上加入pwm呼吸灯设计,关于pwm呼吸灯设计可以看博主上一篇博客PWM呼吸灯设计 ,开发板上灯每两秒进行一次切换,每一个的亮灭间隔为一秒。
代码参考:
module pwm_led_change(input wire clk ,input wire rst_n ,output reg [3:0] led
);parameter TIME_US = 6'd49;//50*20ns 1us
parameter TIME_MS = 10'd999;//1000ns*1000 1ms
parameter TIME_S = 10'd999;//1000ms*1000 1sreg [5:0] cnt_us;
reg [9:0] cnt_ms;
reg [9:0] cnt_s;
reg [1:0] cnt_2s;
reg [1:0] state;//保存led灯状态
reg flag;//闪烁标志wire add_cnt_us;//us计数器开始计数标志
wire end_cnt_us;//us计数器结束计数标志wire add_cnt_ms;//ms计数器开始计数标志
wire end_cnt_ms;//ms计数器结束计数标志wire add_cnt_s;
wire end_cnt_s;wire end_cnt_2s;//1us计时器
always @(posedge clk or negedge rst_n) beginif(!rst_n) begincnt_us <= 6'd0;endelse if(add_cnt_us) beginif(end_cnt_us) begincnt_us <= 6'd0;endelse begincnt_us <= cnt_us +1'd1;endendelse begincnt_us <= cnt_us;end
endassign add_cnt_us = 1'b1;
assign end_cnt_us = add_cnt_us && (cnt_us == TIME_US);//1ms计时器
always @(posedge clk or negedge rst_n) beginif(!rst_n) begincnt_ms <= 10'd0;endelse if(add_cnt_ms) beginif(end_cnt_ms) begincnt_ms <= 10'd0;endelse begincnt_ms <= cnt_ms + 1'd1;endendelse begincnt_ms <= cnt_ms;end
endassign add_cnt_ms = end_cnt_us;
assign end_cnt_ms = add_cnt_ms && (cnt_ms == TIME_MS);//1s计时器
always @(posedge clk or negedge rst_n) beginif(!rst_n) begincnt_s <= 10'd0;endelse if(add_cnt_s) beginif(end_cnt_s) begincnt_s <= 10'd0;endelse begincnt_s <= cnt_s + 1'd1;endendelse begincnt_s <= cnt_s;end
endassign add_cnt_s = end_cnt_ms;
assign end_cnt_s = add_cnt_s && (cnt_s == TIME_S);//2s计时
always @(posedge clk or negedge rst_n) beginif(!rst_n) begincnt_2s <= 2'd0;endelse if(end_cnt_s)begincnt_2s <= cnt_2s + 1'd1;endelse if(cnt_2s == 2'd2) begincnt_2s <= 2'd0;endelse begincnt_2s <= cnt_2s;end
endassign end_cnt_2s = (cnt_2s == 2'd2);//state状态
always @(posedge clk or negedge rst_n) beginif(!rst_n) beginstate <= 2'd0;endelse if(end_cnt_2s) beginstate <= state + 1'd1;endelse beginstate <= state;end
end//flag值判断
always @(posedge clk or negedge rst_n) beginif(!rst_n) beginflag <= 1'b0;endelse if(end_cnt_s) beginflag <= ~flag ;endelse beginflag <= flag;end
end//led变化
always @(posedge clk or negedge rst_n) beginif(!rst_n) beginled = 4'b0000;endelse begincase(state)2'd0 : beginif(flag == 1'b1) begin//电亮if(cnt_s > cnt_ms) beginled[0] <= 1'b1;led[3:1] <= 3'b000;endelse beginled[0] <= 1'b0;led[3:1] <= 3'b000;endendelse begin//熄灭if(cnt_s > cnt_ms) beginled[0] <= 1'b1;led[3:1] <= 3'b000;endelse beginled[0] <= 1'b1;led[3:1] <= 3'b000;endendend 2'd1 : beginif(flag == 1'b1) begin//电亮if(cnt_s > cnt_ms) beginled[1] <= 1'b1;led[3:2] <= 2'b00;led[0] <= 1'b0;endelse beginled[1] <= 1'b0;led[3:2] <= 2'b00;led[0] <= 1'b0;endendelse begin//熄灭if(cnt_s > cnt_ms) beginled[1] <= 1'b0;led[3:2] <= 2'b00;led[0] <= 1'b0;endelse beginled[1] <= 1'b1;led[3:2] <= 2'b00;led[0] <= 1'b0;endendend2'd2 : beginif(flag == 1'b1) begin//电亮if(cnt_s > cnt_ms) beginled[2] <= 1'b1;led[3] <= 1'b0;led[1:0] <= 2'b0;endelse beginled[2] <= 1'b0;led[3] <= 1'b0;led[1:0] <= 2'b0;endendelse begin//熄灭if(cnt_s > cnt_ms) beginled[2] <= 1'b0;led[3] <= 1'b0;led[1:0] <= 2'b0;endelse beginled[2] <= 1'b1;led[3] <= 1'b0;led[1:0] <= 2'b0;endendend2'd3 : beginif(flag == 1'b1) begin//电亮if(cnt_s > cnt_ms) beginled[3] <= 1'b1;led[2:0] <= 3'b000;endelse beginled[3] <= 1'b0;led[2:0] <= 3'b000;endendelse begin//熄灭if(cnt_s > cnt_ms) beginled[3] <= 1'b0;led[2:0] <= 3'b000;endelse beginled[3] <= 1'b1;led[2:0] <= 3'b000;endendenddefault :led <= 4'b0000;endcaseend
endendmodule
测试文件:
`timescale 1ns/1ns
module pwm_led_change_tb();reg clk;reg rst_n;wire [3:0] led;parameter CYCLE = 20;parameter TIME_US = 5;parameter TIME_MS = 10;parameter TIME_S = 10;always #(CYCLE/2) clk = ~clk;initial beginclk = 1'b0;rst_n = 1'b0;#(CYCLE);rst_n = 1'b1;#((TIME_US + 1)*(TIME_MS + 1)*(TIME_S + 1)*CYCLE*2*4);$stop;endpwm_led_change #(.TIME_US (TIME_US),.TIME_MS (TIME_MS),.TIME_S (TIME_S))u_pwm_led_change(.clk (clk),.rst_n (rst_n),.led (led));endmodule
我们通过modelsim仿真结果如下:
结果展示: