Skip to content

Commit 7fc7151

Browse files
committed
Add UART deserializer
1 parent eb73f3d commit 7fc7151

File tree

6 files changed

+133
-1
lines changed

6 files changed

+133
-1
lines changed

docs/src/uart.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ accurate retrieval. A standard oversampling factor of 16 minimizes the error to
1212
1/16 from the middle point.
1313

1414
```{figure} img/uart-rx-proto.svg
15-
:width: 200px
15+
:width: 80%
1616
:align: center
1717

1818
Transmission of a byte

hdl/uart/rx.v

Whitespace-only changes.

hdl/uart/tx.v

Whitespace-only changes.

hdl/uart/uart_rx.v

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
`default_nettype none
2+
3+
module uart_rx (
4+
input wire clk,
5+
input wire rst_n,
6+
input wire sd
7+
);
8+
9+
wire tick;
10+
11+
baud_gen baud_gen0 (
12+
.clk(clk),
13+
.rst_n(rst_n),
14+
.tick(tick)
15+
);
16+
17+
endmodule

hdl/uart/uart_rx_des.v

+108
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
`default_nettype none
2+
3+
module uart_rx_des
4+
#( parameter WORD_WIDTH = 8,
5+
parameter OVERSAMPLING = 16) (
6+
input wire clk,
7+
input wire rst_n,
8+
input wire tick,
9+
input wire din,
10+
input wire parity_en,
11+
output wire ready_tick,
12+
output wire [DATA_WIDTH-1:0] dout
13+
);
14+
15+
localparam TICK_MID_VAL = OVERSAMPLING / 2 - 1;
16+
localparam DATA_WIDTH = WORD_WIDTH + 1; // parity bit
17+
18+
localparam [2:0]
19+
IDLE = 3'b000,
20+
START_BIT = 3'b001,
21+
DATA = 3'b010,
22+
STOP_BIT = 3'b011;
23+
24+
reg [2:0 ] state, state_nxt;
25+
26+
// config
27+
reg parity, parity_nxt;
28+
29+
// internal
30+
reg [$clog2(OVERSAMPLING)-1:0] tick_ctr, tick_ctr_nxt;
31+
reg [$clog2(DATA_WIDTH)-1:0 ] bit_ctr, bit_ctr_nxt;
32+
wire [$clog2(DATA_WIDTH)-1:0] N = parity ? DATA_WIDTH : WORD_WIDTH;
33+
34+
// outputs
35+
reg [DATA_WIDTH-1:0 ] d, d_nxt;
36+
reg ready;
37+
38+
always @(posedge clk or negedge rst_n) begin
39+
if (~rst_n) begin
40+
state <= IDLE;
41+
tick_ctr <= 0;
42+
bit_ctr <= 0;
43+
d <= 0;
44+
parity <= 0;
45+
end else begin
46+
state <= state_nxt;
47+
tick_ctr <= tick_ctr_nxt;
48+
bit_ctr <= bit_ctr_nxt;
49+
d <= d_nxt;
50+
parity <= parity_nxt;
51+
end
52+
end
53+
54+
always @(*) begin
55+
state_nxt = state;
56+
tick_ctr_nxt = tick_ctr;
57+
bit_ctr_nxt = bit_ctr;
58+
d_nxt = d;
59+
parity_nxt = parity;
60+
ready = 1'b0;
61+
62+
case (state)
63+
IDLE: begin
64+
if (~din) begin
65+
state_nxt = START_BIT;
66+
tick_ctr_nxt = TICK_MID_VAL;
67+
parity_nxt = parity_en;
68+
end
69+
end
70+
START_BIT: begin
71+
if (tick) begin
72+
tick_ctr_nxt = tick_ctr - 1;
73+
if (tick_ctr == 0) begin
74+
state_nxt = DATA;
75+
tick_ctr_nxt = OVERSAMPLING - 1;
76+
end
77+
end
78+
end
79+
DATA: begin
80+
if (tick) begin
81+
tick_ctr_nxt = tick_ctr - 1;
82+
if (tick_ctr == 0) begin
83+
d_nxt = {din, d[DATA_WIDTH - 1 : 1]};
84+
if (bit_ctr == N)
85+
state_nxt = STOP_BIT;
86+
else
87+
bit_ctr_nxt = bit_ctr + 1;
88+
tick_ctr_nxt = OVERSAMPLING - 1;
89+
end
90+
end
91+
end
92+
STOP_BIT: begin
93+
if (tick) begin
94+
if (tick_ctr == 0) begin
95+
state_nxt = IDLE;
96+
if (din) // check data line deasserted
97+
ready = 1'b1;
98+
end else
99+
tick_ctr_nxt = tick_ctr - 1;
100+
end
101+
end
102+
endcase
103+
end
104+
105+
assign ready_tick = ready;
106+
assign dout = d;
107+
108+
endmodule

hdl/uart/uart_tx.v

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module uart_tx(
2+
input wire clk,
3+
input wire rst_n,
4+
input wire [7:0] data.
5+
6+
output wire sd
7+
);

0 commit comments

Comments
 (0)