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

Subversion Repositories spacewire_light

[/] [spacewire_light/] [trunk/] [rtl/] [vhdl/] [spwxmit.vhd] - Rev 2

Compare with Previous | Blame | View Log

--
--  SpaceWire Transmitter
--
--  This entity translates outgoing characters and tokens into
--  data-strobe signalling.
--
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.spwpkg.all;
 
entity spwxmit is
 
    port (
        -- System clock.
        clk:        in  std_logic;
 
        -- Synchronous reset (active-high).
        rst:        in  std_logic;
 
        -- Scaling factor minus 1, used to scale the system clock into the
        -- transmission bit rate. The system clock is divided by
        -- (unsigned(divcnt) + 1). Changing this signal will immediately
        -- change the transmission rate.
        divcnt:     in  std_logic_vector(7 downto 0);
 
        -- Input signals from spwlink.
        xmiti:      in  spw_xmit_in_type;
 
        -- Output signals to spwlink.
        xmito:      out spw_xmit_out_type;
 
        -- Data Out signal to SpaceWire bus.
        spw_do:     out std_logic;
 
        -- Strobe Out signal to SpaceWire bus.
        spw_so:     out std_logic
    );
 
end entity spwxmit;
 
architecture spwxmit_arch of spwxmit is
 
    -- Registers
    type regs_type is record
        -- tx clock
        txclken:    std_ulogic;         -- high if a bit must be transmitted
        txclkcnt:   unsigned(7 downto 0);
        -- output shift register
        bitshift:   std_logic_vector(12 downto 0);
        bitcnt:     unsigned(3 downto 0);
        -- output signals
        out_data:   std_ulogic;
        out_strobe: std_ulogic;
        -- parity flag
        parity:     std_ulogic;
        -- pending time tick
        pend_tick:  std_ulogic;
        pend_time:  std_logic_vector(7 downto 0);
        -- transmitter mode
        allow_fct:  std_ulogic;         -- allowed to send FCTs
        allow_char: std_ulogic;         -- allowed to send data and time
        sent_null:  std_ulogic;         -- sent at least one NULL token
        sent_fct:   std_ulogic;         -- sent at least one FCT token
    end record;
 
    -- Initial state
    constant regs_reset: regs_type := (
        txclken     => '0',
        txclkcnt    => "00000000",
        bitshift    => (others => '0'),
        bitcnt      => "0000",
        out_data    => '0',
        out_strobe  => '0',
        parity      => '0',
        pend_tick   => '0',
        pend_time   => (others => '0'),
        allow_fct   => '0',
        allow_char  => '0',
        sent_null   => '0',
        sent_fct    => '0' );
 
    -- Registers
    signal r:       regs_type := regs_reset;
    signal rin:     regs_type;
 
