1 |
2 |
motilito |
//------------------------------------------------------------------------------
|
2 |
|
|
// uart tasks:
|
3 |
|
|
// send_serial serial transmitter
|
4 |
|
|
// get_serial serial receiver
|
5 |
|
|
//
|
6 |
|
|
//------------------------------------------------------------------------------
|
7 |
|
|
|
8 |
|
|
/* Serial Parameters used for send_serial task and its callers. */
|
9 |
|
|
`define PARITY_OFF 1'b0
|
10 |
|
|
`define PARITY_ON 1'b1
|
11 |
|
|
`define PARITY_ODD 1'b0
|
12 |
|
|
`define PARITY_EVEN 1'b1
|
13 |
|
|
`define NSTOPS_1 1'b0
|
14 |
|
|
`define NSTOPS_2 1'b1
|
15 |
|
|
`define BAUD_115200 3'b000
|
16 |
|
|
`define BAUD_38400 3'b001
|
17 |
|
|
`define BAUD_28800 3'b010
|
18 |
|
|
`define BAUD_19200 3'b011
|
19 |
|
|
`define BAUD_9600 3'b100
|
20 |
|
|
`define BAUD_4800 3'b101
|
21 |
|
|
`define BAUD_2400 3'b110
|
22 |
|
|
`define BAUD_1200 3'b111
|
23 |
|
|
`define NBITS_7 1'b0
|
24 |
|
|
`define NBITS_8 1'b1
|
25 |
|
|
// constants for status from get_serial task
|
26 |
|
|
`define RECEIVE_RESULT_OK 4'b1000
|
27 |
|
|
`define RECEIVE_RESULT_FALSESTART 4'b0001
|
28 |
|
|
`define RECEIVE_RESULT_BADPARITY 4'b0010
|
29 |
|
|
`define RECEIVE_RESULT_BADSTOP 4'b0100
|
30 |
|
|
|
31 |
|
|
// uart tasks global interfaces signals
|
32 |
|
|
reg serial_out; // transmit serial output
|
33 |
|
|
reg serial_in; // receive serial input
|
34 |
|
|
reg [7:0] get_serial_data; // data received from serial
|
35 |
|
|
reg [7:0] get_serial_status; // status of receive operation
|
36 |
|
|
|
37 |
|
|
//------------------------------------------------------------------------------
|
38 |
|
|
// uart transmit task
|
39 |
|
|
//
|
40 |
|
|
// usage:
|
41 |
|
|
// send_serial (data, baud_rate, parity_type, parity_on, stop_bits_num,
|
42 |
|
|
// data_bit_num, baud_error);
|
43 |
|
|
// where:
|
44 |
|
|
// data data character for transmission
|
45 |
|
|
// parity_type this is a flag indicating that parity should be even
|
46 |
|
|
// (either 'PARITY_ODD or 'PARITY_EVEN)
|
47 |
|
|
// parity_on indicates that the parity is used
|
48 |
|
|
// (either 'PARITY_OFF or 'PARITY_ON)
|
49 |
|
|
// stop_bits_num number of stop bits (either NSTOPS_1 or NSTOPS_2)
|
50 |
|
|
// data_bit_num number of data bits (either NBITS_7 or NBITS_8)
|
51 |
|
|
// baud_error baud error in precentage (-5 is -5%)
|
52 |
|
|
//
|
53 |
|
|
|
54 |
|
|
task send_serial;
|
55 |
|
|
// task input parameters
|
56 |
|
|
input [7:0] inputchar;
|
57 |
|
|
input baud;
|
58 |
|
|
input paritytype;
|
59 |
|
|
input parityenable;
|
60 |
|
|
input nstops;
|
61 |
|
|
input nbits;
|
62 |
|
|
input baud_error_factor;
|
63 |
|
|
// internal registers
|
64 |
|
|
reg nbits;
|
65 |
|
|
reg parityenable;
|
66 |
|
|
reg paritytype;
|
67 |
|
|
reg [1:0] baud;
|
68 |
|
|
reg nstops;
|
69 |
|
|
integer baud_error_factor; // e.g. +5 means 5% too fast and -5 means 5% too slow
|
70 |
|
|
reg [7:0] char;
|
71 |
|
|
reg [7:0] disp_char;
|
72 |
|
|
reg parity_bit;
|
73 |
|
|
integer bit_time;
|
74 |
|
|
integer num_of_bits;
|
75 |
|
|
// task implementation
|
76 |
|
|
begin
|
77 |
|
|
char = inputchar;
|
78 |
|
|
parity_bit = 1'b0;
|
79 |
|
|
// calculate bit time from input baud rate - this assumes a simulation resolution of 1ns
|
80 |
|
|
case (baud)
|
81 |
|
|
`BAUD_115200: bit_time = 1000000000/(115200 + 1152*baud_error_factor);
|
82 |
|
|
// `BAUD_115200: bit_time = 40000000000/(115200 + 1152*baud_error_factor);
|
83 |
|
|
`BAUD_38400: bit_time = 1000000000/(38400 + 384*baud_error_factor);
|
84 |
|
|
`BAUD_28800: bit_time = 1000000000/(28800 + 288*baud_error_factor);
|
85 |
|
|
`BAUD_19200: bit_time = 1000000000/(19200 + 192*baud_error_factor);
|
86 |
|
|
`BAUD_9600: bit_time = 1000000000/(9600 + 96*baud_error_factor);
|
87 |
|
|
`BAUD_4800: bit_time = 1000000000/(4800 + 48*baud_error_factor);
|
88 |
|
|
`BAUD_2400: bit_time = 1000000000/(2400 + 24*baud_error_factor);
|
89 |
|
|
`BAUD_1200: bit_time = 1000000000/(1200 + 12*baud_error_factor);
|
90 |
|
|
endcase
|
91 |
|
|
|
92 |
|
|
// display info
|
93 |
|
|
disp_char = (char >= 8'h20) ? char : 8'hb0;
|
94 |
|
|
$display ("Sending character 0x%h (\"%c\"), at %0d baud (err=%0d), %0d bits, %0s parity, %0d stops",
|
95 |
|
|
(nbits == `NBITS_7) ? (char & 8'h7f) : char,
|
96 |
|
|
(nbits == `NBITS_7) ? (disp_char & 8'h7f) : disp_char,
|
97 |
|
|
1000000000/bit_time,
|
98 |
|
|
baud_error_factor,
|
99 |
|
|
(nbits == `NBITS_7) ? 7 : 8,
|
100 |
|
|
(parityenable == `PARITY_OFF) ? "NONE" : (paritytype == `PARITY_EVEN) ? "EVEN" : "ODD",
|
101 |
|
|
(nstops == `NSTOPS_1) ? 1 : 2
|
102 |
|
|
);
|
103 |
|
|
|
104 |
|
|
// Start bit
|
105 |
|
|
serial_out = 1'b0; // Start bit.
|
106 |
|
|
#(bit_time);
|
107 |
|
|
|
108 |
|
|
// Output data bits
|
109 |
|
|
num_of_bits = (nbits == `NBITS_7) ? 7 : 8;
|
110 |
|
|
repeat (num_of_bits)
|
111 |
|
|
begin
|
112 |
|
|
serial_out = char[0];
|
113 |
|
|
#(bit_time);
|
114 |
|
|
char = {1'b0, char[7:1]};
|
115 |
|
|
end
|
116 |
|
|
|
117 |
|
|
// check if parity is enabled
|
118 |
|
|
if (parityenable == `PARITY_ON) begin
|
119 |
|
|
parity_bit = (nbits == `NBITS_7) ? ^inputchar[6:0] : ^inputchar[7:0];
|
120 |
|
|
// even parity
|
121 |
|
|
if (paritytype == `PARITY_ODD)
|
122 |
|
|
parity_bit = ~parity_bit;
|
123 |
|
|
|
124 |
|
|
serial_out = parity_bit;
|
125 |
|
|
#(bit_time);
|
126 |
|
|
end
|
127 |
|
|
|
128 |
|
|
// Stop bit.
|
129 |
|
|
serial_out = 1'b1;
|
130 |
|
|
#(bit_time);
|
131 |
|
|
// Second stop bit
|
132 |
|
|
if (nstops)
|
133 |
|
|
#(bit_time);
|
134 |
|
|
end
|
135 |
|
|
endtask
|
136 |
|
|
|
137 |
|
|
//------------------------------------------------------------------------------
|
138 |
|
|
// uart receive task
|
139 |
|
|
//
|
140 |
|
|
// usage:
|
141 |
|
|
// get_serial (baud_rate, parity_type, parity_on, stop_bits_num, data_bit_num);
|
142 |
|
|
// where:
|
143 |
|
|
// data data character for transmission
|
144 |
|
|
// parity_type this is a flag indicating that parity should be even
|
145 |
|
|
// (either 'PARITY_ODD or 'PARITY_EVEN)
|
146 |
|
|
// parity_on indicates that the parity is used
|
147 |
|
|
// (either 'PARITY_OFF or 'PARITY_ON)
|
148 |
|
|
// stop_bits_num number of stop bits (either NSTOPS_1 or NSTOPS_2)
|
149 |
|
|
// data_bit_num number of data bits (either NBITS_7 or NBITS_8)
|
150 |
|
|
//
|
151 |
|
|
task get_serial;
|
152 |
|
|
// input parameters
|
153 |
|
|
input baud;
|
154 |
|
|
input paritytype;
|
155 |
|
|
input parityenable;
|
156 |
|
|
input nstops;
|
157 |
|
|
input nbits;
|
158 |
|
|
// internal registers
|
159 |
|
|
reg nbits;
|
160 |
|
|
reg parityenable;
|
161 |
|
|
reg paritytype;
|
162 |
|
|
reg [1:0] baud;
|
163 |
|
|
reg nstops;
|
164 |
|
|
integer bit_time;
|
165 |
|
|
reg expected_parity;
|
166 |
|
|
integer num_of_bits;
|
167 |
|
|
// task implementation
|
168 |
|
|
begin
|
169 |
|
|
// init receive globals
|
170 |
|
|
get_serial_status = 0;
|
171 |
|
|
get_serial_data = 0;
|
172 |
|
|
|
173 |
|
|
// calculate bit time from input baud rate - this assumes a simulation resolution of 1ns
|
174 |
|
|
case (baud)
|
175 |
|
|
`BAUD_115200: bit_time = 1000000000/115200;
|
176 |
|
|
`BAUD_38400: bit_time = 1000000000/38400;
|
177 |
|
|
`BAUD_28800: bit_time = 1000000000/28800;
|
178 |
|
|
`BAUD_19200: bit_time = 1000000000/19200;
|
179 |
|
|
`BAUD_9600: bit_time = 1000000000/9600;
|
180 |
|
|
`BAUD_4800: bit_time = 1000000000/4800;
|
181 |
|
|
`BAUD_2400: bit_time = 1000000000/2400;
|
182 |
|
|
`BAUD_1200: bit_time = 1000000000/1200;
|
183 |
|
|
endcase
|
184 |
|
|
|
185 |
|
|
// Assume OK until bad things happen.
|
186 |
|
|
get_serial_status = `RECEIVE_RESULT_OK;
|
187 |
|
|
|
188 |
|
|
// wait for start bit edge
|
189 |
|
|
@(negedge serial_in);
|
190 |
|
|
|
191 |
|
|
// wait till center of start bit
|
192 |
|
|
#(bit_time/2);
|
193 |
|
|
|
194 |
|
|
// make sure its really a start bit
|
195 |
|
|
if (serial_in != 0)
|
196 |
|
|
get_serial_status = get_serial_status | `RECEIVE_RESULT_FALSESTART;
|
197 |
|
|
else
|
198 |
|
|
begin
|
199 |
|
|
// get all the data bits (7 or 8)
|
200 |
|
|
num_of_bits = (nbits == `NBITS_7) ? 7 : 8;
|
201 |
|
|
repeat (num_of_bits)
|
202 |
|
|
begin
|
203 |
|
|
// wait till center
|
204 |
|
|
#(bit_time);
|
205 |
|
|
// sample a data bit
|
206 |
|
|
get_serial_data = {serial_in, get_serial_data[7:1]};
|
207 |
|
|
end
|
208 |
|
|
|
209 |
|
|
// If we are only expecting 7 bits, go ahead and right-justify what we have
|
210 |
|
|
if (nbits == `NBITS_7)
|
211 |
|
|
get_serial_data = {1'b0, get_serial_data[7:1]};
|
212 |
|
|
|
213 |
|
|
// wait for next bit to start
|
214 |
|
|
#(bit_time);
|
215 |
|
|
|
216 |
|
|
// now, we have either a parity bit, or a stop bit
|
217 |
|
|
if (parityenable == `PARITY_ON) begin
|
218 |
|
|
if (paritytype == `PARITY_EVEN)
|
219 |
|
|
expected_parity = (nbits == `NBITS_7) ? (^get_serial_data[6:0]) :
|
220 |
|
|
(^get_serial_data[7:0]);
|
221 |
|
|
else
|
222 |
|
|
expected_parity = (nbits == `NBITS_7) ? (~(^get_serial_data[6:0])) :
|
223 |
|
|
(~(^get_serial_data[7:0]));
|
224 |
|
|
|
225 |
|
|
if (expected_parity != serial_in)
|
226 |
|
|
get_serial_status = get_serial_status | `RECEIVE_RESULT_BADPARITY;
|
227 |
|
|
end
|
228 |
|
|
// wait for either 1 or 2 stop bits
|
229 |
|
|
else begin
|
230 |
|
|
// this is a stop bit.
|
231 |
|
|
if (serial_in != 1)
|
232 |
|
|
get_serial_status = get_serial_status | `RECEIVE_RESULT_BADSTOP;
|
233 |
|
|
else
|
234 |
|
|
// that was cool. if 2 stops, then do this again
|
235 |
|
|
if (nstops)
|
236 |
|
|
begin
|
237 |
|
|
#(bit_time);
|
238 |
|
|
if (serial_in != 1)
|
239 |
|
|
get_serial_status = get_serial_status | `RECEIVE_RESULT_BADSTOP;
|
240 |
|
|
end
|
241 |
|
|
end
|
242 |
|
|
end
|
243 |
|
|
end
|
244 |
|
|
endtask
|
245 |
|
|
|