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;