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 обновляются выходные данные счетчика и счетчик.