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

Subversion Repositories uart6551

[/] [uart6551/] [trunk/] [trunk/] [rtl/] [uart6551Tx.sv] - Blame information for rev 3

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

Line No. Rev Author Line
1 2 robfinch
// ============================================================================
2
//        __
3
//   \\__/ o\    (C) 2004-2019  Robert Finch, Waterloo
4
//    \  __ /    All rights reserved.
5
//     \/_//     robfinch@finitron.ca
6
//       ||
7
//
8
//
9
// This source file is free software: you can redistribute it and/or modify
10
// it under the terms of the GNU Lesser General Public License as published
11
// by the Free Software Foundation, either version 3 of the License, or
12
// (at your option) any later version.
13
//
14
// This source file is distributed in the hope that it will be useful,
15
// but WITHOUT ANY WARRANTY; without even the implied warranty of
16
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
// GNU General Public License for more details.
18
//
19
// You should have received a copy of the GNU General Public License
20
// along with this program.  If not, see .
21
//
22
// ============================================================================
23
//
24
`define IDLE    0
25
`define CNT             1
26
 
27 3 robfinch
//`define UART_NO_TX_FIFO       1'b1
28
 
29 2 robfinch
module uart6551Tx(rst, clk, cyc, cs, wr, din, ack,
30
        fifoEnable, fifoClear, txBreak,
31
        frameSize, wordLength, parityCtrl, baud16x_ce,
32
        cts, clear, txd, full, empty, qcnt);
33
 
34
input rst;
35
input clk;
36
input cyc;                      // bus cycle valid
37
input cs;                       // core select
38
input wr;                       // write transmitter
39
input [7:0] din;                // fifo data in
40
output ack;
41
 
42
input fifoEnable;
43
input fifoClear;
44
input txBreak;
45
input [7:0] frameSize;
46
input [3:0] wordLength;
47
input [2:0] parityCtrl;
48
input baud16x_ce;       // baud rate clock enable
49
input cts;                      // clear to send
50
input clear;            // clear transmitter
51
output reg txd;         // external serial output
52
output full;            // fifo is full
53
output empty;           // fifo is empty
54
output [3:0] qcnt;      // number of characters queued
55
 
56
reg [7:0] t1;
57
reg [11:0] t2;
58
reg [11:0] tx_data;     // transmit data working reg (raw)
59
reg state;                      // state machine state
60
reg [7:0] cnt;          // baud clock counter
61
reg rd;
62
reg p1, p2;                     // parity bit
63
 
