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

Subversion Repositories spacewire_light

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /spacewire_light
    from Rev 1 to Rev 2
    Reverse comparison

Rev 1 → Rev 2

/trunk/bench/vhdl/streamtest_tb.vhd
0,0 → 1,242
--
-- Test bench for spwstream.
--
-- Tests:
-- * one spwstream instance with SpaceWire signals looped back to itself
-- * sending of bytes, packets and time codes through the SpaceWire link
-- * handling of link disabling and link disconnection
--
-- This test bench is intended to test the buffering logic in spwstream.
-- It does not thoroughly verify behaviour of the receiver, transmitter,
-- signal patterns etc. Please use spwlink_tb.vhd to test those aspects.
--
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use std.textio.all;
use work.spwpkg.all;
 
entity streamtest_tb is
end entity;
 
architecture tb_arch of streamtest_tb is
 
-- Parameters.
constant sys_clock_freq: real := 20.0e6;
 
component streamtest is
generic (
sysfreq: real;
tickdiv: integer range 12 to 24 := 20;
rximpl: spw_implementation_type := impl_generic;
rxchunk: integer range 1 to 4 := 1;
tximpl: spw_implementation_type := impl_generic;
rxfifosize_bits: integer range 6 to 14 := 11;
txfifosize_bits: integer range 2 to 14 := 11 );
port (
clk: in std_logic;
rxclk: in std_logic;
txclk: in std_logic;
rst: in std_logic;
linkstart: in std_logic;
autostart: in std_logic;
linkdisable: in std_logic;
senddata: in std_logic;
sendtick: in std_logic;
txdivcnt: in std_logic_vector(7 downto 0);
linkstarted: out std_logic;
linkconnecting: out std_logic;
linkrun: out std_logic;
linkerror: out std_logic;
gotdata: out std_logic;
dataerror: out std_logic;
tickerror: out std_logic;
spw_di: in std_logic;
spw_si: in std_logic;
spw_do: out std_logic;
spw_so: out std_logic );
end component;
 
signal sys_clock_enable: std_logic := '0';
signal sysclk: std_logic := '0';
signal s_loopback: std_logic := '0';
signal s_nreceived: integer := 0;
 
signal s_rst: std_logic := '1';
signal s_linkstart: std_logic;
signal s_autostart: std_logic;
signal s_linkdisable: std_logic;
signal s_divcnt: std_logic_vector(7 downto 0);
signal s_linkrun: std_logic;
signal s_linkerror: std_logic;
signal s_gotdata: std_logic;
signal s_dataerror: std_logic;
signal s_tickerror: std_logic;
signal s_spwdi: std_logic;
signal s_spwsi: std_logic;
signal s_spwdo: std_logic;
signal s_spwso: std_logic;
 
begin
 
-- streamtest instance
streamtest_inst: streamtest
generic map (
sysfreq => sys_clock_freq,
tickdiv => 16,
rximpl => impl_generic,
rxchunk => 1,
tximpl => impl_generic,
rxfifosize_bits => 9,
txfifosize_bits => 8 )
port map (
clk => sysclk,
rxclk => sysclk,
txclk => sysclk,
rst => s_rst,
linkstart => s_linkstart,
autostart => s_autostart,
linkdisable => s_linkdisable,
senddata => '1',
sendtick => '1',
txdivcnt => s_divcnt,
linkstarted => open,
linkconnecting => open,
linkrun => s_linkrun,
linkerror => s_linkerror,
gotdata => s_gotdata,
dataerror => s_dataerror,
tickerror => s_tickerror,
spw_di => s_spwdi,
spw_si => s_spwsi,
spw_do => s_spwdo,
spw_so => s_spwso );
 
-- Conditional loopback of SpaceWire signals.
s_spwdi <= s_spwdo when (s_loopback = '1') else '0';
s_spwsi <= s_spwso when (s_loopback = '1') else '0';
 
-- Generate system clock.
process is
begin
if sys_clock_enable /= '1' then
wait until sys_clock_enable = '1';
end if;
sysclk <= '1';
wait for (0.5 sec) / sys_clock_freq;
sysclk <= '0';
wait for (0.5 sec) / sys_clock_freq;
end process;
 
-- Verify that error indications remain off.
process is
begin
wait on s_linkerror, s_dataerror, s_tickerror;
assert s_dataerror = '0' report "Detected data error";
assert s_tickerror = '0' report "Detected time code error";
if s_loopback = '1' then
assert s_linkerror /= '1' report "Unexpected link error";
end if;
end process;
 
-- Verify that data is received regularly when the link is up.
process is
begin
if s_linkrun = '0' or s_gotdata = '1' then
wait until s_linkrun = '1' and s_gotdata = '0';
end if;
wait until s_gotdata = '1' or s_linkrun = '0' for 3 ms;
if s_linkrun = '1' then
assert s_gotdata = '1' report "Link running but no data received";
end if;
end process;
 
-- Count number of received characters.
process is
begin
wait until rising_edge(sysclk);
if s_gotdata = '1' then
s_nreceived <= s_nreceived + 1;
end if;
end process;
 
-- Main process.
process is
variable vline: LINE;
begin
report "Starting streamtest test bench";
 
-- Initialize.
s_loopback <= '1';
s_rst <= '1';
s_linkstart <= '0';
s_autostart <= '0';
s_linkdisable <= '0';
s_divcnt <= "00000001";
sys_clock_enable <= '1';
wait for 1 us;
 
-- Test link and data transmission.
report "Testing txdivcnt = 1";
s_rst <= '0';
s_linkstart <= '1';
wait for 100 us;
assert s_linkrun = '1' report "Link failed to start";
wait for 50 ms;
 
-- Check number of received characters.
write(vline, string'("Received "));
write(vline, s_nreceived);
write(vline, string'(" characters in 50 ms."));
writeline(output, vline);
assert s_nreceived > 24000 report "Too few characters received";
 
-- Test switching to different transmission rate.
report "Testing txdivcnt = 2";
s_divcnt <= "00000010";
wait for 10 ms;
report "Testing txdivcnt = 3";
s_divcnt <= "00000011";
wait for 10 ms;
 
-- Disable and re-enable link.
report "Testing link disable/re-enable";
s_linkdisable <= '1';
s_divcnt <= "00000001";
wait for 2 ms;
s_linkdisable <= '0';
wait for 100 us;
assert s_linkrun = '1' report "Link failed to start after re-enable";
wait for 10 ms;
 
-- Cut and reconnect loopback wiring.
report "Testing physical disconnect/reconnect";
s_loopback <= '0';
wait for 2 ms;
s_loopback <= '1';
wait for 100 us;
assert s_linkrun = '1' report "Link failed to start after reconnect";
wait for 10 ms;
s_loopback <= '0';
wait for 2 ms;
s_loopback <= '1';
wait for 100 us;
assert s_linkrun = '1' report "Link failed to start after reconnect (2)";
wait for 10 ms;
 
-- Shut down.
s_rst <= '1';
wait for 1 us;
sys_clock_enable <= '0';
 
write(vline, string'("Received "));
write(vline, s_nreceived);
write(vline, string'(" characters."));
writeline(output, vline);
 
report "Done";
wait;
end process;
 
end architecture tb_arch;
/trunk/bench/vhdl/spwlink_tb_all.vhd
0,0 → 1,326
--
-- Run the spwlink test bench in a several configurations.
--
 
use work.spwpkg.all;
 
entity spwlink_tb_all is
end entity;
 
architecture tb_arch of spwlink_tb_all is
 
component spwlink_tb is
generic (
sys_clock_freq: real := 20.0e6 ;
rx_clock_freq: real := 20.0e6 ;
tx_clock_freq: real := 20.0e6 ;
input_rate: real := 10.0e6 ;
tx_clock_div: integer := 1 ;
rximpl: spw_implementation_type := impl_generic ;
rxchunk: integer := 1 ;
tximpl: spw_implementation_type := impl_generic ;
startwait: time := 0 sec );
end component;
 
begin
 
-- Test 1: default configuration
test1: spwlink_tb
generic map (
sys_clock_freq => 20.0e6,
rx_clock_freq => 20.0e6,
tx_clock_freq => 20.0e6,
input_rate => 10.0e6,
tx_clock_div => 1,
rximpl => impl_generic,
rxchunk => 1,
tximpl => impl_generic,
startwait => 0 ms );
 
-- Test 2: 18 Mbit input
test2: spwlink_tb
generic map (
sys_clock_freq => 20.0e6,
rx_clock_freq => 20.0e6,
tx_clock_freq => 20.0e6,
input_rate => 18.0e6,
tx_clock_div => 1,
rximpl => impl_generic,
rxchunk => 1,
tximpl => impl_generic,
startwait => 1 ms );
 
-- Test 3: 2 Mbit input
test3: spwlink_tb
generic map (
sys_clock_freq => 20.0e6,
rx_clock_freq => 20.0e6,
tx_clock_freq => 20.0e6,
input_rate => 2.0e6,
tx_clock_div => 1,
rximpl => impl_generic,
rxchunk => 1,
tximpl => impl_generic,
startwait => 2 ms );
 
-- Test 4: 20 Mbit output
test4: spwlink_tb
generic map (
sys_clock_freq => 20.0e6,
rx_clock_freq => 20.0e6,
tx_clock_freq => 20.0e6,
input_rate => 10.0e6,
tx_clock_div => 0,
rximpl => impl_generic,
rxchunk => 1,
tximpl => impl_generic,
startwait => 3 ms );
 
-- Test 5: fast receiver, 10 Mbit in
test5: spwlink_tb
generic map (
sys_clock_freq => 20.0e6,
rx_clock_freq => 20.0e6,
tx_clock_freq => 20.0e6,
input_rate => 10.0e6,
tx_clock_div => 1,
rximpl => impl_fast,
rxchunk => 1,
tximpl => impl_generic,
startwait => 4 ms );
 
-- Test 6: fast receiver, 18 Mbit in
test6: spwlink_tb
generic map (
sys_clock_freq => 20.0e6,
rx_clock_freq => 20.0e6,
tx_clock_freq => 20.0e6,
input_rate => 18.0e6,
tx_clock_div => 1,
rximpl => impl_fast,
rxchunk => 1,
tximpl => impl_generic,
startwait => 5 ms );
 
-- Test 7: fast receiver, 35 Mbit in
test7: spwlink_tb
generic map (
sys_clock_freq => 20.0e6,
rx_clock_freq => 20.0e6,
tx_clock_freq => 20.0e6,
input_rate => 35.0e6,
tx_clock_div => 1,
rximpl => impl_fast,
rxchunk => 2,
tximpl => impl_generic,
startwait => 6 ms );
 
-- Test 8: fast receiver, 55 Mbit in
test8: spwlink_tb
generic map (
sys_clock_freq => 20.0e6,
rx_clock_freq => 30.0e6,
tx_clock_freq => 20.0e6,
input_rate => 55.0e6,
tx_clock_div => 1,
rximpl => impl_fast,
rxchunk => 3,
tximpl => impl_generic,
startwait => 7 ms );
 
-- Test 9: fast receiver, 75 Mbit in
test9: spwlink_tb
generic map (
sys_clock_freq => 20.0e6,
rx_clock_freq => 40.0e6,
tx_clock_freq => 20.0e6,
input_rate => 75.0e6,
tx_clock_div => 1,
rximpl => impl_fast,
rxchunk => 4,
tximpl => impl_generic,
startwait => 8 ms );
 
-- Test 10: fast receiver, 75 Mbit in, 100 MHz sample clock
test10: spwlink_tb
generic map (
sys_clock_freq => 20.0e6,
rx_clock_freq => 100.0e6,
tx_clock_freq => 20.0e6,
input_rate => 75.0e6,
tx_clock_div => 1,
rximpl => impl_fast,
rxchunk => 4,
tximpl => impl_generic,
startwait => 9 ms );
 
-- Test 11: fast receiver, 2 Mbit in, 100 MHz sample clock
test11: spwlink_tb
generic map (
sys_clock_freq => 20.0e6,
rx_clock_freq => 100.0e6,
tx_clock_freq => 20.0e6,
input_rate => 2.0e6,
tx_clock_div => 1,
rximpl => impl_fast,
rxchunk => 4,
tximpl => impl_generic,
startwait => 10 ms );
 
-- Test 12: fast receiver, 67.13 Mbit in, 43 MHz sample clock
test12: spwlink_tb
generic map (
sys_clock_freq => 20.0e6,
rx_clock_freq => 43.0e6,
tx_clock_freq => 20.0e6,
input_rate => 67.13e6,
tx_clock_div => 1,
rximpl => impl_fast,
rxchunk => 4,
tximpl => impl_generic,
startwait => 11 ms );
 
-- Test 13: fast transmitter, 39/2 Mbit out
test13: spwlink_tb
generic map (
sys_clock_freq => 20.0e6,
rx_clock_freq => 20.0e6,
tx_clock_freq => 39.0e6,
input_rate => 10.0e6,
tx_clock_div => 1,
rximpl => impl_generic,
rxchunk => 1,
tximpl => impl_fast,
startwait => 12 ms );
 
-- Test 14: fast transmitter, 39 Mbit out
test14: spwlink_tb
generic map (
sys_clock_freq => 20.0e6,
rx_clock_freq => 20.0e6,
tx_clock_freq => 39.0e6,
input_rate => 10.0e6,
tx_clock_div => 0,
rximpl => impl_generic,
rxchunk => 1,
tximpl => impl_fast,
startwait => 13 ms );
 
-- Test 15: fast transmitter, 80 Mbit out
test15: spwlink_tb
generic map (
sys_clock_freq => 20.0e6,
rx_clock_freq => 20.0e6,
tx_clock_freq => 80.0e6,
input_rate => 10.0e6,
tx_clock_div => 0,
rximpl => impl_generic,
rxchunk => 1,
tximpl => impl_fast,
startwait => 14 ms );
 
-- Test 16: fast transmitter, 20/3 Mbit out
test16: spwlink_tb
generic map (
sys_clock_freq => 20.0e6,
rx_clock_freq => 20.0e6,
tx_clock_freq => 20.0e6,
input_rate => 10.0e6,
tx_clock_div => 2,
rximpl => impl_generic,
rxchunk => 1,
tximpl => impl_fast,
startwait => 15 ms );
 
-- Test 17: fast transmitter, 80/4 Mbit out
test17: spwlink_tb
generic map (
sys_clock_freq => 20.0e6,
rx_clock_freq => 20.0e6,
tx_clock_freq => 80.0e6,
input_rate => 10.0e6,
tx_clock_div => 3,
rximpl => impl_generic,
rxchunk => 1,
tximpl => impl_fast,
startwait => 16 ms );
 
-- Test 18: fast transmitter, 80/5 Mbit out
test18: spwlink_tb
generic map (
sys_clock_freq => 20.0e6,
rx_clock_freq => 20.0e6,
tx_clock_freq => 80.0e6,
input_rate => 10.0e6,
tx_clock_div => 4,
rximpl => impl_generic,
rxchunk => 1,
tximpl => impl_fast,
startwait => 17 ms );
 
-- Test 19: fast transmitter, 80/40 Mbit out
test19: spwlink_tb
generic map (
sys_clock_freq => 20.0e6,
rx_clock_freq => 20.0e6,
tx_clock_freq => 80.0e6,
input_rate => 10.0e6,
tx_clock_div => 39,
rximpl => impl_generic,
rxchunk => 1,
tximpl => impl_fast,
startwait => 18 ms );
 
-- Test 20: fast transmitter, 200/97 Mbit out
test20: spwlink_tb
generic map (
sys_clock_freq => 50.0e6,
rx_clock_freq => 50.0e6,
tx_clock_freq => 200.0e6,
input_rate => 10.0e6,
tx_clock_div => 96,
rximpl => impl_generic,
rxchunk => 1,
tximpl => impl_fast,
startwait => 19 ms );
 
-- Test 21: fast transmitter, 78.5/2 Mbit out
test21: spwlink_tb
generic map (
sys_clock_freq => 20.0e6,
rx_clock_freq => 20.0e6,
tx_clock_freq => 78.5e6,
input_rate => 10.0e6,
tx_clock_div => 1,
rximpl => impl_generic,
rxchunk => 1,
tximpl => impl_fast,
startwait => 20 ms );
 
-- Test 22: fast receiver and fast transmitter, 78.5 Mbit out
test22: spwlink_tb
generic map (
sys_clock_freq => 20.0e6,
rx_clock_freq => 43.0e6,
tx_clock_freq => 78.5e6,
input_rate => 67.13e6,
tx_clock_div => 0,
rximpl => impl_fast,
rxchunk => 4,
tximpl => impl_fast,
startwait => 21 ms );
 
-- Test 23: fast receiver and fast transmitter, 77.5/2 Mbit out
test23: spwlink_tb
generic map (
sys_clock_freq => 20.0e6,
rx_clock_freq => 43.0e6,
tx_clock_freq => 77.5e6,
input_rate => 67.13e6,
tx_clock_div => 1,
rximpl => impl_fast,
rxchunk => 4,
tximpl => impl_fast,
startwait => 22 ms );
 
end tb_arch;
/trunk/bench/vhdl/spwlink_tb.vhd
0,0 → 1,978
--
-- Test Bench for Link interface.
--
-- Unfortunately rather incomplete.
-- The following items are verified:
-- * reset;
-- * link start, NULL exchange, FCT exchange;
-- * link autostart on first NULL;
-- * send/receive time codes, data characters, EOP/EEP;
-- * detection of timeout, disconnection, parity error, escape error.
--
 
library ieee;
use ieee.std_logic_1164.all, ieee.numeric_std.all;
use std.textio.all;
use work.spwpkg.all;
 
entity spwlink_tb is
 
-- Tests should be done with several different combinations
-- of values for the generics.
generic (
 
-- System clock frequency
sys_clock_freq: real := 20.0e6 ;
 
-- Receiver sample clock frequency
rx_clock_freq: real := 20.0e6 ;
 
-- Transmitter clock frequency
tx_clock_freq: real := 20.0e6 ;
 
-- Input bit rate
input_rate: real := 10.0e6 ;
 
-- TX clock division factor (actual factor is one tx_clock_div+1)
tx_clock_div: integer := 1 ;
 
-- Receiver implementation
rximpl: spw_implementation_type := impl_generic ;
 
-- Bits per sysclk for fast receiver
rxchunk: integer := 1 ;
 
-- Transmitter implementation
tximpl: spw_implementation_type := impl_generic ;
 
-- Wait before starting test bench
startwait: time := 0 sec
);
 
end spwlink_tb;
 
architecture tb_arch of spwlink_tb is
 
-- Bit periods for incoming / outgoing signal
constant inbit_period: time := (1 sec) / input_rate ;
constant outbit_period: time := (1 sec) * real(tx_clock_div + 1) / tx_clock_freq ;
constant txclk_period: time := (1 sec) / tx_clock_freq ;
 
-- clock generation
signal sys_clock_enable: std_logic := '0';
signal sysclk: std_logic;
signal rxclk: std_logic;
signal txclk: std_logic;
 
-- output monitoring
type t_output_chars is array(natural range <>) of std_logic_vector(9 downto 0);
signal output_collect: std_logic;
signal output_ptr: integer;
signal output_bits: std_logic_vector(0 to 4095);
signal output_nchars: integer;
signal output_chars: t_output_chars(0 to 4095);
 
-- input generation
signal input_par: std_logic;
signal input_idle: std_logic;
signal input_pattern: integer := 0;
 
-- interconnect signals
signal s_linki: spw_link_in_type;
signal s_linko: spw_link_out_type;
signal s_rxen: std_logic;
signal s_recvo: spw_recv_out_type;
signal s_xmiti: spw_xmit_in_type;
signal s_xmito: spw_xmit_out_type;
signal s_inact: std_logic;
signal s_inbvalid: std_logic;
signal s_inbits: std_logic_vector(rxchunk-1 downto 0);
 
-- interface signals
signal rst: std_logic := '1';
signal autostart: std_logic;
signal linkstart: std_logic;
signal linkdis: std_logic;
signal divcnt: std_logic_vector(7 downto 0) := (others => '0');
signal tick_in: std_logic;
signal ctrl_in: std_logic_vector(1 downto 0);
signal time_in: std_logic_vector(5 downto 0);
signal rxroom: std_logic_vector(5 downto 0);
signal txwrite: std_logic;
signal txflag: std_logic;
signal txdata: std_logic_vector(7 downto 0);
signal txrdy: std_logic;
signal tick_out: std_logic;
signal ctrl_out: std_logic_vector(1 downto 0);
signal time_out: std_logic_vector(5 downto 0);
signal rxchar: std_logic;
signal rxflag: std_logic;
signal rxdata: std_logic_vector(7 downto 0);
signal started: std_logic;
signal connecting:std_logic;
signal running: std_logic;
signal errdisc: std_logic;
signal errpar: std_logic;
signal erresc: std_logic;
signal errcred: std_logic;
signal spw_di: std_logic;
signal spw_si: std_logic;
signal spw_do: std_logic;
signal spw_so: std_logic;
 
-- misc
signal errany: std_logic;
 
procedure print(i: integer) is
variable v: LINE;
begin
write(v, i);
writeline(output, v);
end procedure;
 
procedure print(x: std_logic_vector) is
variable v: LINE;
begin
write(v, to_bitvector(x));
writeline(output, v);
end procedure;
 
procedure prints(s: string) is
variable v: LINE;
begin
write(v, s);
writeline(output, v);
end procedure;
 
procedure print(lbl: string; x: integer) is
variable v: LINE;
begin
write(v, lbl & " = ");
write(v, x);
writeline(output, v);
end procedure;
 
procedure print(lbl: string; x: real) is
variable v: LINE;
begin
write(v, lbl & " = ");
write(v, x);
writeline(output, v);
end procedure;
 
begin
 
-- Instantiate components.
 
spwlink_inst: spwlink
generic map (
reset_time => integer(sys_clock_freq * 0.0000064) ) -- 6.4 us
port map (
clk => sysclk,
rst => rst,
linki => s_linki,
linko => s_linko,
rxen => s_rxen,
recvo => s_recvo,
xmiti => s_xmiti,
xmito => s_xmito );
 
spwrecv_inst: spwrecv
generic map (
disconnect_time => integer(sys_clock_freq * 0.00000085), -- 850 ns
rxchunk => rxchunk )
port map (
clk => sysclk,
rxen => s_rxen,
recvo => s_recvo,
inact => s_inact,
inbvalid => s_inbvalid,
inbits => s_inbits );
 
spwxmit_if: if tximpl = impl_generic generate
spwxmit_inst: spwxmit
port map (
clk => sysclk,
rst => rst,
divcnt => divcnt,
xmiti => s_xmiti,
xmito => s_xmito,
spw_so => spw_so,
spw_do => spw_do );
end generate;
spwxmit_fast_if: if tximpl = impl_fast generate
spwxmit_fast_inst: spwxmit_fast
port map (
clk => sysclk,
txclk => txclk,
rst => rst,
divcnt => divcnt,
xmiti => s_xmiti,
xmito => s_xmito,
spw_so => spw_so,
spw_do => spw_do );
end generate;
 
spwrecvfront_generic_if: if rximpl = impl_generic generate
spwrecvfront_generic_inst: spwrecvfront_generic
port map (
clk => sysclk,
rxen => s_rxen,
inact => s_inact,
inbvalid => s_inbvalid,
inbits => s_inbits,
spw_di => spw_di,
spw_si => spw_si );
end generate;
spwrecvfront_fast_if: if rximpl = impl_fast generate
spwrecvfront_fast_inst: spwrecvfront_fast
generic map (
rxchunk => rxchunk )
port map (
clk => sysclk,
rxclk => rxclk,
rxen => s_rxen,
inact => s_inact,
inbvalid => s_inbvalid,
inbits => s_inbits,
spw_di => spw_di,
spw_si => spw_si );
end generate;
 
s_linki <= ( autostart => autostart,
linkstart => linkstart,
linkdis => linkdis,
rxroom => rxroom,
tick_in => tick_in,
ctrl_in => ctrl_in,
time_in => time_in,
txwrite => txwrite,
txflag => txflag,
txdata => txdata );
started <= s_linko.started;
connecting <= s_linko.connecting;
running <= s_linko.running;
errdisc <= s_linko.errdisc;
errpar <= s_linko.errpar;
erresc <= s_linko.erresc;
errcred <= s_linko.errcred;
txrdy <= s_linko.txack;
tick_out <= s_linko.tick_out;
ctrl_out <= s_linko.ctrl_out;
time_out <= s_linko.time_out;
rxchar <= s_linko.rxchar;
rxflag <= s_linko.rxflag;
rxdata <= s_linko.rxdata;
 
-- Logic OR of all error signals.
errany <= errdisc or errpar or erresc or errcred;
 
-- Generate system clock.
process is
begin
if sys_clock_enable /= '1' then
wait until sys_clock_enable = '1';
end if;
sysclk <= '1';
wait for (0.5 sec) / sys_clock_freq;
sysclk <= '0';
wait for (0.5 sec) / sys_clock_freq;
end process;
 
-- Generate rx sample clock.
process is
begin
if sys_clock_enable /= '1' then
wait until sys_clock_enable = '1';
end if;
rxclk <= '1';
wait for (0.5 sec) / rx_clock_freq;
rxclk <= '0';
wait for (0.5 sec) / rx_clock_freq;
end process;
 
-- Generate tx clock.
process is
begin
if sys_clock_enable /= '1' then
wait until sys_clock_enable = '1';
end if;
txclk <= '1';
wait for (0.5 sec) / tx_clock_freq;
txclk <= '0';
wait for (0.5 sec) / tx_clock_freq;
end process;
 
-- Collect output bits on SPW_DO and SPW_SO.
process is
variable t_last: time;
variable output_last_do: std_logic;
variable output_last_so: std_logic;
begin
if output_collect = '1' then
-- wait for next bit
if output_ptr <= output_bits'high then
output_bits(output_ptr) <= spw_do;
output_ptr <= output_ptr + 1;
end if;
output_last_do := spw_do;
output_last_so := spw_so;
t_last := now;
wait until (output_collect = '0') or (output_last_do /= spw_do) or (output_last_so /= spw_so);
if output_collect = '1' and output_ptr > 1 then
assert now > t_last + outbit_period - 1 ns
report "output bit period too short";
assert now < t_last + outbit_period + 1 ns
report "output bit period too long";
end if;
else
-- reset
output_ptr <= 0;
output_last_do := '0';
output_last_so := '0';
wait until output_collect = '1';
end if;
end process;
 
-- Collect received data on rxdata and tick_out.
process is
begin
wait until ((output_collect = '1') and rising_edge(sysclk)) or
((output_collect = '0') and (output_nchars /= 0));
if output_collect = '0' then
output_nchars <= 0;
elsif rising_edge(sysclk) and (output_nchars <= output_chars'high) then
assert (rxchar = '0') or (tick_out = '0');
if tick_out = '1' then
output_chars(output_nchars) <= "10" & ctrl_out & time_out;
output_nchars <= output_nchars + 1;
elsif rxchar = '1' then
output_chars(output_nchars) <= "0" & (rxflag) & rxdata;
output_nchars <= output_nchars + 1;
end if;
end if;
end process;
 
-- Generate input data.
process is
procedure input_reset is
begin
spw_di <= '0';
spw_si <= '0';
input_par <= '0';
end procedure;
procedure genbit(b: std_logic) is
begin
spw_si <= not (spw_si xor spw_di xor b);
spw_di <= b;
wait for inbit_period;
end procedure;
procedure genfct is
begin
genbit(input_par);
genbit('1');
genbit('0');
input_par <= '0';
genbit('0');
end procedure;
procedure genesc is
begin
genbit(input_par);
genbit('1');
genbit('1');
input_par <= '0';
genbit('1');
end procedure;
procedure geneop(e: std_logic) is
begin
genbit(input_par);
genbit('1');
genbit(e);
input_par <= '1';
genbit(not e);
end procedure;
procedure gendat(dat: std_logic_vector(7 downto 0)) is
begin
genbit(not input_par);
genbit('0');
genbit(dat(0)); genbit(dat(1)); genbit(dat(2)); genbit(dat(3));
genbit(dat(4)); genbit(dat(5)); genbit(dat(6));
input_par <= dat(0) xor dat(1) xor dat(2) xor dat(3) xor
dat(4) xor dat(5) xor dat(6) xor dat(7);
genbit(dat(7));
end procedure;
begin
input_idle <= '1';
input_reset;
wait until input_pattern /= 0;
input_idle <= '0';
while input_pattern /= 0 loop
if input_pattern = 1 then
-- NULL tokens
genesc; genfct;
elsif input_pattern = 2 then
-- FCT tokens
genfct;
elsif input_pattern = 3 then
-- invalid bit pattern
genbit('0');
genbit('1');
elsif input_pattern = 4 then
-- EOP token
geneop('0');
elsif input_pattern = 5 then
-- FCT, TIME, 8 chars, NULLs
genfct;
genesc; gendat("00111000");
gendat("01010101");
gendat("10101010");
gendat("01010101");
gendat("10101010");
gendat("01010101");
gendat("10101010");
gendat("01010101");
gendat("10101010");
while input_pattern = 5 loop
genesc; genfct;
end loop;
elsif input_pattern = 6 then
-- ESC tokens
genesc;
elsif input_pattern = 7 then
-- FCT, NULL, NULL, EOP, EEP, NULLs
genfct;
genesc; genfct;
genesc; genfct;
geneop('0');
geneop('1');
while input_pattern = 7 loop
genesc; genfct;
end loop;
elsif input_pattern = 8 then
-- FCT, NULL, NULL, NULL, NULL, NULL, char, parity error
genfct;
genesc; genfct;
genesc; genfct;
genesc; genfct;
genesc; genfct;
genesc; genfct;
gendat("01010101");
genbit(not input_par);
genbit('0');
genbit('1'); genbit('0'); genbit('1'); genbit('0');
genbit('1'); genbit('0'); genbit('1');
input_par <= '1'; -- wrong parity !!
genbit('0');
while input_pattern = 8 loop
genesc; genfct;
end loop;
else
assert false;
end if;
end loop;
end process;
 
-- Main process.
process is
 
-- Skip NULL tokens and return position of first non-NULL.
function skip_null(data: in std_logic_vector; start: in integer; len: in integer) return integer is
variable i: integer;
begin
i := start;
if (i + 7 < len) and (data((i+1) to (i+7)) = "1110100") then
i := i + 8;
end if;
while (i + 7 < len) and (data(i to (i+7)) = "01110100") loop
i := i + 8;
end loop;
return i;
end function;
 
function check_parity(data: in std_logic_vector; start: in integer; len: in integer) return boolean is
variable i: integer;
variable p: std_logic;
begin
i := start;
p := data(start);
while i + 3 < len loop
if data(i+1) = '1' then
if data(0) /= p then return false; end if;
p := data(2) xor data(3);
i := i + 4;
else
if i + 9 < len then return true; end if;
if data(0) /= not p then return false; end if;
p := not (data(2) xor data(3) xor data(4) xor data(5) xor
data(6) xor data(7) xor data(8) xor data(9));
i := i + 10;
end if;
end loop;
return true;
end function;
 
variable i: integer;
 
begin
 
-- Wait for start of test.
wait for startwait;
 
-- Initialize.
rst <= '1';
input_pattern <= 0;
sys_clock_enable <= '1';
output_collect <= '0';
 
-- Say hello
report "Starting spwlink test bench";
print(" sys_clock_freq", sys_clock_freq);
print(" rx_clock_freq ", rx_clock_freq);
print(" tx_clock_freq ", tx_clock_freq);
print(" input_rate ", input_rate);
print(" tx_clock_div ", tx_clock_div);
case rximpl is
when impl_generic => prints(" rximpl = impl_generic");
when impl_fast => prints(" rximpl = impl_fast");
end case;
print(" rxchunk ", rxchunk);
case tximpl is
when impl_generic => prints(" tximpl = impl_generic");
when impl_fast => prints(" tximpl = impl_fast");
end case;
 
-- Test 1: Reset.
autostart <= '0'; linkstart <= '0'; linkdis <= '0';
divcnt <= std_logic_vector(to_unsigned(tx_clock_div, divcnt'length));
tick_in <= '0'; ctrl_in <= "00"; time_in <= "000000"; rxroom <= "000000";
txwrite <= '0'; txflag <= '0'; txdata <= "00000000";
wait until rising_edge(sysclk);
wait until rising_edge(sysclk);
wait for 1 ns;
rst <= '0';
assert (txrdy = '0') report " 1. reset (txrdy = 0)";
assert (tick_out = '0') report " 1. reset (tick_out = 0)";
assert (rxchar = '0') report " 1. reset (rxchar = 0)";
assert (started = '0') report " 1. reset (started = 0)";
assert (connecting = '0') report " 1. reset (connecting = 0)";
assert (running = '0') report " 1. reset (running = 0)";
assert (errdisc = '0') report " 1. reset (errdisc = 0)";
assert (errpar = '0') report " 1. reset (errpar = 0)";
assert (erresc = '0') report " 1. reset (erresc = 0)";
assert (errcred = '0') report " 1. reset (errcred = 0)";
assert (spw_do = '0') report " 1. reset (spw_do = 0)";
assert (spw_so = '0') report " 1. reset (spw_so = 0)";
 
-- Test 2: Remain idle after one clock cycle.
wait until rising_edge(sysclk);
wait until falling_edge(sysclk);
assert (started = '0') and (running = '0')
report " 2. init (state)";
assert (spw_do = '0') and (spw_so = '0')
report " 2. init (SPW idle)";
 
-- Test 3: Move to Ready state.
wait on started, running, spw_do, spw_so for 50 us;
assert (started = '0') and (running = '0')
report " 3. ready (state)";
assert (spw_do = '0') and (spw_so = '0')
report " 3. ready (SPW idle)";
 
-- Test 4: Start link; wait for NULL patterns.
linkstart <= '1';
rxroom <= "001111";
wait on started, connecting, running, spw_do, spw_so for 1 us;
assert (started = '1') and (running = '0')
report " 4. nullgen (started)";
if spw_so = '0' then
wait on started, connecting, running, spw_do, spw_so for 1.2 us;
end if;
assert (started = '1') and (connecting = '0') and (running = '0') and
(spw_do = '0') and (spw_so = '1')
report " 4. nullgen (SPW strobe)";
output_collect <= '1';
wait on started, connecting, running for (7.1 * outbit_period);
assert (started = '1') and (running = '0')
report " 4. nullgen (state 2)";
assert (output_ptr = 8) and (output_bits(0 to 7) = "01110100")
report " 4. nullgen (NULL 1)";
-- got the first NULL, wait for the second one ...
wait on started, connecting, running for (8.0 * outbit_period);
assert (started = '1') and (running = '0')
report " 4. nullgen (state 3)";
assert (output_ptr = 16) and (output_bits(8 to 15) = "01110100")
report " 4. nullgen (NULL 2)";
output_collect <= '0';
 
-- Test 5: Timeout in Started state.
wait on started, connecting, running, errany for 9.5 us - (15.0 * outbit_period);
assert (started = '1') and (running = '0') and (errany = '0')
report " 5. started_timeout (wait)";
wait on started, connecting, running, errany for 4 us;
assert (started = '0') and (connecting = '0') and (running = '0') and (errany = '0')
report " 5. started_timeout (trigger)";
wait for (3.1 * outbit_period + 20 * txclk_period);
assert (spw_do = '0') and (spw_so = '0')
report " 5. started_timeout (SPW to zero)";
 
-- Test 6: Start link; simulate NULL pattern; wait for FCT pattern.
wait on started, connecting, running, spw_so for 18 us - (3.1 * outbit_period + 20 * txclk_period);
assert (started = '0') and (connecting = '0') and (running = '0') and (spw_so = '0')
report " 6. fctgen (SPW idle)";
wait on started, connecting, running, spw_so for 2 us;
assert (started = '1') and (connecting = '0') and (running = '0')
report " 6. fctgen (started)";
if spw_so = '0' then
wait on started, connecting, running, spw_do, spw_so for 1.2 us;
end if;
assert (spw_do = '0') and (spw_so = '1')
report " 6. fctgen (SPW strobe)";
output_collect <= '1';
input_pattern <= 1;
wait on started, connecting, running for 8 us;
assert (started = '0') and (connecting = '1') and (running = '0')
report " 6. fctgen (detect NULL)";
wait for (1.1 sec) / sys_clock_freq;
wait on started, connecting, running, errany for 12 us;
assert (started = '0') and (connecting = '1') and (running = '0') and (errany = '0')
report " 6. fctgen (connecting failed early)";
assert (output_ptr > 7) and (output_bits(0 to 7) = "01110100")
report " 6. fctgen (gen NULL)";
i := skip_null(output_bits, 0, output_ptr);
assert (i > 0) and (i + 11 < output_ptr) and (output_bits(i to (i+11)) = "010001110100")
report " 6. fctgen (gen FCT NULL)";
output_collect <= '0';
 
-- Test 7: Timeout in Connecting state.
wait on started, connecting, running, errany for 4 us;
assert (started = '0') and (connecting = '0') and (running = '0') and (errany = '0')
report " 7. connecting_timeout";
input_pattern <= 0;
wait until rising_edge(sysclk);
 
-- Test 8: Autostart link; simulate NULL and FCT; move to Run state; disconnect.
linkstart <= '0';
autostart <= '1';
rxroom <= "010000";
wait on started, connecting, running, errany for 50 us;
assert (started = '0') and (connecting = '0') and (running = '0') and (errany = '0')
report " 8. autostart (wait)";
output_collect <= '1';
input_pattern <= 1;
wait on started, connecting, running for 200 ns + 20 * inbit_period;
assert (started = '1') and (connecting = '0') and (running = '0')
report " 8. autostart (Started)";
input_pattern <= 2;
wait on started, connecting, running for 1 us;
assert (started = '0') and (connecting = '1') and (running = '0')
report " 8. autostart (Connecting)";
wait on started, connecting, running, errany for 200 ns + 24 * inbit_period;
assert (started = '0') and (connecting = '0') and (running = '1') and (errany = '0')
report " 8. autostart (Run)";
input_pattern <= 1;
txwrite <= '1';
if txrdy = '0' then
wait on running, errany, txrdy for (20 * outbit_period);
end if;
assert (running = '1') and (errany = '0') and (txrdy = '1')
report " 8. running (txrdy = 1)";
txwrite <= '0';
wait on running, errany for 50 us;
assert (running = '1') and (errany = '0')
report " 8. running stable";
assert output_bits(1 to 24) = "011101000100010001110100"
report " 8. NULL FCT FCT NULL";
output_collect <= '0';
linkdis <= '1';
wait on started, running, errany for (2.1 sec) / sys_clock_freq;
assert (started = '0') and (running = '0') and (errany = '0')
report " 8. link disable";
autostart <= '0';
linkdis <= '0';
input_pattern <= 0;
wait until rising_edge(sysclk);
 
-- Test 9: Start link until Run state; disconnect.
linkstart <= '1';
rxroom <= "001000";
input_pattern <= 1;
wait on started, connecting, running for 20 us;
assert (started = '1') and (connecting = '0') and (running = '0')
report " 9. running_disconnect (Started)";
linkstart <= '0';
wait until rising_edge(sysclk);
input_pattern <= 2;
wait on started, connecting, running, errany for 20 * inbit_period;
assert (started = '0') and (connecting = '1') and (running = '0') and (errany = '0')
report " 9. running_disconnect (Connecting)";
wait on started, connecting, running, errany for 150 ns + 24 * inbit_period;
assert (started = '0') and (connecting = '0') and (running = '1') and (errany = '0')
report " 9. running_disconnect (Run)";
input_pattern <= 0;
wait until input_idle = '1';
wait on started, connecting, running, errany for 1500 ns;
assert errdisc = '1'
report " 9. running_disconnect (errdisc = 1)";
if running = '1' then
wait on started, connecting, running for (1.1 sec) / sys_clock_freq;
end if;
assert (started = '0') and (connecting = '0') and (running = '0')
report " 9. running_disconnect (running = 0)";
wait until rising_edge(sysclk);
assert (started = '0') and (connecting = '0') and (running = '0') and (errany = '0')
report " 9. running_disconnect (reset)";
wait until rising_edge(sysclk);
 
-- Test 10: Junk signal before starting link.
autostart <= '1';
input_pattern <= 3;
wait on started, errany for 6 us;
assert (started = '0') and (errany = '0')
report "10. junk signal (ignore noise)";
input_pattern <= 2;
wait on started, errany for 4 us;
assert (started = '0') and (errany = '0')
report "10. junk signal (ignore FCT)";
input_pattern <= 0;
wait until input_idle = '1';
input_pattern <= 1; -- send NULL
wait until input_idle = '0';
input_pattern <= 3; -- send invalid pattern; spw should now reset
wait on started, errany for 8 us;
assert (started = '0') and (errany = '0')
report "10. junk signal (hidden reset)";
input_pattern <= 1; -- send NULL
wait on started, errany for 10 us;
assert (started = '0') and (errany = '0')
report "10. junk signal (waiting)";
wait on started, errany for 10 us;
assert (started = '1') and (errany = '0')
report "10. junk signal (Started)";
autostart <= '0';
rst <= '1';
wait until rising_edge(sysclk);
rst <= '0';
wait until rising_edge(sysclk);
assert (started = '0') and (errany = '0')
report "10. junk signal (rst)";
wait until rising_edge(sysclk);
 
-- Test 11: Incoming EOP before first FCT.
linkstart <= '1';
rxroom <= "001000";
input_pattern <= 1;
wait on connecting, running, errany for 21 us;
assert (connecting = '1') and (errany = '0')
report "11. unexpected EOP (Connecting)";
input_pattern <= 4;
linkstart <= '0';
wait on connecting, running, errany for 200 ns + 24 * inbit_period;
assert (connecting = '0') and (running = '0') and (errany = '0')
report "11. unexpected EOP (reset on EOP)";
input_pattern <= 0;
wait for (10 * outbit_period);
 
-- Test 12: Send and receive characters, time codes, abort on double ESC.
wait until falling_edge(sysclk);
linkstart <= '1';
wait on started, errany for 21 us;
assert (started = '1') and (errany = '0')
report "12. characters (Started)";
rxroom <= "001000";
input_pattern <= 1;
output_collect <= '1';
tick_in <= '1';
wait on connecting, running, errany for 21 us;
assert (connecting = '1') and (errany = '0')
report "12. characters (Connecting)";
wait until output_ptr > 9 for 2 us;
input_pattern <= 5; -- FCT, TIME, 8 chars, NULLs
time_in <= "000111";
txwrite <= '1';
txflag <= '0';
txdata <= "01101100";
wait on connecting, running, errany for 200 ns + (24 * inbit_period);
assert (running = '1') and (errany = '0')
report "12. characters (Run)";
wait until rising_edge(sysclk);
assert (running = '1') and (errany = '0')
report "12. characters (running = 1)";
tick_in <= '0';
wait for 4 * outbit_period; -- wait until first FCT sent
rxroom <= "000111";
wait until txrdy = '1' for 200 ns + (20 * outbit_period);
assert (running = '1') and (txrdy = '1')
report "12. characters (txrdy = 1)";
wait on running, errany for 50 us + (80 * outbit_period);
assert (running = '1') and (errany = '0')
report "12. characters (stable)";
input_pattern <= 6; -- just ESC tokens
wait on running, errany for 200 ns + (32 * inbit_period);
assert erresc = '1'
report "12. characters (erresc = 1)";
wait until rising_edge(sysclk);
wait for 1 ns;
assert (started = '0') and (connecting = '0') and (running = '0')
report "12. characters (reset)";
assert (output_ptr > 8) and (output_bits(1 to 8) = "01110100")
report "12. characters (gen NULL 1)";
i := skip_null(output_bits, 1, output_ptr);
assert (i > 0) and (output_bits(i to (i+3)) = "0100")
report "12. characters (gen FCT)";
i := skip_null(output_bits, i + 4, output_ptr);
assert (i + 13 < output_ptr) and (output_bits(i to (i+13)) = "01111011100000")
report "12. characters (gen TimeCode)";
i := i + 14;
assert (i + 79 < output_ptr) and (output_bits(i to (i+79)) = "00001101101000110110100011011010001101101000110110100011011010001101101000110110")
report "12. characters (gen Data)";
i := i + 80;
assert (i + 7 < output_ptr) and (output_bits(i to (i+7)) = "01110100")
report "12. characters (gen NULL 2)";
assert (output_nchars > 0) and (output_chars(0) = "1000111000")
report "12. characters (got TimeCode)";
assert (output_nchars > 1) and (output_chars(1) = "0001010101")
report "12. characters (got byte 1)";
assert (output_nchars > 2) and (output_chars(2) = "0010101010")
report "12. characters (got byte 2)";
assert (output_nchars > 3) and (output_chars(3) = "0001010101")
report "12. characters (got byte 3)";
assert (output_nchars > 4) and (output_chars(4) = "0010101010")
report "12. characters (got byte 4)";
assert check_parity(output_bits, 1, output_ptr)
report "12. parity of output bits";
output_collect <= '0';
input_pattern <= 0;
txwrite <= '0';
linkstart <= '0';
wait for (20 * outbit_period);
 
-- Test 13: Send and receive EOP, EEP, abort on credit error.
linkstart <= '1';
rxroom <= "001000";
input_pattern <= 1;
output_collect <= '1';
wait on connecting, running, errany for 21 us;
assert (connecting = '1') and (errany = '0')
report "13. eop, eep (Connecting)";
wait until output_ptr > 9 for 2 us;
input_pattern <= 7; -- FCT, NULL, NULL, EOP, EEP, NULLs
wait for (1.1 sec) / sys_clock_freq;
wait on connecting, running, errany for 12 us;
assert (running = '1') and (errany = '0')
report "13. eop, eep (Run)";
wait for 1 ns;
txwrite <= '1';
txflag <= '1';
txdata <= "01101100";
wait until rising_edge(sysclk) and txrdy = '1' for 1 us + (14 * outbit_period);
assert (txrdy = '1') and (running = '1') and (errany = '0')
report "13. eop, eep (txrdy 1)";
rxroom <= "000111" after 1 ns;
txdata <= "00000001" after 1 ns;
wait until rising_edge(sysclk) and txrdy = '1' for 1 us + (14 * outbit_period);
assert (txrdy = '1') and (running = '1') and (errany = '0')
report "13. eop, eep (txrdy 2)";
txdata <= "00000000" after 1 ns;
wait until rising_edge(sysclk) and txrdy = '1' for (14 * outbit_period);
assert (txrdy = '1') and (running = '1') and (errany = '0')
report "13. eop, eep (txrdy 3)";
txdata <= "11111111" after 1 ns;
wait until rising_edge(sysclk) and txrdy = '1' for (14 * outbit_period);
assert (txrdy = '1') and (running = '1') and (errany = '0')
report "13. eop, eep (txrdy 4)";
txdata <= "11111110" after 1 ns;
wait until rising_edge(sysclk) and txrdy = '1' for (14 * outbit_period);
assert (txrdy = '1') and (running = '1') and (errany = '0')
report "13. eop, eep (txrdy 5)";
txdata <= "01010101" after 1 ns;
wait until rising_edge(sysclk) and txrdy = '1' for (14 * outbit_period);
assert (txrdy = '1') and (running = '1') and (errany = '0')
report "13. eop, eep (txrdy 6)";
txdata <= "10101010" after 1 ns;
wait until rising_edge(sysclk) and txrdy = '1' for (14 * outbit_period);
assert (txrdy = '1') and (running = '1') and (errany = '0')
report "13. eop, eep (txrdy 7)";
txdata <= "01010101" after 1 ns;
wait until rising_edge(sysclk) and txrdy = '1' for (14 * outbit_period);
assert (txrdy = '1') and (running = '1') and (errany = '0')
report "13. eop, eep (txrdy 8)";
txdata <= "10101010" after 1 ns;
wait until rising_edge(sysclk) and (txrdy = '1') for (14 * outbit_period);
assert (txrdy = '0') and (running = '1') and (errany = '0')
report "13. eop, eep (txrdy 9)";
txwrite <= '0';
txflag <= '0';
wait on running, errany for (10 * outbit_period);
assert (running = '1') and (errany = '0')
report "13. eop, eep (flush out)";
input_pattern <= 2; -- FCT tokens
wait on running, errany for (80 * inbit_period);
assert errcred = '1'
report "13. eop, eep (errcred = 1)";
wait until running = '0';
assert (output_ptr > 8) and (output_bits(1 to 8) = "01110100")
report "13. eop, eep (gen NULL 1)";
i := skip_null(output_bits, 1, output_ptr);
assert (i > 0) and (output_bits(i to (i+3)) = "0100")
report "13. eop, eep (gen FCT)";
i := i + 4;
for j in 0 to 3 loop
i := skip_null(output_bits, i, output_ptr);
assert (i + 3 < output_ptr) and (output_bits(i+1 to (i+3)) = "101")
report "13. eop, eep (eop)";
i := skip_null(output_bits, i + 4, output_ptr);
assert (i + 3 < output_ptr) and (output_bits(i+1 to (i+3)) = "110")
report "13. eop, eep (eep)";
i := i + 4;
end loop;
assert (i + 8 < output_ptr) and (output_bits(i to (i+8)) = "111101000")
report "13. eop, eep (gen NULL 2)";
assert check_parity(output_bits, 1, output_ptr)
report "12. parity of output bits";
assert (output_nchars > 0) and (output_chars(0) = "0100000000")
report "13. eop, eep (got EOP)";
assert (output_nchars = 2) and (output_chars(1) = "0100000001")
report "13. eop, eep (got EEP)";
output_collect <= '0';
input_pattern <= 0;
linkstart <= '0';
wait until rising_edge(sysclk);
 
-- Test 14: Abort on parity error.
wait for 10 us;
assert spw_do = '0' and spw_so = '0'
report "14. output still babbling";
linkstart <= '1';
rxroom <= "001000";
input_pattern <= 1;
output_collect <= '1';
wait for 1 ns; -- ghdl is totally fucked up
wait on connecting, running, errany for 21 us;
assert (connecting = '1') and (errany = '0')
report "14. partity (Connecting)";
input_pattern <= 8; -- FCT, NULL, NULL, NULL, NULL, NULL, char, error
wait for (1.1 sec) / sys_clock_freq;
wait on running, errany for 12 us;
assert (running = '1') and (errany = '0')
report "14. parity (Run)";
wait on running, errany for 150 ns + (84 * inbit_period);
assert errpar = '1'
report "14. parity (errpar = 1)";
wait until running = '0';
assert (output_nchars = 1) and (output_chars(0) = "0001010101")
report "14. parity (received char)";
output_collect <= '0';
input_pattern <= 0;
linkstart <= '0';
wait until rising_edge(sysclk);
 
-- Stop simulation
input_pattern <= 0;
wait for 100 us;
sys_clock_enable <= '0';
report "Done.";
wait;
 
end process;
 
end tb_arch;
/trunk/GPL-2.txt
0,0 → 1,339
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
 
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
 
Preamble
 
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
 
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
 
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
 
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
 
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
 
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
 
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
 
The precise terms and conditions for copying, distribution and
modification follow.
 
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
 
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
 
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
 
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
 
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
 
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
 
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
 
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
 
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
 
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
 
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
 
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
 
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
 
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
 
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
 
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
 
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
 
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
 
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
 
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
 
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
 
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
 
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
 
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
 
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
 
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
 
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
 
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
 
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
 
NO WARRANTY
 
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
 
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
 
END OF TERMS AND CONDITIONS
 
How to Apply These Terms to Your New Programs
 
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
 
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
 
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
Also add information on how to contact you by electronic and paper mail.
 
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
 
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
 
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
 
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
 
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
 
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
 
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.
/trunk/rtl/vhdl/spwrecvfront_fast.vhd
0,0 → 1,467
--
-- Front-end for SpaceWire Receiver
--
-- This entity samples the input signals DataIn and StrobeIn to detect
-- valid bit transitions. Received bits are handed to the application
-- in groups of "rxchunk" bits at a time, synchronous to the system clock.
--
-- This receiver is based on synchronous oversampling of the input signals.
-- Inputs are sampled on the rising and falling edges of an externally
-- supplied sample clock "rxclk". Therefore the maximum bitrate of the
-- incoming signal must be significantly lower than two times the "rxclk"
-- clock frequency. The maximum incoming bitrate must also be strictly
-- lower than rxchunk times the system clock frequency.
--
-- This code is tuned for implementation on Xilinx Spartan-3.
--
-- Details
-- -------
--
-- Stage A: The inputs "spw_di" and "spw_si" are handled as DDR signals,
-- synchronously sampled on both edges of "rxclk".
--
-- Stage B: The input signals are re-registered on the rising edge of "rxclk"
-- for further processing. This implies that every rising edge of "rxclk"
-- produces two new samples of "spw_di" and two new samples of "spw_si".
-- Some preparation is done for data/strobe decoding.
--
-- Stage C: Transitions in input signals are detected by comparing the XOR
-- of data and strobe to the XOR of the previous data and strobe samples.
-- If there is a difference, we know that either data or strobe has changed
-- and the new value of data is a valid new bit. Every rising edge of "rxclk"
-- thus produces either zero, one or two new data bits.
--
-- Received data bits are pushed into a cyclic buffer. A two-hot array marks
-- the two positions where the next received bits will go into the buffer.
-- In addition, a 4-step gray-encoded counter "headptr" indicates the current
-- position in the cyclic buffer.
--
-- The contents of the cyclic buffer and the head pointer are re-registered
-- on the rising edge of the system clock. A binary counter "tailptr" points
-- to next group of bits to read from the cyclic buffer. A comparison between
-- "tailptr" and "headptr" determines whether those bits have already been
-- received and safely stored in the buffer.
--
-- Implementation guidelines
-- -------------------------
--
-- IOB flip-flops must be used to sample spw_di and spw_si.
-- Clock skew between the IOBs for spw_di and spw_si must be minimized.
--
-- "rxclk" must be at least as fast as the system clock;
-- "rxclk" does not need to be phase-related to the system clock;
-- it is allowed for "rxclk" to be equal to the system clock.
--
-- The following timing constraints are needed:
-- * PERIOD constraint on the system clock;
-- * PERIOD constraint on "rxclk";
-- * FROM-TO constraint from "rxclk" to system clock, equal to one "rxclk" period;
-- * FROM-TO constraint from system clock to "rxclk", equal to one "rxclk" period.
--
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
entity spwrecvfront_fast is
 
generic (
-- Number of bits to pass to the application per system clock.
rxchunk: integer range 1 to 4 );
 
port (
-- System clock.
clk: in std_logic;
 
-- Sample clock.
rxclk: in std_logic;
 
-- High to enable receiver; low to disable and reset receiver.
rxen: in std_logic;
 
-- High if there has been recent activity on the input lines.
inact: out std_logic;
 
-- High if inbits contains a valid group of received bits.
-- If inbvalid='1', the application must sample inbits on
-- the rising edge of clk.
inbvalid: out std_logic;
 
-- Received bits (bit 0 is the earliest received bit).
inbits: out std_logic_vector(rxchunk-1 downto 0);
 
-- Data In signal from SpaceWire bus.
spw_di: in std_logic;
 
-- Strobe In signal from SpaceWire bus.
spw_si: in std_logic );
 
-- Turn off FSM extraction.
-- Without this, XST will happily apply one-hot encoding to rrx.headptr.
attribute FSM_EXTRACT: string;
attribute FSM_EXTRACT of spwrecvfront_fast: entity is "NO";
 
-- Turn off register replication.
-- Without this, XST will happily replicate my synchronization flip-flops.
attribute REGISTER_DUPLICATION: string;
attribute REGISTER_DUPLICATION of spwrecvfront_fast: entity is "FALSE";
 
end entity spwrecvfront_fast;
 
architecture spwrecvfront_arch of spwrecvfront_fast is
 
-- size of the cyclic buffer in bits;
-- typically 4 times rxchunk, except when rxchunk = 1
type chunk_array_type is array(1 to 4) of integer;
constant chunk_to_buflen: chunk_array_type := ( 8, 8, 12, 16 );
constant c_buflen: integer := chunk_to_buflen(rxchunk);
 
-- convert from straight binary to reflected binary gray code
function gray_encode(b: in std_logic_vector) return std_logic_vector is
variable g: std_logic_vector(b'high downto b'low);
begin
g(b'high) := b(b'high);
for i in b'high-1 downto b'low loop
g(i) := b(i) xor b(i+1);
end loop;
return g;
end function;
 
-- convert from reflected binary gray code to straight binary
function gray_decode(g: in std_logic_vector) return std_logic_vector is
variable b: std_logic_vector(g'high downto g'low);
begin
b(g'high) := g(g'high);
for i in g'high-1 downto g'low loop
b(i) := g(i) xor b(i+1);
end loop;
return b;
end function;
 
-- stage A: input flip-flops for rising/falling rxclk
signal s_a_di0: std_logic;
signal s_a_di1: std_logic;
signal s_a_si0: std_logic;
signal s_a_si1: std_logic;
 
-- registers in rxclk domain
type rxregs_type is record
-- reset synchronizer
reset: std_logic_vector(1 downto 0);
-- stage B: re-register input samples and prepare for data/strobe decoding
b_di0: std_ulogic;
b_di1: std_ulogic;
b_si1: std_ulogic;
b_xor0: std_ulogic; -- b_xor0 = b_di0 xor b_si0
-- stage C: after data/strobe decoding
c_bit: std_logic_vector(1 downto 0);
c_val: std_logic_vector(1 downto 0);
c_xor1: std_ulogic;
-- cyclic bit buffer
bufdata: std_logic_vector(c_buflen-1 downto 0); -- data bits
bufmark: std_logic_vector(c_buflen-1 downto 0); -- two-hot, marking destination of next two bits
headptr: std_logic_vector(1 downto 0); -- gray encoded head position
headlow: std_logic_vector(1 downto 0); -- least significant bits of head position
headinc: std_ulogic; -- must update headptr on next clock
-- activity detection
bitcnt: std_logic_vector(2 downto 0); -- gray counter
end record;
 
-- registers in system clock domain
type regs_type is record
-- cyclic bit buffer, re-registered to the system clock
bufdata: std_logic_vector(c_buflen-1 downto 0); -- data bits
headptr: std_logic_vector(1 downto 0); -- gray encoded head position
-- tail pointer (binary)
tailptr: std_logic_vector(2 downto 0);
-- activity detection
bitcnt: std_logic_vector(2 downto 0);
bitcntp: std_logic_vector(2 downto 0);
bitcntpp: std_logic_vector(2 downto 0);
-- output registers
inact: std_ulogic;
inbvalid: std_ulogic;
inbits: std_logic_vector(rxchunk-1 downto 0);
rxen: std_ulogic;
end record;
 
-- registers
signal r, rin: regs_type;
signal rrx, rrxin: rxregs_type;
 
-- force use of IOB flip-flops
attribute IOB: string;
attribute IOB of s_a_di0: signal is "TRUE";
attribute IOB of s_a_di1: signal is "TRUE";
attribute IOB of s_a_si0: signal is "TRUE";
attribute IOB of s_a_si1: signal is "TRUE";
 
begin
 
-- sample inputs on rising edge of rxclk
process (rxclk) is
begin
if rising_edge(rxclk) then
s_a_di0 <= spw_di;
s_a_si0 <= spw_si;
end if;
end process;
 
-- sample inputs on falling edge of rxclk
process (rxclk) is
begin
if falling_edge(rxclk) then
s_a_di1 <= spw_di;
s_a_si1 <= spw_si;
end if;
end process;
 
-- combinatorial process
process (r, rrx, rxen, s_a_di0, s_a_di1, s_a_si0, s_a_si1)
variable v: regs_type;
variable vrx: rxregs_type;
variable v_i: integer range 0 to 7;
variable v_tail: std_logic_vector(1 downto 0);
begin
v := r;
vrx := rrx;
v_i := 0;
v_tail := (others => '0');
 
-- ---- SAMPLE CLOCK DOMAIN ----
 
-- stage B: re-register input samples
vrx.b_di0 := s_a_di0;
vrx.b_di1 := s_a_di1;
vrx.b_xor0 := s_a_di0 xor s_a_si0;
vrx.b_si1 := s_a_si1;
 
-- stage C: decode data/strobe and detect valid bits
if (rrx.b_xor0 xor rrx.c_xor1) = '1' then
-- b_di0 is a valid new bit
vrx.c_bit(0) := rrx.b_di0;
else
-- skip b_di0 and try b_di1
vrx.c_bit(0) := rrx.b_di1;
end if;
vrx.c_bit(1) := rrx.b_di1;
vrx.c_val(0) := (rrx.b_xor0 xor rrx.c_xor1) or (rrx.b_di1 xor rrx.b_si1 xor rrx.b_xor0);
vrx.c_val(1) := (rrx.b_xor0 xor rrx.c_xor1) and (rrx.b_di1 xor rrx.b_si1 xor rrx.b_xor0);
vrx.c_xor1 := rrx.b_di1 xor rrx.b_si1;
 
-- Note:
-- c_val = "00" if no new bits are received
-- c_val = "01" if one new bit is received; the new bit is in c_bit(0)
-- c_val = "11" if two new bits are received
 
-- Note:
-- bufmark contains two '1' bits in neighbouring positions, marking
-- the positions that newly received bits will be written to.
 
-- Update the cyclic buffer.
for i in 0 to c_buflen-1 loop
-- update data bit at position (i)
if rrx.bufmark(i) = '1' then
if rrx.bufmark((i+1) mod rrx.bufmark'length) = '1' then
-- this is the first of the two marked positions;
-- put the first received bit here (if any)
vrx.bufdata(i) := rrx.c_bit(0);
else
-- this is the second of the two marked positions;
-- put the second received bit here (if any)
vrx.bufdata(i) := rrx.c_bit(1);
end if;
end if;
-- update marker at position (i)
if rrx.c_val(0) = '1' then
if rrx.c_val(1) = '1' then
-- shift two positions
vrx.bufmark(i) := rrx.bufmark((i+rrx.bufmark'length-2) mod rrx.bufmark'length);
else
-- shift one position
vrx.bufmark(i) := rrx.bufmark((i+rrx.bufmark'length-1) mod rrx.bufmark'length);
end if;
end if;
end loop;
 
-- Update "headlow", the least significant bits of the head position.
-- This is a binary counter from 0 to rxchunk-1, or from 0 to 1
-- if rxchunk = 1. If the counter overflows, "headptr" will be
-- updated in the next clock cycle.
case rxchunk is
when 1 | 2 =>
-- count from "00" to "01"
if rrx.c_val(1) = '1' then -- got two new bits
vrx.headlow(0) := rrx.headlow(0);
vrx.headinc := '1';
elsif rrx.c_val(0) = '1' then -- got one new bit
vrx.headlow(0) := not rrx.headlow(0);
vrx.headinc := rrx.headlow(0);
else -- got nothing
vrx.headlow(0) := rrx.headlow(0);
vrx.headinc := '0';
end if;
when 3 =>
-- count from "00" to "10"
if rrx.c_val(1) = '1' then -- got two new bits
case rrx.headlow is
when "00" => vrx.headlow := "10";
when "01" => vrx.headlow := "00";
when others => vrx.headlow := "01";
end case;
vrx.headinc := rrx.headlow(0) or rrx.headlow(1);
elsif rrx.c_val(0) = '1' then -- got one new bit
if rrx.headlow(1) = '1' then
vrx.headlow := "00";
vrx.headinc := '1';
else
vrx.headlow(0) := not rrx.headlow(0);
vrx.headlow(1) := rrx.headlow(0);
vrx.headinc := '0';
end if;
else -- got nothing
vrx.headlow := rrx.headlow;
vrx.headinc := '0';
end if;
when 4 =>
-- count from "00" to "11"
if rrx.c_val(1) = '1' then -- got two new bits
vrx.headlow(0) := rrx.headlow(0);
vrx.headlow(1) := not rrx.headlow(1);
vrx.headinc := rrx.headlow(1);
elsif rrx.c_val(0) = '1' then -- got one new bit
vrx.headlow(0) := not rrx.headlow(0);
vrx.headlow(1) := rrx.headlow(1) xor rrx.headlow(0);
vrx.headinc := rrx.headlow(0) and rrx.headlow(1);
else -- got nothing
vrx.headlow := rrx.headlow;
vrx.headinc := '0';
end if;
end case;
 
-- Update the gray-encoded head position.
if rrx.headinc = '1' then
case rrx.headptr is
when "00" => vrx.headptr := "01";
when "01" => vrx.headptr := "11";
when "11" => vrx.headptr := "10";
when others => vrx.headptr := "00";
end case;
end if;
 
-- Activity detection.
if rrx.c_val(0) = '1' then
vrx.bitcnt := gray_encode(
std_logic_vector(unsigned(gray_decode(rrx.bitcnt)) + 1));
end if;
 
-- Synchronize reset signal for rxclk domain.
if r.rxen = '0' then
vrx.reset := "11";
else
vrx.reset := "0" & rrx.reset(1);
end if;
 
-- Synchronous reset of rxclk domain.
if rrx.reset(0) = '1' then
vrx.bufmark := (0 => '1', 1 => '1', others => '0');
vrx.headptr := "00";
vrx.headlow := "00";
vrx.headinc := '0';
vrx.bitcnt := "000";
end if;
 
-- ---- SYSTEM CLOCK DOMAIN ----
 
-- Re-register cyclic buffer and head pointer in the system clock domain.
v.bufdata := rrx.bufdata;
v.headptr := rrx.headptr;
 
-- Increment tailptr if there was new data on the previous clock.
if r.inbvalid = '1' then
v.tailptr := std_logic_vector(unsigned(r.tailptr) + 1);
end if;
 
-- Compare tailptr to headptr to decide whether there is new data.
-- If the values are equal, we are about to read data which were not
-- yet released by the rxclk domain
-- Note: headptr is gray-coded while tailptr is normal binary.
if rxchunk = 1 then
-- headptr counts blocks of 2 bits while tailptr counts single bits
v_tail := v.tailptr(2 downto 1);
else
-- headptr and tailptr both count blocks of rxchunk bits
v_tail := v.tailptr(1 downto 0);
end if;
if (r.headptr(1) = v_tail(1)) and
((r.headptr(0) xor r.headptr(1)) = v_tail(0)) then
-- pointers have the same value
v.inbvalid := '0';
else
v.inbvalid := '1';
end if;
-- Multiplex bits from the cyclic buffer into the output register.
if rxen = '1' then
if rxchunk = 1 then
-- cyclic buffer contains 8 slots of 1 bit wide
v_i := to_integer(unsigned(v.tailptr));
v.inbits := r.bufdata(v_i downto v_i);
else
-- cyclic buffer contains 4 slots of rxchunk bits wide
v_i := to_integer(unsigned(v.tailptr(1 downto 0)));
v.inbits := r.bufdata(rxchunk*v_i+rxchunk-1 downto rxchunk*v_i);
end if;
end if;
 
-- Activity detection.
v.bitcnt := rrx.bitcnt;
v.bitcntp := r.bitcnt;
v.bitcntpp := r.bitcntp;
if rxen = '1' then
if r.bitcntp = r.bitcntpp then
v.inact := r.inbvalid;
else
v.inact := '1';
end if;
end if;
 
-- Synchronous reset of system clock domain.
if rxen = '0' then
v.tailptr := "000";
v.inact := '0';
v.inbvalid := '0';
v.inbits := (others => '0');
end if;
 
-- Register rxen to ensure glitch-free signal to rxclk domain
v.rxen := rxen;
 
-- drive outputs
inact <= r.inact;
inbvalid <= r.inbvalid;
inbits <= r.inbits;
 
-- update registers
rrxin <= vrx;
rin <= v;
 
end process;
 
-- update registers on rising edge of rxclk
process (rxclk) is
begin
if rising_edge(rxclk) then
rrx <= rrxin;
end if;
end process;
 
-- update registers on rising edge of system clock
process (clk) is
begin
if rising_edge(clk) then
r <= rin;
end if;
end process;
 
end architecture spwrecvfront_arch;
/trunk/rtl/vhdl/spwstream.vhd
0,0 → 1,544
--
-- SpaceWire core with character-stream interface.
--
-- This entity provides a SpaceWire core with a character-stream interface.
-- The interface provides means for connection initiation, sending and
-- receiving of N-Chars and TimeCodes, and error reporting.
--
-- This entity instantiates spwlink, spwrecv, spwxmit and one of the
-- spwrecvfront implementations. It also implements a receive FIFO and
-- a transmit FIFO.
--
-- The SpaceWire standard requires that each transceiver use an initial
-- signalling rate of 10 Mbit/s. This implies that the system clock frequency
-- must be a multiple of 10 MHz. See the datasheet for further details on
-- bitrates and clocking.
--
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.spwpkg.all;
 
entity spwstream is
 
generic (
-- System clock frequency in Hz.
-- This must be set to the frequency of "clk". It is used to setup
-- counters for reset timing, disconnect timeout and to transmit
-- at 10 Mbit/s during the handshake.
sysfreq: real;
 
-- Selection of a receiver front-end implementation.
rximpl: spw_implementation_type := impl_generic;
 
-- Maximum number of bits received per system clock
-- (must be 1 in case of impl_generic).
rxchunk: integer range 1 to 4 := 1;
 
-- Selection of a transmitter implementation.
tximpl: spw_implementation_type := impl_generic;
 
-- Size of the receive FIFO as the 2-logarithm of the number of bytes.
-- Must be at least 6 (64 bytes).
rxfifosize_bits: integer range 6 to 14 := 11;
 
-- Size of the transmit FIFO as the 2-logarithm of the number of bytes.
txfifosize_bits: integer range 2 to 14 := 11
);
 
port (
-- System clock.
clk: in std_logic;
 
-- Receiver sample clock (only for impl_fast)
rxclk: in std_logic;
 
-- Transmit clock (only for impl_fast)
txclk: in std_logic;
 
-- Synchronous reset (active-high).
rst: in std_logic;
 
-- Enables automatic link start on receipt of a NULL character.
autostart: in std_logic;
 
-- Enables link start once the Ready state is reached.
-- Without autostart or linkstart, the link remains in state Ready.
linkstart: in std_logic;
 
-- Do not start link (overrides linkstart and autostart) and/or disconnect
-- if the link is in state Run.
linkdis: in std_logic;
 
-- Scaling factor minus 1, used to scale the system clock into the transmission
-- signalling rate. The system clock is divided by (unsigned(divcnt) + 1).
-- Changing this signal will immediately change the transmission rate.
-- During link setup, the transmission rate is always 10 Mbit/s.
txdivcnt: in std_logic_vector(7 downto 0);
 
-- High for one clock cycle to request transmission of a TimeCode.
-- The request is registered inside the entity until it can be processed.
tick_in: in std_logic;
 
-- Control bits of the TimeCode to be sent. Must be valid while tick_in is high.
ctrl_in: in std_logic_vector(1 downto 0);
 
-- Counter value of the TimeCode to be sent. Must be valid while tick_in is high.
time_in: in std_logic_vector(5 downto 0);
 
-- Pulled high by the application to write an N-Char to the transmit
-- queue. If "txwrite" and "txrdy" are both high on the rising edge
-- of "clk", a character is added to the transmit queue.
-- This signal has no effect if "txrdy" is low.
txwrite: in std_logic;
 
-- Control flag to be sent with the next N_Char.
-- Must be valid while txwrite is high.
txflag: in std_logic;
 
-- Byte to be sent, or "00000000" for EOP or "00000001" for EEP.
-- Must be valid while txwrite is high.
txdata: in std_logic_vector(7 downto 0);
 
-- High if the entity is ready to accept an N-Char for transmission.
txrdy: out std_logic;
 
-- High if the transmission queue is at least half full.
txhalff: out std_logic;
 
-- High for one clock cycle if a TimeCode was just received.
tick_out: out std_logic;
 
-- Control bits of the last received TimeCode.
ctrl_out: out std_logic_vector(1 downto 0);
 
-- Counter value of the last received TimeCode.
time_out: out std_logic_vector(5 downto 0);
 
-- High if "rxflag" and "rxdata" contain valid data.
-- This signal is high unless the receive FIFO is empty.
rxvalid: out std_logic;
 
-- High if the receive FIFO is at least half full.
rxhalff: out std_logic;
 
-- High if the received character is EOP or EEP; low if the received
-- character is a data byte. Valid if "rxvalid" is high.
rxflag: out std_logic;
 
-- Received byte, or "00000000" for EOP or "00000001" for EEP.
-- Valid if "rxvalid" is high.
rxdata: out std_logic_vector(7 downto 0);
 
-- Pulled high by the application to accept a received character.
-- If "rxvalid" and "rxread" are both high on the rising edge of "clk",
-- a character is removed from the receive FIFO and "rxvalid", "rxflag"
-- and "rxdata" are updated.
-- This signal has no effect if "rxvalid" is low.
rxread: in std_logic;
 
-- High if the link state machine is currently in the Started state.
started: out std_logic;
 
-- High if the link state machine is currently in the Connecting state.
connecting: out std_logic;
 
-- High if the link state machine is currently in the Run state, indicating
-- that the link is fully operational. If none of started, connecting or running
-- is high, the link is in an initial state and the transmitter is not yet enabled.
running: out std_logic;
 
-- Disconnect detected in state Run. Triggers a reset and reconnect of the link.
-- This indication is auto-clearing.
errdisc: out std_logic;
 
-- Parity error detected in state Run. Triggers a reset and reconnect of the link.
-- This indication is auto-clearing.
errpar: out std_logic;
 
-- Invalid escape sequence detected in state Run. Triggers a reset and reconnect of
-- the link. This indication is auto-clearing.
erresc: out std_logic;
 
-- Credit error detected. Triggers a reset and reconnect of the link.
-- This indication is auto-clearing.
errcred: out std_logic;
 
-- Data In signal from SpaceWire bus.
spw_di: in std_logic;
 
-- Strobe In signal from SpaceWire bus.
spw_si: in std_logic;
 
-- Data Out signal to SpaceWire bus.
spw_do: out std_logic;
 
-- Strobe Out signal to SpaceWire bus.
spw_so: out std_logic
);
 
end entity spwstream;
 
architecture spwstream_arch of spwstream is
 
-- Convert boolean to std_logic.
type bool_to_logic_type is array(boolean) of std_ulogic;
constant bool_to_logic: bool_to_logic_type := (false => '0', true => '1');
 
-- Reset time (6.4 us) in system clocks
constant reset_time: integer := integer(sysfreq * 6.4e-6);
 
-- Disconnect time (850 ns) in system clocks
constant disconnect_time: integer := integer(sysfreq * 850.0e-9);
 
-- Initial tx clock scaler (10 Mbit).
constant default_divcnt: std_logic_vector(7 downto 0) :=
std_logic_vector(to_unsigned(integer(sysfreq / 10.0e6 - 1.0), 8));
 
-- Registers.
type regs_type is record
-- packet state
rxpacket: std_logic; -- '1' when receiving a packet
rxeep: std_logic; -- '1' when rx EEP character pending
txpacket: std_logic; -- '1' when transmitting a packet
txdiscard: std_logic; -- '1' when discarding a tx packet
-- FIFO pointers
rxfifo_raddr: std_logic_vector(rxfifosize_bits-1 downto 0);
rxfifo_waddr: std_logic_vector(rxfifosize_bits-1 downto 0);
txfifo_raddr: std_logic_vector(txfifosize_bits-1 downto 0);
txfifo_waddr: std_logic_vector(txfifosize_bits-1 downto 0);
-- FIFO state
rxfifo_rvalid: std_logic; -- '1' if s_rxfifo_rdata is valid
txfifo_rvalid: std_logic; -- '1' if s_txfifo_rdata is valid
rxfull: std_logic; -- '1' if RX fifo is full
rxhalff: std_logic; -- '1' if RX fifo is at least half full
txfull: std_logic; -- '1' if TX fifo is full
txhalff: std_logic; -- '1' if TX fifo is at least half full
rxroom: std_logic_vector(5 downto 0);
end record;
 
constant regs_reset: regs_type := (
rxpacket => '0',
rxeep => '0',
txpacket => '0',
txdiscard => '0',
rxfifo_raddr => (others => '0'),
rxfifo_waddr => (others => '0'),
txfifo_raddr => (others => '0'),
txfifo_waddr => (others => '0'),
rxfifo_rvalid => '0',
txfifo_rvalid => '0',
rxfull => '0',
rxhalff => '0',
txfull => '0',
txhalff => '0',
rxroom => (others => '0') );
 
signal r: regs_type := regs_reset;
signal rin: regs_type;
 
-- Interface signals to components.
signal recv_rxen: std_logic;
signal recvo: spw_recv_out_type;
signal recv_inact: std_logic;
signal recv_inbvalid: std_logic;
signal recv_inbits: std_logic_vector(rxchunk-1 downto 0);
signal xmiti: spw_xmit_in_type;
signal xmito: spw_xmit_out_type;
signal xmit_divcnt: std_logic_vector(7 downto 0);
signal linki: spw_link_in_type;
signal linko: spw_link_out_type;
 
-- Memory interface signals.
signal s_rxfifo_raddr: std_logic_vector(rxfifosize_bits-1 downto 0);
signal s_rxfifo_rdata: std_logic_vector(8 downto 0);
signal s_rxfifo_wen: std_logic;
signal s_rxfifo_waddr: std_logic_vector(rxfifosize_bits-1 downto 0);
signal s_rxfifo_wdata: std_logic_vector(8 downto 0);
signal s_txfifo_raddr: std_logic_vector(txfifosize_bits-1 downto 0);
signal s_txfifo_rdata: std_logic_vector(8 downto 0);
signal s_txfifo_wen: std_logic;
signal s_txfifo_waddr: std_logic_vector(txfifosize_bits-1 downto 0);
signal s_txfifo_wdata: std_logic_vector(8 downto 0);
 
begin
 
-- Instantiate link controller.
link_inst: spwlink
generic map (
reset_time => reset_time )
port map (
clk => clk,
rst => rst,
linki => linki,
linko => linko,
rxen => recv_rxen,
recvo => recvo,
xmiti => xmiti,
xmito => xmito );
 
-- Instantiate receiver.
recv_inst: spwrecv
generic map(
disconnect_time => disconnect_time,
rxchunk => rxchunk )
port map (
clk => clk,
rxen => recv_rxen,
recvo => recvo,
inact => recv_inact,
inbvalid => recv_inbvalid,
inbits => recv_inbits );
 
-- Instantiate transmitter.
xmit_sel0: if tximpl = impl_generic generate
xmit_inst: spwxmit
port map (
clk => clk,
rst => rst,
divcnt => xmit_divcnt,
xmiti => xmiti,
xmito => xmito,
spw_do => spw_do,
spw_so => spw_so );
end generate;
xmit_sel1: if tximpl = impl_fast generate
xmit_fast_inst: spwxmit_fast
port map (
clk => clk,
txclk => txclk,
rst => rst,
divcnt => xmit_divcnt,
xmiti => xmiti,
xmito => xmito,
spw_do => spw_do,
spw_so => spw_so );
end generate;
 
-- Instantiate receiver front-end.
recvfront_sel0: if rximpl = impl_generic generate
recvfront_generic_inst: spwrecvfront_generic
port map (
clk => clk,
rxen => recv_rxen,
inact => recv_inact,
inbvalid => recv_inbvalid,
inbits => recv_inbits,
spw_di => spw_di,
spw_si => spw_si );
end generate;
recvfront_sel1: if rximpl = impl_fast generate
recvfront_fast_inst: spwrecvfront_fast
generic map (
rxchunk => rxchunk )
port map (
clk => clk,
rxclk => rxclk,
rxen => recv_rxen,
inact => recv_inact,
inbvalid => recv_inbvalid,
inbits => recv_inbits,
spw_di => spw_di,
spw_si => spw_si );
end generate;
 
-- Instantiate RX memory.
rxmem: spwram
generic map (
abits => rxfifosize_bits,
dbits => 9 )
port map (
rclk => clk,
wclk => clk,
ren => '1',
raddr => s_rxfifo_raddr,
rdata => s_rxfifo_rdata,
wen => s_rxfifo_wen,
waddr => s_rxfifo_waddr,
wdata => s_rxfifo_wdata );
 
-- Instantiate TX memory.
txmem: spwram
generic map (
abits => txfifosize_bits,
dbits => 9 )
port map (
rclk => clk,
wclk => clk,
ren => '1',
raddr => s_txfifo_raddr,
rdata => s_txfifo_rdata,
wen => s_txfifo_wen,
waddr => s_txfifo_waddr,
wdata => s_txfifo_wdata );
 
-- Combinatorial process
process (r, linko, s_rxfifo_rdata, s_txfifo_rdata, rst, autostart, linkstart, linkdis, txdivcnt, tick_in, ctrl_in, time_in, txwrite, txflag, txdata, rxread) is
variable v: regs_type;
variable v_tmprxroom: unsigned(rxfifosize_bits-1 downto 0);
variable v_tmptxroom: unsigned(txfifosize_bits-1 downto 0);
begin
v := r;
v_tmprxroom := to_unsigned(0, v_tmprxroom'length);
v_tmptxroom := to_unsigned(0, v_tmptxroom'length);
 
-- Keep track of whether we are sending and/or receiving a packet.
if linko.rxchar = '1' then
-- got character
v.rxpacket := not linko.rxflag;
end if;
if linko.txack = '1' then
-- send character
v.txpacket := not s_txfifo_rdata(8);
end if;
if linko.running = '0' then
-- not connected
v.rxpacket := '0';
v.txpacket := '0';
end if;
 
-- Clear the discard flags when the link is explicitly disabled.
if linkdis = '1' then
v.rxeep := '0';
v.txdiscard := '0';
end if;
 
-- Update RX fifo pointers.
if (rxread = '1') and (r.rxfifo_rvalid = '1') then
-- read from fifo
v.rxfifo_raddr := std_logic_vector(unsigned(r.rxfifo_raddr) + 1);
end if;
if r.rxfull = '0' then
if (linko.rxchar = '1') or (r.rxeep = '1') then
-- write to fifo (received char or pending EEP)
v.rxfifo_waddr := std_logic_vector(unsigned(r.rxfifo_waddr) + 1);
end if;
v.rxeep := '0';
end if;
 
-- Keep track of whether the RX fifo contains valid data.
-- (use new value of rxfifo_raddr)
v.rxfifo_rvalid := bool_to_logic(v.rxfifo_raddr /= r.rxfifo_waddr);
 
-- Update room in RX fifo (use new value of rxfifo_waddr).
v_tmprxroom := unsigned(r.rxfifo_raddr) - unsigned(v.rxfifo_waddr) - 1;
v.rxfull := bool_to_logic(v_tmprxroom = 0);
v.rxhalff := not v_tmprxroom(v_tmprxroom'high);
if v_tmprxroom > 63 then
v.rxroom := (others => '1');
else
v.rxroom := std_logic_vector(v_tmprxroom(5 downto 0));
end if;
 
-- Update TX fifo pointers.
if (r.txfifo_rvalid = '1') and ((linko.txack = '1') or (r.txdiscard = '1')) then
-- read from fifo
v.txfifo_raddr := std_logic_vector(unsigned(r.txfifo_raddr) + 1);
if s_txfifo_rdata(8) = '1' then
v.txdiscard := '0'; -- got EOP/EEP, stop discarding data
end if;
end if;
if (r.txfull = '0') and (txwrite = '1') then
-- write to fifo
v.txfifo_waddr := std_logic_vector(unsigned(r.txfifo_waddr) + 1);
end if;
 
-- Keep track of whether the TX fifo contains valid data.
-- (use new value of txfifo_raddr)
v.txfifo_rvalid := bool_to_logic(v.txfifo_raddr /= r.txfifo_waddr);
 
-- Update room in TX fifo (use new value of both txfifo_waddr).
v_tmptxroom := unsigned(r.txfifo_raddr) - unsigned(v.txfifo_waddr) - 1;
v.txfull := bool_to_logic(v_tmptxroom = 0);
v.txhalff := not v_tmptxroom(v_tmptxroom'high);
-- If an error occurs, set a flag to discard the current packet.
if (linko.errdisc or linko.errpar or
linko.erresc or linko.errcred) = '1' then
v.rxeep := v.rxeep or v.rxpacket; -- use new value of rxpacket
v.txdiscard := v.txdiscard or r.txpacket;
v.rxpacket := '0';
v.txpacket := '0';
end if;
 
-- Drive control signals to RX fifo.
s_rxfifo_raddr <= v.rxfifo_raddr; -- using new value of rxfifo_raddr
s_rxfifo_wen <= (not r.rxfull) and (linko.rxchar or r.rxeep);
s_rxfifo_waddr <= r.rxfifo_waddr;
if r.rxeep = '1' then
s_rxfifo_wdata <= "100000001";
else
s_rxfifo_wdata <= linko.rxflag & linko.rxdata;
end if;
 
-- Drive control signals to TX fifo.
s_txfifo_raddr <= v.txfifo_raddr; -- using new value of txfifo_raddr
s_txfifo_wen <= (not r.txfull) and txwrite;
s_txfifo_waddr <= r.txfifo_waddr;
s_txfifo_wdata <= txflag & txdata;
 
-- Drive inputs to spwlink.
linki.autostart <= autostart;
linki.linkstart <= linkstart;
linki.linkdis <= linkdis;
linki.rxroom <= r.rxroom;
linki.tick_in <= tick_in;
linki.ctrl_in <= ctrl_in;
linki.time_in <= time_in;
linki.txwrite <= r.txfifo_rvalid and not r.txdiscard;
linki.txflag <= s_txfifo_rdata(8);
linki.txdata <= s_txfifo_rdata(7 downto 0);
 
-- Drive divcnt input to spwxmit.
if linko.running = '1' then
xmit_divcnt <= txdivcnt;
else
xmit_divcnt <= default_divcnt;
end if;
 
-- Drive outputs.
txrdy <= not r.txfull;
txhalff <= r.txhalff;
tick_out <= linko.tick_out;
ctrl_out <= linko.ctrl_out;
time_out <= linko.time_out;
rxvalid <= r.rxfifo_rvalid;
rxhalff <= r.rxhalff;
rxflag <= s_rxfifo_rdata(8);
rxdata <= s_rxfifo_rdata(7 downto 0);
started <= linko.started;
connecting <= linko.connecting;
running <= linko.running;
errdisc <= linko.errdisc;
errpar <= linko.errpar;
erresc <= linko.erresc;
errcred <= linko.errcred;
 
-- Reset.
if rst = '1' then
v.rxpacket := '0';
v.rxeep := '0';
v.txpacket := '0';
v.txdiscard := '0';
v.rxfifo_raddr := (others => '0');
v.rxfifo_waddr := (others => '0');
v.txfifo_raddr := (others => '0');
v.txfifo_waddr := (others => '0');
v.rxfifo_rvalid := '0';
v.txfifo_rvalid := '0';
end if;
 
-- Update registers.
rin <= v;
end process;
 
-- Update registers.
process (clk) is
begin
if rising_edge(clk) then
r <= rin;
end if;
end process;
 
end architecture spwstream_arch;
/trunk/rtl/vhdl/spwlink.vhd
0,0 → 1,282
--
-- SpaceWire Exchange Level Controller.
--
-- This entity implements exchange level aspects of the SpaceWire protocol.
-- It handles connection setup, error detection and flow control.
--
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.spwpkg.all;
 
entity spwlink is
 
generic (
-- Reset time expressed in system clock cycles.
-- Should be 6.4 us (5.82 us .. 7.2 us) according to the standard.
reset_time: integer
);
 
port (
-- System clock.
clk: in std_logic;
 
-- Synchronous reset (active-high).
-- Disconnects, resets error conditions, puts the link state machine
-- in state ErrorReset.
rst: in std_logic;
 
-- Link level inputs.
linki: in spw_link_in_type;
 
-- Link level outputs.
linko: out spw_link_out_type;
 
-- Receiver enable signal to spwrecv.
rxen: out std_logic;
 
-- Output signals from spwrecv.
recvo: in spw_recv_out_type;
 
-- Input signals for spwxmit.
xmiti: out spw_xmit_in_type;
 
-- Output signals from spwxmit.
xmito: in spw_xmit_out_type
);
 
end entity spwlink;
 
architecture spwlink_arch of spwlink is
 
-- Convert boolean to std_logic.
type bool_to_logic_type is array(boolean) of std_ulogic;
constant bool_to_logic: bool_to_logic_type := (false => '0', true => '1');
 
-- State machine.
type state_type is (
S_ErrorReset, S_ErrorWait, S_Ready, S_Started, S_Connecting, S_Run );
 
-- Registers
type regs_type is record
-- state machine
state: state_type;
-- credit accounting
tx_credit: unsigned(5 downto 0);
rx_credit: unsigned(5 downto 0);
errcred: std_ulogic;
-- reset timer
timercnt: unsigned(10 downto 0);
timerdone: std_ulogic;
-- signal to transmitter
xmit_fct_in: std_ulogic;
end record;
 
-- Initial state
constant regs_reset: regs_type := (
state => S_ErrorReset,
tx_credit => "000000",
rx_credit => "000000",
errcred => '0',
timercnt => to_unsigned(reset_time, 11),
timerdone => '0',
xmit_fct_in => '0' );
 
signal r: regs_type := regs_reset;
signal rin: regs_type;
 
begin
 
-- Combinatorial process
process (r, rst, linki, recvo, xmito) is
variable v: regs_type;
variable v_timerrst: std_logic;
begin
v := r;
v_timerrst := '0';
 
-- State machine.
case r.state is
 
when S_ErrorReset =>
-- Wait for timer.
if r.timercnt = 0 then
v.state := S_ErrorWait;
v_timerrst := '1';
end if;
v.errcred := '0';
v.xmit_fct_in := '0';
 
when S_ErrorWait =>
-- Wait for 2 timer periods.
if ((recvo.errdisc or recvo.errpar or recvo.erresc) = '1') or
((recvo.gotfct or recvo.tick_out or recvo.rxchar) = '1') then
v.state := S_ErrorReset; -- error, go back to reset
v_timerrst := '1';
elsif r.timercnt = 0 then
if r.timerdone = '1' then
v.state := S_Ready;
v_timerrst := '1';
end if;
end if;
 
when S_Ready =>
-- Wait for link start.
if ((recvo.errdisc or recvo.errpar or recvo.erresc) = '1') or
((recvo.gotfct or recvo.tick_out or recvo.rxchar) = '1') then
v.state := S_ErrorReset; -- error, go back to reset
v_timerrst := '1';
elsif (linki.linkdis = '0') and (r.xmit_fct_in = '1') and
((linki.linkstart or (linki.autostart and recvo.gotnull)) = '1') then
v.state := S_Started; -- link enabled; start sending NULL
v_timerrst := '1';
end if;
 
when S_Started =>
-- Wait for NULL.
if ((recvo.errdisc or recvo.errpar or recvo.erresc) = '1') or
((recvo.gotfct or recvo.tick_out or recvo.rxchar) = '1') or
((r.timercnt = 0) and r.timerdone = '1') then
v.state := S_ErrorReset; -- error, go back to reset
v_timerrst := '1';
elsif recvo.gotnull = '1' then
v.state := S_Connecting; -- received null, continue
v_timerrst := '1';
end if;
 
when S_Connecting =>
-- Wait for FCT.
if ((recvo.errdisc or recvo.errpar or recvo.erresc) = '1') or
((recvo.tick_out or recvo.rxchar) = '1') or
((r.timercnt = 0) and r.timerdone = '1') then
v.state := S_ErrorReset; -- error, go back to reset
v_timerrst := '1';
elsif recvo.gotfct = '1' then
v.state := S_Run; -- got FCT, init completed
end if;
 
when S_Run =>
-- All is well.
if ((recvo.errdisc or recvo.errpar or recvo.erresc) = '1') or
(r.errcred = '1') or
(linki.linkdis = '1') then
v.state := S_ErrorReset; -- error, go back to reset
v_timerrst := '1';
end if;
 
when others =>
v.state := S_ErrorReset; -- recover from invalid state
v_timerrst := '1';
 
end case;
 
-- Update credit counters.
if r.state = S_ErrorReset then
 
-- reset credit
v.tx_credit := to_unsigned(0, v.tx_credit'length);
v.rx_credit := to_unsigned(0, v.rx_credit'length);
 
else
 
-- update TX credit
if recvo.gotfct = '1' then
-- just received a FCT token
v.tx_credit := v.tx_credit + to_unsigned(8, v.tx_credit'length);
if r.tx_credit > 48 then
-- received too many FCT tokens
v.errcred := '1';
end if;
end if;
if xmito.txack = '1' then
-- just sent one byte
v.tx_credit := v.tx_credit - to_unsigned(1, v.tx_credit'length);
end if;
 
-- update RX credit after sending FCT
if xmito.fctack = '1' then
-- just sent a FCT token
v.rx_credit := v.rx_credit + to_unsigned(8, v.rx_credit'length);
end if;
 
-- decide about sending FCT tokens
v.xmit_fct_in := bool_to_logic( (v.rx_credit <= 48) and
(v.rx_credit + to_unsigned(8, v.rx_credit'length) <= unsigned(linki.rxroom)) );
 
-- update RX credit after receiving character
if recvo.rxchar = '1' then
-- just received a character
v.rx_credit := v.rx_credit - to_unsigned(1, v.rx_credit'length);
if r.rx_credit = 0 then
-- remote transmitter violated its credit
v.errcred := '1';
end if;
end if;
 
end if;
 
-- Update the initializaton reset timer.
if v_timerrst = '1' then
v.timercnt := to_unsigned(reset_time, v.timercnt'length);
v.timerdone := '0';
else
if r.timercnt = 0 then
v.timercnt := to_unsigned(reset_time, v.timercnt'length);
v.timerdone := '1';
else
v.timercnt := r.timercnt - 1;
end if;
end if;
 
-- Reset
if rst = '1' then
v := regs_reset;
end if;
 
-- Drive link level outputs.
linko.started <= bool_to_logic(r.state = S_Started);
linko.connecting <= bool_to_logic(r.state = S_Connecting);
linko.running <= bool_to_logic(r.state = S_Run);
linko.errdisc <= recvo.errdisc and bool_to_logic(r.state = S_Run);
linko.errpar <= recvo.errpar and bool_to_logic(r.state = S_Run);
linko.erresc <= recvo.erresc and bool_to_logic(r.state = S_Run);
linko.errcred <= r.errcred;
linko.txack <= xmito.txack;
linko.tick_out <= recvo.tick_out and bool_to_logic(r.state = S_Run);
linko.ctrl_out <= recvo.ctrl_out;
linko.time_out <= recvo.time_out;
linko.rxchar <= recvo.rxchar and bool_to_logic(r.state = S_Run);
linko.rxflag <= recvo.rxflag;
linko.rxdata <= recvo.rxdata;
 
-- Drive receiver inputs.
rxen <= bool_to_logic(r.state /= S_ErrorReset);
 
-- Drive transmitter input signals.
xmiti.txen <= bool_to_logic(r.state = S_Started or
r.state = S_Connecting or
r.state = S_Run);
xmiti.stnull <= bool_to_logic(r.state = S_Started);
xmiti.stfct <= bool_to_logic(r.state = S_Connecting);
xmiti.fct_in <= r.xmit_fct_in;
xmiti.tick_in <= linki.tick_in and bool_to_logic(r.state = S_Run);
xmiti.ctrl_in <= linki.ctrl_in;
xmiti.time_in <= linki.time_in;
xmiti.txwrite <= linki.txwrite and bool_to_logic(r.tx_credit /= 0);
xmiti.txflag <= linki.txflag;
xmiti.txdata <= linki.txdata;
 
-- Update registers.
rin <= v;
end process;
 
-- Update registers.
process (clk) is
begin
if rising_edge(clk) then
r <= rin;
end if;
end process;
 
end architecture spwlink_arch;
/trunk/rtl/vhdl/spwxmit_fast.vhd
0,0 → 1,706
--
-- SpaceWire Transmitter
--
-- This entity translates outgoing characters and tokens into
-- data-strobe signalling.
--
-- The output stage is driven by a separate transmission clock "txclk" which
-- will typically be faster than the system clock. The actual transmission
-- rate is determined by dividing the transmission clock by an integer factor.
--
-- The code is tuned for implementation on Xilinx Spartan-3.
--
-- Concept
-- -------
--
-- Logic in the system clock domain generates a stream of tokens to be
-- transmitted. These tokens are encoded as instances of the token_type
-- record. Tokens are queued in a two-slot FIFO buffer (r.token0 and r.token1)
-- with a 1-bit pointer (r.tokmux) pointing to the head of the queue.
-- When a token is pushed into the buffer, a flag register is flipped
-- (r.sysflip0 and r.sysflip1) to indicate to the txclk domain that the
-- buffer slot has been refilled.
--
-- The txclk domain pulls tokens from the FIFO buffer, flipping flag
-- registers (rtx.txflip0 and rtx.txflip1) to indicate to the system clock
-- domain that a token has been pulled. When the system clock domain detects
-- that a token has been consumed, it refills the buffer slot with a new
-- token (assuming that there are tokens waiting to be transmitted).
-- Whenever the FIFO buffer is empty, the txclk domain sends NULLs instead.
-- This can happen either when there are no tokens to send, or when the
-- system clock domain is late to refill the buffer.
--
-- Details
-- -------
--
-- Logic in the system clock domain accepts transmission requests through
-- the external interface of the entity. Pending requests are translated
-- into a stream of tokens. The tokens are pushed to the txclk domain through
-- the FIFO buffer as described above.
--
-- The data path through the txclk domain is divided into stages A through F
-- in a half-hearted attempt to keep things simple. Stage A is just a
-- 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
-- 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
-- stage E switches to a new token. If the previous token was ESC, stage B
-- skips a turn because stage C will already know what to do.
--
-- Stage C takes a token from stage B and translates it into a bit pattern.
-- Time codes and NULL tokens are broken into two separate tokens starting
-- with ESC. Stage C is triggered one clock after the shift buffer in
-- stage E drops to 3 tokens.
--
-- Stage D completes the task of translating tokens to bit patterns and
-- distinguishes between 10-bit and 4-bit tokens. It is not explicitly
-- triggered but simply follows stage C.
--
-- Stage E is the bit shift register. It shifts when "txclken" is high.
-- A one-hot counter keeps track of the number of bits remaining in
-- the register. When the register falls empty, it loads a new 10-bit or
-- 4-bit pattern as prepared by stage D. Stage E also computes parity.
--
-- Stage F performs data strobe encoding. When the transmitter is disabled,
-- the outputs of stage F fall to zero in a controlled way.
--
-- To generate the transmission bit clock, the txclk is divided by an
-- integer factor (divcnt+1) using an 8-bit down counter. The implementation
-- of this counter has become quite complicated in order to meet timing goals.
-- The counter consists of 4 blocks of two bits each (txclkcnt), with a
-- carry-save concept used between blocks (txclkcy). Detection of terminal
-- count (txclkdone) has a pipeline delay of two cycles. Therefore a separate
-- concept is used if the initial count is less than 2 (txdivnorm). This is
-- all glued together in the final assignment to txclken.
--
-- The initial count for txclk division (divcnt) comes from the system clock
-- domain and thus needs to be synchronized for use in the txclk domain.
-- To facilitate this, the system clock domain latches the value of divcnt
-- once every 6 sysclk cycles and sets a flag to indicate when the latched
-- value can safely be used by the txclk domain.
--
-- A tricky aspect of the design is the initial state of the txclk logic.
-- When the transmitter is enabled (txen goes high), the txclk logic starts
-- with the first ESC pattern already set up in stage D, and stage C ready
-- to produce the FCT part of the first NULL.
--
-- The following guidelines are used to get good timing for the txclk domain:
-- * The new value of a register depends on at most 4 inputs (single LUT),
-- or in a few cases on 5 inputs (two LUTs and F5MUX).
-- * Synchronous resets may be used, but only if the reset signal comes
-- directly from a register (no logic in set/reset path);
-- * Clock enables may be used, but only if the enable signal comes directly
-- from a register (no logic in clock enable path).
--
-- Synchronization issues
-- ----------------------
--
-- There is a two-slot FIFO buffer between the system and txclk domains.
-- After the txclk domain pulls a token from the buffer, the system clock
-- domain should ideally refill the buffer before the txclk domain again
-- tries to pull from the same buffer slot. If the refill occurs late,
-- the txclk domain needs to insert a NULL token which is inefficient
-- use of bandwidth.
--
-- Assuming the transmission consists of a stream of data characters,
-- 10 bits per character, there are exactly 2*10 bit periods between
-- successive reads from the same buffer slot by the txclk logic.
--
-- The time needed for the system clock logic to refill a buffer slot =
-- 1 txclk period (update of rtx.txflipN)
-- + 1 txclk period (routing delay between domains)
-- + 2 sysclk periods (synchronizer for txflipN)
-- + 1 sysclk period (refill buffer slot and update r.sysflipN)
-- + 1 txclk period (routing delay between domains)
-- + 2 txclk periods (synchronizer for sysflipN)
-- = 5 txclk periods + 3 sysclk periods
--
-- If for example txclk is 4 times as fast as sysclk, this amounts to
-- 5 txclk + 3 sysclk = 5 + 3*4 txclk = 17 txclk
-- is less than 20 bit periods even at maximum transmission rate, so
-- no problem there.
--
-- This is different when the data stream includes 4-bit tokens.
-- See the datasheet for an analysis of that case.
--
-- Implementation guidelines
-- -------------------------
--
-- To minimize clock skew, IOB flip-flops should be used to drive
-- spw_do and spw_so.
--
-- "txclk" must be at least as fast as the system clock;
-- "txclk" does not need to be phase-related to the system clock;
-- it is allowed for "txclk" to be equal to "clk".
--
-- The following timing constraints are needed:
-- * PERIOD constraint on the system clock;
-- * PERIOD constraint on "txclk";
-- * FROM-TO constraint from "txclk" to the system clock, equal to
-- one "txclk" period;
-- * FROM-TO constraint from the system clock to "txclk", equal to
-- one "txclk" period.
--
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.spwpkg.all;
 
entity spwxmit_fast is
 
port (
-- System clock.
clk: in std_logic;
 
-- Transmit clock.
txclk: in std_logic;
 
-- Synchronous reset (active-high)
-- Used asynchronously by fast clock domain (must be glitch-free).
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
);
 
-- Turn off FSM extraction to avoid synchronization problems.
attribute FSM_EXTRACT: string;
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;
 
architecture spwxmit_fast_arch of spwxmit_fast is
 
-- Convert boolean to std_logic.
type bool_to_logic_type is array(boolean) of std_ulogic;
constant bool_to_logic: bool_to_logic_type := (false => '0', true => '1');
 
-- Data records passed between clock domains.
type token_type is record
tick: std_ulogic; -- send time code
fct: std_ulogic; -- send FCT
flag: std_ulogic; -- send EOP or EEP
char: std_logic_vector(7 downto 0); -- character or time code
end record;
 
-- Registers in txclk domain
type txregs_type is record
-- sync to system clock domain
txflip0: 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
b_update: std_ulogic;
b_mux: std_ulogic;
b_txflip: std_ulogic;
b_valid: std_ulogic;
b_token: token_type;
-- stage C
c_update: std_ulogic;
c_esc: std_ulogic;
c_fct: std_ulogic;
c_bits: std_logic_vector(8 downto 0);
-- stage D
d_bits: std_logic_vector(8 downto 0);
d_cnt4: std_ulogic;
d_cnt10: std_ulogic;
-- stage E
e_valid: std_ulogic;
e_shift: std_logic_vector(9 downto 0);
e_count: std_logic_vector(9 downto 0);
e_parity: std_ulogic;
-- stage F
f_spwdo: std_ulogic;
f_spwso: std_ulogic;
-- tx clock enable logic
txclken: std_ulogic;
txclkpre: std_ulogic;
txclkcnt: std_logic_vector(7 downto 0);
txclkcy: std_logic_vector(2 downto 0);
txclkdone: std_logic_vector(1 downto 0);
txclkdiv: std_logic_vector(7 downto 0);
txdivnorm: std_ulogic;
txdivsafe: std_logic_vector(1 downto 0);
-- tx enable logic
txensync: std_logic_vector(1 downto 0);
end record;
 
-- Registers in system clock domain
type regs_type is record
-- sync status to txclk domain
txenreg: std_ulogic;
txdivreg: std_logic_vector(7 downto 0);
txdivnorm: std_ulogic;
txdivtmp: std_logic_vector(1 downto 0);
txdivsafe: std_ulogic;
-- data stream to txclk domain
sysflip0: std_ulogic;
sysflip1: std_ulogic;
token0: token_type;
token1: token_type;
tokmux: std_ulogic;
-- sync feedback from txclk domain
txflip0: std_logic_vector(1 downto 0);
txflip1: std_logic_vector(1 downto 0);
-- transmitter management
pend_fct: std_ulogic; -- '1' if an outgoing FCT 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_tick: std_ulogic; -- '1' if an outgoing time tick is pending
pend_time: std_logic_vector(7 downto 0); -- data bits of pending time tick
allow_fct: std_ulogic; -- '1' when allowed to send FCTs
allow_char: std_ulogic; -- '1' when allowed to send data and time
sent_fct: std_ulogic; -- '1' when at least one FCT token was sent
end record;
 
-- Initial state of system clock domain
constant regs_reset: regs_type := (
txenreg => '0',
txdivreg => (others => '0'),
txdivnorm => '0',
txdivtmp => "00",
txdivsafe => '0',
sysflip0 => '0',
sysflip1 => '0',
token0 => ( tick => '0', fct => '0', flag => '0', char => (others => '0') ),
token1 => ( tick => '0', fct => '0', flag => '0', char => (others => '0') ),
tokmux => '0',
txflip0 => "00",
txflip1 => "00",
pend_fct => '0',
pend_char => '0',
pend_data => (others => '0'),
pend_tick => '0',
pend_time => (others => '0'),
allow_fct => '0',
allow_char => '0',
sent_fct => '0' );
 
-- Registers
signal rtx: txregs_type;
signal rtxin: txregs_type;
signal r: regs_type := regs_reset;
signal rin: regs_type;
 
-- Reset synchronizer for txclk domain
signal s_tx_rst_sync: std_logic_vector(1 downto 0) := "11";
signal s_tx_reset: std_ulogic := '1';
 
-- Output flip-flops
signal s_spwdo: std_logic;
signal s_spwso: std_logic;
 
-- Force use of IOB flip-flops
attribute IOB: string;
attribute IOB of s_spwdo: signal is "TRUE";
attribute IOB of s_spwso: signal is "TRUE";
 
begin
 
-- Drive SpaceWire output signals
spw_do <= s_spwdo;
spw_so <= s_spwso;
 
-- Combinatorial process
process (r, rtx, rst, divcnt, xmiti, s_tx_reset) is
variable v: regs_type;
variable vtx: txregs_type;
variable v_needtoken: std_ulogic;
variable v_havetoken: std_ulogic;
variable v_token: token_type;
begin
v := r;
vtx := rtx;
v_needtoken := '0';
v_havetoken := '0';
v_token := ( tick => '0', fct => '0', flag => '0', char => (others => '0') );
 
-- ---- 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.
-- Update stage B three bit periods after updating stage C
-- (i.e. in time for the next update of stage C).
-- Do not update stage B if the last token from stage C was ESC;
-- stage C already knows what token to put after the ESC.
vtx.b_update := rtx.txclken and rtx.e_count(0) and (not rtx.c_esc);
if rtx.b_mux = '0' then
vtx.b_txflip := rtx.txflip0;
else
vtx.b_txflip := rtx.txflip1;
end if;
if rtx.b_update = '1' then
if rtx.b_mux = '0' then
-- get token from slot 0
vtx.b_valid := rtx.a_sysflip0(1) xor rtx.b_txflip;
vtx.b_token := r.token0;
-- update mux flag if we got a valid token
vtx.b_mux := rtx.a_sysflip0(1) xor rtx.b_txflip;
vtx.txflip0 := rtx.a_sysflip0(1);
vtx.txflip1 := rtx.txflip1;
else
-- get token from slot 1
vtx.b_valid := rtx.a_sysflip1(1) xor rtx.b_txflip;
vtx.b_token := r.token1;
-- update mux flag if we got a valid token
vtx.b_mux := not (rtx.a_sysflip1(1) xor rtx.b_txflip);
vtx.txflip0 := rtx.txflip0;
vtx.txflip1 := rtx.a_sysflip1(1);
end if;
end if;
 
-- Stage C: Prepare to transmit EOP, EEP or a data character.
vtx.c_update := rtx.txclken and rtx.e_count(3);
if rtx.c_update = '1' then
-- NULL is broken into two tokens: ESC + FCT
-- time codes are broken into two tokens: ESC + char
vtx.c_esc := (rtx.b_token.tick or (not rtx.b_valid)) and
(not rtx.c_esc);
vtx.c_fct := rtx.b_token.fct or (not rtx.b_valid);
if rtx.b_token.flag = '1' then
if rtx.b_token.char(0) = '0' then
-- prepare to send EOP
vtx.c_bits := "000000101"; -- EOP = P101
else
-- prepare to send EEP
vtx.c_bits := "000000011"; -- EEP = P110
end if;
else
-- prepare to send data char
vtx.c_bits := rtx.b_token.char & '0';
end if;
end if;
 
-- Stage D: Prepare to transmit FCT, ESC, or the stuff from stage C.
if rtx.c_esc = '1' then
-- prepare to send ESC
vtx.d_bits := "000000111"; -- ESC = P111
vtx.d_cnt4 := '1'; -- 3 bits + implicit parity bit
vtx.d_cnt10 := '0';
elsif rtx.c_fct = '1' then
-- prepare to send FCT
vtx.d_bits := "000000001"; -- FCT = P100
vtx.d_cnt4 := '1'; -- 3 bits + implicit parity bit
vtx.d_cnt10 := '0';
else
-- send the stuff from stage C.
vtx.d_bits := rtx.c_bits;
vtx.d_cnt4 := rtx.c_bits(0);
vtx.d_cnt10 := not rtx.c_bits(0);
end if;
 
-- Stage E: Shift register.
if rtx.txclken = '1' then
if rtx.e_count(0) = '1' then
-- reload shift register; output parity bit
vtx.e_valid := '1';
vtx.e_shift(vtx.e_shift'high downto 1) := rtx.d_bits;
vtx.e_shift(0) := not (rtx.e_parity xor rtx.d_bits(0));
vtx.e_count := rtx.d_cnt10 & "00000" & rtx.d_cnt4 & "000";
vtx.e_parity := rtx.d_bits(0);
else
-- shift bits to output; update parity bit
vtx.e_shift := '0' & rtx.e_shift(rtx.e_shift'high downto 1);
vtx.e_count := '0' & rtx.e_count(rtx.e_count'high downto 1);
vtx.e_parity := rtx.e_parity xor rtx.e_shift(1);
end if;
end if;
 
-- Stage F: Data/strobe encoding.
if rtx.txclken = '1' then
if rtx.e_valid = '1' then
-- output next data/strobe bits
vtx.f_spwdo := rtx.e_shift(0);
vtx.f_spwso := not (rtx.e_shift(0) xor rtx.f_spwdo xor rtx.f_spwso);
else
-- gentle reset of spacewire signals
vtx.f_spwdo := rtx.f_spwdo and rtx.f_spwso;
vtx.f_spwso := '0';
end if;
end if;
 
-- Generate tx clock enable
-- An 8-bit counter decrements on every clock. A txclken pulse is
-- produced 2 cycles after the counter reaches value 2. Counter reload
-- values of 0 and 1 are handled as special cases.
-- count down in blocks of two bits
vtx.txclkcnt(1 downto 0) := std_logic_vector(unsigned(rtx.txclkcnt(1 downto 0)) - 1);
vtx.txclkcnt(3 downto 2) := std_logic_vector(unsigned(rtx.txclkcnt(3 downto 2)) - unsigned(rtx.txclkcy(0 downto 0)));
vtx.txclkcnt(5 downto 4) := std_logic_vector(unsigned(rtx.txclkcnt(5 downto 4)) - unsigned(rtx.txclkcy(1 downto 1)));
vtx.txclkcnt(7 downto 6) := std_logic_vector(unsigned(rtx.txclkcnt(7 downto 6)) - unsigned(rtx.txclkcy(2 downto 2)));
-- propagate carry in blocks of two bits
vtx.txclkcy(0) := bool_to_logic(rtx.txclkcnt(1 downto 0) = "00");
vtx.txclkcy(1) := rtx.txclkcy(0) and bool_to_logic(rtx.txclkcnt(3 downto 2) = "00");
vtx.txclkcy(2) := rtx.txclkcy(1) and bool_to_logic(rtx.txclkcnt(5 downto 4) = "00");
-- detect value 2 in counter
vtx.txclkdone(0) := bool_to_logic(rtx.txclkcnt(3 downto 0) = "0010");
vtx.txclkdone(1) := bool_to_logic(rtx.txclkcnt(7 downto 4) = "0000");
-- trigger txclken
vtx.txclken := (rtx.txclkdone(0) and rtx.txclkdone(1)) or rtx.txclkpre;
vtx.txclkpre := (not rtx.txdivnorm) and ((not rtx.txclkpre) or (not rtx.txclkdiv(0)));
-- reload counter
if rtx.txclken = '1' then
vtx.txclkcnt := rtx.txclkdiv;
vtx.txclkcy := "000";
vtx.txclkdone := "00";
end if;
 
-- Synchronize txclkdiv
vtx.txdivsafe(0) := r.txdivsafe;
vtx.txdivsafe(1) := rtx.txdivsafe(0);
if rtx.txdivsafe(1) = '1' then
vtx.txclkdiv := r.txdivreg;
vtx.txdivnorm := r.txdivnorm;
end if;
 
-- Synchronize txen signal.
vtx.txensync(0) := r.txenreg;
vtx.txensync(1) := rtx.txensync(0);
 
-- Transmitter disabled.
if rtx.txensync(1) = '0' then
vtx.txflip0 := '0';
vtx.txflip1 := '0';
vtx.b_update := '0';
vtx.b_mux := '0';
vtx.b_valid := '0';
vtx.c_update := '0';
vtx.c_esc := '1'; -- need to send 2nd part of NULL
vtx.c_fct := '1';
vtx.d_bits := "000000111"; -- ESC = P111
vtx.d_cnt4 := '1'; -- 3 bits + implicit parity bit
vtx.d_cnt10 := '0';
vtx.e_valid := '0';
vtx.e_parity := '0';
vtx.e_count := (0 => '1', others => '0');
end if;
 
-- Reset.
if s_tx_reset = '1' then
vtx.f_spwdo := '0';
vtx.f_spwso := '0';
vtx.txensync := "00";
vtx.txclken := '0';
vtx.txclkpre := '1';
vtx.txclkcnt := (others => '0');
vtx.txclkdiv := (others => '0');
vtx.txdivnorm := '0';
end if;
 
-- ---- SYSTEM CLOCK DOMAIN ----
 
-- Hold divcnt and txen for use by txclk domain.
v.txdivtmp := std_logic_vector(unsigned(r.txdivtmp) - 1);
if r.txdivtmp = "00" then
if r.txdivsafe = '0' then
-- Latch the current value of divcnt and txen.
v.txdivsafe := '1';
v.txdivtmp := "01";
v.txdivreg := divcnt;
if unsigned(divcnt(divcnt'high downto 1)) = 0 then
v.txdivnorm := '0';
else
v.txdivnorm := '1';
end if;
v.txenreg := xmiti.txen;
else
-- Drop the txdivsafe flag but keep latched values.
v.txdivsafe := '0';
end if;
end if;
 
-- Pass falling edge of txen signal as soon as possible.
if xmiti.txen = '0' then
v.txenreg := '0';
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.
if xmiti.fct_in = '1' and r.allow_fct = '1' then
v.pend_fct := '1';
end if;
 
if xmiti.txen = '0' then
 
-- Transmitter disabled; reset state.
v.sysflip0 := '0';
v.sysflip1 := '0';
v.tokmux := '0';
v.pend_fct := '0';
v.pend_char := '0';
v.pend_tick := '0';
v.allow_fct := '0';
v.allow_char := '0';
v.sent_fct := '0';
 
else
 
-- Determine if a new token is needed.
if r.tokmux = '0' then
if r.sysflip0 = r.txflip0(1) then
v_needtoken := '1';
end if;
else
if r.sysflip1 = r.txflip1(1) then
v_needtoken := '1';
end if;
end if;
 
-- Prepare new token.
if r.allow_char = '1' and r.pend_tick = '1' then
-- prepare to send time code
v_token.tick := '1';
v_token.fct := '0';
v_token.flag := '0';
v_token.char := r.pend_time;
v_havetoken := '1';
if v_needtoken = '1' then
v.pend_tick := '0';
end if;
elsif r.allow_fct = '1' and (xmiti.fct_in = '1' or r.pend_fct = '1') then
-- prepare to send FCT
v_token.tick := '0';
v_token.fct := '1';
v_token.flag := '0';
v_havetoken := '1';
if v_needtoken = '1' then
v.pend_fct := '0';
v.sent_fct := '1';
end if;
elsif r.allow_char = '1' and r.pend_char = '1' then
-- prepare to send N-Char
v_token.tick := '0';
v_token.fct := '0';
v_token.flag := r.pend_data(8);
v_token.char := r.pend_data(7 downto 0);
v_havetoken := '1';
if v_needtoken = '1' then
v.pend_char := '0';
end if;
end if;
 
-- Put new token in slot.
if v_havetoken = '1' then
if r.tokmux = '0' then
if r.sysflip0 = r.txflip0(1) then
v.sysflip0 := not r.sysflip0;
v.token0 := v_token;
v.tokmux := '1';
end if;
else
if r.sysflip1 = r.txflip1(1) then
v.sysflip1 := not r.sysflip1;
v.token1 := v_token;
v.tokmux := '0';
end if;
end if;
end if;
 
-- Determine whether we are allowed to send FCTs and characters
v.allow_fct := not xmiti.stnull;
v.allow_char := (not xmiti.stnull) and (not xmiti.stfct) and r.sent_fct;
 
-- Store request for data transmission.
if xmiti.txwrite = '1' and r.allow_char = '1' and r.pend_char = '0' then
v.pend_char := '1';
v.pend_data := xmiti.txflag & xmiti.txdata;
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 of system clock domain.
if rst = '1' then
v := regs_reset;
end if;
 
-- Drive outputs.
-- Note: the outputs are combinatorially dependent on certain inputs.
 
-- Set fctack high if (FCT requested) and (FCTs allowed) AND
-- (no FCT pending)
xmito.fctack <= xmiti.fct_in and xmiti.txen and r.allow_fct and
(not r.pend_fct);
 
-- Set txrdy high if (character requested) AND (characters allowed) AND
-- (no character pending)
xmito.txack <= xmiti.txwrite and xmiti.txen and r.allow_char and
(not r.pend_char);
 
-- Update registers.
rin <= v;
rtxin <= vtx;
end process;
 
-- Synchronous process in txclk domain
process (txclk) is
begin
if rising_edge(txclk) then
-- drive spacewire output signals
s_spwdo <= rtx.f_spwdo;
s_spwso <= rtx.f_spwso;
-- update registers
rtx <= rtxin;
end if;
end process;
 
-- Synchronous process in system clock domain
process (clk) is
begin
if rising_edge(clk) then
-- update registers
r <= rin;
end if;
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;
/trunk/rtl/vhdl/spwram.vhd
0,0 → 1,58
--
-- Synchronous dual-port RAM with separate clocks for read and write ports.
-- The synthesizer for Xilinx Spartan-3 will infer Block RAM for this entity.
--
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
entity spwram is
 
generic (
abits: integer;
dbits: integer );
 
port (
rclk: in std_logic;
wclk: in std_logic;
ren: in std_logic;
raddr: in std_logic_vector(abits-1 downto 0);
rdata: out std_logic_vector(dbits-1 downto 0);
wen: in std_logic;
waddr: in std_logic_vector(abits-1 downto 0);
wdata: in std_logic_vector(dbits-1 downto 0) );
 
end entity spwram;
 
architecture spwram_arch of spwram is
 
type mem_type is array(0 to (2**abits - 1)) of
std_logic_vector(dbits-1 downto 0);
 
signal s_mem: mem_type;
 
begin
 
-- read process
process (rclk) is
begin
if rising_edge(rclk) then
if ren = '1' then
rdata <= s_mem(to_integer(unsigned(raddr)));
end if;
end if;
end process;
 
-- write process
process (wclk) is
begin
if rising_edge(wclk) then
if wen = '1' then
s_mem(to_integer(unsigned(waddr))) <= wdata;
end if;
end if;
end process;
 
end architecture;
 
/trunk/rtl/vhdl/spwrecv.vhd
0,0 → 1,266
--
-- SpaceWire Receiver
--
-- This entity decodes the sequence of incoming data bits into tokens.
-- Data bits are passed to this entity from the Receiver Front-end
-- in groups of rxchunk bits at a time.
--
-- The bitrate of the incoming SpaceWire signal must be strictly less
-- than rxchunk times the system clock frequency.
--
 
library ieee;
use ieee.std_logic_1164.all, ieee.numeric_std.all;
use work.spwpkg.all;
 
entity spwrecv is
 
generic (
-- Disconnect timeout, expressed in system clock cycles.
-- Should be 850 ns (727 ns .. 1000 ns) according to the standard.
disconnect_time: integer range 1 to 255;
 
-- Nr of bits sampled per system clock.
rxchunk: integer range 1 to 4
);
 
port (
-- System clock.
clk: in std_logic;
 
-- High to enable receiver; low to disable and reset receiver.
rxen: in std_logic;
 
-- Output signals to spwlink.
recvo: out spw_recv_out_type;
 
-- High if there has been recent activity on the input lines.
inact: in std_logic;
 
-- High if inbits contains a valid group of received bits.
inbvalid: in std_logic;
 
-- Received bits from receiver front-end.
inbits: in std_logic_vector(rxchunk-1 downto 0)
);
 
end entity spwrecv;
 
architecture spwrecv_arch of spwrecv is
 
-- registers
type regs_type is record
-- receiver state
bit_seen: std_ulogic; -- got a bit transition
null_seen: std_ulogic; -- got a NULL token
-- input shift register
bitshift: std_logic_vector(8 downto 0);
bitcnt: std_logic_vector(9 downto 0); -- one-hot counter
-- parity flag
parity: std_ulogic;
-- decoding
control: std_ulogic; -- next code is control code
escaped: std_ulogic; -- last code was ESC
-- output registers
gotfct: std_ulogic;
tick_out: std_ulogic;
rxchar: std_ulogic;
rxflag: std_ulogic;
timereg: std_logic_vector(7 downto 0);
datareg: std_logic_vector(7 downto 0);
-- disconnect timer
disccnt: unsigned(7 downto 0);
-- error flags
errpar: std_ulogic;
erresc: std_ulogic;
end record;
 
-- Initial state
constant regs_reset: regs_type := (
bit_seen => '0',
null_seen => '0',
bitshift => (others => '1'),
bitcnt => (others => '0'),
parity => '0',
control => '0',
escaped => '0',
gotfct => '0',
tick_out => '0',
rxchar => '0',
rxflag => '0',
timereg => (others => '0'),
datareg => (others => '0'),
disccnt => "00000000",
errpar => '0',
erresc => '0' );
 
-- registers
signal r: regs_type := regs_reset;
signal rin: regs_type;
 
begin
 
-- combinatorial process
process (r, rxen, inact, inbvalid, inbits)
variable v: regs_type;
variable v_inbit: std_ulogic;
begin
v := r;
v_inbit := '0';
 
-- disconnect timer
if inact = '1' then
-- activity on input; reset timer
v.disccnt := to_unsigned(disconnect_time, v.disccnt'length);
elsif r.disccnt /= 0 then
-- count down
v.disccnt := r.disccnt - 1;
end if;
 
-- assume no new token
v.gotfct := '0';
v.tick_out := '0';
v.rxchar := '0';
 
if inbvalid = '1' then
 
-- process incoming bits
for i in 0 to rxchunk-1 loop
v_inbit := inbits(i);
 
-- got a bit transition
v.bit_seen := '1';
 
if v.bitcnt(0) = '1' then
-- received new token
if (v.parity xor v_inbit) = '0' then
-- Parity check failed.
v.errpar := '1';
else
if v.control = '1' then
-- received control code
case v.bitshift(7 downto 6) is
when "00" => -- FCT or NULL
v.gotfct := not r.escaped;
v.escaped := '0';
when "10" => -- EOP
if r.escaped = '1' then
v.erresc := '1';
end if;
v.escaped := '0';
v.rxchar := not r.escaped;
v.rxflag := '1';
v.datareg := "00000000";
when "01" => -- EEP
if r.escaped = '1' then
v.erresc := '1';
end if;
v.escaped := '0';
v.rxchar := not r.escaped;
v.rxflag := '1';
v.datareg := "00000001";
when others => -- ESC
if r.escaped = '1' then
v.erresc := '1';
end if;
v.escaped := '1';
end case;
else
-- received 8-bit character
if r.escaped = '1' then
-- received Time-Code
v.tick_out := '1';
v.timereg := v.bitshift(7 downto 0);
else
-- received data character
v.rxflag := '0';
v.rxchar := '1';
v.datareg := v.bitshift(7 downto 0);
end if;
v.escaped := '0';
end if;
end if;
-- prepare for next code
v.parity := '0';
v.control := v_inbit;
if v_inbit = '1' then
-- next word will be control code.
v.bitcnt := (3 => '1', others => '0');
else
-- next word will be a data byte.
v.bitcnt := (9 => '1', others => '0');
end if;
else
-- wait until next code is completely received;
-- accumulate parity
v.bitcnt := '0' & v.bitcnt(9 downto 1);
v.parity := v.parity xor v_inbit;
end if;
 
-- detect first NULL
if v.null_seen = '0' then
if v.bitshift = "000101110" then
-- got first NULL pattern
v.null_seen := '1';
v.control := v_inbit; -- should always be '1'
v.parity := '0';
v.bitcnt := (3 => '1', others => '0');
end if;
end if;
 
-- shift new bit into register.
v.bitshift := v_inbit & v.bitshift(v.bitshift'high downto 1);
 
end loop;
end if;
 
-- synchronous reset
if rxen = '0' then
v.bit_seen := '0';
v.null_seen := '0';
v.bitshift := "111111111";
v.bitcnt := (others => '0');
v.gotfct := '0';
v.tick_out := '0';
v.rxchar := '0';
v.rxflag := '0';
v.escaped := '0';
v.timereg := "00000000";
v.datareg := "00000000";
v.disccnt := to_unsigned(0, v.disccnt'length);
v.errpar := '0';
v.erresc := '0';
end if;
 
-- drive outputs
recvo.gotbit <= r.bit_seen;
recvo.gotnull <= r.null_seen;
recvo.gotfct <= r.gotfct;
recvo.tick_out <= r.tick_out;
recvo.ctrl_out <= r.timereg(7 downto 6);
recvo.time_out <= r.timereg(5 downto 0);
recvo.rxchar <= r.rxchar;
recvo.rxflag <= r.rxflag;
recvo.rxdata <= r.datareg;
if r.bit_seen = '1' and r.disccnt = 0 then
recvo.errdisc <= '1';
else
recvo.errdisc <= '0';
end if;
recvo.errpar <= r.errpar;
recvo.erresc <= r.erresc;
 
-- update registers
rin <= v;
 
end process;
 
-- update registers on rising edge of system clock
process (clk) is
begin
if rising_edge(clk) then
r <= rin;
end if;
end process;
 
end architecture spwrecv_arch;
/trunk/rtl/vhdl/spwxmit.vhd
0,0 → 1,249
--
-- 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;
/trunk/rtl/vhdl/spwpkg.vhd
0,0 → 1,393
--
-- SpaceWire VHDL package
--
 
library ieee;
use ieee.std_logic_1164.all;
 
package spwpkg is
 
 
-- Indicates a platform-specific implementation.
type spw_implementation_type is ( impl_generic, impl_fast );
 
 
-- Input signals to spwlink.
type spw_link_in_type is record
 
-- Enables automatic link start on receipt of a NULL character.
autostart: std_logic;
 
-- Enables link start once the Ready state is reached.
-- Without either "autostart" or "linkstart", the link remains in
-- state Ready.
linkstart: std_logic;
 
-- Do not start link (overrides "linkstart" and "autostart") and/or
-- disconnect the currently running link.
linkdis: std_logic;
 
-- Number of bytes available in the receive buffer. Used to for
-- flow-control operation. At least 8 bytes must be available
-- initially, otherwise the link can not start. Values larger than 63
-- are irrelevant and may be presented as 63. The available room may
-- decrease by one byte due to the reception of an N-Char; in that case
-- the "rxroom" signal must be updated on the clock following the clock
-- on which "rxchar" is high. Under no other circumstances may "rxroom"
-- be decreased.
rxroom: std_logic_vector(5 downto 0);
 
-- High for one clock cycle to request transmission of a TimeCode.
-- The request is registered inside spwxmit until it can be processed.
tick_in: std_logic;
 
-- Control bits of the TimeCode to be sent.
-- Must be valid while tick_in is high.
ctrl_in: std_logic_vector(1 downto 0);
 
-- Counter value of the TimeCode to be sent.
-- Must be valid while tick_in is high.
time_in: std_logic_vector(5 downto 0);
 
-- Requests transmission of an N-Char.
-- Keep this signal high until confirmed by "txack".
txwrite: std_logic;
 
-- Control flag to be sent with the next N-Char.
-- Must be valid while "txwrite" is high.
txflag: std_logic;
 
-- Byte to be sent, or "00000000" for EOP or "00000001" for EEP.
-- Must be valid while "txwrite" is high.
txdata: std_logic_vector(7 downto 0);
end record;
 
 
-- Output signals from spwlink.
type spw_link_out_type is record
 
-- High if the link state machine is currently in state Started.
started: std_logic;
 
-- High if the link state machine is currently in state Connecting.
connecting: std_logic;
 
-- High if the link state machine is currently in state Run.
running: std_logic;
 
-- Disconnect detected in state Run. Triggers a reset and reconnect.
-- This indication is auto-clearing.
errdisc: std_logic;
 
-- Parity error detected in state Run. Triggers a reset and reconnect.
-- This indication is auto-clearing.
errpar: std_logic;
 
-- Invalid escape sequence detected in state Run.
-- Triggers a reset and reconnect; auto-clearing.
erresc: std_logic;
 
-- Credit error detected. Triggers a reset and reconnect.
-- This indication is auto-clearing.
errcred: std_logic;
 
-- High to confirm the transmission of an N-Char.
-- This is a Wishbone-style handshake signal. It has a combinatorial
-- dependency on "txwrite".
txack: std_logic;
 
-- High for one clock cycle if a TimeCode was just received.
-- Verification of the TimeCode as described in 8.12.2 of ECSS-E-50
-- is not implemented; all received timecodes are reported.
tick_out: std_logic;
 
-- Control bits of last received TimeCode.
ctrl_out: std_logic_vector(1 downto 0);
 
-- Counter value of last received TimeCode.
time_out: std_logic_vector(5 downto 0);
 
-- High for one clock cycle if an N-Char (data byte or EOP or EEP) was
-- just received. The data bits must be accepted immediately from
-- "rxflag" and "rxdata".
rxchar: std_logic;
 
-- High if the received character is EOP or EEP, low if it is a data
-- byte. Valid when "rxchar" is high.
rxflag: std_logic;
 
 
-- Received byte, or "00000000" for EOP or "00000001" for EEP.
-- Valid when "rxchar" is high.
rxdata: std_logic_vector(7 downto 0);
end record;
 
 
-- Output signals from spwrecv to spwlink.
type spw_recv_out_type is record
 
-- High if at least one signal change was seen since enable.
-- Resets to low when rxen is low.
gotbit: std_logic;
 
-- High if at least one valid NULL pattern was detected since enable.
-- Resets to low when rxen is low.
gotnull: std_logic;
 
-- High for one clock cycle if an FCT token was just received.
gotfct: std_logic;
 
-- High for one clock cycle if a TimeCode was just received.
tick_out: std_logic;
 
-- Control bits of last received TimeCode.
ctrl_out: std_logic_vector(1 downto 0);
 
-- Counter value of last received TimeCode.
time_out: std_logic_vector(5 downto 0);
 
-- High for one clock cycle if an N-Char (data byte or EOP/EEP) was just received.
rxchar: std_logic;
 
-- High if rxchar is high and the received character is EOP or EEP.
-- Low if rxchar is high and the received character is a data byte.
rxflag: std_logic;
 
-- Received byte, or "00000000" for EOP or "00000001" for EEP.
-- Valid when "rxchar" is high.
rxdata: std_logic_vector(7 downto 0);
 
-- Disconnect detected (after a signal change was seen).
-- Resets to low when rxen is low or when a signal change is seen.
errdisc: std_logic;
 
-- Parity error detected (after a valid NULL pattern was seen).
-- Sticky; resets to low when rxen is low.
errpar: std_logic;
 
-- Escape sequence error detected (after a valid NULL pattern was seen).
-- Sticky; resets to low when rxen is low.
erresc: std_logic;
end record;
 
 
-- Input signals to spwxmit from spwlink.
type spw_xmit_in_type is record
 
-- High to enable transmitter; low to disable and reset transmitter.
txen: std_logic;
 
-- Indicates that only NULL characters may be transmitted.
stnull: std_logic;
 
-- Indicates that only NULL and/or FCT characters may be transmitted.
stfct: std_logic;
 
-- Requests transmission of an FCT character.
-- Keep this signal high until confirmed by "fctack".
fct_in: std_logic;
 
-- High for one clock cycle to request transmission of a TimeCode.
-- The request is registered inside spwxmit until it can be processed.
tick_in: std_logic;
 
-- Control bits of the TimeCode to be sent.
-- Must be valid while "tick_in" is high.
ctrl_in: std_logic_vector(1 downto 0);
 
-- Counter value of the TimeCode to be sent.
-- Must be valid while "tick_in" is high.
time_in: std_logic_vector(5 downto 0);
 
-- Request transmission of an N-Char.
-- Keep this signal high until confirmed by "txack".
txwrite: std_logic;
 
-- Control flag to be sent with the next N-Char.
-- Must be valid while "txwrite" is high.
txflag: std_logic;
 
-- Byte to send, or "00000000" for EOP or "00000001" for EEP.
-- Must be valid while "txwrite" is high.
txdata: std_logic_vector(7 downto 0);
end record;
 
 
-- Output signals from spwxmit to spwlink.
type spw_xmit_out_type is record
 
-- High to confirm transmission on an FCT character.
-- This is a Wishbone-style handshaking signal; it is combinatorially
-- dependent on "fct_in".
fctack: std_logic;
 
-- High to confirm transmission of an N-Char.
-- This is a Wishbone-style handshaking signal; it is combinatorially
-- dependent on both "fct_in" and "txwrite".
txack: std_logic;
end record;
 
 
-- Character-stream interface
component spwstream is
generic (
sysfreq: real; -- clk freq in Hz
rximpl: spw_implementation_type := impl_generic;
rxchunk: integer range 1 to 4 := 1; -- max bits per clk
tximpl: spw_implementation_type := impl_generic;
rxfifosize_bits: integer range 6 to 14 := 11; -- rx fifo size
txfifosize_bits: integer range 2 to 14 := 11 -- tx fifo size
);
port (
clk: in std_logic; -- system clock
rxclk: in std_logic; -- receiver sample clock
txclk: in std_logic; -- transmit clock
rst: in std_logic; -- synchronous reset
autostart: in std_logic; -- automatic link start
linkstart: in std_logic; -- forced link start
linkdis: in std_logic; -- stop link
txdivcnt: in std_logic_vector(7 downto 0); -- tx scale factor
tick_in: in std_logic; -- request timecode xmit
ctrl_in: in std_logic_vector(1 downto 0);
time_in: in std_logic_vector(5 downto 0);
txwrite: in std_logic; -- request character xmit
txflag: in std_logic; -- control flag of tx char
txdata: in std_logic_vector(7 downto 0);
txrdy: out std_logic; -- room in tx fifo
txhalff: out std_logic; -- tx fifo half full
tick_out: out std_logic; -- timecode received
ctrl_out: out std_logic_vector(1 downto 0);
time_out: out std_logic_vector(5 downto 0);
rxvalid: out std_logic; -- rx fifo not empty
rxhalff: out std_logic; -- rx fifo half full
rxflag: out std_logic; -- control flag of rx char
rxdata: out std_logic_vector(7 downto 0);
rxread: in std_logic; -- accept rx character
started: out std_logic; -- link in Started state
connecting: out std_logic; -- link in Connecting state
running: out std_logic; -- link in Run state
errdisc: out std_logic; -- disconnect error
errpar: out std_logic; -- parity error
erresc: out std_logic; -- escape error
errcred: out std_logic; -- credit error
spw_di: in std_logic;
spw_si: in std_logic;
spw_do: out std_logic;
spw_so: out std_logic
);
end component spwstream;
 
 
-- Link Level Interface
component spwlink is
generic (
reset_time: integer -- reset time in clocks (6.4 us)
);
port (
clk: in std_logic; -- system clock
rst: in std_logic; -- synchronous reset (active-high)
linki: in spw_link_in_type;
linko: out spw_link_out_type;
rxen: out std_logic;
recvo: in spw_recv_out_type;
xmiti: out spw_xmit_in_type;
xmito: in spw_xmit_out_type
);
end component spwlink;
 
 
-- Receiver
component spwrecv is
generic (
disconnect_time: integer range 1 to 255; -- disconnect period in system clock cycles
rxchunk: integer range 1 to 4 -- nr of bits per system clock
);
port (
clk: in std_logic; -- system clock
rxen: in std_logic; -- receiver enabled
recvo: out spw_recv_out_type;
inact: in std_logic;
inbvalid: in std_logic;
inbits: in std_logic_vector(rxchunk-1 downto 0)
);
end component spwrecv;
 
 
-- Transmitter (generic implementation)
component spwxmit is
port (
clk: in std_logic; -- system clock
rst: in std_logic; -- synchronous reset (active-high)
divcnt: in std_logic_vector(7 downto 0);
xmiti: in spw_xmit_in_type;
xmito: out spw_xmit_out_type;
spw_do: out std_logic; -- tx data to SPW bus
spw_so: out std_logic -- tx strobe to SPW bus
);
end component spwxmit;
 
 
-- Transmitter (separate tx clock domain)
component spwxmit_fast is
port (
clk: in std_logic; -- system clock
txclk: in std_logic; -- transmit clock
rst: in std_logic; -- synchronous reset (active-high)
divcnt: in std_logic_vector(7 downto 0);
xmiti: in spw_xmit_in_type;
xmito: out spw_xmit_out_type;
spw_do: out std_logic; -- tx data to SPW bus
spw_so: out std_logic -- tx strobe to SPW bus
);
end component spwxmit_fast;
 
 
-- Front-end for SpaceWire Receiver (generic implementation)
component spwrecvfront_generic is
port (
clk: in std_logic; -- system clock
rxen: in std_logic; -- high to enable receiver
inact: out std_logic; -- high if activity on input
inbvalid: out std_logic; -- high if inbits contains a valid received bit
inbits: out std_logic_vector(0 downto 0); -- received bit
spw_di: in std_logic; -- Data In signal from SpaceWire bus
spw_si: in std_logic -- Strobe In signal from SpaceWire bus
);
end component spwrecvfront_generic;
 
 
-- Front-end for SpaceWire Receiver (separate rx clock domain)
component spwrecvfront_fast is
generic (
rxchunk: integer range 1 to 4 -- max number of bits per system clock
);
port (
clk: in std_logic; -- system clock
rxclk: in std_logic; -- sample clock (DDR)
rxen: in std_logic; -- high to enable receiver
inact: out std_logic; -- high if activity on input
inbvalid: out std_logic; -- high if inbits contains a valid group of received bits
inbits: out std_logic_vector(rxchunk-1 downto 0); -- received bits
spw_di: in std_logic; -- Data In signal from SpaceWire bus
spw_si: in std_logic -- Strobe In signal from SpaceWire bus
);
end component spwrecvfront_fast;
 
 
-- Synchronous dual-port memory.
component spwram is
generic (
abits: integer;
dbits: integer );
port (
rclk: in std_logic;
wclk: in std_logic;
ren: in std_logic;
raddr: in std_logic_vector(abits-1 downto 0);
rdata: out std_logic_vector(dbits-1 downto 0);
wen: in std_logic;
waddr: in std_logic_vector(abits-1 downto 0);
wdata: in std_logic_vector(dbits-1 downto 0) );
end component spwram;
 
end package;
/trunk/rtl/vhdl/streamtest.vhd
0,0 → 1,442
--
-- Test application for spwstream.
--
-- This entity implements one spwstream instance with SpaceWire signals
-- routed to external ports. The SpaceWire port is assumed to be looped back
-- to itself externally, either directly (tx pins wired to rx pins) or
-- through a foreigh SpaceWire device which is programmed to echo anything
-- it receives.
--
-- This entity submits a series of test patterns to the transmit side of
-- spwstream. At the same time it monitors the receive side of spwstream
-- and verifies that received data matches the transmitted data pattern.
--
-- Link mode and tx bit rate may be programmed through digital inputs
-- (presumably connected to switches or buttons). Link state and progress of
-- the test are reported through digital outputs (presumably connected to
-- LEDs).
--
-- Note: there is no check on the integrity of the first packet received
-- after the link goes up.
--
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.spwpkg.all;
 
entity streamtest is
 
generic (
-- System clock frequency in Hz.
sysfreq: real;
 
-- 2-log of division factor from system clock freq to timecode freq.
tickdiv: integer range 12 to 24 := 20;
 
-- Receiver front-end implementation.
rximpl: spw_implementation_type := impl_generic;
 
-- Maximum number of bits received per system clock (impl_fast only).
rxchunk: integer range 1 to 4 := 1;
 
-- Transmitter implementation.
tximpl: spw_implementation_type := impl_generic;
 
-- Size of receive FIFO.
rxfifosize_bits: integer range 6 to 14 := 11;
 
-- Size of transmit FIFO.
txfifosize_bits: integer range 2 to 14 := 11 );
 
port (
-- System clock.
clk: in std_logic;
 
-- Receiver sample clock (only for impl_fast).
rxclk: in std_logic;
 
-- Transmit clock (only for impl_fast).
txclk: in std_logic;
 
-- Synchronous reset (active-high).
rst: in std_logic;
 
-- Enables spontaneous link start.
linkstart: in std_logic;
 
-- Enables automatic link start on receipt of a NULL token.
autostart: in std_logic;
 
-- Do not start link and/or disconnect current link.
linkdisable: in std_logic;
 
-- Enable sending test patterns to spwstream.
senddata: in std_logic;
 
-- Enable sending time codes to spwstream.
sendtick: in std_logic;
 
-- Scaling factor minus 1 for TX bitrate.
txdivcnt: in std_logic_vector(7 downto 0);
 
-- Link in state Started.
linkstarted: out std_logic;
 
-- Link in state Connecting.
linkconnecting: out std_logic;
 
-- Link in state Run.
linkrun: out std_logic;
 
-- Link error (one cycle pulse, not directly suitable for LED)
linkerror: out std_logic;
 
-- High when taking a byte from the receive FIFO.
gotdata: out std_logic;
 
-- Incorrect or unexpected data received (sticky).
dataerror: out std_logic;
 
-- Incorrect or unexpected time code received (sticky).
tickerror: out std_logic;
 
-- SpaceWire signals.
spw_di: in std_logic;
spw_si: in std_logic;
spw_do: out std_logic;
spw_so: out std_logic );
 
end entity streamtest;
 
architecture streamtest_arch of streamtest is
 
-- Update 16-bit maximum length LFSR by 8 steps
function lfsr16(x: in std_logic_vector) return std_logic_vector is
variable y: std_logic_vector(15 downto 0);
begin
-- poly = x^16 + x^14 + x^13 + x^11 + 1
-- tap positions = x(0), x(2), x(3), x(5)
y(7 downto 0) := x(15 downto 8);
y(15 downto 8) := x(7 downto 0) xor x(9 downto 2) xor x(10 downto 3) xor x(12 downto 5);
return y;
end function;
 
-- Sending side state.
type tx_state_type is ( txst_idle, txst_prepare, txst_data );
 
-- Receiving side state.
type rx_state_type is ( rxst_idle, rxst_data );
 
-- Registers.
type regs_type is record
tx_state: tx_state_type;
tx_timecnt: std_logic_vector((tickdiv-1) downto 0);
tx_quietcnt: std_logic_vector(15 downto 0);
tx_pktlen: std_logic_vector(15 downto 0);
tx_lfsr: std_logic_vector(15 downto 0);
tx_enabledata: std_ulogic;
rx_state: rx_state_type;
rx_quietcnt: std_logic_vector(15 downto 0);
rx_enabledata: std_ulogic;
rx_gottick: std_ulogic;
rx_expecttick: std_ulogic;
rx_expectglitch: unsigned(5 downto 0);
rx_badpacket: std_ulogic;
rx_pktlen: std_logic_vector(15 downto 0);
rx_prev: std_logic_vector(15 downto 0);
rx_lfsr: std_logic_vector(15 downto 0);
running: std_ulogic;
tick_in: std_ulogic;
time_in: std_logic_vector(5 downto 0);
txwrite: std_ulogic;
txflag: std_ulogic;
txdata: std_logic_vector(7 downto 0);
rxread: std_ulogic;
gotdata: std_ulogic;
dataerror: std_ulogic;
tickerror: std_ulogic;
end record;
 
-- Reset state.
constant regs_reset: regs_type := (
tx_state => txst_idle,
tx_timecnt => (others => '0'),
tx_quietcnt => (others => '0'),
tx_pktlen => (others => '0'),
tx_lfsr => (1 => '1', others => '0'),
tx_enabledata => '0',
rx_state => rxst_idle,
rx_quietcnt => (others => '0'),
rx_enabledata => '0',
rx_gottick => '0',
rx_expecttick => '0',
rx_expectglitch => "000001",
rx_badpacket => '0',
rx_pktlen => (others => '0'),
rx_prev => (others => '0'),
rx_lfsr => (others => '0'),
running => '0',
tick_in => '0',
time_in => (others => '0'),
txwrite => '0',
txflag => '0',
txdata => (others => '0'),
rxread => '0',
gotdata => '0',
dataerror => '0',
tickerror => '0' );
 
signal r: regs_type := regs_reset;
signal rin: regs_type;
 
-- Interface signals.
signal s_txrdy: std_logic;
signal s_tickout: std_logic;
signal s_timeout: std_logic_vector(5 downto 0);
signal s_rxvalid: std_logic;
signal s_rxflag: std_logic;
signal s_rxdata: std_logic_vector(7 downto 0);
signal s_running: std_logic;
signal s_errdisc: std_logic;
signal s_errpar: std_logic;
signal s_erresc: std_logic;
signal s_errcred: std_logic;
 
begin
 
-- spwstream instance
spwstream_inst: spwstream
generic map (
sysfreq => sysfreq,
rximpl => rximpl,
rxchunk => rxchunk,
tximpl => tximpl,
rxfifosize_bits => rxfifosize_bits,
txfifosize_bits => txfifosize_bits )
port map (
clk => clk,
rxclk => rxclk,
txclk => txclk,
rst => rst,
autostart => autostart,
linkstart => linkstart,
linkdis => linkdisable,
txdivcnt => txdivcnt,
tick_in => r.tick_in,
ctrl_in => (others => '0'),
time_in => r.time_in,
txwrite => r.txwrite,
txflag => r.txflag,
txdata => r.txdata,
txrdy => s_txrdy,
txhalff => open,
tick_out => s_tickout,
ctrl_out => open,
time_out => s_timeout,
rxvalid => s_rxvalid,
rxhalff => open,
rxflag => s_rxflag,
rxdata => s_rxdata,
rxread => r.rxread,
started => linkstarted,
connecting => linkconnecting,
running => s_running,
errdisc => s_errdisc,
errpar => s_errpar,
erresc => s_erresc,
errcred => s_errcred,
spw_di => spw_di,
spw_si => spw_si,
spw_do => spw_do,
spw_so => spw_so );
 
-- Drive status indications.
linkrun <= s_running;
linkerror <= s_errdisc or s_errpar or s_erresc or s_errcred;
gotdata <= r.gotdata;
dataerror <= r.dataerror;
tickerror <= r.tickerror;
 
process (r, rst, senddata, sendtick, s_txrdy, s_tickout, s_timeout, s_rxvalid, s_rxflag, s_rxdata, s_running) is
variable v: regs_type;
begin
v := r;
 
-- Initiate timecode transmissions.
v.tx_timecnt := std_logic_vector(unsigned(r.tx_timecnt) + 1);
if unsigned(v.tx_timecnt) = 0 then
v.tick_in := sendtick;
else
v.tick_in := '0';
end if;
if r.tick_in = '1' then
v.time_in := std_logic_vector(unsigned(r.time_in) + 1);
v.rx_expecttick := '1';
v.rx_gottick := '0';
end if;
 
-- Turn data generator on/off at regular intervals.
v.tx_quietcnt := std_logic_vector(unsigned(r.tx_quietcnt) + 1);
if unsigned(r.tx_quietcnt) = 61000 then
v.tx_quietcnt := (others => '0');
end if;
v.tx_enabledata := senddata and (not r.tx_quietcnt(15));
 
-- Generate data packets.
case r.tx_state is
when txst_idle =>
-- generate packet length
v.tx_state := txst_prepare;
v.tx_pktlen := r.tx_lfsr;
v.txwrite := '0';
v.tx_lfsr := lfsr16(r.tx_lfsr);
when txst_prepare =>
-- generate first byte of packet
v.tx_state := txst_data;
v.txwrite := r.tx_enabledata;
v.txflag := '0';
v.txdata := r.tx_lfsr(15 downto 8);
v.tx_lfsr := lfsr16(r.tx_lfsr);
when txst_data =>
-- generate data bytes and EOP
v.txwrite := r.tx_enabledata;
if r.txwrite = '1' and s_txrdy = '1' then
-- just sent one byte
v.tx_pktlen := std_logic_vector(unsigned(r.tx_pktlen) - 1);
if unsigned(r.tx_pktlen) = 0 then
-- done with packet
v.tx_state := txst_idle;
v.txwrite := '0';
elsif unsigned(r.tx_pktlen) = 1 then
-- generate EOP
v.txwrite := r.tx_enabledata;
v.txflag := '1';
v.txdata := (others => '0');
v.tx_lfsr := lfsr16(r.tx_lfsr);
else
-- generate next data byte
v.txwrite := r.tx_enabledata;
v.txflag := '0';
v.txdata := r.tx_lfsr(15 downto 8);
v.tx_lfsr := lfsr16(r.tx_lfsr);
end if;
end if;
end case;
 
-- Blink light when receiving data.
v.gotdata := s_rxvalid and r.rxread;
 
-- Detect missing timecodes.
if r.tick_in = '1' and r.rx_expecttick = '1' then
-- This is bad; a new timecode is being generated while
-- we have not even received the previous one yet.
v.tickerror := '1';
end if;
 
-- Receive and check incoming timecodes.
if s_tickout = '1' then
if unsigned(s_timeout) + 1 /= unsigned(r.time_in) then
-- Received time code does not match last transmitted code.
v.tickerror := '1';
end if;
if r.rx_gottick = '1' then
-- Already received the last transmitted time code.
v.tickerror := '1';
end if;
v.rx_expecttick := '0';
v.rx_gottick := '1';
end if;
 
-- Turn data receiving on/off at regular intervals
v.rx_quietcnt := std_logic_vector(unsigned(r.rx_quietcnt) + 1);
if unsigned(r.rx_quietcnt) = 55000 then
v.rx_quietcnt := (others => '0');
end if;
v.rx_enabledata := not r.rx_quietcnt(15);
 
case r.rx_state is
when rxst_idle =>
-- get expected packet length
v.rx_state := rxst_data;
v.rx_pktlen := r.rx_lfsr;
v.rx_lfsr := lfsr16(r.rx_lfsr);
v.rx_prev := (others => '0');
when rxst_data =>
v.rxread := r.rx_enabledata;
if r.rxread = '1' and s_rxvalid = '1' then
-- got next byte
v.rx_pktlen := std_logic_vector(unsigned(r.rx_pktlen) - 1);
v.rx_prev := s_rxdata & r.rx_prev(15 downto 8);
if s_rxflag = '1' then
-- got EOP or EEP
v.rxread := '0';
v.rx_state := rxst_idle;
if s_rxdata = "00000000" then
-- got EOP
if unsigned(r.rx_pktlen) /= 0 then
-- unexpected EOP
v.rx_badpacket := '1';
end if;
-- count errors against expected glitches
if v.rx_badpacket = '1' then
-- got glitch
if r.rx_expectglitch = 0 then
v.dataerror := '1';
else
v.rx_expectglitch := r.rx_expectglitch - 1;
end if;
end if;
-- resynchronize LFSR
v.rx_lfsr := lfsr16(lfsr16(r.rx_prev));
else
-- got EEP
v.rx_badpacket := '1';
end if;
v.rx_badpacket := '0';
else
-- got next byte
v.rx_lfsr := lfsr16(r.rx_lfsr);
if unsigned(r.rx_pktlen) = 0 then
-- missing EOP
v.rx_badpacket := '1';
end if;
if s_rxdata /= r.rx_lfsr(15 downto 8) then
-- bad data
v.rx_badpacket := '1';
end if;
end if;
end if;
end case;
 
-- If the link goes away, we should expect inconsistency on the receiving side.
v.running := s_running;
if r.running = '1' and s_running = '0' then
if r.rx_expectglitch /= "111111" then
v.rx_expectglitch := r.rx_expectglitch + 1;
end if;
end if;
 
-- If there is no link, we should not expect to receive time codes.
if s_running = '0' then
v.rx_expecttick := '0';
end if;
 
-- Synchronous reset.
if rst = '1' then
v := regs_reset;
end if;
 
-- Update registers.
rin <= v;
end process;
 
-- Update registers.
process (clk) is
begin
if rising_edge(clk) then
r <= rin;
end if;
end process;
 
end architecture streamtest_arch;
/trunk/rtl/vhdl/spwrecvfront_generic.vhd
0,0 → 1,95
--
-- Front-end for SpaceWire Receiver
--
-- This entity samples the input signals DataIn and StrobeIn to detect
-- valid bit transitions. Received bits are handed to the application.
--
-- Inputs are sampled on the rising edge of the system clock, therefore
-- the maximum bitrate of the incoming signal must be significantly lower
-- than system clock frequency.
--
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
entity spwrecvfront_generic is
 
port (
-- System clock.
clk: in std_logic;
 
-- High to enable receiver; low to disable and reset receiver.
rxen: in std_logic;
 
-- High if there has been recent activity on the input lines.
inact: out std_logic;
 
-- High if inbits contains a valid received bit.
-- If inbvalid='1', the application must sample inbits on
-- the rising edge of clk.
inbvalid: out std_logic;
 
-- Received bit
inbits: out std_logic_vector(0 downto 0);
 
-- Data In signal from SpaceWire bus.
spw_di: in std_logic;
 
-- Strobe In signal from SpaceWire bus.
spw_si: in std_logic );
 
end entity spwrecvfront_generic;
 
architecture spwrecvfront_arch of spwrecvfront_generic is
 
-- input flip-flops
signal s_spwdi1: std_ulogic;
signal s_spwsi1: std_ulogic;
signal s_spwdi2: std_ulogic;
signal s_spwsi2: std_ulogic;
 
-- data/strobe decoding
signal s_spwsi3: std_ulogic;
 
-- output registers
signal s_inbvalid: std_ulogic;
signal s_inbit: std_ulogic;
 
begin
 
-- drive outputs
inact <= s_inbvalid;
inbvalid <= s_inbvalid;
inbits(0) <= s_inbit;
 
-- synchronous process
process (clk) is
begin
if rising_edge(clk) then
 
-- sample input signal
s_spwdi1 <= spw_di;
s_spwsi1 <= spw_si;
 
-- more flip-flops for safe synchronization
s_spwdi2 <= s_spwdi1;
s_spwsi2 <= s_spwsi1;
 
-- keep strobe signal for data/strobe decoding
s_spwsi3 <= s_spwsi2;
 
if rxen = '1' then
-- data/strobe decoding
s_inbit <= s_spwdi2;
s_inbvalid <= s_spwdi2 xor s_spwsi2 xor s_inbit xor s_spwsi3;
else
-- reset receiver
s_inbit <= '0';
s_inbvalid <= '0';
end if;
 
end if;
end process;
 
end architecture spwrecvfront_arch;
/trunk/sim/ghdl/Makefile
0,0 → 1,53
#
# Makefile for building and running RTL simulation with GHDL.
#
# Simulation has been tested with GHDL 0.29.
# GHDL is available from http://ghdl.free.fr/
#
 
GHDL = ghdl
RTLDIR = ../../rtl/vhdl
TBDIR = ../../bench/vhdl
 
.PHONY: default test_spwlink test_streamtest clean
 
default:
@echo "Targets:"
@echo " make spwlink_tb Build default spwlink testbench"
@echo " make spwlink_tb_all Build spwlink mega testbench"
@echo " make test_spwlink Run spwlink mega testbench"
@echo " make streamtest_tb Build spwstream testbench"
@echo " make test_streamtest Run spwstream testbench"
@echo " make clean Remove build files"
 
SPWLINK_VHDL = $(RTLDIR)/spwpkg.vhd \
$(RTLDIR)/spwlink.vhd \
$(RTLDIR)/spwrecv.vhd \
$(RTLDIR)/spwxmit.vhd \
$(RTLDIR)/spwxmit_fast.vhd \
$(RTLDIR)/spwrecvfront_generic.vhd \
$(RTLDIR)/spwrecvfront_fast.vhd
 
SPWSTREAM_VHDL = $(SPWLINK_VHDL) \
$(RTLDIR)/spwstream.vhd \
$(RTLDIR)/spwram.vhd
 
spwlink_tb: $(TBDIR)/spwlink_tb.vhd $(SPWLINK_VHDL)
$(GHDL) -c $^ -e spwlink_tb
 
spwlink_tb_all: $(TBDIR)/spwlink_tb_all.vhd $(TBDIR)/spwlink_tb.vhd $(SPWLINK_VHDL)
$(GHDL) -c $^ -e spwlink_tb_all
 
test_spwlink: spwlink_tb_all
$(GHDL) -r spwlink_tb_all --assert-level=error
 
streamtest_tb: $(TBDIR)/streamtest_tb.vhd $(RTLDIR)/streamtest.vhd $(SPWSTREAM_VHDL)
$(GHDL) -c $^ -e streamtest_tb
 
test_streamtest: streamtest_tb
$(GHDL) -r streamtest_tb --assert-level=error
 
clean:
$(GHDL) --clean
$(RM) e~spwlink_tb.o e~spwlink_tb_all.o e~streamtest_tb.o
 
/trunk/syn/spwstream_gr-xc3s1500/spwstream.ucf
0,0 → 1,10
 
NET "clk" TNM_NET = "clk" ;
TIMESPEC "TS_clk" = PERIOD "clk" 13 ns ;
 
NET "fastclk" TNM_NET = "fastclk" ;
TIMESPEC "TS_fastclk" = PERIOD "fastclk" 4 ns ;
 
TIMESPEC "TS_fast_to_sys" = FROM "fastclk" TO "clk" 4 ns ;
TIMESPEC "TS_sys_to_fast" = FROM "clk" TO "fastclk" 4 ns ;
 
/trunk/syn/spwstream_gr-xc3s1500/spwstream_top.vhd
0,0 → 1,95
library ieee;
use ieee.std_logic_1164.all, ieee.numeric_std.all;
use work.spwpkg.all;
 
entity spwstream_top is
 
port (
clk: in std_logic;
fastclk: in std_logic;
rst: in std_logic;
autostart: in std_logic;
linkstart: in std_logic;
linkdis: in std_logic;
txdivcnt: in std_logic_vector(7 downto 0);
tick_in: in std_logic;
ctrl_in: in std_logic_vector(1 downto 0);
time_in: in std_logic_vector(5 downto 0);
txwrite: in std_logic;
txflag: in std_logic;
txdata: in std_logic_vector(7 downto 0);
txrdy: out std_logic;
txhalff: out std_logic;
tick_out: out std_logic;
ctrl_out: out std_logic_vector(1 downto 0);
time_out: out std_logic_vector(5 downto 0);
rxvalid: out std_logic;
rxhalff: out std_logic;
rxflag: out std_logic;
rxdata: out std_logic_vector(7 downto 0);
rxread: in std_logic;
started: out std_logic;
connecting: out std_logic;
running: out std_logic;
errdisc: out std_logic;
errpar: out std_logic;
erresc: out std_logic;
errcred: out std_logic;
spw_di: in std_logic;
spw_si: in std_logic;
spw_do: out std_logic;
spw_so: out std_logic
);
 
end entity spwstream_top;
 
architecture spwstream_top_arch of spwstream_top is
 
begin
 
spwstream_inst: spwstream
generic map (
sysfreq => 60.0e6,
rximpl => impl_fast,
rxchunk => 4,
tximpl => impl_fast,
rxfifosize_bits => 11,
txfifosize_bits => 6 )
port map (
clk => clk,
rxclk => fastclk,
txclk => fastclk,
rst => rst,
autostart => autostart,
linkstart => linkstart,
linkdis => linkdis,
txdivcnt => txdivcnt,
tick_in => tick_in,
ctrl_in => ctrl_in,
time_in => time_in,
txwrite => txwrite,
txflag => txflag,
txdata => txdata,
txrdy => txrdy
, txhalff => txhalff,
tick_out => tick_out,
ctrl_out => ctrl_out,
time_out => time_out,
rxvalid => rxvalid,
rxhalff => rxhalff,
rxflag => rxflag,
rxdata => rxdata,
rxread => rxread,
started => started,
connecting => connecting,
running => running,
errdisc => errdisc,
errpar => errpar,
erresc => erresc,
errcred => errcred,
spw_di => spw_di,
spw_si => spw_si,
spw_do => spw_do,
spw_so => spw_so );
 
end architecture spwstream_top_arch;
/trunk/syn/spwstream_gr-xc3s1500/Makefile
0,0 → 1,290
 
###############################################################################
## ##
## project-dependent variables ##
## ##
###############################################################################
 
# The project name. The bit-file that is generated in the end will be named
# "$(PROJ).bit"
 
PROJ = spwstream
 
# The top-level entity to be instantiated
 
TOPLEVEL = spwstream_top
 
# The VHDL sources that need to be compiled during synthesis
 
RTLDIR = ../../rtl/vhdl
VHDL_SOURCES = spwstream_top.vhd \
$(RTLDIR)/spwpkg.vhd \
$(RTLDIR)/spwstream.vhd \
$(RTLDIR)/spwlink.vhd \
$(RTLDIR)/spwram.vhd \
$(RTLDIR)/spwrecv.vhd \
$(RTLDIR)/spwxmit.vhd \
$(RTLDIR)/spwxmit_fast.vhd \
$(RTLDIR)/spwrecvfront_generic.vhd \
$(RTLDIR)/spwrecvfront_fast.vhd
 
# Device type: Spartan-3 on Pender XC3S1500 board
 
FPGA_TYPE = xc3s1500-fg456-4
 
# The default target; recommended targets: "bitfile" or "upload"
 
default : bitfile
 
UCFFILE = spwstream.ucf
 
###############################################################################
## ##
## miscellaneous project-independent variables & rules ##
## ##
###############################################################################
 
# use this to make most tools quieter
OPT_INTSTYLE = -intstyle ise
 
# Phony (non file creating) targets
 
.PHONY : default clean bitfile
 
clean :
$(RM) -rf *~ work dump.xst _ngo 'file graph' xlnx_auto_0_xdb
$(RM) $(PROJ).xst-script
$(RM) $(PROJ).lso $(PROJ).prj
$(RM) $(PROJ).ngc $(PROJ).xst.log $(PROJ).syr $(PROJ).srp $(PROJ).ngr
$(RM) $(PROJ).ngd $(PROJ).bld
$(RM) $(PROJ).twx $(PROJ).twr
$(RM) $(PROJ).pcf $(PROJ)_map.mrp $(PROJ)_map.ncd $(PROJ)_map.ngm
$(RM) $(PROJ).ncd $(PROJ).pad $(PROJ).par $(PROJ).xpi $(PROJ)_pad.csv $(PROJ)_pad.txt
$(RM) $(PROJ).bit $(PROJ).bgn $(PROJ).drca
$(RM) $(PROJ).ptwx $(PROJ).unroutes *.xrpt $(PROJ)_summary.xml $(PROJ)_usage.xml $(PROJ)_map.map
 
bitfile : $(PROJ).bit
 
###############################################################################
# #
# STAGE 1: "xst" (Xilinx Synthesis Tool) #
# needs: #
# #
# $(PROJ).vhdl #
# $(PROJ).prj - Project file (created below) #
# $(PROJ).lso - Library Search Order file (created below) #
# #
# created files: #
# #
# $(PROJ).ngc - netlist #
# $(PROJ).ngr - XILINX-XDB 0.1 STUB 0.1 ASCII / XILINX-XDM V1.2e #
# (optional, depending on the '-rtlview' option) #
# $(PROJ).xst.log - human-readable synthesis report #
# (AKA .syr, .srp) #
# #
# created directories: #
# #
# work #
# dump.xst #
# #
###############################################################################
 
# Generate a "Library Search Order" file, containing just "work" for now.
 
$(PROJ).lso :
@echo "work" > $@
 
# Generate a "Project" file, consisting of lines containing each of the
# VHDL_SOURCES, preceded by "vhdl work".
 
$(PROJ).prj :
$(shell echo -n $(VHDL_SOURCES) | \
sed 's/\([^ ]\+\) */vhdl work \1\n/g' > $@)
 
$(PROJ).xst-script :
@echo "set -tmpdir /tmp" > $@
@echo "set -xsthdpdir ." >> $@
@echo "run" >> $@
@echo "-ifn $(PROJ).prj" >> $@
@echo "-ifmt mixed" >> $@
@echo "-ofn $(PROJ)" >> $@
@echo "-ofmt ngc" >> $@
@echo "-p $(FPGA_TYPE)" >> $@
@echo "-top $(TOPLEVEL)" >> $@
@echo "-opt_mode speed" >> $@
@echo "-opt_level 1" >> $@
@echo "-iuc no" >> $@
@echo "-lso $(PROJ).lso" >> $@
@echo "-keep_hierarchy no" >> $@
@echo "-glob_opt AllClockNets" >> $@
@echo "-rtlview no" >> $@
@echo "-read_cores yes" >> $@
@echo "-write_timing_constraints yes" >> $@
@echo "-cross_clock_analysis no" >> $@
# @echo "-hierarchy_separator _" >> $@
@echo "-bus_delimiter <>" >> $@
@echo "-case maintain" >> $@
@echo "-slice_utilization_ratio 100" >> $@
# @echo "-verilog2001 yes" >> $@
# @echo "-vlgincdir" >> $@
@echo "-fsm_extract yes" >> $@
@echo "-fsm_encoding auto" >> $@
@echo "-fsm_style lut" >> $@
@echo "-ram_extract yes" >> $@
@echo "-ram_style auto" >> $@
@echo "-rom_extract yes" >> $@
@echo "-rom_style auto" >> $@
@echo "-mux_extract yes" >> $@
@echo "-mux_style auto" >> $@
@echo "-decoder_extract yes" >> $@
@echo "-priority_extract yes" >> $@
@echo "-shreg_extract yes" >> $@
@echo "-shift_extract yes" >> $@
@echo "-xor_collapse yes" >> $@
@echo "-resource_sharing yes" >> $@
@echo "-mult_style auto" >> $@
@echo "-iobuf yes" >> $@
@echo "-max_fanout 500" >> $@
@echo "-bufg 8" >> $@
@echo "-register_duplication yes" >> $@
@echo "-equivalent_register_removal yes" >> $@
@echo "-register_balancing no" >> $@
@echo "-slice_packing yes" >> $@
@echo "-optimize_primitives no" >> $@
@echo "-iob auto" >> $@
 
$(PROJ).ngc $(PROJ).xst.log : $(VHDL_SOURCES) $(PROJ).prj $(PROJ).lso $(PROJ).xst-script
rm -rf work dump.xst
xst $(OPT_INTSTYLE) -ifn $(PROJ).xst-script -ofn $(PROJ).xst.log
rm -rf work dump.xst
 
###############################################################################
# #
# STAGE 2: ngdbuild #
# needs: #
# #
# $(PROJ).ngc #
# #
# created files: #
# #
# $(PROJ).bld - human-readable build log #
# $(PROJ).ngd - XILINX-XDB 0.1 STUB 0.1 ASCII / XILINX-XDM V1.2e #
# #
# created dir: #
# _ngo #
# #
###############################################################################
 
$(PROJ).ngd $(PROJ).bld: $(PROJ).ngc $(UCFFILE)
rm -rf _ngo
ngdbuild $(OPT_INTSTYLE) -dd _ngo -aul -p $(FPGA_TYPE) $(if $(UCFFILE),-uc $(UCFFILE)) $(PROJ).ngc $(PROJ).ngd
rm -rf _ngo
 
###############################################################################
# #
# STAGE 3: Mapper #
# needs: #
# #
# $(PROJ).ngd #
# #
# created files: #
# #
# $(PROJ).pcf - ASCII file #
# $(PROJ)_map.mrp - human-readable mapping report #
# $(PROJ)_map.ncd - binary format #
# $(PROJ)_map.ngm - XILINX-XDB 0.1 STUB 0.1 ASCII / XILINX-XDM V1.2e #
# #
# NOTE: #
# #
# In order to prevent the make process from terminating on these spurious #
# problems, we precede the "map" invocation with a hyphen, instructing #
# make to ignore the return code from "map". #
# #
###############################################################################
 
$(PROJ).pcf $(PROJ)_map.mrp $(PROJ)_map.ncd $(PROJ)_map.ngm: $(PROJ).ngd
map $(OPT_INTSTYLE) -p $(FPGA_TYPE) -cm area -pr b -c 100 -o $(PROJ)_map.ncd $(PROJ).ngd $(PROJ).pcf
 
###############################################################################
# #
# STAGE 4: Place-and-Route #
# needs: #
# #
# $(PROJ).pcf #
# $(PROJ)_map.ncd #
# #
# created files: #
# #
# $(PROJ).ncd - binary file #
# $(PROJ).pad - ASCII file for import in spreadsheet #
# $(PROJ).par - human-readable place-and-route report #
# $(PROJ).xpi - ASCII file #
# $(PROJ)_pad.csv - human-readable CVS file #
# $(PROJ)_pad.txt - human-readable file #
# #
###############################################################################
 
$(PROJ).ncd $(PROJ).pad $(PROJ).par $(PROJ).xpi $(PROJ)_pad.csv $(PROJ)_pad.txt: $(PROJ).pcf $(PROJ)_map.ncd
par -w $(OPT_INTSTYLE) -t 1 $(PROJ)_map.ncd $(PROJ).ncd $(PROJ).pcf
 
###############################################################################
# #
# STAGE 4.5 (optional): trace #
# needs: #
# #
# created files: #
# #
###############################################################################
 
$(PROJ).twr $(PROJ).twx : $(PROJ).ncd $(PROJ).pcf
trce $(OPT_INTSTYLE) -e 5 -l 5 -u 5 -xml $(PROJ) $(PROJ).ncd -o $(PROJ).twr $(PROJ).pcf
 
###############################################################################
# #
# STAGE 5: Generate BIT-file #
# needs: #
# #
# $(PROJ).ncd #
# #
# created files: $(PROJ).bgn $(PROJ).bit $(PROJ).drc #
# #
# $(PROJ).bgn - human-readable BitGen report #
# $(PROJ).drc - human readable DRC report #
# $(PROJ).bit - binary image file #
# #
###############################################################################
 
# We omit "-g StartUpClk:JtagClk" ; this doesn't work if the image is loaded
# from a PROM.
 
OPT_BITGEN = -w \
-g DebugBitstream:No \
-g Binary:no \
-g CRC:Enable \
-g ConfigRate:6 \
-g CclkPin:PullUp \
-g M0Pin:PullUp \
-g M1Pin:PullUp \
-g M2Pin:PullUp \
-g ProgPin:PullUp \
-g DonePin:PullUp \
-g TckPin:PullUp \
-g TdiPin:PullUp \
-g TdoPin:PullUp \
-g TmsPin:PullUp \
-g UnusedPin:PullDown \
-g UserID:0xFFFFFFFF \
-g DCMShutDown:Disable \
-g DONE_cycle:4 \
-g GTS_cycle:5 \
-g GWE_cycle:6 \
-g LCK_cycle:NoWait \
-g Match_cycle:Auto \
-g Security:None \
-g DonePipe:No \
-g DriveDone:No
 
$(PROJ).bit $(PROJ).bgn $(PROJ).drc: $(PROJ).ncd
bitgen $(OPT_INTSTYLE) $(OPT_BITGEN) $(PROJ).ncd
 
###############################################################################
/trunk/syn/streamtest_digilent-xc3s200/streamtest.xise
0,0 → 1,388
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<project xmlns="http://www.xilinx.com/XMLSchema" xmlns:xil_pn="http://www.xilinx.com/XMLSchema">
 
<header>
<!-- ISE source project file created by Project Navigator. -->
<!-- -->
<!-- This file contains project source information including a list of -->
<!-- project source files, project and process properties. This file, -->
<!-- along with the project source files, is sufficient to open and -->
<!-- implement in ISE Project Navigator. -->
<!-- -->
<!-- Copyright (c) 1995-2009 Xilinx, Inc. All rights reserved. -->
</header>
 
<version xil_pn:ise_version="11.3" xil_pn:schema_version="2"/>
 
<files>
<file xil_pn:name="../../rtl/vhdl/spwlink.vhd" xil_pn:type="FILE_VHDL">
<association xil_pn:name="BehavioralSimulation"/>
<association xil_pn:name="Implementation"/>
</file>
<file xil_pn:name="../../rtl/vhdl/spwpkg.vhd" xil_pn:type="FILE_VHDL">
<association xil_pn:name="BehavioralSimulation"/>
<association xil_pn:name="Implementation"/>
</file>
<file xil_pn:name="../../rtl/vhdl/spwram.vhd" xil_pn:type="FILE_VHDL">
<association xil_pn:name="BehavioralSimulation"/>
<association xil_pn:name="Implementation"/>
</file>
<file xil_pn:name="../../rtl/vhdl/spwrecv.vhd" xil_pn:type="FILE_VHDL">
<association xil_pn:name="BehavioralSimulation"/>
<association xil_pn:name="Implementation"/>
</file>
<file xil_pn:name="../../rtl/vhdl/spwrecvfront_fast.vhd" xil_pn:type="FILE_VHDL">
<association xil_pn:name="BehavioralSimulation"/>
<association xil_pn:name="Implementation"/>
</file>
<file xil_pn:name="../../rtl/vhdl/spwrecvfront_generic.vhd" xil_pn:type="FILE_VHDL">
<association xil_pn:name="BehavioralSimulation"/>
<association xil_pn:name="Implementation"/>
</file>
<file xil_pn:name="../../rtl/vhdl/spwstream.vhd" xil_pn:type="FILE_VHDL">
<association xil_pn:name="BehavioralSimulation"/>
<association xil_pn:name="Implementation"/>
</file>
<file xil_pn:name="../../rtl/vhdl/spwxmit.vhd" xil_pn:type="FILE_VHDL">
<association xil_pn:name="BehavioralSimulation"/>
<association xil_pn:name="Implementation"/>
</file>
<file xil_pn:name="../../rtl/vhdl/spwxmit_fast.vhd" xil_pn:type="FILE_VHDL">
<association xil_pn:name="BehavioralSimulation"/>
<association xil_pn:name="Implementation"/>
</file>
<file xil_pn:name="../../rtl/vhdl/streamtest.vhd" xil_pn:type="FILE_VHDL">
<association xil_pn:name="BehavioralSimulation"/>
<association xil_pn:name="Implementation"/>
</file>
<file xil_pn:name="streamtest.ucf" xil_pn:type="FILE_UCF">
<association xil_pn:name="Implementation"/>
</file>
<file xil_pn:name="streamtest_top.vhd" xil_pn:type="FILE_VHDL">
<association xil_pn:name="BehavioralSimulation"/>
<association xil_pn:name="Implementation"/>
</file>
</files>
 
<properties>
<property xil_pn:name="Add I/O Buffers" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Allow Logic Optimization Across Hierarchy" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Allow SelectMAP Pins to Persist" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Allow Unexpanded Blocks" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Allow Unmatched LOC Constraints" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Allow Unmatched Timing Group Constraints" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Asynchronous To Synchronous" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Auto Implementation Compile Order" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Auto Implementation Top" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Automatic BRAM Packing" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Automatically Insert glbl Module in the Netlist" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Automatically Run Generate Target PROM/ACE File" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="BRAM Utilization Ratio" xil_pn:value="100" xil_pn:valueState="default"/>
<property xil_pn:name="Block RAM Data File" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Bring Out Global Set/Reset Net as a Port" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Bring Out Global Tristate Net as a Port" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Bus Delimiter" xil_pn:value="&lt;>" xil_pn:valueState="default"/>
<property xil_pn:name="CLB Pack Factor Percentage" xil_pn:value="100" xil_pn:valueState="default"/>
<property xil_pn:name="Case" xil_pn:value="Maintain" xil_pn:valueState="default"/>
<property xil_pn:name="Case Implementation Style" xil_pn:value="None" xil_pn:valueState="default"/>
<property xil_pn:name="Change Device Speed To" xil_pn:value="-4" xil_pn:valueState="default"/>
<property xil_pn:name="Change Device Speed To Post Trace" xil_pn:value="-4" xil_pn:valueState="default"/>
<property xil_pn:name="Combinatorial Logic Optimization" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Command line syntax" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Compile EDK Simulation Library" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Compile SIMPRIM (Timing) Simulation Library" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Compile UNISIM (Functional) Simulation Library" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Compile XilinxCoreLib (CORE Generator) Simulation Library" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Compile for HDL Debugging" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Compiled Library Directory" xil_pn:value="$XILINX/&lt;language>/&lt;simulator>" xil_pn:valueState="default"/>
<property xil_pn:name="Configuration Clk (Configuration Pins)" xil_pn:value="Pull Up" xil_pn:valueState="default"/>
<property xil_pn:name="Configuration Pin Done" xil_pn:value="Pull Up" xil_pn:valueState="default"/>
<property xil_pn:name="Configuration Pin HSWAPEN" xil_pn:value="Pull Up" xil_pn:valueState="default"/>
<property xil_pn:name="Configuration Pin M0" xil_pn:value="Pull Up" xil_pn:valueState="default"/>
<property xil_pn:name="Configuration Pin M1" xil_pn:value="Pull Up" xil_pn:valueState="default"/>
<property xil_pn:name="Configuration Pin M2" xil_pn:value="Pull Up" xil_pn:valueState="default"/>
<property xil_pn:name="Configuration Pin Program" xil_pn:value="Pull Up" xil_pn:valueState="default"/>
<property xil_pn:name="Configuration Rate" xil_pn:value="Default (6)" xil_pn:valueState="default"/>
<property xil_pn:name="Constraints Entry" xil_pn:value="Constraints Editor" xil_pn:valueState="non-default"/>
<property xil_pn:name="Constraints Interaction Report File" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Constraints Interaction Report File Post Trace" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Cores Search Directories" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Correlate Output to Input Design" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Create ASCII Configuration File" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Create Binary Configuration File" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Create Bit File" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Create I/O Pads from Ports" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Create IEEE 1532 Configuration File" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Create Logic Allocation File" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Create Mask File" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Create ReadBack Data Files" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Cross Clock Analysis" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Custom Project Filename Behavioral" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Custom Project Filename Post-Route" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Custom Simulation Command File" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Custom Simulation Command File Par" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Custom Waveform Configuration File Behav" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Custom Waveform Configuration File Par" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="DCI Update Mode" xil_pn:value="As Required" xil_pn:valueState="default"/>
<property xil_pn:name="Decoder Extraction" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Delay Values To Be Read from SDF" xil_pn:value="Setup Time" xil_pn:valueState="default"/>
<property xil_pn:name="Device" xil_pn:value="xc3s200" xil_pn:valueState="non-default"/>
<property xil_pn:name="Device Family" xil_pn:value="Spartan3" xil_pn:valueState="non-default"/>
<property xil_pn:name="Device Speed Grade/Select ABS Minimum" xil_pn:value="-4" xil_pn:valueState="default"/>
<property xil_pn:name="Display Incremental Messages" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Do Not Escape Signal and Instance Names in Netlist" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Done (Output Events)" xil_pn:value="Default (4)" xil_pn:valueState="default"/>
<property xil_pn:name="Drive Done Pin High" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Editor" xil_pn:value="ISE Text Editor" xil_pn:valueState="default"/>
<property xil_pn:name="Enable BitStream Compression" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Enable Cyclic Redundancy Checking (CRC)" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Enable Debugging of Serial Mode BitStream" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Enable Enhanced Design Summary" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Enable Internal Done Pipe" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Enable Message Filtering" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Enable Outputs (Output Events)" xil_pn:value="Default (5)" xil_pn:valueState="default"/>
<property xil_pn:name="Equivalent Register Removal XST" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Exclude Compilation of Deprecated EDK Cores" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Exclude Compilation of EDK Sub-Libraries" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Extra Effort" xil_pn:value="None" xil_pn:valueState="default"/>
<property xil_pn:name="Extra Effort (Highest PAR level only)" xil_pn:value="None" xil_pn:valueState="default"/>
<property xil_pn:name="FPGA Start-Up Clock" xil_pn:value="CCLK" xil_pn:valueState="default"/>
<property xil_pn:name="FSM Encoding Algorithm" xil_pn:value="Auto" xil_pn:valueState="default"/>
<property xil_pn:name="FSM Style" xil_pn:value="LUT" xil_pn:valueState="default"/>
<property xil_pn:name="Filter Files From Compile Order" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Fitter Report Format" xil_pn:value="HTML" xil_pn:valueState="non-default"/>
<property xil_pn:name="Flatten Output Netlist" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Flow Debug Level" xil_pn:value="0" xil_pn:valueState="default"/>
<property xil_pn:name="Functional Model Target Language ArchWiz" xil_pn:value="VHDL" xil_pn:valueState="default"/>
<property xil_pn:name="Functional Model Target Language Coregen" xil_pn:value="VHDL" xil_pn:valueState="default"/>
<property xil_pn:name="Functional Model Target Language Schematic" xil_pn:value="VHDL" xil_pn:valueState="default"/>
<property xil_pn:name="Generate Architecture Only (No Entity Declaration)" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Generate Asynchronous Delay Report" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Generate Clock Region Report" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Generate Constraints Interaction Report" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Generate Constraints Interaction Report Post Trace" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Generate Datasheet Section" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Generate Datasheet Section Post Trace" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Generate Detailed MAP Report" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Generate Multiple Hierarchical Netlist Files" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Generate Post-Place &amp; Route Power Report" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Generate Post-Place &amp; Route Simulation Model" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Generate RTL Schematic" xil_pn:value="Yes" xil_pn:valueState="default"/>
<property xil_pn:name="Generate SAIF File for Power Optimization/Estimation Par" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Generate Testbench File" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Generate Timegroups Section" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Generate Timegroups Section Post Trace" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Generics, Parameters" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Global Optimization Goal" xil_pn:value="AllClockNets" xil_pn:valueState="default"/>
<property xil_pn:name="Global Set/Reset Port Name" xil_pn:value="GSR_PORT" xil_pn:valueState="default"/>
<property xil_pn:name="Global Tristate Port Name" xil_pn:value="GTS_PORT" xil_pn:valueState="default"/>
<property xil_pn:name="HDL INI File" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Hierarchy Separator" xil_pn:value="/" xil_pn:valueState="default"/>
<property xil_pn:name="ISim UUT Instance Name" xil_pn:value="UUT" xil_pn:valueState="default"/>
<property xil_pn:name="Ignore User Timing Constraints Map" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Ignore User Timing Constraints Par" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Implementation Top" xil_pn:value="Architecture|streamtest_top|streamtest_top_arch" xil_pn:valueState="non-default"/>
<property xil_pn:name="Implementation Top Instance Path" xil_pn:value="/streamtest_top" xil_pn:valueState="non-default"/>
<property xil_pn:name="Include 'uselib Directive in Verilog File" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Include SIMPRIM Models in Verilog File" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Include UNISIM Models in Verilog File" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Include sdf_annotate task in Verilog File" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Incremental Compilation" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Input TCL Command Script" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Insert Buffers to Prevent Pulse Swallowing" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Instantiation Template Target Language Xps" xil_pn:value="VHDL" xil_pn:valueState="default"/>
<property xil_pn:name="JTAG Pin TCK" xil_pn:value="Pull Up" xil_pn:valueState="default"/>
<property xil_pn:name="JTAG Pin TDI" xil_pn:value="Pull Up" xil_pn:valueState="default"/>
<property xil_pn:name="JTAG Pin TDO" xil_pn:value="Pull Up" xil_pn:valueState="default"/>
<property xil_pn:name="JTAG Pin TMS" xil_pn:value="Pull Up" xil_pn:valueState="default"/>
<property xil_pn:name="Keep Hierarchy" xil_pn:value="No" xil_pn:valueState="default"/>
<property xil_pn:name="Language" xil_pn:value="VHDL" xil_pn:valueState="default"/>
<property xil_pn:name="Last Applied Goal" xil_pn:value="Balanced" xil_pn:valueState="default"/>
<property xil_pn:name="Last Applied Strategy" xil_pn:value="Xilinx Default (unlocked)" xil_pn:valueState="default"/>
<property xil_pn:name="Last Unlock Status" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Library Search Order" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Load Physical Constraints File" xil_pn:value="Default" xil_pn:valueState="default"/>
<property xil_pn:name="Load Setting File" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Load Simulation File" xil_pn:value="Default" xil_pn:valueState="default"/>
<property xil_pn:name="Logical Shifter Extraction" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Macro Search Path" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Manual Implementation Compile Order" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Map Effort Level" xil_pn:value="Standard" xil_pn:valueState="default"/>
<property xil_pn:name="Map Slice Logic into Unused Block RAMs" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Max Fanout" xil_pn:value="500" xil_pn:valueState="default"/>
<property xil_pn:name="Maximum Number of Lines in Report" xil_pn:value="1000" xil_pn:valueState="default"/>
<property xil_pn:name="Move First Flip-Flop Stage" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Move Last Flip-Flop Stage" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Multiplier Style" xil_pn:value="Auto" xil_pn:valueState="default"/>
<property xil_pn:name="Mux Extraction" xil_pn:value="Yes" xil_pn:valueState="default"/>
<property xil_pn:name="Mux Style" xil_pn:value="Auto" xil_pn:valueState="default"/>
<property xil_pn:name="Netlist Hierarchy" xil_pn:value="As Optimized" xil_pn:valueState="default"/>
<property xil_pn:name="Netlist Translation Type" xil_pn:value="Timestamp" xil_pn:valueState="default"/>
<property xil_pn:name="Number of Clock Buffers" xil_pn:value="8" xil_pn:valueState="default"/>
<property xil_pn:name="Number of Paths in Error/Verbose Report" xil_pn:value="3" xil_pn:valueState="default"/>
<property xil_pn:name="Number of Paths in Error/Verbose Report Post Trace" xil_pn:value="3" xil_pn:valueState="default"/>
<property xil_pn:name="Optimization Effort" xil_pn:value="Normal" xil_pn:valueState="default"/>
<property xil_pn:name="Optimization Goal" xil_pn:value="Speed" xil_pn:valueState="default"/>
<property xil_pn:name="Optimization Strategy (Cover Mode)" xil_pn:value="Area" xil_pn:valueState="default"/>
<property xil_pn:name="Optimize Instantiated Primitives" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Other Bitgen Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Other Compiler Options" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Other Compiler Options Par" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Other Compxlib Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Other Map Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Other NETGEN Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Other Ngdbuild Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Other Place &amp; Route Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Other XPWR Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Other XST Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Output Extended Identifiers" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Output File Name" xil_pn:value="streamtest_top" xil_pn:valueState="default"/>
<property xil_pn:name="Overwrite Compiled Libraries" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Pack I/O Registers into IOBs" xil_pn:value="Auto" xil_pn:valueState="default"/>
<property xil_pn:name="Pack I/O Registers/Latches into IOBs" xil_pn:value="For Inputs and Outputs" xil_pn:valueState="non-default"/>
<property xil_pn:name="Package" xil_pn:value="ft256" xil_pn:valueState="non-default"/>
<property xil_pn:name="Path Used in sdf_annotate task" xil_pn:value="Default" xil_pn:valueState="default"/>
<property xil_pn:name="Path(s) to Previously Compiled EDK Libraries" xil_pn:value="Search in Path" xil_pn:valueState="default"/>
<property xil_pn:name="Perform Advanced Analysis" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Perform Advanced Analysis Post Trace" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Perform Timing-Driven Packing and Placement" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Place &amp; Route Effort Level (Overall)" xil_pn:value="Standard" xil_pn:valueState="default"/>
<property xil_pn:name="Place And Route Mode" xil_pn:value="Normal Place and Route" xil_pn:valueState="default"/>
<property xil_pn:name="Placer Effort Level (Overrides Overall Level)" xil_pn:value="None" xil_pn:valueState="default"/>
<property xil_pn:name="Port to be used" xil_pn:value="Auto - default" xil_pn:valueState="default"/>
<property xil_pn:name="Post Map Simulation Model Name" xil_pn:value="streamtest_top_map.vhd" xil_pn:valueState="default"/>
<property xil_pn:name="Post Place &amp; Route Simulation Model Name" xil_pn:value="streamtest_top_timesim.vhd" xil_pn:valueState="default"/>
<property xil_pn:name="Post Synthesis Simulation Model Name" xil_pn:value="streamtest_top_synthesis.vhd" xil_pn:valueState="default"/>
<property xil_pn:name="Post Translate Simulation Model Name" xil_pn:value="streamtest_top_translate.vhd" xil_pn:valueState="default"/>
<property xil_pn:name="Power Activity File Map" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Power Activity File Par" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Power Reduction Map" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Power Reduction Par" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Preferred Language" xil_pn:value="VHDL" xil_pn:valueState="non-default"/>
<property xil_pn:name="Priority Encoder Extraction" xil_pn:value="Yes" xil_pn:valueState="default"/>
<property xil_pn:name="Produce Advanced Verbose Report" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Produce Verbose Report" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Project Description" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Property Specification in Project File" xil_pn:value="Store all values" xil_pn:valueState="default"/>
<property xil_pn:name="RAM Extraction" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="RAM Style" xil_pn:value="Auto" xil_pn:valueState="default"/>
<property xil_pn:name="ROM Extraction" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="ROM Style" xil_pn:value="Auto" xil_pn:valueState="default"/>
<property xil_pn:name="Read Cores" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Regenerate Core" xil_pn:value="Under Current Project Setting" xil_pn:valueState="default"/>
<property xil_pn:name="Register Balancing" xil_pn:value="No" xil_pn:valueState="default"/>
<property xil_pn:name="Register Duplication" xil_pn:value="Off" xil_pn:valueState="default"/>
<property xil_pn:name="Register Duplication Xst" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Release Write Enable (Output Events)" xil_pn:value="Default (6)" xil_pn:valueState="default"/>
<property xil_pn:name="Rename Design Instance in Testbench File to" xil_pn:value="UUT" xil_pn:valueState="default"/>
<property xil_pn:name="Rename Top Level Architecture To" xil_pn:value="Structure" xil_pn:valueState="default"/>
<property xil_pn:name="Rename Top Level Entity to" xil_pn:value="streamtest_top" xil_pn:valueState="default"/>
<property xil_pn:name="Rename Top Level Module To" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Report Fastest Path(s) in Each Constraint" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Report Fastest Path(s) in Each Constraint Post Trace" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Report Paths by Endpoint" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Report Paths by Endpoint Post Trace" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Report Type" xil_pn:value="Verbose Report" xil_pn:valueState="default"/>
<property xil_pn:name="Report Type Post Trace" xil_pn:value="Verbose Report" xil_pn:valueState="default"/>
<property xil_pn:name="Report Unconstrained Paths" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Report Unconstrained Paths Post Trace" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Reset DCM if SHUTDOWN &amp; AGHIGH performed" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Reset On Configuration Pulse Width" xil_pn:value="100" xil_pn:valueState="default"/>
<property xil_pn:name="Resource Sharing" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Retain Hierarchy" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Router Effort Level (Overrides Overall Level)" xil_pn:value="None" xil_pn:valueState="default"/>
<property xil_pn:name="Run Design Rules Checker (DRC)" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Run for Specified Time" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Run for Specified Time Par" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="SAIF File Name ISim" xil_pn:value="xpower_time_sim.saif" xil_pn:valueState="default"/>
<property xil_pn:name="SDK Export Directory" xil_pn:value="SDK_Export" xil_pn:valueState="default"/>
<property xil_pn:name="Safe Implementation" xil_pn:value="Yes" xil_pn:valueState="non-default"/>
<property xil_pn:name="Security" xil_pn:value="Enable Readback and Reconfiguration" xil_pn:valueState="default"/>
<property xil_pn:name="Selected Simulation Root Source Node Behavioral" xil_pn:value="Architecture|streamtest_top|streamtest_top_arch" xil_pn:valueState="non-default"/>
<property xil_pn:name="Selected Simulation Root Source Node Post-Route" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Selected Simulation Source Node" xil_pn:value="UUT" xil_pn:valueState="default"/>
<property xil_pn:name="Setting Output File" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Shift Register Extraction" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Show All Models" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Simulation Model Target" xil_pn:value="VHDL" xil_pn:valueState="default"/>
<property xil_pn:name="Simulation Run Time ISim" xil_pn:value="1000 ns" xil_pn:valueState="default"/>
<property xil_pn:name="Simulation Run Time Par" xil_pn:value="1000 ns" xil_pn:valueState="default"/>
<property xil_pn:name="Simulator" xil_pn:value="ISim (VHDL/Verilog)" xil_pn:valueState="default"/>
<property xil_pn:name="Simulator Path" xil_pn:value="Search in Path" xil_pn:valueState="default"/>
<property xil_pn:name="Slice Packing" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Slice Utilization Ratio" xil_pn:value="100" xil_pn:valueState="default"/>
<property xil_pn:name="Smart Guide File Name" xil_pn:value="streamtest_top_guide.ncd" xil_pn:valueState="default"/>
<property xil_pn:name="Specify 'define Macro Name and Value" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Specify Search Directories for 'Include" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Specify Source Libraries Path" xil_pn:value="Search in Path" xil_pn:valueState="default"/>
<property xil_pn:name="Specify Top Level Instance Names Behavioral" xil_pn:value="streamtest_top" xil_pn:valueState="default"/>
<property xil_pn:name="Specify Top Level Instance Names Post-Route" xil_pn:value="Default" xil_pn:valueState="default"/>
<property xil_pn:name="Speed Grade" xil_pn:value="-4" xil_pn:valueState="non-default"/>
<property xil_pn:name="Stamp Timing Model Filename" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Starting Placer Cost Table (1-100) Map" xil_pn:value="1" xil_pn:valueState="default"/>
<property xil_pn:name="Starting Placer Cost Table (1-100) Par" xil_pn:value="1" xil_pn:valueState="default"/>
<property xil_pn:name="Synthesis Constraints File" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Synthesis Tool" xil_pn:value="XST (VHDL/Verilog)" xil_pn:valueState="default"/>
<property xil_pn:name="Target UCF File Name" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Timing Mode Map" xil_pn:value="Non Timing Driven" xil_pn:valueState="default"/>
<property xil_pn:name="Timing Mode Par" xil_pn:value="Performance Evaluation" xil_pn:valueState="default"/>
<property xil_pn:name="Top-Level Module Name in Output Netlist" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Top-Level Source Type" xil_pn:value="HDL" xil_pn:valueState="default"/>
<property xil_pn:name="Trim Unconnected Signals" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Tristate On Configuration Pulse Width" xil_pn:value="0" xil_pn:valueState="default"/>
<property xil_pn:name="Unused IOB Pins" xil_pn:value="Pull Down" xil_pn:valueState="default"/>
<property xil_pn:name="Use Bonded I/Os" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Use Clock Enable" xil_pn:value="Yes" xil_pn:valueState="default"/>
<property xil_pn:name="Use Custom Project File Behavioral" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Use Custom Project File Post-Route" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Use Custom Simulation Command File Behavioral" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Use Custom Simulation Command File Par" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Use Custom Waveform Configuration File Behav" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Use Custom Waveform Configuration File Par" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Use LOC Constraints" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Use RLOC Constraints" xil_pn:value="Yes" xil_pn:valueState="default"/>
<property xil_pn:name="Use Smart Guide" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Use Synchronous Reset" xil_pn:value="Yes" xil_pn:valueState="default"/>
<property xil_pn:name="Use Synchronous Set" xil_pn:value="Yes" xil_pn:valueState="default"/>
<property xil_pn:name="Use Synthesis Constraints File" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="User Browsed Strategy Files" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="User Rules File for Netlister Launcher" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="UserID Code (8 Digit Hexadecimal)" xil_pn:value="0xFFFFFFFF" xil_pn:valueState="default"/>
<property xil_pn:name="Value Range Check" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Verilog 2001 Xst" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Verilog Include Directories" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Verilog Macros" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Wait for DCI Match (Output Events) virtex2" xil_pn:value="Auto" xil_pn:valueState="default"/>
<property xil_pn:name="Wait for DLL Lock (Output Events)" xil_pn:value="3" xil_pn:valueState="non-default"/>
<property xil_pn:name="Waveform Database Filename Behavioral" xil_pn:value="streamtest_top_isim_beh.wdb" xil_pn:valueState="default"/>
<property xil_pn:name="Waveform Database Filename Post-Route" xil_pn:value="top_isim_par.wdb" xil_pn:valueState="default"/>
<property xil_pn:name="Work Directory" xil_pn:value="xst" xil_pn:valueState="default"/>
<property xil_pn:name="Working Directory" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Write Timing Constraints" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="XOR Collapsing" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="iMPACT Project File" xil_pn:value="Default" xil_pn:valueState="default"/>
<!-- -->
<!-- The following properties are for internal use only. These should not be modified.-->
<!-- -->
<property xil_pn:name="PROP_BehavioralSimTop" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="PROP_DesignName" xil_pn:value="streamtest" xil_pn:valueState="non-default"/>
<property xil_pn:name="PROP_DevFamilyPMName" xil_pn:value="spartan3" xil_pn:valueState="default"/>
<property xil_pn:name="PROP_PartitionCreateDelete" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="PROP_PartitionForcePlacement" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="PROP_PartitionForceSynth" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="PROP_PartitionForceTranslate" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="PROP_PostMapSimTop" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="PROP_PostParSimTop" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="PROP_PostSynthSimTop" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="PROP_PostXlateSimTop" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="PROP_intWorkingDirLocWRTProjDir" xil_pn:value="Same" xil_pn:valueState="non-default"/>
<property xil_pn:name="PROP_intWorkingDirUsed" xil_pn:value="No" xil_pn:valueState="non-default"/>
</properties>
 
<bindings/>
 
<libraries/>
 
<partitions/>
 
</project>
/trunk/syn/streamtest_digilent-xc3s200/streamtest.ucf
0,0 → 1,43
# Constraints for Digilent XC3S200 board.
 
# Board clock, 50 MHz = 20 ns nominal, - 2 ns margin = 18 ns
NET "clk50" TNM_NET = "clk50" ;
TIMESPEC "TS_clk" = PERIOD "clk50" 18.0 ns ;
 
# Paths between fastclk and sysclk must be constrained to fastclk period.
# fastclk = 200 MHz = 5 ns nominal, - 1 ns margin = 4 ns
NET "sysclk" TNM_NET = "sysclk" ;
NET "fastclk" TNM_NET = "fastclk" ;
TIMESPEC "TS_fast_to_sys" = FROM "fastclk" TO "sysclk" 4 ns ;
TIMESPEC "TS_sys_to_fast" = FROM "sysclk" TO "fastclk" 4 ns ;
 
NET "clk50" LOC = "T9" ;
NET "led(0)" LOC = "K12" | DRIVE = 6 ;
NET "led(1)" LOC = "P14" | DRIVE = 6 ;
NET "led(2)" LOC = "L12" | DRIVE = 6 ;
NET "led(3)" LOC = "N14" | DRIVE = 6 ;
NET "led(4)" LOC = "P13" | DRIVE = 6 ;
NET "led(5)" LOC = "N12" | DRIVE = 6 ;
NET "led(6)" LOC = "P12" | DRIVE = 6 ;
NET "led(7)" LOC = "P11" | DRIVE = 6 ;
NET "button(0)" LOC = "M13" ;
NET "button(1)" LOC = "M14" ;
NET "button(2)" LOC = "L13" ;
NET "button(3)" LOC = "L14" ;
NET "switch(0)" LOC = "F12" ;
NET "switch(1)" LOC = "G12" ;
NET "switch(2)" LOC = "H14" ;
NET "switch(3)" LOC = "H13" ;
NET "switch(4)" LOC = "J14" ;
NET "switch(5)" LOC = "J13" ;
NET "switch(6)" LOC = "K14" ;
NET "switch(7)" LOC = "K13" ;
NET "spw_di_p" LOC = "B5" ; # | IOSTANDARD = LVDS_25;
NET "spw_di_n" LOC = "C5" ; # | IOSTANDARD = LVDS_25;
NET "spw_si_p" LOC = "D6" ; # | IOSTANDARD = LVDS_25;
NET "spw_si_n" LOC = "E6" ; # | IOSTANDARD = LVDS_25;
NET "spw_do_p" LOC = "B6" ; # | IOSTANDARD = LVDS_25;
NET "spw_do_n" LOC = "C6" ; # | IOSTANDARD = LVDS_25;
NET "spw_so_p" LOC = "D7" ; # | IOSTANDARD = LVDS_25;
NET "spw_so_n" LOC = "E7" ; # | IOSTANDARD = LVDS_25;
 
/trunk/syn/streamtest_digilent-xc3s200/streamtest_top.vhd
0,0 → 1,253
--
-- Test of spwstream on Digilent XC3S200 board.
--
-- LED 0 = link started
-- LED 1 = link connecting
-- LED 2 = link run
-- LED 3 = link error (sticky until clear button)
-- LED 4 = gotdata
-- LED 5 = off
-- LED 6 = data error (sticky until reset)
-- LED 7 = time code error (sticky until reset)
--
-- Button 0 = reset
-- Button 1 = clear LED 3
--
-- Switch 0 = link autostart
-- Switch 1 = link start
-- Switch 2 = link disable
-- Switch 3 = send data and time codes
-- Switch 4-7 = bits 0-3 of tx bit rate scale factor
--
-- SpaceWire signals on A2 expansion connector:
-- Data In pos,neg = B5,C5 = pin 19,6
-- Strobe In pos,neg = D6,E6 = pin 7,4
-- Data Out pos,neg = B6,C6 = pin 21,8
-- Strobe Out pos,neg = D7,E7 = pin 11,9
--
-- Note: these are not true LVDS signals; they are configured as LVDS25
-- but powered from 3.3V instead of 2.5V, not differentially routed and
-- not properly terminated.
--
-- The SpaceWire port should be looped back to itself with wires from
-- outputs to corresponding inputs.
--
 
library ieee;
use ieee.std_logic_1164.all, ieee.numeric_std.all;
library unisim;
use unisim.vcomponents.all;
use work.spwpkg.all;
 
entity streamtest_top is
 
port (
clk50: in std_logic;
button: in std_logic_vector(3 downto 0);
switch: in std_logic_vector(7 downto 0);
led: out std_logic_vector(7 downto 0);
spw_di_p: in std_logic;
spw_di_n: in std_logic;
spw_si_p: in std_logic;
spw_si_n: in std_logic;
spw_do_p: out std_logic;
spw_do_n: out std_logic;
spw_so_p: out std_logic;
spw_so_n: out std_logic );
 
end entity streamtest_top;
 
architecture streamtest_top_arch of streamtest_top is
 
-- Clock generation.
signal boardclk: std_logic;
signal sysclk: std_logic;
signal fastclk: std_logic;
 
-- Synchronize buttons
signal s_resetbtn: std_logic := '0';
signal s_clearbtn: std_logic := '0';
 
-- Sticky LED
signal s_linkerrorled: std_logic := '0';
 
-- Interface signals.
signal s_rst: std_logic := '1';
signal s_linkstart: std_logic := '0';
signal s_autostart: std_logic := '0';
signal s_linkdisable: std_logic := '0';
signal s_senddata: std_logic := '0';
signal s_txdivcnt: std_logic_vector(7 downto 0) := "00000000";
signal s_linkstarted: std_logic;
signal s_linkconnecting: std_logic;
signal s_linkrun: std_logic;
signal s_linkerror: std_logic;
signal s_gotdata: std_logic;
signal s_dataerror: std_logic;
signal s_tickerror: std_logic;
signal s_spwdi: std_logic;
signal s_spwsi: std_logic;
signal s_spwdo: std_logic;
signal s_spwso: std_logic;
 
-- Make clock nets visible to UCF file.
attribute KEEP: string;
attribute KEEP of sysclk: signal is "SOFT";
attribute KEEP of fastclk: signal is "SOFT";
 
component streamtest is
generic (
sysfreq: real;
tickdiv: integer range 12 to 24 := 20;
rximpl: spw_implementation_type := impl_generic;
rxchunk: integer range 1 to 4 := 1;
tximpl: spw_implementation_type := impl_generic;
rxfifosize_bits: integer range 6 to 14 := 11;
txfifosize_bits: integer range 2 to 14 := 11 );
port (
clk: in std_logic;
rxclk: in std_logic;
txclk: in std_logic;
rst: in std_logic;
linkstart: in std_logic;
autostart: in std_logic;
linkdisable: in std_logic;
senddata: in std_logic;
sendtick: in std_logic;
txdivcnt: in std_logic_vector(7 downto 0);
linkstarted: out std_logic;
linkconnecting: out std_logic;
linkrun: out std_logic;
linkerror: out std_logic;
gotdata: out std_logic;
dataerror: out std_logic;
tickerror: out std_logic;
spw_di: in std_logic;
spw_si: in std_logic;
spw_do: out std_logic;
spw_so: out std_logic );
end component;
 
begin
 
-- Buffer incoming clock.
bufg0: BUFG port map ( I => clk50, O => boardclk );
 
-- Generate 60 MHz system clock.
dcm0: DCM
generic map (
CLKFX_DIVIDE => 5,
CLKFX_MULTIPLY => 6,
CLK_FEEDBACK => "NONE",
CLKIN_DIVIDE_BY_2 => false,
CLKIN_PERIOD => 20.0,
CLKOUT_PHASE_SHIFT => "NONE",
DESKEW_ADJUST => "SYSTEM_SYNCHRONOUS",
DFS_FREQUENCY_MODE => "LOW",
DUTY_CYCLE_CORRECTION => true,
STARTUP_WAIT => true )
port map (
CLKIN => boardclk,
RST => '0',
CLKFX => sysclk );
 
-- Generate 200 MHz fast clock.
dcm1: DCM
generic map (
CLKFX_DIVIDE => 1,
CLKFX_MULTIPLY => 4,
CLK_FEEDBACK => "NONE",
CLKIN_DIVIDE_BY_2 => false,
CLKIN_PERIOD => 20.0,
CLKOUT_PHASE_SHIFT => "NONE",
DESKEW_ADJUST => "SYSTEM_SYNCHRONOUS",
DFS_FREQUENCY_MODE => "LOW",
DUTY_CYCLE_CORRECTION => true,
STARTUP_WAIT => true )
port map (
CLKIN => boardclk,
RST => '0',
CLKFX => fastclk );
 
-- Streamtest instance
streamtest_inst: streamtest
generic map (
sysfreq => 60.0e6,
tickdiv => 22,
rximpl => impl_fast,
rxchunk => 4,
tximpl => impl_fast,
rxfifosize_bits => 11,
txfifosize_bits => 10 )
port map (
clk => sysclk,
rxclk => fastclk,
txclk => fastclk,
rst => s_rst,
linkstart => s_linkstart,
autostart => s_autostart,
linkdisable => s_linkdisable,
senddata => s_senddata,
sendtick => s_senddata,
txdivcnt => s_txdivcnt,
linkstarted => s_linkstarted,
linkconnecting => s_linkconnecting,
linkrun => s_linkrun,
linkerror => s_linkerror,
gotdata => s_gotdata,
dataerror => s_dataerror,
tickerror => s_tickerror,
spw_di => s_spwdi,
spw_si => s_spwsi,
spw_do => s_spwdo,
spw_so => s_spwso );
 
-- LVDS buffers
spwdi_pad: IBUFDS
generic map ( IOSTANDARD => "LVDS_25" )
port map ( O => s_spwdi, I => spw_di_p, IB => spw_di_n );
spwsi_pad: IBUFDS
generic map ( IOSTANDARD => "LVDS_25" )
port map ( O => s_spwsi, I => spw_si_p, IB => spw_si_n );
spwdo_pad: OBUFDS
generic map ( IOSTANDARD => "LVDS_25" )
port map ( O => spw_do_p, OB => spw_do_n, I => s_spwdo );
spwso_pad: OBUFDS
generic map ( IOSTANDARD => "LVDS_25" )
port map ( O => spw_so_p, OB => spw_so_n, I => s_spwso );
 
process (sysclk) is
begin
if rising_edge(sysclk) then
 
-- Synchronize buttons
s_resetbtn <= button(0);
s_rst <= s_resetbtn;
s_clearbtn <= button(1);
 
-- Synchronize switch settings
s_autostart <= switch(0);
s_linkstart <= switch(1);
s_linkdisable <= switch(2);
s_senddata <= switch(3);
s_txdivcnt(3 downto 0) <= switch(7 downto 4);
 
-- Sticky link error LED
s_linkerrorled <= (s_linkerrorled or s_linkerror) and
(not s_clearbtn) and
(not s_resetbtn);
 
-- Drive LEDs
led(0) <= s_linkstarted;
led(1) <= s_linkconnecting;
led(2) <= s_linkrun;
led(3) <= s_linkerrorled;
led(4) <= s_gotdata;
led(5) <= '0';
led(6) <= s_dataerror;
led(7) <= s_tickerror;
 
end if;
end process;
 
end architecture streamtest_top_arch;
/trunk/syn/streamtest_digilent-xc3s200/Makefile
0,0 → 1,296
 
###############################################################################
## ##
## project-dependent variables ##
## ##
###############################################################################
 
# The project name. The bit-file that is generated in the end will be named
# "$(PROJ).bit"
 
PROJ = streamtest
 
# The top-level entity to be instantiated
 
TOPLEVEL = streamtest_top
 
# The VHDL sources that need to be compiled during synthesis
 
RTLDIR = ../../rtl/vhdl
VHDL_SOURCES = streamtest_top.vhd \
$(RTLDIR)/streamtest.vhd \
$(RTLDIR)/spwpkg.vhd \
$(RTLDIR)/spwstream.vhd \
$(RTLDIR)/spwlink.vhd \
$(RTLDIR)/spwram.vhd \
$(RTLDIR)/spwrecv.vhd \
$(RTLDIR)/spwxmit.vhd \
$(RTLDIR)/spwxmit_fast.vhd \
$(RTLDIR)/spwrecvfront_generic.vhd \
$(RTLDIR)/spwrecvfront_fast.vhd
 
# Device type: Spartan-3 200 on Digilent board
 
FPGA_TYPE = xc3s200-ft256-4
 
# The default target; recommended targets: "bitfile" or "upload"
 
default : bitfile
 
UCFFILE = streamtest.ucf
 
###############################################################################
## ##
## miscellaneous project-independent variables & rules ##
## ##
###############################################################################
 
# use this to make most tools quieter
OPT_INTSTYLE = -intstyle ise
 
# Phony (non file creating) targets
 
.PHONY : default clean bitfile
 
clean :
$(RM) -rf *~ work dump.xst _ngo 'file graph' xlnx_auto_0_xdb
$(RM) $(PROJ).xst-script
$(RM) $(PROJ).lso $(PROJ).prj
$(RM) $(PROJ).ngc $(PROJ).xst.log $(PROJ).syr $(PROJ).srp $(PROJ).ngr
$(RM) $(PROJ).ngd $(PROJ).bld
$(RM) $(PROJ).twx $(PROJ).twr
$(RM) $(PROJ).pcf $(PROJ)_map.mrp $(PROJ)_map.ncd $(PROJ)_map.ngm
$(RM) $(PROJ).ncd $(PROJ).pad $(PROJ).par $(PROJ).xpi $(PROJ)_pad.csv $(PROJ)_pad.txt
$(RM) $(PROJ).bit $(PROJ).bgn $(PROJ).drc
$(RM) $(PROJ).ptwx $(PROJ).unroutes *.xrpt $(PROJ)_summary.xml $(PROJ)_usage.xml $(PROJ)_map.map
 
bitfile : $(PROJ).bit
 
###############################################################################
# #
# STAGE 1: "xst" (Xilinx Synthesis Tool) #
# needs: #
# #
# $(PROJ).vhdl #
# $(PROJ).prj - Project file (created below) #
# $(PROJ).lso - Library Search Order file (created below) #
# #
# created files: #
# #
# $(PROJ).ngc - netlist #
# $(PROJ).ngr - XILINX-XDB 0.1 STUB 0.1 ASCII / XILINX-XDM V1.2e #
# (optional, depending on the '-rtlview' option) #
# $(PROJ).xst.log - human-readable synthesis report #
# (AKA .syr, .srp) #
# #
# created directories: #
# #
# work #
# dump.xst #
# #
###############################################################################
 
# Generate a "Library Search Order" file, containing just "work" for now.
 
$(PROJ).lso :
@echo "work" > $@
 
# Generate a "Project" file, consisting of lines containing each of the
# VHDL_SOURCES, preceded by "vhdl work".
 
$(PROJ).prj :
$(shell echo -n $(VHDL_SOURCES) | \
sed 's/\([^ ]\+\) */vhdl work \1\n/g' > $@)
 
$(PROJ).xst-script :
@echo "set -tmpdir /tmp" > $@
@echo "set -xsthdpdir ." >> $@
@echo "run" >> $@
@echo "-ifn $(PROJ).prj" >> $@
@echo "-ifmt mixed" >> $@
@echo "-ofn $(PROJ)" >> $@
@echo "-ofmt ngc" >> $@
@echo "-p $(FPGA_TYPE)" >> $@
@echo "-top $(TOPLEVEL)" >> $@
@echo "-opt_mode speed" >> $@
@echo "-opt_level 1" >> $@
@echo "-iuc no" >> $@
@echo "-lso $(PROJ).lso" >> $@
@echo "-keep_hierarchy no" >> $@
@echo "-glob_opt AllClockNets" >> $@
@echo "-rtlview no" >> $@
@echo "-read_cores yes" >> $@
# Note: write_timing_constraints is non-standard
@echo "-write_timing_constraints yes" >> $@
@echo "-cross_clock_analysis no" >> $@
# @echo "-hierarchy_separator _" >> $@
@echo "-bus_delimiter <>" >> $@
@echo "-case maintain" >> $@
@echo "-slice_utilization_ratio 100" >> $@
# @echo "-verilog2001 yes" >> $@
# @echo "-vlgincdir" >> $@
@echo "-fsm_extract yes" >> $@
@echo "-fsm_encoding auto" >> $@
@echo "-fsm_style lut" >> $@
# Note: safe_implementation is non-standard
@echo "-safe_implementation yes" >> $@
@echo "-ram_extract yes" >> $@
@echo "-ram_style auto" >> $@
@echo "-rom_extract yes" >> $@
@echo "-rom_style auto" >> $@
@echo "-mux_extract yes" >> $@
@echo "-mux_style auto" >> $@
@echo "-decoder_extract yes" >> $@
@echo "-priority_extract yes" >> $@
@echo "-shreg_extract yes" >> $@
@echo "-shift_extract yes" >> $@
@echo "-xor_collapse yes" >> $@
@echo "-resource_sharing yes" >> $@
@echo "-mult_style auto" >> $@
@echo "-iobuf yes" >> $@
@echo "-max_fanout 500" >> $@
@echo "-bufg 8" >> $@
@echo "-register_duplication yes" >> $@
@echo "-equivalent_register_removal yes" >> $@
@echo "-register_balancing no" >> $@
@echo "-slice_packing yes" >> $@
@echo "-optimize_primitives no" >> $@
@echo "-iob auto" >> $@
 
$(PROJ).ngc $(PROJ).xst.log : $(VHDL_SOURCES) $(PROJ).prj $(PROJ).lso $(PROJ).xst-script
rm -rf work dump.xst
xst $(OPT_INTSTYLE) -ifn $(PROJ).xst-script -ofn $(PROJ).xst.log
rm -rf work dump.xst
 
###############################################################################
# #
# STAGE 2: ngdbuild #
# needs: #
# #
# $(PROJ).ngc #
# #
# created files: #
# #
# $(PROJ).bld - human-readable build log #
# $(PROJ).ngd - XILINX-XDB 0.1 STUB 0.1 ASCII / XILINX-XDM V1.2e #
# #
# created dir: #
# _ngo #
# #
###############################################################################
 
$(PROJ).ngd $(PROJ).bld: $(PROJ).ngc $(UCFFILE)
rm -rf _ngo
ngdbuild $(OPT_INTSTYLE) -dd _ngo -aul -p $(FPGA_TYPE) $(if $(UCFFILE),-uc $(UCFFILE)) $(PROJ).ngc $(PROJ).ngd
rm -rf _ngo
 
###############################################################################
# #
# STAGE 3: Mapper #
# needs: #
# #
# $(PROJ).ngd #
# #
# created files: #
# #
# $(PROJ).pcf - ASCII file #
# $(PROJ)_map.mrp - human-readable mapping report #
# $(PROJ)_map.ncd - binary format #
# $(PROJ)_map.ngm - XILINX-XDB 0.1 STUB 0.1 ASCII / XILINX-XDM V1.2e #
# #
# NOTE: #
# #
# In order to prevent the make process from terminating on these spurious #
# problems, we precede the "map" invocation with a hyphen, instructing #
# make to ignore the return code from "map". #
# #
###############################################################################
 
$(PROJ).pcf $(PROJ)_map.mrp $(PROJ)_map.ncd $(PROJ)_map.ngm: $(PROJ).ngd
map $(OPT_INTSTYLE) -p $(FPGA_TYPE) -cm area -pr b -c 100 -o $(PROJ)_map.ncd $(PROJ).ngd $(PROJ).pcf
 
###############################################################################
# #
# STAGE 4: Place-and-Route #
# needs: #
# #
# $(PROJ).pcf #
# $(PROJ)_map.ncd #
# #
# created files: #
# #
# $(PROJ).ncd - binary file #
# $(PROJ).pad - ASCII file for import in spreadsheet #
# $(PROJ).par - human-readable place-and-route report #
# $(PROJ).xpi - ASCII file #
# $(PROJ)_pad.csv - human-readable CVS file #
# $(PROJ)_pad.txt - human-readable file #
# #
###############################################################################
 
$(PROJ).ncd $(PROJ).pad $(PROJ).par $(PROJ).xpi $(PROJ)_pad.csv $(PROJ)_pad.txt: $(PROJ).pcf $(PROJ)_map.ncd
par -w $(OPT_INTSTYLE) -t 1 $(PROJ)_map.ncd $(PROJ).ncd $(PROJ).pcf
 
###############################################################################
# #
# STAGE 4.5 (optional): trace #
# needs: #
# #
# created files: #
# #
###############################################################################
 
$(PROJ).twr $(PROJ).twx : $(PROJ).ncd $(PROJ).pcf
trce $(OPT_INTSTYLE) -e 5 -l 5 -u 5 -xml $(PROJ) $(PROJ).ncd -o $(PROJ).twr $(PROJ).pcf
 
###############################################################################
# #
# STAGE 5: Generate BIT-file #
# needs: #
# #
# $(PROJ).ncd #
# #
# created files: $(PROJ).bgn $(PROJ).bit $(PROJ).drc #
# #
# $(PROJ).bgn - human-readable BitGen report #
# $(PROJ).drc - human readable DRC report #
# $(PROJ).bit - binary image file #
# #
###############################################################################
 
# We omit "-g StartUpClk:JtagClk" ; this doesn't work if the image is loaded
# from a PROM.
 
# Note: LCK_cycle:3 is non-standard
OPT_BITGEN = -w \
-g DebugBitstream:No \
-g Binary:no \
-g CRC:Enable \
-g ConfigRate:6 \
-g CclkPin:PullUp \
-g M0Pin:PullUp \
-g M1Pin:PullUp \
-g M2Pin:PullUp \
-g ProgPin:PullUp \
-g DonePin:PullUp \
-g TckPin:PullUp \
-g TdiPin:PullUp \
-g TdoPin:PullUp \
-g TmsPin:PullUp \
-g UnusedPin:PullDown \
-g UserID:0xFFFFFFFF \
-g DCMShutDown:Disable \
-g DONE_cycle:4 \
-g GTS_cycle:5 \
-g GWE_cycle:6 \
-g LCK_cycle:3 \
-g Match_cycle:Auto \
-g Security:None \
-g DonePipe:No \
-g DriveDone:No
 
$(PROJ).bit $(PROJ).bgn $(PROJ).drc: $(PROJ).ncd
bitgen $(OPT_INTSTYLE) $(OPT_BITGEN) $(PROJ).ncd
 
###############################################################################
 
/trunk/LGPL-2.1.txt
0,0 → 1,510
 
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
 
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
 
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
 
Preamble
 
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
 
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations
below.
 
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
 
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
 
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
 
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
 
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
 
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
 
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
 
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
 
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it
becomes a de-facto standard. To achieve this, non-free programs must
be allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
 
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
 
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
 
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
 
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
 
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
 
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
 
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control
compilation and installation of the library.
 
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
 
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
 
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
 
a) The modified work must itself be a software library.
 
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
 
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
 
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
 
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
 
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
 
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
 
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
 
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
 
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
 
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
 
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
 
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
 
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
 
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
 
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
 
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
 
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
 
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
 
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
 
c) Accompany the work with a written offer, valid for at least
three years, to give the same user the materials specified in
Subsection 6a, above, for a charge no more than the cost of
performing this distribution.
 
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
 
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
 
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
 
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
 
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
 
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
 
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
 
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
 
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
 
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply, and the section as a whole is intended to apply in other
circumstances.
 
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
 
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
 
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License
may add an explicit geographical distribution limitation excluding those
countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
 
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
 
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
 
NO WARRANTY
 
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
 
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
 
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
 
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms
of the ordinary General Public License).
 
To apply these terms, attach the following notices to the library.
It is safest to attach them to the start of each source file to most
effectively convey the exclusion of warranty; and each file should
have at least the "copyright" line and a pointer to where the full
notice is found.
 
 
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 
Also add information on how to contact you by electronic and paper mail.
 
You should also get your employer (if you work as a programmer) or
your school, if any, to sign a "copyright disclaimer" for the library,
if necessary. Here is a sample; alter the names:
 
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James
Random Hacker.
 
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
 
That's all there is to it!
 
 
/trunk/README.txt
0,0 → 1,62
 
SpaceWire Light
===============
 
Copyright 2009-2010 Joris van Rantwijk
 
SpaceWire Light is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License
as published by the Free Software Foundation; either version 2.1
of the License, or (at your option) any later version.
 
SpaceWire Light is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with the SpaceWire Light package. If not, see
<http://www.gnu.org/licenses/>.
 
 
Overview
--------
 
SpaceWire Light is a SpaceWire encoder-decoder with FIFO interface.
It is synthesizable for FPGA targets (up to 200 Mbit on Spartan-3).
 
The goal is to provide a complete, reliable, fast implementation
of a SpaceWire encoder-decoder according to ECSS-E-50-12C.
The core is "light" in the sense that it does not provide additional
features such as RMAP, routing etc.
 
This core would be very suitable for application in lab environments,
to add a SpaceWire interface to a custom FPGA design, and for interfacing
between existing SpaceWire equipment and a computer.
 
The project is currently very much in alpha phase. Most importantly,
there is no proper documentation. I WILL PROVIDE DOCUMENTATION SOON.
 
Short term plan:
* more testing
* documentation
 
Long term plan:
* add AMBA bus interface
 
 
Contact
-------
 
For the latest version of this core, see the OpenCores project page.
 
For more information, comments, suggestions or bug reports, either
go to the OpenCores project page or email me directly.
 
Project page at OpenCores:
http://opencores.org/project,spacewire_light
 
Email:
jvrantwijk (at) xs4all (dot) nl
 
--

powered by: WebSVN 2.1.0

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