OpenCores
URL https://opencores.org/ocsvn/spacewire_light/spacewire_light/trunk

Subversion Repositories spacewire_light

[/] [spacewire_light/] [trunk/] [rtl/] [vhdl/] [spwxmit_fast.vhd] - Diff between revs 3 and 7

Show entire file | Details | Blame | View Log

Rev 3 Rev 7
Line 36... Line 36...
--  Logic in the system clock domain accepts transmission requests through
--  Logic in the system clock domain accepts transmission requests through
--  the external interface of the entity. Pending requests are translated
--  the external interface of the entity. Pending requests are translated
--  into a stream of tokens. The tokens are pushed to the txclk domain through
--  into a stream of tokens. The tokens are pushed to the txclk domain through
--  the FIFO buffer as described above.
--  the FIFO buffer as described above.
--
--
--  The data path through the txclk domain is divided into stages A through F
--  The data path through the txclk domain is divided into stages B through F
--  in a half-hearted attempt to keep things simple. Stage A is just a
--  in a half-hearted attempt to keep things simple.
--  synchronizer for the buffer status flags from the system clock domain.
 
--
--
--  Stage B takes a token from the FIFO buffer and updates a buffer status
--  Stage B takes a token from the FIFO buffer and updates a buffer status
--  flag to indicate that the buffer slot needs to be refilled. If the FIFO
--  flag to indicate that the buffer slot needs to be refilled. If the FIFO
--  is empty, a NULL is inserted. Stage B is triggered one clock after
--  is empty, a NULL is inserted. Stage B is triggered one clock after
--  stage E switches to a new token. If the previous token was ESC, stage B
--  stage E switches to a new token. If the previous token was ESC, stage B
Line 182... Line 181...
 
 
    -- Turn off FSM extraction to avoid synchronization problems.
    -- Turn off FSM extraction to avoid synchronization problems.
    attribute FSM_EXTRACT: string;
    attribute FSM_EXTRACT: string;
    attribute FSM_EXTRACT of spwxmit_fast: entity is "NO";
    attribute FSM_EXTRACT of spwxmit_fast: entity is "NO";
 
 
    -- Turn off register duplication to avoid synchronization problems.
 
    attribute REGISTER_DUPLICATION: string;
 
    attribute REGISTER_DUPLICATION of spwxmit_fast: entity is "FALSE";
 
 
 
end entity spwxmit_fast;
end entity spwxmit_fast;
 
 
architecture spwxmit_fast_arch of spwxmit_fast is
architecture spwxmit_fast_arch of spwxmit_fast is
 
 
    -- Convert boolean to std_logic.
    -- Convert boolean to std_logic.
Line 208... Line 203...
    -- Registers in txclk domain
    -- Registers in txclk domain
    type txregs_type is record
    type txregs_type is record
        -- sync to system clock domain
        -- sync to system clock domain
        txflip0:    std_ulogic;
        txflip0:    std_ulogic;
        txflip1:    std_ulogic;
        txflip1:    std_ulogic;
        -- stage A
 
        a_sysflip0: std_logic_vector(1 downto 0);
 
        a_sysflip1: std_logic_vector(1 downto 0);
 
        -- stage B
        -- stage B
        b_update:   std_ulogic;
        b_update:   std_ulogic;
        b_mux:      std_ulogic;
        b_mux:      std_ulogic;
        b_txflip:   std_ulogic;
        b_txflip:   std_ulogic;
        b_valid:    std_ulogic;
        b_valid:    std_ulogic;
Line 243... Line 235...
        txclkcnt:   std_logic_vector(7 downto 0);
        txclkcnt:   std_logic_vector(7 downto 0);
        txclkcy:    std_logic_vector(2 downto 0);
        txclkcy:    std_logic_vector(2 downto 0);
        txclkdone:  std_logic_vector(1 downto 0);
        txclkdone:  std_logic_vector(1 downto 0);
        txclkdiv:   std_logic_vector(7 downto 0);
        txclkdiv:   std_logic_vector(7 downto 0);
        txdivnorm:  std_ulogic;
        txdivnorm:  std_ulogic;
        txdivsafe:  std_logic_vector(1 downto 0);
 
        -- tx enable logic
 
        txensync:   std_logic_vector(1 downto 0);
 
    end record;
    end record;
 
 
    -- Registers in system clock domain
    -- Registers in system clock domain
    type regs_type is record
    type regs_type is record
        -- sync status to txclk domain
        -- sync status to txclk domain
