
PWM은 이전에 블로그에 정리해뒀습니다.
Verilog로 구현을 해보자면 아래 사진처럼 구현할 수 있습니다.다음은
10ns주기를 갖는Basys-3 보드의 주기를 100주기 카운터를 이용해서 우리는1us(마이크로세크)를 카운트합니다. 100번 카운트하므로7bit로 선언하였고clk(10ns)이1us(마이크로세크)가 될때edge_dectector의 하강엣지가 발생하도록 합니다.
우리는 이1us가 될때마다 발생하는 하강엣지clk_div_100_negedge가 발생하면count를 하나씩 증가시키고 이또한 0~99까지 100번 카운트 합니다 그리고 우리는duty를 활용해서 만약duty값이 10이라면100us중에 count가 0~9라면 pwm에 1을 출력하고 10 이후부터는 0을 출력하여 pwm출력을 내보낼 수 있습니다.시뮬레이션결과 및 고찰
- 첫번째 시뮬레이션 결과를 보면
count_sysclk이 50 이하면clk_div_100의 값이 0임을 확인할 수 있고 50을 넘으면텍스트clk_div_100의 값이 1임을 확인할 수 있습니다.- 두번째 시뮬레이션 결과를 보면
count_sysclk이 99 를 넘게되면 0으로 초기화되고clk_div_100의 값이 1이였다가 0으로 초기화되니 0으로 값이 바뀌면서clk_div_100_negedge에 하강엣지 원클락 펄스가 발생합니다.
- 세번째 시뮬레이션 결과를 보면 duty값이 10으로 주어졌고,
clk_div_100_negedge에 하강엣지 원클락 펄스가 발생 할 때마다count의 값이 올라가는 것을 볼 수 있습니다. 0~99까지 카운트되고 0~9까지 카운트 될때pwm = 1이되면서duty cycle = 10, 즉100us중10us는 1,90us는 0이되면서 1:9 비율로 dutyCycle 비율이 완성되는 것을 확인 할 수 있습니다.128주기 PWM
sys_clk_freq = 100_000_000;은basys-3의10ns의 주기를 주파수로 변경하면100_000_000 HZ가 나오게 된다. 즉, 고정되는 값이다.
duty_step= 펄스폭의 단계를 설정합니다. 이전에는 최대 100개의 step이 있었지만 지금은 128이 최대!
즉,10ns = 100_000_000 (HZ = 100MHz)를1MHz(1us)로 만들어서 그1us(1MHz)를duty_step만큼 나누어 제어할 수 있다.(이 step이 많을수록 섬세하게 제어할 수 있습니다.)상세설명
temp = 78이므로temp_half = 39입니다. 코드대로count_sysclk이temp_half를 보다 크다면clk_div_100은 1이 될것이고 작으면 0이됩니다 이를 이용해count_sysclk이 다시0이될때clk_div_100_negedge가 하강엣지에서 원클락펄스를 발생하게됩니다.clk_div_100_negedge가 발생될때마다count가 증가하고 이 우리가 설정한duty = 32값을 넘기면pwm이 0 이되고 이전에는 1이되면서pwm값을 제어합니다.
- 위는
PWM을 32, 64로 했을때 한 주기 당 걸리는 시간을 확인한 결과입니다.PWM = 32일 때는1ms의1/4의 시간,PWM = 64일 때는1ms의1/2의 시간이 걸립니다.128PWM_topModule
- 위 처럼
clk이 돌때마다clk_div에 1씩 더해주고duty에clk_div를 할당해주게된다면?
아래 사진처럼1씩 더해주게 된다면 첫번째 비트는clk이 돌때마다1bit씩 바뀌고 2번째 비트는clk이 두번 돌때 변경되고 3번째는 4번 돌때 4번째비트는 8번 돌때 변경된다. 위처럼clk_div[31:25]로 할당하게된다면LED가 천천히 밝아졌다가 어두워질것이다! 왜? 31번째 비트는 총 2,147,483,648 번째clk이 돌때 비트가 변경될 것이기 때문이다.
즉, 비트의 자릿수가 올라갈 수록 주기가 늘어나고 주파수는 낮아진다.