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

Subversion Repositories s6soc

[/] [s6soc/] [trunk/] [rtl/] [txuart.v] - Blame information for rev 2

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

Line No. Rev Author Line
1 2 dgisselq
/////////////////////////////////////////////////////////////////////////
2
//
3
//
4
// Filename:    txuart.v
5
//
6
// Project:     FPGA library development (Spartan 3E development board)
7
//
8
// Purpose:     Transmit outputs over a single UART line.
9
//
10
//      To interface with this module, connect it to your system clock,
11
//      pass it the 32 bit setup register (defined below) and the byte
12
//      of data you wish to transmit.  Strobe the i_wr line high for one
13
//      clock cycle, and your data will be off.  Wait until the 'o_busy'
14
//      line is low before strobing the i_wr line again--this implementation
15
//      has NO BUFFER, so strobing i_wr while the core is busy will just
16
//      cause your data to be lost.  The output will be placed on the o_txuart
17
//      output line.  If you wish to set/send a break condition, assert the
18
//      i_break line otherwise leave it low.
19
//
20
//      There is a synchronous reset line, logic high.
21
//
22
//      Now for the setup register.  The register is 32 bits, so that this
23
//      UART may be set up over a 32-bit bus.
24
//
25
//      i_setup[29:28]  Indicates the number of data bits per word.  This will
26
//      either be 2'b00 for an 8-bit word, 2'b01 for a 7-bit word, 2'b10
27
//      for a six bit word, or 2'b11 for a five bit word.
28
//
29
//      i_setup[27]     Indicates whether or not to use one or two stop bits.
30
//              Set this to one to expect two stop bits, zero for one.
31
//
32
//      i_setup[26]     Indicates whether or not a parity bit exists.  Set this
33
//              to 1'b1 to include parity.
34
//
35
//      i_setup[25]     Indicates whether or not the parity bit is fixed.  Set
36
//              to 1'b1 to include a fixed bit of parity, 1'b0 to allow the
37
//              parity to be set based upon data.  (Both assume the parity
38
//              enable value is set.)
39
//
40
//      i_setup[24]     This bit is ignored if parity is not used.  Otherwise,
41
//              in the case of a fixed parity bit, this bit indicates whether
42
//              mark (1'b1) or space (1'b0) parity is used.  Likewise if the
43
//              parity is not fixed, a 1'b1 selects even parity, and 1'b0
44
//              selects odd.
45
//
46
//      i_setup[23:0]   Indicates the speed of the UART in terms of clocks.
47
//              So, for example, if you have a 200 MHz clock and wish to
48
//              run your UART at 9600 baud, you would take 200 MHz and divide
49
//              by 9600 to set this value to 24'd20834.  Likewise if you wished
50
//              to run this serial port at 115200 baud from a 200 MHz clock,
51
//              you would set the value to 24'd1736
52
//
53
//      Thus, to set the UART for the common setting of an 8-bit word, 
54
//      one stop bit, no parity, and 115200 baud over a 200 MHz clock, you
55
//      would want to set the setup value to:
56
//
57
//      32'h0006c8              // For 115,200 baud, 8 bit, no parity
58
//      32'h005161              // For 9600 baud, 8 bit, no parity
59
//      
60
// Creator:     Dan Gisselquist
61
//              Gisselquist Technology, LLC
62
//
63
// Copyright:   2015
64
//
65
//
66
/////////////////////////////////////////////////////////////////////////
67
//
68
// This software is the ownership of Gisselquist Technology, LLC, and as
69
// such it is proprietary.  It is provided without any warrantees, either
70
// express or implied, so that it may be tested.  Upon completion, I ask
71
// that working code be returned and not further distributed beyond those
72
// that it is originally offered to.
73
//
74
// Thank you.
75
//
76
`define TXU_BIT_ZERO    4'h0
77
`define TXU_BIT_ONE     4'h1
78
`define TXU_BIT_TWO     4'h2
79
`define TXU_BIT_THREE   4'h3
80
`define TXU_BIT_FOUR    4'h4
81
`define TXU_BIT_FIVE    4'h5
82
`define TXU_BIT_SIX     4'h6
83
`define TXU_BIT_SEVEN   4'h7
84
`define TXU_PARITY      4'h8    // Constant 1
85
`define TXU_STOP        4'h9    // Constant 1
86
`define TXU_SECOND_STOP 4'ha
87
// 4'hb // Unused
88
// 4'hc // Unused
89
// `define      TXU_START       4'hd    // An unused state
90
`define TXU_BREAK       4'he
91
`define TXU_IDLE        4'hf
92
 
93
module txuart(i_clk, i_reset, i_setup, i_break, i_wr, i_data, o_uart, o_busy);
94
        input                   i_clk, i_reset;
95
        input           [29:0]   i_setup;
96
        input                   i_break;
97
        input                   i_wr;
98
        input           [7:0]    i_data;
99
        output  reg             o_uart, o_busy;
100
 
