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