Line 262... Line 251...
        sysflip0:   std_ulogic;
        sysflip0:   std_ulogic;
        sysflip1:   std_ulogic;
        sysflip1:   std_ulogic;
        token0:     token_type;
        token0:     token_type;
        token1:     token_type;
        token1:     token_type;
        tokmux:     std_ulogic;
        tokmux:     std_ulogic;
        -- sync feedback from txclk domain
 
        txflip0:    std_logic_vector(1 downto 0);
 
        txflip1:    std_logic_vector(1 downto 0);
 
        -- transmitter management
        -- transmitter management
        pend_fct:   std_ulogic;                     -- '1' if an outgoing FCT is pending
        pend_fct:   std_ulogic;                     -- '1' if an outgoing FCT is pending
        pend_char:  std_ulogic;                     -- '1' if an outgoing N-Char is pending
        pend_char:  std_ulogic;                     -- '1' if an outgoing N-Char is pending
        pend_data:  std_logic_vector(8 downto 0);   -- control flag and data bits of pending char
        pend_data:  std_logic_vector(8 downto 0);   -- control flag and data bits of pending char
        pend_tick:  std_ulogic;                     -- '1' if an outgoing time tick is pending
        pend_tick:  std_ulogic;                     -- '1' if an outgoing time tick is pending
Line 294... Line 280...
        sysflip0    => '0',
        sysflip0    => '0',
        sysflip1    => '0',
        sysflip1    => '0',
        token0      => token_reset,
        token0      => token_reset,
        token1      => token_reset,
        token1      => token_reset,
        tokmux      => '0',
        tokmux      => '0',
        txflip0     => "00",
 
        txflip1     => "00",
 
        pend_fct    => '0',
        pend_fct    => '0',
        pend_char   => '0',
        pend_char   => '0',
        pend_data   => (others => '0'),
        pend_data   => (others => '0'),
        pend_tick   => '0',
        pend_tick   => '0',
        pend_time   => (others => '0'),
        pend_time   => (others => '0'),
        allow_fct   => '0',
        allow_fct   => '0',
        allow_char  => '0',
        allow_char  => '0',
        sent_fct    => '0' );
        sent_fct    => '0' );
 
 
 
    -- Signals that are re-synchronized from system clock to txclk domain.
 
    type synctx_type is record
 
        rstn:       std_ulogic;
 
        sysflip0:   std_ulogic;
 
        sysflip1:   std_ulogic;
 
        txen:       std_ulogic;
 
        txdivsafe:  std_ulogic;
 
    end record;
 
 
 
    -- Signals that are re-synchronized from txclk to system clock domain.
 
    type syncsys_type is record
 
        txflip0:    std_ulogic;
 
        txflip1:    std_ulogic;
 
    end record;
 
 
    -- Registers
    -- Registers
    signal rtx:     txregs_type;
    signal rtx:     txregs_type;
    signal rtxin:   txregs_type;
    signal rtxin:   txregs_type;
    signal r:       regs_type := regs_reset;
    signal r:       regs_type := regs_reset;
    signal rin:     regs_type;
    signal rin:     regs_type;
 
 
    -- Reset synchronizer for txclk domain
    -- Synchronized signals after crossing clock domains.
    signal s_tx_rst_sync: std_logic_vector(1 downto 0) := "11";
    signal synctx:  synctx_type;
    signal s_tx_reset:    std_ulogic := '1';
    signal syncsys: syncsys_type;
 
 
    -- Output flip-flops
    -- Output flip-flops
    signal s_spwdo: std_logic;
    signal s_spwdo: std_logic;
    signal s_spwso: std_logic;
    signal s_spwso: std_logic;
 
 
