pwm на verilog в три строки.

PWM или просто ШИМ, что это такое объяснять здесь не надо. Работает это дело через изменение скважности сигнала. Т.е ширины импульса, соотношение лог. 0 и лог 1 в сигнале. Как это описать программно, сказано дальше.


В программном виде можно представить шим модулированный сигнал как импульс поделенный на разрядность самого шим модулятора.



Значит нам надо счетчик, компаратор и несколько регистров. Алгоритм прост, по достижении счетчиком входного значения перевести выход в 0 иначе оставить 1. На Verilog для 8 битного ШИМ-а это выглядит следующим образом. Разрядность регулируется исключительно размером входного сигнала, и разрядностью счетчика.


module pwm(in,clk,out);
input[7:0] in;
input clk;

output out;

reg[7:0] counter;
reg out;

always@(posedge clk)
begin
if(counter<=in) 
    out <=1'b1;
else 
    out <=1'b0;
counter<=counter+8'b1;
end

endmodule


И ясное дело скрин из квартуса
  • +1
  • 11 октября 2012, 12:09
  • letni

Комментарии (10)

RSS свернуть / развернуть
Мощно :)
0
кстати. вариант реализации ШИМ для источника тока. самая мелкая альтера, в которую это влезет, будет явно дешевле даже одного компаратора. а клок можно и с контроллера подать.
0
на самом деле у меня просто кроме альтер «самых дешевых» больше ничего не валяется. Хотя для того применения куда он надо (как мигалка с плавным затуханием и возгаранием) можно было обойтись одним транзистором генератором синуса + повторитель на оу. Кстати, случаем ни кто не имеет идей по поводу СНЧ (!) генератора синуса, потому что простой генератор с фазовым сдвигом отказался работать, а использовать лампочки в мостах вина мне религия не позволяет.
0
Эээ, сдвоенный компаратор стоит 5р, а MAX2 на 32 макроячейки — полтинник, или больше ли.
0
на какую частоту?
я про шим, который evsi выкатывал в одном из топиков на тему гальваники и металлизации.
0
Не знаю. Я про LM339. Но эта штука тоже до 390кГц где-то выдаст, не больше (при 8 битах и 100МГц тактовой). А evsi хочет мегагерц и выше.
0
Этот код вполне понятен и прозрачен, а вот другой код с сайта fpga4fan.com я не сильно понимаю
module PWM(clk, PWM_in, PWM_out);
input clk;
input [7:0] PWM_in;
output PWM_out;

reg [8:0] PWM_accumulator;
always @(posedge clk) PWM_accumulator <= PWM_accumulator[7:0] + PWM_in;

assign PWM_out = PWM_accumulator[8];
endmodule

если можно обьясните разницу
0
это не шим, это сигма-дельта. только они забыли еще PWM_out к аккумулятору как младший бит добавить, если подать код 255 то «1» на выходе будет не всё время, а будет иногда в 0 дергаться. но это мелочи.
и имхо сигма-дельта модуляция гораздо лучше чем широтно-импульсная, да и всего в одну строчку, а не в три :)
вот то же самое, только они с вычитанием красивее обошлись просто откинув старший разряд.
module SigmaDeltaModulator(in, clk, out);
parameter WIDTH = 8;
input[WIDTH-1:0] in;
input clk;
output out;

reg[WIDTH:0] acc = 0;
assign out = acc[WIDTH];

always @(posedge clk) acc <= acc + in + out - (out << WIDTH);

endmodule

при коде 128, например, на выходе ШИМа будет меандр с частотой clk/256, а тут всего clk/2, а высокую частоту гораздо легче потом отфильтровывать.
да и ресурсов съест почти столько же, (по триггерам) разве что сумматор может немного посложнее выходит.
+1
Спасибо понятно. Меня наверное слово PWM спутало.
0
Начал изучение ПЛИСок, и взял тут ваш пример ШИМа себе просимулировать. Использую Icarus Verilog для сборки и GTKVawe для симуляции. Возник вопрос, нужно ли дать начальное значение переменной counter = 0? Т.к. у меня при симуляции всегда на выходе out всегда 0 (т.е. всегда работает ветка когда counter больше in) пока не задал начальное значение этой переменной
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.