New memory map:

Offset  Name  Access  Description
---------------------------------------------------------------------
0x00    RXTX  R/W     write to tx buffer, read from rx buffer
0x04    DIV   R/W     divisor for baud generator
0x08    STAT  R       status register
0x0c    CTRL  R/W     control register
0x10    DBG   R/W     debug register

STAT
Bit    Name   Description
---------------------------------------------------------------------
0      DR     Data Ready. '1' if a character was received.
                '0' if RXTX is read.
1      THRE   Transmit Hold Register Empty. '1' if no
                                transmission is in progress, otherwise '0'.

CTRL
Bit    Name        Description
---------------------------------------------------------------------
0      RX_INT_EN   Enable RBR IRQ.
1      TX_INT_EN   Enable THRE IRQ.
2      THRU_EN     Enable loopback mode.

DBG
Bit    Name        Description
---------------------------------------------------------------------
0      BREAK_EN    Enable hardware exception on UART break frame.

Interrupts:
  One IRQ, pulses of (DR & RX_INT_EN) | (THRE & TX_INT_EN).
---
 boards/milkymist-one/rtl/system.v |   23 +++++--------
 cores/uart/rtl/uart.v             |   65 ++++++++++++++++++++++++-------------
 2 files changed, 51 insertions(+), 37 deletions(-)

diff --git a/boards/milkymist-one/rtl/system.v 
b/boards/milkymist-one/rtl/system.v
index 9608344..ae95ffe 100644
--- a/boards/milkymist-one/rtl/system.v
+++ b/boards/milkymist-one/rtl/system.v
@@ -720,8 +720,7 @@ fmlbrg #(
 //---------------------------------------------------------------------------
 // Interrupts
 //---------------------------------------------------------------------------
-wire uartrx_irq;
-wire uarttx_irq;
+wire uart_irq;
 wire gpio_irq;
 wire timer0_irq;
 wire timer1_irq;
@@ -734,8 +733,7 @@ wire tmu_irq;
 wire ethernetrx_irq;
 wire ethernettx_irq;
 wire videoin_irq;
-wire midirx_irq;
-wire miditx_irq;
+wire midi_irq;
 wire ir_irq;
 wire usb_irq;
 
@@ -743,8 +741,8 @@ wire [31:0] cpu_interrupt;
 assign cpu_interrupt = {14'd0,
        usb_irq,
        ir_irq,
-       miditx_irq,
-       midirx_irq,
+       1'b0,
+       midi_irq,
        videoin_irq,
        ethernettx_irq,
        ethernetrx_irq,
@@ -757,8 +755,8 @@ assign cpu_interrupt = {14'd0,
        timer1_irq,
        timer0_irq,
        gpio_irq,
-       uarttx_irq,
-       uartrx_irq
+       1'b0,
+       uart_irq
 };
 
 //---------------------------------------------------------------------------
@@ -876,8 +874,7 @@ uart #(
        .csr_di(csr_dw),
        .csr_do(csr_dr_uart),
 
-       .rx_irq(uartrx_irq),
-       .tx_irq(uarttx_irq),
+       .irq(uart_irq),
 
        .uart_rx(uart_rx),
        .uart_tx(uart_tx),
@@ -1383,16 +1380,14 @@ uart #(
        .csr_di(csr_dw),
        .csr_do(csr_dr_midi),
 
-       .rx_irq(midirx_irq),
-       .tx_irq(miditx_irq),
+       .irq(midi_irq),
 
        .uart_rx(midi_rx),
        .uart_tx(midi_tx)
 );
 `else
 assign csr_dr_midi = 32'd0;
-assign midirx_irq = 1'b0;
-assign miditx_irq = 1'b0;
+assign midi_irq = 1'b0;
 assign midi_tx = 1'b1;
 `endif
 
diff --git a/cores/uart/rtl/uart.v b/cores/uart/rtl/uart.v
index 9c250af..b63d4bd 100644
--- a/cores/uart/rtl/uart.v
+++ b/cores/uart/rtl/uart.v
@@ -29,8 +29,7 @@ module uart #(
        input [31:0] csr_di,
        output reg [31:0] csr_do,
 
