Asynchronous Counter
module t_ff (
input wire clk,
input wire reset,
input wire T,
output reg Q,
output wire Q_bar
);
assign Q_bar = ~Q;
always @(negedge clk or posedge reset) begin
if (reset)
Q <= 1'b0;
else if (T)
Q <= ~Q;
end
endmodule
// --- Main Module: Asynchronous Up/Down Counter ---
module async_mod4_updown (
input wire clk,
input wire reset,
input wire M, // M = 0 for UP, M = 1 for DOWN
output wire [1:0] Q
);
wire q0_bar, q1_bar;
wire clk1;
// Flip-Flop 0 (LSB): Clocked continuously by the external clock
t_ff ffA (
.clk(clk),
.reset(reset),
.T(1'b1),
.Q(Q[0]),
.Q_bar(q0_bar)
);
// Clock Steering Logic (2-to-1 Multiplexer)
// If M=0 (UP), clock FF1 with Q[0].
// If M=1 (DOWN), clock FF1 with ~Q[0].
assign clk1 = (M == 1'b0) ? Q[0] : q0_bar;
// Modified logic with a 3ns propagation delay injected:
// assign #3 clk1 = (M == 1'b0) ? Q[0] : q0_bar;
// Flip-Flop 1 (MSB): Clocked by the output of the steering logic
t_ff ffB (
.clk(clk1),
.reset(reset),
.T(1'b1),
.Q(Q[1]),
.Q_bar(q1_bar)
);
endmodule
Synchronous Counter
module sync_mod4_updown (
input wire clk,
input wire reset,
input wire M, // M = 0 for UP, M = 1 for DOWN
output reg [1:0] Q // 2-bit output
);
// Synchronous design: All state changes happen on the rising edge of the master clock
always @(posedge clk or posedge reset) begin
if (reset) begin
Q <= 2'b00;
end else begin
if (M == 1'b0)
Q <= Q + 1'b1; // Count Up
else
Q <= Q - 1'b1; // Count Down
end
end
endmodule
Test Bench
module tb_counters();
// Testbench signals
reg clk;
reg reset;
reg M;
// Outputs from the counters
wire [1:0] q_sync;
wire [1:0] q_async;
// Instantiate the Synchronous Counter
sync_mod4_updown uut_sync (
.clk(clk),
.reset(reset),
.M(M),
.Q(q_sync)
);
// Instantiate the Asynchronous Counter
async_mod4_updown uut_async (
.clk(clk),
.reset(reset),
.M(M),
.Q(q_async)
);
// Clock Generation (10ns period -> 100MHz)
initial begin
clk = 0;
forever #5 clk = ~clk;
end
// Test Sequence
initial begin
// 1. Initialize Inputs
reset = 1;
M = 0;
// 2. Release Reset after a short delay
#12 reset = 0;
// 3. Test UP Counting (Let it run for a few clock cycles)
// Expected sequence: 0 -> 1 -> 2 -> 3 -> 0
#50;
// 4. Test DOWN Counting
// Expected sequence: 0 -> 3 -> 2 -> 1 -> 0
M = 1;
#50;
// End simulation
$finish;
end
initial begin
// Name of the output waveform file
$dumpfile("dump.vcd");
// The '0' tells the simulator to dump all signals
// across ALL levels of the hierarchy within tb_counters
$dumpvars(0, tb_counters);
end
// Console Output Monitor
initial begin
$display("Time | Mode | clk1 (FF1 Clock) | q0_bar | q1_bar | Final Output (Q)");
$display("-------------------------------------------------------------------");
// Using dot notation to pull wires from inside uut_async
$monitor("%0t | %b | %b | %b | %b | %b",
$time,
M,
uut_async.clk1, // The steered clock signal
uut_async.q0_bar, // Inverted Q0
uut_async.q1_bar, // Inverted Q1
q_async); // The top-level output
end
// Console Output Monitor
initial begin
$display("Time\\t Mode(M)\\t Sync_Q\\t Async_Q");
$display("-----------------------------------------");
$monitor("%0t\\t %b\\t\\t %b\\t %b", $time, M, q_sync, q_async);
end
endmodule