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

Subversion Repositories wbuart32

[/] [wbuart32/] [trunk/] [rtl/] [wbuart.v] - Diff between revs 9 and 15

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 9 Rev 15
Line 45... Line 45...
module  wbuart(i_clk, i_rst,
module  wbuart(i_clk, i_rst,
                //
                //
                i_wb_cyc, i_wb_stb, i_wb_we, i_wb_addr, i_wb_data,
                i_wb_cyc, i_wb_stb, i_wb_we, i_wb_addr, i_wb_data,
                        o_wb_ack, o_wb_stall, o_wb_data,
                        o_wb_ack, o_wb_stall, o_wb_data,
                //
                //
                i_uart_rx, o_uart_tx, i_rts, o_cts,
                i_uart_rx, o_uart_tx, i_cts_n, o_rts_n,
                // i_uart_rts, o_uart_cts, i_uart_dtr, o_uart_dts
 
                //
                //
                o_uart_rx_int, o_uart_tx_int,
                o_uart_rx_int, o_uart_tx_int,
                o_uart_rxfifo_int, o_uart_txfifo_int);
                o_uart_rxfifo_int, o_uart_txfifo_int);
        parameter [30:0] INITIAL_SETUP = 31'd25; // 4MB 8N1, when using 100MHz clock
        parameter [30:0] INITIAL_SETUP = 31'd25; // 4MB 8N1, when using 100MHz clock
        parameter [3:0]  LGFLEN = 4;
        parameter [3:0]  LGFLEN = 4;
Line 75... Line 74...
        // RTS is used for hardware flow control.  According to Wikipedia, it
        // RTS is used for hardware flow control.  According to Wikipedia, it
        // should probably be renamed RTR for "ready to receive".  It tell us
        // should probably be renamed RTR for "ready to receive".  It tell us
        // whether or not the receiving hardware is ready to accept another
        // whether or not the receiving hardware is ready to accept another
        // byte.  If low, the transmitter will pause.
        // byte.  If low, the transmitter will pause.
        //
        //
        // If you don't wish to use hardware flow control, just set i_rts to
        // If you don't wish to use hardware flow control, just set i_cts_n to
        // 1'b1 and let the optimizer simply remove this logic.
        // 1'b0 and let the optimizer simply remove this logic.
        input                   i_rts;
        input                   i_cts_n;
        // CTS is the "Clear-to-send" signal.  We set it anytime our FIFO
        // CTS is the "Clear-to-send" signal.  We set it anytime our FIFO
        // isn't full.  Feel free to ignore this output if you do not wish to
        // isn't full.  Feel free to ignore this output if you do not wish to
        // use flow control.
        // use flow control.
        output  reg             o_cts;
        output  reg             o_rts_n;
        output  wire            o_uart_rx_int, o_uart_tx_int,
        output  wire            o_uart_rx_int, o_uart_tx_int,
                                o_uart_rxfifo_int, o_uart_txfifo_int;
                                o_uart_rxfifo_int, o_uart_txfifo_int;
 
 
        wire    tx_busy;
        wire    tx_busy;
 
 
Line 118... Line 117...
        wire    [7:0]    rx_uart_data;
        wire    [7:0]    rx_uart_data;
        reg             rx_uart_reset;
        reg             rx_uart_reset;
 
 
        // Here's our UART receiver.  Basically, it accepts our setup wires, 
        // Here's our UART receiver.  Basically, it accepts our setup wires, 
        // the UART input, a clock, and a reset line, and produces outputs:
        // the UART input, a clock, and a reset line, and produces outputs:
        // a stb (true when new data is ready), an 8-bit data out value
        // a stb (true when new data is ready), and an 8-bit data out value
        // valid when stb is high, a break value (true during a break cond.),
        // valid when stb is high.
        // and parity/framing error flags--also valid when stb is true.
