-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathuart_tx.sv
97 lines (82 loc) · 1.67 KB
/
uart_tx.sv
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
module uart_tx
#(
parameter CLK_SPEED = 50_000000,
parameter BAUD = 115200
)
(
i_clk,
i_data, i_stb,
o_tx, o_busy
);
input wire i_clk;
input wire [7:0] i_data;
input wire i_stb;
output reg o_tx;
output wire o_busy;
initial begin
o_tx = 1;
end
localparam SAMPLE_INTERVAL = (CLK_SPEED / BAUD);
integer counter;
reg [3:0] state;
reg [7:0] data;
initial begin
counter = 0;
state = 0;
end
assign o_busy = state != IDLE;
localparam IDLE = 0,
RX_START = 2,
RX_0 = 3,
RX_1 = 4,
RX_2 = 5,
RX_3 = 6,
RX_4 = 7,
RX_5 = 8,
RX_6 = 9,
RX_7 = 10,
RX_STOP = 11,
RX_LAST_STATE = 12;
always @(posedge i_clk) begin
if (state == IDLE) begin
if (i_stb) begin
counter <= 0;
state <= RX_START;
data <= i_data;
end
end
else begin
if (counter == SAMPLE_INTERVAL) begin
counter <= 0;
if (state == RX_STOP)
state <= IDLE;
else
state <= state + 1;
end
else
counter <= counter + 1;
end
end
always @(*) begin
case(state)
RX_START: o_tx = 0;
IDLE,
RX_STOP: o_tx = 1;
default: o_tx = data[state - 3];
endcase
end
`ifdef FORMAL
always @(*) begin
assert(counter <= SAMPLE_INTERVAL);
assert(state < RX_LAST_STATE);
end
reg past_valid;
initial past_valid = 0;
always @(posedge i_clk) past_valid <= 1;
always @(posedge i_clk) begin
if (past_valid && $past(state) != IDLE) begin
assert(counter != $past(counter));
end
end
`endif
endmodule