1 //----------------------------------------------------------------------------
2 // Copyright (C) 2001 Authors
4 // This source file may be used and distributed without restriction provided
5 // that this copyright statement is not removed from the file and that any
6 // derivative work contains the original copyright notice and the associated
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 2.1 of the License, or
12 // (at your option) any later version.
14 // This source is distributed in the hope that it will be useful, but WITHOUT
15 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17 // License for more details.
19 // You should have received a copy of the GNU Lesser General Public License
20 // along with this source; if not, write to the Free Software Foundation,
21 // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 //----------------------------------------------------------------------------
25 // *File Name: omsp_dbg_uart.v
27 // *Module Description:
28 // Debug UART communication interface (8N1, Half-duplex)
31 // - Olivier Girard, olgirard@gmail.com
33 //----------------------------------------------------------------------------
35 // $LastChangedBy: olivier.girard $
36 // $LastChangedDate: 2010-08-28 21:53:08 +0200 (Sat, 28 Aug 2010) $
37 //----------------------------------------------------------------------------
38 `include "timescale.v"
39 `include "openMSP430_defines.v"
41 module omsp_dbg_uart (
44 dbg_addr, // Debug register address
45 dbg_din, // Debug register data input
46 dbg_rd, // Debug register data read
47 dbg_uart_txd, // Debug interface: UART TXD
48 dbg_wr, // Debug register data write
51 dbg_dout, // Debug register data output
52 dbg_rd_rdy, // Debug register data is ready for read
53 dbg_uart_rxd, // Debug interface: UART RXD
54 mclk, // Main system clock
55 mem_burst, // Burst on going
56 mem_burst_end, // End TX/RX burst
57 mem_burst_rd, // Start TX burst
58 mem_burst_wr, // Start RX burst
59 mem_bw, // Burst byte width
65 output [5:0] dbg_addr; // Debug register address
66 output [15:0] dbg_din; // Debug register data input
67 output dbg_rd; // Debug register data read
68 output dbg_uart_txd; // Debug interface: UART TXD
69 output dbg_wr; // Debug register data write
73 input [15:0] dbg_dout; // Debug register data output
74 input dbg_rd_rdy; // Debug register data is ready for read
75 input dbg_uart_rxd; // Debug interface: UART RXD
76 input mclk; // Main system clock
77 input mem_burst; // Burst on going
78 input mem_burst_end; // End TX/RX burst
79 input mem_burst_rd; // Start TX burst
80 input mem_burst_wr; // Start RX burst
81 input mem_bw; // Burst byte width
82 input por; // Power on reset
85 //=============================================================================
86 // 1) UART RECEIVE LINE SYNCHRONIZTION & FILTERING
87 //=============================================================================
89 // Synchronize RXD input & buffer
90 //--------------------------------
92 always @ (posedge mclk or posedge por)
93 if (por) rxd_sync <= 4'h0;
94 else rxd_sync <= {rxd_sync[2:0], dbg_uart_rxd};
97 //------------------------
100 wire [1:0] rxd_maj_cnt = {1'b0, rxd_sync[1]} +
101 {1'b0, rxd_sync[2]} +
103 wire rxd_maj_nxt = (rxd_maj_cnt>=2'b10);
105 always @ (posedge mclk or posedge por)
106 if (por) rxd_maj <= 1'b0;
107 else rxd_maj <= rxd_maj_nxt;
109 wire rxd_s = rxd_maj;
110 wire rxd_fe = rxd_maj & ~rxd_maj_nxt;
111 wire rxd_re = ~rxd_maj & rxd_maj_nxt;
114 //=============================================================================
115 // 2) UART STATE MACHINE
116 //=============================================================================
119 //------------------------
120 reg [2:0] uart_state;
121 reg [2:0] uart_state_nxt;
127 // State machine definition
128 parameter RX_SYNC = 3'h0;
129 parameter RX_CMD = 3'h1;
130 parameter RX_DATA1 = 3'h2;
131 parameter RX_DATA2 = 3'h3;
132 parameter TX_DATA1 = 3'h4;
133 parameter TX_DATA2 = 3'h5;
136 always @(uart_state or xfer_buf or mem_burst or mem_burst_wr or mem_burst_rd or mem_burst_end or mem_bw)
138 RX_SYNC : uart_state_nxt = RX_CMD;
139 RX_CMD : uart_state_nxt = mem_burst_wr ?
140 (mem_bw ? RX_DATA2 : RX_DATA1) :
142 (mem_bw ? TX_DATA2 : TX_DATA1) :
143 (xfer_buf[`DBG_UART_WR] ?
144 (xfer_buf[`DBG_UART_BW] ? RX_DATA2 : RX_DATA1) :
145 (xfer_buf[`DBG_UART_BW] ? TX_DATA2 : TX_DATA1));
146 RX_DATA1 : uart_state_nxt = RX_DATA2;
147 RX_DATA2 : uart_state_nxt = (mem_burst & ~mem_burst_end) ?
148 (mem_bw ? RX_DATA2 : RX_DATA1) :
150 TX_DATA1 : uart_state_nxt = TX_DATA2;
151 TX_DATA2 : uart_state_nxt = (mem_burst & ~mem_burst_end) ?
152 (mem_bw ? TX_DATA2 : TX_DATA1) :
154 default : uart_state_nxt = RX_CMD;
158 always @(posedge mclk or posedge por)
159 if (por) uart_state <= RX_SYNC;
160 else if (xfer_done | sync_done |
161 mem_burst_wr | mem_burst_rd) uart_state <= uart_state_nxt;
164 wire cmd_valid = (uart_state==RX_CMD) & xfer_done;
165 wire tx_active = (uart_state==TX_DATA1) | (uart_state==TX_DATA2);
168 //=============================================================================
169 // 3) UART SYNCHRONIZATION
170 //=============================================================================
171 // After POR, the host needs to fist send a synchronization character (0x80)
172 // If this feature doesn't work properly, it is possible to disable it by
173 // commenting the DBG_UART_AUTO_SYNC define in the openMSP430.inc file.
176 always @ (posedge mclk or posedge por)
177 if (por) sync_busy <= 1'b0;
178 else if ((uart_state==RX_SYNC) & rxd_fe) sync_busy <= 1'b1;
179 else if ((uart_state==RX_SYNC) & rxd_re) sync_busy <= 1'b0;
181 assign sync_done = (uart_state==RX_SYNC) & rxd_re & sync_busy;
183 `ifdef DBG_UART_AUTO_SYNC
185 reg [`DBG_UART_XFER_CNT_W+2:0] sync_cnt;
186 always @ (posedge mclk or posedge por)
187 if (por) sync_cnt <= {{`DBG_UART_XFER_CNT_W{1'b1}}, 3'b000};
188 else if (sync_busy) sync_cnt <= sync_cnt+{{`DBG_UART_XFER_CNT_W+2{1'b0}}, 1'b1};
190 wire [`DBG_UART_XFER_CNT_W-1:0] bit_cnt_max = sync_cnt[`DBG_UART_XFER_CNT_W+2:3];
192 wire [`DBG_UART_XFER_CNT_W-1:0] bit_cnt_max = `DBG_UART_CNT;
196 //=============================================================================
197 // 4) UART RECEIVE / TRANSMIT
198 //=============================================================================
201 //------------------------
203 reg [`DBG_UART_XFER_CNT_W-1:0] xfer_cnt;
205 wire txd_start = dbg_rd_rdy | (xfer_done & (uart_state==TX_DATA1));
206 wire rxd_start = (xfer_bit==4'h0) & rxd_fe & ((uart_state!=RX_SYNC));
207 wire xfer_bit_inc = (xfer_bit!=4'h0) & (xfer_cnt=={`DBG_UART_XFER_CNT_W{1'b0}});
208 assign xfer_done = (xfer_bit==4'hb);
210 always @ (posedge mclk or posedge por)
211 if (por) xfer_bit <= 4'h0;
212 else if (txd_start | rxd_start) xfer_bit <= 4'h1;
213 else if (xfer_done) xfer_bit <= 4'h0;
214 else if (xfer_bit_inc) xfer_bit <= xfer_bit+4'h1;
216 always @ (posedge mclk or posedge por)
217 if (por) xfer_cnt <= {`DBG_UART_XFER_CNT_W{1'b0}};
218 else if (rxd_start) xfer_cnt <= {1'b0, bit_cnt_max[`DBG_UART_XFER_CNT_W-1:1]};
219 else if (txd_start | xfer_bit_inc) xfer_cnt <= bit_cnt_max;
220 else xfer_cnt <= xfer_cnt+{`DBG_UART_XFER_CNT_W{1'b1}};
223 // Receive/Transmit buffer
224 //-------------------------
225 wire [19:0] xfer_buf_nxt = {rxd_s, xfer_buf[19:1]};
227 always @ (posedge mclk or posedge por)
228 if (por) xfer_buf <= 18'h00000;
229 else if (dbg_rd_rdy) xfer_buf <= {1'b1, dbg_dout[15:8], 2'b01, dbg_dout[7:0], 1'b0};
230 else if (xfer_bit_inc) xfer_buf <= xfer_buf_nxt;
233 // Generate TXD output
234 //------------------------
237 always @ (posedge mclk or posedge por)
238 if (por) dbg_uart_txd <= 1'b1;
239 else if (xfer_bit_inc & tx_active) dbg_uart_txd <= xfer_buf[0];
242 //=============================================================================
243 // 5) INTERFACE TO DEBUG REGISTERS
244 //=============================================================================
247 always @ (posedge mclk or posedge por)
248 if (por) dbg_addr <= 6'h00;
249 else if (cmd_valid) dbg_addr <= xfer_buf[`DBG_UART_ADDR];
252 always @ (posedge mclk or posedge por)
253 if (por) dbg_bw <= 1'b0;
254 else if (cmd_valid) dbg_bw <= xfer_buf[`DBG_UART_BW];
256 wire dbg_din_bw = mem_burst ? mem_bw : dbg_bw;
258 wire [15:0] dbg_din = dbg_din_bw ? {8'h00, xfer_buf[18:11]} :
259 {xfer_buf[18:11], xfer_buf[8:1]};
260 wire dbg_wr = (xfer_done & (uart_state==RX_DATA2));
261 wire dbg_rd = mem_burst ? (xfer_done & (uart_state==TX_DATA2)) :
262 (cmd_valid & ~xfer_buf[`DBG_UART_WR]) | mem_burst_rd;
266 endmodule // omsp_dbg_uart
268 `include "openMSP430_undefines.v"