forked from SJTU-YONGFU-RESEARCH-GRP/core
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathparameterized_deserializer.v
More file actions
executable file
·161 lines (147 loc) · 6.09 KB
/
parameterized_deserializer.v
File metadata and controls
executable file
·161 lines (147 loc) · 6.09 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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
/**
* Parameterized Deserializer
*
* This module implements a deserializer that converts serial data to parallel
* data. It includes clock division for rate adaptation and supports both
* explicit load signal and optional sync pattern detection.
*
* Key Features:
* - Serial-to-parallel conversion: Converts serial bit stream to parallel word
* - Clock division: Divides clock for rate adaptation
* - State machine: IDLE, RECEIVING, DONE states
* - Completion signals: rx_done and rx_busy indicate status
* - Optional sync pattern: Can detect synchronization pattern (future feature)
*
* Deserializer Operation:
* - Load signal: Starts reception when load is asserted
* - Bit reception: Receives bits on sample pulse (divided clock)
* - Shift register: Accumulates received bits
* - Completion: Outputs parallel data when all bits received
*
* Clock Division:
* - Divides input clock by 8 (clk_div_counter: 0-7)
* - Sample pulse: Generated when counter = 0
* - Rate adaptation: Allows slower serial data rate
*
* State Machine:
* - IDLE: Waiting for load signal
* - RECEIVING: Actively receiving bits
* - DONE: Reception complete, data available
*
* Use Cases:
* - Serial communication reception
* - Data deserialization
* - Interface conversion
* - Rate adaptation
*
* @param DATA_WIDTH Width of parallel output (default: 8 bits)
* @param CLOCK_DIV Clock division factor (default: 4, not fully used)
* @param MSB_FIRST Bit order: 1=MSB first, 0=LSB first (default: 1)
* @param SYNC_PATTERN Synchronization pattern (default: 8'hA5)
* @param USE_SYNC_PATTERN Use sync pattern: 1=use pattern, 0=use load (default: 0)
*
* @input clk System clock
* @input rst_n Active-low reset
* @input enable Module enable
* @input serial_in Serial data input
* @input load Start reception (when USE_SYNC_PATTERN=0)
* @output parallel_out[DATA_WIDTH-1:0] Parallel data output
* @output rx_done Reception complete flag
* @output rx_busy Deserializer is busy receiving
* @output sync_detected Sync pattern detected (when USE_SYNC_PATTERN=1)
*/
module parameterized_deserializer #(
parameter DATA_WIDTH = 8, // Width of the parallel output
/* verilator lint_off UNUSEDPARAM */
parameter CLOCK_DIV = 4, // Clock division factor
parameter MSB_FIRST = 1, // 1 = MSB first, 0 = LSB first
/* verilator lint_off UNUSEDPARAM */
parameter SYNC_PATTERN = 8'hA5, // Synchronization pattern to detect start of frame
parameter USE_SYNC_PATTERN = 0 // 1 = Use sync pattern detection, 0 = Use explicit load signal
/* verilator lint_on UNUSEDPARAM */
) (
input wire clk, // System clock
input wire rst_n, // Active low reset
input wire enable, // Module enable
input wire serial_in, // Serial data input
input wire load, // Start reception (used when USE_SYNC_PATTERN=0)
output reg [DATA_WIDTH-1:0] parallel_out, // Parallel data output
output reg rx_done, // Reception complete flag
output reg rx_busy, // Deserializer is busy receiving
output reg sync_detected // Sync pattern detected (when USE_SYNC_PATTERN=1)
);
// Internal registers
reg [DATA_WIDTH-1:0] shift_reg;
reg [3:0] bit_counter; // 4 bits for counting 0-8
reg [2:0] clk_div_counter; // 3 bits to count 0-7
// State machine states
localparam IDLE = 2'b00;
localparam RECEIVING = 2'b01;
localparam DONE = 2'b10;
reg [1:0] state;
// 1 clock cycle pulse when we should sample the bit
wire sample_pulse = (clk_div_counter == 3'd0);
// Clock division counter
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
clk_div_counter <= 0;
end else if (enable) begin
if (clk_div_counter == 3'd7) begin
clk_div_counter <= 0;
end else begin
clk_div_counter <= clk_div_counter + 1;
end
end
end
// Main state machine
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
state <= IDLE;
bit_counter <= 0;
shift_reg <= 0;
parallel_out <= 0;
rx_done <= 0;
rx_busy <= 0;
sync_detected <= 0;
end else if (enable) begin
case (state)
IDLE: begin
// Clear all registers
rx_done <= 0;
bit_counter <= 0;
shift_reg <= 0;
// Start reception when load is asserted
if (load) begin
state <= RECEIVING;
rx_busy <= 1;
end
end
RECEIVING: begin
// Only process on sample pulse (divided clock)
if (sample_pulse) begin
// MSB-first deserializer
// Shift left and insert new bit at LSB
shift_reg <= {shift_reg[DATA_WIDTH-2:0], serial_in};
// Keep track of received bits
bit_counter <= bit_counter + 1;
// Once we've received all 8 bits, go to DONE state
if (bit_counter == 4'd7) begin
state <= DONE;
end
end
end
DONE: begin
// Output the fully received parallel data
parallel_out <= shift_reg;
rx_done <= 1;
rx_busy <= 0;
// Wait for load to be deasserted before going back to IDLE
if (!load) begin
state <= IDLE;
end
end
default: state <= IDLE;
endcase
end
end
endmodule