-
Notifications
You must be signed in to change notification settings - Fork 0
/
uart.v
208 lines (175 loc) · 4.94 KB
/
uart.v
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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
// uart module
// stolen from altera cookbook
// Copyright 2007 Altera Corporation. All rights reserved.
// Altera products are protected under numerous U.S. and foreign patents,
// maskwork rights, copyrights and other intellectual property laws.
//
// This reference design file, and your use thereof, is subject to and governed
// by the terms and conditions of the applicable Altera Reference Design
// License Agreement (either as signed by you or found at www.altera.com). By
// using this reference design file, you indicate your acceptance of such terms
// and conditions between you and Altera Corporation. In the event that you do
// not agree with such terms and conditions, you may not use the reference
// design file and please promptly destroy any copies you have made.
//
// This reference design file is being provided on an "as-is" basis and as an
// accommodation and therefore all warranties, representations or guarantees of
// any kind (whether express, implied or statutory) including, without
// limitation, warranties of merchantability, non-infringement, or fitness for
// a particular purpose, are specifically disclaimed. By making this reference
// design file available, Altera expressly does not recommend, suggest or
// require that this reference design file be used in combination with any
// other product not provided by Altera.
/////////////////////////////////////////////////////////////////////////////
// baeckler - 02-16-2007
////////////////////////////////////////////////////////////////////
module uart_tx (clk,tx_data,tx_data_valid,tx_data_ack,txd);
output txd;
input clk;
input [7:0] tx_data;
input tx_data_valid;
output tx_data_ack;
parameter BAUD_DIVISOR = 868;
reg [9:0] sample_cntr;
reg [10:0] tx_shift;
reg sample_now;
reg tx_data_ack;
assign txd = tx_shift[0];
always @(posedge clk) begin
if (sample_cntr == (BAUD_DIVISOR-1)) begin
sample_cntr <= 0;
sample_now <= 1'b1;
end
else begin
sample_now <= 1'b0;
sample_cntr <= sample_cntr + 1'b1;
end
end
reg ready;
always @(posedge clk) begin
if (!ready & sample_now) begin
tx_shift <= {1'b0,tx_shift[10:1]};
tx_data_ack <= 1'b0;
ready <= ~|tx_shift[10:1];
end
else if (ready & tx_data_valid) begin
tx_shift[10:1] <= {1'b1,tx_data,1'b0};
tx_data_ack <= 1'b1;
ready <= 1'b0;
end
else begin
tx_data_ack <= 1'b0;
ready <= ~|tx_shift[10:1];
end
end
endmodule
////////////////////////////////////////////////////////////////////
module uart_rx (clk,rx_data,rx_data_fresh,rxd);
input clk, rxd;
output [7:0] rx_data;
output rx_data_fresh;
parameter BAUD_DIVISOR = 868;
reg [10:0] sample_cntr;
reg [7:0] rx_shift;
reg sample_now;
reg [7:0] rx_data;
reg rx_data_fresh;
reg last_rxd;
always @(posedge clk) begin
last_rxd <= rxd;
end
wire slew = rxd ^ last_rxd;
always @(posedge clk) begin
if (sample_cntr == (BAUD_DIVISOR-1) || slew) begin
sample_cntr <= 0;
end
else if (sample_cntr == (BAUD_DIVISOR/2)) begin
sample_now <= 1'b1;
sample_cntr <= sample_cntr + 1'b1;
end
else begin
sample_now <= 1'b0;
sample_cntr <= sample_cntr + 1'b1;
end
end
reg [1:0] state;
reg [3:0] held_bits;
parameter WAITING = 2'b00, READING = 2'b01, STOP = 2'b10, RECOVER = 2'b11;
always @(posedge clk) begin
rx_data_fresh <= 1'b0;
case (state)
WAITING : begin
// wait for a start bit (0)
if (!slew & sample_now && !last_rxd) begin
state <= READING;
held_bits <= 0;
end
end
READING : begin
// gather data bits
if (sample_now) begin
rx_shift <= {last_rxd,rx_shift[7:1]};
held_bits <= held_bits + 1'b1;
if (held_bits == 4'h7) state <= STOP;
end
end
STOP : begin
// verify stop bit (1)
if (sample_now) begin
if (last_rxd) begin
rx_data <= rx_shift;
rx_data_fresh <= 1'b1;
state <= WAITING;
end
else begin
// there was a framing error -
// discard the byte and work on resync
state <= RECOVER;
end
end
end
RECOVER : begin
// wait for an idle (1) then resume
if (sample_now) begin
if (last_rxd) state <= WAITING;
end
end
endcase
end
endmodule
////////////////////////////////////////////////////////////////////
module uart (clk,
tx_data,tx_data_valid,tx_data_ack,txd,
rx_data,rx_data_fresh,rxd);
parameter CLK_HZ = 100_000_000;
parameter BAUD = 115200;
parameter BAUD_DIVISOR = CLK_HZ / BAUD;
initial begin
if (BAUD_DIVISOR > 16'hffff) begin
// This rate is too slow for the TX and RX sample
// counter resolution
$display ("Error - Increase the size of the sample counters");
$stop();
end
end
output txd;
input clk, rxd;
input [7:0] tx_data;
input tx_data_valid;
output tx_data_ack;
output [7:0] rx_data;
output rx_data_fresh;
uart_tx utx (
.clk(clk),
.tx_data(tx_data),
.tx_data_valid(tx_data_valid),
.tx_data_ack(tx_data_ack),
.txd(txd));
defparam utx .BAUD_DIVISOR = BAUD_DIVISOR;
uart_rx urx (
.clk(clk),
.rx_data(rx_data),
.rx_data_fresh(rx_data_fresh),
.rxd(rxd));
defparam urx .BAUD_DIVISOR = BAUD_DIVISOR;
endmodule