161 lines
3.6 KiB
Verilog
161 lines
3.6 KiB
Verilog
`timescale 1 ns / 1 ps
|
|
|
|
module breath_gen#
|
|
(
|
|
parameter CLK_PERIOD = 10
|
|
)
|
|
(
|
|
input clk ,
|
|
input rst_n ,
|
|
|
|
input enable ,
|
|
output pwm
|
|
);
|
|
|
|
|
|
//*****************************************************************************
|
|
// localparam definition
|
|
//*****************************************************************************
|
|
localparam PWM_PERIOD = 200000/CLK_PERIOD;
|
|
localparam T_MS = 1000000/CLK_PERIOD;
|
|
|
|
localparam IDLE = 4'd0;
|
|
localparam UP_ST = 4'd1;
|
|
localparam PEAK_ST = 4'd2;
|
|
localparam DOWN_ST = 4'd3;
|
|
localparam REST_ST = 4'd4;
|
|
|
|
localparam T_UP_MS = 2000;//2000
|
|
localparam T_PEAK_MS = 1;//500
|
|
localparam T_DOWN_MS = 2000;//2000
|
|
localparam T_REST_MS = 200;//200
|
|
|
|
localparam STRENGTH = PWM_PERIOD;
|
|
localparam T_UP_STEP = STRENGTH/T_UP_MS;
|
|
localparam T_UP_MAX = T_UP_STEP*T_UP_MS;
|
|
localparam T_DOWN_STEP = T_UP_MAX/T_DOWN_MS;
|
|
localparam T_DOWN_MAX = T_DOWN_STEP*T_DOWN_MS;
|
|
|
|
|
|
|
|
//*****************************************************************************
|
|
// Internal register and wire declarations
|
|
//*****************************************************************************
|
|
reg [ 4-1:0] cstate ;
|
|
reg [ 4-1:0] nstate ;
|
|
|
|
reg [28-1:0] clk_cnt ;
|
|
reg pulse_ms ;
|
|
reg [16-1:0] ms_cnt ;
|
|
|
|
reg [16-1:0] breath_data ;
|
|
|
|
//*****************************************************************************
|
|
// Instantiation
|
|
//*****************************************************************************
|
|
pwm_gen#
|
|
(
|
|
.DATA_WIDTH ( 16 )
|
|
)
|
|
u_pwm_gen
|
|
(
|
|
.clk ( clk ),
|
|
.rst_n ( rst_n ),
|
|
|
|
.enable ( enable ),
|
|
.period ( PWM_PERIOD ),
|
|
.duty ( breath_data ),
|
|
.pwm ( pwm )
|
|
);
|
|
|
|
//*****************************************************************************
|
|
always @ ( posedge clk or negedge rst_n ) begin
|
|
if( !rst_n )
|
|
clk_cnt <= 0;
|
|
else if ( ~enable )
|
|
clk_cnt <= 0;
|
|
else if ( clk_cnt != T_MS - 1 )
|
|
clk_cnt <= clk_cnt + 1'b1;
|
|
else
|
|
clk_cnt <= 0;
|
|
end
|
|
|
|
always @ ( posedge clk or negedge rst_n ) begin
|
|
if( !rst_n )
|
|
pulse_ms <= 1'b0;
|
|
else if ( clk_cnt == T_MS - 1 )
|
|
pulse_ms <= 1'b1;
|
|
else
|
|
pulse_ms <= 1'b0;
|
|
end
|
|
|
|
always@( posedge clk or negedge rst_n ) begin
|
|
if( !rst_n ) cstate <= IDLE;
|
|
else if (~enable) cstate <= IDLE;
|
|
else cstate <= nstate;
|
|
end
|
|
|
|
always@( * ) begin
|
|
case ( cstate )
|
|
IDLE:
|
|
if ( enable )
|
|
nstate <= UP_ST;
|
|
else
|
|
nstate <= IDLE;
|
|
UP_ST:
|
|
if( ms_cnt == T_UP_MS )
|
|
nstate <= PEAK_ST;
|
|
else
|
|
nstate <= UP_ST;
|
|
PEAK_ST:
|
|
if( ms_cnt == T_PEAK_MS )
|
|
nstate <= DOWN_ST;
|
|
else
|
|
nstate <= PEAK_ST;
|
|
DOWN_ST:
|
|
if( ms_cnt == T_DOWN_MS )
|
|
nstate <= REST_ST;
|
|
else
|
|
nstate <= DOWN_ST;
|
|
REST_ST:
|
|
if( ms_cnt == T_REST_MS )
|
|
nstate <= UP_ST;
|
|
else
|
|
nstate <= REST_ST;
|
|
default:
|
|
nstate <= IDLE;
|
|
endcase
|
|
end
|
|
|
|
always @ ( posedge clk or negedge rst_n ) begin
|
|
if( !rst_n )
|
|
ms_cnt <= 0;
|
|
else if ( cstate != nstate )
|
|
ms_cnt <= 0;
|
|
else if ( pulse_ms )
|
|
ms_cnt <= ms_cnt + 1'b1;
|
|
end
|
|
|
|
always @ ( posedge clk or negedge rst_n ) begin
|
|
if( !rst_n )
|
|
breath_data <= 0;
|
|
else if (cstate == IDLE)
|
|
breath_data <= 0;
|
|
else if ( pulse_ms && cstate == UP_ST )
|
|
breath_data <= breath_data + T_UP_STEP;
|
|
else if ( pulse_ms && cstate == PEAK_ST )
|
|
breath_data <= breath_data;
|
|
else if ( pulse_ms && cstate == DOWN_ST )
|
|
breath_data <= breath_data - T_DOWN_STEP;
|
|
else if ( pulse_ms )
|
|
breath_data <= 0;
|
|
|
|
end
|
|
|
|
//*****************************************************************************
|
|
// Wire assignment
|
|
//*****************************************************************************
|
|
|
|
|
|
endmodule
|