`ifdef  USE_LITE_UART
 
        rxuartlite      #(INITIAL_SETUP[23:0])
 
                rx(i_clk, (i_rst), i_uart_rx, rx_stb, rx_uart_data);
 
        assign  rx_break = 1'b0;
 
        assign  rx_perr  = 1'b0;
 
        assign  rx_ferr  = 1'b0;
 
        assign  ck_uart  = 1'b0;
 
`else
 
        // The full receiver also produces a break value (true during a break
 
        // cond.), and parity/framing error flags--also valid when stb is true.
        rxuart  #(INITIAL_SETUP) rx(i_clk, (i_rst)||(rx_uart_reset),
        rxuart  #(INITIAL_SETUP) rx(i_clk, (i_rst)||(rx_uart_reset),
                        uart_setup, i_uart_rx,
                        uart_setup, i_uart_rx,
                        rx_stb, rx_uart_data, rx_break,
                        rx_stb, rx_uart_data, rx_break,
                        rx_perr, rx_ferr, ck_uart);
                        rx_perr, rx_ferr, ck_uart);
        // The real trick is ... now that we have this data, what do we do
        // The real trick is ... now that we have this extra data, what do we do
        // with it?
        // with it?
 
`endif
 
 
 
 
        // We place it into a receiver FIFO.
        // We place it into a receiver FIFO.
        //
        //
        // Here's the declarations for the wires it needs.
        // Here's the declarations for the wires it needs.
Line 168... Line 177...
        // to be true any time the FIFO has fewer than N-2 items in it.
        // to be true any time the FIFO has fewer than N-2 items in it.
        // Why N-1?  Because at N-1 we are totally full, but already so full
        // Why N-1?  Because at N-1 we are totally full, but already so full
        // that if the transmit end starts sending we won't have a location to
        // that if the transmit end starts sending we won't have a location to
        // receive it.  (Transmit might've started on the next character by the
        // receive it.  (Transmit might've started on the next character by the
        // time we set this--need to set it to one character before necessary
        // time we set this--need to set it to one character before necessary
        // thus.)
 
        wire    [(LCLLGFLEN-1):0]        check_cutoff;
 
        assign  check_cutoff = -3;
 
        always @(posedge i_clk)
        always @(posedge i_clk)
                o_cts = (!HARDWARE_FLOW_CONTROL_PRESENT)
                o_rts_n = ((HARDWARE_FLOW_CONTROL_PRESENT)
                        ||(rxf_status[(LCLLGFLEN+1):2] > check_cutoff);
                        &&(!uart_setup[30])
 
                        &&(rxf_status[(LCLLGFLEN+1):4]=={(LCLLGFLEN-2){1'b1}}));
 
 
        // If the bus requests that we read from the receive FIFO, we need to
        // If the bus requests that we read from the receive FIFO, we need to
        // tell this to the receive FIFO.  Note that because we are using a 
        // tell this to the receive FIFO.  Note that because we are using a 
        // clock here, the output from the receive FIFO will necessarily be
        // clock here, the output from the receive FIFO will necessarily be
        // delayed by an extra clock.
        // delayed by an extra clock.
Line 248... Line 255...
        //
        //
        // Then the UART transmitter
        // Then the UART transmitter
        //
        //
        //
        //
        /////////////////////////////////////////
        /////////////////////////////////////////
        wire            tx_empty_n, txf_err;
        wire            tx_empty_n, txf_err, tx_break;
        wire    [7:0]    tx_data;
        wire    [7:0]    tx_data;
        wire    [15:0]   txf_status;
        wire    [15:0]   txf_status;
        reg             r_tx_break, txf_wb_write, tx_uart_reset;
        reg             txf_wb_write, tx_uart_reset;
        reg     [7:0]    txf_wb_data;
        reg     [7:0]    txf_wb_data;
 
 
        // Unlike the receiver which goes from RXUART -> UFIFO -> WB, the
        // Unlike the receiver which goes from RXUART -> UFIFO -> WB, the
        // transmitter basically goes WB -> UFIFO -> TXUART.  Hence, to build
        // transmitter basically goes WB -> UFIFO -> TXUART.  Hence, to build
        // support for the transmitter, we start with the command to write data
        // support for the transmitter, we start with the command to write data
Line 280... Line 287...
        // differences to note: we reset the transmitter on any request for a
        // differences to note: we reset the transmitter on any request for a
        // break.  We read from the FIFO any time the UART transmitter is idle.
        // break.  We read from the FIFO any time the UART transmitter is idle.
        // and ... we just set the values (above) for controlling writing into
        // and ... we just set the values (above) for controlling writing into
        // this.
        // this.
        ufifo   #(.LGFLEN(LGFLEN), .RXFIFO(0))
        ufifo   #(.LGFLEN(LGFLEN), .RXFIFO(0))
                txfifo(i_clk, (r_tx_break)||(tx_uart_reset),
                txfifo(i_clk, (tx_break)||(tx_uart_reset),
                        txf_wb_write, txf_wb_data,
                        txf_wb_write, txf_wb_data,
                        tx_empty_n,
                        tx_empty_n,
                        (!tx_busy)&&(tx_empty_n), tx_data,
                        (!tx_busy)&&(tx_empty_n), tx_data,
                        txf_status, txf_err);
                        txf_status, txf_err);
        // Let's create two transmit based interrupts from the FIFO for the CPU.
        // Let's create two transmit based interrupts from the FIFO for the CPU.
Line 294... Line 301...
        //      The second will be true any time the FIFO is less than half
        //      The second will be true any time the FIFO is less than half
        //      full, allowing us a change to always keep it (near) fully 
        //      full, allowing us a change to always keep it (near) fully 
        //      charged.
        //      charged.
        assign  o_uart_txfifo_int = txf_status[1];
        assign  o_uart_txfifo_int = txf_status[1];
 
 
 
`ifndef USE_LITE_UART
        // Break logic
        // Break logic
        //
        //
        // A break in a UART controller is any time the UART holds the line
        // A break in a UART controller is any time the UART holds the line
        // low for an extended period of time.  Here, we capture the wb_data[9]
        // low for an extended period of time.  Here, we capture the wb_data[9]
        // wire, on writes, as an indication we wish to break.  As long as you
        // wire, on writes, as an indication we wish to break.  As long as you
        // write unsigned characters to the interface, this will never be true
        // write unsigned characters to the interface, this will never be true
        // unless you wish it to be true.  Be aware, though, writing a valid
        // unless you wish it to be true.  Be aware, though, writing a valid
        // value to the interface will bring it out of the break condition.
        // value to the interface will bring it out of the break condition.
 
        reg     r_tx_break;
        initial r_tx_break = 1'b0;
        initial r_tx_break = 1'b0;
        always @(posedge i_clk)
        always @(posedge i_clk)
                if (i_rst)
                if (i_rst)
                        r_tx_break <= 1'b0;
                        r_tx_break <= 1'b0;
                else if ((i_wb_stb)&&(i_wb_addr[1:0]==`UART_TXREG)&&(i_wb_we))
                else if ((i_wb_stb)&&(i_wb_addr[1:0]==`UART_TXREG)&&(i_wb_we))
                        r_tx_break <= i_wb_data[9];
                        r_tx_break <= i_wb_data[9];
 
        assign  tx_break = r_tx_break;
 
