OpenCores
URL https://opencores.org/ocsvn/8051/8051/trunk

Subversion Repositories 8051

[/] [8051/] [trunk/] [rtl/] [verilog/] [oc8051_uart.v] - Blame information for rev 119

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 82 simont
//////////////////////////////////////////////////////////////////////
2
////                                                              ////
3
////  8051 cores serial interface                                 ////
4
////                                                              ////
5
////  This file is part of the 8051 cores project                 ////
6
////  http://www.opencores.org/cores/8051/                        ////
7
////                                                              ////
8
////  Description                                                 ////
9
////   uart for 8051 core                                         ////
10
////                                                              ////
11
////  To Do:                                                      ////
12
////   Nothing                                                    ////
13
////                                                              ////
14
////  Author(s):                                                  ////
15
////      - Simon Teran, simont@opencores.org                     ////
16
////                                                              ////
17
//////////////////////////////////////////////////////////////////////
18
////                                                              ////
19
//// Copyright (C) 2000 Authors and OPENCORES.ORG                 ////
20
////                                                              ////
21
//// This source file may be used and distributed without         ////
22
//// restriction provided that this copyright statement is not    ////
23
//// removed from the file and that any derivative work contains  ////
24
//// the original copyright notice and the associated disclaimer. ////
25
////                                                              ////
26
//// This source file is free software; you can redistribute it   ////
27
//// and/or modify it under the terms of the GNU Lesser General   ////
28
//// Public License as published by the Free Software Foundation; ////
29
//// either version 2.1 of the License, or (at your option) any   ////
30
//// later version.                                               ////
31
////                                                              ////
32
//// This source is distributed in the hope that it will be       ////
33
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
34
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
35
//// PURPOSE.  See the GNU Lesser General Public License for more ////
36
//// details.                                                     ////
37
////                                                              ////
38
//// You should have received a copy of the GNU Lesser General    ////
39
//// Public License along with this source; if not, download it   ////
40
//// from http://www.opencores.org/lgpl.shtml                     ////
41
////                                                              ////
42
//////////////////////////////////////////////////////////////////////
43
//
44
// CVS Revision History
45
//
46
// $Log: not supported by cvs2svn $
47 119 simont
// Revision 1.12  2003/04/07 14:58:02  simont
48
// change sfr's interface.
49
//
50 116 simont
// Revision 1.11  2003/04/07 13:29:16  simont
51
// change uart to meet timing.
52
//
53 115 simont
// Revision 1.10  2003/01/13 14:14:41  simont
54
// replace some modules
55
//
56 82 simont
// Revision 1.9  2002/09/30 17:33:59  simont
57
// prepared header
58
//
59
//
60
 
61
// synopsys translate_off
62
`include "oc8051_timescale.v"
63
// synopsys translate_on
64
 
65
`include "oc8051_defines.v"
66
 
67 115 simont
module oc8051_uart (rst, clk,
68
             bit_in, data_in,
69 116 simont
             wr_addr,
70 115 simont
             wr, wr_bit,
71 116 simont
             rxd, txd,
72 115 simont
             intr,
73
             brate2, t1_ow, pres_ow,
74 116 simont
             rclk, tclk,
75
//registers
76
             scon, pcon, sbuf);
77 82 simont
 
78 115 simont
input        rst,
79
             clk,
80
             bit_in,
81
             wr,
82
             rxd,
83
             wr_bit,
84
             t1_ow,
85
             brate2,
86
             pres_ow,
87
             rclk,
88
             tclk;
89 116 simont
input [7:0]  data_in,
90 115 simont
             wr_addr;
91 82 simont
 
92 115 simont
output       txd,
93 116 simont
             intr;
94
output [7:0] scon,
95
             pcon,
96
             sbuf;
97 82 simont
 
98
 
99 115 simont
reg t1_ow_buf;
100 82 simont
//
101 116 simont
reg [7:0] scon, pcon;
102 82 simont
 
103
 
104 115 simont
reg        txd,
105
           trans,
106
           receive,
107
           tx_done,
108
           rx_done,
109
           rxd_r,
110
           shift_tr,
111
           shift_re;
112
reg [1:0]  rx_sam;
113
reg [3:0]  tr_count,
114
           re_count;
115
reg [7:0]  sbuf_rxd;
116
reg [11:0] sbuf_rxd_tmp;
117 119 simont
reg [10:0] sbuf_txd;
118 115 simont
 
119 116 simont
assign sbuf = sbuf_rxd;
120 82 simont
assign intr = scon[1] | scon [0];
121
 