Line 326... Line 325...
    attribute IOB of s_spwdo: signal is "TRUE";
    attribute IOB of s_spwdo: signal is "TRUE";
    attribute IOB of s_spwso: signal is "TRUE";
    attribute IOB of s_spwso: signal is "TRUE";
 
 
begin
begin
 
 
 
    -- Reset synchronizer for txclk domain.
 
    synctx_rst: syncdff
 
        port map ( clk => txclk, rst => rst, di => '1',         do => synctx.rstn );
 
 
 
    -- Synchronize signals from system clock domain to txclk domain.
 
    synctx_sysflip0: syncdff
 
        port map ( clk => txclk, rst => rst, di => r.sysflip0,  do => synctx.sysflip0 );
 
    synctx_sysflip1: syncdff
 
        port map ( clk => txclk, rst => rst, di => r.sysflip1,  do => synctx.sysflip1 );
 
    synctx_txen: syncdff
 
        port map ( clk => txclk, rst => rst, di => r.txenreg,   do => synctx.txen );
 
    synctx_txdivsafe: syncdff
 
        port map ( clk => txclk, rst => rst, di => r.txdivsafe, do => synctx.txdivsafe );
 
 
 
    -- Synchronize signals from txclk domain to system clock domain.
 
    syncsys_txflip0: syncdff
 
        port map ( clk => clk,   rst => rst, di => rtx.txflip0, do => syncsys.txflip0 );
 
    syncsys_txflip1: syncdff
 
        port map ( clk => clk,   rst => rst, di => rtx.txflip1, do => syncsys.txflip1 );
 
 
    -- Drive SpaceWire output signals
    -- Drive SpaceWire output signals
    spw_do      <= s_spwdo;
    spw_do      <= s_spwdo;
    spw_so      <= s_spwso;
    spw_so      <= s_spwso;
 
 
    -- Combinatorial process
    -- Combinatorial process
    process (r, rtx, rst, divcnt, xmiti, s_tx_reset) is
    process (r, rtx, rst, divcnt, xmiti, synctx, syncsys) is
        variable v:         regs_type;
        variable v:         regs_type;
        variable vtx:       txregs_type;
        variable vtx:       txregs_type;
        variable v_needtoken: std_ulogic;
        variable v_needtoken: std_ulogic;
        variable v_havetoken: std_ulogic;
        variable v_havetoken: std_ulogic;
        variable v_token:     token_type;
        variable v_token:     token_type;
Line 346... Line 365...
        v_havetoken := '0';
        v_havetoken := '0';
        v_token     := token_reset;
        v_token     := token_reset;
 
 
        -- ---- FAST CLOCK DOMAIN ----
        -- ---- FAST CLOCK DOMAIN ----
 
 
        -- Stage A: Synchronize token buffer counts from system clock domain.
 
        vtx.a_sysflip0(0) := r.sysflip0;
 
        vtx.a_sysflip0(1) := rtx.a_sysflip0(0);
 
        vtx.a_sysflip1(0) := r.sysflip1;
 
        vtx.a_sysflip1(1) := rtx.a_sysflip1(0);
 
 
 
        -- Stage B: Multiplex tokens from system clock domain.
        -- Stage B: Multiplex tokens from system clock domain.
        -- Update stage B three bit periods after updating stage C
        -- Update stage B three bit periods after updating stage C
        -- (i.e. in time for the next update of stage C).
        -- (i.e. in time for the next update of stage C).
        -- Do not update stage B if stage C is indicating that it needs to
        -- Do not update stage B if stage C is indicating that it needs to
        -- send a second token to complete its task.
        -- send a second token to complete its task.
Line 366... Line 379...
            vtx.b_txflip := rtx.txflip1;
            vtx.b_txflip := rtx.txflip1;
        end if;
        end if;
        if rtx.b_update = '1' then
        if rtx.b_update = '1' then
            if rtx.b_mux = '0' then
            if rtx.b_mux = '0' then
                -- get token from slot 0
                -- get token from slot 0
                vtx.b_valid := rtx.a_sysflip0(1) xor rtx.b_txflip;
                vtx.b_valid := synctx.sysflip0 xor rtx.b_txflip;
                vtx.b_token := r.token0;
                vtx.b_token := r.token0;
                -- update mux flag if we got a valid token
                -- update mux flag if we got a valid token
                vtx.b_mux   := rtx.a_sysflip0(1) xor rtx.b_txflip;
                vtx.b_mux   := synctx.sysflip0 xor rtx.b_txflip;
                vtx.txflip0 := rtx.a_sysflip0(1);
                vtx.txflip0 := synctx.sysflip0;
                vtx.txflip1 := rtx.txflip1;
                vtx.txflip1 := rtx.txflip1;
            else
            else
                -- get token from slot 1
                -- get token from slot 1
                vtx.b_valid := rtx.a_sysflip1(1) xor rtx.b_txflip;
                vtx.b_valid := synctx.sysflip1 xor rtx.b_txflip;
                vtx.b_token := r.token1;
                vtx.b_token := r.token1;
                -- update mux flag if we got a valid token
                -- update mux flag if we got a valid token
                vtx.b_mux   := not (rtx.a_sysflip1(1) xor rtx.b_txflip);
                vtx.b_mux   := not (synctx.sysflip1 xor rtx.b_txflip);
                vtx.txflip0 := rtx.txflip0;
                vtx.txflip0 := rtx.txflip0;
                vtx.txflip1 := rtx.a_sysflip1(1);
                vtx.txflip1 := synctx.sysflip1;
            end if;
            end if;
        end if;
        end if;
 
 
        -- Stage C: Prepare to transmit EOP, EEP or a data character.
        -- Stage C: Prepare to transmit EOP, EEP or a data character.
        vtx.c_update := rtx.txclken and rtx.e_count(3);
        vtx.c_update := rtx.txclken and rtx.e_count(3);
Line 495... Line 508...
            vtx.txclkcy   := "000";
            vtx.txclkcy   := "000";
            vtx.txclkdone := "00";
            vtx.txclkdone := "00";
        end if;
        end if;
 
 
        -- Synchronize txclkdiv
        -- Synchronize txclkdiv
        vtx.txdivsafe(0) := r.txdivsafe;
        if synctx.txdivsafe = '1' then
        vtx.txdivsafe(1) := rtx.txdivsafe(0);
 
        if rtx.txdivsafe(1) = '1' then
 
            vtx.txclkdiv  := r.txdivreg;
            vtx.txclkdiv  := r.txdivreg;
            vtx.txdivnorm := r.txdivnorm;
            vtx.txdivnorm := r.txdivnorm;
        end if;
        end if;
 
 
        -- Synchronize txen signal.
 
        vtx.txensync(0) := r.txenreg;
 
        vtx.txensync(1) := rtx.txensync(0);
 
 
 
        -- Transmitter disabled.
        -- Transmitter disabled.
        if rtx.txensync(1) = '0' then
        if synctx.txen = '0' then
            vtx.txflip0   := '0';
            vtx.txflip0   := '0';
            vtx.txflip1   := '0';
            vtx.txflip1   := '0';
            vtx.b_update  := '0';
            vtx.b_update  := '0';
            vtx.b_mux     := '0';
            vtx.b_mux     := '0';
            vtx.b_valid   := '0';
            vtx.b_valid   := '0';
Line 526... Line 533...
            vtx.e_parity  := '0';
            vtx.e_parity  := '0';
            vtx.e_count   := (0 => '1', others => '0');
            vtx.e_count   := (0 => '1', others => '0');
        end if;
        end if;
 
 
        -- Reset.
        -- Reset.
        if s_tx_reset = '1' then
        if synctx.rstn = '0' then
            vtx.f_spwdo   := '0';
            vtx.f_spwdo   := '0';
            vtx.f_spwso   := '0';
            vtx.f_spwso   := '0';
            vtx.txensync  := "00";
 
            vtx.txclken   := '0';
            vtx.txclken   := '0';
            vtx.txclkpre  := '1';
            vtx.txclkpre  := '1';
            vtx.txclkcnt  := (others => '0');
            vtx.txclkcnt  := (others => '0');
            vtx.txclkdiv  := (others => '0');
            vtx.txclkdiv  := (others => '0');
            vtx.txdivnorm := '0';
            vtx.txdivnorm := '0';
