ШИМ контроллер на Verilog-A

Понадобился тут мне ШИМ контроллер, а готового в библиотеках cadence не было, пришлось выкручиваться на Verilog-A.

Остальное внутри поста 🙂

Итак мне нужен ШИМ контроллер с возможностью изменения скважности, причем управление скважностью должно осуществляться с помощью напряжения, чтобы организовать нормальную обратную связь в некоторых применениях. Картинка в начале поста кстати результат моделирования моего контроллера 🙂 А да, период шим не должен быть установленным намертво в коде.

Ну поехали:


// VerilogA for TB_sarge, PWMController, veriloga

`include "constants.vams"
`include "disciplines.vams"

module PWMController(Clk, Duty, Out);
output Out;
input Clk;
input Duty;

electrical Clk;
electrical Out;
electrical Duty;

parameter real Vh = 2.5;          //Максимальное напряжение
parameter real Vl = 0;            //Минимальное напряжение
parameter real vth = (Vh+Vl)/2;   //Напряжение, при котором состояние будет переключаться
parameter real PWMperiod = 2.5u; //Период ШИМ
real state;                      //Переменная для обработки напряжения по входу Duty
integer n;                       //переменная индикатор состояния

real timeper;                    //характеристика скважности

analog begin
@(initial_step) state = 0;       //Инициализация

@(cross(V(Clk) - vth, +1)) begin //По каждому возрастающему фронту
  n = 1;
  timeper = $abstime;              //timeper = текущее время
  state = V(Duty);                 //state = напряжение на управляющем входе
end

@(timer(0, timeper+state*PWMperiod))     //таймер срабатывает через текущее время + часть периода шим
begin
 n = 0;                                 //и затягивает состояние выхода в противоположное
end

V(Out) <+ transition(n ? Vl:Vh, 0, 100p);  //выход равен либо Vh либо Vl, время нарастания 100 пс

end
endmodule

Контроллер готов, можно цеплять к нему источник с меандром по выходу и напряжением регулировать скважность, но есть одно но – код будет адекватно работать лишь если на входе у него напряжение от 0 до 1 (0-100% скважность). Поэтому пришлось еще приделать небольшой конвертер напряжений:


// VerilogA for TB_sarge, PWMConverter, veriloga

`include "constants.vams"
`include "disciplines.vams"
module PWMConverter(In, Out);

input In;
output Out;
electrical In;
electrical Out;

parameter real VHpeak = 2.5;
parameter real VLpeak = 0;

analog begin
 V(Out) <+ (VHpeak - VLpeak -V(In))/(VHpeak-VLpeak);   //Разбиваем наш диапазон напряжений на 100 частей и получаем в итоге напряжение от 0 до 1

end
endmodule

В данной версии кода кроме конвертирования происходит еще и инвертирование напряжения, то есть в максимально напряжении на входе, на выходе будет минимальное, то есть 0. Если инверсия не нужна, то строку 16 нужно переписать:

<pre>V(Out) <+ V(In)/(VHpeak-VLpeak);</pre>

Вот, теперь собираем тестовую схемку:

И наслаждаемся результатом 🙂

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.