1
0
mirror of git://projects.qi-hardware.com/nn-usb-fpga.git synced 2025-04-21 12:27:27 +03:00

Updating examples to Board changes, adding irq driver demo

This commit is contained in:
Carlos Camargo
2010-06-11 08:06:13 -05:00
parent c8b70e5307
commit 5041c0eb60
41 changed files with 2263 additions and 145 deletions

View File

@@ -0,0 +1,23 @@
TEX=uart.tex
DVI=$(TEX:.tex=.dvi)
PS=$(TEX:.tex=.ps)
PDF=$(TEX:.tex=.pdf)
AUX=$(TEX:.tex=.aux)
LOG=$(TEX:.tex=.log)
all: $(PDF)
%.dvi: %.tex
latex $<
%.ps: %.dvi
dvips $<
%.pdf: %.ps
ps2pdf $<
clean:
rm -f $(DVI) $(PS) $(PDF) $(AUX) $(LOG)
.PHONY: clean

View File

@@ -0,0 +1,57 @@
\documentclass[a4paper,11pt]{article}
\usepackage{fullpage}
\usepackage[latin1]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[normalem]{ulem}
\usepackage[english]{babel}
\usepackage{listings,babel}
\lstset{breaklines=true,basicstyle=\ttfamily}
\usepackage{graphicx}
\usepackage{moreverb}
\usepackage{amsmath}
\usepackage{url}
\usepackage{tabularx}
\title{Simple UART}
\author{S\'ebastien Bourdeauducq}
\date{December 2009}
\begin{document}
\setlength{\parindent}{0pt}
\setlength{\parskip}{5pt}
\maketitle{}
\section{Specifications}
The UART is based on a very simple design from Das Labor. Its purpose is basically to provide a debug console.
The UART operates with 8 bits per character, no parity, and 1 stop bit. The default baudrate is configured during synthesis and can be modified at runtime using the divisor register.
The divisor is computed as follows :
\begin{equation*}
\text{divisor} = \frac{\text{Clock frequency (Hz)}}{16 \cdot \text{Bitrate (bps)}}
\end{equation*}
\section{Registers}
\begin{tabularx}{\textwidth}{|l|l|l|X|}
\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. \\
\hline
0x4 & RW & for default bitrate & Divisor register (for bitrate selection). \\
\hline
\end{tabularx}\\
\section{Interrupts}
The core has two active-high edge-sensitive interrupts outputs.
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.
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{Using the core}
Connect the CSR signals and the interrupts to the system bus and the interrupt controller. The \verb!uart_txd! and \verb!uart_rxd! 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.
\section*{Copyright notice}
Copyright \copyright 2007-2009 S\'ebastien Bourdeauducq. \\
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the LICENSE.FDL file at the root of the Milkymist source distribution.
\end{document}

View File

@@ -0,0 +1,87 @@
/*
* Milkymist VJ SoC
* Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
module uart #(
parameter csr_addr = 4'h0,
parameter clk_freq = 100000000,
parameter baud = 115200
) (
input sys_clk,
input sys_rst,
input [13:0] csr_a,
input csr_we,
input [31:0] csr_di,
output reg [31:0] csr_do,
output rx_irq,
output tx_irq,
input uart_rxd,
output uart_txd
);
reg [15:0] divisor;
wire [7:0] rx_data;
wire [7:0] tx_data;
wire tx_wr;
uart_transceiver transceiver(
.sys_clk(sys_clk),
.sys_rst(sys_rst),
.uart_rxd(uart_rxd),
.uart_txd(uart_txd),
.divisor(divisor),
.rx_data(rx_data),
.rx_done(rx_irq),
.tx_data(tx_data),
.tx_wr(tx_wr),
.tx_done(tx_irq)
);
/* CSR interface */
wire csr_selected = csr_a[13:10] == csr_addr;
assign tx_data = csr_di[7:0];
assign tx_wr = csr_selected & csr_we & (csr_a[0] == 1'b0);
parameter default_divisor = clk_freq/baud/16;
always @(posedge sys_clk) begin
if(sys_rst) begin
divisor <= default_divisor;
csr_do <= 32'd0;
end else begin
csr_do <= 32'd0;
if(csr_selected) begin
case(csr_a[0])
1'b0: csr_do <= rx_data;
1'b1: csr_do <= divisor;
endcase
if(csr_we) begin
if(csr_a[0] == 1'b1)
divisor <= csr_di[15:0];
end
end
end
end
endmodule

View File

@@ -0,0 +1,157 @@
/*
* Milkymist VJ SoC
* Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
* Copyright (C) 2007 Das Labor
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
module uart_transceiver(
input sys_rst,
input sys_clk,
input uart_rxd,
output reg uart_txd,
input [15:0] divisor,
output reg [7:0] rx_data,
output reg rx_done,
input [7:0] tx_data,
input tx_wr,
output reg tx_done
);
//-----------------------------------------------------------------
// enable16 generator
//-----------------------------------------------------------------
reg [15:0] enable16_counter;
wire enable16;
assign enable16 = (enable16_counter == 16'd0);
always @(posedge sys_clk) begin
if(sys_rst)
enable16_counter <= divisor - 16'b1;
else begin
enable16_counter <= enable16_counter - 16'd1;
if(enable16)
enable16_counter <= divisor - 16'b1;
end
end
//-----------------------------------------------------------------
// Synchronize uart_rxd
//-----------------------------------------------------------------
reg uart_rxd1;
reg uart_rxd2;
always @(posedge sys_clk) begin
uart_rxd1 <= uart_rxd;
uart_rxd2 <= uart_rxd1;
end
//-----------------------------------------------------------------
// UART RX Logic
//-----------------------------------------------------------------
reg rx_busy;
reg [3:0] rx_count16;
reg [3:0] rx_bitcount;
reg [7:0] rxd_reg;
always @(posedge sys_clk) begin
if(sys_rst) begin
rx_done <= 1'b0;
rx_busy <= 1'b0;
rx_count16 <= 4'd0;
rx_bitcount <= 4'd0;
end else begin
rx_done <= 1'b0;
if(enable16) begin
if(~rx_busy) begin // look for start bit
if(~uart_rxd2) begin // start bit found
rx_busy <= 1'b1;
rx_count16 <= 4'd7;
rx_bitcount <= 4'd0;
end
end else begin
rx_count16 <= rx_count16 + 4'd1;
if(rx_count16 == 4'd0) begin // sample
rx_bitcount <= rx_bitcount + 4'd1;
if(rx_bitcount == 4'd0) begin // verify startbit
if(uart_rxd2)
rx_busy <= 1'b0;
end else if(rx_bitcount == 4'd9) begin
rx_busy <= 1'b0;
if(uart_rxd2) begin // stop bit ok
rx_data <= rxd_reg;
rx_done <= 1'b1;
end // ignore RX error
end else
rxd_reg <= {uart_rxd2, rxd_reg[7:1]};
end
end
end
end
end
//-----------------------------------------------------------------
// UART TX Logic
//-----------------------------------------------------------------
reg tx_busy;
reg [3:0] tx_bitcount;
reg [3:0] tx_count16;
reg [7:0] txd_reg;
always @(posedge sys_clk) begin
if(sys_rst) begin
tx_done <= 1'b0;
tx_busy <= 1'b0;
uart_txd <= 1'b1;
end else begin
tx_done <= 1'b0;
if(tx_wr) begin
txd_reg <= tx_data;
tx_bitcount <= 4'd0;
tx_count16 <= 4'd1;
tx_busy <= 1'b1;
uart_txd <= 1'b0;
`ifdef SIMULATION
$display("UART: %c", tx_data);
`endif
end else if(enable16 && tx_busy) begin
tx_count16 <= tx_count16 + 4'd1;
if(tx_count16 == 4'd0) begin
tx_bitcount <= tx_bitcount + 4'd1;
if(tx_bitcount == 4'd8) begin
uart_txd <= 1'b1;
end else if(tx_bitcount == 4'd9) begin
uart_txd <= 1'b1;
tx_busy <= 1'b0;
tx_done <= 1'b1;
end else begin
uart_txd <= txd_reg[0];
txd_reg <= {1'b0, txd_reg[7:1]};
end
end
end
end
end
endmodule