]> rtime.felk.cvut.cz Git - fpga/openmsp430.git/blob - omsp_dbg_uart.v
e52b2b5b090bdd39b50fe550fb394e08d7de9afa
[fpga/openmsp430.git] / omsp_dbg_uart.v
1 //----------------------------------------------------------------------------
2 // Copyright (C) 2001 Authors
3 //
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
7 // disclaimer.
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 2.1 of the License, or
12 // (at your option) any later version.
13 //
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.
18 //
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
22 //
23 //----------------------------------------------------------------------------
24 //
25 // *File Name: omsp_dbg_uart.v
26 // 
27 // *Module Description:
28 //                       Debug UART communication interface (8N1, Half-duplex)
29 //
30 // *Author(s):
31 //              - Olivier Girard,    olgirard@gmail.com
32 //
33 //----------------------------------------------------------------------------
34 // $Rev: 74 $
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"
40
41 module  omsp_dbg_uart (
42
43 // OUTPUTs
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
49                              
50 // INPUTs
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
60     por                             // Power on reset
61 );
62
63 // OUTPUTs
64 //=========
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
70
71 // INPUTs
72 //=========
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
83
84
85 //=============================================================================
86 // 1)  UART RECEIVE LINE SYNCHRONIZTION & FILTERING
87 //=============================================================================
88
89 // Synchronize RXD input & buffer
90 //--------------------------------
91 reg  [3:0] rxd_sync;
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};
95
96 // Majority decision
97 //------------------------
98 reg        rxd_maj;
99
100 wire [1:0] rxd_maj_cnt = {1'b0, rxd_sync[1]} +
101                          {1'b0, rxd_sync[2]} +
102                          {1'b0, rxd_sync[3]};
103 wire       rxd_maj_nxt = (rxd_maj_cnt>=2'b10);
104    
105 always @ (posedge mclk or posedge por)
106   if (por) rxd_maj <=  1'b0;
107   else     rxd_maj <=  rxd_maj_nxt;
108
109 wire rxd_s  =  rxd_maj;
110 wire rxd_fe =  rxd_maj & ~rxd_maj_nxt;
111 wire rxd_re = ~rxd_maj &  rxd_maj_nxt;
112
113    
114 //=============================================================================
115 // 2)  UART STATE MACHINE
116 //=============================================================================
117
118 // Receive state
119 //------------------------
120 reg  [2:0] uart_state;
121 reg  [2:0] uart_state_nxt;
122
123 wire       sync_done;
124 wire       xfer_done;
125 reg [19:0] xfer_buf;
126
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;
134
135 // State transition
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)
137   case (uart_state)
138     RX_SYNC  : uart_state_nxt =  RX_CMD;
139     RX_CMD   : uart_state_nxt =  mem_burst_wr                ?
140                                 (mem_bw                      ? RX_DATA2 : RX_DATA1) :
141                                  mem_burst_rd                ?
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) :
149                                  RX_CMD;
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) :
153                                  RX_CMD;
154     default  : uart_state_nxt =  RX_CMD;
155   endcase
156    
157 // State machine
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;
162
163 // Utility signals
164 wire cmd_valid = (uart_state==RX_CMD) & xfer_done;
165 wire tx_active = (uart_state==TX_DATA1) | (uart_state==TX_DATA2);
166
167    
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.
174
175 reg        sync_busy;
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;
180
181 assign sync_done =  (uart_state==RX_SYNC) & rxd_re & sync_busy;
182
183 `ifdef DBG_UART_AUTO_SYNC
184
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};
189
190 wire [`DBG_UART_XFER_CNT_W-1:0] bit_cnt_max = sync_cnt[`DBG_UART_XFER_CNT_W+2:3];
191 `else
192 wire [`DBG_UART_XFER_CNT_W-1:0] bit_cnt_max = `DBG_UART_CNT;
193 `endif
194    
195    
196 //=============================================================================
197 // 4)  UART RECEIVE / TRANSMIT
198 //=============================================================================
199    
200 // Transfer counter
201 //------------------------
202 reg                      [3:0] xfer_bit;
203 reg [`DBG_UART_XFER_CNT_W-1:0] xfer_cnt;
204
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);
209    
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;
215
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}};
221
222
223 // Receive/Transmit buffer
224 //-------------------------
225 wire [19:0] xfer_buf_nxt =  {rxd_s, xfer_buf[19:1]};
226
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;
231
232
233 // Generate TXD output
234 //------------------------
235 reg dbg_uart_txd;
236    
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];
240
241  
242 //=============================================================================
243 // 5) INTERFACE TO DEBUG REGISTERS
244 //=============================================================================
245
246 reg [5:0] dbg_addr;
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];
250
251 reg       dbg_bw;
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];
255
256 wire        dbg_din_bw =  mem_burst  ? mem_bw : dbg_bw;
257
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;
263
264             
265    
266 endmodule // omsp_dbg_uart
267
268 `include "openMSP430_undefines.v"