`else
 
        assign  tx_break = 1'b0;
 
`endif
 
 
        // TX-Reset logic
        // TX-Reset logic
        //
        //
        // This is nearly identical to the RX reset logic above.  Basically,
        // This is nearly identical to the RX reset logic above.  Basically,
        // any time someone writes to bit [12] the transmitter will go through
        // any time someone writes to bit [12] the transmitter will go through
Line 324... Line 337...
                else if ((i_wb_stb)&&(i_wb_addr[1:0]==`UART_TXREG)&&(i_wb_we))
                else if ((i_wb_stb)&&(i_wb_addr[1:0]==`UART_TXREG)&&(i_wb_we))
                        tx_uart_reset <= i_wb_data[12];
                        tx_uart_reset <= i_wb_data[12];
                else
                else
                        tx_uart_reset <= 1'b0;
                        tx_uart_reset <= 1'b0;
 
 
        wire    rts;
`ifdef  USE_LITE_UART
        assign  rts = (!HARDWARE_FLOW_CONTROL_PRESENT)||(i_rts);
        txuart  #(INITIAL_SETUP[23:0]) tx(i_clk, (tx_empty_n), tx_data,
 
                        o_uart_tx, tx_busy);
 
`else
 
        wire    cts_n;
 
        assign  cts_n = (HARDWARE_FLOW_CONTROL_PRESENT)&&(i_cts_n);
        // Finally, the UART transmitter module itself.  Note that we haven't
        // Finally, the UART transmitter module itself.  Note that we haven't
        // connected the reset wire.  Transmitting is as simple as setting
        // connected the reset wire.  Transmitting is as simple as setting
        // the stb value (here set to tx_empty_n) and the data.  When these
        // the stb value (here set to tx_empty_n) and the data.  When these
        // are both set on the same clock that tx_busy is low, the transmitter
        // are both set on the same clock that tx_busy is low, the transmitter
        // will move on to the next data byte.  Really, the only thing magical
        // will move on to the next data byte.  Really, the only thing magical
