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

Subversion Repositories hive

[/] [hive/] [trunk/] [v04.05/] [uart_tx.v] - Blame information for rev 4

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 ericw
/*
2
--------------------------------------------------------------------------------
3
 
4
Module: uart_tx.v
5
 
6
Function:
7
- Forms the TX side of a DATA_W,n,STOP_BITS RS232 UART.
8
 
9
Instantiates:
10
- functions.h
11
 
12
Notes:
13
- Rising edge of baud_clk_i is employed.
14
- baud_clk_i / BAUD_OSR = uart baud (bit) rate.
15
- baud_clk_i mist be synchronous to clk_i.
16
- Serial data is non-inverted; quiescent serial state is high (assumes
17
  external inverting buffer).
18
- Bits are in this order (@ serial port of this module, line s/b inverted):
19
  - 1 start bit (low),
20
  - DATA_W data bits (LSB first, MSB last),
21
  - 1 or more stop bits (high).
22
- The parallel data interface may be connected to a FIFO or similar.
23
- Parameterized data width.
24
- Parameterized oversampling rate.
25
- Parameterized stop bits.
26
 
27
--------------------------------------------------------------------------------
28
*/
29
 
30
module uart_tx
31
        #(
32
        parameter               integer                         DATA_W                          = 8,            // parallel data width (bits)
33
        parameter               integer                         BAUD_OSR                        = 16,           // BAUD clock oversample rate (3 or larger)
34
        parameter               integer                         STOP_BITS                       = 1             // number of stop bits
35
        )
36
        (
37
        // clocks & resets
38
        input           wire                                                    clk_i,                                                  // clock
39
        input           wire                                                    rst_i,                                                  // async. reset, active hi
40
        // timing interface
41
        input           wire                                                    baud_clk_i,                                             // baud clock
42
        // parallel interface   
43
        input           wire    [DATA_W-1:0]             tx_data_i,                                              // data
44
        output  reg                                                     tx_rdy_o,                                               // ready for data, active hi
45
        input           wire                                                    tx_wr_i,                                                        // data write, active high
46
        // serial interface
47
        output  wire                                                    tx_o                                                            // serial data
48
        );
49
 
50
 
51
        /*
52
        ----------------------
53
        -- internal signals --
54
        ----------------------
55
        */
