RTL Design/Verilog 연습
10kHz인 PWM 설계 (Duty ratio stage 128단계) - (3)
유로 청년
2024. 8. 11. 19:42
1. LED의 밝기를 128단계로 나누어 컨트롤하기
- 이번에는 LED를 켜진 상태를 유지하면서 LED의 밝기를 128단계로 분리 한뒤, 시간 지남에 따라 점차 밝아지도록 설계해보도록 하겠다.
- 소스 코드에 대한 자세한 설명은 아래 게시글을 참고하길 바란다.
https://jbhdeve.tistory.com/285
Verilog RTL 설계(7월 31일 - 4, PWM - 4)
1. Pulse wave의 duty ratio를 128단계로 나누어 컨트롤 하는 모듈을 설계한 뒤, LED를 통한 출력 Pulse wave의 duty ratio를 128단계로 나누어 컨트롤 하는 모듈 >// Duty ratio 128 step controlmodule PWM_prescaling_128_Contro
jbhdeve.tistory.com
2. PWM Control 모듈 소스 코드
< Source, Edge detector >
// Edge detector
module edge_detector (
input clk, reset_p,
input cp,
output p_edge, n_edge );
reg flip_flop_current, flip_flop_old;
always @(posedge clk or posedge reset_p) begin
if(reset_p) begin
flip_flop_current <= 0;
flip_flop_old <= 0;
end
else begin
flip_flop_current <= cp;
flip_flop_old <= flip_flop_current;
end
end
assign p_edge = ({flip_flop_current, flip_flop_old} == 2'b10) ? 1 : 0;
assign n_edge = ({flip_flop_current, flip_flop_old} == 2'b01) ? 1 : 0;
endmodule
< Source, 10kHz PWM의 Duty ratio를 128단계 컨트롤 모듈 >
// PWM Control module
module pwm_cntr(
input clk, reset_p,
input [6:0] duty,
output pwm );
// Declare parameter
parameter clk_freq = 100_000_000;
parameter clk_pwm = 10_000;
parameter duty_stage = 128;
// Declare temp.
parameter temp = clk_freq / clk_pwm / duty_stage;
parameter temp_half = temp / 2;
// 10kHz PWM을 만들기 위해 78분주화 한다.
reg [6:0] cnt_temp;
always @(posedge clk or posedge reset_p) begin
if(reset_p) cnt_temp = 0;
else begin
if(cnt_temp >= temp - 1) cnt_temp = 0;
else cnt_temp = cnt_temp + 1;
end
end
wire temp_pulse;
assign temp_pulse = (cnt_temp < temp_half) ? 0 : 1;
// Get one cycle pulse of temp_pulse
wire temp_pulse_nedge;
edge_detector edge_detector_0 (.clk(clk), .reset_p(reset_p), .cp(temp_pulse), .n_edge(temp_pulse_nedge));
// PWM의 Duty ratio를 128단계로 나누어 컨트롤하기 위해 128분주화
reg [6:0] cnt_pwm;
always @(posedge clk or posedge reset_p) begin
if(reset_p) cnt_pwm = 0;
else cnt_pwm = cnt_pwm + 1;
end
assign pwm = (cnt_pwm < duty) ? 1 : 0;
endmodule
< Source, Top module of LED Control by using PWM >
// Top module
module top_module_led_pwm (
input clk, reset_p,
output pwm );
// Control duty.
reg [31:0] cnt_duty;
always @(posedge clk or posedge reset_p) begin
if(reset_p) cnt_duty = 0;
else cnt_duty = cnt_duty + 1;
end
// Control PWM
pwm_cntr control_pwm (.clk(clk), .reset_p(reset_p), .duty(cnt_duty[31:25]), .pwm(pwm));
endmodule
3. 구현 영상
- 32bit 크기를 갖는 Counter인 cnt_duty는 Clock Pulse를 기준으로 1씩 Counting 된다.
- 이번 구현에서는 cnt_duty의 31번째 bit ~ 25번째 bit를 duty 값으로 주었기 때문에 LED의 밝기가 0단계에서 부터 시작해서 127단계까지 천천히 밝아졌다가 다시 0단계로 돌아오는 데까지 걸리는 시간은 2^32 * 10ns = 42.9496초 소요될 것으로 예상할 수 있다.
- 실험 결과, LED의 밝기가 0단계에서 부터 시작해서 127단계까지 천천히 밝아졌다가 다시 0단계로 돌아오는 데까지 걸리는 시간은 42초 정도가 소요되었다.