
1s 주기면 깜빡 깜빡
1ms 이면 다이나믹 구동
주기가 더 짧아지면.....

led도 다이오드, 커패시터 성질있음, 주기가 짧으면 충전되다 방전되다 반복

밝기가 어둡게 켜진것처럼 보인다

펄스폭이 커지면 초록색 밝기로 켜짐

펄스폭이 작아지면, 파란색 펄스는 노란색으로 반응, 더 어두워짐
듀티비에 따라 밝기가 달라짐
module pwm_100step(
input clk, reset_p,
input [6:0] duty, //100단계 //듀티값은 시뮬레이션에서 정해주었다
output pwm);
reg [6:0] cnt_sysclk; //100까지 세는 카운터, 7비트 필요
always @(negedge clk or posedge reset_p)begin //100분주, 10ns->1us
if(reset_p)cnt_sysclk = 0;
else begin
if(cnt_sysclk >= 99) cnt_sysclk = 0;
else cnt_sysclk = cnt_sysclk + 1;
end
end
assign clk_div_100 = (cnt_sysclk < 50) ? 1 : 0; //펄스폭이 반반인 1us짜리 펄스
edge_detector_n ed(
.clk(clk), .reset_p(reset_p), .cp(clk_div_100),
.n_edge(clk_div_100_nedge));
reg [6:0] cnt; //100까지 세는 카운터, 7비트 필요
always @(negedge clk or posedge reset_p)begin //100분주, 1us->100us
if(reset_p)cnt = 0;
else if(clk_div_100_nedge)begin
if(cnt >= 99) cnt = 0; //cnt가 99를넘어 다시 0되면 100us
else cnt = cnt + 1;
end
end
assign pwm = (cnt < duty) ? 1 : 0; //duty값은 시뮬레이션에서 넣어줌
endmodule


always @(negedge clk or posedge reset_p)begin
if(reset_p)cnt = 0;
else if(clk_div_100_nedge)begin
// if(cnt >= 99) cnt = 0;
// else
cnt = cnt + 1; //7비트 cnt의 오버플로우를 이용한 0~127단계 조절
end
end
펄스폭이 작을때 주파수가 최소한 10000Hz는 되어야 led가 깜빡임 없이 켜지는것처럼 보일수있다고 한다
module pwm_100step(
input clk, reset_p,
input [6:0] duty, //100단계
output pwm);
parameter sys_clk_freq = 100_000_000;
parameter pwm_freq = 10_000;
parameter duty_step = 128;
parameter temp = sys_clk_freq / duty_step / pwm_freq;
parameter temp_half = temp / 2;
integer cnt_sysclk; //100까지 세는 카운터,7비트 필요
always @(negedge 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; //주파수를 10000Hz에 맞춰놨고 주파수에 맞추기 위한 분주를 하는 것
end
end
assign clk_div_100 = (cnt_sysclk < temp_half) ? 1 : 0;
edge_detector_n ed(
.clk(clk), .reset_p(reset_p), .cp(clk_div_100),
.n_edge(clk_div_100_nedge));
reg [6:0] cnt; //100까지 세는 카운터,7비트 필요
always @(negedge clk or posedge reset_p)begin
if(reset_p)cnt = 0;
else if(clk_div_100_nedge)begin
//if(cnt >= 99) cnt = 0;
//else
cnt = cnt + 1; //오버플로우를 이용한 127단계 조절
end
end
assign pwm = (cnt < duty) ? 1 : 0;
endmodule
스위치로 조절하기 위한 탑모듈
module led_pwm_top(
input clk, reset_p,
input [6:0] duty,
output pwm);
pwm_100step pwm_inst(.clk(clk), .reset_p(reset_p), .duty(duty), .pwm(pwm));
endmodule
xdc 변경
# LEDs
set_property -dict { PACKAGE_PIN U16 IOSTANDARD LVCMOS33 } [get_ports {pwm}]
-----------------------------------------------
# Switches
set_property -dict { PACKAGE_PIN V17 IOSTANDARD LVCMOS33 } [get_ports {duty[0]}]
set_property -dict { PACKAGE_PIN V16 IOSTANDARD LVCMOS33 } [get_ports {duty[1]}]
set_property -dict { PACKAGE_PIN W16 IOSTANDARD LVCMOS33 } [get_ports {duty[2]}]
set_property -dict { PACKAGE_PIN W17 IOSTANDARD LVCMOS33 } [get_ports {duty[3]}]
set_property -dict { PACKAGE_PIN W15 IOSTANDARD LVCMOS33 } [get_ports {duty[4]}]
set_property -dict { PACKAGE_PIN V15 IOSTANDARD LVCMOS33 } [get_ports {duty[5]}]
set_property -dict { PACKAGE_PIN W14 IOSTANDARD LVCMOS33 } [get_ports {duty[6]}]
클락에의한 자동 밝기 조절을 위한 탑모듈
module led_pwm_top_2(
input clk, reset_p,
output pwm);
reg [31:0] clk_div;
always @(posedge clk)clk_div = clk_div + 1;
pwm_100step pwm_inst(.clk(clk), .reset_p(reset_p), .duty(clk_div[27:21]), .pwm(pwm));
endmodule
임시
module pwm_100step (
input clk, reset_p,
input [6:0] duty,
output pwm);
// Prescaler 100
parameter sys_clk = 100_000_000; // System Clock Pulse 주파수
parameter pwm_freq = 10_000; // LED가 연속적으로 보여지기 위한 주파수
parameter duty_step = 128; // Duty ratio의 단계
parameter temp = sys_clk / duty_step / pwm_freq;
parameter temp_half = temp / 2;
integer cnt_sysclk;
wire clk_div100_nedge;
always @(negedge 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
assign clk_div_100 = (cnt_sysclk < temp_half) ? 0 : 1;
edge_detector_n edge_detector_0 (.clk(clk), .reset_p(reset_p), .cp(clk_div_100), .n_edge(clk_div100_nedge));
// Prescaler 128
reg [6:0] cnt;
always @(negedge clk or posedge reset_p)begin
if(reset_p)cnt = 0;
else if(clk_div100_nedge)begin
cnt = cnt + 1;
end
end
assign pwm = (cnt < duty) ? 1 : 0;
endmodule