-
Notifications
You must be signed in to change notification settings - Fork 0
/
UART_tx.sv
126 lines (87 loc) · 1.89 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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
module UART_tx(clk , rst_n ,trmt , tx_data, tx_done, TX);
input clk, trmt, rst_n ;
input [7:0] tx_data;
output TX ;
output reg tx_done;
typedef enum logic {IDLE , TRANSMITTING} state_t;
logic init, shift ,transmitting;
logic [3:0] bit_cnt;
logic [3:0] nxt_bit_cnt;
logic [11:0] baud_cnt;
logic [11:0] nxt_baud_cnt;
logic [8:0] shift_reg;
logic [8:0] nxt_shift_reg;
always_comb begin
priority case ({init,shift}) inside
2'b1x: nxt_bit_cnt = '0;
2'b01: nxt_bit_cnt = bit_cnt + 1;
2'b00: nxt_bit_cnt = bit_cnt;
endcase
end
always_ff @(posedge clk) begin
bit_cnt <= nxt_bit_cnt;
end
always_comb begin
priority case ({(init || shift),transmitting}) inside
2'b1x: nxt_baud_cnt = '0;
2'b01: nxt_baud_cnt = baud_cnt + 1;
2'b00: nxt_baud_cnt = baud_cnt;
endcase
end
always_ff @(posedge clk) begin
baud_cnt <= nxt_baud_cnt;
end
assign shift = (baud_cnt === 12'hA2C)?1'b1:1'b0;
always_comb begin
priority case ({init,shift}) inside
2'b1x: nxt_shift_reg = {tx_data,1'b0};
2'b01: nxt_shift_reg = {1'b1,shift_reg[8:1]};
2'b00: nxt_shift_reg = shift_reg;
endcase
end
always_ff @(posedge clk , negedge rst_n) begin
if(!rst_n)
shift_reg = '1;
else
shift_reg = nxt_shift_reg;
end
assign TX = shift_reg[0];
state_t state, nxt_state;
logic setdone;
always_comb begin
nxt_state = state;
init = 0;
transmitting = 0;
setdone = 0;
unique case(state)
IDLE: if(trmt) begin
init = 1;
nxt_state = TRANSMITTING;
end
TRANSMITTING: begin
init = 0;
transmitting = 1;
if(bit_cnt === 4'b1010) begin
setdone = 1;
nxt_state = IDLE;
end
end
endcase
end
always_ff @(posedge clk, negedge rst_n) begin
if(!rst_n)
state <= IDLE;
else
state <= nxt_state;
end
always_ff @(posedge clk, negedge rst_n) begin
if(!rst_n)
tx_done <= 1'b0;
else begin
if(init)
tx_done <= 1'b0;
else if(setdone)
tx_done <= 1'b1;
end
end
endmodule