---------------------------------------------------------------------------------- -- Company: -- Engineer: KIEGAING EMMANUEL/GAMOM Roland CHristian -- -- Create Date: 03:47:50 04/24/2011 -- Design Name: -- Module Name: INPUT_PORT_MODULE - Behavioral -- Project Name: -- Target Devices: -- Tool versions: -- Description: -- Module de gestion des entrées des ports du switch crossbar -- il supose qu'une donnée est empilée à chaque cycle d'horloge -- Dependencies: -- FIFO_64_FWFT.vhd -- RAM_64.vhd -- Revision: 1 -- remplacement du fifo ordinaire par un fifo fwft -- Revision 1.01 - File Created -- Additional Comments: -- modifié le 14/05/20011 pour eviter une écriture multiple dans le FIFO de sortie -- si le FIFO d'entrée vient a se vider pendant le transfert d'un packet -- le machine a état on été re modeliser et sont maintenant du type FSMD -- remodéliation pour plus de vitesse --inclusion du signal priority rotation pour eviter la perte du grant pendant une transmission --02-08-2012 :Prise en compte du signal Port_Granted dans un process ---------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; --use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; USE ieee.numeric_std.ALL; use work.Coretypes.all; ---- Uncomment the following library declaration if instantiating ---- any Xilinx primitives in this code. --library UNISIM; --use UNISIM.VComponents.all; entity INPUT_PORT_MODULE is generic(number_of_ports : positive := 4; adr_mask : natural := 0;--le nombre de'1' en partant le la gauche de l'adresse adr_len: positive:=10; --la taille en bit de l'adresse 10 bits --> 1024 hotes tot_ports: positive :=8; --Nomnre de ports total du réseau adr_sub_net : std_logic_vector(9 downto 0) := (others=>'0');--l'adresse du sous-réseau Port_num: natural:=1; -- port_num est l'id du port nbyte : positive:=2); -- le nombre de Byte dans chaque mot du port par défaut 2 Port ( data_in : in STD_LOGIC_VECTOR (Word-1 downto 0); data_in_en : in STD_LOGIC; -- signaler la présence des données en entrée cmd_in_en :in STD_LOGIC; --permet d'identifier les données qui sont dans le tampon reset : in STD_LOGIC; clk : in STD_LOGIC; request : out STD_LOGIC_VECTOR (number_of_ports downto 1); --demande de canal de transmission grant : in STD_LOGIC_VECTOR (number_of_ports downto 1); -- autorisation de transmission fifo_full : out STD_LOGIC; -- signaler que les données ne peuvent plus être acceptées en entrée fifo_empty : out STD_LOGIC; -- le tampon d'entrée est vide priority_rotation : out std_logic; -- reserver le canal de transmission data_out : out STD_LOGIC_VECTOR (7 downto 0); --données vers le réseau crossbar data_out_pulse : out std_logic); -- permet de ... end INPUT_PORT_MODULE; architecture Behavioral of INPUT_PORT_MODULE is -- declaration du fifo 64 octet utilisé pour chaque port component FIFO_256_FWFT port ( clk: IN std_logic; din: IN std_logic_VECTOR(Word-1 downto 0); rd_en: IN std_logic; srst: IN std_logic; wr_en: IN std_logic; dout: OUT std_logic_VECTOR(Word-1 downto 0); empty: OUT std_logic; full: OUT std_logic); end component; --definition du type etat pour les fsm type fsm_states is (state0, CmdOn, WaitGrant, ReqPort,addhead,addheadn, state1,state1n, state2,state2n,strecover,stpulse,stpulsen,stateErr, state3);-- definition du type etat pour le codage des etats des fsm type fsm_states2 is(cmdstart,cmdwait,cmdread,cmdSetDest,cmdSetCount,cmdSetId,cmdSetDestn,cmdSetCountn,cmdSetIdn,cmdpulse,cmdpulsen,CmdEnd); signal pop_state : fsm_states; signal cmdstate : fsm_states2; signal cmd_exec : std_logic:='0'; --indique que le port est en train d'exécuter une commande signal dat_exec :std_logic:='0'; -- indique le port est en train de transférer des données signal dat_Err :std_logic:='0'; -- signal une erreur pendant l'exécution signal wrok,readOk,CmdReadOk : std_logic:='0'; --indique s'il est possible de lire les données -- signal rt_err : std_logic;--erreur sur la route signal route :std_logic_vector(9 downto 0); signal dest_port:std_logic_vector(Word/2-1 downto 0); signal nib,cnib:natural range 0 to 4:=1;--indique le sous-octet à traiter signal pulseOn :std_logic:='0';--indique que le prochain état est celui de l'impulsion -- signaux utilisés dans les fsm signal request_decoder,req_grant : STD_LOGIC_VECTOR(number_of_ports downto 1); signal request_decoder_en : std_logic; signal request_latch : STD_LOGIC_VECTOR(4 downto 1):=(others=>'0'); -- pourquoi pas 3 downto 0 ? signal request_latch_en : std_logic; signal pipeline_latch : std_logic_vector(7 downto 0); signal pipeline_latch_en : std_logic; signal request_word : std_logic_vector(5 downto 1); signal port_granted : std_logic; signal rd_en_signal : std_logic; --signaux utilisés dans la MAE de gestion des commandes signal cmd_request_latch_en :std_logic; signal cmd_pipeline_latch_en :std_logic; signal cmd_fifo_read_signal :std_logic; signal cmd_request_decoder_en :std_logic; signal cmd_data_out_pulse :std_logic; signal cmd_priority_rotation :std_logic; --signaux utilisés dans la MAE de transfert des données signal dat_request_latch_en :std_logic; signal dat_pipeline_latch_en :std_logic; signal dat_fifo_read_signal :std_logic; signal dat_request_decoder_en :std_logic; signal dat_data_out_pulse :std_logic; signal dat_priority_rotation :std_logic; -- signaux utilisés pour les connections entre composants signal clk_signal : std_logic; signal reset_signal : std_logic; signal fifo_empty_signal : std_logic; signal fifo_read_signal : std_logic; signal fifo_out_signal,fifo_out2,cmd_data_signal : std_logic_vector(Word-1 downto 0); signal push_dout : std_logic_vector(7 downto 0); signal empty_latch : std_logic ; -- signaux du compteur de données signal data_counter : std_logic_vector(Word-1 downto 0); function count_bits(param:natural) return natural is variable p : natural range 0 to 127:=0; begin n1: for i in 0 to 127 loop if param<=2**i then p:=i; exit n1; end if; end loop n1; return p; end function; function Get_Port_ID(adr_sub_net:std_logic_vector;adr_mask:natural;n_ports:positive;numport:positive) return std_logic_vector is --cette fonction permet de calculer le port_id ou l'adresse de sous réseau en fonction du masque variable tport_id:std_logic_vector(adr_len-1 downto 0):=(others=>'0'); -- variable p : natural range 0 to 9:=0; begin --n1: for i in 0 to 9 loop -- if n_ports-1<2**i then -- p:=i; -- exit n1; -- end if; -- end loop n1; p:=count_bits(n_ports-1); tport_id:=adr_sub_net(adr_len-1 downto p) & std_logic_vector(to_unsigned(numport-1,p)); return tport_id; end function; --case n_ports is --when 1|2|3 =>tport_id(adr_len-1 downto adr_len-adr_mask-1):=adr_sub_net(adr_len-1 downto adr_len-adr_mask-1); --tport_id(adr_len-adr_mask-2 downto adr_len-adr_mask-2):= std_logic_vector(to_unsigned(numport,1)); --when 4|5 =>tport_id(adr_len-1 downto adr_len-adr_mask-1):=adr_sub_net(adr_len-1 downto adr_len-adr_mask-1); --tport_id(adr_len-adr_mask-2 downto adr_len-adr_mask-3):= std_logic_vector(to_unsigned(numport,2)); --when 6|9 =>tport_id(adr_len-1 downto adr_len-adr_mask-1):=adr_sub_net(adr_len-1 downto adr_len-adr_mask-1); --tport_id(adr_len-adr_mask-2 downto adr_len-adr_mask-4):= std_logic_vector(to_unsigned(numport,3)); -- --when others => --10 to 16 --tport_id(adr_len-1 downto adr_len-adr_mask-1):=adr_sub_net(adr_len-1 downto adr_len-adr_mask-1) ; --tport_id(adr_len-adr_mask-2 downto adr_len-adr_mask-5):= std_logic_vector(to_unsigned(numport,4)); -- --end case; -- return tport_id; --end function; signal PORT_ID :std_logic_vector(adr_len-1 downto 0):=GET_PORT_ID(adr_sub_net,adr_mask,number_of_ports,port_num); constant n_ports_bits:natural:=count_bits(number_of_ports-1);--compte le nombre de bit par port constant pid_bits:natural:=count_bits(tot_ports); --donne le nombre de bits utiles dans une adresse begin -- instantiation du FIFO_256 INPUT_PORT_FIFO : FIFO_256_FWFT port map ( clk => clk_signal, din => data_in, rd_en => fifo_read_signal, srst => reset_signal, wr_en => data_in_en, dout => fifo_out_signal, empty => fifo_empty_signal, full => fifo_full); -- connections avec les ports de l'entité data_out <= pipeline_latch ;--when cmd_exec='0' else cmd_data_signal; fifo_empty <= empty_latch; reset_signal <= reset; grant_proc:process(req_grant) begin --if rising_edge(clk) then -- if unsigned(grant)> 0 then if unsigned(req_grant) > 0 then port_granted <= '1'; --il faut veiller à ce que ce port soit vraiment autorisé else Port_granted<='0'; --ceci présuppose que la valeur qu'il reçoit est forcément la sienne end if; --end if; end process; rd_en_signal <= not(fifo_empty_signal);--not(empty_latch) ; request <= request_decoder; reg_grant:process (request_decoder,grant) begin req_grant<=request_decoder and grant; end process reg_grant; request_word <= request_latch & request_decoder_en; clk_signal <= clk; WITH cmd_exec SELECT request_latch_en <= dat_request_latch_en WHEN '0', cmd_request_latch_en WHEN others; WITH cmd_exec SELECT pipeline_latch_en <= dat_pipeline_latch_en WHEN '0', cmd_pipeline_latch_en WHEN others; WITH cmd_exec SELECT fifo_read_signal <=dat_fifo_read_signal WHEN '0', cmd_fifo_read_signal WHEN others; WITH cmd_exec SELECT request_decoder_en <=dat_request_decoder_en WHEN '0', cmd_request_decoder_en WHEN others; WITH cmd_exec SELECT data_out_pulse <=dat_data_out_pulse WHEN '0', cmd_data_out_pulse WHEN others; WITH cmd_exec SELECT priority_rotation<=dat_priority_rotation WHEN '0', cmd_priority_rotation WHEN others; --processus permettant de latcher le signal empty -- evite une perte de données en cas d'arret au cours d'une transmission empty_latch_process : process(clk) begin if rising_edge(clk) then if reset_signal = '1' then empty_latch <= '1'; else empty_latch <= fifo_empty_signal; end if; end if; end process; -- decodeur de requete en fonction de l'adresse destination -- le circuit genere depend du parametre generique nombre de ports -- switch 2 ports switch2x2 : if number_of_ports = 2 generate with request_word select request_decoder <="01" when "00001", "10" when "00011", "00" when others; end generate switch2x2; -- switch 3 ports switch3x3 : if number_of_ports = 3 generate with request_word select request_decoder <="001" when "00001", "010" when "00011", "100" when "00101", "000" when others; end generate switch3x3; -- switch 4 ports switch4x4 : if number_of_ports = 4 generate with request_word select request_decoder <="0001" when "00001", "0010" when "00011", "0100" when "00101", "1000" when "00111", "0000" when others; end generate switch4x4; -- switch 5 ports switch5x5 : if number_of_ports = 5 generate with request_word select request_decoder <="00001" when "00001", "00010" when "00011", "00100" when "00101", "01000" when "00111", "10000" when "01001", "00000" when others; end generate switch5x5; -- switch 6 ports switch6x6 : if number_of_ports = 6 generate with request_word select request_decoder <="000001" when "00001", "000010" when "00011", "000100" when "00101", "001000" when "00111", "010000" when "01001", "100000" when "01011", "000000" when others; end generate switch6x6; -- switch 7 ports switch7x7 : if number_of_ports = 7 generate with request_word select request_decoder <="0000001" when "00001", "0000010" when "00011", "0000100" when "00101", "0001000" when "00111", "0010000" when "01001", "0100000" when "01011", "1000000" when "01101", "0000000" when others; end generate switch7x7; -- switch 8 ports switch8x8 : if number_of_ports = 8 generate with request_word select request_decoder <="00000001" when "00001", "00000010" when "00011", "00000100" when "00101", "00001000" when "00111", "00010000" when "01001", "00100000" when "01011", "01000000" when "01101", "10000000" when "01111", "00000000" when others; end generate switch8x8; -- switch 9 ports switch9x9 : if number_of_ports = 9 generate with request_word select request_decoder <="000000001" when "00001", "000000010" when "00011", "000000100" when "00101", "000001000" when "00111", "000010000" when "01001", "000100000" when "01011", "001000000" when "01101", "010000000" when "01111", "100000000" when "10001", "000000000" when others; end generate switch9x9; -- switch 10 ports switch10x10 : if number_of_ports = 10 generate with request_word select request_decoder <="0000000001" when "00001", "0000000010" when "00011", "0000000100" when "00101", "0000001000" when "00111", "0000010000" when "01001", "0000100000" when "01011", "0001000000" when "01101", "0010000000" when "01111", "0100000000" when "10001", "1000000000" when "10011", "0000000000" when others; end generate switch10x10; -- switch 11 ports switch11x11 : if number_of_ports = 11 generate with request_word select request_decoder <="00000000001" when "00001", "00000000010" when "00011", "00000000100" when "00101", "00000001000" when "00111", "00000010000" when "01001", "00000100000" when "01011", "00001000000" when "01101", "00010000000" when "01111", "00100000000" when "10001", "01000000000" when "10011", "10000000000" when "10101", "00000000000" when others; end generate switch11x11; -- switch 12 ports switch12x12 : if number_of_ports = 12 generate with request_word select request_decoder <="000000000001" when "00001", "000000000010" when "00011", "000000000100" when "00101", "000000001000" when "00111", "000000010000" when "01001", "000000100000" when "01011", "000001000000" when "01101", "000010000000" when "01111", "000100000000" when "10001", "001000000000" when "10011", "010000000000" when "10101", "100000000000" when "10111", "000000000000" when others; end generate switch12x12; -- switch 13 ports switch13x13 : if number_of_ports = 13 generate with request_word select request_decoder <="0000000000001" when "00001", "0000000000010" when "00011", "0000000000100" when "00101", "0000000001000" when "00111", "0000000010000" when "01001", "0000000100000" when "01011", "0000001000000" when "01101", "0000010000000" when "01111", "0000100000000" when "10001", "0001000000000" when "10011", "0010000000000" when "10101", "0100000000000" when "10111", "1000000000000" when "11001", "0000000000000" when others; end generate switch13x13; -- switch 14 ports switch14x14 : if number_of_ports = 14 generate with request_word select request_decoder <="00000000000001" when "00001", "00000000000010" when "00011", "00000000000100" when "00101", "00000000001000" when "00111", "00000000010000" when "01001", "00000000100000" when "01011", "00000001000000" when "01101", "00000010000000" when "01111", "00000100000000" when "10001", "00001000000000" when "10011", "00010000000000" when "10101", "00100000000000" when "10111", "01000000000000" when "11001", "10000000000000" when "11011", "00000000000000" when others; end generate switch14x14; -- switch 15 ports switch15x15 : if number_of_ports = 15 generate with request_word select request_decoder <="000000000000001" when "00001", "000000000000010" when "00011", "000000000000100" when "00101", "000000000001000" when "00111", "000000000010000" when "01001", "000000000100000" when "01011", "000000001000000" when "01101", "000000010000000" when "01111", "000000100000000" when "10001", "000001000000000" when "10011", "000010000000000" when "10101", "000100000000000" when "10111", "001000000000000" when "11001", "010000000000000" when "11011", "100000000000000" when "11101", "000000000000000" when others; end generate switch15x15; -- switch 16 ports switch16x16 : if number_of_ports = 16 generate with request_word select request_decoder <="0000000000000001" when "00001", "0000000000000010" when "00011", "0000000000000100" when "00101", "0000000000001000" when "00111", "0000000000010000" when "01001", "0000000000100000" when "01011", "0000000001000000" when "01101", "0000000010000000" when "01111", "0000000100000000" when "10001", "0000001000000000" when "10011", "0000010000000000" when "10101", "0000100000000000" when "10111", "0001000000000000" when "11001", "0010000000000000" when "11011", "0100000000000000" when "11101", "1000000000000000" when "11111", "0000000000000000" when others; end generate switch16x16; --latch du fifo de sortie ?? pipeline_latch_process : process(clk) begin if rising_edge(clk) then if reset_signal = '1' then pipeline_latch <= (others => '0'); elsif pipeline_latch_en = '1' and cmd_exec='0' then pipeline_latch <= push_dout; elsif pipeline_latch_en = '1' and cmd_exec='1' then pipeline_latch <= cmd_data_signal(8*cnib-1 downto 8*(cnib-1)); end if; end if; end process; --latch qui memorise l'adresse de destination du packet request_latch_process : process(clk) variable rt:std_logic_vector(9 downto 0):=(others=>'0');--route variable reql:std_logic_vector(4 downto 1):=(others=>'0');--request_latch --variable adr_e,p:natural range 0 to 15:=0; begin if rising_edge(clk) then if reset_signal = '1' then reql := (others => '0'); elsif request_latch_en = '1' and cmd_in_en='0' then --si la lecture de la destination est autorisée rt:=(others=>'0'); if adr_mask=0 then reql(n_ports_bits downto 1):=fifo_out_signal(pid_bits-adr_mask-1 downto pid_bits-adr_mask-n_ports_bits); request_latch(n_ports_bits downto 1)<=fifo_out_signal(pid_bits-adr_mask-1 downto pid_bits-adr_mask-n_ports_bits); report "Route racine:"; else rt(pid_bits-1 downto pid_bits-adr_mask):=fifo_out_signal(pid_bits-1 downto pid_bits-adr_mask); if rt=adr_sub_net then report "Route trouvé:" & integer'image(to_integer(unsigned(rt))) & " adr_sub_net=" & integer'image(to_integer(unsigned(adr_sub_net))) & " fifo_out_sig:=" & image(fifo_out_signal) & " sur le port " & integer'image(to_integer(unsigned(port_id))+1); reql(n_ports_bits downto 1):=fifo_out_signal(pid_bits-adr_mask-1 downto pid_bits-adr_mask-n_ports_bits); request_latch(n_ports_bits downto 1)<=fifo_out_signal(pid_bits-adr_mask-1 downto pid_bits-adr_mask-n_ports_bits); else if number_of_ports=Port_num then --si c'est un paquet descendant alors le détruire report "Input_port_module n°" & integer'image(to_integer(unsigned(port_id))) & " La route sollicité n'existe pas dans ce sous réseau le paquet va être détruit ! fifo_out_sig:=" & image(fifo_out_signal); request_latch<="0000"; --à revoir il faut empêcher le routeur de se bloquer rt_err<='1'; --il faut activer la destruction du paquet else --faire monter les données vers le ports supérieur request_latch<=std_logic_vector(to_unsigned(number_of_ports-1,4)); reql:=std_logic_vector(to_unsigned(number_of_ports-1,4)); rt_err<='0'; end if; end if; end if; report "fifo_out=" & image(fifo_out_signal) & " pid_bits:=" & integer'image(pid_bits) & " adr_mask:=" & integer'image(adr_mask) & " rt:=" & image(rt) & " adr_sub_net=" & image(adr_sub_net) & " reql:=" & image(reql) & " sur le port " & integer'image(to_integer(unsigned(port_id))+1); assert (unsigned(reql) '0'); elsif cmd_exec='0' then --il ne faut pas exécuter cette MAE -- lorsque l'autre est en cours wrok<='0'; case pop_state is when state0 => if cmd_in_en='0' then --il ne faut pas exécuter les deux MAE ... if empty_latch ='0' then -- pile pas vide on doit dépiler pop_state <= WaitGrant; end if; else pop_state <= CmdOn; end if; nib<=nbyte; when CmdOn => if empty_latch='1' and cmd_in_en='0' then pop_state <= state0; elsif empty_latch='0' and cmd_in_en='1' then pop_state <= CmdOn; elsif empty_latch='1' and cmd_in_en='1' then pop_state <= state0; else -- empty_latch='0' and cmd_in_en='0' pop_state <= WaitGrant; end if; when WaitGrant => if port_granted = '1' then -- pop_state <= ReqPort; end if; when ReqPort => --if port_granted = '1' then -- pop_state <= state1; fifo_out2<=fifo_out_signal; --end if; when addhead => pop_state <= addheadn; when addheadn => pop_state <= state1; when state1 => if port_granted ='1' then --lecture de la longueur des données data_counter <= fifo_out_signal; if unsigned(fifo_out_signal)<=3 then ReadOk<='1'; else readOk<='1'; end if; pop_state <= state1n; nib<=nib-1; wrok<='1'; else wrok<='0'; end if; when state1n => if nib=1 then pop_state <= state2; nib<=nbyte; else nib<=nib-1; end if; wrok<='1'; fifo_out2<=fifo_out_signal; when state2 => if port_granted='1' then wrok<='1'; if fifo_empty_signal ='0' then if rd_en_signal ='1' and unsigned(data_counter)<= 2 then data_counter <= data_counter - 1; pop_state <= state2n; nib<=nib-1; ReadOk<='1'; pulseon<='1'; elsif rd_en_signal ='1' then data_counter <= data_counter - 1; pop_state <= state2n; nib<=nib-1; ReadOk<='1'; else --fifo_empty_signal='1' fin prématurée de la lecture ReadOk<='0'; wrok<='0'; --pop_state<=stateErr; --data_counter<=(others => '0'); end if; else pop_state<=strecover; data_counter <= data_counter + 1; report "Input_port_module : Le fifo d'entrée du port " & integer'image(to_integer(unsigned(Port_id(3 downto 0))+1)) & " est vide !!!"; wrok<='0'; readok<='0'; end if; else wrOk<='0'; readok<='0'; report "Input_port_module : Le fifo de réception du port " & integer'image(to_integer(unsigned(request_latch)+1)) & " est probablement plein !!!"; pop_state<=strecover; data_counter <= data_counter + 1; end if; when state2n => if nib=1 then if pulseon='1' then pop_state <= stpulse; else pop_state <= state2; end if; nib<=nbyte; else nib<=nib-1; end if; wrok<='1'; fifo_out2<=fifo_out_signal; when strecover => if fifo_empty_signal='0' and port_granted='1' then pop_state<=state2; readok<='0'; wrok<='0'; else readok<='0'; wrok<='0'; end if; when stpulse => if port_granted='1' then pop_state <= state3;--stpulsen; --pousser la dernière donnée dehors --nib<=nib-1; data_counter <= data_counter - 1; wrok<='1'; pulseon<='0'; else wrok<='0'; end if; when stpulsen => wrok<='0'; if nib=1 then pop_state <= state3; nib<=nbyte; else nib<=nib-1; end if; fifo_out2<=fifo_out_signal; when state3 => wrok<='0'; data_counter <= data_counter - 1; pop_state <= state0; when stateErr => wrok<='0'; data_counter <= data_counter; pop_state <= stateErr; report "Error in the NoC when sending data " ; when others => pop_state <= state0; wrok<='0'; end case; end if; end if; end process; -- actions associées à chaque etat de la fsm de mealy pop_fsm_action : process(pop_state, fifo_out_signal,fifo_out2,empty_latch, rd_en_signal,readok, port_granted,nib ) begin -- code fonctionnel case pop_state is when state0 => dat_request_latch_en <= '0'; dat_pipeline_latch_en <= '0'; dat_fifo_read_signal <='0'; dat_request_decoder_en <= '0'; dat_data_out_pulse <= '0'; dat_priority_rotation <= '1'; dat_exec<='0'; dat_Err<='0'; push_dout<=fifo_out_signal(8*nib-1 downto 8*(nib-1)); when CmdOn => dat_request_latch_en <= '0'; dat_pipeline_latch_en <= '0'; dat_fifo_read_signal <='0'; dat_request_decoder_en <= '0'; dat_data_out_pulse <= '0'; dat_priority_rotation <= '1'; dat_exec<='0'; dat_Err<='0'; push_dout<=fifo_out_signal(8*nib-1 downto 8*(nib-1)); when WaitGrant => dat_request_latch_en <='1'; --autoriser l'identification du port de destination dat_pipeline_latch_en <= '0'; --pour le transmettre à travers le réseau dat_fifo_read_signal <= '0'; dat_request_decoder_en <= '1'; --autoriser le decodeur activer le dernier bit de request dat_data_out_pulse <= '0'; --transmettre le signal pour le dernier mot dat_priority_rotation <= Port_granted; --dès qu'on a la priorité on la garde dat_exec<='1'; dat_Err<='0'; push_dout<=fifo_out_signal(8*nib-1 downto 8*(nib-1)); --push_dout<=fifo_out_signal(Word-1 downto Word/2) & PORT_ID(Word/2-1 downto 0); when ReqPort => dat_request_latch_en <='1'; --autoriser l'identification du port de destination dat_pipeline_latch_en <= '0'; --pour le transmettre à travers le réseau dat_fifo_read_signal <= '1'; dat_request_decoder_en <= '1'; --autoriser le decodeur activer le dernier bit de request dat_data_out_pulse <= '0'; --transmettre le signal pour le dernier mot dat_priority_rotation <= '0'; dat_exec<='1'; dat_Err<='0'; push_dout<=fifo_out_signal(8*nib-1 downto 8*(nib-1)); --push_dout<=fifo_out_signal(Word-1 downto Word/2) & PORT_ID(Word/2-1 downto 0); when addhead => dat_request_latch_en <='0'; --autoriser l'identification du port de destination dat_pipeline_latch_en <= '1'; --pour le transmettre à travers le réseau dat_fifo_read_signal <= '0'; dat_request_decoder_en <= '1'; --autoriser le decodeur activer le dernier bit de request dat_data_out_pulse <= '0'; --transmettre le signal pour le dernier mot dat_priority_rotation <= '0'; dat_exec<='1'; dat_Err<='0'; push_dout<=fifo_out_signal(8*nib-1 downto 8*(nib-1)); when state1 => dat_request_latch_en <= '0'; dat_pipeline_latch_en <= rd_en_signal and port_granted; dat_fifo_read_signal <= '0';--rd_en_signal and port_granted; dat_request_decoder_en <= '1'; dat_data_out_pulse <= '0';--port_granted; dat_priority_rotation <= '0'; dat_exec<='1'; dat_Err<='0'; push_dout<=fifo_out2(8*nib-1 downto 8*(nib-1)); when state1n => dat_request_latch_en <= '0'; dat_pipeline_latch_en <= '1'; -- toujours actif pour cet octet dat_fifo_read_signal <= '0'; dat_request_decoder_en <= '1'; dat_data_out_pulse <= port_granted; dat_priority_rotation <= '0'; dat_exec<='1'; dat_Err<='0'; push_dout<=fifo_out2(8*nib-1 downto 8*(nib-1)); when state2 |strecover => dat_request_latch_en <= '0'; dat_pipeline_latch_en <= port_granted and wrok and not(fifo_empty_signal); --autoriser la lecture du fifo en sortie dat_fifo_read_signal <= port_granted and readok; dat_request_decoder_en <= '1'; --autoriser le decodeur activer le dernier bit de request dat_data_out_pulse <= port_granted and wrOk ;--and not(fifo_empty_signal); dat_priority_rotation <= '0'; dat_exec<='1'; dat_Err<='0'; push_dout<=fifo_out2(8*nib-1 downto 8*(nib-1)); when state2n => dat_request_latch_en <= '0'; dat_pipeline_latch_en <= '1'; --autoriser la lecture du fifo en sortie dat_fifo_read_signal <= '0'; dat_request_decoder_en <= '1'; --autoriser le decodeur activer le dernier bit de request dat_data_out_pulse <= port_granted and wrOk ;--and not(fifo_empty_signal); dat_priority_rotation <= '0'; dat_exec<='1'; dat_Err<='0'; push_dout<=fifo_out2(8*nib-1 downto 8*(nib-1)); when stpulse|stpulsen => dat_request_latch_en <= '0'; --pousser la dernière donnée dat_pipeline_latch_en <= wrok; --autoriser la lecture du fifo en sortie dat_fifo_read_signal <='0'; dat_request_decoder_en <= '1'; --autoriser le decodeur activer le dernier bit de request dat_data_out_pulse <= '1'; -- pousser le dernier mot dat_priority_rotation <= '0'; dat_exec<='1'; dat_Err<='0'; push_dout<=fifo_out2(8*nib-1 downto 8*(nib-1)); when state3 => dat_request_latch_en <= '0'; dat_pipeline_latch_en <= '0'; dat_priority_rotation <= '1'; -- libérer la priorité dat_fifo_read_signal <= '0'; dat_request_decoder_en <= '0'; --libérer le décodeur dat_data_out_pulse <= '0'; dat_exec<='0'; dat_Err<='0'; push_dout<=fifo_out_signal(8*nib-1 downto 8*(nib-1)); when stateErr => dat_request_latch_en <= '0'; dat_pipeline_latch_en <= '0'; dat_priority_rotation <= '1'; -- libérer la priorité dat_fifo_read_signal <= '0'; dat_request_decoder_en <= '0'; --libérer le décodeur dat_data_out_pulse <= '0'; dat_exec<='1'; dat_Err<='1'; push_dout<=fifo_out_signal(8*nib-1 downto 8*(nib-1)); when others => dat_request_latch_en <= '0'; dat_pipeline_latch_en <= '0'; dat_priority_rotation <= '1'; dat_fifo_read_signal <= '0'; dat_request_decoder_en <= '0'; dat_data_out_pulse <= '0'; dat_exec<='0'; dat_Err<='0'; push_dout<=fifo_out_signal(8*nib-1 downto 8*(nib-1)); end case; end process; -- traitement des commandes reçues par le switch fsm_cmd:process(clk) variable timeout : natural:=0; variable cmdcode : natural range 0 to 255; begin if rising_edge(clk) then if reset_signal = '1' then cmdstate<=cmdstart; else -- il ne faut pas traiter les cmdes et les données en même temps case cmdstate is when cmdstart => if cmd_in_en='1' and dat_exec='0' and empty_latch='0' then cmdstate<=cmdread; end if; cmdReadOk<='0'; cnib<=nbyte; when cmdwait => if port_granted='1' then -- demande du port de sortie cmdstate<=cmdsetdest; elsif cmd_in_en='1' then cmdstate<=cmdwait; else cmdstate<=cmdstart; end if; cmdReadOk<='0'; when cmdread => -- if port_granted ='1'then -- ne pas modifier l'état des priorités si on ne l'avait pas cmdcode:= to_integer(unsigned(fifo_out_signal)); if cmdcode=1 then --code de getportid cmdstate<=cmdwait; cmdReadOk<='1'; else --ne pas prendre le code inconnu en compte cmdstate<=cmdend; -- la commande n'a pas été reconnu cmdReadOk<='0'; end if; -- end if; when cmdsetdest => if port_granted='1' then cmdstate<=cmdsetdestn; cnib<=cnib-1; end if; cmdReadOk<='0'; when cmdsetdestn => if cnib=1 then cmdstate<=cmdsetcount; cnib<=nbyte; else cnib<=cnib-1; end if; when cmdsetcount => if port_granted='1' then cmdstate<=cmdsetcountn; cnib<=cnib-1; else cmdstate<=cmdsetcount; end if; cmdReadOk<='0'; when cmdsetcountn => if cnib=1 then cmdstate<=cmdsetID; cnib<=nbyte; else cnib<=cnib-1; end if; when cmdsetID=> if port_granted='1' then cmdstate <=cmdsetIDn; cnib<=cnib-1; end if; cmdReadOk<='0'; when cmdsetIDn => if cnib=1 then cmdstate<=cmdpulse; cnib<=nbyte; else cnib<=cnib-1; end if; when cmdpulse => if port_granted='1' then cmdstate <=cmdpulsen; cnib<=cnib-1; end if; cmdReadOk<='0'; when cmdpulsen => if cnib=1 then cmdstate<=cmdEnd; cnib<=nbyte; else cnib<=cnib-1; end if; when cmdend => if cmd_in_en='0' then --éviter l'exécution en boucle cmdstate<=cmdstart; end if; cmdReadOk<='0'; end case; end if; end if; end process fsm_cmd; cmdaffect:process (cmdstate,fifo_empty_signal, port_granted, PORT_ID) begin case cmdstate is when cmdstart => cmd_exec<='0'; cmd_pipeline_latch_en <='0'; cmd_priority_rotation <= '1'; cmd_request_latch_en<='0'; cmd_fifo_read_signal <= '0'; cmd_request_decoder_en <= '0'; cmd_data_signal<=(others=>'0'); cmd_data_out_pulse <= '0'; when cmdread => cmd_exec<='1'; cmd_pipeline_latch_en <= '0'; cmd_fifo_read_signal <= '1'; -- vider le tampon d'entrée cmd_request_latch_en<='1'; --mémoriser l'adresse de destination cmd_request_decoder_en <= '1'; --demande d'émission cmd_data_out_pulse <= '0'; cmd_priority_rotation <= '1'; --sans priorité cmd_data_signal<=std_logic_vector(to_unsigned(tot_ports,Word-adr_len)) & Port_ID; when cmdwait => cmd_exec<='1'; cmd_pipeline_latch_en <='0'; cmd_fifo_read_signal <= '0'; cmd_request_latch_en<='1'; cmd_priority_rotation <= '0'; --avec priorité cmd_request_decoder_en <= '1'; --demande d'émission cmd_data_signal<=std_logic_vector(to_unsigned(tot_ports,Word-adr_len)) & Port_ID; cmd_data_out_pulse <= '0'; when cmdsetdest => --cmd_request_decoder_en <= '1'; cmd_exec<='1'; cmd_pipeline_latch_en <='1'; --empiler dans le tampon de sortie la donnée cmd_fifo_read_signal <='0'; cmd_request_latch_en<='0'; cmd_request_decoder_en <= '1'; --autoriser le decodeur à activer le dernier bit de request cmd_data_out_pulse <= '0'; cmd_priority_rotation <= '0'; cmd_data_signal<=std_logic_vector(to_unsigned(tot_ports,Word-adr_len)) & Port_ID; -- le numéro du port et le nombre total des ports est envoyé when cmdsetdestn => --cmd_request_decoder_en <= '1'; cmd_exec<='1'; cmd_pipeline_latch_en <='1'; --empiler dans le tampon de sortie la donnée cmd_fifo_read_signal <='0'; cmd_request_latch_en<='0'; cmd_request_decoder_en <= '1'; --autoriser le decodeur à activer le dernier bit de request cmd_data_out_pulse <= '1'; cmd_priority_rotation <= '0'; cmd_data_signal<=std_logic_vector(to_unsigned(tot_ports,Word-adr_len)) & Port_ID; -- le numéro du port et le nombre total des ports est envoyé when cmdsetcount|cmdsetcountn=> cmd_exec<='1'; cmd_pipeline_latch_en <='1'; -- empiler dans le tampon de sortie les données cmd_fifo_read_signal <='0'; cmd_request_latch_en<='0'; --enregistrer l'adresse de destination cmd_request_decoder_en <= '1'; --autoriser le decodeur activer le dernier bit de request cmd_data_out_pulse <= port_granted; cmd_priority_rotation <= '0'; cmd_data_signal<=STD_LOGIC_VECTOR(to_unsigned(3,Word)); when cmdSetId| cmdSetIdn=> --cmd_request_decoder_en <= '1'; cmd_exec<='1'; cmd_pipeline_latch_en <='1'; cmd_fifo_read_signal <='0'; cmd_request_latch_en<='0'; --enregistrer l'adresse de destination cmd_request_decoder_en <= '1'; --autoriser le decodeur à activer le dernier bit de request cmd_data_out_pulse <= port_granted; cmd_priority_rotation <= '0'; cmd_data_signal<=std_logic_vector(to_unsigned(tot_ports,Word-adr_len)) & Port_ID; -- le numéro du port et le nombre total des ports est envoyé when cmdpulse => cmd_exec<='1'; cmd_pipeline_latch_en <='1'; cmd_fifo_read_signal <='0'; cmd_request_latch_en<='0'; cmd_request_decoder_en <= '1'; --autoriser le decodeur activer le dernier bit de request cmd_data_out_pulse <= '1';--port_granted; --s'assurer que la dernière donnée est bien lue cmd_priority_rotation <= '0'; cmd_data_signal<=std_logic_vector(to_unsigned(tot_ports,Word-adr_len)) & Port_ID; when cmdpulsen => cmd_exec<='1'; cmd_pipeline_latch_en <='0'; cmd_fifo_read_signal <='0'; cmd_request_latch_en<='0'; cmd_request_decoder_en <= '1'; --autoriser le decodeur activer le dernier bit de request cmd_data_out_pulse <= '0';--port_granted; --s'assurer que la dernière donnée est bien lue cmd_priority_rotation <= '0'; --cmd_data_signal<=Port_ID ; cmd_data_signal<=std_logic_vector(to_unsigned(tot_ports,Word-adr_len)) & Port_ID; when cmdend => cmd_exec<='0'; cmd_request_latch_en <= '0'; cmd_pipeline_latch_en <= '0'; cmd_fifo_read_signal <= '0'; cmd_request_latch_en<='0'; cmd_request_decoder_en <= '0'; cmd_data_out_pulse <= '0'; cmd_priority_rotation <= '1'; cmd_data_signal<=(others=>'0'); end case ; end process cmdaffect; end Behavioral;