Line 337... Line 354...
        // we read it here.  (You might notice above, we register a read any
        // we read it here.  (You might notice above, we register a read any
        // time (tx_empty_n) and (!tx_busy) are both true---the condition for
        // time (tx_empty_n) and (!tx_busy) are both true---the condition for
        // starting to transmit a new byte.)
        // starting to transmit a new byte.)
        txuart  #(INITIAL_SETUP) tx(i_clk, 1'b0, uart_setup,
        txuart  #(INITIAL_SETUP) tx(i_clk, 1'b0, uart_setup,
                        r_tx_break, (tx_empty_n), tx_data,
                        r_tx_break, (tx_empty_n), tx_data,
                        i_rts, o_uart_tx, tx_busy);
                        cts_n, o_uart_tx, tx_busy);
 
`endif
 
 
        // Now that we are done with the chain, pick some wires for the user
        // Now that we are done with the chain, pick some wires for the user
        // to read on any read of the transmit port.
        // to read on any read of the transmit port.
        //
        //
        // This port is different from reading from the receive port, since
        // This port is different from reading from the receive port, since
Line 353... Line 371...
        // voltage on the line (o_uart_tx)--and even the voltage on the receive
        // voltage on the line (o_uart_tx)--and even the voltage on the receive
        // line (ck_uart), as well as our current setting of the break and
        // line (ck_uart), as well as our current setting of the break and
        // whether or not we are actively transmitting.
        // whether or not we are actively transmitting.
        wire    [31:0]   wb_tx_data;
        wire    [31:0]   wb_tx_data;
        assign  wb_tx_data = { 16'h00,
        assign  wb_tx_data = { 16'h00,
                                i_rts, txf_status[1:0], txf_err,
                                i_cts_n, txf_status[1:0], txf_err,
                                ck_uart, o_uart_tx, r_tx_break, (tx_busy|txf_status[0]),
                                ck_uart, o_uart_tx, tx_break, (tx_busy|txf_status[0]),
                                (tx_busy|txf_status[0])?txf_wb_data:8'b00};
                                (tx_busy|txf_status[0])?txf_wb_data:8'b00};
 
 
        // Each of the FIFO's returns a 16 bit status value.  This value tells
        // Each of the FIFO's returns a 16 bit status value.  This value tells
        // us both how big the FIFO is, as well as how much of the FIFO is in 
        // us both how big the FIFO is, as well as how much of the FIFO is in 
        // use.  Let's merge those two status words together into a word we
        // use.  Let's merge those two status words together into a word we

powered by: WebSVN 2.1.0

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