Section B.5. Summary


B.5. Summary

This example has demonstrated how two Impulse C software processes (the producer and consumer processes in Figure B-4) can be connected via a standard, readily available serial interface device for creating an FPGA-based grid computing system. When you combine this kind of high-speed serial communication with embedded software processors and related embedded operating systems (as demonstrated in earlier chapters) you can create extremely powerful, FPGA-based grid computing platforms for relatively little cost.

Figure B-5. Transceiver VHDL source code.
 --transceiver.vhdl --This VHDL code describes the implementation of an eight-bit ImpulseC --compatible stream for use over the DS92LV16 serializer/deserializer. -- --Scott Bekker --6/24/04 library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity transceiver is   generic(data_width : natural := 8); -- Max data width: 13 due to                                       -- 16 bit serdes bus width - 3 flag bits used   port ( clk : in std_logic;       -- hardware transceiver ports        rclk : in std_logic;        din : out std_logic_vector(15 downto 0);        rout : in std_logic_vector(15 downto 0);        sync_out : out std_logic;        local_lock_active_low : in std_logic;        --producer ports        producer_os_rdy : out std_logic;        producer_wr_en : in std_logic;        producer_eos : in std_logic;        producer_data_in : in std_ulogic_vector(data_width - 1 downto 0);        --consumer ports        consumer_os_rdy : out std_logic;        consumer_rd_en : in std_logic;        consumer_eos : out std_logic;        consumer_data_out : out std_ulogic_vector(data_width - 1 downto 0)); end transceiver; architecture Behavioral of transceiver is component async_fifo IS   port ( din: IN std_logic_VECTOR(15 downto 0);        wr_en: IN std_logic;        wr_clk: IN std_logic;        rd_en: IN std_logic;        rd_clk: IN std_logic;        ainit: IN std_logic;        dout: OUT std_logic_VECTOR(15 downto 0);        full: OUT std_logic;        empty: OUT std_logic;        rd_count: OUT std_logic_VECTOR(6 downto 0)); END component; TYPE state_type is (send_sync, send_sync_240, send_flags_240,                    send_ack1, send_ack2, connected); signal present_state : state_type := send_sync; signal counter : std_logic_vector(23 downto 0); signal din_sig : std_logic_vector(15 downto 0); signal data_to_transceiver : std_logic_vector(15 downto 0); signal link_established : std_ulogic; signal rout_sig : std_logic_vector(15 downto 0); signal flag_cnt : std_logic_vector(7 downto 0); signal fifo_out_sig : std_logic_vector(15 downto 0); signal wr_en_sig : std_logic; signal rd_en_sig : std_logic; signal empty_sig : std_logic; signal rd_count_sig : std_logic_vector(6 downto 0); signal remote_fifo_too_full : std_logic; signal local_fifo_too_full : std_logic; signal producer_data_in_sig : std_logic_vector(data_width - 1 downto 0); signal consumer_data_out_sig : std_ulogic_vector(data_width - 1 downto 0); begin  async_fifo0: async_fifo   port map( din => rout_sig,         wr_en => wr_en_sig,         wr_clk => rclk,         rd_en => rd_en_sig,         rd_clk => clk,         ainit => '0',--reset_sig,         dout => fifo_out_sig,         full => open,         empty => empty_sig,         rd_count => rd_count_sig); --state machine process to perform handshaking and establish a serial connection process(clk) begin   if rising_edge(clk) then --allow producer to write if remote fifo is not too --full and link is established producer_os_rdy <= (not remote_fifo_too_full) and link_established;                           --rdy signal must be synchronous to clk case present_state is when send_sync =>    --send sync pattern until local transceiver                           --has been locked for a period of time   sync_out <= '1';   link_established <= '0';   flag_cnt <= X"00";   if local_lock_active_low = '0' then       counter <= counter + 1;       if counter > X"200000" then   --26 ms at 80 MHz (delay for switch bounce)           counter <= X"000000";           present_state <= send_sync_240;        else           present_state <= send_sync;        end if;      else         present_state <= send_sync;         counter <= X"000000";      end if; when send_sync_240 =>  --send sync pattern until a valid flag                        --pattern is received or until timeout occurs   sync_out <= '1';   link_established <= '0';   if local_lock_active_low = '0' then       if counter > X"000FFF" then           counter <= X"000000";           present_state <= send_flags_240;       else           counter <= counter + 1;           if (rout = X"00BB") or (rout = X"00CC")                 or (rout = X"00DD") then                         --remote transceiver is in send_xxxx_160 or send_ackx               flag_cnt <= flag_cnt + 1;               if flag_cnt > X"F0" then                   counter <= X"000000";                   flag_cnt <= X"00";                   present_state <= send_ack1;               end if;            else          flag_cnt <= X"00";          present_state <= send_sync_240;        end if;      end if;   else     present_state <= send_sync;   end if; when send_flags_240 =>  --send flag pattern until a valid flag pattern                         --is received or until timeout occurs   sync_out <= '0';   din_sig <= X"00BB";   link_established <= '0';   if local_lock_active_low = '0' then      if counter > X"000FFF" then          counter <= X"000000";          present_state <= send_sync_240;      else         counter <= counter + 1;         if (rout = X"00BB") or (rout = X"00CC")               or (rout = X"00DD") then  --remote transceiver is in                                         --send_xxxx_240 or send_ackx           flag_cnt <= flag_cnt + 1;           if flag_cnt > X"F0" then             counter <= X"000000";             flag_cnt <= X"00";             present_state <= send_ack1;           end if;        else          flag_cnt <= X"00";          present_state <= send_flags_240;        end if;      end if;   else     present_state <= send_sync;   end if; when send_ack1 =>   --wait here for remote transceiver to reach this state                     --or the next state   sync_out <= '0';   link_established <= '0';   din_sig <= X"00CC";   if local_lock_active_low = '0' then      if (rout_sig = X"00CC") or (rout_sig = X"00DD") then          --remote transceiver is in send_ack1 or send_ack2       flag_cnt <= flag_cnt + 1;       if flag_cnt > X"F0" then           counter <= X"000000";           present_state <= send_ack2;         end if;      else        flag_cnt <= X"00";        present_state <= send_ack1;      end if;   else     present_state <= send_sync;   end if; when send_ack2 => --when this state is reached both transceivers are                   --locked, send flags for a period then go to connected state   sync_out <= '0';   link_established <= '0';   din_sig <= X"00DD";   counter <= counter + 1;   if local_lock_active_low = '0' then      if counter > X"0000FFF" then          present_state <= connected;        else          if rout_sig = X"00DD" then             flag_cnt <= flag_cnt + 1;             if flag_cnt > X"F0" or counter > X"0000FFF" then                 present_state <= connected;               end if;            else              flag_cnt <= X"00";              present_state <= send_ack2;            end if;          end if;       else          present_state <= send_sync;       end if; when connected =>   --both transceivers are connected, assert                     --link_established signal and allow data transmission   sync_out <= '0';   din_sig <= data_to_transceiver;   link_established <= '1';   if local_lock_active_low = '0' then          present_state <= connected;       else          counter <= X"000000";          present_state <= send_sync;         end if;      when others =>        present_state <= send_sync;      end case; end if; end process; --retrieve remote fifo too full signal off of transceiver output when link is established with link_established select   remote_fifo_too_full <= rout_sig(15) when '1',                 '1' when others; --retrieve end of stream signal off of transceiver output when link is established, --consumer enables read, and data is valid with std_logic_vector'(link_established, consumer_rd_en, fifo_out_sig(14)) select    consumer_eos <= fifo_out_sig(13) when "111",           '0' when others;  --retrieve data from fifo and output to the consumer consumer_data_out <= consumer_data_out_sig; with std_logic_vector'(link_established, consumer_rd_en, fifo_out_sig(14)) select   consumer_data_out_sig <= std_ulogic_vector(fifo_out_sig(data_width - 1 downto 0))                when "111",                consumer_data_out_sig when others; --if there is data in the fifo, allow consumer to read it consumer_os_rdy <= not empty_sig; --send flags and data to the transceiver for sending data_to_transceiver(15 downto 13) <= local_fifo_too_full & producer_wr_en & producer_eos; data_to_transceiver(data_width - 1 downto 0) <= producer_data_in_sig; --latch data from producer when producer write enable is asserted with producer_wr_en select   producer_data_in_sig <= std_logic_vector(producer_data_in) when '1',                producer_data_in_sig when others; --assert fifo write enable when link is established and write flag is set with std_logic_vector'(link_established, rout_sig(14)) select   wr_en_sig <= '1' when "11",             '0' when others; --assert fifo read enable when consumer asserts read enable or when fifo data --is not valid rd_en_sig <= consumer_rd_en or not fifo_out_sig(14); --latch data from DS92LV16 on rising edge of rclk when locked onto serial data stream process(rclk) begin if rising_edge(rclk) then     if local_lock_active_low = '0' then         rout_sig <= rout;     end if; end if; end process; --update transceiver input data on falling edge of the clock -- hardware transceiver reads input on rising clock edge so data must be -- stable during rising edge process(clk) begin if falling_edge(clk) then     din <= din_sig; end if; end process; --set local_fifo_too_full_sig based on rd_count_sig flag is -- set if fifo contains more than 64 items and cleared if fifo -- contains fewer than 31 items process(clk) begin if rising_edge(clk) then     if rd_count_sig > "1000000" and rd_count_sig < "1111111" then --fifo occasionally                                                                   --reports a count of                                                                   --127 when it is empty        local_fifo_too_full <= '1';     elsif rd_count_sig < "0011111" then        local_fifo_too_full <= '0';     else        local_fifo_too_full <= local_fifo_too_full;     end if; end if; end process; end Behavioral; 



    Practical FPGA Programming in C
    Practical FPGA Programming in C
    ISBN: 0131543180
    EAN: 2147483647
    Year: 2005
    Pages: 208

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net