Up-down counter with direction control in Verilog - Time & Space Complexity
We want to understand how the time needed to run an up-down counter changes as the input size changes.
Specifically, how does the counting process scale when we control the direction?
Analyze the time complexity of the following code snippet.
module up_down_counter(
input wire clk,
input wire rst,
input wire dir, // 1 for up, 0 for down
output reg [3:0] count
);
always @(posedge clk or posedge rst) begin
if (rst) count <= 0;
else if (dir) count <= count + 1;
else count <= count - 1;
end
endmodule
This code counts up or down by 1 on each clock pulse depending on the direction signal.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The counting update happens once every clock cycle.
- How many times: It repeats for each clock pulse, which depends on how long the system runs.
Each clock cycle triggers one count update, so the number of operations grows directly with the number of clock cycles.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 10 count updates |
| 100 | 100 count updates |
| 1000 | 1000 count updates |
Pattern observation: The operations grow linearly as the input size (number of clock cycles) increases.
Time Complexity: O(n)
This means the time to run the counter grows directly in proportion to how many times it counts.
[X] Wrong: "The counter updates all bits at once, so it takes constant time regardless of count size."
[OK] Correct: While the hardware updates all bits simultaneously, the number of updates depends on the number of clock cycles, which grows with input time, not the bit width.
Understanding how simple counters scale helps you reason about timing and performance in hardware design, a key skill for many projects.
"What if we changed the counter to count by 2 instead of 1 each cycle? How would the time complexity change?"
Practice
Solution
Step 1: Understand the role of the direction signal
The direction signal determines if the counter increments or decrements its value.Step 2: Relate direction to counting behavior
If direction is high, the counter counts up; if low, it counts down.Final Answer:
Whether the counter counts up or down -> Option CQuick Check:
Direction controls count direction = C [OK]
- Confusing direction with clock speed
- Thinking reset controls counting direction
- Assuming direction changes output width
Solution
Step 1: Check variable declarations and types
Count should be a 4-bit reg, direction input is 'dir'.Step 2: Verify always block and assignments
Use posedge clk, non-blocking assignments '<=' for sequential logic, reset sets count to 0, dir controls increment or decrement.Final Answer:
Correct syntax with reg, posedge clk, non-blocking assignments, and direction control -> Option BQuick Check:
Proper reg and non-blocking assignments = A [OK]
- Using wire instead of reg for count
- Using blocking '=' in sequential always block
- Incorrect clock edge sensitivity
- Reversing increment and decrement logic
reg [2:0] count = 3'b000; always @(posedge clk) begin if(reset) count <= 3'b000; else if(dir) count <= count + 1; else count <= count - 1; end
If
reset=0, dir=1, and the clock pulses 5 times starting from 0, what is the value of count after 5 pulses?Solution
Step 1: Understand initial conditions and direction
Count starts at 0, reset is inactive, dir=1 means count up.Step 2: Calculate count after 5 increments
Counting up 5 times from 0: 0->1->2->3->4->5, which is 3'b101 in binary.Final Answer:
3'b101 -> Option AQuick Check:
0 + 5 increments = 5 (binary 101) [OK]
- Forgetting initial count is zero
- Confusing binary values
- Counting down instead of up
reg [3:0] count; always @(posedge clk) begin if(reset) count = 0; else if(dir) count <= count + 1; else count <= count - 1; end
Solution
Step 1: Check assignment types in sequential always block
Sequential logic requires non-blocking assignments '<=' for all assignments inside always @(posedge clk).Step 2: Identify inconsistent assignment usage
Reset uses blocking '=' which can cause simulation mismatches; it should use '<=' like other assignments.Final Answer:
Using blocking assignment '=' for reset inside always block -> Option AQuick Check:
Use '<=' for all sequential assignments [OK]
- Mixing blocking and non-blocking assignments
- Ignoring declaration of signals
- Wrong sensitivity list for clock
Solution
Step 1: Understand wrap-around conditions
When counting up at max (15), reset to 0; when counting down at 0, reset to 15.Step 2: Check code logic for direction and wrap-around
always @(posedge clk) begin if(reset) count <= 0; else if(dir) count <= (count == 4'b1111) ? 0 : count + 1; else count <= (count == 4'b0000) ? 4'b1111 : count - 1; end correctly uses conditional operator to wrap count on max and min values based on direction.Final Answer:
Code with conditional wrap-around for max and min counts -> Option DQuick Check:
Wrap-around logic matches direction and limits [OK]
- Not wrapping count at max/min values
- Reversing increment and decrement logic
- Using incorrect boundary values
Ready to prove it?
Pass the test and this pattern moves unknown