56
        `include "functions.h"  // for clog2()
57
        //
58
        localparam              integer                         BIT_PHASE_W                     = clog2( BAUD_OSR );
59
        localparam              integer                         BIT_PHASE_MAX           = BAUD_OSR-1;
60
        localparam              integer                         BIT_COUNT_MAX           = DATA_W+STOP_BITS;
61
        localparam              integer                         BIT_COUNT_W             = clog2( BIT_COUNT_MAX );
62
        //
63
        reg                                                                             baud_clk_reg;
64
        wire                                                                            baud_flg;
65
        reg                             [DATA_W-1:0]             tx_data_reg;
66
        //
67
        reg                             [BIT_PHASE_W-1:0]        bit_phase;
68
        wire                                                                            bit_done_flg;
69
        //
70
        reg                             [BIT_COUNT_W-1:0]        bit_count;
71
        wire                                                                            word_done_flg;
72
        //
73
        reg                             [DATA_W:0]                       tx_data_sr;
74
        wire                                                                            load_flg;
75
        //
76
        localparam      integer                                 STATE_W = 2;    // state width (bits)
77
        reg                             [STATE_W-1:0]            state_sel, state;
78
        localparam              [STATE_W-1:0]
79
                st_idle = 0,
80
                st_wait = 1,
81
                st_load = 2,
82
                st_data = 3;
83
 
84
 
85
        /*
86
        ================
87
        == code start ==
88
        ================
89
        */
90
 
91
 
92
        /*
93
        -----------
94
        -- input --
95
        -----------
96
        */
97
 
98
        // register to detect edges
99
        always @ ( posedge clk_i or posedge rst_i ) begin
100
                if ( rst_i ) begin
101
                        baud_clk_reg <= 'b0;
102
                end else begin
103
                        baud_clk_reg <= baud_clk_i;
104
                end
105
        end
106
 
107
        // decode rising edge
108
        assign baud_flg = ( ~baud_clk_reg & baud_clk_i );
109
 
110
        // register parallel data
111
        always @ ( posedge clk_i or posedge rst_i ) begin
112
                if ( rst_i ) begin
113
                        tx_data_reg <= 'b0;
114
                        tx_rdy_o <= 'b1;
115
                end else begin
116
                        if ( tx_wr_i ) begin
117
                                tx_data_reg <= tx_data_i;
118
                                tx_rdy_o <= 'b0;
119
                        end else if ( load_flg ) begin
120
                                tx_rdy_o <= 'b1;
121
                        end
122
                end
123
        end
124
 
125
 
126
        /*
127
        --------------
128
        -- counters --
129
        --------------
130
        */
131
 
132
        // form the bit_phase & bit_count up-counters
133
        always @ ( posedge clk_i or posedge rst_i ) begin
134
                if ( rst_i ) begin
135
                        bit_phase <= 'b0;
136
                        bit_count <= 'b0;
137
                end else begin
138
                        if ( state_sel != st_data ) begin
139
                                bit_phase <= 'b0;
140
                                bit_count <= 'b0;
141
                        end else if ( bit_done_flg ) begin
142
                                bit_phase <= 'b0;
143
                                bit_count <= bit_count + 1'b1;
144
                        end else if ( baud_flg ) begin
145
                                bit_phase <= bit_phase + 1'b1;
146
                        end
147
                end
148
        end
149
 
150
        // decode flags
151
        assign bit_done_flg   = ( ( bit_phase == BIT_PHASE_MAX[BIT_PHASE_W-1:0] ) & baud_flg );
152
        assign word_done_flg  = ( ( bit_count == BIT_COUNT_MAX[BIT_COUNT_W-1:0] ) & bit_done_flg );
153
 
154
 
155
        /*
156
        -------------------
157
        -- state machine --
158
        -------------------
159
        */
160
 
161
        // select next state
162
        always @ ( * ) begin
163
                state_sel <= state;  // default: stay in current state
164
                case ( state )
165
                        st_idle : begin  // idle
166
                                if ( ~tx_rdy_o ) begin
167
                                        state_sel <= st_wait;  // proceed
168
                                end
169
                        end
170
                        st_wait : begin  // wait for baud sync
171
                                if ( baud_flg ) begin
172
                                        state_sel <= st_load;  // proceed
173
                                end
174
                        end
175
                        st_load : begin  // load
176
                                state_sel <= st_data;  // proceed
177
                        end
178
                        st_data : begin  // data bits
179
                                if ( word_done_flg ) begin
180
                                        if ( ~tx_rdy_o ) begin
181
                                                state_sel <= st_load;  // do again
182
                                        end else begin
183
                                                state_sel <= st_idle;  // done
184
                                        end
185
                                end
186
                        end
187
                        default : begin  // for fault tolerance
188
                                state_sel <= st_idle;
189
                        end
190
                endcase
191
        end
192
 
193
        // register state
194
        always @ ( posedge clk_i or posedge rst_i ) begin
195
                if ( rst_i ) begin
196
                        state <= st_idle;
197
                end else begin
198
                        state <= state_sel;
199
                end
200
        end
201
 
202
        // decode flags
203
        assign load_flg = ( state_sel == st_load );
204
 
205
 
206
        /*
207
        ---------------------
208
        -- data conversion --
209
        ---------------------
210
        */
211
 
212
        // parallel => serial conversion
213
        always @ ( posedge clk_i or posedge rst_i ) begin
214
                if ( rst_i ) begin
215
                        tx_data_sr <= { (DATA_W+1){1'b1} };
216
                end else begin
217
                        if ( load_flg ) begin
218
                                tx_data_sr <= { tx_data_reg, 1'b0 };
219
                        end else if ( bit_done_flg ) begin
220
                                tx_data_sr <= { 1'b1, tx_data_sr[DATA_W:1] };
221
                        end
222
                end
223
        end
224
 
225
 
226
        /*
227
        ------------
228
        -- output --
229
        ------------
230
        */
231
 
232
        // outputs
233
        assign tx_o = tx_data_sr[0];
234
 
235
 
236
endmodule

powered by: WebSVN 2.1.0

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