Skip to content
Snippets Groups Projects
DialogueCPU.vhd 19.2 KiB
Newer Older
library ieee;
library work;
use ieee.std_logic_1164.all;
use work.EtatPak.all;


entity DialogueCPU is
  port (
    RD, WR, A0, CS: in std_logic;
    sortie : out std_logic;
    D : inout std_logic_vector(7 downto 0) := "ZZZZZZZZ";
    d_buf_out : in std_logic_vector(15 downto 0);
    d_buf_in : out std_logic_vector(15 downto 0);
    charge_d, latch_d : out std_logic
  ) ;
end DialogueCPU ;

architecture archDialogueCPU of DialogueCPU is

    signal EtatW, EtatR : state := L;
    signal ctrlWord : std_logic_vector(7 downto 0) ;
    alias RW_op : std_logic_vector(1 downto 0) is ctrlWord(5 downto 4);
    alias D_RW : std_logic_vector(1 downto 0) is D(5 downto 4);

    alias d_buf_inMSB : std_logic_vector(7 downto 0) is d_buf_in(15 downto 8);
    alias d_buf_inLSB : std_logic_vector(7 downto 0) is d_buf_in( 7 downto 0);

    alias d_buf_outMSB : std_logic_vector(7 downto 0) is d_buf_out(15 downto 8);
    alias d_buf_outLSB : std_logic_vector(7 downto 0) is d_buf_out( 7 downto 0);

begin
    
    --sortie <= '0' when (WR = '1') and (RD = '0') and (A0 = '0') and ((D_RW = Least) or (D_RW = Most) or (D_RW = LeastMost)) else '1';
    sortie <= '0' when (WR = '1') and (RD = '0') and ( ((A0 = '1') and ((D_RW = Least) or (D_RW = Most) or (D_RW = LeastMost))) or (A0 = '0') ) else '1';

    ReceptData : process(CS)
    begin
        if rising_edge(CS)  then
        if ((WR = '1') and (RD = '0') and (A0 = '1')) then -- Reception ctrl
            D <= "ZZZZZZZZ";
            charge_d <= '0';
            if (D_RW = Latch) then
                latch_d <= '1';
                --sortie <= '1';
            else
                RW_op <= D_RW;
                latch_d <= '0';
                --sortie <= '0';
                if D_RW = Most then
                    EtatW <= M;
                    EtatR <= M;
                else
                    EtatW <= L;
                    EtatR <= L;
                end if ;
            end if ;
            
                
        elsif((WR = '1') and (RD = '0') and (A0 = '0')) then -- reception data
            D <= "ZZZZZZZZ";
            if EtatW = L then
                d_buf_inLSB <= D;
                if (RW_op = LeastMost) then
                    EtatW <= M;
                    charge_d <= '0';
                elsif (RW_op = Least) then
                    d_buf_inMSB <= x"00";
                    charge_d <= '1';
                end if ;
            elsif EtatW = M then
                d_buf_inMSB <= D;  
                if (RW_op = LeastMost) then
                    EtatW <= L;
                    charge_d <= '1';
                elsif (RW_op = Most) then
                    charge_d <= '1';
                    d_buf_inLSB <= x"00";
                end if ;
            else
                    
            end if ;
        elsif ((WR = '0') and (RD = '1') and (A0 = '0')) then -- envoie data
        charge_d <= '0';
            if EtatR = L then
                D <= d_buf_outLSB;
                if RW_op = LeastMost then
                    EtatR <= M;
                elsif RW_op = Most then
                    latch_d <= '0';
                end if ;
            elsif EtatR = M then
                D <= d_buf_outMSB;
                if RW_op = LeastMost then
                    EtatR <= L;
                    latch_d <= '0';
                elsif RW_op = Most then
                    latch_d <= '0';
                end if ;
            end if ;

        else

        end if ;
    end if ;
    end process ; -- ReceptData
    

    

    -- Pro_Etat_W : process
    -- begin
        
    -- end process ; -- Pro_Etat_W

    -- Pro_Etat_R : process
    -- begin
        
    -- end process ; -- Pro_Etat_R

end architecture ; -- archDialogueCPU