122
//
123
//serial port control register
124
//
125 115 simont
wire ren, tb8, rb8, ri;
126
assign ren = scon[4];
127
assign tb8 = scon[3];
128
assign rb8 = scon[2];
129
assign ri  = scon[0];
130
 
131 82 simont
always @(posedge clk or posedge rst)
132
begin
133
  if (rst)
134
    scon <= #1 `OC8051_RST_SCON;
135
  else if ((wr) & !(wr_bit) & (wr_addr==`OC8051_SFR_SCON))
136
    scon <= #1 data_in;
137
  else if ((wr) & (wr_bit) & (wr_addr[7:3]==`OC8051_SFR_B_SCON))
138
    scon[wr_addr[2:0]] <= #1 bit_in;
139 115 simont
  else if (tx_done)
140 82 simont
    scon[1] <= #1 1'b1;
141 115 simont
  else if (!rx_done) begin
142
    if (scon[7:6]==2'b00) begin
143
      scon[0] <= #1 1'b1;
144
    end else if ((sbuf_rxd_tmp[11]) | !(scon[5])) begin
145
      scon[0] <= #1 1'b1;
146
      scon[2] <= #1 sbuf_rxd_tmp[11];
147
    end else
148
      scon[2] <= #1 sbuf_rxd_tmp[11];
149
  end
150
end
151
 
152
//
153
//power control register
154
//
155
wire smod;
156
assign smod = pcon[7];
157
always @(posedge clk or posedge rst)
158
begin
159
  if (rst)
160
  begin
161
    pcon <= #1 `OC8051_RST_PCON;
162
  end else if ((wr_addr==`OC8051_SFR_PCON) & (wr) & !(wr_bit))
163
    pcon <= #1 data_in;
164
end
165
 
166
 
167
//
168
//serial port buffer (transmit)
169
//
170
 
171
wire wr_sbuf;
172
assign wr_sbuf = (wr_addr==`OC8051_SFR_SBUF) & (wr) & !(wr_bit);
173
 
174
always @(posedge clk or posedge rst)
175
begin
176
  if (rst) begin
177
    txd      <= #1 1'b1;
178
    tr_count <= #1 4'd0;
179
    trans    <= #1 1'b0;
180
    sbuf_txd <= #1 11'h00;
181
    tx_done  <= #1 1'b0;
182
//
183
// start transmiting
184
//
185
  end else if (wr_sbuf) begin
186 82 simont
    case (scon[7:6])
187 115 simont
      2'b00: begin  // mode 0
188
        sbuf_txd <= #1 {3'b001, data_in};
189 82 simont
      end
190 115 simont
      2'b01: begin // mode 1
191
        sbuf_txd <= #1 {2'b01, data_in, 1'b0};
192
      end
193
      default: begin  // mode 2 and mode 3
194
        sbuf_txd <= #1 {1'b1, tb8, data_in, 1'b0};
195
      end
196 82 simont
    endcase
197 115 simont
    trans    <= #1 1'b1;
198
    tr_count <= #1 4'd0;
199
    tx_done  <= #1 1'b0;
200
//
201
// transmiting
202
//
203
  end else if (trans & (scon[7:6] == 2'b00) & pres_ow) // mode 0
204
  begin
205
    if (~|sbuf_txd[10:1]) begin
206
      trans   <= #1 1'b0;
207
      tx_done <= #1 1'b1;
208
    end else begin
209
      {sbuf_txd, txd} <= #1 {1'b0, sbuf_txd};
210
      tx_done         <= #1 1'b0;
211
    end
212
  end else if (trans & (scon[7:6] != 2'b00) & shift_tr) begin // mode 1, 2, 3
213
    tr_count <= #1 tr_count + 4'd1;
214
    if (~|tr_count) begin
215
      if (~|sbuf_txd[10:0]) begin
216
        trans   <= #1 1'b0;
217
        tx_done <= #1 1'b1;
218
        txd <= #1 1'b1;
219
      end else begin
220
        {sbuf_txd, txd} <= #1 {1'b0, sbuf_txd};
221
        tx_done         <= #1 1'b0;
222
      end
223
    end
224
  end else if (!trans) begin
225
    txd     <= #1 1'b1;
226
    tx_done <= #1 1'b0;
227 82 simont
  end
228
end
229
 
230
//
231
//
232 115 simont
reg sc_clk_tr, smod_clk_tr;
233
always @(brate2 or t1_ow or t1_ow_buf or scon[7:6] or tclk)
234
begin
235
  if (scon[7:6]==8'b10) begin //mode 2
236
    sc_clk_tr = 1'b1;
237
  end else if (tclk) begin //
238
    sc_clk_tr = brate2;
239
  end else begin //
240
    sc_clk_tr = !t1_ow_buf & t1_ow;
241
  end
242
end
243
 
244 82 simont
always @(posedge clk or posedge rst)
245
begin
246
  if (rst) begin
247 115 simont
    smod_clk_tr <= #1 1'b0;
248
    shift_tr    <= #1 1'b0;
249
  end else if (sc_clk_tr) begin
250
    if (smod) begin
251
      shift_tr <= #1 1'b1;
252
    end else begin
253
      shift_tr    <= #1  smod_clk_tr;
254
      smod_clk_tr <= #1 !smod_clk_tr;
255
    end
256
  end else begin
257
    shift_tr <= #1 1'b0;
258
  end
259 82 simont
end
260
 
261
 
262
//
263 115 simont
//serial port buffer (receive)
264 82 simont
//
265
always @(posedge clk or posedge rst)
266
begin
267 115 simont
  if (rst) begin
268
    re_count     <= #1 4'd0;
269
    receive      <= #1 1'b0;
270
    sbuf_rxd     <= #1 8'h00;
271
    sbuf_rxd_tmp <= #1 12'd0;
272
    rx_done      <= #1 1'b1;
273
    rxd_r        <= #1 1'b1;
274
    rx_sam       <= #1 2'b00;
275
  end else if (!rx_done) begin
276
    receive <= #1 1'b0;
277
    rx_done <= #1 1'b1;
278 116 simont
    sbuf_rxd <= #1 sbuf_rxd_tmp[10:3];
279 115 simont
  end else if (receive & (scon[7:6]==2'b00) & pres_ow) begin //mode 0
280
    {sbuf_rxd_tmp, rx_done} <= #1 {rxd, sbuf_rxd_tmp};
281
  end else if (receive & (scon[7:6]!=2'b00) & shift_re) begin //mode 1, 2, 3
282
    re_count <= #1 re_count + 4'd1;
283
    case (re_count)
284
      4'h7: rx_sam[0] <= #1 rxd;
285
      4'h8: rx_sam[1] <= #1 rxd;
286
      4'h9: begin
287
        {sbuf_rxd_tmp, rx_done} <= #1 {(rxd==rx_sam[0] ? rxd : rx_sam[1]), sbuf_rxd_tmp};
288
      end
289
    endcase
290
//
291
//start receiving
292
//
293
  end else if (scon[7:6]==2'b00) begin //start mode 0
294
    rx_done <= #1 1'b1;
295
    if (ren && !ri && !receive) begin
296
      receive      <= #1 1'b1;
297
      sbuf_rxd_tmp <= #1 10'h0ff;
298
    end
299
  end else if (ren & shift_re) begin
300
    rxd_r <= #1 rxd;
301
    rx_done <= #1 1'b1;
302
    re_count <= #1 4'h0;
303
    receive <= #1 (rxd_r & !rxd);
304
    sbuf_rxd_tmp <= #1 10'h1ff;
305
  end else
306
    rx_done <= #1 1'b1;
307 82 simont
end
308
 
309
//
310
//
311 115 simont
reg sc_clk_re, smod_clk_re;
312
always @(brate2 or t1_ow or t1_ow_buf or scon[7:6] or rclk)
313
begin
314
  if (scon[7:6]==8'b10) begin //mode 2
315
    sc_clk_re = 1'b1;
316
  end else if (rclk) begin //
317
    sc_clk_re = brate2;
318
  end else begin //
319
    sc_clk_re = !t1_ow_buf & t1_ow;
320
  end
321
end
322
 
323 82 simont
always @(posedge clk or posedge rst)
324
begin
325
  if (rst) begin
326 115 simont
    smod_clk_re <= #1 1'b0;
327
    shift_re    <= #1 1'b0;
328
  end else if (sc_clk_re) begin
329
    if (smod) begin
330
      shift_re <= #1 1'b1;
331
    end else begin
332
      shift_re    <= #1  smod_clk_re;
333
      smod_clk_re <= #1 !smod_clk_re;
334
    end
335
  end else begin
336
    shift_re <= #1 1'b0;
337
  end
338
end
339
 
340
 
341 82 simont
 
342
//
343
//
344
//
345
 
346
always @(posedge clk or posedge rst)
347
begin
348
  if (rst) begin
349
    t1_ow_buf <= #1 1'b0;
350
  end else begin
351
    t1_ow_buf <= #1 t1_ow;
352
  end
353
end
354
 
355 115 simont
 
356 82 simont
 
357
endmodule
358
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.