My first FPGA – UART-Communication

My first steps in the world of FPGAs I did last week when I tried to implement an UART-interface to communicate with my PC. Because my DE0-Nano did not contain a display, I decided to use the 8 green LED on the board to show the received data.

Of course, there are a lot of examples out there to start with an FPGA and I really used a lot of different blogs to analyze examples to learn from, but it doesn’t mean, another “my-first-FPGA”-example is unnecessary.

I use a SparkFun FTDI Basic Breakout with 3.3V signals, because I was not sure, whether the used GPIO-pins are 5V-tolerant.

The code is segmented into 3 files. One for the main-entity (UART) and two others for the RX- and TX-component:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
ENTITY UART IS
PORT (
	CLOCK_50: IN STD_LOGIC;
	KEY: IN STD_LOGIC_VECTOR(1 downto 0);
	LED: OUT STD_LOGIC_VECTOR(7 downto 0);
	UART_RXD: IN STD_LOGIC;
	UART_TXD: OUT STD_LOGIC
);
END UART;
 
ARCHITECTURE main OF UART IS
 
SIGNAL tx_start: STD_LOGIC:='0';
SIGNAL tx_busy: STD_LOGIC;
SIGNAL tx_data: STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL rx_busy: STD_LOGIC;
SIGNAL rx_data: STD_LOGIC_VECTOR(7 DOWNTO 0);
 
COMPONENT tx
PORT(
	clk: IN STD_LOGIC;
	start: IN STD_LOGIC;
	busy: OUT STD_LOGIC;
	data:  IN STD_LOGIC_VECTOR(7 downto 0);
	tx_line: OUT STD_LOGIC
);
END COMPONENT tx;
 
COMPONENT rx
PORT(
	clk: IN STD_LOGIC;
	busy: OUT STD_LOGIC;
	data:  OUT STD_LOGIC_VECTOR(7 downto 0);
	rx_line: IN STD_LOGIC
);
END COMPONENT rx;
 
BEGIN
 
C1: tx PORT MAP(CLOCK_50, tx_start, tx_busy, tx_data, UART_TXD);
C2: rx PORT MAP(CLOCK_50, rx_busy, rx_data, UART_RXD);
 
PROCESS(rx_busy)
BEGIN
	IF falling_edge(rx_busy) THEN
		LED<=rx_data;
	END IF;
END PROCESS;
 
PROCESS(CLOCK_50)
BEGIN
	IF rising_edge(CLOCK_50) THEN
		IF (KEY(0)='0' AND tx_busy='0') THEN
			tx_data<="00010001";	
			tx_start<='1';
			--LED<=tx_data;
		ELSE
			tx_start<='0';
		END IF;
	END IF;
END PROCESS;
 
END ARCHITECTURE main;

The RX-component look like that:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
ENTITY rx IS
PORT(
clk: IN STD_LOGIC;
busy: OUT STD_LOGIC;
data:  OUT STD_LOGIC_VECTOR(7 downto 0);
rx_line: IN STD_LOGIC
);
END rx;
 
ARCHITECTURE main OF rx IS
SIGNAL prescaler: INTEGER RANGE 0 TO 434:=0;
SIGNAL index: INTEGER RANGE 0 TO 9:=0;
SIGNAL fullData: STD_LOGIC_VECTOR (9 downto 0);
SIGNAL rx_flag: STD_LOGIC:='0';
 
BEGIN
PROCESS(clk)
BEGIN
IF rising_edge(clk) THEN
	IF(rx_flag='0' AND rx_line='0') THEN
		busy<='1';
		index<=0;
		prescaler<=0;
		rx_flag<='1';
	END IF;
 
	IF (rx_flag='1') THEN
		fullData(index)<=rx_line;
		IF (prescaler<433) THEN
			prescaler<=prescaler+1;
		ELSE
			prescaler<=0;
		END IF;
		IF (prescaler=216) THEN
			IF (index<9) THEN	
				index<=index+1;
			ELSE
				IF (fullData(0)='0' AND fullData(9)='1') THEN
					data<=fullData(8 DOWNTO 1);
				ELSE
					data<=(others=>'0');
				END IF;
				rx_flag<='0';
				busy<='0';
			END IF;
		END IF;
	END IF;
END IF;
END PROCESS;
END ARCHITECTURE main;

and the TX-component looks very similar:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
ENTITY tx IS
PORT(
clk: IN STD_LOGIC;
start: IN STD_LOGIC;
busy: OUT STD_LOGIC;
data:  IN STD_LOGIC_VECTOR(7 downto 0);
tx_line: OUT STD_LOGIC
);
END tx;
 
ARCHITECTURE main OF tx IS
SIGNAL prescaler: INTEGER RANGE 0 TO 434:=0;
SIGNAL index: INTEGER RANGE 0 TO 9:=0;
SIGNAL fullData: STD_LOGIC_VECTOR (9 downto 0);
SIGNAL tx_flag: STD_LOGIC:='0';
 
BEGIN
PROCESS(clk)
BEGIN
IF rising_edge(clk) THEN
	IF (tx_flag='0' AND start='1') THEN
		tx_flag<='1';
		busy<='1';
		fullData(0)<='0';
		fullData(9)<='1';
		fullData(8 DOWNTO 1)<=data;
	END IF;
	IF (tx_flag='1') THEN
		IF (prescaler<433) THEN
			prescaler<=prescaler+1;
		ELSE
			prescaler<=0;
		END IF;
		IF (prescaler=216) THEN
			tx_line<=fullData(index);
			IF (index<9) THEN
				index<=index+1;
			ELSE
				tx_flag<='0';
				busy<='0';
				index<=0;
			END IF;
		END IF;
	END IF;
END IF;
 
END PROCESS;
END ARCHITECTURE main;

After programming the Cyclone IV the LED are all off. After sending a 8-bit binary from HTerm the corresponding LED are on now.

One Comment

Add a Comment

Your email address will not be published. Required fields are marked *