---------------------------------------------------------------------------------- -- Company: -- Engineer: GAMOM -- -- Create Date: 14:44:36 03/07/2012 -- Design Name: -- Module Name: EX4_FSM - Behavioral -- Project Name: MPI_CORE_COMPONENTS -- Target Devices: SPARTAN 3E xc3s1200e -- Tool versions: -- Description: Ce module renferme les fonctions permettant d'initialiser la -- bibliothèque matériel MPI -- Dependencies: -- -- Revision: 25/juin/2012 au 24/Octobre/2012 -- Revision 0.03 - File updated -- 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; Library NocLib; use NoCLib.CoreTypes.all; use work.packet_type.all; -- Uncomment the following library declaration if instantiating -- any Xilinx primitives in this code. --library UNISIM; --use UNISIM.VComponents.all; entity EX4_FSM is Port ( Instruction : in STD_LOGIC_VECTOR (Word-1 downto 0); Instruction_En : in STD_LOGIC; clk : in STD_LOGIC; reset : in STD_LOGIC; ResultOut : out STD_LOGIC_VECTOR (Word-1 downto 0):=(others=>'0'); Result_En : out STD_LOGIC:='0'; NocSize : out STD_LOGIC_VECTOR(3 downto 0); PortId : out STD_LOGIC_VECTOR(3 downto 0):=(others=>'0'); AppRank : out STD_LOGIC_VECTOR(3 downto 0):=(others=>'0'); AppSize : out STD_LOGIC_VECTOR(3 downto 0):=(others=>'0'); IsMain : out STD_LOGIC:='0'; Initialized : out STD_LOGIC:='0'; dma_wr_req : out std_logic:='0'; dma_wr_grant : in std_logic; AdrRam : out STD_LOGIC_VECTOR (ADRLEN-1 downto 0):=(others=>'0'); --accès au stockage WeRam : out STD_LOGIC:='0'; --activation de l'écriture en RAM DataRam : out STD_LOGIC_VECTOR (Word-1 downto 0):=(others=>'Z');--données des ports AppAck : in STD_LOGIC; AppReq : in STD_LOGIC; port_in_cmd_en : out STD_LOGIC:='0'; port_in_wr_en : out STD_LOGIC:='0'; port_in_empty : in STD_LOGIC; port_in_full : in STD_LOGIC; port_in_data : out STD_LOGIC_VECTOR (Word-1 downto 0):=(others=>'Z'); port_out_data : in STD_LOGIC_VECTOR (Word-1 downto 0); port_out_rd_en : out STD_LOGIC:='0'; port_out_data_available : in STD_LOGIC); end EX4_FSM; architecture Behavioral of EX4_FSM is Type Ar_MPIPort_In is array (positive range <>) of Typ_MPIPort_in; Type Ar_MPIPort_out is array (positive range <>) of Typ_MPIPort_out; --MAE pour emission de init --type init1_type is (init,NocSize,InitToNoc,NextPort,EndBCast); -- MAE pour affectation des rangs aux différentes librairies MPI type init2_type is (init,GetPortNum,DecodeData,IsPortZero,SeekMain1,SeekMain2,StoreMain,SetMainFlag,GetMainReq,StoreRank,NewRank,SendRank,RegRank,SendApp,EndInit); -- MAE pour réception de init depuis le réseau; type init3_type is (init,GetNocSize,ReadInitHead,StorePort,EndInit); type typ_send is (s_init,s_head,s_len,s_len2,s_data,s_end); type typ_receiv is (r_wait,r_dlen,r_drop,r_glen,r_data,r_pulse,r_end); type typ_cmd is (cmdstart,cmdpost,cmdpostidle,cmdread,cmdlen,cmdglen,cmddata,cmdend,cmdtimeout); signal etsnd : typ_send; signal etrec:typ_receiv; --pour la machine à état de réception signal etcmd :typ_cmd; --pour la machine à état de commande -- signal stInit1, next_stInit1 : init1_type; signal stInit2, next_stInit2 : init2_type; --signal stInit3, next_stInit3 : init3_type; --signaux pour l'interface avec les ports signal cport_in_wr_en,sport_in_wr_en:std_logic; signal cport_out_rd_en,rport_out_rd_en:std_logic; signal tosend,tosend4 :std_logic_vector(Word-1 downto 0); signal selector : std_logic_vector (2 downto 0); -- pour le MUX des signaux vers le port --signaux pour les états des MAE signal NocSizeOk,PortCountFlag : std_logic; signal PortNumFlag,EquFlag,MainResp,RankAsked,RankSent:std_logic; signal RTS_cmd,RTS_dat,CTR,BCast,Send_Ack,DS_Ack,CM_Ack:std_logic:='0'; signal Rcv_On,Snd_On,Cmd_On : std_logic:='0'; --status des MAE d'envoie et de réception signal DS_RDY ,BCast_Rdy,Send_RDY,CM_RDY:std_logic:='0'; signal ExecTime_out:std_logic; --signaux de gestion de la RAM signal Ram_NextAdress : std_logic_vector(ADRLEN-1 downto 0):=std_logic_vector(to_unsigned(Core_BASE_ADR+CORE_Rank2port_BASE,16)); signal Ram_NExtAdress_i :std_logic_vector(ADRLEN-1 downto 0):=std_logic_vector(to_unsigned(Core_BASE_ADR+CORE_Rank2port_BASE,16)); --Signaux des résultats et de l'état signal PortNum_i,MyPort : std_logic_vector(3 downto 0); -- signal NocMax : std_logic_vector(3 downto 0); -- Nombre de ports du réseau -1 ? signal MyRank : std_logic_vector(3 downto 0) ; --rang du PE signal MainPort : std_logic_vector(3 downto 0) ; --Port de la lib main signal NextRank : std_logic_vector(3 downto 0):=(others=>'0'); --utiliser pour gérer les affectations de rangs MPI signal DataToSend : Typ_PortIo(0 to 3):=((others=>'0'),(others=>'0'),(others=>'0'),(others=>'0')); -- permet d'empiler les données à envoyer signal CmdReceived,DataReceived : Typ_PortIO(0 to 3):=((others=>'0'),(others=>'0'),(others=>'0'),(others=>'0')); signal Datalen : natural range 0 to 3 :=0; --indique la longueur des données --other outputs signal RankAsked_i,EquFlag_i,MainResp_i,RankSent_i,IsMain_i,Result_i:std_logic; --signal BCast_Rdy_i : std_logic; signal cdlen,dcount,timeout,timeout_i : natural range 0 to 255:=0; --longueur du paquet reçu par le process pcmd begin --======================================================================================= --fonctions du module --======================================================================================= --======================================================================================= -- Gestion de l'initialisation du Core MPI sync_Init2 : process (clk,reset) begin if reset='1' then stinit2<=init; elsif rising_edge(clk) then stinit2<=next_stinit2; --ajout des autres affectations ici Ram_NextAdress<=Ram_NextAdress_i ; MyPort<=PortNum_i; RankAsked<=RankAsked_i; RankSent<=RankSent_i; AppRank<=MyRank; timeout<=timeout_i; end if; end process; Init2_DECODE: process (stinit2, CmdReceived, EquFlag, MyPort, DS_RDY, MainResp, DataReceived, Ram_NextAdress) variable nextr,nextadr : natural :=to_integer(unsigned(Ram_NextAdress)); begin Case stInit2 is When Init => RTS_cmd<='0'; RTS_dat<='0'; BCast<='0'; Result_En<='0'; Initialized<='0'; CM_Ack <='0'; CTR<='0' ; DS_ACK<='0'; Send_Ack<='0'; WeRam<='0'; ResultOut<=(others=>'0'); PortNum_i<=(others=>'Z'); IsMain<='0'; EquFlag<='0'; RankAsked_i<='0'; dma_wr_req<='0'; When GetPortNum => RTS_cmd<='1'; RTS_dat<='0'; Result_En<='0'; Initialized<='0'; BCast<='0'; --réalise un envoie non collectif CM_Ack<='0'; -- les données sont maintenant attendues CTR<='0' ; DataToSend(0)<=X"0" & GETPORTID; DS_ACK<='0'; Send_Ack<='0'; WeRam<='0'; IsMain<='0'; ResultOut<=(others=>'0'); PortNum_i<=(others=>'Z'); RankAsked_i<='0'; dma_wr_req<='0'; When DecodeData => EquFlag<=(All_zeros(Cmdreceived(2)(3 downto 0))); RTS_cmd<='0'; RTS_dat<='0'; BCast<='0'; IsMain<='0'; Result_En<='0'; Initialized<='0'; CM_Ack <='1'; --les données ont été reçues PortNum_i<=Cmdreceived(2)(3 downto 0); --récupère les valeurs de port NocMax<=Cmdreceived(2)(7 downto 4); -- et la taille du réseau PortNumFlag<='1'; -- le numéro du port est maintenant connu CTR<='0' ; DS_ACK<='0'; Send_Ack<='0'; WeRam<='0'; RankAsked_i<='0'; ResultOut<=(others=>'0'); dma_wr_req<='0'; When IsPortZero => --Ce port est-il le n° 0 du NoC ? BCast<='0'; Result_En<='0'; Initialized<='0'; RTS_cmd<='0'; RTS_dat<='0'; NextRank<="0001"; -- le prochain rang à affecter sera le n° 1 nextr:=1; IsMain<=EquFlag; MyRank<="0000"; MainPort<="0000"; --MainAdr<="0000"; -- le port 0 est le main Lib par défaut; CTR<='0' ; DS_ACK<='0'; WeRam<='0'; RankAsked_i<='0'; ResultOut<=(others=>'0'); dma_wr_req<='0'; When SeekMain1 => -- recherche de la lib main RTS_cmd<='0'; RTS_DAT<='1'; CTR<='1' ; -- prêt à recevoir les données Clear To Receive DS_ACK<='0'; --les données sont attendus Send_Ack<=BCast_rdy; DataToSend(0)<=INIT_SEEKMAIN & MyPort ; DataToSend(1)<="00000011"; -- la longueur du packet =3 DataToSend(2)<="0000" & MyPort; --propose sa propre adresse DataLen<=3; BCast<='1'; IsMain<='0'; Result_En<='0'; Initialized<='0'; WeRam<='0'; ResultOut<=(others=>'0'); EquFlag<='0'; RankAsked_i<='0'; dma_wr_req<='0'; When SeekMain2 => -- recherche de la lib main RTS_cmd<='0'; RTS_DAT<='0'; CTR<='1' ; -- prêt à recevoir les données Clear To Receive DS_ACK<='0'; --les données sont attendus Send_Ack<=BCast_rdy; -- DataToSend(0)<=INIT_SEEKMAIN & MyPort ; -- DataToSend(1)<="00000011"; -- la longueur du packet =3 -- DataToSend(2)<="0000" & MyPort; --propose sa propre adresse -- DataLen<=3; BCast<='0'; IsMain<='0'; Result_En<='0'; Initialized<='0'; WeRam<='0'; ResultOut<=(others=>'0'); EquFlag<='0'; RankAsked_i<='0'; dma_wr_req<='0'; When StoreMain => -- la Main Lib est une autre BCAST<='0'; Result_En<='0'; IsMain<='0'; Initialized<='0'; DS_ACK<=DS_RDY; Send_Ack<='0'; RTS_cmd<='0'; RTS_DAT<='0'; CTR<=not(MainResp); -- essayer de recevoir tant que le main n'a pas répondu WeRam<='1'; ResultOut<=(others=>'0'); RankAsked_i<='0'; EquFlag<='0'; AdrRam<= STD_logic_vector(to_unsigned(Core_init_adr+1,16)); DataRam<=DataReceived(0)(3 downto 0)& DataReceived(2)(3 downto 0); --MainPort & MyRank dma_wr_req<= '0'; ---pas très sûr When SetMainFlag => -- Cette Lib est la Main Lib if (Datareceived(0)(7 downto 4) = INIT_SEEKMAIN) then RankAsked_i<='1'; else RankAsked_i<='0'; end if; RTS_cmd<='0'; Initialized<='0'; RTS_DAT<='0'; BCast<='0'; IsMain<='0'; Result_En<='0'; MyRank<="0000"; MainPort<="0000"; CTR<='1'; DS_ACK<='0'; WeRam<='1'; ResultOut<=(others=>'0'); EquFlag<='1'; AdrRam<= STD_logic_vector(to_unsigned(Core_init_adr+1,16)); DataRam<=(others =>'0'); -- le port vaut 0 et la mainlib est aussi à 0 dma_wr_req<='1'; When GetMainReq => RankAsked_i<='1'; WeRam<='0'; -- pas BCast<='0'; DS_ACK<='0'; IsMain<='0'; Result_En<='0'; Initialized<='0'; RTS_cmd<='0'; RTS_DAT<='0'; CTR<='1'; ResultOut<=(others=>'0'); PortNum_i<=DataReceived(0)(3 downto 0); -- le port qui demande un rang; EquFlag<='1'; dma_wr_req<='0'; When NewRank => nextr:=nextr+1; NextAdr:=NextAdr+1; --NextRank<=incr_vec(NextRank,'1'); NextRank<=STD_logic_vector(to_unsigned(nextr,4)); DataToSend(0)<=INIT_SETRANK & PortNum_i ; DataToSend(1)<="00000011"; DataToSend(2)<="0000" & NextRank; --ici c'est la valeur avant incrémentation ! DataLen<=3; BCast<='0'; DS_ACK<='0'; Result_En<='0'; Initialized<='0'; EquFlag<='1'; RTS_cmd<='0'; Rts_DAT<='1'; IsMain<='0'; CTR<='0' ; WeRam<='0'; RankAsked_i<='1'; ResultOut<=(others=>'0'); dma_wr_req<='0'; When SendRank => BCast<='0'; Result_En<='0'; EquFlag<='1'; Rts_DAT<='1'; RTS_cmd<='0'; DS_ACK<='0'; Send_Ack<=Send_Rdy; IsMain<='0'; CTR<='0' ; WeRam<='0'; ResultOut<=(others=>'0'); RankAsked_i<='1'; Initialized<='0'; dma_wr_req<='0'; When RegRank => if (Datareceived(0)(7 downto 4) = INIT_SEEKMAIN) then RankAsked_i<='1'; else RankAsked_i<='0'; end if; CTR<='0' ; Result_En<='0'; Initialized<='0'; RTS_cmd<='0'; DS_ACK<='0'; Send_Ack<='0'; IsMain<='0'; Rts_Dat<='0'; BCast<='0'; EquFlag<='1'; WeRam<='1'; Ram_NextAdress_i<= STD_logic_vector(to_unsigned(NextAdr,16)); --incr_vec(Ram_NextAdress,'1'); AdrRam<=Ram_NextAdress; -- le rang qui a été envoyé; DataRam<=DataToSend(2)(3 downto 0) & MyPort; ResultOut<=(others=>'0'); dma_wr_req<='1'; When StoreRank => --le processus qui écoute le Port et qui --stoke les adresses des autres bib va gérer le stockage du rang BCAST<='0'; DS_ACK<='1'; Send_Ack<='0'; RTS_cmd<='0'; EquFlag<='0'; RTS_DAT<='0'; CTR<='0'; Result_En<='0'; Initialized<='0'; IsMain<='0'; if ExecTime_out='1' then MainPort<="0000"; MyRank<=MyPort; else MainPort<=DataReceived(0)(3 downto 0); MyRank<=DataReceived(2)(3 downto 0); end if; WeRam<='1'; --AdrRam<=DataReceived(2); -- le rang qui a été envoyé; AdrRam<= STD_logic_vector(to_unsigned(Core_init_adr+1,16)); DataRam<=DataReceived(0)(3 downto 0)& DataReceived(2)(3 downto 0); --MainPort & MyRank ResultOut<=(others=>'0'); RankAsked_i<='0'; dma_wr_req<='1'; When SendApp => --ajouter du code pour recevoir l'adr du reg status Initialized<='1'; ResultOut<="00000001"; -- Init Ok Result_En<='1'; IsMain<='0'; PortId<=MyPort; BCAST<='0'; DS_ACK<='1'; Send_Ack<='0'; RTS_cmd<='0'; RTS_DAT<='0'; CTR<='0'; WeRam<='0'; RankAsked_i<='0'; dma_wr_req<='0'; When EndInit=> RTS_cmd<='0'; RTS_DAT<='0'; Result_En<='0'; IsMain<='0'; Initialized<='0'; DS_ACK<='0'; Send_Ack<='0'; BCAST<='0'; CTR<='0'; WeRam<='0'; RankAsked_i<='0'; ResultOut<=(others=>'0'); dma_wr_req<='0'; end case; end process; NEXT_STInit2_DECODE: process (stInit2,AppReq, AppAck,PortNumFlag,EquFlag,MainResp,RankAsked,RankSent,CM_RDY, CmdReceived, BCast_Rdy, DS_RDY, DataReceived, Send_RDY,TimeOut,Dma_wr_grant) variable InitTimeOut :natural:=0; variable nulvect : std_logic_vector(3 downto 0):="0000"; begin --declare default state for next_state to avoid latches next_stInit2 <= stInit2; --default is to stay in current state --insert statements to decode next_state --below is a simple example case (stInit2) is When Init =>If AppReq='1' then If PortNumFlag='1' and RankAsked='1' then Next_stInit2 <=GetMainReq; else Next_stInit2 <=GetPortNum; end if; TimeOut_i<=0; end if; When GetPortNum => -- récupérer le numéro du port if CM_RDY='1' then Next_stInit2 <=DecodeData; end if; When DecodeData => -- cet état permet de lire les données reçues du port --if CM_RDY='1' then if ((Cmdreceived(2)(3 downto 0) or nulvect)=nulvect) then -- teste si le n° du port est zero --EquFlag<='1'; else --EquFlag<='0'; end if; Next_stInit2 <=IsPortZero; --end if; When IsPortZero => if PortNumFlag='1' then End if; if EquFlag='0' then --tester le numéro de port obtenu Next_stInit2 <=SeekMain1; -- chercher le numéro de port sur le réseau else Next_stInit2<=SetMainFlag; -- enregistrer le numéro de port End If; TimeOut_i<=0; When SeekMain1 =>If BCast_RDY='1' then -- si tous les envois ont été postés Next_stInit2<=SeekMain2; End if; When SeekMain2 => If DS_RDY='1' then -- Si un jeu de données a été reçu Next_stInit2 <=StoreMain; -- de la librairie pricipale elsif ExecTime_Out='1' then -- le Noc ne répond pas -- affecter un numéro en raport avec le port Next_stInit2 <=StoreMain; else Timeout_i<=TimeOut+1; End if; if (Datareceived(0)(7 downto 4) = INIT_SETRANK) then MainResp<='1'; else MainResp<='0'; end if; When StoreMain => if DataReceived(0)(7 downto 4)= MPI_INIT then --ignorer le message Next_stInit2 <=StoreMain; --essayer de recevoir le rang elsif Datareceived(0)(7 downto 4) = INIT_SEEKMAIN then -- ignorer ce message Next_stInit2 <=StoreMain; --essayer de recevoir le rang elsif Datareceived(0)(7 downto 4) = INIT_SETRANK then --ok le rang a été reçu -- enregistrer le Main Adresse et les adresses des autres processus -- dans la variable prévue à cet effet --if dma_wr_grant='1' then Next_stInit2 <=StoreRank; --end if; end if; When StoreRank => --il faut prévoir du code pour s'assurer que la RAM a bien enregistrer -- la donnée ... if dma_wr_grant = '1' then Next_stInit2 <=SendApp; else Next_stInit2 <=StoreRank; end if; When SetMainFlag => if dma_wr_grant='1' then if DS_RDY='1' then Next_stInit2 <=GetMainReq; elsif Timeout=240 then Next_stInit2 <=SendApp; else TimeOut_i<=TimeOut+1; end if; -- il est envisagée de terminer le programme à ce point end if; When GetMainReq => if RankAsked='1' then Next_stInit2 <=NewRank; else Next_stInit2 <=SendApp; end if; When NewRank => Next_stInit2 <=SendRank; When SendRank => if Send_RDY='1' then --RankSent Next_stInit2 <=RegRank; RankSent_i<='1'; -- le rang a été envoyé TimeOut_i<=0; -- prépare le traitement de la prochaine requête -- d'attente des ports end if; When RegRank => --il faut prévoir du code pour s'assurer que la RAM a bien enregistrer -- la donnée ... if dma_wr_grant = '1' then if DS_RDY='1' then RankSent_i<='0'; Next_stInit2 <=GetMainReq; elsif Timeout=10 then Next_stInit2 <=SendApp; else TimeOut_i<=TimeOut+1; end if; -- il est envisagée end if; When SendApp => -- envoyer au programme un signal -- et attendre un acquittement et l'adresse de base If AppAck='1' then Next_stInit2 <=EndInit; end if; When EndInit=> Next_stInit2<=Init; end case; end process; --================================================ --sauvegarde du rang et du main port à l'adresse de retour de la fonction Init --================================================== --==================================================== --envoie des données sur le port --=================================================== selector<=(Rcv_on,Cmd_on,Snd_on); process (selector,Rport_out_rd_en,cport_out_rd_en,sPort_in_wr_en ,cPort_in_wr_en, tosend ,tosend4) begin case selector is when "000" => port_in_data<=(others=>'Z'); Port_in_wr_en<='0'; Port_out_rd_en<='0'; when "001" => port_in_data<=tosend; --envoie de données Port_in_wr_en<=sPort_in_wr_en ; Port_out_rd_en<='0'; when "101" => port_in_data<=tosend; --envoie de données Port_in_wr_en<=sPort_in_wr_en ; Port_out_rd_en<=Rport_out_rd_en ; when "010" | "110" | "011" | "111" => port_in_data<=tosend4; --envoie de commande GetPort Port_in_wr_en<=cPort_in_wr_en; Port_out_rd_en<=cport_out_rd_en; when "100" => port_in_data<=(others=>'Z'); -- réception de données Port_in_wr_en<='0'; Port_out_rd_en<=Rport_out_rd_en ; when others => port_in_data<=(others=>'Z'); Port_in_wr_en<='0'; Port_out_rd_en<='0'; end case; end process; --================================================== --=============================================================== --processus d'accès au réseau --=============================================================== preceiv:process(clk,reset) variable origport,destport : natural range 0 to 15; variable dcount,dlen ,rtimeout:natural range 0 to 255; variable ptype : std_logic_vector(3 downto 0); begin -- if rising_edge(clk) then if reset='1' then etrec<=r_wait; destport:=1; rtimeout:=0; else case etrec is when r_wait => rtimeout:=0; if Port_out_data_available='1' and CTR='1' then ptype:=port_out_data(7 downto 4); origport:=to_integer(unsigned(port_out_data(3 downto 0))); if ptype=MPI_INIT or ptype=INIT_SETRANK or ptype=INIT_SEEKMAIN then etrec<=r_dlen; --identification de la signature d'en tête valide Datareceived(0)<=Port_out_data; --stocker l'entête else --une donnée non attendue est présente sur le port etrec<=r_drop; end if; --elsif Port_out_data_available='1' and CTR='0' then -- etrec<=r_drop; else etrec<=r_wait; end if; When r_drop => -- ignorer les messages qui arrivent à ce noeud tant que --l'application n'a pas été initialisée if port_out_data_available='0' then etrec<=r_end; end if; --Rport_out_rd_en<='1'; --lire les données qui sont dans le tampon de sortie --DS_RDY<='0'; when r_Dlen => --positionnement du mot de longueur des données if Port_out_data_available ='1' then --Rport_out_rd_en<='1'; etrec<=r_glen; rtimeout:=0; else rtimeout:=rtimeout+1; if rtimeout>=30 then Exectime_out<='1'; --read Noc time out etrec<=r_end; -- données pas prêtes end if; end if; --DS_RDY<='0'; -- when r_glen => --lecture effective de la longueur des données if port_out_data_available='1' then dlen:=to_integer(unsigned(port_out_data(Word-1 downto 0))); Datareceived(1)<=Port_out_data; --RPort_out_rd_en<='0'; etrec<=r_data; dcount:=2; -- initialisation du compteur de reception (il y a -- déjà deux mots reçues else rtimeout:=rtimeout+1; if rtimeout>=30 then ExecTime_out<='1'; etrec<=r_end; -- données pas prêtes end if; end if; --DS_RDY<='0'; when r_data => -- lecture des données if port_out_data_available='1' then --Rport_out_rd_en<='1'; --autoriser la lecture DataReceived(dcount)<=Port_out_data; --récupération des données --assert true report "Donnée lue :"; --& string(unsigned(port4_out(Word-1 downto 0))) --DS_RDY<='0'; dcount:=dcount+1; --severity note; if dlen <=dcount then -- ce doit être égale ici et non <= ??? etrec<=r_end; --DS_RDY<='1'; -- jeu de données disponibles elsif dcount=255 then --dépassement de la capacité --DS_RDY<='0'; etrec<=r_end; end if; else rtimeout:=rtimeout+1; if rtimeout>=30 then ExecTime_out<='1'; etrec<=r_end; -- données pas prêtes end if; --DS_RDY<='0'; end if; when r_pulse => etrec<=r_end; when r_end => --rPort_out_rd_en <='0'; if DS_ACK='1' or rtimeout> 30 or CTR='0' then --DS_RDY<='0'; etrec<=r_wait; end if; end case; end if;--reset='1' end if; end process preceiv; val_preceiv: process (etrec) begin case etrec is when r_wait => DS_RDY<='0'; Rport_out_rd_en <='0'; when r_dlen => DS_RDY<='0'; Rport_out_rd_en <='1'; rcv_On<='1'; when r_drop => DS_RDY<='0'; Rport_out_rd_en <='1'; rcv_On<='1'; when r_glen => Rport_out_rd_en <='1'; DS_RDY<='0'; rcv_On<='1'; when r_data => Rport_out_rd_en <='1'; DS_RDY<='0'; rcv_On<='1'; when r_pulse => Rport_out_rd_en <='0'; rcv_On<='1'; DS_RDY<='1'; when r_end => Rport_out_rd_en <='0'; DS_RDY<='1'; rcv_On<='0'; when others => Rport_out_rd_en <='0'; DS_RDY<='0'; rcv_On<='0'; end case; end process; psend:process(clk,reset) --génération des paquets à partir du port courant variable pactype :natural range 0 to 15; variable destport : natural range 0 to 15:=0; variable realdlen, i,i_pair : natural range 0 to 255; variable MaxPort : natural :=to_integer(unsigned(NOCMAX)); -- en fait ne doit pas être 0 begin if rising_edge(clk) then if reset='1' then etsnd<=s_init; else -- le process s'exécute sur chaque front -- montant de l'horloge case etsnd is when s_init => tosend<=(others=>'Z'); MaxPort :=to_integer(unsigned(NOCMAX)); sPort_in_wr_en<='0'; if port_in_full='0' and Rts_dat='1' then --on peut aussi tester si le port est vide BCast_RDY<='0'; -- pas la fin de du Broadcasting Send_RDY<='0'; Snd_on<='1'; if Bcast='1' then -- envoyer à tous les ports le même message ? DestPort :=0; else DestPort:=to_integer(unsigned(DataToSend(0)(3 downto 0))); end if; etsnd<=s_head; end if; when s_head => -- construction et envoie de l'en-tête Send_RDY<='0'; --l'envoi commence BCast_RDY<='0'; Snd_on<='1'; --pactype:=to_integer(MPI_INIT);-- pactype:=to_integer(unsigned(DataToSend(0)(7 downto 4))); --realdlen:=to_integer(unsigned(Datalen)); --? destport:=MAXPORT; -- le port de destination tosend <=STD_LOGIC_VECTOR(to_unsigned(pactype,4)) & STD_LOGIC_VECTOR(to_unsigned(destport,4)); sPort_in_wr_en<='1'; -- i:=1; etsnd<=s_len2; -- passer à l'état suivant when s_len => BCast_RDY<='0'; Send_RDY<='0'; Snd_on<='1'; --tosend<=(STD_LOGIC_VECTOR(to_unsigned(Realdlen,8))); tosend<=DataToSend(1); sPort_in_wr_en <='1'; --port1_in<=tosend1; --copie directe sur le port etsnd<=s_len2; when s_len2 => --tosend<=(STD_LOGIC_VECTOR(to_unsigned(realdlen,8))); sPort_in_wr_en<='1'; tosend<=DataToSend(1); --port1_in<=tosend1; --copie directe sur le port etsnd<=s_data; BCast_RDY<='0'; Send_RDY<='0'; Snd_on<='1'; i:=i+1; when s_data => Snd_on<='1'; if Port_in_full='0'and RTS_dat='1' then sPort_in_wr_en<='1'; --envoie des données sur le port tosend<=DataToSend(i); if i+1>=datalen then etsnd<=s_end; Send_RDY<='1'; --l'envoi est terminé if BCast='1' and destport=MAXPort then BCAST_RDY<='1'; --l'envoi collectif aussi else BCast_RDY<='0'; end if; else BCast_RDY<='0'; Send_RDY<='0'; i:=i+1; end if; else sPort_in_wr_en<='0'; BCast_RDY<='0'; Send_RDY<='0'; end if; when s_end => tosend<=(others=>'Z'); Send_RDY<='1'; sPort_in_wr_en<='0'; Snd_on<='0'; if Bcast='1' then DestPort:=Destport+1; if DestPort<=MaxPort then etsnd<=s_head; else BCast_RDY<='1' ; -- BroadCast End=Ok if Send_ack='1' then etsnd<=s_init; end if; end if; else BCast_RDY<='0'; if Send_ack='1' then etsnd<=s_init; end if; end if; end case; end if; --reset ='1' end if; --rising_edge... end process psend; -- envoi des commandes pcmd:process(clk,reset) variable origport,destport,pid,mport : natural range 0 to 15; variable ctimeout:natural range 0 to 255; begin if rising_edge(clk) then if reset='1' then etcmd<=cmdstart; destport:=0; ctimeout:=0; origport:=1; -- sorigport<=origport; else case etcmd is when cmdstart => if Port_in_empty='1' and RTS_Cmd='1' then etcmd<=cmdpost; end if; when cmdpost => if Port_in_empty='1' then etcmd<=cmdread; end if; when cmdpostidle => --permet juste la prise en compte de la commande etcmd<=cmdread; dcount<=0;-- initialisation du compteur de reception when cmdread => ctimeout:=0; if Port_out_data_available='1' then mport:=to_integer(unsigned(port_out_data(7 downto 4))); pid:=to_integer(unsigned(port_out_data(3 downto 0)))+1; CmdReceived(dcount)<=port_out_data; --cdata_out_en(origport)<='1'; -- if pid=origport then --le port a été bien identifié etcmd<=cmdglen; -- dcount<=dcount+1; -- else -- etcmd<=cmdtimeout; -- end if; else etcmd<=cmdread; end if; when cmdlen => --positionnement du mot de longueur des données if Port_out_data_available='1' then etcmd<=cmdglen; ctimeout:=0; else ctimeout:=ctimeout+1; if ctimeout>=30 then etcmd<=cmdtimeout; -- données pas prêtes end if; end if; when cmdglen => --lecture effective de la longueur des données if Port_out_data_available='1' then cdlen<=to_integer(unsigned(port_out_data(Word-1 downto 0))); CmdReceived(dcount)<=port_out_data; etcmd<=cmddata; dcount<=dcount+1; else ctimeout:=ctimeout+1; if ctimeout>=30 then --time_out(destport)<='1'; etcmd<=cmdtimeout; -- données pas prêtes end if; end if; when cmddata => if (port_out_data_available='1' and ctimeout<30) then --cdata_out_en(origport)<='1'; mport:=to_integer(unsigned(port_out_data(7 downto 4))); --attention les ports sont numérotés à partir de 0 pid:=to_integer(unsigned(port_out_data(3 downto 0)))+1; CmdReceived(dcount)<=port_out_data; if (dcount>=cdlen-1 ) then--attention le compteur de données commence à 0 etcmd<=cmdend; --CM_RDY<='1'; else dcount<=dcount+1; end if; Else if ctimeout>=30 then --time_out(destport)<='1'; etcmd<=cmdtimeout; -- données pas prêtes else ctimeout:=ctimeout+1; etcmd<=cmdend; end if; end if; when cmdend => etcmd<=cmdstart; when cmdtimeout => etcmd<=cmdstart; end case; --sorigport<=origport; end if; --reset='1' end if; end process pcmd; majetcmd: process (etcmd,DataToSend, port_out_data_available, dcount,port_out_data) variable origport : natural; variable i:natural:=0; begin case etcmd is when cmdstart => i:=0; Port_in_cmd_en<='0'; tosend4<=(others=>'Z'); cport_out_rd_en<='0'; cport_in_wr_en<='0'; CM_RDY<='0'; Cmd_on<='0'; when cmdpost | cmdpostidle => cport_in_wr_en<='1'; tosend4<=DataToSend(0); ---code pour getportid Port_in_cmd_en<='1'; cport_out_rd_en<='0'; CM_RDY<='0'; Cmd_on<='1'; when cmdread => tosend4<=(others=>'Z'); cPort_in_wr_en<='0'; cport_out_rd_en<=port_out_data_available; --CmdReceived(dcount)<=port_out_data; --mettre les données dans le tampon Port_in_cmd_en<='1'; CM_RDY<='0'; Cmd_on<='1'; when cmdlen |cmdglen => --positionnement du mot de longueur des données tosend4<=(others=>'Z'); cport_in_wr_en<='0'; cport_out_rd_en<=port_out_data_available; Port_in_cmd_en<='1'; --CmdReceived(dcount)<= port_out_data; CM_RDY<='0'; Cmd_on<='1'; when cmddata => tosend4<=(others=>'Z'); cport_in_wr_en<='0'; cport_out_rd_en<=Port_out_data_available; Port_in_cmd_en<='1'; --CmdReceived(dcount)<=port_out_data; --mettre les données dans le tampon i:=i+1; CM_RDY<='0'; Cmd_on<='1'; when cmdend => tosend4<=(others=>'Z'); cport_in_wr_en<='0'; cport_out_rd_en<='0'; --CmdReceived(dcount)<=port_out_data; Port_in_cmd_en<='0'; CM_RDY<='1'; Cmd_on<='0'; when cmdtimeout => tosend4<=(others=>'Z'); cport_in_wr_en<='0'; cport_out_rd_en<='0'; Port_in_cmd_en<='0'; Cmd_on<='1'; end case; end process majetcmd ; end Behavioral;