⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 devicetranseiver.vhd

📁 < FPGA数字电子系统设计与开发实例导航> 一书的代码
💻 VHD
📖 第 1 页 / 共 2 页
字号:
---------------------------------------------------------------------------------------------------
--
-- File        : e:\Courses\ComputerHardwareInterface\USB_IF_DESIGN\USB_IF\src\DeviceTranseiver.vhd
-- Create Time : Fri Apr 16 20:18:23 2004
-- Title       : DeviceTranseiver
-- Design      : USB Interface IP Core
-- Author      : Lou Xinghua (louxinghua99@mails.tsinghua.edu.cn)
-- Company     : Department of Engineering Physics in Tsinghua Unversity, Beijing, China
-- Version     : 1.0
--
---------------------------------------------------------------------------------------------------
--
-- Description : 
-- This module implements data receiving and transfering with cooperation of PIDUSBD12.
-- It also communicates with the RequestHandler module.
-- Written by Lou Xinghua
--
---------------------------------------------------------------------------------------------------

--{{ Section below this comment is automatically maintained
--   and may be overwritten
--{entity {DeviceTranseiver} architecture {DeviceTranseiver}}

library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_ARITH.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
use WORK.USB_PACKAGE.all;
use WORK.PDIUSBD12_PACKAGE.all;


entity DeviceTranseiver is
	 port(					  
		 reset_n : in STD_LOGIC; 
		 clk : in STD_LOGIC;  
		 int_n : in STD_LOGIC;
		 a0 : out STD_LOGIC;
		 data_in : in STD_LOGIC_VECTOR(7 downto 0);
		 data_out : out STD_LOGIC_VECTOR(7 downto 0);
		 wr_n : out STD_LOGIC;
		 rd_n : out STD_LOGIC;
		 suspend : inout STD_LOGIC;
		 recv_n : out STD_LOGIC;
		 cmd : in STD_LOGIC_VECTOR(7 downto 0);
		 exec_n: in STD_LOGIC;
		 req_type : out STD_LOGIC_VECTOR(7 downto 0);
		 step : out std_logic_vector(7 downto 0)
	     );
end DeviceTranseiver;

--}} End of automatically maintained section

architecture DeviceTranseiver of DeviceTranseiver is

-- Internal Signals

-- Temp Signals

-- State Machine
signal ts_state: TRANSEIVER_STATE;		
signal ih_state: INT_HANDLE_STATE;

signal config: STD_LOGIC;						-- configuration 
signal remote_wakeup: STD_LOGIC;				-- remote wakeup
	
-- Registers
signal ts_data: REG256x8 := TRANSEIVER_DATA; 
	
begin

	-- enter your statements here --
	
	-- signal connections	
	
	-- main process
	main_process: 
	process( reset_n, clk )	

	-- in process variables
	variable handle_step: INTEGER8 := 0; 	
	variable wr_n_var: STD_LOGIC := '1'; 
	variable rd_n_var: STD_LOGIC := '1';
	
	-- 
	variable ir_0: STD_LOGIC_VECTOR(7 downto 0);		-- interrupt register 0 
	variable ir_1: STD_LOGIC;							-- interrupt register 1 (EOT) 
	variable is_setup: STD_LOGIC;						-- last transaction status register	 

	--
	variable active_ep: STD_LOGIC_VECTOR(7 downto 0) := X"FF";
	variable ram_address: INTEGER8 := 0;
	variable read_count: INTEGER8 := 0;	
	variable to_read: INTEGER8 := 0;
	variable read_in: INTEGER8 := 0; 
	variable data_length: INTEGER8 := 0; 
	variable data_count: INTEGER8 := 0;	  
	variable is_receive: STD_LOGIC := '0';	
	variable write_count: INTEGER8 := 0;
	variable to_write: INTEGER8 := 0;  
	variable is_transmit: STD_LOGIC := '0';	
	---- Read/Write EndPoint Related Variables 		 				  
	variable last_ts_state: TRANSEIVER_STATE;

	begin
		if reset_n = '0' then
			-- reset state machine
			ts_state <= TS_DISCONNECTED;  
			ih_state <= IH_IDLE;
			-- reset output signals		 
			a0 <= '0';
			data_out <= X"00";	 
			wr_n <= '1';
			rd_n <= '1';
			recv_n <= '1';
			req_type <= X"00";			 
			step <= X"FF";
			-- reset internal signals & in process variables  
			data_out <= X"00";
			ts_data <= TRANSEIVER_DATA;						 		
			config <= '0';
			remote_wakeup <= '0';
			ir_0 := X"00";
			ir_1 := '0';
			is_setup := '0'; 							
			active_ep := X"FF";
			ram_address := 0; 
			read_count := 0;
			to_read := 0;
			read_in := 0;		   		   
			data_length := 0;		   		   
			data_count := 0;  
			is_receive := '0';		   
			to_write := 0;	 
			is_transmit := '0';
			handle_step := 0;								
			last_ts_state := TS_IDLE;
		elsif rising_edge(clk) then			 
			-- init in process variables
			wr_n_var := '1';
			rd_n_var := '1';
			-- handle according to current state
			case ts_state is												
				
			-- state is 'disconnected', means not connected to PDIUSBD12
			when TS_DISCONNECTED =>	 	
				ts_state <= TS_CONNECTING;   
				handle_step := 0;
				
			-- state is 'connecting', means connecting to PDIUSBD12, sending configuration data
			when TS_CONNECTING =>
				-- send varies of command to config PDIUSBD12
				case handle_step is
				when 0 =>
					data_out <= D12_COMMAND_SET_DMA;
					a0 <= D12_COMMAND;
					wr_n_var := '0';
				when 1 =>
					data_out <= D12_DMA;
					a0 <= D12_DATA;
					wr_n_var := '0';
				when 2 =>
					data_out <= D12_COMMAND_SET_MODE;
					a0 <= D12_COMMAND;
					wr_n_var := '0';
				when 3 =>
					data_out <= D12_MODE_CONFIG;
					a0 <= D12_DATA;
					wr_n_var := '0';
				when 4 =>
					data_out <= D12_MODE_CLOCK_DIV;
					a0 <= D12_DATA;
					wr_n_var := '0';
				when 5 =>
					ts_state <= TS_IDLE;
				when others =>
					NULL;
				end case;
				handle_step := handle_step+1;
				
			-- state is 'idle', means PDIUSBD12 is free
			when TS_IDLE =>
				data_out <= X"00";
				recv_n <= '1';
				ih_state <= IH_START;
				-- check for interrupt & request handler's command
				if int_n = '0' then		   
					handle_step := 0;
					ts_state <= TS_READ_IR;
				elsif exec_n = '0' then
					ts_state <= GetCommandHandler(cmd);
					handle_step := 0;
				end if;

			when TS_END_REQUESTHANDLER =>
--				suspend <= '1';
				ts_state <= TS_IDLE;
								
			-- state is 'read ir', means reading interrupt reigster
			when TS_READ_IR =>
				if handle_step = 0 then
					-- send command: read interrupt register
					a0 <= D12_COMMAND;
					data_out <= D12_COMMAND_READ_IR;
					wr_n_var := '0';
				elsif handle_step = 1 then
					-- try to retrieve the first data
					a0 <= D12_DATA;
					rd_n_var := '0';
				elsif handle_step = 2 then
					-- reserve the first data
					ir_0 := data_in;			 
					-- try to retrieve the second data
					a0 <= D12_DATA;
					rd_n_var := '0';
				else
					-- reserve the second data
					ir_1 := data_in(0);
					-- till now, we have finished retrieving interrupt registers
					ts_state <= GetInterruptHandler(ir_0, ir_1);
					ih_state <= IH_START;
				end if;
				handle_step := handle_step+1;

			when TS_BUSRESET =>
--				suspend <= '1';	 
--				config <= '0';
--				remote_wakeup <= '0';
--				step <= X"FF";  
				ts_state <= TS_IDLE;

			-- state is 'suspend change'
			when TS_SUSPENDCHANGE =>
--				if suspend = '1' then
--					suspend <= '0';
--				end if;
				ts_state <= TS_IDLE;
				
			-- state is 'endpoint0 receive', means endpoint0 has data arrived
			when TS_EP0_RECEIVE =>	
			
				-- state is 'start', means starting processing
				case ih_state is 															   
				when IH_START =>	   	   	
					-- send command: read last transaction status register of endpoint 0
					a0 <= D12_COMMAND;
					data_out <= D12_COMMAND_READ_LTS_EP0_OUT;
					wr_n_var := '0';
					handle_step := 0;
					ih_state <= IH_READ_LTS;
				-- state is 'read lts', means reading last transaction status
				when IH_READ_LTS =>
					if handle_step = 0 then
						-- try to retrieve last transaction status register of endpoint 0
						a0 <= D12_DATA;
						rd_n_var := '0';
						handle_step := handle_step+1;
					else
						-- reserve last transaction status register of endpoint 0
						is_setup := data_in(D12_SETUPPACKET_BIT);
						-- till now, we have finished reading last transaction status 
						-- prepare to retrieve data
						active_ep := X"00";
						read_count := 0; 
						read_in := 0;
						last_ts_state := ts_state;
						ts_state <= TS_READ_ENDPOINT; 
						handle_step := 0; 
						-- check whether it is a setup packet or regular data
						if is_setup = '1' then 
							ram_address := ADDRESS_EP0_BUFFER;
							to_read := LENGTH_SETUP_PACKET;	
							ih_state <= IH_ACK_ENDPOINT;
						elsif is_receive = '1' then  
							ram_address := ADDRESS_EP0_BUFFER+data_count;
							to_read := LENGTH_ENDPOINT0_BUFFER;
							ih_state <= IH_END_RECEIVE;
						else
							ts_state <= TS_IDLE;
						end if;
					end if;
					
				-- state is 'acknowledge setup', means acknowledge retrieving setup packet
				when IH_ACK_ENDPOINT =>	
					if to_read = read_in then
						-- send varies of command to acknowledge endpoint access
						data_out <= ep0_ack_data(handle_step);
						a0 <= D12_COMMAND;
						wr_n_var := '0';
						handle_step := handle_step+1;
						if handle_step = D12_EP0_ACK_DATA_LENGTH then
							-- get the data length of this transaction, reserved in 'data_length'
							data_length := GetDataLength(ts_data(ADDRESS_DATA_LENGTH_HIGH), ts_data(ADDRESS_DATA_LENGTH_LOW));
							-- data_count reserves the amount of retrieved data
							data_count := 0;
							is_receive := '0';
							-- check whether more data need retrieve
							if ts_data(ADDRESS_EP0_BUFFER)(7) = '1' then	-- data is in, no more data to retrieve
								ts_state <= TS_END_RECEIVE;
							elsif data_length = 0 then	-- data_length is ZERO, obviously ...
								ts_state <= TS_END_RECEIVE;
							elsif data_length > LENGTH_ENDPOINT0_BUFFER then -- this is impossible, so ...
								ts_state <= TS_ERROR;
							else	-- still, there are more data to retrieve
								ts_state <= TS_IDLE;
								is_receive := '1';
							end if;								
						end if;
					else
						ts_state <= TS_ERROR;
					end if;	
					
				-- state is 'end receive', means finishing receiving extra data
				when IH_END_RECEIVE =>
					data_count := data_count+read_in;
					if (read_in /= LENGTH_ENDPOINT0_BUFFER) or (data_count >= data_length) then
						is_receive := '0';
						ts_state <= TS_END_RECEIVE;
					else
						ts_state <= TS_IDLE;
					end if;						   					
									
				-- state is unknown, do nothing
				when others =>
					NULL;
				end case;
				
			-- state is 'read endpoint', means retrieving data from endpoint0 buffer
			when TS_READ_ENDPOINT =>
				case handle_step is
				when 0 =>  
					-- send command: select endpoint
					a0 <= D12_COMMAND;
					data_out <= active_ep;
					wr_n_var := '0';
					handle_step := handle_step+1;
				when 1 =>
					-- send command: read endpoint
					a0 <= D12_COMMAND;
					data_out <= D12_COMMAND_RW_BUFFER;
					wr_n_var := '0';
					handle_step := handle_step+1; 
				when 2 | 3 =>					  
					-- try to retrieve the first and second data in endpoint buffer
					a0 <= D12_DATA;
					rd_n_var := '0';			   
					handle_step := handle_step+1;
				when 4 =>
					-- the second data is the buffer lenth, reserve it
					read_in := conv_integer(data_in); 
					-- if no data, just quit reading
					if read_in = 0 then
						handle_step := 7;
					else
						-- try to retrieve rest of the data
						handle_step := handle_step+1;
						a0 <= D12_DATA;
						rd_n_var := '0'; 
					end if;
				when 5 =>
					-- reserve data
					ts_data(ram_address) <= data_in;
					ram_address := ram_address+1;
					read_count := read_count+1;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -