Advertisement
masa-

SPI_to_FT2232

May 26th, 2011
143
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
VHDL 8.60 KB | None | 0 0
  1. ----------------------------------------------------------------------------------
  2. -- Company:
  3. -- Engineer:        Matti Ruohonen
  4. --
  5. -- Create Date:     2011-05-26 15:12:15
  6. -- Modification Date:   2011-05-26 17:14:50
  7. -- Design Name:
  8. -- Module Name:     spi_to_ft2232 - Behavioral
  9. -- Project Name:    LUT PCU Loader: SPI to FT2232 bridge
  10. -- Target Devices:  CoolRunner (XCR3064XL-6CSG48C)
  11. -- Tool versions:
  12. -- Description:     Top level file for SPI to FT2232 communication bridge
  13. --
  14. -- Dependencies:
  15. --
  16. -- Revision:
  17. -- Revision 0.01 - File Created
  18. -- Additional Comments:
  19. --
  20. ----------------------------------------------------------------------------------
  21. library ieee;
  22. use ieee.std_logic_1164.all;
  23. -- Uncomment the following library declaration if using
  24. -- arithmetic functions with Signed or Unsigned values
  25. use ieee.numeric_std.all;
  26. use ieee.std_logic_unsigned.all;
  27. use ieee.std_logic_arith.all;
  28.  
  29. -- Uncomment the following library declaration if instantiating
  30. -- any Xilinx primitives in this code.
  31. --library UNISIM;
  32. --use UNISIM.VComponents.all;
  33.  
  34. entity spi_to_ft2232 is
  35.     port (
  36.         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)
  37.         rst_i       : in  std_logic; -- _RSTOUT from FT2232
  38.  
  39.         spi_clk_i   : in  std_logic; -- SPI SCK from F2806
  40.         spi_din_i   : in  std_logic; -- SPI MOSI from F2806
  41.         spi_ste_i   : in  std_logic; -- SPI STE from F2806
  42.         spi_dout_o  : out std_logic; -- SPI MISO to F2806
  43.  
  44.         data_a_io   : inout std_logic_vector(7 downto 0); -- FT2232 data bus A
  45.         data_b_io   : inout std_logic_vector(7 downto 0); -- FT2232 data bus B
  46.  
  47.         rd_a_o      : out std_logic; -- RD to FT2232 bus A
  48.         wr_a_o      : out std_logic; -- WR to FT2232 bus A
  49.         rxf_a_i     : in  std_logic; -- RXF from FT2232 bus A
  50.         txe_a_i     : in  std_logic; -- TXE from FT2232 bus A
  51.  
  52.         rd_b_o      : out std_logic; -- RD to FT2232 bus A
  53.         wr_b_o      : out std_logic; -- WR to FT2232 bus A
  54.         rxf_b_i     : in  std_logic; -- RXF from FT2232 bus A
  55.         txe_b_i     : in  std_logic; -- TXE from FT2232 bus A
  56.  
  57.         usb_busy_o  : out std_logic -- ??
  58.     );
  59. end spi_to_ft2232;
  60.  
  61. architecture Behavioral of spi_to_ft2232 is
  62.  
  63.     signal spi_rx       : std_logic_vector(9 downto 0);
  64.     signal spi_tx       : std_logic_vector(9 downto 0);
  65.     signal ft_tx        : std_logic_vector(7 downto 0);
  66.     signal ft_rx        : std_logic_vector(9 downto 0);
  67.     signal clk_counter  : std_logic_vector(3 downto 0);
  68.     signal tx_cnt_w     : std_logic;
  69.     signal tx_cnt_r     : std_logic;
  70.  
  71.     signal rd_a     : std_logic;
  72.     signal wr_a     : std_logic;
  73.     signal rd_b     : std_logic;
  74.     signal wr_b     : std_logic;
  75.  
  76.     signal tx_a     : std_logic;
  77.     signal tx_b     : std_logic;
  78.     signal da_a, dt_a   : std_logic;
  79.     signal da_b, dt_b   : std_logic;
  80.     signal init     : std_logic := '0';
  81.  
  82. begin
  83.  
  84.     PROCESS_SCK_R: process (spi_clk_i)
  85.     begin
  86.         if (spi_clk_i'event and spi_clk_i = '1') then -- SPI SCK rising edge
  87.             if (spi_ste_i = '0') then   -- STE active: SPI enabled
  88.                 spi_rx      <= spi_rx(8 downto 0) & spi_din_i;
  89.                 tx_a        <= '0';
  90.                 tx_b        <= '0';
  91.  
  92.                 -- 9 bits received already, this is the 10th => one frame received
  93.                 if (clk_counter = "1001") then
  94.                     -- The new value is not available yet, so we construct it manually here too
  95.                     ft_tx   <= spi_rx(6 downto 0) & spi_din_i;
  96.  
  97.                     -- NOTE: Header is in bits 8..7 since the new value is not yet available
  98.                     if (spi_rx(8 downto 7) = "01") then -- Valid header for channel A
  99.                         tx_a    <= '1';
  100.                     elsif (spi_rx(8 downto 7) = "10") then -- Valid header for channel B
  101.                         tx_b    <= '1';
  102.                     end if;
  103.  
  104. --                  spi_rx      <= (others => '0');
  105.                     clk_counter <= (others => '0');
  106.                 -- The bit counter will start counting from the valid header onwards
  107.                 -- This has the effect of re-synchronising after possible bit errors
  108.                 elsif (clk_counter = "0000") then -- Waiting for valid header
  109.                     -- Valid headers are 01 and 10 for A and B channel respectively
  110.                     if (spi_rx(1 downto 0) = "01" or spi_rx(1 downto 0) = "10") then
  111.                         -- NOTE: We have actually received 3 bits at this point,
  112.                         -- since the register gets updated after this process ends.
  113.                         clk_counter <= "0011"; -- So, set the counter to three
  114.                         -- The above is also why we check the bits 1 and 0 from the register.
  115.                         -- Or rather, we could check bit 0 and spi_din_i and set the counter to two...
  116.                     end if;
  117.                 else
  118.                     clk_counter     <= clk_counter + 1;
  119.                 end if;
  120.             end if;
  121.         end if;
  122.     end process PROCESS_SCK_R;
  123.  
  124.     PROCESS_SCK_F: process(spi_clk_i)
  125.     begin
  126.         if (spi_clk_i'event and spi_clk_i = '0') then -- Falling edge on SPI SCK
  127.             if (spi_ste_i = '1') then
  128.                 spi_tx          <= (others => '0');
  129.                 tx_cnt_w        <= '0'; --(others => '0');
  130.             else
  131. --          if (spi_ste_i = '0') then -- STE low: SPI enabled
  132.                 if (clk_counter = "0000") then
  133.                     spi_tx      <= ft_rx;
  134. --                  tx_cnt_w    <= tx_cnt_w XOR '1';
  135.                 else
  136.                     spi_tx      <= spi_tx(8 downto 0) & '0'; -- Shift transmit register
  137.                 end if;
  138.             end if;
  139.         end if;
  140.     end process PROCESS_SCK_F;
  141.  
  142.  
  143.     PROCESS_CLK: process (clk_i)
  144.     begin
  145.         if (clk_i'event and clk_i = '1') then   -- CLK rising edge
  146.             if (rst_i = '0' or init = '0') then -- Reset (from FT2232) active
  147.                 rd_a        <= '1'; -- active low
  148.                 rd_b        <= '1'; -- active low
  149.                 wr_a        <= '0';
  150.                 wr_b        <= '0';
  151.                 da_a        <= '0';
  152.                 dt_a        <= '0';
  153.                 da_b        <= '0';
  154.                 dt_b        <= '0';
  155. --              ft_rx       <= (others => '0');
  156. --              tx_cnt_r    <= (others => '0');
  157.                 init        <= '1'; -- Used to check for power-up init
  158.             else
  159.                 if (da_a = '1') then -- There is data to be transmitted
  160.                     if (wr_a = '1') then -- Write signal has been high for one clock cycle
  161.                         -- Lower the write signal, which also latches the data into the FT2232
  162.                         wr_a    <= '0';
  163.                         -- tx_a already inactive, so we can reset the check_a signal too
  164.                         if (tx_a = '0') then
  165.                             da_a    <= '0'; -- Reset the 'only transmit once check' signal
  166.                             dt_a    <= '0'; -- Reset the 'data transmitted' signal
  167.                         end if;
  168.                     -- Transmission allowed for channel A and data not already transmitted
  169.                     elsif (txe_a_i = '0' and dt_a = '0') then
  170.                         wr_a    <= '1'; -- Activate channel A WR signal
  171.                         dt_a    <= '1'; -- Mark the data as transmitted
  172.                     elsif (tx_a = '0' and dt_a = '1') then -- tx_a inactive and data has been transmitted
  173.                         da_a    <= '0'; -- Reset the 'only transmit once check' signal
  174.                         dt_a    <= '0'; -- Reset the 'data transmitted' signal
  175.                     end if;
  176.                 elsif (tx_a = '1') then -- Latch the 'data available' status to a private signal
  177.                     da_a    <= '1';
  178.                 elsif (da_b = '1') then -- There is data to be transmitted
  179.                     if (wr_b = '1') then -- Write signal has been high for one clock cycle
  180.                         -- Lower the write signal, which also latches the data into the FT2232
  181.                         wr_b    <= '0';
  182.                         -- tx_a already inactive, so we can reset the check_a signal too
  183.                         if (tx_b = '0') then
  184.                             da_b    <= '0'; -- Reset the 'only transmit once check' signal
  185.                             dt_b    <= '0'; -- Reset the 'data transmitted' signal
  186.                         end if;
  187.                     -- Transmission allowed for channel A and data not already transmitted
  188.                     elsif (txe_b_i = '0' and dt_b = '0') then
  189.                         wr_b    <= '1'; -- Activate channel A WR signal
  190.                         dt_b    <= '1'; -- Mark the data as transmitted
  191.                     elsif (tx_b = '0' and dt_b = '1') then -- tx_a inactive and data has been transmitted
  192.                         da_b    <= '0'; -- Reset the 'only transmit once check' signal
  193.                         dt_b    <= '0'; -- Reset the 'data transmitted' signal
  194.                     end if;
  195.                 elsif (tx_b = '1') then -- Latch the 'data available' status to a private signal
  196.                     da_b    <= '1';
  197.                 end if;
  198.  
  199.                 -- No Tx going on, check for received data
  200.                 if (da_a = '0' and da_b = '0') then
  201.                     if (tx_cnt_w /= tx_cnt_r) then -- Old data transmitted
  202.                         -- Received data for channel A in FT2232 buffer
  203.                         if (rxf_a_i = '0') then
  204.                             if (rd_a = '0') then -- RD signal already active
  205.                                 ft_rx   <= "01" & data_a_io; -- Read channel A data byte and add header
  206.                                 rd_a    <= '1'; -- Disable RD signal
  207.                             else
  208.                                 rd_a    <= '0'; -- Activate RD signal
  209.                             end if;
  210.                         -- Received data for channel B in FT2232 buffer and no Tx going on
  211.                         elsif (rxf_b_i = '0') then
  212.                             if (rd_b = '0') then -- RD signal already active
  213.                                 ft_rx   <= "10" & data_b_io; -- Read channel B data byte and add header
  214.                                 rd_b    <= '1'; -- Disable RD signal
  215.                             else
  216.                                 rd_b    <= '0'; -- Activate RD signal
  217.                             end if;
  218.                         end if;
  219.                         tx_cnt_r    <= tx_cnt_w;
  220.                     end if;
  221.                 end if;
  222.             end if;
  223.         end if;
  224.     end process PROCESS_CLK;
  225.  
  226.     data_a_io   <= ft_tx when (wr_a = '1') else (others => 'Z');
  227.     data_b_io   <= ft_tx when (wr_b = '1') else (others => 'Z');
  228.  
  229.     rd_a_o      <= rd_a;
  230.     wr_a_o      <= wr_a;
  231.     rd_b_o      <= rd_b;
  232.     wr_b_o      <= wr_b;
  233.     spi_dout_o  <= spi_tx(9);
  234.  
  235. end Behavioral;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement