OpenCores
URL https://opencores.org/ocsvn/ft245r_interface/ft245r_interface/trunk

Subversion Repositories ft245r_interface

[/] [ft245r_interface/] [trunk/] [ft245rl_interface.vhd] - Rev 3

Go to most recent revision | Compare with Previous | Blame | View Log

--------------------------------------------------------------------------
--------------------------------------------------------------------------
-- Title			: FT245R interface
-- File			: ft245rl_interface.vhd
-- Author		: Alexey Lyashko <pradd@opencores.org>
-- License		: LGPL
--------------------------------------------------------------------------
-- Description	:
-- The controller simplifies the communication with FT245R chip. While 
-- provided interface is very similar to that of the chip itself, 
-- this controller takes care of all the delays and other aspects of 
-- FT245R's protocol as well as provifes separate ports for input and 
-- output.
--------------------------------------------------------------------------
--------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
 
entity ft245rl_interface is
	-- This value is for 400MHz clock. Change it to suit your configuration.
	generic (min_delay : real := 2.5);														
	port
	(
		-- physical FT245RL interface 
		data_io					: inout 	std_logic_vector(7 downto 0);					
		nrst						: out		std_logic := '1';									
		ntxe						: in		std_logic;
		nrxf						: in		std_logic;
		nwr						: out		std_logic := '0';
		nrd						: out		std_logic := '1';
 
		-- logical interface
		clk						: in		std_logic;								-- System clock
		data_in					: in		std_logic_vector(7 downto 0);		-- Input from client entity
		data_out					: out		std_logic_vector(7 downto 0);		-- Output to client entity
		nce						: in		std_logic := '1';						-- "Chip" enable
		fetch_next_byte		: in		std_logic := '0';						-- Strobing this to '1' instructs the module to poll FT245RL for next available byte
		do_write					: in		std_logic := '0';						-- Strobing this to '1' instructs the module to write byte to FT245RL
		busy						: out		std_logic := '0';						-- Is '1' when the module is processing data
		data_available			: buffer	std_logic := '0';						-- Notifies the client of data availability
		reset						: in		std_logic := '1'						-- Resets the module
	);
end ft245rl_interface;
 
 
architecture action of ft245rl_interface is
	type state_t is (
								INIT,
								IDLE,
								READ_BYTE,
								READ_BYTE1,
								READ_BYTE2,
								READ_BYTE3,
								WRITE_BYTE,
								WRITE_BYTE1,
								WRITE_BYTE2,
								WRITE_BYTE3,
								DO_DELAY
							);
	signal c_state	: state_t := INIT;	-- current state
	signal n_state	: state_t := INIT;	-- next state
 
	signal delay_cnt:integer := 0;								-- Delay counter register
	signal current_delay : integer := 0;						-- This register holds number of clock cycles 
																			-- needed by the specified delay
	signal in_buff	: std_logic_vector(7 downto 0);			-- holds data received from FT245RL
	signal out_buff: std_logic_vector(7 downto 0);			-- holds data to be sent to FT245RL
	signal we		: std_logic := '0';							-- enables data output to FT245RL
 
	-- All delay specs may be found in FT245RL datasheet at
	-- http://www.ftdichip.com/Support/Documents/DataSheets/ICs/DS_FT245R.pdf
	constant t1_delay		:	integer := integer(50.0 / min_delay) - 1;
	constant t2_delay		:	integer := integer((50.0 + 80.0) / min_delay) - 1;
	constant t3_delay		:	integer := integer(35.0 / min_delay) - 1;
	constant t4_delay		:	integer := 0;
	constant t5_delay		:	integer := integer(25.0 / min_delay) - 1;
	constant t6_delay		:	integer := integer(80.0 / min_delay) - 1;
	constant t7_delay		:	integer := integer(50.0 / min_delay) - 1;
	constant t8_delay		:	integer := integer(50.0 / min_delay) - 1;
	constant t9_delay		:	integer := integer(20.0 / min_delay) - 1;
	constant t10_delay	:	integer := 0;
	constant t11_delay	:	integer := integer(25.0 / min_delay) - 1;
	constant t12_delay	:	integer := integer(80.0 / min_delay) - 1;
begin
 
	-- Bidirectional bus implementation.
	data_io	<=	out_buff when we = '1' else
					"ZZZZZZZZ" when we = '0' else
					"XXXXXXXX";
	in_buff	<= data_io;
 
 
	process(clk, reset, nrxf, ntxe, nce)
	begin
		if(reset = '0')then
			c_state		<= INIT;
		elsif(rising_edge(clk) and nce = '0')then
 
			case c_state is
				-- The module enters this state on powerup or when 'reset' is low.
				when INIT =>
									delay_cnt		<= 0;
									current_delay	<= 0;
									c_state			<= IDLE;
									nrst				<= '0';								-- Reset FT245RL on init
 
				-- This is the "main loop"
				when IDLE =>
									nrst 				<= '1';
 
									-- If this condition is true, we may safely read another byte from FT245RL's FIFO
									if(nrxf = '0' and data_available = '0')then
										c_state		<= READ_BYTE;
 
									-- We have to clear 'data_available' when the client module is requesting a new byte
									elsif(fetch_next_byte = '1')then
										data_available	<= '0';
										c_state		<= IDLE;
 
									-- Well, here we simply write a byte to FT245RL's data bus
									elsif(do_write = '1')then
										c_state		<= WRITE_BYTE;
									end if;
 
 
				-- Read one byte from the device
				when READ_BYTE =>
									busy				<= '1';
									nrd				<= '0';
									current_delay	<= t3_delay;
									c_state			<= DO_DELAY;
									n_state			<= READ_BYTE1;
 
				when READ_BYTE1 =>
									current_delay	<= t1_delay - t3_delay;
									c_state			<= DO_DELAY;
									n_state			<= READ_BYTE2;
 
				when READ_BYTE2 =>
									data_out			<= in_buff;
									nrd				<= '1';
									current_delay	<= t5_delay;
									c_state			<= DO_DELAY;
									n_state			<= READ_BYTE3;
 
				when READ_BYTE3 =>
									current_delay	<= t2_delay;
									c_state			<= DO_DELAY;
									n_state			<= IDLE;
									data_available	<= '1';
									busy				<= '0';
 
				-- Write one byte to the device
				when WRITE_BYTE =>
									busy			<= '1';
									if(ntxe = '0')then
										nwr			<= '1';
										we				<= '1';
										current_delay<= t7_delay;
										c_state		<= DO_DELAY;
										n_state		<= WRITE_BYTE1;
										out_buff		<= data_in;
									else
										c_state		<= WRITE_BYTE;
									end if;
 
				when WRITE_BYTE1 =>
									nwr				<= '0';
									current_delay	<= t11_delay;
									c_state			<= DO_DELAY;
									n_state			<= WRITE_BYTE2;
 
				when WRITE_BYTE2 =>
									we					<= '0';
									current_delay	<= t12_delay;
									c_state			<=DO_DELAY;
									n_state			<= WRITE_BYTE3;
 
				when WRITE_BYTE3 =>
									busy				<= '0';
									c_state			<= IDLE;
 
				when DO_DELAY =>
									if(delay_cnt < current_delay)then	
										delay_cnt 	<= delay_cnt + 1;
									else
										c_state		<= n_state;
										delay_cnt	<= 0;
									end if;
 
				when others =>
									c_state		<= INIT;
			end case;	-- c_state
		end if;
	end process;
 
end action;

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.