64
assign ack = cyc & cs;
65
edge_det ued1 (.rst(rst), .clk(clk), .ce(1'b1), .i(ack & wr), .pe(awr), .ne(), .ee());
66
 
67
`ifdef UART_NO_TX_FIFO
68 3 robfinch
reg [7:0] fdo2;
69 2 robfinch
reg empty;
70
 
71
always @(posedge clk)
72 3 robfinch
        if (awr) fdo2 <= {3'd0,din};
73 2 robfinch
 
74
always @(posedge clk)
75
        begin
76
                if (awr) empty <= 0;
77
                else if (rd) empty <= 1;
78
        end
79
 
80
assign full = ~empty;
81 3 robfinch
wire [7:0] fdo = fdo2;
82 2 robfinch
`else
83 3 robfinch
reg [7:0] fdo2;
84
always @(posedge clk)
85
        if (awr) fdo2 <= {3'd0,din};
86 2 robfinch
// generate an empty signal for when the fifo is disabled
87
reg fempty2;
88
always @(posedge clk)
89
        if (rst)
90
                fempty2 <= 1;
91
        else begin
92
                if (awr) fempty2 <= 0;
93
                else if (rd) fempty2 <= 1;
94
        end
95
 
96
 
97 3 robfinch
wire [7:0] fdo1;                // fifo data output
98 2 robfinch
wire rdf = fifoEnable ? rd : awr;
99
wire fempty;
100
wire ffull;
101
uart6551Fifo #(.WID(8)) fifo0
102
(
103
  .clk(clk),
104
  .rst(rst|clear|fifoClear),
105
  .din(din),
106
  .wr(awr),
107
  .rd(rdf),
108 3 robfinch
  .dout(fdo1),
109 2 robfinch
  .full(ffull),
110
  .empty(fempty),
111
  .ctr(qcnt)
112
);
113
assign empty = fifoEnable ? fempty : fempty2;
114
assign full = fifoEnable ? ffull : ~fempty2;
115 3 robfinch
wire [7:0] fdo = fifoEnable ? fdo1 : fdo2;
116 2 robfinch
`endif
117
 
118
// mask transmit data for word length
119
// this mask is needed for proper parity generation
120
integer n;
121
reg [7:0] mask;
122
always @*
123
        for (n = 0; n < 8; n = n + 1)
124
                mask[n] = n < wordLength ? 1'b1 : 1'b0;
125
 
126
always @*
127
if (txBreak)
128
        t1 <= 0;
129
else
130
        t1 <= fdo & mask;
131
 
132
 
133
// compute parity bit
134
always @*
135
begin
136
        case (parityCtrl)
137
        3'b001: p1 <= ~^t1;// odd parity
138
        3'b011: p1 <= ^t1;      // even parity
139
        3'b101: p1 <= 1;        // mark bit
140
        3'b111: p1 <= 0;        // space bit
141
        default: p1 <= 1;       // stop bit when no parity
142
        endcase
143
end
144
 
145
/*
146
Could pipeline this, but then watch out for empty signal control
147
always @(posedge clk)
148
        if (ce) t2 <= t1;
149
 
150
always @(posedge clk)
151
        if (ce) p2 <= p1;
152
*/
153
// Insert start, parity bit and stop
154
always @*
155
case(wordLength)
156
4'd5:   t2 <= {5'b11111,p1,t1[4:0],1'b0};
157
4'd6:   t2 <= {4'b1111,p1,t1[5:0],1'b0};
158
4'd7:   t2 <= {3'b111,p1,t1[6:0],1'b0};
159
default:        t2 <= {2'b11,p1,t1[7:0],1'b0};
160
endcase
161
 
162
always @(posedge clk)
163
if (rst)
164
        state <= `IDLE;
165
else begin
166
        if (clear)
167
                state <= `IDLE;
168
        if (baud16x_ce) begin
169
                case(state)
170
                `IDLE:
171
                        if ((!empty && cts)||txBreak)
172
                                state <= `CNT;
173
                `CNT:
174
                        if (cnt==frameSize)
175
                                state <= `IDLE;
176
                endcase
177
        end
178
end
179
 
180
always @(posedge clk)
181
if (rst)
182
        cnt <= 8'h00;
183
else begin
184
        if (clear)
185
                cnt <= 8'h00;
186
        if (baud16x_ce) begin
187
                case(state)
188
                `IDLE:
189
                        cnt <= 8'h00;
190
                `CNT:
191
                        cnt <= cnt + 8'd1;
192
                endcase
193
        end
194
end
195
 
196
always @(posedge clk)
197
if (rst)
198
        rd <= 0;
199
else begin
200
        rd <= 0;
201
        if (clear)
202
                rd <= 0;
203
        if (baud16x_ce) begin
204
                case(state)
205
                `IDLE:
206
                        if ((!empty && cts)||txBreak)
207
                                rd <= 1;
208
                endcase
209
        end
210
end
211
 
212
always @(posedge clk)
213
if (rst)
214
        tx_data <= 12'hFFF;
215
else begin
216
        if (baud16x_ce) begin
217
                case(state)
218
                `IDLE:
219
                        if ((!empty && cts)||txBreak)
220
                                tx_data <= t2;
221
                `CNT:
222
                        // Shift the data out. LSB first.
223
                        if (cnt[3:0]==4'hF)
224
                                tx_data <= {1'b1,tx_data[11:1]};
225
                endcase
226
        end
227
end
228
 
229
always @(posedge clk)
230
if (rst)
231
        txd <= 1'b1;
232
else
233
        txd <= tx_data[0];
234
 
235
endmodule

powered by: WebSVN 2.1.0

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