Line 564... Line 570...
        -- Pass falling edge of txen signal as soon as possible.
        -- Pass falling edge of txen signal as soon as possible.
        if xmiti.txen = '0' then
        if xmiti.txen = '0' then
            v.txenreg   := '0';
            v.txenreg   := '0';
        end if;
        end if;
 
 
        -- Synchronize feedback from txclk domain.
 
        v.txflip0(0) := rtx.txflip0;
 
        v.txflip0(1) := r.txflip0(0);
 
        v.txflip1(0) := rtx.txflip1;
 
        v.txflip1(1) := r.txflip1(0);
 
 
 
        -- Store requests for FCT transmission.
        -- Store requests for FCT transmission.
        if xmiti.fct_in = '1' and r.allow_fct = '1' then
        if xmiti.fct_in = '1' and r.allow_fct = '1' then
            v.pend_fct  := '1';
            v.pend_fct  := '1';
        end if;
        end if;
 
 
Line 592... Line 592...
 
 
        else
        else
 
 
            -- Determine if a new token is needed.
            -- Determine if a new token is needed.
            if r.tokmux = '0' then
            if r.tokmux = '0' then
                if r.sysflip0 = r.txflip0(1) then
                if r.sysflip0 = syncsys.txflip0 then
                    v_needtoken := '1';
                    v_needtoken := '1';
                end if;
                end if;
            else
            else
                if r.sysflip1 = r.txflip1(1) then
                if r.sysflip1 = syncsys.txflip1 then
                    v_needtoken := '1';
                    v_needtoken := '1';
                end if;
                end if;
            end if;
            end if;
 
 
            -- Prepare new token.
            -- Prepare new token.
Line 640... Line 640...
            end if;
            end if;
 
 
            -- Put new token in slot.
            -- Put new token in slot.
            if v_havetoken = '1' then
            if v_havetoken = '1' then
                if r.tokmux = '0' then
                if r.tokmux = '0' then
                    if r.sysflip0 = r.txflip0(1) then
                    if r.sysflip0 = syncsys.txflip0 then
                        v.sysflip0  := not r.sysflip0;
                        v.sysflip0  := not r.sysflip0;
                        v.token0    := v_token;
                        v.token0    := v_token;
                        v.tokmux    := '1';
                        v.tokmux    := '1';
                    end if;
                    end if;
                else
                else
                    if r.sysflip1 = r.txflip1(1) then
                    if r.sysflip1 = syncsys.txflip1 then
                        v.sysflip1  := not r.sysflip1;
                        v.sysflip1  := not r.sysflip1;
                        v.token1    := v_token;
                        v.token1    := v_token;
                        v.tokmux    := '0';
                        v.tokmux    := '0';
                    end if;
                    end if;
                end if;
                end if;
Line 716... Line 716...
            -- update registers
            -- update registers
            r <= rin;
            r <= rin;
        end if;
        end if;
    end process;
    end process;
 
 
    -- Reset synchronizer for txclk domain
 
    process (txclk, rst) is
 
    begin
 
        if rst = '1' then
 
            s_tx_rst_sync <= "11";
 
            s_tx_reset    <= '1';
 
        elsif rising_edge(txclk) then
 
            s_tx_rst_sync <= s_tx_rst_sync(0 downto 0) & "0";
 
            s_tx_reset    <= s_tx_rst_sync(1);
 
        end if;
 
    end process;
 
 
 
end architecture spwxmit_fast_arch;
end architecture spwxmit_fast_arch;
 
 
 No newline at end of file
 No newline at end of file

powered by: WebSVN 2.1.0

© copyright 1999-2021 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.