Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ----------------------------------------------------------------------------------
- -- Company:
- -- Engineer: Matti Ruohonen
- --
- -- Create Date: 2011-05-26 15:12:15
- -- Modification Date: 2011-05-26 17:14:50
- -- Design Name:
- -- Module Name: spi_to_ft2232 - Behavioral
- -- Project Name: LUT PCU Loader: SPI to FT2232 bridge
- -- Target Devices: CoolRunner (XCR3064XL-6CSG48C)
- -- Tool versions:
- -- Description: Top level file for SPI to FT2232 communication bridge
- --
- -- Dependencies:
- --
- -- Revision:
- -- Revision 0.01 - File Created
- -- Additional Comments:
- --
- ----------------------------------------------------------------------------------
- library ieee;
- use ieee.std_logic_1164.all;
- -- Uncomment the following library declaration if using
- -- arithmetic functions with Signed or Unsigned values
- use ieee.numeric_std.all;
- use ieee.std_logic_unsigned.all;
- use ieee.std_logic_arith.all;
- -- Uncomment the following library declaration if instantiating
- -- any Xilinx primitives in this code.
- --library UNISIM;
- --use UNISIM.VComponents.all;
- entity spi_to_ft2232 is
- port (
- clk_i : in std_logic; -- 6 MHz clock input from FT2232 XTOUT NOTE: only runs when the FT2232 is connected to USB bus (has power)
- rst_i : in std_logic; -- _RSTOUT from FT2232
- spi_clk_i : in std_logic; -- SPI SCK from F2806
- spi_din_i : in std_logic; -- SPI MOSI from F2806
- spi_ste_i : in std_logic; -- SPI STE from F2806
- spi_dout_o : out std_logic; -- SPI MISO to F2806
- data_a_io : inout std_logic_vector(7 downto 0); -- FT2232 data bus A
- data_b_io : inout std_logic_vector(7 downto 0); -- FT2232 data bus B
- rd_a_o : out std_logic; -- RD to FT2232 bus A
- wr_a_o : out std_logic; -- WR to FT2232 bus A
- rxf_a_i : in std_logic; -- RXF from FT2232 bus A
- txe_a_i : in std_logic; -- TXE from FT2232 bus A
- rd_b_o : out std_logic; -- RD to FT2232 bus A
- wr_b_o : out std_logic; -- WR to FT2232 bus A
- rxf_b_i : in std_logic; -- RXF from FT2232 bus A
- txe_b_i : in std_logic; -- TXE from FT2232 bus A
- usb_busy_o : out std_logic -- ??
- );
- end spi_to_ft2232;
- architecture Behavioral of spi_to_ft2232 is
- signal spi_rx : std_logic_vector(9 downto 0);
- signal spi_tx : std_logic_vector(9 downto 0);
- signal ft_tx : std_logic_vector(7 downto 0);
- signal ft_rx : std_logic_vector(9 downto 0);
- signal clk_counter : std_logic_vector(3 downto 0);
- signal tx_cnt_w : std_logic;
- signal tx_cnt_r : std_logic;
- signal rd_a : std_logic;
- signal wr_a : std_logic;
- signal rd_b : std_logic;
- signal wr_b : std_logic;
- signal tx_a : std_logic;
- signal tx_b : std_logic;
- signal da_a, dt_a : std_logic;
- signal da_b, dt_b : std_logic;
- signal init : std_logic := '0';
- begin
- PROCESS_SCK_R: process (spi_clk_i)
- begin
- if (spi_clk_i'event and spi_clk_i = '1') then -- SPI SCK rising edge
- if (spi_ste_i = '0') then -- STE active: SPI enabled
- spi_rx <= spi_rx(8 downto 0) & spi_din_i;
- tx_a <= '0';
- tx_b <= '0';
- -- 9 bits received already, this is the 10th => one frame received
- if (clk_counter = "1001") then
- -- The new value is not available yet, so we construct it manually here too
- ft_tx <= spi_rx(6 downto 0) & spi_din_i;
- -- NOTE: Header is in bits 8..7 since the new value is not yet available
- if (spi_rx(8 downto 7) = "01") then -- Valid header for channel A
- tx_a <= '1';
- elsif (spi_rx(8 downto 7) = "10") then -- Valid header for channel B
- tx_b <= '1';
- end if;
- -- spi_rx <= (others => '0');
- clk_counter <= (others => '0');
- -- The bit counter will start counting from the valid header onwards
- -- This has the effect of re-synchronising after possible bit errors
- elsif (clk_counter = "0000") then -- Waiting for valid header
- -- Valid headers are 01 and 10 for A and B channel respectively
- if (spi_rx(1 downto 0) = "01" or spi_rx(1 downto 0) = "10") then
- -- NOTE: We have actually received 3 bits at this point,
- -- since the register gets updated after this process ends.
- clk_counter <= "0011"; -- So, set the counter to three
- -- The above is also why we check the bits 1 and 0 from the register.
- -- Or rather, we could check bit 0 and spi_din_i and set the counter to two...
- end if;
- else
- clk_counter <= clk_counter + 1;
- end if;
- end if;
- end if;
- end process PROCESS_SCK_R;
- PROCESS_SCK_F: process(spi_clk_i)
- begin
- if (spi_clk_i'event and spi_clk_i = '0') then -- Falling edge on SPI SCK
- if (spi_ste_i = '1') then
- spi_tx <= (others => '0');
- tx_cnt_w <= '0'; --(others => '0');
- else
- -- if (spi_ste_i = '0') then -- STE low: SPI enabled
- if (clk_counter = "0000") then
- spi_tx <= ft_rx;
- -- tx_cnt_w <= tx_cnt_w XOR '1';
- else
- spi_tx <= spi_tx(8 downto 0) & '0'; -- Shift transmit register
- end if;
- end if;
- end if;
- end process PROCESS_SCK_F;
- PROCESS_CLK: process (clk_i)
- begin
- if (clk_i'event and clk_i = '1') then -- CLK rising edge
- if (rst_i = '0' or init = '0') then -- Reset (from FT2232) active
- rd_a <= '1'; -- active low
- rd_b <= '1'; -- active low
- wr_a <= '0';
- wr_b <= '0';
- da_a <= '0';
- dt_a <= '0';
- da_b <= '0';
- dt_b <= '0';
- -- ft_rx <= (others => '0');
- -- tx_cnt_r <= (others => '0');
- init <= '1'; -- Used to check for power-up init
- else
- if (da_a = '1') then -- There is data to be transmitted
- if (wr_a = '1') then -- Write signal has been high for one clock cycle
- -- Lower the write signal, which also latches the data into the FT2232
- wr_a <= '0';
- -- tx_a already inactive, so we can reset the check_a signal too
- if (tx_a = '0') then
- da_a <= '0'; -- Reset the 'only transmit once check' signal
- dt_a <= '0'; -- Reset the 'data transmitted' signal
- end if;
- -- Transmission allowed for channel A and data not already transmitted
- elsif (txe_a_i = '0' and dt_a = '0') then
- wr_a <= '1'; -- Activate channel A WR signal
- dt_a <= '1'; -- Mark the data as transmitted
- elsif (tx_a = '0' and dt_a = '1') then -- tx_a inactive and data has been transmitted
- da_a <= '0'; -- Reset the 'only transmit once check' signal
- dt_a <= '0'; -- Reset the 'data transmitted' signal
- end if;
- elsif (tx_a = '1') then -- Latch the 'data available' status to a private signal
- da_a <= '1';
- elsif (da_b = '1') then -- There is data to be transmitted
- if (wr_b = '1') then -- Write signal has been high for one clock cycle
- -- Lower the write signal, which also latches the data into the FT2232
- wr_b <= '0';
- -- tx_a already inactive, so we can reset the check_a signal too
- if (tx_b = '0') then
- da_b <= '0'; -- Reset the 'only transmit once check' signal
- dt_b <= '0'; -- Reset the 'data transmitted' signal
- end if;
- -- Transmission allowed for channel A and data not already transmitted
- elsif (txe_b_i = '0' and dt_b = '0') then
- wr_b <= '1'; -- Activate channel A WR signal
- dt_b <= '1'; -- Mark the data as transmitted
- elsif (tx_b = '0' and dt_b = '1') then -- tx_a inactive and data has been transmitted
- da_b <= '0'; -- Reset the 'only transmit once check' signal
- dt_b <= '0'; -- Reset the 'data transmitted' signal
- end if;
- elsif (tx_b = '1') then -- Latch the 'data available' status to a private signal
- da_b <= '1';
- end if;
- -- No Tx going on, check for received data
- if (da_a = '0' and da_b = '0') then
- if (tx_cnt_w /= tx_cnt_r) then -- Old data transmitted
- -- Received data for channel A in FT2232 buffer
- if (rxf_a_i = '0') then
- if (rd_a = '0') then -- RD signal already active
- ft_rx <= "01" & data_a_io; -- Read channel A data byte and add header
- rd_a <= '1'; -- Disable RD signal
- else
- rd_a <= '0'; -- Activate RD signal
- end if;
- -- Received data for channel B in FT2232 buffer and no Tx going on
- elsif (rxf_b_i = '0') then
- if (rd_b = '0') then -- RD signal already active
- ft_rx <= "10" & data_b_io; -- Read channel B data byte and add header
- rd_b <= '1'; -- Disable RD signal
- else
- rd_b <= '0'; -- Activate RD signal
- end if;
- end if;
- tx_cnt_r <= tx_cnt_w;
- end if;
- end if;
- end if;
- end if;
- end process PROCESS_CLK;
- data_a_io <= ft_tx when (wr_a = '1') else (others => 'Z');
- data_b_io <= ft_tx when (wr_b = '1') else (others => 'Z');
- rd_a_o <= rd_a;
- wr_a_o <= wr_a;
- rd_b_o <= rd_b;
- wr_b_o <= wr_b;
- spi_dout_o <= spi_tx(9);
- end Behavioral;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement