📄 devicetranseiver.vhd
字号:
---------------------------------------------------------------------------------------------------
--
-- 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 + -