4-битный счетчик переноса пульсаций в Verilog HDL
Чтобы продолжить работу с кодом Verilog, мы сначала поймем структуру 4-битного счетчика пульсаций. Верхний дизайнерский блок состоит из четырех T-Flip Flop. Пока игнорируйте ввод и вывод T-Flip Flop. Давайте рассмотрим общую внешнюю структуру Ripple Counter. У нас есть два входа, т. е. часы и сброс, и q на выходе. Выход q находится в 4-битной векторной форме.
В Ripple Carry Counter сначала тактовый сигнал проходит через первый T-триггер. Для второго T-триггера выход первого T-триггера действует как часы и так далее. Сброс одинаков для всех Т-триггеров.
Давайте теперь реализуем блок ripplecounter.
module ripplecounter(clk,rst,q); input clk,rst; output [3:0]q; // initiate 4 T-FF to update the count tff tf1(q[0],clk,rst); tff tf2(q[1],q[0],rst); tff tf3(q[2],q[1],rst); tff tf4(q[3],q[2],rst); endmodule
Поскольку мы создали экземпляр tff в ripplecounter, теперь давайте посмотрим на внутреннюю часть T Flip Flop. Внутри T-триггера у нас есть D-триггер и инвертор, т.е. не ворота. Чтобы реализовать T-триггер, нам нужно создать экземпляр d flip и flop, и у нас есть clk и reset в качестве входных данных и q в качестве выходных данных. Нам нужен дополнительный провод d, который в дальнейшем действует как вход для D-триггера.
module tff(q,clk,rst); // tff takes clk and reset as input // q is output input clk,rst; output q; wire d; // by referring the diagram of tff, // instantiate d flip flop and not gate dff df1(q,d,clk,rst); not n1(d,q); endmodule
Таблица истинности флип-флопа D для справки:
клик | первый | г | д |
---|---|---|---|
⇡ | 1 | Икс | 0 |
⇡ | 0 | 0 | 0 |
⇡ | 0 | 1 | 1 |
Блок дизайна:
module ripplecounter(clk,rst,q); input clk,rst; output [3:0]q; // initiate 4 T-FF to update the count tff tf1(q[0],clk,rst); tff tf2(q[1],q[0],rst); tff tf3(q[2],q[1],rst); tff tf4(q[3],q[2],rst); endmodule module tff(q,clk,rst); // tff takes clk and reset as input // q is output input clk,rst; output q; wire d; // by referring the diagram of tff, // instantiate d flip flop and not gate dff df1(q,d,clk,rst); not n1(d,q); endmodule module dff(q,d,clk,rst); input d,clk,rst; output q; reg q; // store the output value always @(posedge clk or posedge rst) begin // refer the truth table to provide // values to q based on reset. if(rst) q=1"b0; else q=d; endripplecounter endmodule
Испытательный стенд:
Моделирование используется для проверки проектного блока путем предоставления входных значений тестируемому устройству. Нам нужно написать testbench со ссылкой на блок ripplecounter, где у нас на входе есть clk и reset.
Часы должны переключаться через определенную единицу времени, поэтому мы изначально указываем clk как 0. А затем после каждой 5-кратной единицы времени мы переключаем часы с 0 на 1 и наоборот в блоке всегда.
initial clk=0; always #5 clk=~clk;
Вот симуляция счетчика пульсаций:
module tb; // input to be stored in reg and output as net(wire) reg clk; reg rst; wire [3:0]q; // instantiate the ripplecounter design block ripplecounter dut(clk,rst,q); // generate clock pulse // initially provide 0 // then inside always block toggle // clock every 5 time units initial clk = 0; always #5 clk = ~clk; // provide reset values as the input initial begin rst = 1; #15 rst = 0; #180 rst = 1; #10 rst = 1; #20 $finish; end initial $monitor("time=%g,rst=%b,clk=%b,q=%d",$time,rst,clk,q); endmodule
Выход:
Как видно, когда сброс равен 0, на выходе q обновляются выходные данные счетчика и счетчик.