-       output rx_irq,
-       output tx_irq,
+       output irq,
 
        input uart_rx,
        output uart_tx,
@@ -55,58 +54,78 @@ uart_transceiver transceiver(
        .divisor(divisor),
 
        .rx_data(rx_data),
-       .rx_done(rx_irq),
+       .rx_done(rx_done),
 
        .tx_data(tx_data),
        .tx_wr(tx_wr),
-       .tx_done(tx_irq),
+       .tx_done(tx_done),
 
        .break(break_transceiver)
 );
 
-assign uart_tx = thru ? uart_rx : uart_tx_transceiver;
+assign uart_tx = thru_en ? uart_rx : uart_tx_transceiver;
 assign break = break_en & break_transceiver;
 
 /* CSR interface */
 wire csr_selected = csr_a[13:10] == csr_addr;
 
+assign irq = (tx_done & tx_irq_en) | (rx_done & rx_irq_en);
+
 assign tx_data = csr_di[7:0];
-assign tx_wr = csr_selected & csr_we & (csr_a[1:0] == 2'b00);
+assign tx_wr = csr_selected & csr_we & (csr_a[2:0] == 3'b000);
+assign rx_rd = csr_selected & !csr_we & (csr_a[2:0] == 3'b000);
 
 parameter default_divisor = clk_freq/baud/16;
 
-reg thru;
+reg thru_en;
 reg break_en;
-reg tx_pending;
+
+reg tx_irq_en;
+reg rx_irq_en;
+reg thre;
+reg data_ready;
 
 always @(posedge sys_clk) begin
        if(sys_rst) begin
                divisor <= default_divisor;
                csr_do <= 32'd0;
-               thru <= 1'b0;
+               thru_en <= 1'b0;
                break_en <= break_en_default;
-               tx_pending <= 1'b0;
+               rx_irq_en <= 1'b0;
+               tx_irq_en <= 1'b0;
+               data_ready <= 1'b0;
+               thre <= 1'b1;
        end else begin
                csr_do <= 32'd0;
                if(break)
                        break_en <= 1'b0;
-               if(tx_irq)
-                       tx_pending <= 1'b0;
+               if(tx_done)
+                       thre <= 1'b1;
                if(tx_wr)
-                       tx_pending <= 1'b1;
+                       thre <= 1'b0;
+               if(rx_done)
+                       data_ready <= 1'b1;
+               if(rx_rd)
+                       data_ready <= 1'b0;
                if(csr_selected) begin
-                       case(csr_a[1:0])
-                               2'b00: csr_do <= rx_data;
-                               2'b01: csr_do <= divisor;
-                               2'b10: csr_do <= thru;
-                               2'b11: csr_do <= {tx_pending, break_en};
+                       case(csr_a[2:0])
+                               3'b000: csr_do <= rx_data;
+                               3'b001: csr_do <= divisor;
+                               3'b010: csr_do <= {thre, data_ready};
+                               3'b011: csr_do <= {thru_en, tx_irq_en, 
rx_irq_en};
+                               3'b100: csr_do <= {break_en};
                        endcase
                        if(csr_we) begin
-                               case(csr_a[1:0])
-                                       2'b00:; /* handled by transceiver */
-                                       2'b01: divisor <= csr_di[15:0];
-                                       2'b10: thru <= csr_di[0];
-                                       2'b11: break_en <= csr_di[0];
+                               case(csr_a[2:0])
+                                       3'b000:; /* handled by transceiver */
+                                       3'b001: divisor <= csr_di[15:0];
+                                       3'b010:; /* read only */
+                                       3'b011: begin
+                                               rx_irq_en <= csr_di[0];
+                                               tx_irq_en <= csr_di[1];
+                                               thru_en <= csr_di[2];
+                                       end
+                                       3'b100: break_en <= csr_di[0];
                                endcase
                        end
                end
-- 
1.7.2.5

_______________________________________________
http://lists.milkymist.org/listinfo.cgi/devel-milkymist.org
IRC: #milkymist@Freenode
Twitter: www.twitter.com/milkymistvj
Ideas? http://milkymist.uservoice.com

Reply via email to