begin
 
    -- Combinatorial process
    process (r, rst, divcnt, xmiti) is
        variable v: regs_type;
    begin
        v := r;
 
        -- Generate TX clock.
        if r.txclkcnt = 0 then
            v.txclkcnt  := unsigned(divcnt);
            v.txclken   := '1';
        else
            v.txclkcnt  := r.txclkcnt - 1;
            v.txclken   := '0';
        end if;
 
        if xmiti.txen = '0' then
 
            -- Transmitter disabled; reset state.
            v.bitcnt     := "0000";
            v.parity     := '0';
            v.pend_tick  := '0';
            v.allow_fct  := '0';
            v.allow_char := '0';
            v.sent_null  := '0';
            v.sent_fct   := '0';
 
            -- Gentle reset of spacewire bus signals
            if r.txclken = '1' then
                v.out_data   := r.out_data and r.out_strobe;
                v.out_strobe := '0';
            end if;
 
        else
            -- Transmitter enabled.
 
            v.allow_fct  := (not xmiti.stnull) and r.sent_null;
            v.allow_char := (not xmiti.stnull) and r.sent_null and
                            (not xmiti.stfct) and r.sent_fct;
 
            -- On tick of transmission clock, put next bit on the output.
            if r.txclken = '1' then
 
                if r.bitcnt = 0 then
 
                    -- Need to start a new character.
                    if (r.allow_char = '1') and (r.pend_tick = '1') then
                        -- Send Time-Code.
                        v.out_data  := r.parity;
                        v.bitshift(12 downto 5) := r.pend_time;
                        v.bitshift(4 downto 0)  := "01111";
                        v.bitcnt    := to_unsigned(13, v.bitcnt'length);
                        v.parity    := '0';
                        v.pend_tick := '0';
                    elsif (r.allow_fct = '1') and (xmiti.fct_in = '1') then
                        -- Send FCT.
                        v.out_data  := r.parity;
                        v.bitshift(2 downto 0)  := "001";
                        v.bitcnt    := to_unsigned(3, v.bitcnt'length);
                        v.parity    := '1';
                        v.sent_fct  := '1';
                    elsif (r.allow_char = '1') and (xmiti.txwrite = '1') then
                        -- Send N-Char.
                        v.bitshift(0) := xmiti.txflag;
                        v.parity    := xmiti.txflag;
                        if xmiti.txflag = '0' then
                            -- Data byte
                            v.out_data  := not r.parity;
                            v.bitshift(8 downto 1) := xmiti.txdata;
                            v.bitcnt    := to_unsigned(9, v.bitcnt'length);
                        else
                            -- EOP or EEP
                            v.out_data  := r.parity;
                            v.bitshift(1) := xmiti.txdata(0);
                            v.bitshift(2) := not xmiti.txdata(0);
                            v.bitcnt    := to_unsigned(3, v.bitcnt'length);
                        end if;
                    else
                        -- Send NULL.
                        v.out_data  := r.parity;
                        v.bitshift(6 downto 0) := "0010111";
                        v.bitcnt    := to_unsigned(7, v.bitcnt'length);
                        v.parity    := '0';
                        v.sent_null := '1';
                    end if;
 
                else
 
                    -- Shift next bit to the output.
                    v.out_data  := r.bitshift(0);
                    v.parity    := r.parity xor r.bitshift(0);
                    v.bitshift(r.bitshift'high-1 downto 0) := r.bitshift(r.bitshift'high downto 1);
                    v.bitcnt    := r.bitcnt - 1;
 
                end if;
 
                -- Data-Strobe encoding.
                v.out_strobe := not (r.out_strobe xor r.out_data xor v.out_data);
 
            end if;
 
            -- Store requests for time tick transmission.
            if xmiti.tick_in = '1' then
                v.pend_tick := '1';
                v.pend_time := xmiti.ctrl_in & xmiti.time_in;
            end if;
 
        end if;
 
        -- Synchronous reset
        if rst = '1' then
            v := regs_reset;
        end if;
 
        -- Drive outputs.
        -- Note: the outputs are combinatorially dependent on certain inputs.
 
        -- Set fctack high if (transmitter enabled) AND
        -- (ready for token) AND (FCTs allowed) AND
        -- ((characters not allowed) OR (no timecode pending)) AND
        -- (FCT requested)
        if (xmiti.txen = '1') and
           (r.txclken = '1') and (r.bitcnt = 0) and (r.allow_fct = '1') and
           ((r.allow_char = '0') or (r.pend_tick = '0')) then
            xmito.fctack  <= xmiti.fct_in;
        else
            xmito.fctack  <= '0';
        end if;
 
        -- Set txrdy high if (transmitter enabled) AND
        -- (ready for token) AND (characters enabled) AND
        -- (no timecode pending) AND (no FCT requested) AND
        -- (character requested)
        if (xmiti.txen = '1') and
           (r.txclken = '1') and (r.bitcnt = 0) and (r.allow_char = '1') and
           (r.pend_tick = '0') and (xmiti.fct_in = '0') then
            xmito.txack   <= xmiti.txwrite;
        else
            xmito.txack   <= '0';
        end if;
 
        -- Update registers
        rin <= v;
    end process;
 
    -- Synchronous process
    process (clk) is
    begin
        if rising_edge(clk) then
 
            -- Update registers
            r <= rin;
 
            -- Drive spacewire output signals
            spw_do  <= r.out_data;
            spw_so  <= r.out_strobe;
 
        end if;
    end process;
 
end architecture spwxmit_arch;
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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