RTL Design/Verilog 연습
10kHz인 PWM 설계 (Duty ratio stage 128단계) - (1)
유로 청년
2024. 8. 11. 14:03
1. Duty ratio를 128단계로 나눈 10kHz PWM 설계
- LED의 밝기를 128단계로 나누어 컨트롤하기 위해 Duty ratio를 128단계로 나누어 컨트롤 할 수 있는 PWM 설계한다.
- Duty ratio를 128단계 나누어 컨트롤하기 위해서 128 분주화, 78.125 분주화, 총 2번의 분주를 할 것이다.
- Duty ratio를 128단계로 나눈 10kHz PWM에 대한 자세한 설명은 아래 게시글 참고하길 바란다.
https://jbhdeve.tistory.com/284
Verilog RTL 설계(7월 31일 - 3, PWM - 3)
1. LED의 밝기를 128단계로 나누어 컨트롤하기.이번에는 LED의 밝기를 128단계로 나누어 컨트롤 할 수 있도록 모듈 설계해보도록 하겠다.이를 통해 "왜 2단계로 나누어 Prescaling을 진행하는가?"를 정
jbhdeve.tistory.com
2. 소스 코드
< Source, Edge detector >
// Edge detector
module edge_detector (
input clk, reset_p,
input cp,
output n_edge, p_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, Duty ratio를 128단계 나눈 10kHz PWM >
module PWM_cntr(
input clk, reset_p,
input [6:0] stage,
output pwm );
// Declare parameter
parameter sys_clk = 100_000_000; // Clock Pulse의 주파수
parameter duty_stage = 128; // Duty ratio 128 stage
parameter pwm_freq = 10_000; // PWM Frequency = 10kHz
// 10kHz PWM을 만들기 위해서는 몇 분주화를 해야 하는가?
parameter temp = sys_clk / duty_stage / pwm_freq;
parameter temp_half = temp / 2;
// 10kHz 주파수를 갖는 PWM를 만들기 위한 78.125 분주화.
reg [6:0] cnt_sysclk;
always @(posedge clk or posedge reset_p) begin
if(reset_p) cnt_sysclk = 0;
else begin
if(cnt_sysclk >= temp - 1) cnt_sysclk = 0;
else cnt_sysclk = cnt_sysclk + 1;
end
end
wire temp_freq;
assign temp_freq = (cnt_sysclk < temp_half) ? 1 : 0;
// Get one cycle pulse of temp_freq.
wire temp_freq_nedge;
edge_detector edge_detector_0 (.clk(clk), .reset_p(reset_p), .cp(temp_freq), .n_edge(temp_freq_nedge));
// LED의 밝기를 128단계로 나누어 컨트롤 하기 위해서
// temp_freq_nedge가 활성화되면 128분주화한다.
reg [6:0] cnt_pwm;
always @(posedge clk or posedge reset_p) begin
if(reset_p) cnt_pwm = 0;
else if(temp_freq_nedge) cnt_pwm = cnt_pwm + 1;
end
// 입력 받은 duty ratio만큼 duty ratio를 갖는 pwm 생성
assign pwm = (cnt_pwm < stage) ? 1 : 0;
endmodule
3. Simulation
< Duty ratio = 50 >
- Duty ratio = {(139us - 100us) / 100us} * 128 = 49.92 = 50 임을 확인할 수 있다.
< Duty ratio = 100 >
- Duty ratio = {(177.708us - 100.465us) / 100us} * 128 = 98.871 = 100 임을 확인할 수 있다.