Project02_BREATH_LED

 

RTL代码
module breath_led #
(
    parameter   CLOCK_FRQ = 50_000_000,                             // 输入时钟频率50M,对应1 Sec
    parameter   PWM_FRQ = 1000,                                     // PWM频率1K
    parameter   BREATH_ERIOD = 2,                                   // 呼吸周期 2 Sec
    parameter   SET_COMPARE_FRQ = 1000,                             // 比较输出频率 1K
    parameter   PWM_COUNTER_MAX = CLOCK_FRQ/PWM_FRQ,                // PWM发生计数最大值,50_000;一个PWM方波周期 1ms,期间占空比会变化
    parameter   BREATH_COUNTER_MAX = CLOCK_FRQ*BREATH_ERIOD,        // 呼吸计数最大值,100_000_000;2s
    parameter   SET_COMPARE_COUNTER_MAX = CLOCK_FRQ/SET_COMPARE_FRQ,// 设置的比较计数最大值,50_000;1ms
    parameter   COMPARE_VALUE_STEP = PWM_COUNTER_MAX/SET_COMPARE_FRQ// 比较值的步长50,对应1us;
)
(
    input wire clk,
    input wire rstn,
    output wire [3:0]led
);	
reg [31:0]counter_pwm;
reg [31:0]counter_breath;
reg [31:0]counter_compare;
reg [31:0]compare_value;
reg pwm_period_clk_view;                // 没有实际作用
reg breath_period_clk_view;             // 没有实际作用
reg compare_period_clk_view;            // 没有实际作用
reg [3:0]led_number;

reg led_breath_view;
reg breath_dir;
reg [3:0]led_reg;
assign	led = led_reg;

//led的值输出,4路译码器
always @(posedge clk or negedge rstn)
begin
	if(rstn==0)led_reg<=0;
	case (led_number)
	4'b000:	led_reg[0]<=led_breath_view;
	4'b001:	led_reg[1]<=led_breath_view;
	4'b010:	led_reg[2]<=led_breath_view;
	4'b011:	led_reg[3]<=led_breath_view;
	default: led_reg[0]<=led_breath_view;
	endcase 
end

//pwm
always @(posedge clk or negedge rstn)
begin
	if(rstn==0)
	begin
		counter_pwm <= 0;
		pwm_period_clk_view <= 0;
	end
	else 
	begin
		counter_pwm <= counter_pwm + 1;
		if(counter_pwm < compare_value) led_breath_view <= 1; // compare_value对应占空比,LED high active,compare_value越大越亮
		else led_breath_view <= 0;
		if(counter_pwm > PWM_COUNTER_MAX-1)                   // PWM_COUNTER_MAX=50_000,对应1ms
		begin
			counter_pwm <= 0;
			pwm_period_clk_view <= ~pwm_period_clk_view;     // 二分频,25MHz
		end
	end
end

//led输出逻辑
reg [3:0]led_number_state;
always @(posedge clk or negedge rstn)
begin
	if(rstn==0)
    begin
        led_number=0;
        counter_breath<=0;
        breath_period_clk_view<=0;
        breath_dir<=0;
        led_number_state<=0;
    end
	else 
	begin
		counter_breath <= counter_breath + 1;
		if(counter_breath > BREATH_COUNTER_MAX-1)                     // 每2s间隔,LED强度趋势变化一次;0~2s变强,2~4s变弱
		begin
			counter_breath <= 0;
			breath_period_clk_view <= ~breath_period_clk_view;
			breath_dir <= ~breath_dir;
			if(breath_dir==1)
			begin
				case (led_number_state)
				0:	         begin 	led_number_state=1; led_number=0;	end
				1:	         begin 	led_number_state=2; led_number=1;	end
				2:	         begin 	led_number_state=3; led_number=2;	end
				3:	         begin 	led_number_state=4; led_number=3;	end
				4:	         begin 	led_number_state=5; led_number=2;	end
				5:	         begin 	led_number_state=6; led_number=1;	end
				6:	         begin 	led_number_state=0; led_number=0;	end
                default:     begin 	led_number_state=0; led_number=0;   end
				endcase 
			end
		end
	end
end

//呼吸逻辑和向上向下计数逻辑
always @(posedge clk or negedge rstn)
begin
	if(rstn==0)
		begin
			counter_compare<=0;
			compare_period_clk_view<=0;
			compare_value<=0;
		end
	else 
	begin
		counter_compare<=counter_compare+1;
		if(counter_compare>SET_COMPARE_COUNTER_MAX-1)     // 占空比每隔1ms变化一次
		begin
			counter_compare<=0;
			if(breath_dir==0)                            // 方向0:PWM占空比越来越大,亮度越来越强,强到一定程度肉眼分辨不出
			begin
				if(compare_value < PWM_COUNTER_MAX) compare_value <= compare_value + COMPARE_VALUE_STEP;       // 占空比每次变化1us 
			end
			else if(breath_dir==1)                       // 方向1:PWM占空比越来越小,亮度越来越弱,弱到一定程度肉眼认为是灭的
			begin
				if(compare_value>0)compare_value<=compare_value-COMPARE_VALUE_STEP;
			end
			compare_period_clk_view<=~compare_period_clk_view;
		end
	end
end		
endmodule

 

仿真代码
`timescale 1ns / 1ns
module breath_led_tb();
    
    reg clk_reg;
    reg rstn_reg;
    wire [3:0]led;
    
    wire clk;
    wire rstn;
    
    initial begin
    clk_reg=0;
    rstn_reg=0;
    #10
    rstn_reg=1;
    end
    
    always #10 clk_reg=~clk_reg;
    assign rstn=rstn_reg;
    assign clk=clk_reg;
    breath_led #
    (
    .CLOCK_FRQ(5_000_000)
    )
     breath_led_inst
    (
    .clk(clk),
    .rstn(rstn),
    .led(led)
    );
endmodule

 

 

 

 

posted @ 2023-12-23 16:57  NEWICER  阅读(20)  评论(0)    收藏  举报