diff options
Diffstat (limited to 'tests/openmsp430/rtl/omsp_dbg_uart.v')
-rw-r--r-- | tests/openmsp430/rtl/omsp_dbg_uart.v | 298 |
1 files changed, 298 insertions, 0 deletions
diff --git a/tests/openmsp430/rtl/omsp_dbg_uart.v b/tests/openmsp430/rtl/omsp_dbg_uart.v new file mode 100644 index 000000000..319099a5f --- /dev/null +++ b/tests/openmsp430/rtl/omsp_dbg_uart.v @@ -0,0 +1,298 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2009 , Olivier Girard +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the authors nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +// THE POSSIBILITY OF SUCH DAMAGE +// +//---------------------------------------------------------------------------- +// +// *File Name: omsp_dbg_uart.v +// +// *Module Description: +// Debug UART communication interface (8N1, Half-duplex) +// +// *Author(s): +// - Olivier Girard, olgirard@gmail.com +// +//---------------------------------------------------------------------------- +// $Rev: 134 $ +// $LastChangedBy: olivier.girard $ +// $LastChangedDate: 2012-03-22 21:31:06 +0100 (Thu, 22 Mar 2012) $ +//---------------------------------------------------------------------------- +`ifdef OMSP_NO_INCLUDE +`else +`include "openMSP430_defines.v" +`endif + +module omsp_dbg_uart ( + +// OUTPUTs + dbg_addr, // Debug register address + dbg_din, // Debug register data input + dbg_rd, // Debug register data read + dbg_uart_txd, // Debug interface: UART TXD + dbg_wr, // Debug register data write + +// INPUTs + dbg_clk, // Debug unit clock + dbg_dout, // Debug register data output + dbg_rd_rdy, // Debug register data is ready for read + dbg_rst, // Debug unit reset + dbg_uart_rxd, // Debug interface: UART RXD + mem_burst, // Burst on going + mem_burst_end, // End TX/RX burst + mem_burst_rd, // Start TX burst + mem_burst_wr, // Start RX burst + mem_bw // Burst byte width +); + +// OUTPUTs +//========= +output [5:0] dbg_addr; // Debug register address +output [15:0] dbg_din; // Debug register data input +output dbg_rd; // Debug register data read +output dbg_uart_txd; // Debug interface: UART TXD +output dbg_wr; // Debug register data write + +// INPUTs +//========= +input dbg_clk; // Debug unit clock +input [15:0] dbg_dout; // Debug register data output +input dbg_rd_rdy; // Debug register data is ready for read +input dbg_rst; // Debug unit reset +input dbg_uart_rxd; // Debug interface: UART RXD +input mem_burst; // Burst on going +input mem_burst_end; // End TX/RX burst +input mem_burst_rd; // Start TX burst +input mem_burst_wr; // Start RX burst +input mem_bw; // Burst byte width + + +//============================================================================= +// 1) UART RECEIVE LINE SYNCHRONIZTION & FILTERING +//============================================================================= + +// Synchronize RXD input +//-------------------------------- +`ifdef SYNC_DBG_UART_RXD + + wire uart_rxd_n; + + omsp_sync_cell sync_cell_uart_rxd ( + .data_out (uart_rxd_n), + .data_in (~dbg_uart_rxd), + .clk (dbg_clk), + .rst (dbg_rst) + ); + wire uart_rxd = ~uart_rxd_n; +`else + wire uart_rxd = dbg_uart_rxd; +`endif + +// RXD input buffer +//-------------------------------- +reg [1:0] rxd_buf; +always @ (posedge dbg_clk or posedge dbg_rst) + if (dbg_rst) rxd_buf <= 2'h3; + else rxd_buf <= {rxd_buf[0], uart_rxd}; + +// Majority decision +//------------------------ +reg rxd_maj; + +wire rxd_maj_nxt = (uart_rxd & rxd_buf[0]) | + (uart_rxd & rxd_buf[1]) | + (rxd_buf[0] & rxd_buf[1]); + +always @ (posedge dbg_clk or posedge dbg_rst) + if (dbg_rst) rxd_maj <= 1'b1; + else rxd_maj <= rxd_maj_nxt; + +wire rxd_s = rxd_maj; +wire rxd_fe = rxd_maj & ~rxd_maj_nxt; +wire rxd_re = ~rxd_maj & rxd_maj_nxt; +wire rxd_edge = rxd_maj ^ rxd_maj_nxt; + +//============================================================================= +// 2) UART STATE MACHINE +//============================================================================= + +// Receive state +//------------------------ +reg [2:0] uart_state; +reg [2:0] uart_state_nxt; + +wire sync_done; +wire xfer_done; +reg [19:0] xfer_buf; +wire [19:0] xfer_buf_nxt; + +// State machine definition +parameter RX_SYNC = 3'h0; +parameter RX_CMD = 3'h1; +parameter RX_DATA1 = 3'h2; +parameter RX_DATA2 = 3'h3; +parameter TX_DATA1 = 3'h4; +parameter TX_DATA2 = 3'h5; + +// State transition +always @(uart_state or xfer_buf_nxt or mem_burst or mem_burst_wr or mem_burst_rd or mem_burst_end or mem_bw) + case (uart_state) + RX_SYNC : uart_state_nxt = RX_CMD; + RX_CMD : uart_state_nxt = mem_burst_wr ? + (mem_bw ? RX_DATA2 : RX_DATA1) : + mem_burst_rd ? + (mem_bw ? TX_DATA2 : TX_DATA1) : + (xfer_buf_nxt[`DBG_UART_WR] ? + (xfer_buf_nxt[`DBG_UART_BW] ? RX_DATA2 : RX_DATA1) : + (xfer_buf_nxt[`DBG_UART_BW] ? TX_DATA2 : TX_DATA1)); + RX_DATA1 : uart_state_nxt = RX_DATA2; + RX_DATA2 : uart_state_nxt = (mem_burst & ~mem_burst_end) ? + (mem_bw ? RX_DATA2 : RX_DATA1) : + RX_CMD; + TX_DATA1 : uart_state_nxt = TX_DATA2; + TX_DATA2 : uart_state_nxt = (mem_burst & ~mem_burst_end) ? + (mem_bw ? TX_DATA2 : TX_DATA1) : + RX_CMD; + // pragma coverage off + default : uart_state_nxt = RX_CMD; + // pragma coverage on + endcase + +// State machine +always @(posedge dbg_clk or posedge dbg_rst) + if (dbg_rst) uart_state <= RX_SYNC; + else if (xfer_done | sync_done | + mem_burst_wr | mem_burst_rd) uart_state <= uart_state_nxt; + +// Utility signals +wire cmd_valid = (uart_state==RX_CMD) & xfer_done; +wire rx_active = (uart_state==RX_DATA1) | (uart_state==RX_DATA2) | (uart_state==RX_CMD); +wire tx_active = (uart_state==TX_DATA1) | (uart_state==TX_DATA2); + + +//============================================================================= +// 3) UART SYNCHRONIZATION +//============================================================================= +// After DBG_RST, the host needs to fist send a synchronization character (0x80) +// If this feature doesn't work properly, it is possible to disable it by +// commenting the DBG_UART_AUTO_SYNC define in the openMSP430.inc file. + +reg sync_busy; +always @ (posedge dbg_clk or posedge dbg_rst) + if (dbg_rst) sync_busy <= 1'b0; + else if ((uart_state==RX_SYNC) & rxd_fe) sync_busy <= 1'b1; + else if ((uart_state==RX_SYNC) & rxd_re) sync_busy <= 1'b0; + +assign sync_done = (uart_state==RX_SYNC) & rxd_re & sync_busy; + +`ifdef DBG_UART_AUTO_SYNC + +reg [`DBG_UART_XFER_CNT_W+2:0] sync_cnt; +always @ (posedge dbg_clk or posedge dbg_rst) + if (dbg_rst) sync_cnt <= {{`DBG_UART_XFER_CNT_W{1'b1}}, 3'b000}; + else if (sync_busy | (~sync_busy & sync_cnt[2])) sync_cnt <= sync_cnt+{{`DBG_UART_XFER_CNT_W+2{1'b0}}, 1'b1}; + +wire [`DBG_UART_XFER_CNT_W-1:0] bit_cnt_max = sync_cnt[`DBG_UART_XFER_CNT_W+2:3]; +`else +wire [`DBG_UART_XFER_CNT_W-1:0] bit_cnt_max = `DBG_UART_CNT; +`endif + + +//============================================================================= +// 4) UART RECEIVE / TRANSMIT +//============================================================================= + +// Transfer counter +//------------------------ +reg [3:0] xfer_bit; +reg [`DBG_UART_XFER_CNT_W-1:0] xfer_cnt; + +wire txd_start = dbg_rd_rdy | (xfer_done & (uart_state==TX_DATA1)); +wire rxd_start = (xfer_bit==4'h0) & rxd_fe & ((uart_state!=RX_SYNC)); +wire xfer_bit_inc = (xfer_bit!=4'h0) & (xfer_cnt=={`DBG_UART_XFER_CNT_W{1'b0}}); +assign xfer_done = rx_active ? (xfer_bit==4'ha) : (xfer_bit==4'hb); + +always @ (posedge dbg_clk or posedge dbg_rst) + if (dbg_rst) xfer_bit <= 4'h0; + else if (txd_start | rxd_start) xfer_bit <= 4'h1; + else if (xfer_done) xfer_bit <= 4'h0; + else if (xfer_bit_inc) xfer_bit <= xfer_bit+4'h1; + +always @ (posedge dbg_clk or posedge dbg_rst) + if (dbg_rst) xfer_cnt <= {`DBG_UART_XFER_CNT_W{1'b0}}; + else if (rx_active & rxd_edge) xfer_cnt <= {1'b0, bit_cnt_max[`DBG_UART_XFER_CNT_W-1:1]}; + else if (txd_start | xfer_bit_inc) xfer_cnt <= bit_cnt_max; + else if (|xfer_cnt) xfer_cnt <= xfer_cnt+{`DBG_UART_XFER_CNT_W{1'b1}}; + + +// Receive/Transmit buffer +//------------------------- +assign xfer_buf_nxt = {rxd_s, xfer_buf[19:1]}; + +always @ (posedge dbg_clk or posedge dbg_rst) + if (dbg_rst) xfer_buf <= 20'h00000; + else if (dbg_rd_rdy) xfer_buf <= {1'b1, dbg_dout[15:8], 2'b01, dbg_dout[7:0], 1'b0}; + else if (xfer_bit_inc) xfer_buf <= xfer_buf_nxt; + + +// Generate TXD output +//------------------------ +reg dbg_uart_txd; + +always @ (posedge dbg_clk or posedge dbg_rst) + if (dbg_rst) dbg_uart_txd <= 1'b1; + else if (xfer_bit_inc & tx_active) dbg_uart_txd <= xfer_buf[0]; + + +//============================================================================= +// 5) INTERFACE TO DEBUG REGISTERS +//============================================================================= + +reg [5:0] dbg_addr; + always @ (posedge dbg_clk or posedge dbg_rst) + if (dbg_rst) dbg_addr <= 6'h00; + else if (cmd_valid) dbg_addr <= xfer_buf_nxt[`DBG_UART_ADDR]; + +reg dbg_bw; +always @ (posedge dbg_clk or posedge dbg_rst) + if (dbg_rst) dbg_bw <= 1'b0; + else if (cmd_valid) dbg_bw <= xfer_buf_nxt[`DBG_UART_BW]; + +wire dbg_din_bw = mem_burst ? mem_bw : dbg_bw; + +wire [15:0] dbg_din = dbg_din_bw ? {8'h00, xfer_buf_nxt[18:11]} : + {xfer_buf_nxt[18:11], xfer_buf_nxt[9:2]}; +wire dbg_wr = (xfer_done & (uart_state==RX_DATA2)); +wire dbg_rd = mem_burst ? (xfer_done & (uart_state==TX_DATA2)) : + (cmd_valid & ~xfer_buf_nxt[`DBG_UART_WR]) | mem_burst_rd; + + + +endmodule // omsp_dbg_uart + +`ifdef OMSP_NO_INCLUDE +`else +`include "openMSP430_undefines.v" +`endif |