Skip to content

Commit e1567fc

Browse files
committed
More work on uart_rx and uart_tb
1 parent 2cb6866 commit e1567fc

File tree

5 files changed

+80
-28
lines changed

5 files changed

+80
-28
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
xcelium.d
22
xrun.*
3+
*.vcd

filelist.f

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@
22
rtl/fifo_ctrl.sv
33
rtl/fifo_mem.sv
44
rtl/uart.sv
5+
rtl/uart_rx.sv
56
rtl/uart_prescaler.sv
6-
test/uart_prescaler_tb.sv
7+
test/uart_tb.sv

rtl/uart.sv

+25-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
`timescale 1ns / 1ps
22
// Configurable UART module
3-
module uart_axi #(
3+
module uart #(
44
parameter FifoDepth = 8
55
)(
66
/* Main Signals */
@@ -20,8 +20,10 @@ module uart_axi #(
2020
input logic i_cts,
2121
output logic o_rts
2222
);
23-
logic fifo_empty;
23+
logic prescaler_half, prescaler_strobe, prescaler_en;
2424

25+
/*
26+
logic fifo_empty;
2527
fifo #(
2628
.DataWidth(8),
2729
.Depth(FifoDepth)
@@ -35,8 +37,28 @@ module uart_axi #(
3537
.o_full(),
3638
.o_empty(fifo_empty)
3739
);
40+
*/
41+
42+
uart_rx uart_rx (
43+
.i_clk,
44+
.i_rst_n,
45+
.i_rx,
46+
.o_rx_data(),
47+
.i_strobe(prescaler_strobe),
48+
.i_half(prescaler_half),
49+
.o_prescaler_en(prescaler_en)
50+
);
51+
52+
uart_prescaler uart_prescaler (
53+
.i_clk,
54+
.i_rst_n,
55+
.i_en(prescaler_en),
56+
.i_scaler(16'd8),
57+
.o_strobe(prescaler_strobe),
58+
.o_half(prescaler_half)
59+
);
3860

39-
assign o_rx_rdy = ~fifo_empty;
61+
//assign o_rx_rdy = ~fifo_empty;
4062

4163
endmodule
4264

rtl/uart_prescaler.sv

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
`timescale 1ns / 1ps
22
// Scales the clock signal according to scale factor
33
module uart_prescaler #(
4-
parameter InitialDivider = 16
4+
parameter InitialDivider = 16,
5+
parameter OverSample = 8
56
)(
67
input logic i_clk,
78
input logic i_rst_n,
@@ -10,6 +11,7 @@ module uart_prescaler #(
1011
output logic o_strobe, /* Strobe signal */
1112
output logic o_half /* Halfway signal */
1213
);
14+
1315
logic [15:0] counter;
1416

1517
/* Counter Logic */
@@ -18,7 +20,7 @@ module uart_prescaler #(
1820
counter <= '0;
1921
end else begin
2022
if (i_en) begin
21-
if (counter == (i_scaler - 16'b1)) counter <= '0;
23+
if (counter == (i_scaler - 16'd1)) counter <= '0;
2224
else counter <= counter + 16'b1;
2325
end
2426
end
@@ -29,7 +31,7 @@ module uart_prescaler #(
2931
if (!i_rst_n) begin
3032
o_half <= 1'b0;
3133
end else begin
32-
o_half <= (counter == (i_scaler[15:1] - 16'b1));
34+
o_half <= (counter == (i_scaler[15:1] - 16'd2));
3335
end
3436
end
3537

@@ -38,7 +40,7 @@ module uart_prescaler #(
3840
if (!i_rst_n) begin
3941
o_strobe <= 1'b0;
4042
end else begin
41-
o_strobe <= (counter == (i_scaler - 16'b1));
43+
o_strobe <= (counter == (i_scaler - 16'd2));
4244
end
4345
end
4446

rtl/uart_rx.sv

+46-20
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
module uart_rx #(
2+
parameter Parity = 1'b0,
3+
parameter StopBit = 1'b1,
4+
parameter OverSample = 8
25
//params
36
)(
47
//i/o
@@ -11,19 +14,28 @@ module uart_rx #(
1114
/* Sample Timing */
1215
input logic i_strobe,
1316
input logic i_half,
14-
output logic o_prescaler_en
17+
output logic o_prescaler_en,
18+
output logic o_parity_error,
19+
output logic o_stop_bit_error
1520
);
1621

22+
localparam counter_width = $clog2(OverSample);
23+
1724
typedef enum logic [2:0] {
18-
RESET = 3'b000,
19-
WAIT = 2'b001,
20-
LOAD = 3'b010,
21-
STOP = 3'b011,
22-
READY = 3'b100
25+
RESET = 3'b000,
26+
WAIT = 2'b001,
27+
LOAD = 3'b010,
28+
PARITY = 3'b011,
29+
STOP = 3'b100,
30+
READY = 3'b101
2331
} states_t;
2432

2533
states_t curr_state, next_state;
26-
logic [2:0] counter;
34+
35+
logic [counter_width:0] counter;
36+
logic counter_rst_n;
37+
38+
logic parity_bit;
2739

2840
// State controller
2941
always_ff @(posedge i_clk) begin
@@ -33,45 +45,59 @@ module uart_rx #(
3345

3446
// Next State Logic Controller
3547
always_comb begin
36-
unique case (state)
48+
unique case (curr_state)
3749
RESET:
3850
next_state = WAIT;
3951
WAIT:
40-
if (serial_in == '0)
52+
if (i_rx == '0)
4153
next_state = LOAD;
4254
else
4355
next_state = WAIT;
4456
LOAD:
4557
if (counter == '0)
46-
next_state = STOP;
58+
generate
59+
case (Parity)
60+
0: next_state = STOP;
61+
1: next_state = PARITY;
62+
endcase
63+
endgenerate
4764
else
4865
next_state = LOAD;
66+
PARITY:
67+
if (i_half)
68+
next_state = STOP;
69+
else
70+
next_state = PARITY;
4971
STOP:
50-
// wait for stop bit
72+
if (i_half && i_rx) // halfway strobe AND rx == 1 (stop bit)
73+
next_state = READY;
74+
else
75+
next_state = STOP;
5176
READY:
5277
next_state = WAIT;
5378
endcase
5479
end
5580

5681
always_comb begin
57-
unique case (state)
58-
RESET:
59-
WAIT:
60-
LOAD:
61-
STOP:
62-
READY:
82+
unique case (curr_state)
83+
RESET: {o_prescaler_en, counter_rst_n} = 2'b00;
84+
WAIT: {o_prescaler_en, counter_rst_n} = 2'b00;
85+
LOAD: {o_prescaler_en, counter_rst_n} = 2'b11;
86+
PARITY: {o_prescaler_en, counter_rst_n} = 2'b10;
87+
STOP: {o_prescaler_en, counter_rst_n} = 2'b10;
88+
READY: {o_prescaler_en, counter_rst_n} = 2'b00;
6389
endcase
6490
end
6591

6692
always_ff @(posedge i_clk)
6793
if (!i_rst_n)
6894
o_rx_data <= 0;
6995
else if (i_half)
70-
o_rx_data <= {rx, o_rx_data[7:1]};
96+
o_rx_data <= {i_rx, o_rx_data[7:1]};
7197

7298
always_ff @(posedge i_clk)
73-
if (!i_rst_n)
74-
counter <= '0;
99+
if (!counter_rst_n)
100+
counter <= '1;
75101
else if (i_half)
76102
counter <= counter - 3'b1;
77103

0 commit comments

Comments
 (0)