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

Subversion Repositories s6soc

[/] [s6soc/] [trunk/] [rtl/] [rxuart.v] - Diff between revs 4 and 46

Show entire file | Details | Blame | View Log

Rev 4 Rev 46
Line 1... Line 1...
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//
// Filename:    rxuart.v
// Filename:    rxuart.v
//
//
// Project:     CMod S6 System on a Chip, ZipCPU demonstration project
// Project:     wbuart32, a full featured UART with simulator
//
//
// Purpose:     Receive and decode inputs from a single UART line.
// Purpose:     Receive and decode inputs from a single UART line.
//
//
//
//
//      To interface with this module, connect it to your system clock,
//      To interface with this module, connect it to your system clock,
Line 17... Line 17...
//      There is a synchronous reset line, logic high.
//      There is a synchronous reset line, logic high.
//
//
//      Now for the setup register.  The register is 32 bits, so that this
//      Now for the setup register.  The register is 32 bits, so that this
//      UART may be set up over a 32-bit bus.
//      UART may be set up over a 32-bit bus.
//
//
 
//      i_setup[30]     True if we are not using hardware flow control.  This bit
 
//              is ignored within this module, as any receive hardware flow
 
//              control will need to be implemented elsewhere.
 
//
//      i_setup[29:28]  Indicates the number of data bits per word.  This will
//      i_setup[29:28]  Indicates the number of data bits per word.  This will
//      either be 2'b00 for an 8-bit word, 2'b01 for a 7-bit word, 2'b10
//      either be 2'b00 for an 8-bit word, 2'b01 for a 7-bit word, 2'b10
//      for a six bit word, or 2'b11 for a five bit word.
//      for a six bit word, or 2'b11 for a five bit word.
//
//
//      i_setup[27]     Indicates whether or not to use one or two stop bits.
//      i_setup[27]     Indicates whether or not to use one or two stop bits.
Line 72... Line 76...
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// for more details.
// for more details.
//
//
// You should have received a copy of the GNU General Public License along
// You should have received a copy of the GNU General Public License along
// with this program.  (It's in the $(ROOT)/doc directory, run make with no
// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no
// target there if the PDF file isn't present.)  If not, see
// target there if the PDF file isn't present.)  If not, see
// <http://www.gnu.org/licenses/> for a copy.
// <http://www.gnu.org/licenses/> for a copy.
//
//
// License:     GPL, v3, as defined and found on www.gnu.org,
// License:     GPL, v3, as defined and found on www.gnu.org,
//              http://www.gnu.org/licenses/gpl.html
//              http://www.gnu.org/licenses/gpl.html
Line 88... Line 92...
// States: (@ baud counter == 0)
// States: (@ baud counter == 0)
//      0        First bit arrives
//      0        First bit arrives
//      ..7     Bits arrive
//      ..7     Bits arrive
//      8       Stop bit (x1)
//      8       Stop bit (x1)
//      9       Stop bit (x2)
//      9       Stop bit (x2)
///     c       break condition
//      c       break condition
//      d       Waiting for the channel to go high
//      d       Waiting for the channel to go high
//      e       Waiting for the reset to complete
//      e       Waiting for the reset to complete
//      f       Idle state
//      f       Idle state
`define RXU_BIT_ZERO            4'h0
`define RXU_BIT_ZERO            4'h0
`define RXU_BIT_ONE             4'h1
`define RXU_BIT_ONE             4'h1
Line 109... Line 113...
// Unused 4'hc
// Unused 4'hc
`define RXU_BREAK               4'hd
`define RXU_BREAK               4'hd
`define RXU_RESET_IDLE          4'he
`define RXU_RESET_IDLE          4'he
`define RXU_IDLE                4'hf
`define RXU_IDLE                4'hf
 
 
module rxuart(i_clk, i_reset, i_setup, i_uart, o_wr, o_data, o_break,
module rxuart(i_clk, i_reset, i_setup, i_uart_rx, o_wr, o_data, o_break,
                        o_parity_err, o_frame_err, o_ck_uart);
                        o_parity_err, o_frame_err, o_ck_uart);
        //  parameter // CLOCKS_PER_BAUD = 25'd004340,
        parameter [30:0] INITIAL_SETUP = 31'd868;
                        //  BREAK_CONDITION = CLOCKS_PER_BAUD * 12,
 
                        //  CLOCKS_PER_HALF_BAUD = CLOCKS_PER_BAUD/2;
 
        // 8 data bits, no parity, (at least 1) stop bit
        // 8 data bits, no parity, (at least 1) stop bit
        input                   i_clk, i_reset;
        input                   i_clk, i_reset;
        input           [29:0]   i_setup;
        input           [30:0]   i_setup;
        input                   i_uart;
        input                   i_uart_rx;
        output  reg             o_wr;
        output  reg             o_wr;
        output  reg     [7:0]    o_data;
        output  reg     [7:0]    o_data;
        output  reg             o_break;
        output  reg             o_break;
        output  reg             o_parity_err, o_frame_err;
        output  reg             o_parity_err, o_frame_err;
        output  wire            o_ck_uart;
        output  wire            o_ck_uart;