architecture archImplantation of DialogueCPU is

    signal EtatW_q, EtatR_q : state := L;
    signal EtatW, EtatR : state;

    signal ctrlWord : std_logic_vector(7 downto 0) := x"00";
    alias RW_op : std_logic_vector(1 downto 0) is ctrlWord(5 downto 4);
    alias d_buf_outMSB : std_logic_vector(7 downto 0) is d_buf_out(15 downto 8);
    alias d_buf_outLSB : std_logic_vector(7 downto 0) is d_buf_out( 7 downto 0);

    constant inputVectWidth : integer := 46;

    COMPONENT DFFEXb 
        generic(width : integer := inputVectWidth);
        port (
            clk : in std_logic;
            Din : in std_logic_vector((width-1) downto 0) ;
            Q :  out std_logic_vector((width-1) downto 0)
        ) ;
    end COMPONENT;

    signal inputVect : std_logic_vector((inputVectWidth-1) downto 0) ;
    signal outputVect : std_logic_vector((inputVectWidth-1) downto 0)  := (OTHERS => '0');
    signal latch_d_temp : std_logic;
    signal d_buf_in_temp : std_logic_vector(15 downto 0) ;

    alias D_q  : std_logic_vector(7 downto 0) is outputVect(7 downto 0);
    alias D_RW_q : std_logic_vector(1 downto 0) is outputVect(5 downto 4) ;
    alias RD_q : std_logic is outputVect(8) ;
    alias WR_q : std_logic is outputVect(9) ;
    alias A0_q : std_logic is outputVect(10) ;
    alias d_buf_q : std_logic_vector(15 downto 0) is outputVect(26 downto 11) ;
    alias RW_op_q : std_logic_vector(1 downto 0) is outputVect(28 downto 27) ;
    alias latch_d_q : std_logic is outputVect(29);
    alias d_buf_inLSB_q : std_logic_vector(7 downto 0) is outputVect(37 downto 30) ;
    alias d_buf_inMSB_q : std_logic_vector(7 downto 0) is outputVect(45 downto 38) ;

    alias d_buf_in_tempLSB : std_logic_vector(7 downto 0) is d_buf_in_temp( 7 downto 0);
    alias d_buf_in_tempMSB : std_logic_vector(7 downto 0) is d_buf_in_temp(15 downto 8);
    -- avoid using a buffer in the declaration of the entity
    latch_d <= latch_d_temp; 
    d_buf_in <= d_buf_in_temp;
    -- signals required to set the output signal of the entity stored in the same vector (whitout EtatW annd EtatR because there aren't std_logic)
    inputVect <= (d_buf_in_temp & latch_d_temp & RW_op & d_buf_out & A0 & WR & RD & D) ;
    bascule_D_CS : DFFEXb
        PORT MAP(CS, inputVect, outputVect);
    -- dedicated DFF to store EtatR and EtatW
    DFF_Etats_W_R : process( CS )
    begin
        if rising_edge(CS)  then
            EtatW_q <= EtatW;
            EtatR_q <= EtatR;
        end if ;
    end process ; -- DFF_Etats_W_R



    -- output functions
        -- '0' force the output of the timer to 0, '1' allow the counter to modify the output of the timer
    Sortie <= '0' when ((WR_q='1') and (RD_q='0') and (
              ((A0_q = '1') and not(D_RW_q=Latch))                                   --Receive controle word without counter latch command
            or ((A0_q = '0') and (CS = '1'))                                          --Load data in the counter
            ))
    else '1';
        -- '0' = false, '1' = true
    charge_d <= '1' when ((CS = '1') and (WR_q='1') and (RD_q='0') and (A0_q = '0') and ( -- test if instruction is a load of counter
               ((EtatW_q = L) and  (RW_op_q = Least))                     -- if instruction load only lsb bytes
            or ((EtatW_q = M) and ((RW_op_q = Most) or (RW_op_q = LeastMost))) -- if instruction load only msb bytes or all bytes (and reading MSB bytes)
            ))
            else '0';

    latch_d_temp <= '1' 
             when  ((WR_q='1') and (RD_q='0') and (A0_q = '1') and (D_RW_q=Latch))          -- if instruction is writing a control world
    else '0' when (((WR_q='0') and (RD_q='1') and (A0_q = '0') and (                         -- test if instruction is a read of counter
                            ((EtatW_q = L) and  (RW_op_q = Least))                          -- if instruction readonly lsb bytes
                        or  ((EtatW_q = M) and ((RW_op_q = Most) or (RW_op_q = LeastMost))) -- if instruction readonly msb bytes or all bytes (and reading MSB bytes)
                        )) 
                or ((WR_q='1') and (RD_q='0') and (A0_q = '1') and (not(D_RW_q=Latch)))          -- if instruction is writing a control world without latch as RW command
                )
    else latch_d_q; -- keep the previous value of latch 

      
    RW_op <= D_RW_q when  ((WR_q='1') and (RD_q='0') and (A0_q = '1') and (not(D_RW_q=Latch))) -- if instruction is writing a control world without latch as RW command
                else RW_op_q; -- keep the previous value of RW_op

    d_buf_in_tempLSB <= D_q when ((WR_q='1') and (RD_q='0') and (A0_q = '0') and (EtatW_q = L))                          -- transfer of the LSB from D to d_buf_in(7 downto 0)
        else "00000000" when ((WR_q='1') and (RD_q='0') and (A0_q = '0') and (EtatW_q = M) and (RW_op_q = Most))    -- if we only load the MSB force x"00" to d_buf_in(7 downto 0)
        else d_buf_inLSB_q;    -- keep the previous value of the variable

    d_buf_in_tempMSB <= D_q when ((WR_q='1') and (RD_q='0') and (A0_q = '0') and (EtatW_q = M))                          -- transfer of the MSB from D to d_buf_in(15 downto 8)
        else "00000000" when ((WR_q='1') and (RD_q='0') and (A0_q = '0') and (EtatW_q = L) and (RW_op_q = Least))    -- if we only load the MSB force x"00" to d_buf_in(15 downto 8)
        else d_buf_inMSB_q;    -- keep the previous value of the variable 
    -- the CPU maintain (WR='0') and (RD='1') to keep value of dbuf_out on D if the CPU prepare an other instruction dialogue CPU set D as HiZ so the CPU can write on it
    D <= d_buf_outLSB when ((CS = '1') and (WR_q='0') and (RD_q='1') and (A0_q = '0') and (EtatW_q = L)) -- transfer of the LSB from d_buf_out( 7 downto 0) to D 
        else d_buf_outMSB when ((CS = '1') and (WR_q='0') and (RD_q='1') and (A0_q = '0') and (EtatW_q = M) and (WR='0') and (RD='1')) -- transfer of the MSB from d_buf_out(15 downto 8) to D
        else "ZZZZZZZZ";    -- other instruction does not impact the bus

    EtatW <= M when (((WR_q='1') and (RD_q='0') and (A0_q = '0') and (EtatW_q = L) and (RW_op_q = LeastMost))       -- if loading in leastMost mode and EtatW_q = L
                  or ((WR_q='1') and (RD_q='0') and (A0_q = '1') and (D_RW_q = Most)))   -- if writing control word D_RW and mode is leastMost or Least
        
        else L when (((WR_q='1') and (RD_q='0') and (A0_q = '0') and (EtatW_q = M) and (RW_op_q = LeastMost))       -- if loading in leastMost mode and EtatW_q = M
                or ((WR_q='1') and (RD_q='0') and (A0_q = '1') and ((D_RW_q = LeastMost) or (D_RW_q = Least))))                                -- if writing control word D_RW and mode is Most
                
        else EtatW_q; -- keep previous value

    EtatR <= M when (((WR_q='0') and (RD_q='1') and (A0_q = '0') and (EtatW_q = L) and (RW_op_q = LeastMost))       -- if reading in leastMost mode and EtatW_q = L
                or ((WR_q='1') and (RD_q='0') and (A0_q = '1') and (D_RW_q = Most)))   -- if writing control word D_RW and mode is leastMost or Least

        else L when (((WR_q='0') and (RD_q='1') and (A0_q = '0') and (EtatW_q = M) and (RW_op_q = LeastMost))       -- if reading in leastMost mode and EtatW_q = M
            or ((WR_q='1') and (RD_q='0') and (A0_q = '1') and ((D_RW_q = LeastMost) or (D_RW_q = Least))))                                -- if writing control word D_RW and mode is Most
            
        else EtatR_q; -- keep previous value

end archImplantation ; -- archImplantation


architecture archFSM of DialogueCPU is

    type stateFSM is(
        CS1,
        CS0
    );
    signal state_c : stateFSM := CS0;
    signal state_f : stateFSM := CS0;

    signal EtatW_q, EtatR_q : state := L;
    signal EtatW, EtatR : state;

    signal ctrlWord : std_logic_vector(7 downto 0) := x"00";
    alias RW_op : std_logic_vector(1 downto 0) is ctrlWord(5 downto 4);
    alias D_RW : std_logic_vector(1 downto 0) is D(5 downto 4);

    alias d_buf_outMSB : std_logic_vector(7 downto 0) is d_buf_out(15 downto 8);
    alias d_buf_outLSB : std_logic_vector(7 downto 0) is d_buf_out( 7 downto 0);

    constant inputVectWidth : integer := 46;

    COMPONENT DFFEXb 
        generic(width : integer := inputVectWidth);
        port (
            clk : in std_logic;
            Din : in std_logic_vector((width-1) downto 0) ;
            Q :  out std_logic_vector((width-1) downto 0)
        ) ;
    end COMPONENT;

    signal inputVect : std_logic_vector((inputVectWidth-1) downto 0) ;
    signal outputVect : std_logic_vector((inputVectWidth-1) downto 0)  := (OTHERS => '0');
    signal latch_d_temp : std_logic;
    signal d_buf_in_temp : std_logic_vector(15 downto 0) ;

    alias D_q  : std_logic_vector(7 downto 0) is outputVect(7 downto 0);
    alias D_RW_q : std_logic_vector(1 downto 0) is outputVect(5 downto 4) ;
    alias RD_q : std_logic is outputVect(8) ;
    alias WR_q : std_logic is outputVect(9) ;
    alias A0_q : std_logic is outputVect(10) ;
    alias d_buf_q : std_logic_vector(15 downto 0) is outputVect(26 downto 11) ;
    alias RW_op_q : std_logic_vector(1 downto 0) is outputVect(28 downto 27) ;
    alias latch_d_q : std_logic is outputVect(29);
    alias d_buf_inLSB_q : std_logic_vector(7 downto 0) is outputVect(37 downto 30) ;
    alias d_buf_inMSB_q : std_logic_vector(7 downto 0) is outputVect(45 downto 38) ;

    alias d_buf_in_tempLSB : std_logic_vector(7 downto 0) is d_buf_in_temp( 7 downto 0);
    alias d_buf_in_tempMSB : std_logic_vector(7 downto 0) is d_buf_in_temp(15 downto 8);

begin
    -- avoid using a buffer in the declaration of the entity
    latch_d <= latch_d_q;
    d_buf_in <= (d_buf_inMSB_q & d_buf_inLSB_q);
    -- signals required to set the output signal of the entity stored in the same vector (whitout EtatW annd EtatR because there aren't std_logic)
    inputVect <= (d_buf_in_temp & latch_d_temp & RW_op & d_buf_out & A0 & WR & RD & D) ;

    bascule_D_CS : DFFEXb
        PORT MAP(clk, inputVect, outputVect);

    -- dedicated DFF to store EtatR and EtatW
    DFF_Etats_W_R : process( clk,  state_c, CS)
        if rising_edge(clk) and (state_c = CS1) and (CS = '0') then
            EtatW_q <= EtatW;
            EtatR_q <= EtatR;
        end if ;
    end process ; -- DFF_Etats_W_R

    state_f <= CS1 when CS='1'
            else CS0;
    
    StateReg : process(clk)
    begin
        if rising_edge(clk) then
            state_c <= state_f;
        end if;
    end process;

    -- output functions
        -- '0' force the output of the timer to 0, '1' allow the counter to modify the output of the timer
    Sortie <= '0' when ((CS='1') and (WR='1') and (RD='0') and (
              ((A0 = '1') and not(D_RW=Latch))                                   --Receive controle word without counter latch command
            or ((A0 = '0'))                                          --Load data in the counter
            ))
    else '1';
        -- '0' = false, '1' = true
    charge_d <= '1' when ((state_c=CS1) and (WR='1') and (RD='0') and (A0 = '0') and ( -- test if instruction is a load of counter
               ((EtatW_q = L) and  (RW_op_q = Least))                     -- if instruction load only lsb bytes
            or ((EtatW_q = M) and ((RW_op_q = Most) or (RW_op_q = LeastMost))) -- if instruction load only msb bytes or all bytes (and reading MSB bytes)
            ))
            else '0';

-- gérer la remise à 0 de latch_d_temps

             when  ((CS='1') and(WR='1') and (RD='0') and (A0 = '1') and (D_RW=Latch))          -- if instruction is writing a control world
    else '0' when ((CS='1') and (((WR='0') and (RD='1') and (A0 = '0') and (                         -- test if instruction is a read of counter
                            ((EtatR_q = L) and  (RW_op_q = Least))                          -- if instruction readonly lsb bytes
                        or  ((EtatR_q = M) and ((RW_op_q = Most) or (RW_op_q = LeastMost))) -- if instruction readonly msb bytes or all bytes (and reading MSB bytes)
                        )) 
                or ((WR='1') and (RD='0') and (A0 = '1') and (not(D_RW=Latch)))          -- if instruction is writing a control world without latch as RW command
                ))
    else latch_d_q; -- keep the previous value of latch 

      
    
    RW_op <= D_RW_q when  ((CS='1') and (WR='1') and (RD='0') and (A0 = '1') and (not(D_RW=Latch))) -- if instruction is writing a control world without latch as RW command
    d_buf_in_tempLSB <= D when ((CS='1') and (WR='1') and (RD='0') and (A0 = '0') and (EtatW_q = L))                          -- transfer of the LSB from D to d_buf_in(7 downto 0)
        else "00000000" when ((CS='1') and (WR='1') and (RD='0') and (A0 = '0') and (EtatW_q = M) and (RW_op_q = Most))    -- if we only load the MSB force x"00" to d_buf_in(7 downto 0)
        else d_buf_inLSB_q;    -- keep the previous value of the variable

    d_buf_in_tempMSB <= D when ((CS='1') and (WR='1') and (RD='0') and (A0 = '0') and (EtatW_q = M))                          -- transfer of the MSB from D to d_buf_in(15 downto 8)
        else "00000000" when ((CS='1') and (WR='1') and (RD='0') and (A0 = '0') and (EtatW_q = L) and (RW_op_q = Least))    -- if we only load the MSB force x"00" to d_buf_in(15 downto 8)
        else d_buf_inMSB_q;    -- keep the previous value of the variable 

    -- the CPU maintain (WR='0') and (RD='1') to keep value of dbuf_out on D if the CPU prepare an other instruction dialogue CPU set D as HiZ so the CPU can write on it
    D <= d_buf_outLSB when ((state_c=CS1) and (WR='0') and (RD='1') and (A0 = '0') and (EtatR_q = L)) -- transfer of the LSB from d_buf_out( 7 downto 0) to D 
        else d_buf_outMSB when ((state_c=CS1) and (WR='0') and (RD='1') and (A0 = '0') and (EtatR_q = M)) -- transfer of the MSB from d_buf_out(15 downto 8) to D
        else "ZZZZZZZZ";    -- other instruction does not impact the bus

    -- rd_q ? yes so they are only update when state_c = CS1 and CS = 0 (at the end of the instruction) only input use as a condition and change in the same instruction
    -- Pay attention to not update too early and Msb are modified wheras only LSB should have been 
    EtatW <= M when((state_c=CS1)  and (((WR_q='1') and (RD_q='0') and (A0_q = '0') and (EtatW_q = L) and (RW_op_q = LeastMost))       -- if loading in leastMost mode and EtatW_q = L
                  or ((WR_q='1') and (RD_q='0') and (A0_q = '1') and (D_RW_q = Most))))   -- if writing control word D_RW and mode is leastMost or Least
        else L when ((state_c=CS1) and (((WR_q='1') and (RD_q='0') and (A0_q = '0') and (EtatW_q = M) and (RW_op_q = LeastMost))       -- if loading in leastMost mode and EtatW_q = M
                or ((WR_q='1') and (RD_q='0') and (A0_q = '1') and ((D_RW_q = LeastMost) or (D_RW_q = Least)))))                                -- if writing control word D_RW and mode is Most
    EtatR <= M when ((state_c=CS1) and (((WR_q='0') and (RD_q='1') and (A0_q = '0') and (EtatR_q = L) and (RW_op_q = LeastMost))       -- if reading in leastMost mode and EtatW_q = L
                or ((WR_q='1') and (RD_q='0') and (A0_q = '1') and (D_RW_q = Most))))   -- if writing control word D_RW and mode is leastMost or Least
        else L when ((state_c=CS1) and (((WR_q='0') and (RD_q='1') and (A0_q = '0') and (EtatR_q = M) and (RW_op_q = LeastMost))       -- if reading in leastMost mode and EtatW_q = M
            or ((WR_q='1') and (RD_q='0') and (A0_q = '1') and ((D_RW_q = LeastMost) or (D_RW_q = Least)))))                               -- if writing control word D_RW and mode is Most
            
        else EtatR_q; -- keep previous value

end archFSM ; -- archImplantation