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

Subversion Repositories oms8051mini

[/] [oms8051mini/] [trunk/] [rtl/] [8051/] [oc8051_uart.v] - Blame information for rev 36

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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