101
        wire    [27:0]   clocks_per_baud, break_condition;
102
        wire    [1:0]    data_bits;
103
        wire            use_parity, parity_even, dblstop, fixd_parity;
104
        reg     [29:0]   r_setup;
105
        assign  clocks_per_baud = { 4'h0, r_setup[23:0] };
106
        assign  break_condition = { r_setup[23:0], 4'h0 };
107
        assign  data_bits   = r_setup[29:28];
108
        assign  dblstop     = r_setup[27];
109
        assign  use_parity  = r_setup[26];
110
        assign  fixd_parity = r_setup[25];
111
        assign  parity_even = r_setup[24];
112
 
113
        reg     [27:0]   baud_counter;
114
        reg     [3:0]    state;
115
        reg     [7:0]    lcl_data;
116
        reg             calc_parity;
117
 
118
        initial o_uart = 1'b1;
119
        initial o_busy = 1'b1;
120
        initial state  = `TXU_IDLE;
121
        // initial      baud_counter = clocks_per_baud;
122
        always @(posedge i_clk)
123
        begin
124
                if (i_reset)
125
                begin
126
                        baud_counter <= clocks_per_baud;
127
                        o_uart <= 1'b1;
128
                        o_busy <= 1'b1;
129
                        state <= `TXU_IDLE;
130
                        lcl_data <= 8'h0;
131
                        calc_parity <= 1'b0;
132
                end else if (i_break)
133
                begin
134
                        baud_counter <= break_condition;
135
                        o_uart <= 1'b0;
136
                        state <= `TXU_BREAK;
137
                        calc_parity <= 1'b0;
138
                        o_busy <= 1'b1;
139
                end else if (baud_counter != 0)
140
                begin // o_busy needs to be set coming into here
141
                        baud_counter <= baud_counter - 28'h01;
142
                        o_busy <= 1'b1;
143
                end else if (state == `TXU_BREAK)
144
                begin
145
                        state <= `TXU_IDLE;
146
                        o_busy <= 1'b1;
147
                        o_uart <= 1'b1;
148
                        calc_parity <= 1'b0;
149
                        // Give us two stop bits before becoming available
150
                        baud_counter <= clocks_per_baud<<2;
151
                end else if (state == `TXU_IDLE)        // STATE_IDLE
152
                begin
153
                        // baud_counter <= 0;
154
                        r_setup <= i_setup;
155
                        calc_parity <= 1'b0;
156
                        if ((i_wr)&&(~o_busy))
157
                        begin   // Immediately start us off with a start bit
158
                                o_uart <= 1'b0;
159
                                o_busy <= 1'b1;
160
                                case(data_bits)
161
                                2'b00: state <= `TXU_BIT_ZERO;
162
                                2'b01: state <= `TXU_BIT_ONE;
163
                                2'b10: state <= `TXU_BIT_TWO;
164
                                2'b11: state <= `TXU_BIT_THREE;
165
                                endcase
166
                                lcl_data <= i_data;
167
                                baud_counter <= clocks_per_baud-28'h01;
168
                        end else begin // Stay in idle
169
                                o_uart <= 1'b1;
170
                                o_busy <= 0;
171
                                // lcl_data is irrelevant
172
                                // state <= state;
173
                        end
174
                end else begin
175
                        // One clock tick in each of these states ...
176
                        baud_counter <= clocks_per_baud - 28'h01;
177
                        o_busy <= 1'b1;
178
                        if (state[3] == 0) // First 8 bits
179
                        begin
180
                                o_uart <= lcl_data[0];
181
                                calc_parity <= calc_parity ^ lcl_data[0];
182
                                if (state == `TXU_BIT_SEVEN)
183
                                        state <= (use_parity)?`TXU_PARITY:`TXU_STOP;
184
                                else
185
                                        state <= state + 1;
186
                                lcl_data <= { 1'b0, lcl_data[7:1] };
187
                        end else if (state == `TXU_PARITY)
188
                        begin
189
                                state <= `TXU_STOP;
190
                                if (fixd_parity)
191
                                        o_uart <= parity_even;
192
                                else
193
                                        o_uart <= calc_parity^((parity_even)? 1'b1:1'b0);
194
                        end else if (state == `TXU_STOP)
195
                        begin // two stop bit(s)
196
                                o_uart <= 1'b1;
197
                                if (dblstop)
198
                                        state <= `TXU_SECOND_STOP;
199
                                else
200
                                        state <= `TXU_IDLE;
201
                                calc_parity <= 1'b0;
202
                        end else // `TXU_SECOND_STOP and default:
203
                        begin
204
                                state <= `TXU_IDLE; // Go back to idle
205
                                o_uart <= 1'b1;
206
                                // Still o_busy, since we need to wait
207
                                // for the baud clock to finish counting
208
                                // out this last bit.
209
                        end
210
                end
211
        end
212
 
213
endmodule
214
 
215
 
216
 
217
 

powered by: WebSVN 2.1.0

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