forked from SJTU-YONGFU-RESEARCH-GRP/core
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathparameterized_johnson_updown_counter.v
More file actions
executable file
·95 lines (91 loc) · 4.05 KB
/
parameterized_johnson_updown_counter.v
File metadata and controls
executable file
·95 lines (91 loc) · 4.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
/**
* Parameterized Johnson Up/Down Counter
*
* This module implements a bidirectional Johnson counter that can count up
* or down. A Johnson counter is a modified ring counter where the inverted
* MSB (for up) or inverted LSB (for down) is fed back, creating a sequence
* that is 2×WIDTH states long.
*
* Key Features:
* - Bidirectional: Count up or down based on up_down signal
* - Johnson counter: Modified ring counter with inverted feedback
* - Sequence length: 2×WIDTH states
* - One-hot encoding: Only one bit changes per transition
* - Configurable width: Any bit width via WIDTH parameter
*
* Johnson Counter Operation:
* - Up mode: Shift right, feed inverted LSB to MSB
* - Down mode: Shift left, feed inverted MSB to LSB
* - Initial state: MSB set (for up mode)
* - Sequence length: 2×WIDTH states
*
* Up Mode Sequence (WIDTH=4):
* 1000 → 1100 → 1110 → 1111 → 0111 → 0011 → 0001 → 0000 → 1000
*
* Down Mode Sequence (WIDTH=4):
* 1000 → 0000 → 0001 → 0011 → 0111 → 1111 → 1110 → 1100 → 1000
*
* Use Cases:
* - State machines with 2×WIDTH states
* - Frequency division (divide by 2×WIDTH)
* - Sequence generation (bidirectional)
* - Phase generation
*
* @param WIDTH Width of Johnson counter (default: 4 bits)
* Sequence length = 2×WIDTH states
*
* @input clk Clock signal
* @input rst_n Active-low reset signal
* @input enable Enable signal (high to count)
* @input up_down Direction control: 1=count up, 0=count down
* @output count[WIDTH-1:0] Johnson counter output
*/
module parameterized_johnson_updown_counter #(
parameter WIDTH = 4
)(
input wire clk,
input wire rst_n, // Active low reset
input wire enable, // Enable signal
input wire up_down, // Direction control (1 for up, 0 for down)
output wire [WIDTH-1:0] count
);
reg [WIDTH-1:0] counter_reg;
// ============================================================================
// Johnson Counter Logic (Bidirectional)
// ============================================================================
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
// ====================================================================
// Reset State
// ====================================================================
// Initialize with only MSB set (one-hot encoding)
// Format: {1, zeros} = 100...0
// This is the starting state for up mode
counter_reg <= {1'b1, {(WIDTH-1){1'b0}}};
end else if (enable) begin
if (up_down) begin
// ====================================================================
// Up Mode (Shift Right with Inverted Feedback)
// ====================================================================
// Shift right, feed inverted LSB to MSB
// Format: {inverted_LSB, existing_bits[WIDTH-1:1]}
// Example (WIDTH=4): 1000 → 1100 → 1110 → 1111 → 0111 → ...
counter_reg <= {~counter_reg[0], counter_reg[WIDTH-1:1]};
end else begin
// ====================================================================
// Down Mode (Shift Left with Inverted Feedback)
// ====================================================================
// Shift left, feed inverted MSB to LSB
// Format: {existing_bits[WIDTH-2:0], inverted_MSB}
// Example (WIDTH=4): 1000 → 0000 → 0001 → 0011 → 0111 → ...
counter_reg <= {counter_reg[WIDTH-2:0], ~counter_reg[WIDTH-1]};
end
end
// ========================================================================
// Hold Mode
// ========================================================================
// When enable is low, counter holds current value
// (implicit: no assignment means value is maintained)
end
assign count = counter_reg;
endmodule