Line 129... Line 131...
 
 
        wire    [27:0]   clocks_per_baud, break_condition, half_baud;
        wire    [27:0]   clocks_per_baud, break_condition, half_baud;
        wire    [1:0]    data_bits;
        wire    [1:0]    data_bits;
        wire            use_parity, parity_even, dblstop, fixd_parity;
        wire            use_parity, parity_even, dblstop, fixd_parity;
        reg     [29:0]   r_setup;
        reg     [29:0]   r_setup;
 
        reg     [3:0]    state;
 
 
        assign  clocks_per_baud = { 4'h0, r_setup[23:0] };
        assign  clocks_per_baud = { 4'h0, r_setup[23:0] };
 
        // assign hw_flow_control = !r_setup[30];
        assign  data_bits   = r_setup[29:28];
        assign  data_bits   = r_setup[29:28];
        assign  dblstop     = r_setup[27];
        assign  dblstop     = r_setup[27];
        assign  use_parity  = r_setup[26];
        assign  use_parity  = r_setup[26];
        assign  fixd_parity = r_setup[25];
        assign  fixd_parity = r_setup[25];
        assign  parity_even = r_setup[24];
        assign  parity_even = r_setup[24];
        assign  break_condition = { r_setup[23:0], 4'h0 };
        assign  break_condition = { r_setup[23:0], 4'h0 };
        assign  half_baud = { 5'h00, r_setup[23:1] };
        assign  half_baud = { 5'h00, r_setup[23:1] }-28'h1;
 
        reg     [27:0]   baud_counter;
 
        reg             zero_baud_counter;
 
 
 
 
 
        // Since this is an asynchronous receiver, we need to register our
 
        // input a couple of clocks over to avoid any problems with 
 
        // metastability.  We do that here, and then ignore all but the
 
        // ck_uart wire.
        reg     q_uart, qq_uart, ck_uart;
        reg     q_uart, qq_uart, ck_uart;
        initial q_uart  = 1'b0;
        initial q_uart  = 1'b0;
        initial qq_uart = 1'b0;
        initial qq_uart = 1'b0;
        initial ck_uart = 1'b0;
        initial ck_uart = 1'b0;
        always @(posedge i_clk)
        always @(posedge i_clk)
        begin
        begin
                q_uart <= i_uart;
                q_uart <= i_uart_rx;
                qq_uart <= q_uart;
                qq_uart <= q_uart;
                ck_uart <= qq_uart;
                ck_uart <= qq_uart;
        end
        end
 
 
 
        // In case anyone else wants this clocked, stabilized value, we
 
        // offer it on our output.
        assign  o_ck_uart = ck_uart;
        assign  o_ck_uart = ck_uart;
 
 
 
        // Keep track of the number of clocks since the last change.
 
        //
 
        // This is used to determine if we are in either a break or an idle
 
        // condition, as discussed further below.
        reg     [27:0]   chg_counter;
        reg     [27:0]   chg_counter;
        initial chg_counter = 28'h00;
        initial chg_counter = 28'h00;
        always @(posedge i_clk)
        always @(posedge i_clk)
                if (i_reset)
                if (i_reset)
                        chg_counter <= 28'h00;
                        chg_counter <= 28'h00;
                else if (qq_uart != ck_uart)
                else if (qq_uart != ck_uart)
                        chg_counter <= 28'h00;
                        chg_counter <= 28'h00;
                else if (chg_counter < break_condition)
                else if (chg_counter < break_condition)
                        chg_counter <= chg_counter + 1;
                        chg_counter <= chg_counter + 1;
 
 
 
        // Are we in a break condition?
 
        //
 
        // A break condition exists if the line is held low for longer than
 
        // a data word.  Hence, we keep track of when the last change occurred.
 
        // If it was more than break_condition clocks ago, and the current input
 
        // value is a 0, then we're in a break--and nothing can be read until
 
        // the line idles again.
 
        initial o_break    = 1'b0;
        always @(posedge i_clk)
        always @(posedge i_clk)
                o_break <=((chg_counter >= break_condition)&&(~ck_uart))? 1'b1:1'b0;
                o_break <=((chg_counter >= break_condition)&&(~ck_uart))? 1'b1:1'b0;
 
 
        reg     [3:0]    state;
        // Are we between characters?
        reg     [27:0]   baud_counter;
        //
        reg     [7:0]    data_reg;
        // The opposite of a break condition is where the line is held high
        reg             calc_parity;
        // for more clocks than would be in a character.  When this happens,
        initial o_wr = 1'b0;
        // we know we have synchronization--otherwise, we might be sampling
 
        // from within a data word.
 
        //
 
        // This logic is used later to hold the RXUART in a reset condition
 
        // until we know we are between data words.  At that point, we should
 
        // be able to hold on to our synchronization.
 
        reg     line_synch;
 
        initial line_synch = 1'b0;
 
        always @(posedge i_clk)
 
                line_synch <= ((chg_counter >= break_condition)&&(ck_uart));
 
 
 
        // Are we in the middle of a baud iterval?  Specifically, are we
 
        // in the middle of a start bit?  Set this to high if so.  We'll use
 
        // this within our state machine to transition out of the IDLE
 
        // state.
 
        reg     half_baud_time;
 
        initial half_baud_time = 0;
 
        always @(posedge i_clk)
 
                half_baud_time <= (~ck_uart)&&(chg_counter >= half_baud);
 
 
 
 
 
        // Allow our controlling processor to change our setup at any time
 
        // outside of receiving/processing a character.
 
        initial r_setup     = INITIAL_SETUP[29:0];
 
        always @(posedge i_clk)
 
                if (state >= `RXU_RESET_IDLE)
 
                        r_setup <= i_setup[29:0];
 
 
 
 
 
        // Our monster state machine.  YIKES!
 
        //
 
        // Yeah, this may be more complicated than it needs to be.  The basic
 
        // progression is:
 
        //      RESET -> RESET_IDLE -> (when line is idle) -> IDLE
 
        //      IDLE -> bit 0 -> bit 1 -> bit_{ndatabits} -> 
 
        //              (optional) PARITY -> STOP -> (optional) SECOND_STOP
 
        //              -> IDLE
 
        //      ANY -> (on break) BREAK -> IDLE
 
        //
 
        // There are 16 states, although all are not used.  These are listed
 
        // at the top of this file.
 
        //
 
        //      Logic inputs (12):      (I've tried to minimize this number)
 
        //              state   (4)
 
        //              i_reset
 
        //              line_synch
 
        //              o_break
 
        //              ckuart
 
        //              half_baud_time
 
        //              zero_baud_counter
 
        //              use_parity
 
        //              dblstop
 
        //      Logic outputs (4):
 
        //              state
 
        //
        initial state = `RXU_RESET_IDLE;
        initial state = `RXU_RESET_IDLE;
        initial o_parity_err = 1'b0;
 
        initial o_frame_err  = 1'b0;
 
        // initial      baud_counter = clocks_per_baud;
 
        always @(posedge i_clk)
        always @(posedge i_clk)
        begin
        begin
                if (i_reset)
                if (i_reset)
                begin
 
                        o_wr <= 1'b0;
 
                        o_data <= 8'h00;
 
                        state <= `RXU_RESET_IDLE;
                        state <= `RXU_RESET_IDLE;
                        baud_counter <= clocks_per_baud; // Set, not reset
                else if (state == `RXU_RESET_IDLE)
                        data_reg <= 8'h00;
 
                        calc_parity <= 1'b0;
 
                        o_parity_err <= 1'b0;
 
                        o_frame_err <= 1'b0;
 
                end else if (state == `RXU_RESET_IDLE)
 
                begin
                begin
                        r_setup <= i_setup;
                        if (line_synch)
                        data_reg <= 8'h00; o_data <= 8'h00; o_wr <= 1'b0;
 
                        baud_counter <= clocks_per_baud-28'h01;// Set, not reset
 
                        if ((ck_uart)&&(chg_counter >= break_condition))
 
                                // Goto idle state from a reset
                                // Goto idle state from a reset
                                state <= `RXU_IDLE;
                                state <= `RXU_IDLE;
                        else // Otherwise, stay in this condition 'til reset
                        else // Otherwise, stay in this condition 'til reset
                                state <= `RXU_RESET_IDLE;
                                state <= `RXU_RESET_IDLE;
                        calc_parity <= 1'b0;
                end else if (o_break)
                        o_parity_err <= 1'b0;
 
                        o_frame_err <= 1'b0;
 
                end else if ((~ck_uart)&&(chg_counter >= break_condition))
 
                begin // We are in a break condition
                begin // We are in a break condition
                        state <= `RXU_BREAK;
                        state <= `RXU_BREAK;
                        o_wr <= 1'b0;
 
                        o_data <= 8'h00;
 
                        baud_counter <= clocks_per_baud-28'h01;// Set, not reset
 
                        data_reg <= 8'h00;
 
                        calc_parity <= 1'b0;
 
                        o_parity_err <= 1'b0;
 
                        o_frame_err <= 1'b0;
 
                        r_setup <= i_setup;
 
                end else if (state == `RXU_BREAK)
                end else if (state == `RXU_BREAK)
                begin // Goto idle state following return ck_uart going high
                begin // Goto idle state following return ck_uart going high
                        data_reg <= 8'h00; o_data <= 8'h00; o_wr <= 1'b0;
 
                        baud_counter <= clocks_per_baud - 28'h01;
 
                        if (ck_uart)
                        if (ck_uart)
                                state <= `RXU_IDLE;
                                state <= `RXU_IDLE;
                        else
                        else
                                state <= `RXU_BREAK;
                                state <= `RXU_BREAK;
                        calc_parity <= 1'b0;
 
                        o_parity_err <= 1'b0;
 
                        o_frame_err <= 1'b0;
 
                        r_setup <= i_setup;
 
                end else if (state == `RXU_IDLE)
                end else if (state == `RXU_IDLE)
                begin // Idle state, independent of baud counter
                begin // Idle state, independent of baud counter
                        data_reg <= 8'h00; o_data <= 8'h00; o_wr <= 1'b0;
                        if ((~ck_uart)&&(half_baud_time))
                        baud_counter <= clocks_per_baud - 28'h01;
 
                        if ((ck_uart == 1'b0)&&(chg_counter > half_baud))
 
                        begin
                        begin
                                // We are in the center of a valid start bit
                                // We are in the center of a valid start bit
                                case (data_bits)
                                case (data_bits)
                                2'b00: state <= `RXU_BIT_ZERO;
                                2'b00: state <= `RXU_BIT_ZERO;
                                2'b01: state <= `RXU_BIT_ONE;
                                2'b01: state <= `RXU_BIT_ONE;
                                2'b10: state <= `RXU_BIT_TWO;
                                2'b10: state <= `RXU_BIT_TWO;
                                2'b11: state <= `RXU_BIT_THREE;
                                2'b11: state <= `RXU_BIT_THREE;
                                endcase
                                endcase
                        end else // Otherwise, just stay here in idle
                        end else // Otherwise, just stay here in idle
                                state <= `RXU_IDLE;
                                state <= `RXU_IDLE;
                        calc_parity <= 1'b0;
                end else if (zero_baud_counter)
                        o_parity_err <= 1'b0;
 
                        o_frame_err <= 1'b0;
 
                end else if (baud_counter == 0)
 
                begin
                begin
                        baud_counter <= clocks_per_baud-28'h1;
 
                        if (state < `RXU_BIT_SEVEN)
                        if (state < `RXU_BIT_SEVEN)
                        begin
 
                                // Data arrives least significant bit first.
                                // Data arrives least significant bit first.
                                // By the time this is clocked in, it's what
                                // By the time this is clocked in, it's what
                                // you'll have.
                                // you'll have.
                                data_reg <= { ck_uart, data_reg[7:1] };
 
                                calc_parity <= calc_parity ^ ck_uart;
 
                                o_data <= 8'h00;
 
                                o_wr <= 1'b0;
 
                                state <= state + 1;
                                state <= state + 1;
                                o_parity_err <= 1'b0;
                        else if (state == `RXU_BIT_SEVEN)
                                o_frame_err <= 1'b0;
 
                        end else if (state == `RXU_BIT_SEVEN)
 
                        begin
 
                                data_reg <= { ck_uart, data_reg[7:1] };
 
                                calc_parity <= calc_parity ^ ck_uart;
 
                                o_data <= 8'h00;
 
                                o_wr <= 1'b0;
 
                                state <= (use_parity) ? `RXU_PARITY:`RXU_STOP;
                                state <= (use_parity) ? `RXU_PARITY:`RXU_STOP;
                                o_parity_err <= 1'b0;
                        else if (state == `RXU_PARITY)
                                o_frame_err <= 1'b0;
 
                        end else if (state == `RXU_PARITY)
 
                        begin
 
                                if (fixd_parity)
 
                                        o_parity_err <= (ck_uart ^ parity_even);
 
                                else
 
                                        o_parity_err <= ((parity_even && (calc_parity != ck_uart))
 
                                                ||((~parity_even)&&(calc_parity==ck_uart)));
 
                                state <= `RXU_STOP;
                                state <= `RXU_STOP;
                                o_frame_err <= 1'b0;
                        else if (state == `RXU_STOP)
                        end else if (state == `RXU_STOP)
 
                        begin // Stop (or parity) bit(s)
                        begin // Stop (or parity) bit(s)
                                case (data_bits)
                                if (~ck_uart) // On frame error, wait 4 ch idle
                                2'b00: o_data <= data_reg;
 
                                2'b01: o_data <= { 1'b0, data_reg[7:1] };
 
                                2'b10: o_data <= { 2'b0, data_reg[7:2] };
 
                                2'b11: o_data <= { 3'b0, data_reg[7:3] };
 
                                endcase
 
                                o_wr <= 1'b1; // Pulse the write
 
                                o_frame_err <= (~ck_uart);
 
                                if (~ck_uart)
 
                                        state <= `RXU_RESET_IDLE;
                                        state <= `RXU_RESET_IDLE;
                                else if (dblstop)
                                else if (dblstop)
                                        state <= `RXU_SECOND_STOP;
                                        state <= `RXU_SECOND_STOP;
                                else
                                else
                                        state <= `RXU_IDLE;
                                        state <= `RXU_IDLE;
                                // o_parity_err <= 1'b0;
 
                        end else // state must equal RX_SECOND_STOP
                        end else // state must equal RX_SECOND_STOP
                        begin
                        begin
                                if (~ck_uart)
                                if (~ck_uart) // On frame error, wait 4 ch idle
                                begin
 
                                        o_frame_err <= 1'b1;
 
                                        state <= `RXU_RESET_IDLE;
                                        state <= `RXU_RESET_IDLE;
                                end else begin
                                else
                                        state <= `RXU_IDLE;
                                        state <= `RXU_IDLE;
                                        o_frame_err  <= 1'b0;
 
                                end
                                end
                                o_parity_err <= 1'b0;
 
                        end
                        end
                end else begin
        end
                        o_wr <= 1'b0;   // data_reg = data_reg
 
                        baud_counter <= baud_counter - 28'd1;
        // Data bit capture logic.
 
        //
 
        // This is drastically simplified from the state machine above, based
 
        // upon: 1) it doesn't matter what it is until the end of a captured
 
        // byte, and 2) the data register will flush itself of any invalid
 
        // data in all other cases.  Hence, let's keep it real simple.
 
        // The only trick, though, is that if we have parity, then the data
 
        // register needs to be held through that state without getting
 
        // updated.
 
        reg     [7:0]    data_reg;
 
        always @(posedge i_clk)
 
                if ((zero_baud_counter)&&(state != `RXU_PARITY))
 
                        data_reg <= { ck_uart, data_reg[7:1] };
 
 
 
        // Parity calculation logic
 
        //
 
        // As with the data capture logic, all that must be known about this
 
        // bit is that it is the exclusive-OR of all bits prior.  The first
 
        // of those will follow idle, so we set ourselves to zero on idle.
 
        // Then, as we walk through the states of a bit, all will adjust this
 
        // value up until the parity bit, where the value will be read.  Setting
 
        // it then or after will be irrelevant, so ... this should be good
 
        // and simplified.  Note--we don't need to adjust this on reset either,
 
        // since the reset state will lead to the idle state where we'll be
 
        // reset before any transmission takes place.
 
        reg             calc_parity;
 
        always @(posedge i_clk)
 
                if (state == `RXU_IDLE)
 
                        calc_parity <= 0;
 
                else if (zero_baud_counter)
 
                        calc_parity <= calc_parity ^ ck_uart;
 
 
 
        // Parity error logic
 
        //
 
        // Set during the parity bit interval, read during the last stop bit
 
        // interval, cleared on BREAK, RESET_IDLE, or IDLE states.
 
        initial o_parity_err = 1'b0;
 
        always @(posedge i_clk)
 
                if ((zero_baud_counter)&&(state == `RXU_PARITY))
 
                begin
 
                        if (fixd_parity)
 
                                // Fixed parity bit--independent of any dat
 
                                // value.
 
                                o_parity_err <= (ck_uart ^ parity_even);
 
                        else if (parity_even)
 
                                // Parity even: The XOR of all bits including
 
                                // the parity bit must be zero.
 
                                o_parity_err <= (calc_parity != ck_uart);
 
                        else
 
                                // Parity odd: the parity bit must equal the
 
                                // XOR of all the data bits.
 
                                o_parity_err <= (calc_parity == ck_uart);
 
                end else if (state >= `RXU_BREAK)
                        o_parity_err <= 1'b0;
                        o_parity_err <= 1'b0;
 
 
 
        // Frame error determination
 
        //
 
        // For the purpose of this controller, a frame error is defined as a
 
        // stop bit (or second stop bit, if so enabled) not being high midway
 
        // through the stop baud interval.   The frame error value is
 
        // immediately read, so we can clear it under all other circumstances.
 
        // Specifically, we want it clear in RXU_BREAK, RXU_RESET_IDLE, and
 
        // most importantly in RXU_IDLE.
 
        initial o_frame_err  = 1'b0;
 
        always @(posedge i_clk)
 
                if ((zero_baud_counter)&&((state == `RXU_STOP)
 
                                                ||(state == `RXU_SECOND_STOP)))
 
                        o_frame_err <= (o_frame_err)||(~ck_uart);
 
                else if ((zero_baud_counter)||(state >= `RXU_BREAK))
                        o_frame_err  <= 1'b0;
                        o_frame_err  <= 1'b0;
                end
 
        end
        // Our data bit logic doesn't need nearly the complexity of all that
 
        // work above.  Indeed, we only need to know if we are at the end of
 
        // a stop bit, in which case we copy the data_reg into our output
 
        // data register, o_data.
 
        //
 
        // We would also set o_wr to be true when this is the case, but ... we
 
        // won't know if there is a frame error on the second stop bit for 
 
        // another baud interval yet.  So, instead, we set up the logic so that
 
        // we know on the next zero baud counter that we can write out.  That's
 
        // the purpose of pre_wr.
 
        initial o_data = 8'h00;
 
        reg     pre_wr;
 
        initial pre_wr = 1'b0;
 
        always @(posedge i_clk)
 
                if (i_reset)
 
                begin
 
                        pre_wr <= 1'b0;
 
                        o_data <= 8'h00;
 
                end else if ((zero_baud_counter)&&(state == `RXU_STOP))
 
                begin
 
                        pre_wr <= 1'b1;
 
                        case (data_bits)
 
                        2'b00: o_data <= data_reg;
 
                        2'b01: o_data <= { 1'b0, data_reg[7:1] };
 
                        2'b10: o_data <= { 2'b0, data_reg[7:2] };
 
                        2'b11: o_data <= { 3'b0, data_reg[7:3] };
 
                        endcase
 
                end else if ((zero_baud_counter)||(state == `RXU_IDLE))
 
                        pre_wr <= 1'b0;
 
 
 
        // Create an output strobe, true for one clock only, once we know
 
        // all we need to know.  o_data will be set on the last baud interval,
 
        // o_parity_err on the last parity baud interval (if it existed,
 
        // cleared otherwise, so ... we should be good to go here.)
 
        initial o_wr   = 1'b0;
 
        always @(posedge i_clk)
 
                if ((zero_baud_counter)||(state == `RXU_IDLE))
 
                        o_wr <= (pre_wr)&&(!i_reset);
 
                else
 
                        o_wr <= 1'b0;
 
 
 
        // The baud counter
 
        //
 
        // This is used as a "clock divider" if you will, but the clock needs
 
        // to be reset before any byte can be decoded.  In all other respects,
 
        // we set ourselves up for clocks_per_baud counts between baud
 
        // intervals.
 
        always @(posedge i_clk)
 
                if (i_reset)
 
                        baud_counter <= clocks_per_baud-28'h01;
 
                else if (zero_baud_counter)
 
                        baud_counter <= clocks_per_baud-28'h01;
 
                else case(state)
 
                        `RXU_RESET_IDLE:baud_counter <= clocks_per_baud-28'h01;
 
                        `RXU_BREAK:     baud_counter <= clocks_per_baud-28'h01;
 
                        `RXU_IDLE:      baud_counter <= clocks_per_baud-28'h01;
 
                        default:        baud_counter <= baud_counter-28'h01;
 
                endcase
 
 
 
        // zero_baud_counter
 
        //
 
        // Rather than testing whether or not (baud_counter == 0) within our
 
        // (already too complicated) state transition tables, we use
 
        // zero_baud_counter to pre-charge that test on the clock
 
        // before--cleaning up some otherwise difficult timing dependencies.
 
        initial zero_baud_counter = 1'b0;
 
        always @(posedge i_clk)
 
                if (state == `RXU_IDLE)
 
                        zero_baud_counter <= 1'b0;
 
                else
 
                zero_baud_counter <= (baud_counter == 28'h01);
 
 
 
 
endmodule
endmodule
 
 
 
 
 
 
 No newline at end of file
 No newline at end of file

powered by: WebSVN 2.1.0

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