---
boards/milkymist-one/rtl/system.v | 23 +++++-------
cores/uart/doc/uart.tex | 57 ++++++++++++++++++++++++++---
cores/uart/rtl/uart.v | 72 +++++++++++++++++++++++++------------
3 files changed, 110 insertions(+), 42 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/doc/uart.tex b/cores/uart/doc/uart.tex
index dc1a5a4..d4eb8c1 100644
--- a/cores/uart/doc/uart.tex
+++ b/cores/uart/doc/uart.tex
@@ -34,21 +34,68 @@ The divisor is computed as follows :
\hline
\bf{Offset} & \bf{Read/Write} & \bf{Default} & \bf{Description} \\
\hline
-0x0 & RW & 0x00 & Data register. Received bytes and bytes to transmit are
read/written from/to this register. \\
+0x00 & RW & 0x00 & Data register. Received bytes and bytes to transmit are
read/written from/to this register. \\
\hline
-0x4 & RW & for default bitrate & Divisor register (for bitrate selection). \\
+0x04 & RW & for default bitrate & Divisor register (for bitrate selection). \\
+\hline
+0x08 & R, W1C & 0x01 & Status and event register. Events are cleared by
writing 1. \\
+\hline
+0x0c & RW & 0x00 & Control register. \\
+\hline
+0x10 & RW & configurable & Debug register. \\
\hline
\end{tabularx}\\
+\subsection{Status and event register, offset 0x08}
+\begin{tabularx}{\textwidth}{|l|l|l|X|}
+\hline
+\bf Bits & \bf Access & \bf Default & \bf Description \\
+\hline
+0 & R & 1 & (Transmit Holding Register Empty). If this bit is set, the
transmit holding register is empty, eg. transmission is finished. \\
+\hline
+1 & R, W1C & 0 & (RX Event). See below. \\
+\hline
+2 & R, W1C & 0 & (TX Event). See below. \\
+\hline
+\end{tabularx}
+
+\subsection{Control register, offset 0x0c}
+\begin{tabularx}{\textwidth}{|l|l|l|X|}
+\hline
+\bf Bits & \bf Access & \bf Default & \bf Description \\
+\hline
+0 & RW & 1 & (RX IRQ Enable). If this bit is set, a pending RX event will
assert the interrupt output. \\
+\hline
+1 & RW & 1 & (TX IRQ Enable). If this bit is set, a pending TX event will
assert the interrupt output. \\
+\hline
+2 & RW & 1 & (THRU). If this bit is set, MIDI thru mode is enabled. \\
+\hline
+\end{tabularx}
+
+\subsection{Debug control register, offset 0x10}
+\begin{tabularx}{\textwidth}{|l|l|l|X|}
+\hline
+\bf Bits & \bf Access & \bf Default & \bf Description \\
+\hline
+0 & RW & 1 & (Break Enable). If this bit is set and the UART core receives a
BREAK symbol, the break output will be pulsed and this bit is cleared
automatically. \\
+\hline
+\end{tabularx}
+
\section{Interrupts}
-The core has two active-high edge-sensitive interrupts outputs.
+The core has one active-high level-sensitive interrupt output.
+
+Whenever an event bit is set and the corresponding event is enabled in the
control register, the interrupt output is asserted.
-The ``RX'' interrupt is sent whenever a new character is received. The CPU
should then read the data register immediately. If a new character is sent
before the CPU has had time to read it, the first character will be lost.
+\section{Events}
+The ``RX'' event is sent whenever a new character is received. The CPU should
then read the data register immediately. If a new character is sent before the
CPU has had time to read it, the first character will be lost.
The ``TX'' interrupt is sent as soon as the UART finished transmitting a
character. When the CPU has written to the data register, it must wait for the
interrupt before writing again.
+\section{MIDI thru mode}
+TBD.
+
\section{Using the core}
-Connect the CSR signals and the interrupts to the system bus and the interrupt
controller. The \verb!uart_tx! and \verb!uart_rx! signals should go to the FPGA
pads. You must also provide the desired default baudrate and the system clock
frequency in Hz using the parameters.
+Connect the CSR signals and the interrupt to the system bus and the interrupt
controller. The \verb!uart_tx! and \verb!uart_rx! signals should go to the FPGA
pads. You must also provide the desired default baudrate and the system clock
frequency in Hz using the parameters. The \verb!break! signal may be connected
to your CPU debug unit to raise an exception on BREAK.
\section*{Copyright notice}
Copyright \copyright 2007-2010 S\'ebastien Bourdeauducq. \\
diff --git a/cores/uart/rtl/uart.v b/cores/uart/rtl/uart.v
index 9c250af..6412804 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,85 @@ 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_event & tx_irq_en) | (rx_event & 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);
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 rx_event;
+reg tx_event;
+reg thre;
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;
+ tx_event <= 1'b0;
+ rx_event <= 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) begin
+ tx_event <= 1'b1;
+ thre <= 1'b1;
+ end
if(tx_wr)
- tx_pending <= 1'b1;
+ thre <= 1'b0;
+ if(rx_done) begin
+ rx_event <= 1'b1;
+ end
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 <= {tx_event, rx_event, thre};
+ 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: begin
+ /* write one to clear */
+ if(csr_di[1])
+ rx_event <= 1'b0;
+ if(csr_di[2])
+ tx_event <= 1'b0;
+ end
+ 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