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

Subversion Repositories tosnet

Compare Revisions

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

Rev 1 → Rev 2

/trunk/gateware/TosNet_rev3_2/enc_8b10b.vhd
0,0 → 1,320
----------------------------------------------------------------------------------
-- Company: University of Southern Denmark
-- Engineer: Simon Falsig
--
-- Create Date: 11/5/2010
-- Design Name: 8b/10b encoder
-- Module Name: enc_8b10b - Behavioral
-- File Name: enc_8b10b.vhd
-- Project Name: TosNet
-- Target Devices: Spartan3/6
-- Tool versions: Xilinx ISE 12.2
-- Description: An 8b/10b encoder. The complete 8b/10b encoding is not
-- implemented though (only the control symbols K.28.1 and
-- K.28.5 are available, all others will just encode as K.28.1).
-- This is done to simplify and minimize the code, and as the
-- other control codes aren't used by the TosNet physical layer
-- anyways.
--
-- Revision:
-- Revision 3.2 - Initial release
--
-- Copyright 2010
--
-- This module 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 3 of the License, or
-- (at your option) any later version.
--
-- This module 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 module. If not, see <http://www.gnu.org/licenses/>.
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
 
entity enc_8b10b is
port ( clk : in STD_LOGIC;
ce : in STD_LOGIC;
din : in STD_LOGIC_VECTOR(7 downto 0);
dout : out STD_LOGIC_VECTOR(9 downto 0);
kin : in STD_LOGIC);
end enc_8b10b;
 
architecture Behavioral of enc_8b10b is
 
signal rd : STD_LOGIC := '0';
signal next_rd : STD_LOGIC;
signal temp_rd_s0 : STD_LOGIC; --Stage 0
signal temp_rd_k0 : STD_LOGIC; --Stage 1, k=0
signal dxA : STD_LOGIC;
signal EDCBA : STD_LOGIC_VECTOR(4 downto 0) := (others => '0');
signal HGF : STD_LOGIC_VECTOR(2 downto 0) := (others => '0');
signal iedcba : STD_LOGIC_VECTOR(5 downto 0) := (others => '0');
signal jhgf : STD_LOGIC_VECTOR(3 downto 0) := (others => '0');
begin
 
process(jhgf, iedcba, kin, rd, temp_rd_k0, EDCBA, HGF)
begin
if(kin = '0') then
dout <= jhgf & iedcba;
next_rd <= temp_rd_k0;
else
next_rd <= not rd;
if(HGF = "101" and EDCBA = "11100") then
if(rd = '0') then
dout <= "0101111100";
else
dout <= "1010000011";
end if;
else --Transmit K.28.1 => QUIET
if(rd = '0') then
dout <= "1001111100";
else
dout <= "0110000011";
end if;
end if;
end if;
end process;
 
process(clk)
begin
if(clk = '1' and clk'event) then
if(ce = '1') then
EDCBA <= din(4 downto 0);
HGF <= din(7 downto 5);
rd <= next_rd;
end if;
end if;
end process;
process(EDCBA, rd)
begin
case EDCBA is
when "00000" =>
temp_rd_s0 <= not rd;
if(rd = '0') then
iedcba <= "111001";
else
iedcba <= "000110";
end if;
when "00001" =>
temp_rd_s0 <= not rd;
if(rd = '0') then
iedcba <= "101110";
else
iedcba <= "010001";
end if;
when "00010" =>
temp_rd_s0 <= not rd;
if(rd = '0') then
iedcba <= "101101";
else
iedcba <= "010010";
end if;
when "00011" =>
temp_rd_s0 <= rd;
iedcba <= "100011";
when "00100" =>
temp_rd_s0 <= not rd;
if(rd = '0') then
iedcba <= "101011";
else
iedcba <= "010100";
end if;
when "00101" =>
temp_rd_s0 <= rd;
iedcba <= "100101";
when "00110" =>
temp_rd_s0 <= rd;
iedcba <= "100110";
when "00111" =>
temp_rd_s0 <= rd;
if(rd = '0') then
iedcba <= "000111";
else
iedcba <= "111000";
end if;
when "01000" =>
temp_rd_s0 <= not rd;
if(rd = '0') then
iedcba <= "100111";
else
iedcba <= "011000";
end if;
when "01001" =>
temp_rd_s0 <= rd;
iedcba <= "101001";
when "01010" =>
temp_rd_s0 <= rd;
iedcba <= "101010";
when "01011" =>
temp_rd_s0 <= rd;
iedcba <= "001011";
when "01100" =>
temp_rd_s0 <= rd;
iedcba <= "101100";
when "01101" =>
temp_rd_s0 <= rd;
iedcba <= "001101";
when "01110" =>
temp_rd_s0 <= rd;
iedcba <= "001110";
when "01111" =>
temp_rd_s0 <= not rd;
if(rd = '0') then
iedcba <= "111010";
else
iedcba <= "000101";
end if;
when "10000" =>
temp_rd_s0 <= not rd;
if(rd = '0') then
iedcba <= "110110";
else
iedcba <= "001001";
end if;
when "10001" =>
temp_rd_s0 <= rd;
iedcba <= "110001";
when "10010" =>
temp_rd_s0 <= rd;
iedcba <= "110010";
when "10011" =>
temp_rd_s0 <= rd;
iedcba <= "010011";
when "10100" =>
temp_rd_s0 <= rd;
iedcba <= "110100";
when "10101" =>
temp_rd_s0 <= rd;
iedcba <= "010101";
when "10110" =>
temp_rd_s0 <= rd;
iedcba <= "010110";
when "10111" =>
temp_rd_s0 <= not rd;
if(rd = '0') then
iedcba <= "010111";
else
iedcba <= "101000";
end if;
when "11000" =>
temp_rd_s0 <= not rd;
if(rd = '0') then
iedcba <= "110011";
else
iedcba <= "001100";
end if;
when "11001" =>
temp_rd_s0 <= rd;
iedcba <= "011001";
when "11010" =>
temp_rd_s0 <= rd;
iedcba <= "011010";
when "11011" =>
temp_rd_s0 <= not rd;
if(rd = '0') then
iedcba <= "011011";
else
iedcba <= "100100";
end if;
when "11100" =>
temp_rd_s0 <= rd;
iedcba <= "011100";
when "11101" =>
temp_rd_s0 <= not rd;
if(rd = '0') then
iedcba <= "011101";
else
iedcba <= "100010";
end if;
when "11110" =>
temp_rd_s0 <= not rd;
if(rd = '0') then
iedcba <= "011110";
else
iedcba <= "100001";
end if;
when "11111" =>
temp_rd_s0 <= not rd;
if(rd = '0') then
iedcba <= "110101";
else
iedcba <= "001010";
end if;
when others =>
end case;
end process;
dxA <= '1' when (((EDCBA = 17 or EDCBA = 18 or EDCBA = 20) and temp_rd_s0 = '0') or
((EDCBA = 11 or EDCBA = 13 or EDCBA = 14) and temp_rd_s0 = '1'))
else '0';
 
process(HGF, EDCBA, dxA, temp_rd_s0)
begin
case HGF is
when "000" =>
temp_rd_k0 <= not temp_rd_s0;
if(temp_rd_s0 = '0') then
jhgf <= "1101";
else
jhgf <= "0010";
end if;
when "001" =>
temp_rd_k0 <= temp_rd_s0;
jhgf <= "1001";
when "010" =>
temp_rd_k0 <= temp_rd_s0;
jhgf <= "1010";
when "011" =>
temp_rd_k0 <= not temp_rd_s0;
if(temp_rd_s0 = '0') then
jhgf <= "0011";
else
jhgf <= "1100";
end if;
when "100" =>
temp_rd_k0 <= not temp_rd_s0;
if(temp_rd_s0 = '0') then
jhgf <= "1011";
else
jhgf <= "0100";
end if;
when "101" =>
temp_rd_k0 <= temp_rd_s0;
jhgf <= "0101";
when "110" =>
temp_rd_k0 <= temp_rd_s0;
jhgf <= "0110";
when "111" =>
temp_rd_k0 <= not temp_rd_s0;
if(dxA = '0') then
if(temp_rd_s0 = '0') then
jhgf <= "0111";
else
jhgf <= "1000";
end if;
else
if(temp_rd_s0 = '0') then
jhgf <= "1110";
else
jhgf <= "0001";
end if;
end if;
when others =>
end case;
end process;
 
end Behavioral;
 
/trunk/gateware/TosNet_rev3_2/crcgen.vhd
0,0 → 1,127
----------------------------------------------------------------------------------
-- Company: University of Southern Denmark
-- Engineer: Simon Falsig
--
-- Create Date: 1/4/2010
-- Design Name 8bit CRC generator
-- Module Name: crcgen - Behavioral
-- File Name: crcgen.vhd
-- Project Name: TosNet
-- Target Devices: Spartan3/6
-- Tool versions: Xilinx ISE 12.2
-- Description: Adapted from "Parallel CRC Realization", by Guiseppe
 
-- Transactions on Computers, Vol.52, No.10, October 2003.
-- Adjustments have been made to the layout, the reset has been
-- converted to a synchronous reset instead of the asynchronous
-- reset from the original paper, and a clock enable has been
-- added.
--
-- Revision:
-- Revision 3.2 - Initial release
--
-- Copyright 2010
--
-- This module 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 3 of the License, or
-- (at your option) any later version.
--
-- This module 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 module. If not, see <http://www.gnu.org/licenses/>.
----------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.crcpack.all;
 
 
entity crcgen is
Port ( reset : in STD_LOGIC;
clk : in STD_LOGIC;
clk_en : in STD_LOGIC;
Din : in STD_LOGIC_VECTOR(DATA_WIDTH - 1 downto 0);
Xout : out STD_LOGIC_VECTOR(CRCDIM - 1 downto 0));
end crcgen;
 
 
architecture rtl of crcgen is
signal X : STD_LOGIC_VECTOR(CRCDIM - 1 downto 0);
signal X1 : STD_LOGIC_VECTOR(CRCDIM - 1 downto 0);
signal X2 : STD_LOGIC_VECTOR(CRCDIM - 1 downto 0);
signal Dins : STD_LOGIC_VECTOR(CRCDIM - 1 downto 0);
begin
 
process(Din)
variable Dinv : STD_LOGIC_VECTOR(CRCDIM - 1 downto 0);
begin
Dinv := (others => '0');
Dinv(DATA_WIDTH - 1 downto 0) := Din; --LFSR:
Dins <= Dinv;
end process;
 
X2 <= X ; --LFSR
 
process(clk)
begin
if(clk = '1' and clk'EVENT) then
if(reset = '1') then
X <= (others => '0');
elsif(clk_en = '1') then
X <= X1 xor Dins ; --LFSR
end if;
end if;
end process;
 
Xout <= X;
 
--This process builds matrix M=F^w
process(X2)
variable Xtemp : STD_LOGIC_VECTOR(CRCDIM - 1 downto 0);
variable vect : STD_LOGIC_VECTOR(CRCDIM - 1 downto 0);
variable vect2 : STD_LOGIC_VECTOR(CRCDIM - 1 downto 0);
variable M : matrix;
variable F : matrix;
begin
--Matrix F
F(0) := CRC(CRCDIM - 1 downto 0);
for i in 0 to CRCDIM - 2 loop
vect := (others => '0');
vect(CRCDIM - i - 1) := '1';
F(i+1) := vect;
end loop;
--Matrix M=F?w
M(DATA_WIDTH - 1) := CRC(CRCDIM - 1 downto 0);
for k in 2 to DATA_WIDTH loop
vect2 := M(DATA_WIDTH - k + 1 );
vect := (others => '0');
for i in 0 to CRCDIM - 1 loop
if(vect2(CRCDIM - 1 - i) = '1') then
vect := vect xor F(i);
end if;
end loop;
M(DATA_WIDTH - k) := vect;
end loop;
for k in DATA_WIDTH - 1 to CRCDIM - 1 loop
M(k) := F(k - DATA_WIDTH + 1);
end loop;
 
--Combinatorial logic equations : X1 = M ( x ) X
 
Xtemp := (others => '0');
for i in 0 to CRCDIM - 1 loop
vect := M(i);
for j in 0 to CRCDIM - 1 loop
if(vect(j) = '1') then
Xtemp(j) := Xtemp(j) xor X2(CRCDIM - 1 - i);
end if;
end loop;
end loop;
X1 <= Xtemp;
end process;
end rtl;
/trunk/gateware/TosNet_rev3_2/tal_top.vhd
0,0 → 1,1192
----------------------------------------------------------------------------------
-- Company: University of Southern Denmark
-- Engineer: Simon Falsig
--
-- Create Date: 17/3/2008
-- Design Name TosNet
-- Module Name: tal_top - Behavioral
-- File Name: tal_top.vhd
-- Project Name: TosNet
-- Target Devices: Spartan3/6
-- Tool versions: Xilinx ISE 12.2
-- Description: The TosNet application layer handles the shared memory block,
-- and keeps it updated. It also handles the FIFO buffers used
-- for the asynchronous communication.
--
-- Revision:
-- Revision 3.2 - Initial release
--
-- Copyright 2010
--
-- This module 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 3 of the License, or
-- (at your option) any later version.
--
-- This module 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 module. If not, see <http://www.gnu.org/licenses/>.
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.NUMERIC_STD.ALL;
 
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
 
entity tal_top is
Generic(disable_master : in STD_LOGIC := '0';
disable_slave : in STD_LOGIC := '1';
disable_async : in STD_LOGIC := '1');
Port ( node_id : in STD_LOGIC_VECTOR(3 downto 0);
max_skipped_writes : in STD_LOGIC_VECTOR(15 downto 0);
max_skipped_reads : in STD_LOGIC_VECTOR(15 downto 0);
data_in : in STD_LOGIC_VECTOR(7 downto 0);
data_in_strobe : in STD_LOGIC;
data_in_enable : in STD_LOGIC;
data_out : out STD_LOGIC_VECTOR(7 downto 0);
data_out_strobe : out STD_LOGIC;
data_out_enable : out STD_LOGIC;
buffer_full : in STD_LOGIC;
packet_error : in STD_LOGIC;
force_packet_error : out STD_LOGIC;
sync_strobe : in STD_LOGIC;
network_reg_addr : out STD_LOGIC_VECTOR(3 downto 0);
network_reg_data : in STD_LOGIC_VECTOR(31 downto 0);
network_reg_clk : out STD_LOGIC;
data_reg_addr : in STD_LOGIC_VECTOR(9 downto 0);
data_reg_data_in : in STD_LOGIC_VECTOR(31 downto 0);
data_reg_data_out : out STD_LOGIC_VECTOR(31 downto 0);
data_reg_clk : in STD_LOGIC;
data_reg_we : in STD_LOGIC_VECTOR(0 downto 0);
data_reg_commit_write : in STD_LOGIC;
data_reg_commit_read : in STD_LOGIC;
skip_count_write : out STD_LOGIC_VECTOR(15 downto 0);
skip_count_read : out STD_LOGIC_VECTOR(15 downto 0);
current_buffer_index : out STD_LOGIC_VECTOR(3 downto 0);
node_address : in STD_LOGIC_VECTOR(3 downto 0);
is_master : in STD_LOGIC;
clk_50M : in STD_LOGIC;
pause : in STD_LOGIC;
pause_ack : out STD_LOGIC;
reset : in STD_LOGIC;
system_halt : out STD_LOGIC;
reset_counter : out STD_LOGIC_VECTOR(31 downto 0);
packet_counter : out STD_LOGIC_VECTOR(31 downto 0);
error_counter : out STD_LOGIC_VECTOR(31 downto 0);
async_in_data : in STD_LOGIC_VECTOR(37 downto 0);
async_out_data : out STD_LOGIC_VECTOR(37 downto 0);
async_in_clk : in STD_LOGIC;
async_out_clk : in STD_LOGIC;
async_in_full : out STD_LOGIC;
async_out_empty : out STD_LOGIC;
async_in_wr_en : in STD_LOGIC;
async_out_rd_en : in STD_LOGIC;
async_out_valid : out STD_LOGIC);
end tal_top;
 
architecture Behavioral of tal_top is
constant ASYNC_M2S_VALID : STD_LOGIC_VECTOR := "1001";
constant ASYNC_S2M_VALID : STD_LOGIC_VECTOR := "1010";
constant ASYNC_M2S_INVALID : STD_LOGIC_VECTOR := "0001";
constant ASYNC_S2M_INVALID : STD_LOGIC_VECTOR := "0010";
 
type SLV_STATES is (IDLE, ADDR_1, ADDR_2, ADDR_3, DATA, ASYNC_CTL_HEAD, ASYNC, ASYNC_CTL_TAIL);
type MST_TRN_STATES is (IDLE, ADDR_1, ADDR_2, ADDR_3, DATA, ASYNC_CTL_HEAD, ASYNC, ASYNC_CTL_TAIL, WAIT_STATE);
type MST_REC_STATES is (IDLE, ADDR_1, ADDR_2, ADDR_3, DATA, ASYNC_CTL_HEAD, ASYNC, ASYNC_CTL_TAIL);
signal slv_state : SLV_STATES := IDLE;
signal next_slv_state : SLV_STATES := IDLE;
signal mst_trn_state : MST_TRN_STATES := IDLE;
signal next_mst_trn_state : MST_TRN_STATES := IDLE;
 
signal mst_rec_state : MST_REC_STATES := IDLE;
signal next_mst_rec_state : MST_REC_STATES := IDLE;
signal slave_reset : STD_LOGIC;
signal master_reset : STD_LOGIC;
signal last_data_in_strobe : STD_LOGIC := '0';
 
signal current_user_reg_write : STD_LOGIC := '0';
signal current_sys_reg_write : STD_LOGIC := '1';
 
signal current_user_reg_read : STD_LOGIC := '0';
signal current_sys_reg_read : STD_LOGIC := '1';
signal skip_counter_write : STD_LOGIC_VECTOR(15 downto 0) := "0000000000000000";
signal skip_counter_read : STD_LOGIC_VECTOR(15 downto 0) := "0000000000000000";
signal write_commited : STD_LOGIC := '0';
signal read_commited : STD_LOGIC := '0';
signal last_commit_write : STD_LOGIC;
signal last_commit_read : STD_LOGIC;
signal data_reg_addr_user : STD_LOGIC_VECTOR(10 downto 0) := "00000000000";
signal sync_ok : STD_LOGIC := '1';
signal last_sync_strobe : STD_LOGIC := '0';
 
signal slv_current_node : STD_LOGIC_VECTOR(3 downto 0) := "0000";
signal slv_current_reg : STD_LOGIC_VECTOR(2 downto 0) := "000";
signal slv_current_rw : STD_LOGIC := '0'; --Read: '0', Write: '1'
signal slv_current_var : STD_LOGIC_VECTOR(3 downto 0) := "0000";
signal slv_current_reg_ok : STD_LOGIC;
signal slv_current_node_address : STD_LOGIC_VECTOR(3 downto 0);
signal slv_current_node_id : STD_LOGIC_VECTOR(3 downto 0);
signal slv_current_node_read_reg_enable : STD_LOGIC_VECTOR(7 downto 0);
signal slv_current_node_write_reg_enable : STD_LOGIC_VECTOR(7 downto 0);
 
signal mst_trn_current_node : STD_LOGIC_VECTOR(3 downto 0) := "0000";
signal mst_trn_current_reg : STD_LOGIC_VECTOR(2 downto 0) := "000";
signal mst_trn_current_rw : STD_LOGIC := '0'; --Read: '0', Write: '1'
signal mst_trn_current_var : STD_LOGIC_VECTOR(3 downto 0) := "0000";
signal mst_trn_current_reg_ok : STD_LOGIC;
signal mst_trn_current_node_address : STD_LOGIC_VECTOR(3 downto 0);
signal mst_trn_current_node_id : STD_LOGIC_VECTOR(3 downto 0);
signal mst_trn_current_node_read_reg_enable : STD_LOGIC_VECTOR(7 downto 0);
signal mst_trn_current_node_write_reg_enable: STD_LOGIC_VECTOR(7 downto 0);
 
signal mst_rec_current_node : STD_LOGIC_VECTOR(3 downto 0) := "0000";
signal mst_rec_current_reg : STD_LOGIC_VECTOR(2 downto 0) := "000";
signal mst_rec_current_rw : STD_LOGIC := '0'; --Read: '0', Write: '1'
signal mst_rec_current_var : STD_LOGIC_VECTOR(3 downto 0) := "0000";
signal mst_rec_current_reg_ok : STD_LOGIC;
signal mst_rec_current_node_address : STD_LOGIC_VECTOR(3 downto 0);
signal mst_rec_current_node_id : STD_LOGIC_VECTOR(3 downto 0);
signal mst_rec_current_node_read_reg_enable : STD_LOGIC_VECTOR(7 downto 0);
signal mst_rec_current_node_write_reg_enable: STD_LOGIC_VECTOR(7 downto 0);
 
signal data_in_buffer : STD_LOGIC_VECTOR(7 downto 0);
signal waiting_for_trn : STD_LOGIC;
 
signal data_reg_internal_clk : STD_LOGIC;
signal data_reg_internal_data_in : STD_LOGIC_VECTOR(7 downto 0);
signal data_reg_internal_addr : STD_LOGIC_VECTOR(12 downto 0);
signal data_reg_internal_data_out : STD_LOGIC_VECTOR(7 downto 0);
signal data_reg_internal_we : STD_LOGIC_VECTOR(0 downto 0);
 
signal async_rd_en : STD_LOGIC;
signal async_wr_en : STD_LOGIC;
signal async_rd_data : STD_LOGIC_VECTOR(37 downto 0);
signal async_wr_data : STD_LOGIC_VECTOR(37 downto 0);
signal async_full : STD_LOGIC;
signal async_empty : STD_LOGIC;
signal async_valid : STD_LOGIC;
signal async_buffer : STD_LOGIC_VECTOR(95 downto 0);
signal async_trn_byte_count : STD_LOGIC_VECTOR(3 downto 0);
signal async_trn_valid_byte_count : STD_LOGIC_VECTOR(3 downto 0);
signal async_rec_byte_count : STD_LOGIC_VECTOR(3 downto 0);
signal async_rec_valid_byte_count : STD_LOGIC_VECTOR(3 downto 0);
signal async_trn_target : STD_LOGIC_VECTOR(3 downto 0);
signal async_rec_target : STD_LOGIC_VECTOR(3 downto 0);
signal async_trn_done : STD_LOGIC;
signal async_wr_be : STD_LOGIC_VECTOR(1 downto 0);
signal async_rec_valid : STD_LOGIC;
 
signal async_slv_buffer : STD_LOGIC_VECTOR(95 downto 0);
signal async_slv_trn_byte_count : STD_LOGIC_VECTOR(3 downto 0);
signal async_slv_trn_valid_byte_count : STD_LOGIC_VECTOR(3 downto 0);
signal async_slv_rec_byte_count : STD_LOGIC_VECTOR(3 downto 0);
signal async_slv_rec_valid_byte_count : STD_LOGIC_VECTOR(3 downto 0);
signal async_slv_trn_target : STD_LOGIC_VECTOR(3 downto 0);
signal async_slv_rec_target : STD_LOGIC_VECTOR(3 downto 0);
signal async_slv_trn_done : STD_LOGIC;
signal async_slv_wr_be : STD_LOGIC_VECTOR(1 downto 0);
signal async_slv_valid : STD_LOGIC;
signal async_slv_broadcast : STD_LOGIC;
 
 
signal read_done : STD_LOGIC;
signal read_progress : STD_LOGIC_VECTOR(1 downto 0);
signal write_done : STD_LOGIC;
signal write_progress : STD_LOGIC_VECTOR(1 downto 0);
signal slv_progress : STD_LOGIC_VECTOR(1 downto 0);
signal rw_arbiter : STD_LOGIC;
 
signal reset_counter_int : STD_LOGIC_VECTOR(31 downto 0) := "00000000000000000000000000000000";
signal packet_counter_int : STD_LOGIC_VECTOR(31 downto 0) := "00000000000000000000000000000000";
signal error_counter_int : STD_LOGIC_VECTOR(31 downto 0) := "00000000000000000000000000000000";
 
signal reset_counted : STD_LOGIC := '0';
 
component data_reg is
Port ( clka : in STD_LOGIC;
dina : in STD_LOGIC_VECTOR(7 downto 0);
addra : in STD_LOGIC_VECTOR(12 downto 0);
wea : in STD_LOGIC_VECTOR(0 downto 0);
douta : out STD_LOGIC_VECTOR(7 downto 0);
clkb : in STD_LOGIC;
dinb : in STD_LOGIC_VECTOR(31 downto 0);
addrb : in STD_LOGIC_VECTOR(10 downto 0);
web : in STD_LOGIC_VECTOR(0 downto 0);
doutb : out STD_LOGIC_VECTOR(31 downto 0));
end component;
 
component async_fifo is
Port ( rst : in STD_LOGIC;
wr_clk : in STD_LOGIC;
rd_clk : in STD_LOGIC;
din : in STD_LOGIC_VECTOR(37 downto 0);
wr_en : in STD_LOGIC;
rd_en : in STD_LOGIC;
dout : out STD_LOGIC_VECTOR(37 downto 0);
full : out STD_LOGIC;
empty : out STD_LOGIC;
valid : out STD_LOGIC);
end component;
 
begin
 
data_reg_inst : data_reg
Port map ( clka => data_reg_internal_clk,
dina => data_reg_internal_data_in,
addra => data_reg_internal_addr,
wea => data_reg_internal_we,
douta => data_reg_internal_data_out,
clkb => data_reg_clk,
dinb => data_reg_data_in,
addrb => data_reg_addr_user,
web => data_reg_we,
doutb => data_reg_data_out);
async_enabled:
if(disable_async = '0') generate
in_fifo : async_fifo
Port map ( rst => reset,
wr_clk => async_in_clk,
rd_clk => clk_50M,
din => async_in_data,
wr_en => async_in_wr_en,
rd_en => async_rd_en,
dout => async_rd_data,
full => async_in_full,
empty => async_empty,
valid => async_valid);
 
out_fifo : async_fifo
Port map ( rst => reset,
wr_clk => clk_50M,
rd_clk => async_out_clk,
din => async_wr_data,
wr_en => async_wr_en,
rd_en => async_out_rd_en,
dout => async_out_data,
full => async_full,
empty => async_out_empty,
valid => async_out_valid);
end generate;
 
async_disabled:
if(disable_async = '1') generate
async_rd_data <= (others => '0');
async_in_full <= '1';
async_empty <= '1';
async_valid <= '0';
async_out_data <= (others => '0');
async_full <= '1';
async_out_empty <= '1';
async_out_valid <= '0';
end generate;
data_reg_addr_user <= current_user_reg_write & data_reg_addr when --Create the address for the data register depending on the current buffer selection...
(((data_reg_addr(9 downto 6) = node_id) and data_reg_addr(2) = '0') or
(not(data_reg_addr(9 downto 6) = node_id) and data_reg_addr(2) = '1')) else
current_user_reg_read & data_reg_addr;
 
slave_reset <= (reset or is_master) or disable_slave; --The disable switches work by simply making sure that the slave- or master-reset is '1' always
master_reset <= (reset or not is_master) or disable_master; --XST will thus be able to optimize most of the slave- or master-functionality away...:)
 
error_counter <= error_counter_int;
packet_counter <= packet_counter_int;
reset_counter <= reset_counter_int;
 
skip_count_write <= skip_counter_write;
skip_count_read <= skip_counter_read;
current_buffer_index <= current_user_reg_write & current_user_reg_read & current_sys_reg_write & current_sys_reg_read;
 
force_packet_error <= (packet_error and not is_master) and not reset; --If we are forwarding a packet (slave only), and the current packet has an error, make sure that the packet is poisoned...
 
process(clk_50M)
begin
if(clk_50M = '1' and clk_50M'EVENT) then
if(reset = '1') then
write_commited <= '0';
read_commited <= '0';
skip_counter_write <= "0000000000000000";
skip_counter_read <= "0000000000000000";
system_halt <= '0';
sync_ok <= '1'; --Make sure that the system starts automagically when it exits reset
pause_ack <= '0';
if(reset_counted = '0') then
reset_counter_int <= reset_counter_int + 1;
reset_counted <= '1';
end if;
else
reset_counted <= '0';
end if;
if(data_reg_commit_write = '1' and last_commit_write = '0') then
write_commited <= '1';
end if;
 
if(data_reg_commit_read = '1' and last_commit_read = '0') then
read_commited <= '1';
end if;
 
if((sync_strobe = '1') and (last_sync_strobe = '0')) then
if(write_commited = '1' and packet_error = '0') then --Handle the doublebuffering for the write buffers
if(current_user_reg_write = '1') then
current_user_reg_write <= '0';
else
current_user_reg_write <= '1';
end if;
if(current_sys_reg_write = '1') then
current_sys_reg_write <= '0';
else
current_sys_reg_write <= '1';
end if;
write_commited <= '0';
skip_counter_write <= "0000000000000000";
else
skip_counter_write <= skip_counter_write + 1;
end if;
 
if(read_commited = '1' and packet_error = '0') then --Handle the doublebuffering for the read buffers
if(current_user_reg_read = '1') then
current_user_reg_read <= '0';
else
current_user_reg_read <= '1';
end if;
if(current_sys_reg_read = '1') then
current_sys_reg_read <= '0';
else
current_sys_reg_read <= '1';
end if;
read_commited <= '0';
skip_counter_read <= "0000000000000000";
else
skip_counter_read <= skip_counter_read + 1;
end if;
sync_ok <= '1';
packet_counter_int <= packet_counter_int + 1;
if(packet_error = '1') then
error_counter_int <= error_counter_int + 1;
end if;
 
if(pause = '1' and is_master = '1') then --Handle pause functionality
pause_ack <= '1';
else
pause_ack <= '0';
end if;
end if;
if(((skip_counter_write > max_skipped_writes) and not(max_skipped_writes = 0)) or --The system only uses the skip counters if they're different from 0. If 0, an unlimited number of skips are allowed...
((skip_counter_read > max_skipped_reads) and not (max_skipped_reads = 0))) then
system_halt <= '1';
end if;
async_wr_en <= '0';
------------------------------------------------------------------------
-- Slave synchronous part
------------------------------------------------------------------------
if(slave_reset = '1') then
slv_state <= IDLE;
slv_current_node <= "0000";
slv_current_rw <= '0';
slv_current_var <= "0000";
async_slv_buffer <= (others => '0');
async_slv_trn_byte_count <= (others => '0');
async_slv_trn_valid_byte_count <= (others => '0');
async_slv_rec_byte_count <= (others => '0');
async_slv_rec_valid_byte_count <= (others => '0');
async_slv_trn_target <= (others => '0');
async_slv_rec_target <= (others => '0');
async_slv_trn_done <= '0';
async_slv_wr_be <= (others => '0');
async_slv_valid <= '0';
async_slv_broadcast <= '0';
slv_progress <= "00";
else
slv_state <= next_slv_state;
case slv_state is
when IDLE =>
slv_current_node <= "0000";
slv_current_rw <= '0';
slv_current_var <= "0000";
data_out_strobe <= '0';
data_out_enable <= '0';
async_slv_buffer <= (others => '0');
async_slv_trn_byte_count <= (others => '0');
async_slv_trn_valid_byte_count <= (others => '0');
async_slv_rec_byte_count <= (others => '0');
async_slv_rec_valid_byte_count <= (others => '0');
async_slv_trn_target <= (others => '0');
async_slv_rec_target <= (others => '0');
async_slv_trn_done <= '0';
async_slv_wr_be <= (others => '0');
async_slv_valid <= '0';
async_slv_broadcast <= '0';
slv_progress <= "00";
when ADDR_1 => --Retreive network register entry for node
network_reg_addr <= slv_current_node;
network_reg_clk <= '0';
sync_ok <= '0';
when ADDR_2 =>
network_reg_clk <= '1';
when ADDR_3 =>
network_reg_clk <= '0';
slv_current_node_address <= network_reg_data(7 downto 4);
slv_current_node_id <= network_reg_data(3 downto 0);
slv_current_node_read_reg_enable <= network_reg_data(15 downto 8);
slv_current_node_write_reg_enable <= network_reg_data(23 downto 16);
slv_current_rw <= '0';
slv_current_var <= "0000";
when DATA => --Receive, store, and forward packet
data_out_enable <= '1';
if(slv_current_reg_ok = '0') then --No more registers for this part
if(slv_current_rw = '0') then --If read registers are currently selected,
slv_current_rw <= '1'; --then switch to write
else --else the node is done,
slv_current_rw <= '0';
slv_current_node <= slv_current_node + 1; --so go to the next node...
slv_current_var <= "0000";
end if;
else
if(data_in_strobe = '1' and last_data_in_strobe = '0') then
if(slv_current_node = node_address) then
if(slv_current_rw = '1') then --Ignore the Read registers from this node, we're only interested in the write registers...
data_reg_internal_addr <= current_sys_reg_read & slv_current_node_id & slv_current_reg & '1' & slv_current_var;
data_reg_internal_data_in <= data_in;
data_reg_internal_we <= "1";
data_reg_internal_clk <= '0';
data_out <= data_reg_internal_data_out;
data_out_strobe <= '1';
else
data_out <= data_in;
data_out_strobe <= '1';
end if;
else
data_reg_internal_addr <= current_sys_reg_read & slv_current_node_id & slv_current_reg & slv_current_rw & slv_current_var;
data_reg_internal_data_in <= data_in;
data_reg_internal_we <= "1";
data_reg_internal_clk <= '0';
data_out <= data_in;
data_out_strobe <= '1';
end if;
elsif(data_in_strobe = '0' and last_data_in_strobe = '1') then
if(not((slv_current_node = node_address) and (slv_current_rw = '0'))) then
data_reg_internal_clk <= '1';
end if;
data_out_strobe <= '0';
if(slv_current_var = "1111") then --All vars for this register read, set the reg_enable bit for this register to 0 to go to the next register
if(slv_current_rw = '0') then
slv_current_node_read_reg_enable(conv_integer(slv_current_reg)) <= '0';
else
slv_current_node_write_reg_enable(conv_integer(slv_current_reg)) <= '0';
end if;
end if;
slv_current_var <= slv_current_var + 1;
elsif((data_reg_internal_clk = '1') and (data_reg_internal_we = "1") and (data_in_strobe = '0')) then
data_reg_internal_clk <= '0';
data_reg_internal_addr <= current_sys_reg_write & slv_current_node_id & slv_current_reg & '0' & slv_current_var;
data_reg_internal_we <= "0";
elsif((data_reg_internal_clk = '0') and (data_reg_internal_we = "0") and (data_in_strobe = '0')) then
data_reg_internal_clk <= '1';
else
data_reg_internal_clk <= '0';
data_reg_internal_we <= "1";
end if;
end if;
when ASYNC_CTL_HEAD =>
if(data_in_strobe = '1' and last_data_in_strobe = '0') then
if(data_in = ASYNC_M2S_VALID & NODE_ID) then --Data for this node only received
async_slv_valid <= '1';
if(async_valid = '1') then
data_out <= ASYNC_S2M_VALID & NODE_ID;
else
data_out <= ASYNC_S2M_INVALID & NODE_ID;
end if;
elsif(data_in = ASYNC_M2S_VALID & "0000") then --Broadcast received
data_out <= data_in;
async_slv_valid <= '1';
async_trn_done <= '1';
async_slv_broadcast <= '1';
else --Nothing of interest for this node
async_slv_valid <= '0';
data_out <= data_in;
end if;
 
data_out_strobe <= '1';
end if;
when ASYNC =>
data_out_strobe <= '0';
if(data_in_strobe = '1' and last_data_in_strobe = '0') then
if(async_slv_valid = '0') then
data_out <= data_in;
data_out_strobe <= '1';
else
async_slv_buffer <= async_slv_buffer(87 downto 0) & data_in;
async_slv_rec_byte_count <= async_slv_rec_byte_count + 1;
if(async_valid = '1') then
if(async_slv_trn_byte_count = 0) then
async_slv_trn_target <= async_rd_data(35 downto 32);
end if;
else
async_slv_trn_done <= '1';
end if;
slv_progress <= "01";
end if;
elsif(slv_progress = "01") then --We'll only increase slv_progress if async_slv_valid is true, thus no need for a (redundant) check for validity here...
if(async_slv_trn_done = '0' and async_slv_trn_target = async_rd_data(35 downto 32)) then
case async_slv_trn_byte_count(1 downto 0) is
when "00" =>
data_out <= async_rd_data(31 downto 24);
if(async_rd_data(37 downto 36) = "00") then
async_slv_trn_done <= '1';
end if;
when "01" =>
data_out <= async_rd_data(23 downto 16);
if(async_rd_data(37 downto 36) = "01") then
async_slv_trn_done <= '1';
end if;
when "10" =>
data_out <= async_rd_data(15 downto 8);
if(async_rd_data(37 downto 36) = "10") then
async_slv_trn_done <= '1';
end if;
when "11" =>
data_out <= async_rd_data(7 downto 0);
when others =>
end case;
async_slv_trn_valid_byte_count <= async_slv_trn_valid_byte_count + 1;
else
data_out <= data_in;
async_slv_trn_done <= '1';
end if;
data_out_strobe <= '1';
async_slv_trn_byte_count <= async_slv_trn_byte_count + 1;
slv_progress <= "10";
elsif(slv_progress = "10") then
slv_progress <= "00";
end if;
when ASYNC_CTL_TAIL =>
data_out_strobe <= '0';
if(data_in_strobe = '1' and last_data_in_strobe = '0' and slv_progress = "00") then
if(async_slv_broadcast = '1') then
data_out <= data_in;
else
data_out <= async_slv_trn_valid_byte_count & NODE_ID;
end if;
data_out_strobe <= '1';
async_slv_rec_valid_byte_count <= data_in(7 downto 4) - 4;
async_slv_rec_target <= data_in(3 downto 0);
slv_progress <= "01";
if(data_in(7 downto 4) > 3) then
async_slv_wr_be <= "11";
else
async_slv_wr_be <= data_in(5 downto 4) - 1;
end if;
elsif(slv_progress = "01") then
data_out_strobe <= '0';
if((async_slv_rec_valid_byte_count > 8) and (async_slv_rec_valid_byte_count < 13)) then
slv_progress <= "11"; --Done
else
slv_progress <= "10"; --Delay one clock (we've got lots), to make sure we jump out if no data has been received (8 < async_rec_valid_byte_count < 13)
end if;
async_wr_en <= '0';
elsif(slv_progress = "10") then
async_wr_data <= async_slv_wr_be & async_slv_rec_target & async_slv_buffer(95 downto 64);
async_wr_en <= '1';
async_slv_buffer(95 downto 32) <= async_slv_buffer(63 downto 0);
async_slv_rec_valid_byte_count <= async_slv_rec_valid_byte_count - 4;
if(async_slv_rec_valid_byte_count > 3) then
async_slv_wr_be <= "11";
else
async_slv_wr_be <= async_slv_rec_valid_byte_count(1 downto 0) - 1;
end if;
slv_progress <= "01";
end if;
end case;
end if;
------------------------------------------------------------------------
-- Master TRN synchronous part
------------------------------------------------------------------------
if(master_reset = '1') then
mst_trn_state <= IDLE;
mst_trn_current_node <= "0000";
mst_trn_current_rw <= '0';
mst_trn_current_var <= "0000";
read_progress <= "00";
read_done <= '1';
async_trn_byte_count <= (others => '0');
async_trn_valid_byte_count <= (others => '0');
async_trn_done <= '0';
async_trn_target <= (others => '0');
else
mst_trn_state <= next_mst_trn_state;
case mst_trn_state is
when IDLE =>
mst_trn_current_node <= "0000";
mst_trn_current_rw <= '0';
mst_trn_current_var <= "0000";
data_out_strobe <= '0';
data_out_enable <= '0';
read_progress <= "00";
read_done <= '1';
async_trn_byte_count <= (others => '0');
async_trn_valid_byte_count <= (others => '0');
async_trn_done <= '0';
async_trn_target <= (others => '0');
when ADDR_1 => --Retreive network register entry for node
network_reg_addr <= mst_trn_current_node;
network_reg_clk <= '0';
sync_ok <= '0';
pause_ack <= '0';
when ADDR_2 =>
network_reg_clk <= '1';
when ADDR_3 =>
network_reg_clk <= '0';
mst_trn_current_node_address <= network_reg_data(7 downto 4);
mst_trn_current_node_id <= network_reg_data(3 downto 0);
mst_trn_current_node_read_reg_enable <= network_reg_data(15 downto 8);
mst_trn_current_node_write_reg_enable <= network_reg_data(23 downto 16);
mst_trn_current_rw <= '0';
mst_trn_current_var <= "0000";
when DATA => --Receive, store, and forward packet
data_out_enable <= '1';
if(mst_trn_current_reg_ok = '0') then --No more registers for this part
if(mst_trn_current_rw = '0') then --If read registers are currently selected,
mst_trn_current_rw <= '1'; --then switch to write
else --else the node is done,
mst_trn_current_rw <= '0';
mst_trn_current_node <= mst_trn_current_node + 1; --so go to the next node...
mst_trn_current_var <= "0000";
end if;
else
if(read_progress = "00" and write_done = '1' and buffer_full = '0' and rw_arbiter = '0') then
if(mst_trn_current_rw = '0' and not(mst_trn_current_node = node_address)) then
data_reg_internal_addr <= current_sys_reg_read & mst_trn_current_node_id & mst_trn_current_reg & mst_trn_current_rw & mst_trn_current_var;
else
data_reg_internal_addr <= current_sys_reg_write & mst_trn_current_node_id & mst_trn_current_reg & mst_trn_current_rw & mst_trn_current_var;
end if;
data_reg_internal_we <= "0";
data_reg_internal_clk <= '0';
read_progress <= "01";
read_done <= '0';
elsif(read_progress = "01") then
data_reg_internal_clk <= '1';
read_progress <= "10";
elsif(read_progress = "10") then
data_reg_internal_clk <= '0';
data_out <= data_reg_internal_data_out;
data_out_strobe <= '1';
read_progress <= "11";
read_done <= '1';
elsif(read_progress = "11") then
data_out_strobe <= '0';
read_progress <= "00";
 
if(mst_trn_current_var = "1111") then --All vars for this register read, set the reg_enable bit for this register to 0 to go to the next register
if(mst_trn_current_rw = '0') then
mst_trn_current_node_read_reg_enable(conv_integer(mst_trn_current_reg)) <= '0';
else
mst_trn_current_node_write_reg_enable(conv_integer(mst_trn_current_reg)) <= '0';
end if;
end if;
mst_trn_current_var <= mst_trn_current_var + 1;
end if;
end if;
when ASYNC_CTL_HEAD =>
if(buffer_full = '0' and read_progress <= "00") then
if(async_valid = '1') then
async_trn_target <= async_rd_data(35 downto 32);
data_out <= ASYNC_M2S_VALID & async_rd_data(35 downto 32);
else
data_out <= ASYNC_M2S_INVALID & "0000";
async_trn_done <= '1';
end if;
data_out_strobe <= '1';
read_progress <= "01";
else
data_out_strobe <= '0';
end if;
when ASYNC =>
data_out_strobe <= '0';
if(read_progress = "00") then
read_progress <= "01";
elsif(read_progress = "01" and buffer_full = '0') then
if(async_valid = '0') then
async_trn_done <= '1';
end if;
read_progress <= "10";
elsif(read_progress = "10") then
if(async_trn_done = '0' and async_trn_target = async_rd_data(35 downto 32)) then
case async_trn_byte_count(1 downto 0) is
when "00" =>
data_out <= async_rd_data(31 downto 24);
if(async_rd_data(37 downto 36) = "00") then
async_trn_done <= '1';
end if;
when "01" =>
data_out <= async_rd_data(23 downto 16);
if(async_rd_data(37 downto 36) = "01") then
async_trn_done <= '1';
end if;
when "10" =>
data_out <= async_rd_data(15 downto 8);
if(async_rd_data(37 downto 36) = "10") then
async_trn_done <= '1';
end if;
when "11" =>
data_out <= async_rd_data(7 downto 0);
when others =>
end case;
async_trn_valid_byte_count <= async_trn_valid_byte_count + 1;
else
data_out <= (others => '0');
async_trn_done <= '1';
end if;
data_out_strobe <= '1';
async_trn_byte_count <= async_trn_byte_count + 1;
read_progress <= "11";
elsif(read_progress = "11") then
data_out_strobe <= '0';
read_progress <= "00";
end if;
when ASYNC_CTL_TAIL =>
if(read_progress = "00" and buffer_full = '0') then
data_out <= async_trn_valid_byte_count & async_trn_target;
data_out_strobe <= '1';
read_progress <= "01";
elsif(read_progress = "01") then
data_out_strobe <= '0';
read_progress <= "00";
end if;
when WAIT_STATE =>
--Just do nothing...
end case;
end if;
 
------------------------------------------------------------------------
-- Master REC synchronous part
------------------------------------------------------------------------
if(master_reset = '1') then
mst_rec_state <= IDLE;
mst_rec_current_node <= "0000";
mst_rec_current_rw <= '0';
mst_rec_current_var <= "0000";
write_progress <= "00";
write_done <= '1';
async_rec_byte_count <= (others => '0');
async_rec_valid_byte_count <= (others => '0');
async_rec_target <= (others => '0');
async_wr_be <= "00";
async_rec_valid <= '0';
else
mst_rec_state <= next_mst_rec_state;
case mst_rec_state is
when IDLE =>
mst_rec_current_node <= "0000";
mst_rec_current_rw <= '0';
mst_rec_current_var <= "0000";
write_progress <= "00";
write_done <= '1';
async_rec_byte_count <= (others => '0');
async_rec_valid_byte_count <= (others => '0');
async_rec_target <= (others => '0');
async_wr_be <= "00";
async_rec_valid <= '0';
when ADDR_1 => --Retreive network register entry for node
network_reg_addr <= mst_rec_current_node;
network_reg_clk <= '0';
sync_ok <= '0';
when ADDR_2 =>
network_reg_clk <= '1';
when ADDR_3 =>
network_reg_clk <= '0';
mst_rec_current_node_address <= network_reg_data(7 downto 4);
mst_rec_current_node_id <= network_reg_data(3 downto 0);
mst_rec_current_node_read_reg_enable <= network_reg_data(15 downto 8);
mst_rec_current_node_write_reg_enable <= network_reg_data(23 downto 16);
mst_rec_current_rw <= '0';
mst_rec_current_var <= "0000";
when DATA => --Receive, store, and forward packet
if(mst_rec_current_reg_ok = '0') then --No more registers for this part
if(waiting_for_trn = '0') then
if(mst_rec_current_rw = '0') then --If read registers are currently selected,
mst_rec_current_rw <= '1'; --then switch to write
else --else the node is done,
mst_rec_current_rw <= '0';
mst_rec_current_node <= mst_rec_current_node + 1; --so go to the next node...
mst_rec_current_var <= "0000";
end if;
end if;
else
if(data_in_strobe = '1' and last_data_in_strobe = '0') then
if((mst_rec_current_rw = '1') and not(mst_rec_current_node = node_address)) then --Ignore the Read registers for the nodes, we're only interested in the write registers, which hold the newest data...
data_in_buffer <= data_in;
write_progress <= "01";
end if;
elsif(data_in_strobe = '0' and last_data_in_strobe = '1') then
if(mst_rec_current_var = "1111") then --All vars for this register read, set the reg_enable bit for this register to 0 to go to the next register
if(mst_rec_current_rw = '0') then
mst_rec_current_node_read_reg_enable(conv_integer(mst_rec_current_reg)) <= '0';
else
mst_rec_current_node_write_reg_enable(conv_integer(mst_rec_current_reg)) <= '0';
end if;
end if;
mst_rec_current_var <= mst_rec_current_var + 1;
elsif(write_progress = "01" and write_done = '1' and read_done = '1' and rw_arbiter = '1') then
data_reg_internal_addr <= current_sys_reg_read & mst_rec_current_node_id & mst_rec_current_reg & '0' & mst_rec_current_var;
data_reg_internal_data_in <= data_in_buffer;
data_reg_internal_we <= "1";
data_reg_internal_clk <= '0';
write_done <= '0';
write_progress <= "10";
elsif(write_progress = "10" and write_done = '0') then
data_reg_internal_clk <= '1';
write_progress <= "11";
elsif(write_progress = "11" and write_done = '0') then
data_reg_internal_clk <= '0';
data_reg_internal_we <= "0";
write_done <= '1';
write_progress <= "00";
end if;
end if;
when ASYNC_CTL_HEAD =>
if(data_in_strobe = '1' and last_data_in_strobe = '0') then
if(data_in(7 downto 4) = ASYNC_S2M_VALID) then
async_rec_valid <= '1';
else
async_rec_valid <= '0';
end if;
end if;
when ASYNC =>
if(data_in_strobe = '1' and last_data_in_strobe = '0') then
async_buffer <= async_buffer(87 downto 0) & data_in;
async_rec_byte_count <= async_rec_byte_count + 1;
end if;
when ASYNC_CTL_TAIL =>
if(data_in_strobe = '1' and last_data_in_strobe = '0' and write_progress = "00") then
async_rec_valid_byte_count <= data_in(7 downto 4) - 4;
async_rec_target <= data_in(3 downto 0);
write_progress <= "01";
if(data_in(7 downto 4) > 3) then
async_wr_be <= "11";
else
async_wr_be <= data_in(5 downto 4) - 1;
end if;
elsif(write_progress = "01") then
write_progress <= "10"; --Delay one clock (we've got lots), to make sure we jump out if no data has been received (async_rec_valid_byte_count > 8)
async_wr_en <= '0';
elsif(write_progress = "10") then
async_wr_data <= async_wr_be & async_rec_target & async_buffer(95 downto 64);
async_wr_en <= '1';
async_buffer(95 downto 32) <= async_buffer(63 downto 0);
async_rec_valid_byte_count <= async_rec_valid_byte_count - 4;
if(async_rec_valid_byte_count > 3) then
async_wr_be <= "11";
else
async_wr_be <= async_rec_valid_byte_count(1 downto 0) - 1;
end if;
write_progress <= "01";
end if;
end case;
end if;
 
------------------------------------------------------------------------
last_data_in_strobe <= data_in_strobe;
last_sync_strobe <= sync_strobe;
last_commit_write <= data_reg_commit_write;
last_commit_read <= data_reg_commit_read;
if(rw_arbiter = '0') then
rw_arbiter <= '1';
else
rw_arbiter <= '0';
end if;
end if;
end process;
 
------------------------------------------------------------------------
-- Slave combinatorial next-state logic
------------------------------------------------------------------------
process(slv_state, data_in_enable, slv_current_reg_ok, slv_current_rw, slv_current_node, network_reg_data(7 downto 4), slv_progress, async_slv_trn_byte_count, async_slv_rec_valid_byte_count, data_in_strobe, last_data_in_strobe)
begin
case slv_state is
when IDLE =>
if(data_in_enable = '1') then
next_slv_state <= ADDR_1;
else
next_slv_state <= IDLE;
end if;
when ADDR_1 =>
next_slv_state <= ADDR_2;
when ADDR_2 =>
next_slv_state <= ADDR_3;
when ADDR_3 =>
if(slv_current_node = network_reg_data(7 downto 4)) then
next_slv_state <= DATA;
else
next_slv_state <= ASYNC_CTL_HEAD;
end if;
when DATA =>
if(data_in_enable = '0') then
next_slv_state <= IDLE;
elsif(slv_current_reg_ok = '0' and slv_current_rw = '1') then
next_slv_state <= ADDR_1;
else
next_slv_state <= DATA;
end if;
when ASYNC_CTL_HEAD =>
if(data_in_strobe = '1' and last_data_in_strobe = '0') then
next_slv_state <= ASYNC;
else
next_slv_state <= ASYNC_CTL_HEAD;
end if;
when ASYNC =>
if(data_in_enable = '0') then
next_slv_state <= IDLE;
elsif(slv_progress = "00" and async_slv_trn_byte_count = 12) then
next_slv_state <= ASYNC_CTL_TAIL;
else
next_slv_state <= ASYNC;
end if;
when ASYNC_CTL_TAIL =>
if(data_in_enable = '0') then
next_slv_state <= IDLE;
else
next_slv_state <= ASYNC_CTL_TAIL;
end if;
end case;
end process;
 
------------------------------------------------------------------------
-- Master TRN combinatorial next-state logic
------------------------------------------------------------------------
process(mst_trn_state, mst_rec_state, sync_ok, data_in_enable, mst_trn_current_reg_ok, mst_trn_current_rw, mst_trn_current_node, network_reg_data(7 downto 4), pause, read_progress, async_trn_byte_count)
begin
case mst_trn_state is
when IDLE =>
if(mst_rec_state = IDLE and sync_ok = '1' and pause = '0') then --Make sure that we're done receiving and sync'ing before sending out the next packet (for synchronization, buffering and a couple of other reasons...)
next_mst_trn_state <= WAIT_STATE;
else
next_mst_trn_state <= IDLE;
end if;
when ADDR_1 =>
next_mst_trn_state <= ADDR_2;
when ADDR_2 =>
next_mst_trn_state <= ADDR_3;
when ADDR_3 =>
if(mst_trn_current_node = network_reg_data(7 downto 4)) then
next_mst_trn_state <= DATA;
else
next_mst_trn_state <= ASYNC_CTL_HEAD;
end if;
when DATA =>
if(mst_trn_current_reg_ok = '0' and mst_trn_current_rw = '1') then
next_mst_trn_state <= WAIT_STATE;
else
next_mst_trn_state <= DATA;
end if;
when ASYNC_CTL_HEAD =>
if(read_progress = "01") then
next_mst_trn_state <= ASYNC;
else
next_mst_trn_state <= ASYNC_CTL_HEAD;
end if;
when ASYNC =>
if(read_progress = "11" and async_trn_byte_count = 12) then
next_mst_trn_state <= ASYNC_CTL_TAIL;
else
next_mst_trn_state <= ASYNC;
end if;
when ASYNC_CTL_TAIL =>
if(read_progress = "01") then
next_mst_trn_state <= IDLE;
else
next_mst_trn_state <= ASYNC_CTL_TAIL;
end if;
when WAIT_STATE =>
if(mst_rec_state = DATA or mst_rec_state = IDLE) then
next_mst_trn_state <= ADDR_1;
else
next_mst_trn_state <= WAIT_STATE;
end if;
end case;
end process;
------------------------------------------------------------------------
-- Master REC combinatorial next-state logic
------------------------------------------------------------------------
process(mst_rec_state, mst_trn_state, data_in_enable, mst_rec_current_reg_ok, mst_rec_current_rw, mst_rec_current_node, network_reg_data(7 downto 4), async_rec_byte_count, async_rec_valid_byte_count, async_rec_valid, data_in_strobe, last_data_in_strobe)
begin
waiting_for_trn <= '0';
case mst_rec_state is
when IDLE =>
if(data_in_enable = '1' and (mst_trn_state = DATA or mst_trn_state = IDLE or mst_trn_state = ASYNC_CTL_HEAD or mst_trn_state = ASYNC or mst_trn_state = ASYNC_CTL_TAIL)) then
next_mst_rec_state <= ADDR_1;
else
next_mst_rec_state <= IDLE;
end if;
when ADDR_1 =>
next_mst_rec_state <= ADDR_2;
when ADDR_2 =>
next_mst_rec_state <= ADDR_3;
when ADDR_3 =>
if(mst_rec_current_node = network_reg_data(7 downto 4)) then
next_mst_rec_state <= DATA;
else
next_mst_rec_state <= ASYNC_CTL_HEAD;
end if;
when DATA =>
if(data_in_enable = '0') then
next_mst_rec_state <= IDLE;
elsif(mst_rec_current_reg_ok = '0' and mst_rec_current_rw = '1' and (mst_trn_state = DATA or mst_trn_state = IDLE or mst_trn_state = ASYNC_CTL_HEAD or mst_trn_state = ASYNC or mst_trn_state = ASYNC_CTL_TAIL)) then
next_mst_rec_state <= ADDR_1;
elsif(mst_rec_current_reg_ok = '0' and mst_rec_current_rw = '1') then
waiting_for_trn <= '1';
next_mst_rec_state <= DATA;
else
next_mst_rec_state <= DATA;
end if;
when ASYNC_CTL_HEAD =>
if(data_in_strobe = '1' and last_data_in_strobe = '0') then
next_mst_rec_state <= ASYNC;
else
next_mst_rec_state <= ASYNC_CTL_HEAD;
end if;
when ASYNC =>
if(async_rec_byte_count = 12) then
next_mst_rec_state <= ASYNC_CTL_TAIL;
else
next_mst_rec_state <= ASYNC;
end if;
when ASYNC_CTL_TAIL =>
if(((async_rec_valid_byte_count > 8) and (async_rec_valid_byte_count < 13)) or async_rec_valid <= '0') then
next_mst_rec_state <= IDLE;
else
next_mst_rec_state <= ASYNC_CTL_TAIL;
end if;
end case;
end process;
------------------------------------------------------------------------
-- Combinatorial logic for address generation
------------------------------------------------------------------------
async_rd_en <= '1' when (((mst_trn_state = ASYNC) and (read_progress = "11") and (async_trn_done = '0') and (async_trn_byte_count(1 downto 0) = "00")) or
((mst_trn_state = ASYNC_CTL_TAIL) and (read_progress = "01") and not (async_trn_valid_byte_count(1 downto 0) = "00")) or
((slv_state = ASYNC) and (slv_progress = "10") and (async_slv_trn_done = '0') and (async_slv_trn_byte_count(1 downto 0) = "00")) or
((slv_state = ASYNC_CTL_TAIL) and (data_in_strobe = '1') and (last_data_in_strobe = '0') and (slv_progress = "00") and not (async_slv_trn_valid_byte_count(1 downto 0) = "00"))) else '0';
 
slv_current_reg <= "111" when (slv_current_node_read_reg_enable(7) = '1' and slv_current_rw = '0') or
(slv_current_node_write_reg_enable(7) = '1' and slv_current_rw = '1') else
"110" when (slv_current_node_read_reg_enable(6) = '1' and slv_current_rw = '0') or
(slv_current_node_write_reg_enable(6) = '1' and slv_current_rw = '1') else
"101" when (slv_current_node_read_reg_enable(5) = '1' and slv_current_rw = '0') or
(slv_current_node_write_reg_enable(5) = '1' and slv_current_rw = '1') else
"100" when (slv_current_node_read_reg_enable(4) = '1' and slv_current_rw = '0') or
(slv_current_node_write_reg_enable(4) = '1' and slv_current_rw = '1') else
"011" when (slv_current_node_read_reg_enable(3) = '1' and slv_current_rw = '0') or
(slv_current_node_write_reg_enable(3) = '1' and slv_current_rw = '1') else
"010" when (slv_current_node_read_reg_enable(2) = '1' and slv_current_rw = '0') or
(slv_current_node_write_reg_enable(2) = '1' and slv_current_rw = '1') else
"001" when (slv_current_node_read_reg_enable(1) = '1' and slv_current_rw = '0') or
(slv_current_node_write_reg_enable(1) = '1' and slv_current_rw = '1') else
"000";
slv_current_reg_ok <= '0' when slv_current_reg = "000" and not ((slv_current_node_read_reg_enable(0) = '1' and slv_current_rw = '0') or
(slv_current_node_write_reg_enable(0) = '1' and slv_current_rw = '1')) else
'1';
 
 
mst_trn_current_reg <= "111" when (mst_trn_current_node_read_reg_enable(7) = '1' and mst_trn_current_rw = '0') or
(mst_trn_current_node_write_reg_enable(7) = '1' and mst_trn_current_rw = '1') else
"110" when (mst_trn_current_node_read_reg_enable(6) = '1' and mst_trn_current_rw = '0') or
(mst_trn_current_node_write_reg_enable(6) = '1' and mst_trn_current_rw = '1') else
"101" when (mst_trn_current_node_read_reg_enable(5) = '1' and mst_trn_current_rw = '0') or
(mst_trn_current_node_write_reg_enable(5) = '1' and mst_trn_current_rw = '1') else
"100" when (mst_trn_current_node_read_reg_enable(4) = '1' and mst_trn_current_rw = '0') or
(mst_trn_current_node_write_reg_enable(4) = '1' and mst_trn_current_rw = '1') else
"011" when (mst_trn_current_node_read_reg_enable(3) = '1' and mst_trn_current_rw = '0') or
(mst_trn_current_node_write_reg_enable(3) = '1' and mst_trn_current_rw = '1') else
"010" when (mst_trn_current_node_read_reg_enable(2) = '1' and mst_trn_current_rw = '0') or
(mst_trn_current_node_write_reg_enable(2) = '1' and mst_trn_current_rw = '1') else
"001" when (mst_trn_current_node_read_reg_enable(1) = '1' and mst_trn_current_rw = '0') or
(mst_trn_current_node_write_reg_enable(1) = '1' and mst_trn_current_rw = '1') else
"000";
mst_trn_current_reg_ok <= '0' when mst_trn_current_reg = "000" and not ((mst_trn_current_node_read_reg_enable(0) = '1' and mst_trn_current_rw = '0') or
(mst_trn_current_node_write_reg_enable(0) = '1' and mst_trn_current_rw = '1')) else
'1';
 
 
mst_rec_current_reg <= "111" when (mst_rec_current_node_read_reg_enable(7) = '1' and mst_rec_current_rw = '0') or
(mst_rec_current_node_write_reg_enable(7) = '1' and mst_rec_current_rw = '1') else
"110" when (mst_rec_current_node_read_reg_enable(6) = '1' and mst_rec_current_rw = '0') or
(mst_rec_current_node_write_reg_enable(6) = '1' and mst_rec_current_rw = '1') else
"101" when (mst_rec_current_node_read_reg_enable(5) = '1' and mst_rec_current_rw = '0') or
(mst_rec_current_node_write_reg_enable(5) = '1' and mst_rec_current_rw = '1') else
"100" when (mst_rec_current_node_read_reg_enable(4) = '1' and mst_rec_current_rw = '0') or
(mst_rec_current_node_write_reg_enable(4) = '1' and mst_rec_current_rw = '1') else
"011" when (mst_rec_current_node_read_reg_enable(3) = '1' and mst_rec_current_rw = '0') or
(mst_rec_current_node_write_reg_enable(3) = '1' and mst_rec_current_rw = '1') else
"010" when (mst_rec_current_node_read_reg_enable(2) = '1' and mst_rec_current_rw = '0') or
(mst_rec_current_node_write_reg_enable(2) = '1' and mst_rec_current_rw = '1') else
"001" when (mst_rec_current_node_read_reg_enable(1) = '1' and mst_rec_current_rw = '0') or
(mst_rec_current_node_write_reg_enable(1) = '1' and mst_rec_current_rw = '1') else
"000";
mst_rec_current_reg_ok <= '0' when mst_rec_current_reg = "000" and not ((mst_rec_current_node_read_reg_enable(0) = '1' and mst_rec_current_rw = '0') or
(mst_rec_current_node_write_reg_enable(0) = '1' and mst_rec_current_rw = '1')) else
'1';
end Behavioral;
 
/trunk/gateware/TosNet_rev3_2/tdl_top.vhd
0,0 → 1,948
----------------------------------------------------------------------------------
-- Company: University of Southern Denmark
-- Engineer: Simon Falsig
--
-- Create Date: 7/3/2010
-- Design Name: TosNet
-- Module Name: tdl_top - Behavioral
-- File Name: tdl_top.vhd
-- Project Name: TosNet
-- Target Devices: Spartan3/6
-- Tool versions: Xilinx ISE 12.2
-- Description: The datalink layer implementation and physical layer wrapper
-- for the TosNet stack.
--
-- Revision:
-- Revision 3.2 - Initial release
--
-- Copyright 2010
--
-- This module 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 3 of the License, or
-- (at your option) any later version.
--
-- This module 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 module. If not, see <http://www.gnu.org/licenses/>.
--------------------------------------------------------------------------------------------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use work.crcpack.all;
use work.commandpack.all;
 
entity tdl_top is
Port( node_id : in STD_LOGIC_VECTOR(3 downto 0);
reg_enable : in STD_LOGIC_VECTOR(7 downto 0);
watchdog_threshold : in STD_LOGIC_VECTOR(17 downto 0);
data_out_ext : out STD_LOGIC_VECTOR(7 downto 0);
data_out_strobe_ext : out STD_LOGIC;
data_out_enable_ext : out STD_LOGIC;
data_in_ext : in STD_LOGIC_VECTOR(7 downto 0);
data_in_strobe_ext : in STD_LOGIC;
data_in_enable_ext : in STD_LOGIC;
buffer_full : inout STD_LOGIC;
packet_error : inout STD_LOGIC;
force_packet_error : inout STD_LOGIC;
sync_strobe : inout STD_LOGIC;
online : out STD_LOGIC;
network_reg_addr : in STD_LOGIC_VECTOR(3 downto 0);
network_reg_data : out STD_LOGIC_VECTOR(31 downto 0);
network_reg_clk : in STD_LOGIC;
node_is_master : out STD_LOGIC;
node_address : out STD_LOGIC_VECTOR(3 downto 0);
clk_50M : in STD_LOGIC;
reset : in STD_LOGIC;
sig_in : in STD_LOGIC;
sig_out : inout STD_LOGIC);
end tdl_top;
 
architecture Behavioral of tdl_top is
attribute buffer_type: string;
attribute buffer_type of network_reg_clk: signal is "none"; --Make sure that the network register clock doesn't use a GCLK
 
type MAIN_STATES is (IDLE, MASTER_DSC, NET_DSC, REG_DSC, SYNC_DSC, DATA, ERROR);
type TX_STATES is (IDLE, DATA_CMD, DATA, CRC, ERROR);
type RX_STATES is (IDLE, CMD, DATA, CRC, ERROR);
 
signal main_state : MAIN_STATES := IDLE;
signal next_main_state : MAIN_STATES := IDLE;
signal tx_state : TX_STATES := IDLE;
signal next_tx_state : TX_STATES := IDLE;
signal rx_state : RX_STATES := IDLE;
signal next_rx_state : RX_STATES := IDLE;
signal tx_data : STD_LOGIC_VECTOR(7 downto 0);
signal tx_clk_en : STD_LOGIC;
signal tx_enable : STD_LOGIC;
signal tx_clk_div_reset : STD_LOGIC;
signal tx_clk_div_reset_ack : STD_LOGIC;
signal rx_data : STD_LOGIC_VECTOR(7 downto 0);
signal rx_error : STD_LOGIC;
signal rx_valid : STD_LOGIC;
signal rx_clk : STD_LOGIC;
signal rx_cmd_valid : STD_LOGIC;
signal rx_cmd_valid_buffer_1: STD_LOGIC;
signal rx_cmd_valid_buffer_2: STD_LOGIC;
 
signal main_counter : STD_LOGIC_VECTOR(7 downto 0) := "00000000";
signal last_tx_clk_en : STD_LOGIC;
signal last_rx_clk : STD_LOGIC;
signal last_data_in_strobe : STD_LOGIC;
signal input_buffer : STD_LOGIC_VECTOR(7 downto 0);
signal data_buffer : STD_LOGIC_VECTOR(7 downto 0) := (others => '0');
signal data_out_buffer_1 : STD_LOGIC_VECTOR(7 downto 0);
signal data_out_buffer_2 : STD_LOGIC_VECTOR(7 downto 0);
signal data_out_enable_buffer_1 : STD_LOGIC;
signal data_out_enable_buffer_2 : STD_LOGIC;
signal crcgen_rx_output_buffer : STD_LOGIC_VECTOR(7 downto 0);
signal data_buffer_counter : STD_LOGIC := '0';
signal input_available : STD_LOGIC;
signal internal_reset : STD_LOGIC := '0';
signal do_internal_reset : STD_LOGIC := '0';
signal watchdog_counter : STD_LOGIC_VECTOR(17 downto 0) := "000000000000000000";
signal master_dsc_enable : STD_LOGIC;
signal master_dsc_done : STD_LOGIC;
signal master_dsc_reset : STD_LOGIC;
signal is_master : STD_LOGIC;
signal net_dsc_enable : STD_LOGIC;
signal net_dsc_done : STD_LOGIC;
signal net_dsc_reset : STD_LOGIC;
signal node_count : STD_LOGIC_VECTOR(3 downto 0);
signal address : STD_LOGIC_VECTOR(3 downto 0);
signal reg_dsc_enable : STD_LOGIC;
signal reg_dsc_done : STD_LOGIC;
signal reg_dsc_reset : STD_LOGIC;
signal sync_dsc_enable : STD_LOGIC;
signal sync_dsc_done : STD_LOGIC;
signal sync_dsc_reset : STD_LOGIC;
signal data_enable : STD_LOGIC;
signal network_reg_internal_clk : STD_LOGIC;
signal network_reg_internal_write_data : STD_LOGIC_VECTOR(7 downto 0);
signal network_reg_internal_addr : STD_LOGIC_VECTOR(5 downto 0);
signal network_reg_internal_we : STD_LOGIC_VECTOR(0 downto 0);
signal network_reg_internal_read_data : STD_LOGIC_VECTOR(7 downto 0);
 
signal network_reg_internal_clk_net : STD_LOGIC;
signal network_reg_internal_write_data_net : STD_LOGIC_VECTOR(7 downto 0);
signal network_reg_internal_addr_net : STD_LOGIC_VECTOR(5 downto 0);
signal network_reg_internal_we_net : STD_LOGIC_VECTOR(0 downto 0);
 
signal network_reg_internal_clk_reg : STD_LOGIC;
signal network_reg_internal_write_data_reg : STD_LOGIC_VECTOR(7 downto 0);
signal network_reg_internal_addr_reg : STD_LOGIC_VECTOR(5 downto 0);
signal network_reg_internal_we_reg : STD_LOGIC_VECTOR(0 downto 0);
 
signal data_out : STD_LOGIC_VECTOR(7 downto 0);
signal data_out_strobe : STD_LOGIC;
signal data_out_enable : STD_LOGIC;
signal data_in : STD_LOGIC_VECTOR(7 downto 0);
signal data_in_master : STD_LOGIC_VECTOR(7 downto 0);
signal data_in_net : STD_LOGIC_VECTOR(7 downto 0);
signal data_in_reg : STD_LOGIC_VECTOR(7 downto 0);
signal data_in_sync : STD_LOGIC_VECTOR(7 downto 0);
signal data_in_strobe : STD_LOGIC;
signal data_in_strobe_master : STD_LOGIC;
signal data_in_strobe_net : STD_LOGIC;
signal data_in_strobe_reg : STD_LOGIC;
signal data_in_strobe_sync : STD_LOGIC;
 
signal data_in_enable : STD_LOGIC;
signal data_in_enable_master : STD_LOGIC;
signal data_in_enable_net : STD_LOGIC;
signal data_in_enable_reg : STD_LOGIC;
signal data_in_enable_sync : STD_LOGIC;
 
signal crcgen_tx_input : STD_LOGIC_VECTOR(7 downto 0);
signal crcgen_tx_output : STD_LOGIC_VECTOR(7 downto 0);
signal crcgen_tx_reset : STD_LOGIC;
signal crcgen_tx_clk : STD_LOGIC := '0';
signal crcgen_tx_clk_en : STD_LOGIC := '0';
signal crcgen_tx_clk_en_buffer : STD_LOGIC := '0';
signal crc_tx_done : STD_LOGIC := '0';
 
signal crcgen_rx_input : STD_LOGIC_VECTOR(7 downto 0);
signal crcgen_rx_output : STD_LOGIC_VECTOR(7 downto 0);
signal crcgen_rx_reset : STD_LOGIC;
signal crcgen_rx_clk : STD_LOGIC;
signal crcgen_rx_clk_en : STD_LOGIC;
signal tpl_reset : STD_LOGIC;
component tpl_tx is
Port ( data : in STD_LOGIC_VECTOR(7 downto 0);
clk_50M : in STD_LOGIC;
clk_data_en : out STD_LOGIC;
enable : in STD_LOGIC;
reset : in STD_LOGIC;
sig_out : out STD_LOGIC;
clk_div_reset : in STD_LOGIC;
clk_div_reset_ack : out STD_LOGIC);
end component;
 
component tpl_rx is
Port ( data : out STD_LOGIC_VECTOR(7 downto 0);
valid : out STD_LOGIC;
error : out STD_LOGIC;
clk_data : out STD_LOGIC;
clk_50M : in STD_LOGIC;
reset : in STD_LOGIC;
sig_in : in STD_LOGIC);
end component;
 
component tdl_app_master is
Port ( app_enable : in STD_LOGIC;
app_data_in : in STD_LOGIC_VECTOR(7 downto 0);
app_data_in_strobe : in STD_LOGIC;
app_data_out : out STD_LOGIC_VECTOR(7 downto 0);
app_data_out_strobe : out STD_LOGIC;
app_data_out_enable : out STD_LOGIC;
app_buffer_full : in STD_LOGIC;
app_packet_error : in STD_LOGIC;
app_force_packet_error : out STD_LOGIC;
app_cmd_valid : in STD_LOGIC;
app_sync_strobe : in STD_LOGIC;
app_is_master : out STD_LOGIC;
app_dsc_done : out STD_LOGIC;
app_node_id : in STD_LOGIC_VECTOR(3 downto 0);
app_clk : in STD_LOGIC;
app_reset : in STD_LOGIC);
end component;
component tdl_app_net is
Port ( app_enable : in STD_LOGIC;
app_data_in : in STD_LOGIC_VECTOR(7 downto 0);
app_data_in_strobe : in STD_LOGIC;
app_data_out : out STD_LOGIC_VECTOR(7 downto 0);
app_data_out_strobe : out STD_LOGIC;
app_data_out_enable : out STD_LOGIC;
app_buffer_full : in STD_LOGIC;
app_packet_error : in STD_LOGIC;
app_force_packet_error : out STD_LOGIC;
app_cmd_valid : in STD_LOGIC;
app_sync_strobe : in STD_LOGIC;
app_is_master : in STD_LOGIC;
app_dsc_done : out STD_LOGIC;
app_network_reg_clk : out STD_LOGIC;
app_network_reg_addr : out STD_LOGIC_VECTOR(5 downto 0);
app_network_reg_data_in : in STD_LOGIC_VECTOR(7 downto 0);
app_network_reg_data_out : out STD_LOGIC_VECTOR(7 downto 0);
app_network_reg_we : inout STD_LOGIC_VECTOR(0 downto 0);
app_node_count : out STD_LOGIC_VECTOR(3 downto 0);
app_node_address : out STD_LOGIC_VECTOR(3 downto 0);
app_node_id : in STD_LOGIC_VECTOR(3 downto 0);
app_clk : in STD_LOGIC;
app_reset : in STD_LOGIC);
end component;
component tdl_app_reg is
Port ( app_enable : in STD_LOGIC;
app_data_in : in STD_LOGIC_VECTOR(7 downto 0);
app_data_in_strobe : in STD_LOGIC;
app_data_out : out STD_LOGIC_VECTOR(7 downto 0);
app_data_out_strobe : out STD_LOGIC;
app_data_out_enable : out STD_LOGIC;
app_buffer_full : in STD_LOGIC;
app_packet_error : in STD_LOGIC;
app_force_packet_error : out STD_LOGIC;
app_cmd_valid : in STD_LOGIC;
app_sync_strobe : in STD_LOGIC;
app_is_master : in STD_LOGIC;
app_dsc_done : out STD_LOGIC;
app_network_reg_clk : out STD_LOGIC;
app_network_reg_addr : out STD_LOGIC_VECTOR(5 downto 0);
app_network_reg_data_in : in STD_LOGIC_VECTOR(7 downto 0);
app_network_reg_data_out : out STD_LOGIC_VECTOR(7 downto 0);
app_network_reg_we : inout STD_LOGIC_VECTOR(0 downto 0);
app_node_count : in STD_LOGIC_VECTOR(3 downto 0);
app_node_address : in STD_LOGIC_VECTOR(3 downto 0);
app_node_id : in STD_LOGIC_VECTOR(3 downto 0);
app_reg_enable : in STD_LOGIC_VECTOR(7 downto 0);
app_clk : in STD_LOGIC;
app_reset : in STD_LOGIC);
end component;
component tdl_app_sync is
Port ( app_enable : in STD_LOGIC;
app_data_in : in STD_LOGIC_VECTOR(7 downto 0);
app_data_in_strobe : in STD_LOGIC;
app_data_in_enable : in STD_LOGIC;
app_data_out : out STD_LOGIC_VECTOR(7 downto 0);
app_data_out_strobe : out STD_LOGIC;
app_data_out_enable : out STD_LOGIC;
app_buffer_full : in STD_LOGIC;
app_packet_error : in STD_LOGIC;
app_force_packet_error : out STD_LOGIC;
app_cmd_valid : in STD_LOGIC;
app_sync_strobe : out STD_LOGIC;
app_is_master : in STD_LOGIC;
app_dsc_done : out STD_LOGIC;
app_node_id : in STD_LOGIC_VECTOR(3 downto 0);
app_node_count : in STD_LOGIC_VECTOR(3 downto 0);
app_node_address : in STD_LOGIC_VECTOR(3 downto 0);
app_clk : in STD_LOGIC;
app_reset : in STD_LOGIC);
end component;
component crcgen is
Port( reset : in STD_LOGIC;
clk : in STD_LOGIC;
clk_en : in STD_LOGIC;
Din : in STD_LOGIC_VECTOR(DATA_WIDTH - 1 downto 0);
Xout : out STD_LOGIC_VECTOR(CRCDIM - 1 downto 0));
end component;
 
component network_register is
Port ( clka : in STD_LOGIC;
dina : in STD_LOGIC_VECTOR(7 downto 0);
addra : in STD_LOGIC_VECTOR(5 downto 0);
douta : out STD_LOGIC_VECTOR(7 downto 0);
wea : in STD_LOGIC_VECTOR(0 downto 0);
clkb : in STD_LOGIC;
dinb : in STD_LOGIC_VECTOR(31 downto 0);
addrb : in STD_LOGIC_VECTOR(3 downto 0);
web : in STD_LOGIC_VECTOR(0 downto 0);
doutb : out STD_LOGIC_VECTOR(31 downto 0));
end component;
 
begin
tpl_tx_inst : tpl_tx
Port map ( data => tx_data,
enable => tx_enable,
clk_50M => clk_50M,
clk_data_en => tx_clk_en,
reset => tpl_reset,
sig_out => sig_out,
clk_div_reset => tx_clk_div_reset,
clk_div_reset_ack => tx_clk_div_reset_ack);
tpl_rx_inst : tpl_rx
Port map ( data => rx_data,
valid => rx_valid,
error => rx_error,
clk_data => rx_clk,
clk_50M => clk_50M,
reset => tpl_reset,
sig_in => sig_in);
app_master_inst : tdl_app_master
Port map ( app_enable => master_dsc_enable,
app_data_in => data_out,
app_data_in_strobe => data_out_strobe,
app_data_out => data_in_master,
app_data_out_strobe => data_in_strobe_master,
app_data_out_enable => data_in_enable_master,
app_buffer_full => buffer_full,
app_packet_error => packet_error,
app_cmd_valid => rx_cmd_valid,
app_sync_strobe => sync_strobe,
app_is_master => is_master,
app_dsc_done => master_dsc_done,
app_node_id => node_id,
app_clk => clk_50M,
app_reset => master_dsc_reset);
 
app_net_inst : tdl_app_net
Port map ( app_enable => net_dsc_enable,
app_data_in => data_out,
app_data_in_strobe => data_out_strobe,
app_data_out => data_in_net,
app_data_out_strobe => data_in_strobe_net,
app_data_out_enable => data_in_enable_net,
app_buffer_full => buffer_full,
app_packet_error => packet_error,
app_cmd_valid => rx_cmd_valid,
app_sync_strobe => sync_strobe,
app_is_master => is_master,
app_dsc_done => net_dsc_done,
app_network_reg_clk => network_reg_internal_clk_net,
app_network_reg_data_in => network_reg_internal_read_data,
app_network_reg_data_out => network_reg_internal_write_data_net,
app_network_reg_addr => network_reg_internal_addr_net,
app_network_reg_we => network_reg_internal_we_net,
app_node_count => node_count,
app_node_address => address,
app_node_id => node_id,
app_clk => clk_50M,
app_reset => net_dsc_reset);
 
app_reg_inst : tdl_app_reg
Port map ( app_enable => reg_dsc_enable,
app_data_in => data_out,
app_data_in_strobe => data_out_strobe,
app_data_out => data_in_reg,
app_data_out_strobe => data_in_strobe_reg,
app_data_out_enable => data_in_enable_reg,
app_buffer_full => buffer_full,
app_packet_error => packet_error,
app_cmd_valid => rx_cmd_valid,
app_sync_strobe => sync_strobe,
app_is_master => is_master,
app_dsc_done => reg_dsc_done,
app_network_reg_clk => network_reg_internal_clk_reg,
app_network_reg_data_in => network_reg_internal_read_data,
app_network_reg_data_out => network_reg_internal_write_data_reg,
app_network_reg_addr => network_reg_internal_addr_reg,
app_network_reg_we => network_reg_internal_we_reg,
app_node_count => node_count,
app_node_address => address,
app_node_id => node_id,
app_reg_enable => reg_enable,
app_clk => clk_50M,
app_reset => reg_dsc_reset);
 
app_sync_inst : tdl_app_sync
Port map( app_enable => sync_dsc_enable,
app_data_in => data_out,
app_data_in_strobe => data_out_strobe,
app_data_in_enable => data_out_enable,
app_data_out => data_in_sync,
app_data_out_strobe => data_in_strobe_sync,
app_data_out_enable => data_in_enable_sync,
app_buffer_full => buffer_full,
app_packet_error => packet_error,
app_cmd_valid => rx_cmd_valid,
app_sync_strobe => sync_strobe,
app_is_master => is_master,
app_dsc_done => sync_dsc_done,
app_node_id => node_id,
app_node_count => node_count,
app_node_address => address,
app_clk => clk_50M,
app_reset => sync_dsc_reset);
crcgen_tx_inst : crcgen
Port map ( reset => crcgen_tx_reset,
clk => crcgen_tx_clk,
clk_en => crcgen_tx_clk_en,
Din => crcgen_tx_input,
Xout => crcgen_tx_output);
 
crcgen_rx_inst : crcgen
Port map ( reset => crcgen_rx_reset,
clk => crcgen_rx_clk,
clk_en => crcgen_rx_clk_en,
Din => crcgen_rx_input,
Xout => crcgen_rx_output);
 
crcgen_rx_clk <= clk_50M;
crcgen_rx_clk_en <= '1' when ((rx_clk = '1') and (last_rx_clk = '0')) else '0';
crcgen_rx_reset <= not rx_valid;
crcgen_rx_input <= rx_data;
 
crcgen_tx_clk <= clk_50M;
 
network_register_inst : network_register
Port map ( clka => network_reg_internal_clk,
dina => network_reg_internal_write_data,
addra => network_reg_internal_addr,
wea => network_reg_internal_we,
douta => network_reg_internal_read_data,
clkb => network_reg_clk,
dinb => "00000000000000000000000000000000",
addrb => network_reg_addr,
web => "0",
doutb => network_reg_data);
 
node_is_master <= is_master;
node_address <= address;
online <= data_enable;
process(clk_50M)
begin
if(clk_50M = '1' and clk_50M'EVENT) then
if(reset = '1') then
main_state <= IDLE;
tx_state <= IDLE;
rx_state <= IDLE;
watchdog_counter <= (others => '0');
else
main_state <= next_main_state;
if(data_in_strobe = '1' and last_data_in_strobe = '0' and data_in_enable = '1') then --The initial 8 bit input buffer
input_buffer <= data_in;
input_available <= '1';
end if;
if(tx_clk_en = '0' and input_available = '1') then --The main 8 bit input data buffer
if(data_buffer_counter = '0') then
data_buffer <= input_buffer;
data_buffer_counter <= '1';
input_available <= '0';
end if;
end if;
 
last_tx_clk_en <= tx_clk_en;
last_rx_clk <= rx_clk;
last_data_in_strobe <= data_in_strobe;
end if;
 
if(main_state = next_main_state) then
main_counter <= main_counter + 1;
else
main_counter <= "00000000";
end if;
 
case main_state is --Main state machine
when IDLE =>
master_dsc_enable <= '0';
net_dsc_enable <= '0';
reg_dsc_enable <= '0';
sync_dsc_enable <= '0';
data_enable <= '0';
master_dsc_reset <= '1';
net_dsc_reset <= '1';
reg_dsc_reset <= '1';
sync_dsc_reset <= '1';
input_buffer <= "00000000";
input_available <= '0';
data_buffer <= (others => '0');
data_buffer_counter <= '0';
watchdog_counter <= (others => '0');
internal_reset <= '0';
do_internal_reset <= '0';
if(main_counter < 42) then
tpl_reset <= '1';
else
tpl_reset <= '0';
end if;
when MASTER_DSC =>
master_dsc_enable <= '1';
net_dsc_enable <= '0';
reg_dsc_enable <= '0';
sync_dsc_enable <= '0';
data_enable <= '0';
master_dsc_reset <= '0';
net_dsc_reset <= '0';
reg_dsc_reset <= '0';
sync_dsc_reset <= '0';
internal_reset <= '0';
do_internal_reset <= '0';
when NET_DSC =>
master_dsc_enable <= '0';
net_dsc_enable <= '1';
reg_dsc_enable <= '0';
sync_dsc_enable <= '0';
data_enable <= '0';
when REG_DSC =>
master_dsc_enable <= '0';
net_dsc_enable <= '0';
reg_dsc_enable <= '1';
sync_dsc_enable <= '0';
data_enable <= '0';
when SYNC_DSC =>
master_dsc_enable <= '0';
net_dsc_enable <= '0';
reg_dsc_enable <= '0';
sync_dsc_enable <= '1';
data_enable <= '0';
when DATA =>
master_dsc_enable <= '0';
net_dsc_enable <= '0';
reg_dsc_enable <= '0';
sync_dsc_enable <= '1'; --Keep app_sync enabled to maintain the sync signal during operation
data_enable <= '1';
when ERROR =>
end case;
 
if(do_internal_reset = '1') then --Perform reset if requested internally...
internal_reset <= '1';
end if;
 
if(reset = '1' or internal_reset = '1') then
tx_state <= IDLE;
rx_state <= IDLE;
else
tx_state <= next_tx_state;
rx_state <= next_rx_state;
end if;
 
crcgen_tx_clk_en_buffer <= tx_clk_en;
crcgen_tx_clk_en <= crcgen_tx_clk_en_buffer;
 
if(tx_state = IDLE) then --This is used to optimize the jitter performance, by restarting the clock enable generation of the physical transmission layer, thus creating a better synchronization with the upper layers. Without, you risk waiting for tx_clk_en for a full 1.25 MHz clock cycle (800 ns) - by resetting the clock generation you wait 0 to 4 50 MHz clock cycles (max 80 ns) instead.
tx_clk_div_reset <= '0';
else
tx_clk_div_reset <= '1';
end if;
 
case tx_state is --Transmission state machine, this part needs to run on clk_50M to avoid multisourcing data_buffer
when IDLE =>
tx_data <= "00000000";
tx_enable <= '0';
crcgen_tx_reset <= '1';
crc_tx_done <= '0';
when DATA_CMD => --Transmit first nibble of DATA command
if(tx_clk_en = '1' and tx_clk_div_reset_ack = '1') then
tx_data <= CMD_DATA & "0000";
tx_enable <= '1';
crcgen_tx_reset <= '0';
crcgen_tx_input <= CMD_DATA & "0000";
end if;
when DATA => --Transmit contents of data buffer
if(tx_clk_en = '1' and tx_clk_div_reset_ack = '1') then
if(not(data_buffer_counter = '0')) then
tx_data <= data_buffer;
data_buffer_counter <= '0';
tx_enable <= '1';
 
crcgen_tx_reset <= '0'; --Load the transmitted byte into the CRC module
crcgen_tx_input <= data_buffer;
else --AARRG... Buffer underrun... do.. erm... something...
tx_enable <= '0';
end if;
elsif((data_in_enable = '0') and (data_buffer_counter = '0') and (crcgen_tx_clk_en = '1')) then --When data has been transmitted, load a byte containing all zeros into the CRC module
crcgen_tx_input <= "00000000";
crcgen_tx_clk_en_buffer <= '1';
crc_tx_done <= '1';
end if;
when CRC => --Transmit CRC checksum
if(tx_clk_en = '1') then
if(force_packet_error = '1') then
tx_data <= not crcgen_tx_output(7 downto 0); --Flip the CRC byte to make sure this packet produces a CRC error at the receiver... Of course you can neven be completely sure with a CRC check, but the probability is quite good;)
else
tx_data <= crcgen_tx_output(7 downto 0);
end if;
tx_enable <= '1';
end if;
when ERROR =>
end case;
 
 
if(rx_clk = '0' and last_rx_clk = '1') then
data_out <= data_out_buffer_2;
data_out_buffer_2 <= data_out_buffer_1;
data_out_enable <= data_out_enable_buffer_2;
data_out_enable_buffer_2 <= data_out_enable_buffer_1;
rx_cmd_valid <= rx_cmd_valid_buffer_2;
rx_cmd_valid_buffer_2 <= rx_cmd_valid_buffer_1;
end if;
 
case rx_state is
when IDLE =>
data_out_buffer_1 <= (others => '0');
data_out_buffer_2 <= (others => '0');
data_out_enable_buffer_1 <= '0';
data_out_enable_buffer_2 <= '0';
rx_cmd_valid_buffer_1 <= '0';
rx_cmd_valid_buffer_2 <= '0';
when CMD =>
watchdog_counter <= (others => '0'); --We are receiving something => The network is alive (in some way at least) => Reset the watchdog
if(rx_clk = '1' and last_rx_clk = '0') then
data_out_buffer_1 <= rx_data;
 
rx_cmd_valid_buffer_1 <= '0';
case main_state is
when IDLE =>
when MASTER_DSC =>
data_out_enable_buffer_1 <= '1';
case rx_data(7 downto 4) is --Check for a valid command
when CMD_MASTER_DSC =>
rx_cmd_valid_buffer_1 <= '1';
when CMD_MASTER_SET =>
rx_cmd_valid_buffer_1 <= '1';
when others =>
end case;
 
when NET_DSC =>
data_out_enable_buffer_1 <= '1';
 
case rx_data(7 downto 4) is --Check for a valid command
when CMD_MASTER_DSC => --If we receive master discovery packets, the network is being reset, so do the same here
do_internal_reset <= '1';
when CMD_NET_DSC =>
rx_cmd_valid_buffer_1 <= '1';
when CMD_NET_SET =>
rx_cmd_valid_buffer_1 <= '1';
when others =>
end case;
 
when REG_DSC =>
data_out_enable_buffer_1 <= '1';
 
case rx_data(7 downto 4) is --As above
when CMD_MASTER_DSC =>
do_internal_reset <= '1';
when CMD_REG_DSC =>
rx_cmd_valid_buffer_1 <= '1';
when CMD_REG_SET =>
rx_cmd_valid_buffer_1 <= '1';
when others =>
end case;
 
when SYNC_DSC =>
data_out_enable_buffer_1 <= '1';
 
case rx_data(7 downto 4) is --As above (this is actually a leftover from an early sync_dsc implementation, where the delay was measured at startup - currently a fixed delay is used instead, but it's nice to keep this around (also to be able to react to network resets during the sync_dsc state quickly))
when CMD_MASTER_DSC =>
do_internal_reset <= '1';
when CMD_SYNC_DSC =>
rx_cmd_valid_buffer_1 <= '1';
when CMD_SYNC_SET =>
rx_cmd_valid_buffer_1 <= '1';
when others =>
end case;
 
when DATA =>
data_out_enable_buffer_1 <= '0';
 
case rx_data(7 downto 4) is --As above
when CMD_MASTER_DSC =>
do_internal_reset <= '1';
when CMD_DATA =>
rx_cmd_valid_buffer_1 <= '1';
when others =>
end case;
 
when ERROR =>
end case;
end if;
when DATA =>
watchdog_counter <= (others => '0');
if(rx_clk = '1' and last_rx_clk = '0') then
data_out_enable_buffer_1 <= '1';
data_out_buffer_1 <= rx_data;
end if;
crcgen_rx_output_buffer <= crcgen_rx_output;
when CRC =>
data_out_enable_buffer_1 <= '0';
data_out_enable_buffer_2 <= '0';
if(crcgen_rx_output_buffer = "00000000") then
packet_error <= '0';
else
packet_error <= '1';
end if;
when ERROR =>
end case;
 
if(tx_clk_en = '0' and last_tx_clk_en = '1') then
watchdog_counter <= watchdog_counter + 1; --Increment the watchdog
if(watchdog_counter = watchdog_threshold) then --If the watchdog timer crosses the threshold, perform an internal reset
do_internal_reset <= '1';
end if;
end if;
end if;
end process;
data_out_strobe <= rx_clk and data_out_enable;
process(main_state, main_counter, master_dsc_done, net_dsc_done, reg_dsc_done, sync_dsc_done, data_buffer_counter, internal_reset)
begin
case main_state is
when IDLE =>
if(main_counter = 100 and data_buffer_counter = '0') then
next_main_state <= MASTER_DSC;
else
next_main_state <= IDLE;
end if;
when MASTER_DSC =>
if(internal_reset = '1') then
next_main_state <= IDLE;
elsif(master_dsc_done = '1' and data_buffer_counter = '0') then
next_main_state <= NET_DSC;
else
next_main_state <= MASTER_DSC;
end if;
when NET_DSC =>
if(internal_reset = '1') then
next_main_state <= IDLE;
elsif(net_dsc_done = '1' and data_buffer_counter = '0') then
next_main_state <= REG_DSC;
else
next_main_state <= NET_DSC;
end if;
when REG_DSC =>
if(internal_reset = '1') then
next_main_state <= IDLE;
elsif(reg_dsc_done = '1' and data_buffer_counter = '0') then
next_main_state <= SYNC_DSC;
else
next_main_state <= REG_DSC;
end if;
when SYNC_DSC =>
if(internal_reset = '1') then
next_main_state <= IDLE;
elsif(sync_dsc_done = '1' and data_buffer_counter = '0') then
next_main_state <= DATA;
else
next_main_state <= SYNC_DSC;
end if;
when DATA =>
if(internal_reset = '1') then
next_main_state <= IDLE;
else
next_main_state <= DATA;
end if;
when ERROR =>
if(internal_reset = '1') then
next_main_state <= IDLE;
else
next_main_state <= ERROR;
end if;
when others =>
next_main_state <= ERROR;
end case;
end process;
 
process(tx_state, data_in_enable, data_buffer_counter, main_state, crc_tx_done, tx_clk_en, tx_enable)
begin
case tx_state is
when IDLE =>
if(data_buffer_counter = '0') then
next_tx_state <= IDLE;
else
if(main_state = DATA) then
next_tx_state <= DATA_CMD;
else
next_tx_state <= DATA;
end if;
end if;
when DATA_CMD =>
if(tx_enable = '1') then
next_tx_state <= DATA;
else
next_tx_state <= DATA_CMD;
end if;
when DATA =>
if(crc_tx_done = '1') then
next_tx_state <= CRC;
else
next_tx_state <= DATA;
end if;
when CRC =>
if(crc_tx_done = '1' and tx_clk_en = '1') then
next_tx_state <= IDLE;
else
next_tx_state <= CRC;
end if;
when ERROR =>
next_tx_state <= IDLE;
end case;
end process;
 
 
process(rx_state, rx_valid, rx_data, rx_error, rx_clk, last_rx_clk) --Receive state machine
begin
case rx_state is
when IDLE =>
if(rx_valid = '1') then
if(rx_error = '1') then
next_rx_state <= ERROR;
else
next_rx_state <= CMD;
end if;
else
next_rx_state <= IDLE;
end if;
when CMD =>
if(rx_clk = '1' and last_rx_clk = '0') then
if(rx_valid = '1') then
if(rx_error = '1') then
next_rx_state <= ERROR;
else
next_rx_state <= DATA;
end if;
else
next_rx_state <= CRC;
end if;
else
next_rx_state <= CMD;
end if;
when DATA =>
if(rx_clk = '1' and last_rx_clk = '0') then
if(rx_valid = '1') then
if(rx_error = '1') then
next_rx_state <= ERROR;
else
next_rx_state <= DATA;
end if;
else
next_rx_state <= CRC;
end if;
else
next_rx_state <= DATA;
end if;
when CRC =>
next_rx_state <= IDLE;
when ERROR =>
next_rx_state <= IDLE;
end case;
end process;
 
 
 
buffer_full <= '1' when (data_buffer_counter = '1') or (input_available = '1') else '0';
 
--TosNet protocol interface input multiplexing
data_in <= data_in_master when master_dsc_enable = '1' else
data_in_net when net_dsc_enable = '1' else
data_in_reg when reg_dsc_enable = '1' else
data_in_ext when data_enable = '1' else
data_in_sync when sync_dsc_enable = '1' else --Sync needs to be last (or at least just after ext), as it will be kept enabled during operation... Same goes for the other two signals...
"00000000";
data_in_strobe <= data_in_strobe_master when master_dsc_enable = '1' else
data_in_strobe_net when net_dsc_enable = '1' else
data_in_strobe_reg when reg_dsc_enable = '1' else
data_in_strobe_ext when data_enable = '1' else
data_in_strobe_sync when sync_dsc_enable = '1' else
'0';
data_in_enable <= data_in_enable_master when master_dsc_enable = '1' else
data_in_enable_net when net_dsc_enable = '1' else
data_in_enable_reg when reg_dsc_enable = '1' else
data_in_enable_ext when data_enable = '1' else
data_in_enable_sync when sync_dsc_enable = '1' else
'0';
 
--Network register interface multiplexing
network_reg_internal_clk <= network_reg_internal_clk_net when net_dsc_enable = '1' else
network_reg_internal_clk_reg when reg_dsc_enable = '1' else
'0';
network_reg_internal_write_data <= network_reg_internal_write_data_net when net_dsc_enable = '1' else
network_reg_internal_write_data_reg when reg_dsc_enable = '1' else
"00000000";
network_reg_internal_addr <= network_reg_internal_addr_net when net_dsc_enable = '1' else
network_reg_internal_addr_reg when reg_dsc_enable = '1' else
"000000";
network_reg_internal_we <= network_reg_internal_we_net when net_dsc_enable = '1' else
network_reg_internal_we_reg when reg_dsc_enable = '1' else
"0";
 
--TosNet protocol interface output gating
data_out_ext <= data_out when data_enable = '1' else "00000000";
data_out_enable_ext <= data_out_enable when data_enable = '1' else '0';
data_out_strobe_ext <= data_out_strobe when data_enable = '1' else '0';
end Behavioral;
 
/trunk/gateware/TosNet_rev3_2/lfsr.vhd
0,0 → 1,79
----------------------------------------------------------------------------------
-- Company: University of Southern Denmark
-- Engineer: Simon Falsig
--
-- Create Date: 9/6/2008
-- Design Name: Linear Feedback Shift Register
-- Module Name: lfsr - Behavioral
-- File Name: lfsr.vhd
-- Project Name: TosNet
-- Target Devices: Spartan3/6
-- Tool versions: Xilinx ISE 12.2
-- Description: The LFSR is used to create pseudo-random sequences that are
-- used for scrambling outgoing data. With a similarly seeded
-- LFSR on the receiving side, the data can be de-scrambled.
--
-- Revision:
-- Revision 3.2 - Initial release
--
-- Copyright 2010
--
-- This module 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 3 of the License, or
-- (at your option) any later version.
--
-- This module 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 module. If not, see <http://www.gnu.org/licenses/>.
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.NUMERIC_STD.ALL;
 
 
entity lfsr is
generic (
lfsr_length : STD_LOGIC_VECTOR(7 downto 0);
lfsr_out_length : STD_LOGIC_VECTOR(7 downto 0);
lfsr_allow_zero : STD_LOGIC);
port (
lfsr_out : out STD_LOGIC_VECTOR((conv_integer(lfsr_out_length) - 1) downto 0);
lfsr_seed : in STD_LOGIC_VECTOR((conv_integer(lfsr_length) - 1) downto 0);
lfsr_reset : in STD_LOGIC;
lfsr_clk : in STD_LOGIC;
lfsr_clk_en : in STD_LOGIC);
end lfsr;
 
architecture Behavioral of lfsr is
 
signal value : STD_LOGIC_VECTOR((conv_integer(lfsr_length) - 1) downto 0);
 
begin
 
process(lfsr_clk)
begin
if(lfsr_clk = '1' and lfsr_clk'EVENT) then
if(lfsr_reset = '1') then
value <= lfsr_seed;
lfsr_out <= (others => '0');
elsif(lfsr_clk_en = '1') then
value((conv_integer(lfsr_length) - 2) downto 0) <= value((conv_integer(lfsr_length) - 1) downto 1);
value((conv_integer(lfsr_length) - 1)) <= value(1) xor value(0);
if(lfsr_allow_zero = '0' and value((conv_integer(lfsr_length) - 1) downto (conv_integer(lfsr_length) - conv_integer(lfsr_out_length))) = 0) then
lfsr_out <= (others => '1');
else
lfsr_out <= value((conv_integer(lfsr_length) - 1) downto (conv_integer(lfsr_length) - conv_integer(lfsr_out_length)));
end if;
end if;
end if;
end process;
 
end Behavioral;
 
/trunk/gateware/TosNet_rev3_2/crcpack.vhd
0,0 → 1,38
----------------------------------------------------------------------------------
-- Company: SDU, Robolab, Denmark
-- Engineer: Simon Falsig
--
-- Create Date: 15:49:43 04/01/2008
-- Design Name:
-- Module Name: crcpack - Behavioral
-- Project Name: TosNet Datalink Layer
-- Target Devices: Xilinx Spartan3
-- Tool versions: ISE 9.2.04i
-- Description:
-- Adapted from "Parallel CRC Realization", by Guiseppe Campobello, Guiseppe
 
-- October 2003.
-- Adjustments have been made to the layout, and the reset has been converted
-- to a synchronous reset instead of the asynchronous reset from the original
-- paper.
--
-- Dependencies:
-- crcgen.vhd (Contains implementation)
--
-- Revision:
-- Revision 1.00 - Working!
-- Additional Comments:
--
----------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
 
package crcpack is
constant CRC16 : std_logic_vector(16 downto 0) := "11000000000000101";
constant CRCXA6 : std_logic_vector(8 downto 0) := "101100101";
constant CRCDIM : integer := 8;
constant CRC : std_logic_vector(CRCDIM downto 0) := CRCXA6;
constant DATA_WIDTH : integer range 1 to CRCDIM := 8;
type matrix is array (CRCDIM - 1 downto 0) of std_logic_vector (CRCDIM - 1 downto 0);
end crcpack ;
 
/trunk/gateware/TosNet_rev3_2/tpl_rx.vhd
0,0 → 1,260
----------------------------------------------------------------------------------
-- Company: University of Southern Denmark
-- Engineer: Simon Falsig
--
-- Create Date: 19/3/2009
-- Design Name: TosNet
-- Module Name: tpl_rx - Behavioral
-- File Name: tpl_rx.vhd
-- Project Name: TosNet
-- Target Devices: Spartan3/6
-- Tool versions: Xilinx ISE 12.2
-- Description: The receive part of the TosNet physical layer.
--
-- Revision:
-- Revision 3.2 - Initial release
--
-- Copyright 2010
--
-- This module 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 3 of the License, or
-- (at your option) any later version.
--
-- This module 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 module. If not, see <http://www.gnu.org/licenses/>.
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
 
entity tpl_rx is
Port ( data : out STD_LOGIC_VECTOR(7 downto 0);
valid : out STD_LOGIC;
error : out STD_LOGIC;
clk_data : out STD_LOGIC;
clk_50M : in STD_LOGIC;
reset : in STD_LOGIC;
sig_in : in STD_LOGIC);
end tpl_rx;
 
architecture Behavioral of tpl_rx is
 
type STATES is (IDLE, QUIET, REC_START, REC_SEED, REC_DATA, REC_ERROR);
signal state : STATES := IDLE;
signal next_state : STATES := IDLE;
 
signal sig_in_sync : STD_LOGIC := '0';
signal last_sig_in_sync : STD_LOGIC := '0';
signal in_buffer : STD_LOGIC_VECTOR(9 downto 0) := "0000000000";
signal data_buffer : STD_LOGIC_VECTOR(7 downto 0) := "00000000";
signal bit_counter : STD_LOGIC_VECTOR(3 downto 0) := "0000";
signal last_bit_counter : STD_LOGIC_VECTOR(3 downto 0) := "0000";
signal clk_data_int : STD_LOGIC := '0';
signal valid_int : STD_LOGIC := '0';
signal bit_counter_synced : STD_LOGIC := '0';
signal lfsr_rec_out : STD_LOGIC_VECTOR(7 downto 0);
signal lfsr_rec_seed : STD_LOGIC_VECTOR(7 downto 0);
signal lfsr_rec_reset : STD_LOGIC;
signal lfsr_rec_clk : STD_LOGIC;
signal lfsr_rec_clk_en : STD_LOGIC;
signal dec_clk : STD_LOGIC;
signal dec_clk_en : STD_LOGIC;
signal dec_in : STD_LOGIC_VECTOR(9 downto 0);
signal dec_out : STD_LOGIC_VECTOR(7 downto 0);
signal dec_kout : STD_LOGIC;
signal dec_code_err : STD_LOGIC;
component lfsr is
generic (
lfsr_length : STD_LOGIC_VECTOR(7 downto 0);
lfsr_out_length : STD_LOGIC_VECTOR(7 downto 0);
lfsr_allow_zero : STD_LOGIC);
port (
lfsr_out : out STD_LOGIC_VECTOR((conv_integer(lfsr_out_length) - 1) downto 0);
lfsr_seed : in STD_LOGIC_VECTOR((conv_integer(lfsr_length) - 1) downto 0);
lfsr_reset : in STD_LOGIC;
lfsr_clk : in STD_LOGIC;
lfsr_clk_en : in STD_LOGIC);
end component;
component dec_8b10b is
port (
clk : in STD_LOGIC;
ce : in STD_LOGIC;
din : in STD_LOGIC_VECTOR(9 downto 0);
dout : out STD_LOGIC_VECTOR(7 downto 0);
kout : out STD_LOGIC;
code_err : out STD_LOGIC);
end component;
begin
 
clk_data <= clk_data_int;
valid <= valid_int and not dec_kout;
 
lfsr_rec_clk <= clk_50M;
 
lfsr_rec : lfsr
Generic map ( lfsr_length => "00001000",
lfsr_out_length => "00001000",
lfsr_allow_zero => '0')
Port map ( lfsr_out => lfsr_rec_out,
lfsr_seed => lfsr_rec_seed,
lfsr_reset => lfsr_rec_reset,
lfsr_clk => lfsr_rec_clk,
lfsr_clk_en => lfsr_rec_clk_en);
 
dec_clk <= clk_50M;
data_buffer <= dec_out xor lfsr_rec_out;
dec : dec_8b10b
Port map ( clk => dec_clk,
ce => dec_clk_en,
din => dec_in,
dout => dec_out,
kout => dec_kout,
code_err => dec_code_err);
 
process(clk_50M)
variable sig_in_counter : STD_LOGIC_VECTOR(1 downto 0) := "00";
begin
if(clk_50M = '1' and clk_50M'event) then
if(reset = '1') then
state <= IDLE;
else
state <= next_state;
end if;
 
sig_in_sync <= sig_in;
last_sig_in_sync <= sig_in_sync;
 
if(last_sig_in_sync = sig_in_sync) then
sig_in_counter := sig_in_counter + 1;
else
sig_in_counter := (others => '0');
end if;
if(sig_in_counter(1 downto 0) = "01") then --This should be the approximate middle of the bit cell
in_buffer <= sig_in_sync & in_buffer(9 downto 1);
bit_counter <= bit_counter + 1;
if(bit_counter = 0) then
dec_in <= in_buffer;
clk_data_int <= '1';
elsif(bit_counter = 5) then
clk_data_int <= '0';
end if;
end if;
if(bit_counter = 10) then
bit_counter <= "0000";
end if;
 
if((bit_counter = 1) and (last_bit_counter = 0)) then
dec_clk_en <= '1';
else
dec_clk_en <= '0';
end if;
lfsr_rec_clk_en <= dec_clk_en;
last_bit_counter <= bit_counter;
case state is
when IDLE =>
lfsr_rec_seed <= "00000000";
data <= "00000000";
valid_int <= '0';
error <= '0';
when QUIET =>
bit_counter_synced <= '0';
lfsr_rec_seed <= "00000000";
lfsr_rec_reset <= '1';
data <= "00000000";
valid_int <= '0';
error <= '0';
when REC_START =>
if(bit_counter_synced = '0') then
bit_counter <= "0000";
bit_counter_synced <= '1';
end if;
lfsr_rec_seed <= "00000000";
lfsr_rec_reset <= '1';
data <= "00000000";
valid_int <= '0';
error <= '0';
when REC_SEED =>
lfsr_rec_reset <= '1';
if(bit_counter = 9) then
lfsr_rec_seed <= dec_out;
end if;
data <= "00000000";
valid_int <= '0';
error <= '0';
when REC_DATA =>
lfsr_rec_reset <= '0';
if(bit_counter = 2) then
data <= data_buffer;
valid_int <= '1';
error <= '0';
end if;
when REC_ERROR =>
error <= '1';
end case;
end if;
end process;
process(state, in_buffer, bit_counter, dec_kout, dec_code_err)
begin
case state is
when IDLE =>
next_state <= QUIET;
when QUIET =>
if(in_buffer = "0101111100" or in_buffer = "1010000011") then
next_state <= REC_START;
else
next_state <= QUIET;
end if;
when REC_START =>
if(bit_counter = 10) then
next_state <= REC_SEED;
else
next_state <= REC_START;
end if;
when REC_SEED =>
if(dec_code_err = '1') then --Need to wait until this state to check the decoder error output, as otherwise we may pick up the result of decoding something unaligned, resulting in a whole lot of errors that really aren't there...
next_state <= REC_ERROR;
elsif(bit_counter = 10) then
next_state <= REC_DATA;
else
next_state <= REC_SEED;
end if;
when REC_DATA =>
if(dec_code_err = '1') then
next_state <= REC_ERROR;
elsif(bit_counter = 10 and dec_kout = '1') then
next_state <= QUIET;
else
next_state <= REC_DATA;
end if;
when REC_ERROR =>
next_state <= QUIET;
end case;
end process;
end Behavioral;
 
/trunk/gateware/TosNet_rev3_2/tpl_tx.vhd
0,0 → 1,280
----------------------------------------------------------------------------------
-- Company: University of Southern Denmark
-- Engineer: Simon Falsig
--
-- Create Date: 12/3/2009
-- Design Name: TosNet
-- Module Name: tdl_tx - Behavioral
-- File Name: tdl_tx.vhd
-- Project Name: TosNet
-- Target Devices: Spartan3/6
-- Tool versions: Xilinx ISE 12.2
-- Description: The transmit part of the TosNet physical layer.
--
-- Revision:
-- Revision 3.2 - Initial release
--
-- Copyright 2010
--
-- This module 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 3 of the License, or
-- (at your option) any later version.
--
-- This module 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 module. If not, see <http://www.gnu.org/licenses/>.
--------------------------------------------------------------------------------------------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
 
 
entity tpl_tx is
Port ( data : in STD_LOGIC_VECTOR(7 downto 0);
clk_50M : in STD_LOGIC;
clk_data_en : out STD_LOGIC;
enable : in STD_LOGIC;
reset : in STD_LOGIC;
sig_out : out STD_LOGIC;
clk_div_reset : in STD_LOGIC;
clk_div_reset_ack : out STD_LOGIC);
end tpl_tx;
 
architecture Behavioral of tpl_tx is
 
constant LFSR_INITIAL_SEED : STD_LOGIC_VECTOR(7 downto 0) := "01010101";
constant K_COMMA_1 : STD_LOGIC_VECTOR(7 downto 0) := "00111100";
constant K_COMMA_2 : STD_LOGIC_VECTOR(7 downto 0) := "10111100";
 
signal last_clk_div_reset : STD_LOGIC;
signal reset_clk_div : STD_LOGIC := '0';
signal clk_div : STD_LOGIC_VECTOR(5 downto 0) := (others => '0');
signal clk_en_12M5 : STD_LOGIC;
signal clk_en_1M25_0 : STD_LOGIC;
signal clk_en_1M25_1 : STD_LOGIC;
signal clk_en_1M25_2 : STD_LOGIC;
signal clk_en_1M25_3 : STD_LOGIC;
signal data_buffer_1 : STD_LOGIC_VECTOR(7 downto 0) := (others => '0');
signal data_buffer_2 : STD_LOGIC_VECTOR(7 downto 0) := (others => '0');
signal data_buffer_3 : STD_LOGIC_VECTOR(7 downto 0) := (others => '0');
signal enable_buffer_1 : STD_LOGIC := '0';
signal enable_buffer_2 : STD_LOGIC := '0';
signal out_buffer : STD_LOGIC_VECTOR(9 downto 0) := (others => '0');
type STATES is (IDLE, TRN_START, TRN_SEED, TRN_DATA);
signal state : STATES := IDLE;
signal next_state : STATES := IDLE;
 
signal lfsr_seed_out : STD_LOGIC_VECTOR(7 downto 0);
signal lfsr_seed_seed : STD_LOGIC_VECTOR(7 downto 0);
signal lfsr_seed_reset : STD_LOGIC;
signal lfsr_seed_clk : STD_LOGIC;
signal lfsr_seed_clk_en : STD_LOGIC;
signal lfsr_trn_out : STD_LOGIC_VECTOR(7 downto 0);
signal lfsr_trn_seed : STD_LOGIC_VECTOR(7 downto 0);
signal lfsr_trn_reset : STD_LOGIC;
signal lfsr_trn_clk : STD_LOGIC;
signal lfsr_trn_clk_en : STD_LOGIC;
 
signal enc_in : STD_LOGIC_VECTOR(7 downto 0) := K_COMMA_1;
signal enc_out : STD_LOGIC_VECTOR(9 downto 0);
signal enc_kin : STD_LOGIC := '1';
signal enc_clk : STD_LOGIC;
signal enc_clk_en : STD_LOGIC;
component lfsr is
generic (
lfsr_length : STD_LOGIC_VECTOR(7 downto 0);
lfsr_out_length : STD_LOGIC_VECTOR(7 downto 0);
lfsr_allow_zero : STD_LOGIC);
port (
lfsr_out : out STD_LOGIC_VECTOR((conv_integer(lfsr_out_length) - 1) downto 0);
lfsr_seed : in STD_LOGIC_VECTOR((conv_integer(lfsr_length) - 1) downto 0);
lfsr_reset : in STD_LOGIC;
lfsr_clk : in STD_LOGIC;
lfsr_clk_en : in STD_LOGIC);
end component;
component enc_8b10b is
port (
din : in STD_LOGIC_VECTOR(7 downto 0);
kin : in STD_LOGIC;
clk : in STD_LOGIC;
dout : out STD_LOGIC_VECTOR(9 downto 0);
ce : in STD_LOGIC);
end component;
 
begin
 
clk_data_en <= clk_en_1M25_0;
 
lfsr_seed_seed <= LFSR_INITIAL_SEED;
lfsr_seed_clk <= clk_50M;
lfsr_seed_reset <= reset;
lfsr_trn_clk <= clk_50M;
lfsr_trn_clk_en <= clk_en_1M25_1;
 
lfsr_seed : lfsr
Generic map ( lfsr_length => "00001000",
lfsr_out_length => "00001000",
lfsr_allow_zero => '0')
Port map ( lfsr_out => lfsr_seed_out,
lfsr_seed => lfsr_seed_seed,
lfsr_reset => lfsr_seed_reset,
lfsr_clk => lfsr_seed_clk,
lfsr_clk_en => lfsr_seed_clk_en);
lfsr_trn : lfsr
Generic map ( lfsr_length => "00001000",
lfsr_out_length => "00001000",
lfsr_allow_zero => '0')
Port map ( lfsr_out => lfsr_trn_out,
lfsr_seed => lfsr_trn_seed,
lfsr_reset => lfsr_trn_reset,
lfsr_clk => lfsr_trn_clk,
lfsr_clk_en => lfsr_trn_clk_en);
enc : enc_8b10b
Port map ( din => enc_in,
kin => enc_kin,
clk => enc_clk,
dout => enc_out,
ce => enc_clk_en);
 
enc_clk <= clk_50M;
enc_clk_en <= clk_en_1M25_2;
 
process(clk_50M)
begin
if(clk_50M = '1' and clk_50M'event) then
if(clk_div_reset = '1' and last_clk_div_reset = '0') then
reset_clk_div <= '1';
elsif(clk_div_reset = '0') then
clk_div_reset_ack <= '0';
end if;
 
if(reset_clk_div = '1' and clk_div(1 downto 0) = "11") then
clk_div <= "100100";
reset_clk_div <= '0';
clk_div_reset_ack <= '1';
else
if(clk_div = 39) then
clk_div <= (others => '0');
else
clk_div <= clk_div + 1;
end if;
end if;
 
last_clk_div_reset <= clk_div_reset;
end if;
end process;
 
clk_en_12M5 <= '1' when clk_div(1 downto 0) = "11" else '0'; --Sync the phase to clk_en_1M25_3
clk_en_1M25_0 <= '1' when clk_div = "000000" else '0'; --We're using phase-shifted versions of the clock-enables to minimize the latency of the system, as all the parts are perfectly pipelined anyway
clk_en_1M25_1 <= '1' when clk_div = "000001" else '0';
clk_en_1M25_2 <= '1' when clk_div = "000010" else '0';
clk_en_1M25_3 <= '1' when clk_div = "000011" else '0';
 
lfsr_trn_seed <= lfsr_seed_out;
process(clk_50M)
begin
if(clk_50M = '1' and clk_50M'event) then
if(reset = '1') then
state <= IDLE;
elsif(clk_en_1M25_1 = '1') then
state <= next_state;
data_buffer_3 <= data_buffer_2;
data_buffer_2 <= data_buffer_1;
data_buffer_1 <= data;
enable_buffer_2 <= enable_buffer_1;
enable_buffer_1 <= enable;
end if;
end if;
end process;
 
process(state, lfsr_trn_seed, data_buffer_3, lfsr_trn_out, clk_en_1M25_1)
begin
case state is
when IDLE =>
enc_in <= K_COMMA_1;
enc_kin <= '1';
lfsr_trn_reset <= '1';
lfsr_seed_clk_en <= clk_en_1M25_1;
when TRN_START =>
enc_in <= K_COMMA_2;
enc_kin <= '1';
lfsr_trn_reset <= '1';
lfsr_seed_clk_en <= '0';
when TRN_SEED =>
enc_in <= lfsr_trn_seed;
enc_kin <= '0';
lfsr_trn_reset <= '0';
lfsr_seed_clk_en <= '0';
when TRN_DATA =>
enc_in <= data_buffer_3 xor lfsr_trn_out;
enc_kin <= '0';
lfsr_trn_reset <= '0';
lfsr_seed_clk_en <= '0';
end case;
end process;
process(clk_50M)
begin
if(clk_50M = '1' and clk_50M'event) then
if(reset = '1') then
out_buffer <= (others => '0');
sig_out <= '0';
elsif(clk_en_12M5 = '1') then
if(clk_en_1M25_3 = '1') then
out_buffer <= enc_out;
else
out_buffer <= '0' & out_buffer(9 downto 1);
end if;
sig_out <= out_buffer(0);
end if;
end if;
end process;
 
process(state, enable, enable_buffer_2)
begin
case state is
when IDLE =>
if(enable = '1') then
next_state <= TRN_START;
else
next_state <= IDLE;
end if;
when TRN_START =>
next_state <= TRN_SEED;
when TRN_SEED =>
next_state <= TRN_DATA;
when TRN_DATA =>
if(enable_buffer_2 = '1') then
next_state <= TRN_DATA;
else
next_state <= IDLE;
end if;
end case;
end process;
 
end Behavioral;
/trunk/gateware/TosNet_rev3_2/tosnet.vhd
0,0 → 1,266
----------------------------------------------------------------------------------
-- Company: University of Southern Denmark
-- Engineer: Simon Falsig
--
-- Create Date: 30/7/2010
-- Design Name: TosNet
-- Module Name: tosnet - Behavioral
-- File Name: tosnet.vhd
-- Project Name: TosNet
-- Target Devices: Spartan3/6
-- Tool versions: Xilinx ISE 12.2
-- Description: TosNet is a fully FPGA-based isochronous network targeted for
-- use in prototype, modular, distributed robot controllers. Full
-- specification can be seen in the documentation.
-- This is the top-level wrapper, containing the application
-- and data-link/physical layer modules.
--
-- Revision:
-- Revision 3.2 - Initial release
--
-- Copyright 2010
--
-- This module 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 3 of the License, or
-- (at your option) any later version.
--
-- This module 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 module. If not, see <http://www.gnu.org/licenses/>.
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
--use IEEE.STD_LOGIC_UNSIGNED.ALL;
library UNISIM;
use UNISIM.vcomponents.all;
 
entity tosnet is -- Ports marked with * are required
Generic ( disable_slave : STD_LOGIC := '0'; -- Disable the slave functionality
disable_master : STD_LOGIC := '0'; -- Disable the master functionality (can drastically reduce the amount of logic required for slave-only nodes)
disable_async : STD_LOGIC := '0'); -- Disable async functionality (async will still work for other nodes in the network, communication to a node with async disabled will be silently discarded)
Port ( sig_in : in STD_LOGIC; --*The serial input signal
sig_out : out STD_LOGIC; --*The serial output signal
clk_50M : in STD_LOGIC; --*The 50 MHz input clock
reset : in STD_LOGIC; -- Active high reset
sync_strobe : out STD_LOGIC; -- Active high synchronization strobe (asserted for one clock cycle during synchronication)
online : out STD_LOGIC; -- Active high online indicator (asserted when network is configured and running)
is_master : out STD_LOGIC; -- Active high is_master indicator (asserted when current node is master)
packet_error : out STD_LOGIC; -- Active high packet error indicator (asserted whenever the previously received packet was erroneous)
system_halt : out STD_LOGIC; -- Active high system halt signal (asserted when the max_skipped thresholds are exceeded)
node_id : in STD_LOGIC_VECTOR(3 downto 0); --*The id of the current node
reg_enable : in STD_LOGIC_VECTOR(7 downto 0); --*Bit-vector describing which registers are enabled (a '1' indicates that the corresponding register is enabled, '0' that it is disabled)
watchdog_threshold : in STD_LOGIC_VECTOR(17 downto 0); --*The threshold of the watchdog in 1.25 MHz clock cycles
max_skipped_writes : in STD_LOGIC_VECTOR(15 downto 0); --*The maximum amount of consecutive clock cycles without a write to the shared memory block (set to 0 to disable)
max_skipped_reads : in STD_LOGIC_VECTOR(15 downto 0); --*The maximum amount of consecutive clock cycles without a read from the shared memory block (set to 0 to disable)
data_reg_addr : in STD_LOGIC_VECTOR(9 downto 0); -- The address bus of the shared memory block
data_reg_data_in : in STD_LOGIC_VECTOR(31 downto 0); -- The input data bus to the shared memory block
data_reg_data_out : out STD_LOGIC_VECTOR(31 downto 0); -- The output data bus from the shared memory block
data_reg_clk : in STD_LOGIC; -- The clock for the shared memory block
data_reg_we : in STD_LOGIC_VECTOR(0 downto 0); -- Active high write enable for the shared memory block
commit_write : in STD_LOGIC; -- Active high signal to commit the out registers
commit_read : in STD_LOGIC; -- Active high signal to commit the in registers
reset_counter : out STD_LOGIC_VECTOR(31 downto 0); -- The number of resets since last configuration
packet_counter : out STD_LOGIC_VECTOR(31 downto 0); -- The number of data packets transmitted since last configuration
error_counter : out STD_LOGIC_VECTOR(31 downto 0); -- The number of erroneous packets received since last configuration
async_in_data : in STD_LOGIC_VECTOR(37 downto 0); -- The async input data bus
async_out_data : out STD_LOGIC_VECTOR(37 downto 0); -- The async output data bus
async_in_clk : in STD_LOGIC; -- The async input clock
async_out_clk : in STD_LOGIC; -- The async output clock
async_in_full : out STD_LOGIC; -- Active high async input full indicator (asserted when async input buffer is full)
async_out_empty : out STD_LOGIC; -- Active high async output empty indicator (asserted when async output buffer is empty)
async_in_wr_en : in STD_LOGIC; -- Active high async input write enable
async_out_rd_en : in STD_LOGIC; -- Active high async output read enable
async_out_valid : out STD_LOGIC); -- Active high async output valid indicator (asserted when valid data is present on the async output data bus)
end tosnet;
 
architecture Behavioral of tosnet is
component tdl_top is
Port ( node_id : in STD_LOGIC_VECTOR(3 downto 0);
reg_enable : in STD_LOGIC_VECTOR(7 downto 0);
watchdog_threshold : in STD_LOGIC_VECTOR(17 downto 0);
data_out_ext : out STD_LOGIC_VECTOR(7 downto 0);
data_out_strobe_ext : out STD_LOGIC;
data_out_enable_ext : out STD_LOGIC;
data_in_ext : in STD_LOGIC_VECTOR(7 downto 0);
data_in_strobe_ext : in STD_LOGIC;
data_in_enable_ext : in STD_LOGIC;
buffer_full : inout STD_LOGIC;
packet_error : inout STD_LOGIC;
force_packet_error : inout STD_LOGIC;
sync_strobe : inout STD_LOGIC;
online : out STD_LOGIC;
network_reg_addr : in STD_LOGIC_VECTOR(3 downto 0);
network_reg_data : out STD_LOGIC_VECTOR(31 downto 0);
network_reg_clk : in STD_LOGIC;
node_is_master : out STD_LOGIC;
node_address : out STD_LOGIC_VECTOR(3 downto 0);
clk_50M : in STD_LOGIC;
reset : in STD_LOGIC;
sig_in : in STD_LOGIC;
sig_out : inout STD_LOGIC);
end component;
component tal_top is
Generic ( disable_slave : STD_LOGIC;
disable_master : STD_LOGIC;
disable_async : STD_LOGIC);
Port ( node_id : in STD_LOGIC_VECTOR(3 downto 0);
max_skipped_writes : in STD_LOGIC_VECTOR(15 downto 0);
max_skipped_reads : in STD_LOGIC_VECTOR(15 downto 0);
data_in : in STD_LOGIC_VECTOR(7 downto 0);
data_in_strobe : in STD_LOGIC;
data_in_enable : in STD_LOGIC;
data_out : out STD_LOGIC_VECTOR(7 downto 0);
data_out_strobe : out STD_LOGIC;
data_out_enable : out STD_LOGIC;
buffer_full : in STD_LOGIC;
packet_error : in STD_LOGIC;
force_packet_error : out STD_LOGIC;
sync_strobe : in STD_LOGIC;
network_reg_addr : out STD_LOGIC_VECTOR(3 downto 0);
network_reg_data : in STD_LOGIC_VECTOR(31 downto 0);
network_reg_clk : out STD_LOGIC;
data_reg_addr : in STD_LOGIC_VECTOR(9 downto 0);
data_reg_data_in : in STD_LOGIC_VECTOR(31 downto 0);
data_reg_data_out : out STD_LOGIC_VECTOR(31 downto 0);
data_reg_clk : in STD_LOGIC;
data_reg_we : in STD_LOGIC_VECTOR(0 downto 0);
data_reg_commit_write : in STD_LOGIC;
data_reg_commit_read : in STD_LOGIC;
skip_count_write : out STD_LOGIC_VECTOR(15 downto 0);
skip_count_read : out STD_LOGIC_VECTOR(15 downto 0);
current_buffer_index : out STD_LOGIC_VECTOR(3 downto 0);
node_address : in STD_LOGIC_VECTOR(3 downto 0);
is_master : in STD_LOGIC;
clk_50M : in STD_LOGIC;
pause : in STD_LOGIC;
pause_ack : out STD_LOGIC;
reset : in STD_LOGIC;
system_halt : out STD_LOGIC;
reset_counter : out STD_LOGIC_VECTOR(31 downto 0);
packet_counter : out STD_LOGIC_VECTOR(31 downto 0);
error_counter : out STD_LOGIC_VECTOR(31 downto 0);
async_in_data : in STD_LOGIC_VECTOR(37 downto 0);
async_out_data : out STD_LOGIC_VECTOR(37 downto 0);
async_in_clk : in STD_LOGIC;
async_out_clk : in STD_LOGIC;
async_in_full : out STD_LOGIC;
async_out_empty : out STD_LOGIC;
async_in_wr_en : in STD_LOGIC;
async_out_rd_en : in STD_LOGIC;
async_out_valid : out STD_LOGIC);
end component;
 
signal sig_out_int : STD_LOGIC;
signal data_up : STD_LOGIC_VECTOR(7 downto 0);
signal data_up_strobe : STD_LOGIC;
signal data_up_enable : STD_LOGIC;
signal data_down : STD_LOGIC_VECTOR(7 downto 0);
signal data_down_strobe : STD_LOGIC;
signal data_down_enable : STD_LOGIC;
signal buffer_full : STD_LOGIC;
signal sync_strobe_int : STD_LOGIC;
signal network_reg_addr : STD_LOGIC_VECTOR(3 downto 0);
signal network_reg_data : STD_LOGIC_VECTOR(31 downto 0);
signal network_reg_clk : STD_LOGIC;
signal node_address : STD_LOGIC_VECTOR(3 downto 0);
signal is_master_int : STD_LOGIC;
signal packet_error_int : STD_LOGIC;
signal online_int : STD_LOGIC;
signal app_reset : STD_LOGIC;
signal force_packet_error : STD_LOGIC;
 
begin
 
 
tdl_top_inst : tdl_top
Port map ( node_id => node_id,
reg_enable => reg_enable,
watchdog_threshold => watchdog_threshold,
sig_in => sig_in,
sig_out => sig_out_int,
reset => reset,
clk_50M => clk_50M,
data_in_ext => data_down,
data_in_enable_ext => data_down_enable,
data_in_strobe_ext => data_down_strobe,
data_out_ext => data_up,
data_out_enable_ext => data_up_enable,
data_out_strobe_ext => data_up_strobe,
buffer_full => buffer_full,
packet_error => packet_error_int,
force_packet_error => force_packet_error,
sync_strobe => sync_strobe_int,
online => online_int,
network_reg_addr => network_reg_addr,
network_reg_data => network_reg_data,
network_reg_clk => network_reg_clk,
node_address => node_address,
node_is_master => is_master_int);
 
application_inst : tal_top
Generic map(disable_slave => disable_slave,
disable_master => disable_master,
disable_async => disable_async)
Port map ( node_id => node_id,
max_skipped_writes => max_skipped_writes,
max_skipped_reads => max_skipped_reads,
data_in => data_up,
data_in_strobe => data_up_strobe,
data_in_enable => data_up_enable,
data_out => data_down,
data_out_strobe => data_down_strobe,
data_out_enable => data_down_enable,
buffer_full => buffer_full,
packet_error => packet_error_int,
force_packet_error => force_packet_error,
sync_strobe => sync_strobe_int,
network_reg_addr => network_reg_addr,
network_reg_data => network_reg_data,
network_reg_clk => network_reg_clk,
node_address => node_address,
is_master => is_master_int,
data_reg_addr => data_reg_addr,
data_reg_data_in => data_reg_data_in,
data_reg_data_out => data_reg_data_out,
data_reg_clk => data_reg_clk,
data_reg_we => data_reg_we,
data_reg_commit_write => commit_write,
data_reg_commit_read => commit_read,
clk_50M => clk_50M,
pause => '0',
reset => app_reset,
system_halt => system_halt,
packet_counter => packet_counter,
error_counter => error_counter,
reset_counter => reset_counter,
async_in_data => async_in_data,
async_out_data => async_out_data,
async_in_clk => async_in_clk,
async_out_clk => async_out_clk,
async_in_full => async_in_full,
async_out_empty => async_out_empty,
async_in_wr_en => async_in_wr_en,
async_out_rd_en => async_out_rd_en,
async_out_valid => async_out_valid);
 
 
sig_out <= sig_out_int;
 
app_reset <= not online_int;
sync_strobe <= sync_strobe_int;
online <= online_int;
is_master <= is_master_int;
packet_error <= packet_error_int;
end Behavioral;
/trunk/gateware/TosNet_rev3_2/commandpack.vhd
0,0 → 1,37
----------------------------------------------------------------------------------
-- Company: SDU, Robolab, Denmark
-- Engineer: Simon Falsig
--
-- Create Date: 15:49:43 04/01/2008
-- Design Name:
-- Module Name: commandpack - Behavioral
-- Project Name: TosNet Datalink Layer
-- Target Devices: Xilinx Spartan3
-- Tool versions: ISE 9.2.04i
-- Description:
-- Contains the commands used for the network.
--
-- Dependencies:
--
-- Revision:
-- Revision 1.00 - Working!
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.all;
 
package commandpack is
constant CMD_IDLE : STD_LOGIC_VECTOR(3 downto 0) := "0000";
constant CMD_MASTER_DSC : STD_LOGIC_VECTOR(3 downto 0) := "0010";
constant CMD_MASTER_SET : STD_LOGIC_VECTOR(3 downto 0) := "0011";
constant CMD_NET_DSC : STD_LOGIC_VECTOR(3 downto 0) := "0100";
constant CMD_NET_SET : STD_LOGIC_VECTOR(3 downto 0) := "0101";
constant CMD_REG_DSC : STD_LOGIC_VECTOR(3 downto 0) := "0110";
constant CMD_REG_SET : STD_LOGIC_VECTOR(3 downto 0) := "0111";
constant CMD_SYNC_DSC : STD_LOGIC_VECTOR(3 downto 0) := "1000";
constant CMD_SYNC_SET : STD_LOGIC_VECTOR(3 downto 0) := "1001";
constant CMD_DATA : STD_LOGIC_VECTOR(3 downto 0) := "1010";
constant CMD_HALT : STD_LOGIC_VECTOR(3 downto 0) := "1111";
end commandpack;
 
/trunk/gateware/TosNet_rev3_2/tdl_app_sync.vhd
0,0 → 1,184
----------------------------------------------------------------------------------
-- Company: University of Southern Denmark
-- Engineer: Simon Falsig
--
-- Create Date: 7/3/2010
-- Design Name TosNet
-- Module Name: app_sync - Behavioral
-- File Name: app_sync.vhd
-- Project Name: TosNet
-- Target Devices: Spartan3/6
-- Tool versions: Xilinx ISE 12.2
-- Description: The synchronization module handles the synchronization strobes
-- that are emitted at the end of each cycle. The strobe is
-- delayed for a fixed interval, depending on the node address
-- (which specifies the position of the node in the network
-- relative to the master), which causes the strobe to be emitted
-- at the same time in all nodes.
--
-- Revision:
-- Revision 3.2 - Initial release
--
-- Copyright 2010
--
-- This module 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 3 of the License, or
-- (at your option) any later version.
--
-- This module 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 module. If not, see <http://www.gnu.org/licenses/>.
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
 
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
 
entity tdl_app_sync is
Port ( app_enable : in STD_LOGIC;
app_data_in : in STD_LOGIC_VECTOR(7 downto 0);
app_data_in_strobe : in STD_LOGIC;
app_data_in_enable : in STD_LOGIC;
app_data_out : out STD_LOGIC_VECTOR(7 downto 0);
app_data_out_strobe : out STD_LOGIC;
app_data_out_enable : out STD_LOGIC;
app_buffer_full : in STD_LOGIC;
app_packet_error : in STD_LOGIC;
app_force_packet_error : out STD_LOGIC;
app_cmd_valid : in STD_LOGIC;
app_sync_strobe : out STD_LOGIC;
app_is_master : in STD_LOGIC;
app_dsc_done : out STD_LOGIC;
app_node_id : in STD_LOGIC_VECTOR(3 downto 0);
app_node_count : in STD_LOGIC_VECTOR(3 downto 0);
app_node_address : in STD_LOGIC_VECTOR(3 downto 0);
app_clk : in STD_LOGIC;
app_reset : in STD_LOGIC);
end tdl_app_sync;
 
architecture Behavioral of tdl_app_sync is
 
type STATES is (OFF, CALC_SYNC_DELAY, SYNC_READY, SYNC_ONLINE, SYNC_RUNNING, SYNC_SET);
signal state : STATES := OFF;
signal next_state : STATES := OFF;
signal last_data_in_enable : STD_LOGIC;
 
signal counter : STD_LOGIC_VECTOR(4 downto 0) := "00000";
signal delay_counter : STD_LOGIC_VECTOR(11 downto 0) := "000000000000";
signal delay_current_node : STD_LOGIC_VECTOR(11 downto 0) := "000000000000";
constant delay_pr_node : STD_LOGIC_VECTOR(11 downto 0) := "000100101100";
 
begin
 
process(app_clk)
begin
if(app_clk = '1' and app_clk'EVENT) then
if(app_reset = '1') then
state <= OFF;
else
state <= next_state;
end if;
if(state = next_state) then
counter <= counter + 1;
else
counter <= "00000";
end if;
 
case state is
 
when OFF =>
delay_counter <= "000000000000";
delay_current_node <= "000000000000";
app_dsc_done <= '0';
last_data_in_enable <= '0';
app_sync_strobe <= '0';
 
when CALC_SYNC_DELAY =>
if(app_is_master = '1') then
delay_current_node <= "000000000000";
elsif(counter = 0) then
delay_current_node <= delay_pr_node;
else
delay_current_node <= delay_current_node + delay_pr_node;
end if;
when SYNC_READY =>
if(app_is_master = '1') then
app_sync_strobe <= '1'; --If this is the master node, send out a single sync pulse to get the application started...
end if;
when SYNC_ONLINE =>
app_dsc_done <= '1';
app_sync_strobe <= '0';
delay_counter <= "000000000000";
when SYNC_RUNNING =>
delay_counter <= delay_counter + 1;
when SYNC_SET =>
app_sync_strobe <= '1';
end case;
last_data_in_enable <= app_data_in_enable;
end if;
end process;
process(state, app_enable, counter, app_node_count, app_node_address, delay_counter, delay_current_node, app_data_in_enable, last_data_in_enable)
begin
case state is
when OFF =>
if(app_enable = '1') then
next_state <= CALC_SYNC_DELAY;
else
next_state <= OFF;
end if;
when CALC_SYNC_DELAY =>
if(counter = app_node_count - app_node_address - 1) then
next_state <= SYNC_READY;
else
next_state <= CALC_SYNC_DELAY;
end if;
when SYNC_READY => --Make sure that the current transmission is done before going online (if not the enable signal from the received sync_set will trigger the sync mechanism... which is kinda not what we want)
if(app_data_in_enable = '0') then
next_state <= SYNC_ONLINE;
else
next_state <= SYNC_READY;
end if;
when SYNC_ONLINE =>
if(app_data_in_enable = '0' and last_data_in_enable = '1') then
next_state <= SYNC_RUNNING;
else
next_state <= SYNC_ONLINE;
end if;
when SYNC_RUNNING =>
if(app_data_in_enable = '1') then --If app_data_in_enable goes high before the sync_strobe something bad is happening - but let's just make sure we don't make it worse by sending a sync_strobe in the middle of a (probably erroneous) transmission...
next_state <= SYNC_ONLINE;
elsif(delay_counter = delay_current_node) then
next_state <= SYNC_SET;
else
next_state <= SYNC_RUNNING;
end if;
when SYNC_SET =>
next_state <= SYNC_ONLINE;
end case;
end process;
 
end Behavioral;
 
/trunk/gateware/TosNet_rev3_2/tdl_app_reg.vhd
0,0 → 1,361
----------------------------------------------------------------------------------
-- Company: University of Southern Denmark
-- Engineer: Simon Falsig
--
-- Create Date: 10/3/2010
-- Design Name TosNet
-- Module Name: app_reg - Behavioral
-- File Name: app_reg.vhd
-- Project Name: TosNet
-- Target Devices: Spartan3/6
-- Tool versions: Xilinx ISE 12.2
-- Description: The registry discovery module runs during startup, and polls
-- all nodes in the network for their enabled registers. The
-- gathered data is then distributed back to the nodes, and
-- stored in their network registers.
--
-- Revision:
-- Revision 3.2 - Initial release
--
-- Copyright 2010
--
-- This module 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 3 of the License, or
-- (at your option) any later version.
--
-- This module 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 module. If not, see <http://www.gnu.org/licenses/>.
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use work.commandpack.all;
 
entity tdl_app_reg is
Port ( app_enable : in STD_LOGIC;
app_data_in : in STD_LOGIC_VECTOR(7 downto 0);
app_data_in_strobe : in STD_LOGIC;
app_data_out : out STD_LOGIC_VECTOR(7 downto 0);
app_data_out_strobe : out STD_LOGIC;
app_data_out_enable : out STD_LOGIC;
app_buffer_full : in STD_LOGIC;
app_packet_error : in STD_LOGIC;
app_force_packet_error : out STD_LOGIC;
app_cmd_valid : in STD_LOGIC;
app_sync_strobe : in STD_LOGIC;
app_is_master : in STD_LOGIC;
app_dsc_done : out STD_LOGIC;
app_network_reg_clk : out STD_LOGIC;
app_network_reg_addr : out STD_LOGIC_VECTOR(5 downto 0);
app_network_reg_data_in : in STD_LOGIC_VECTOR(7 downto 0);
app_network_reg_data_out : out STD_LOGIC_VECTOR(7 downto 0);
app_network_reg_we : inout STD_LOGIC_VECTOR(0 downto 0);
app_node_count : in STD_LOGIC_VECTOR(3 downto 0);
app_node_address : in STD_LOGIC_VECTOR(3 downto 0);
app_node_id : in STD_LOGIC_VECTOR(3 downto 0);
app_reg_enable : in STD_LOGIC_VECTOR(7 downto 0);
app_clk : in STD_LOGIC;
app_reset : in STD_LOGIC);
end tdl_app_reg;
 
architecture Behavioral of tdl_app_reg is
 
type STATES is (OFF, IDLE, DSC_SEND, DSC_RECEIVE, DSC_RESPOND, SET_SEND, SET_RECEIVE, SET_RESPOND, DONE);
signal state : STATES := OFF;
signal next_state : STATES := OFF;
signal last_data_in_strobe : STD_LOGIC;
signal bytes_received : STD_LOGIC_VECTOR(5 downto 0) := "000000";
signal cmd_received : STD_LOGIC := '0';
signal counter : STD_LOGIC_VECTOR(8 downto 0) := "000000000";
signal node_count : STD_LOGIC_VECTOR(4 downto 0);
signal node_address : STD_LOGIC_VECTOR(4 downto 0);
begin
 
node_count <= '0' & app_node_count; --Add a leading 0, so we have an extra bit for eventual carrys
node_address <= '0' & app_node_address;
 
process(app_clk)
begin
if(app_clk = '1' and app_clk'EVENT) then
if(app_reset = '1') then
state <= OFF;
else
state <= next_state;
end if;
 
if(app_buffer_full = '1') then
counter <= counter;
elsif(state = next_state) then
counter <= counter + 1;
else
counter <= "000000000";
end if;
 
case state is
 
when OFF =>
app_data_out_enable <= '0';
app_data_out_strobe <= '0';
app_data_out <= "00000000";
app_force_packet_error <= 'Z';
app_dsc_done <= '0';
app_network_reg_clk <= '0';
app_network_reg_addr <= "000000";
app_network_reg_data_out <= "00000000";
app_network_reg_we <= "0";
last_data_in_strobe <= '0';
bytes_received <= "000000";
cmd_received <= '0';
 
when IDLE =>
app_data_out_enable <= '0';
app_data_out_strobe <= '0';
app_dsc_done <= '0';
app_network_reg_clk <= '0';
app_network_reg_we <= "0";
 
when DSC_SEND => --Transmit discovery packet (master only)
if(counter(8 downto 1) = 0) then
app_data_out_enable <= '1';
app_data_out <= CMD_REG_DSC & "0000";
app_data_out_strobe <= '1';
elsif(counter(8 downto 1) = 1) then
app_data_out_strobe <= '0';
elsif(counter(8 downto 1) = 2) then
app_data_out <= app_reg_enable;
app_data_out_strobe <= '1';
elsif(counter(8 downto 1) = 3) then
app_data_out_strobe <= '0';
elsif(counter(8 downto 1) = 4) then
app_data_out <= app_reg_enable;
app_data_out_strobe <= '1';
else
app_data_out_enable <= '0';
app_data_out_strobe <= '0';
end if;
 
when DSC_RECEIVE => --Receive discovery packet
if(app_data_in_strobe = '1' and last_data_in_strobe = '0') then
if(bytes_received = 0 and app_data_in(7 downto 4) = CMD_REG_DSC and cmd_received = '0') then
bytes_received <= "000000";
cmd_received <= '1';
else
app_network_reg_addr <= bytes_received(4 downto 0) & not bytes_received(0);
app_network_reg_data_out <= app_data_in;
app_network_reg_we <= "1";
app_network_reg_clk <= '0';
bytes_received <= bytes_received + 1;
end if;
elsif(app_data_in_strobe = '0' and last_data_in_strobe = '1' and app_network_reg_we = "1") then
app_network_reg_clk <= '1';
else
app_network_reg_clk <= '0';
end if;
 
when DSC_RESPOND => --Forward discovery packet (slave only)
if(counter(8 downto 1) = 0) then
app_network_reg_we <= "0";
app_network_reg_clk <= '0';
app_network_reg_addr <= counter(6 downto 2) & not counter(2);
app_data_out_enable <= '1';
app_data_out_strobe <= '1';
app_data_out <= CMD_REG_DSC & "0000";
elsif(counter(7 downto 1) = (node_address) & "01") then
app_data_out_strobe <= '0';
elsif(counter(7 downto 1) = (node_address) & "10") then
app_data_out_strobe <= '1';
app_data_out <= app_reg_enable;
elsif(counter(7 downto 1) = (node_address) & "11") then
app_data_out_strobe <= '0';
elsif(counter(7 downto 1) = (node_address + 1) & "00") then
app_data_out_strobe <= '1';
app_data_out <= app_reg_enable;
elsif(counter(7 downto 1) = (node_address + 1) & "01") then
app_network_reg_we <= "0";
app_network_reg_clk <= '0';
app_data_out_strobe <= '0';
app_data_out_enable <= '0';
bytes_received <= "000000"; --Reset bytes_received, as the combinatorial part doesn't work otherwise
cmd_received <= '0';
elsif(counter(1) = '1') then
app_data_out_strobe <= '0';
app_network_reg_clk <= '1';
else
app_data_out_strobe <= '1';
app_data_out <= app_network_reg_data_in;
app_network_reg_clk <= '0';
app_network_reg_addr <= counter(6 downto 2) & not counter(2);
end if;
when SET_SEND => --Transmit set packet (master only)
if(counter(8 downto 1) = 0) then
app_network_reg_we <= "0";
app_network_reg_clk <= '0';
app_network_reg_addr <= counter(6 downto 2) & not counter(2);
app_data_out_enable <= '1';
app_data_out_strobe <= '1';
app_data_out <= CMD_REG_SET & "0000";
elsif(counter(7 downto 1) = node_count & "01") then
app_network_reg_we <= "0";
app_network_reg_clk <= '0';
app_data_out_strobe <= '0';
app_data_out_enable <= '0';
bytes_received <= "000000"; --Reset node_count and nodes_received, as the combinatorial part doesn't work otherwise
cmd_received <= '0';
elsif(counter(1) = '1') then
app_data_out_strobe <= '0';
app_network_reg_clk <= '1';
else
app_data_out_strobe <= '1';
app_data_out <= app_network_reg_data_in;
app_network_reg_clk <= '0';
app_network_reg_addr <= counter(6 downto 2) & not counter(2);
end if;
 
when SET_RECEIVE => --Receive set packet
if(app_data_in_strobe = '1' and last_data_in_strobe = '0') then
if(bytes_received = 0 and app_data_in(7 downto 4) = CMD_REG_SET and cmd_received = '0') then
bytes_received <= "000000";
cmd_received <= '1';
else
app_network_reg_addr <= bytes_received(4 downto 0) & not bytes_received(0);
app_network_reg_data_out <= app_data_in;
app_network_reg_we <= "1";
app_network_reg_clk <= '0';
bytes_received <= bytes_received + 1;
end if;
elsif(app_data_in_strobe = '0' and last_data_in_strobe = '1' and app_network_reg_we = "1") then
app_network_reg_clk <= '1';
else
app_network_reg_clk <= '0';
end if;
 
when SET_RESPOND => --Forward set packet (slave only)
if(counter(8 downto 1) = 0) then
app_network_reg_we <= "0";
app_network_reg_clk <= '0';
app_network_reg_addr <= counter(6 downto 2) & not counter(2);
app_data_out_enable <= '1';
app_data_out_strobe <= '1';
app_data_out <= CMD_REG_SET & "0000";
elsif(counter(7 downto 1) = node_count & "01") then
app_network_reg_we <= "0";
app_network_reg_clk <= '0';
app_data_out_strobe <= '0';
app_data_out_enable <= '0';
elsif(counter(1) = '1') then
app_data_out_strobe <= '0';
app_network_reg_clk <= '1';
else
app_data_out_strobe <= '1';
app_data_out <= app_network_reg_data_in;
app_network_reg_clk <= '0';
app_network_reg_addr <= counter(6 downto 2) & not counter(2);
end if;
 
when DONE => --Done!
app_network_reg_clk <= '0';
app_network_reg_addr <= "000000";
app_network_reg_data_out <= "00000000";
app_network_reg_we <= "0";
app_dsc_done <= '1';
app_data_out_enable <= '0';
app_data_out_strobe <= '0';
app_data_out <= "00000000";
app_force_packet_error <= 'Z';
end case;
last_data_in_strobe <= app_data_in_strobe;
end if;
end process;
 
process(state, app_enable, counter, node_count, node_address, bytes_received, app_is_master, app_data_in_strobe, app_node_count)
begin
case state is
 
when OFF =>
if(app_enable = '1') then
next_state <= IDLE;
else
next_state <= OFF;
end if;
 
when IDLE =>
if(app_is_master = '1') then
next_state <= DSC_SEND;
else
next_state <= DSC_RECEIVE;
end if;
 
when DSC_SEND =>
if(counter(8 downto 1) = 5) then
next_state <= DSC_RECEIVE;
else
next_state <= DSC_SEND;
end if;
 
when DSC_RECEIVE =>
next_state <= DSC_RECEIVE;
if(app_is_master = '0') then
if((bytes_received(5 downto 1) = node_address) and app_data_in_strobe = '0') then
next_state <= DSC_RESPOND;
end if;
else
if((bytes_received(5 downto 1) = node_count) and app_data_in_strobe = '0') then
next_state <= SET_SEND;
end if;
end if;
 
when DSC_RESPOND =>
if(counter(7 downto 1) = (node_address + 1) & "01") then
next_state <= SET_RECEIVE;
else
next_state <= DSC_RESPOND;
end if;
 
when SET_SEND =>
if(counter(7 downto 1) = node_count & "01") then
next_state <= SET_RECEIVE;
else
next_state <= SET_SEND;
end if;
 
when SET_RECEIVE =>
next_state <= SET_RECEIVE;
if((bytes_received(5 downto 1) = node_count) and (app_data_in_strobe = '0')) then
if(app_is_master = '0') then
next_state <= SET_RESPOND;
else
next_state <= DONE;
end if;
end if;
 
when SET_RESPOND =>
if(counter(7 downto 1) = node_count & "01") then
next_state <= DONE;
else
next_state <= SET_RESPOND;
end if;
 
when DONE =>
next_state <= DONE;
 
end case;
end process;
 
end Behavioral;
/trunk/gateware/TosNet_rev3_2/dec_8b10b.vhd
0,0 → 1,270
----------------------------------------------------------------------------------
-- Company: University of Southern Denmark
-- Engineer: Simon Falsig
--
-- Create Date: 11/5/2010
-- Design Name 8b/10b decoder
-- Module Name: dec_8b10b - Behavioral
-- File Name: dec_8b10b.vhd
-- Project Name: TosNet
-- Target Devices: Spartan3/6
-- Tool versions: Xilinx ISE 12.2
-- Description: An 8b/10b decoder. Like the encoder module, only the
-- functionality that is actually used in the TosNet physical
-- layer is implemented. That means that there is no support for
-- disparity checking, and the code error detection will not
-- detect all code errors (in particular in the case of the
-- primary/alternate encoding of HGF symbol "111"). The datalink
-- layer does CRC checking though, so any errors are very likely
-- to be picked up there instead.
--
-- Revision:
-- Revision 3.2 - Initial release
--
-- Copyright 2010
--
-- This module 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 3 of the License, or
-- (at your option) any later version.
--
-- This module 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 module. If not, see <http://www.gnu.org/licenses/>.
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
 
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
 
entity dec_8b10b is
port ( clk : in STD_LOGIC;
ce : in STD_LOGIC;
din : in STD_LOGIC_VECTOR(9 downto 0);
dout : out STD_LOGIC_VECTOR(7 downto 0);
kout : out STD_LOGIC;
code_err : out STD_LOGIC);
end dec_8b10b;
 
architecture Behavioral of dec_8b10b is
 
signal EDCBA : STD_LOGIC_VECTOR(4 downto 0) := (others => '0');
signal HGF : STD_LOGIC_VECTOR(2 downto 0) := (others => '0');
signal iedcba : STD_LOGIC_VECTOR(5 downto 0) := (others => '0');
signal jhgf : STD_LOGIC_VECTOR(3 downto 0) := (others => '0');
signal jhgfiedcba : STD_LOGIC_VECTOR(9 downto 0) := (others => '0');
signal code_err_s1 : STD_LOGIC;
signal code_err_s2 : STD_LOGIC;
 
begin
 
process(jhgfiedcba, EDCBA, HGF, code_err_s1, code_err_s2)
begin
case jhgfiedcba is
when "1001111100" =>
dout <= "00111100";
kout <= '1';
code_err <= '0';
when "0110000011" =>
dout <= "00111100";
kout <= '1';
code_err <= '0';
when "0101111100" =>
dout <= "10111100";
kout <= '1';
code_err <= '0';
when "1010000011" =>
dout <= "10111100";
kout <= '1';
code_err <= '0';
when others =>
dout <= HGF & EDCBA;
kout <= '0';
code_err <= code_err_s1 or code_err_s2;
end case;
end process;
 
jhgfiedcba <= jhgf & iedcba;
 
process(clk)
begin
if(clk = '1' and clk'event) then
if(ce = '1') then
iedcba <= din(5 downto 0);
jhgf <= din(9 downto 6);
end if;
end if;
end process;
 
process(iedcba)
begin
code_err_s1 <= '0';
case iedcba is
-- when "000000" =>
-- when "000001" =>
-- when "000010" =>
-- when "000011" =>
-- when "000100" =>
when "000101" =>
EDCBA <= "01111";
when "000110" =>
EDCBA <= "00000";
when "000111" =>
EDCBA <= "00111";
-- when "001000" =>
when "001001" =>
EDCBA <= "10000";
when "001010" =>
EDCBA <= "11111";
when "001011" =>
EDCBA <= "01011";
when "001100" =>
EDCBA <= "11000";
when "001101" =>
EDCBA <= "01101";
when "001110" =>
EDCBA <= "01110";
-- when "001111" =>
-- when "010000" =>
when "010001" =>
EDCBA <= "00001";
when "010010" =>
EDCBA <= "00010";
when "010011" =>
EDCBA <= "10011";
when "010100" =>
EDCBA <= "00100";
when "010101" =>
EDCBA <= "10101";
when "010110" =>
EDCBA <= "10110";
when "010111" =>
EDCBA <= "10111";
when "011000" =>
EDCBA <= "01000";
when "011001" =>
EDCBA <= "11001";
when "011010" =>
EDCBA <= "11010";
when "011011" =>
EDCBA <= "11011";
when "011100" =>
EDCBA <= "11100";
when "011101" =>
EDCBA <= "11101";
when "011110" =>
EDCBA <= "11110";
-- when "011111" =>
-- when "100000" =>
when "100001" =>
EDCBA <= "11110";
when "100010" =>
EDCBA <= "11101";
when "100011" =>
EDCBA <= "00011";
when "100100" =>
EDCBA <= "11011";
when "100101" =>
EDCBA <= "00101";
when "100110" =>
EDCBA <= "00110";
when "100111" =>
EDCBA <= "01000";
when "101000" =>
EDCBA <= "10111";
when "101001" =>
EDCBA <= "01001";
when "101010" =>
EDCBA <= "01010";
when "101011" =>
EDCBA <= "00100";
when "101100" =>
EDCBA <= "01100";
when "101101" =>
EDCBA <= "00010";
when "101110" =>
EDCBA <= "00001";
-- when "101111" =>
-- when "110000" =>
when "110001" =>
EDCBA <= "10001";
when "110010" =>
EDCBA <= "10010";
when "110011" =>
EDCBA <= "11000";
when "110100" =>
EDCBA <= "10100";
when "110101" =>
EDCBA <= "11111";
when "110110" =>
EDCBA <= "10000";
-- when "110111" =>
when "111000" =>
EDCBA <= "00111";
when "111001" =>
EDCBA <= "00000";
when "111010" =>
EDCBA <= "01111";
-- when "111011" =>
-- when "111100" =>
-- when "111101" =>
-- when "111110" =>
-- when "111111" =>
when others =>
code_err_s1 <= '1';
EDCBA <= "00000";
end case;
end process;
 
process(jhgf)
begin
code_err_s2 <= '0';
case jhgf is
-- when "0000" =>
when "0001" =>
HGF <= "111";
when "0010" =>
HGF <= "000";
when "0011" =>
HGF <= "011";
when "0100" =>
HGF <= "100";
when "0101" =>
HGF <= "101";
when "0110" =>
HGF <= "110";
when "0111" =>
HGF <= "111";
when "1000" =>
HGF <= "111";
when "1001" =>
HGF <= "001";
when "1010" =>
HGF <= "010";
when "1011" =>
HGF <= "100";
when "1100" =>
HGF <= "011";
when "1101" =>
HGF <= "000";
when "1110" =>
HGF <= "111";
-- when "1111" =>
when others =>
code_err_s2 <= '1';
HGF <= "000";
end case;
end process;
end Behavioral;
 
/trunk/gateware/TosNet_rev3_2/tdl_app_net.vhd
0,0 → 1,377
----------------------------------------------------------------------------------
-- Company: University of Southern Denmark
-- Engineer: Simon Falsig
--
-- Create Date: 10/3/2010
-- Design Name TosNet
-- Module Name: app_net - Behavioral
-- File Name: app_net.vhd
-- Project Name: TosNet
-- Target Devices: Spartan3/6
-- Tool versions: Xilinx ISE 12.2
-- Description: The network discorvery module runs during startup, and
-- performs network discovery. It is initiated by the master
-- node, and polls all attached nodes for their node_ids which
-- are stored together with the addresses of the nodes (that is,
-- their position in the ring, relative to the master) in the
-- network registers on all nodes.
--
-- Revision:
-- Revision 3.2 - Initial release
--
-- Copyright 2010
--
-- This module 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 3 of the License, or
-- (at your option) any later version.
--
-- This module 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 module. If not, see <http://www.gnu.org/licenses/>.
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use work.commandpack.all;
 
 
entity tdl_app_net is
Port ( app_enable : in STD_LOGIC;
app_data_in : in STD_LOGIC_VECTOR(7 downto 0);
app_data_in_strobe : in STD_LOGIC;
app_data_out : out STD_LOGIC_VECTOR(7 downto 0);
app_data_out_strobe : out STD_LOGIC;
app_data_out_enable : out STD_LOGIC;
app_buffer_full : in STD_LOGIC;
app_packet_error : in STD_LOGIC;
app_force_packet_error : out STD_LOGIC;
app_cmd_valid : in STD_LOGIC;
app_sync_strobe : in STD_LOGIC;
app_is_master : in STD_LOGIC;
app_dsc_done : out STD_LOGIC;
app_network_reg_clk : out STD_LOGIC;
app_network_reg_addr : out STD_LOGIC_VECTOR(5 downto 0);
app_network_reg_data_in : in STD_LOGIC_VECTOR(7 downto 0);
app_network_reg_data_out : out STD_LOGIC_VECTOR(7 downto 0);
app_network_reg_we : inout STD_LOGIC_VECTOR(0 downto 0);
app_node_count : out STD_LOGIC_VECTOR(3 downto 0);
app_node_address : out STD_LOGIC_VECTOR(3 downto 0);
app_node_id : in STD_LOGIC_VECTOR(3 downto 0);
app_clk : in STD_LOGIC;
app_reset : in STD_LOGIC);
end tdl_app_net;
 
architecture Behavioral of tdl_app_net is
 
type STATES is (OFF, IDLE, CLEAR_NETWORKREG, DSC_SEND, DSC_RECEIVE, DSC_RESPOND, SET_SEND, SET_RECEIVE, SET_RESPOND, DONE);
signal state : STATES := OFF;
signal next_state : STATES := OFF;
signal last_data_in_strobe : STD_LOGIC;
signal node_count : STD_LOGIC_VECTOR(3 downto 0) := "0000";
signal node_address : STD_LOGIC_VECTOR(3 downto 0) := "0000";
signal nodes_received : STD_LOGIC_VECTOR(4 downto 0) := "00000";
signal cmd_received : STD_LOGIC := '0';
signal counter : STD_LOGIC_VECTOR(8 downto 0) := "000000000";
 
begin
 
process(app_clk)
begin
if(app_clk = '1' and app_clk'EVENT) then
if(app_reset = '1') then
state <= OFF;
else
state <= next_state;
end if;
 
if(app_buffer_full = '1') then
counter <= counter;
elsif(state = next_state) then
counter <= counter + 1;
else
counter <= "000000000";
end if;
 
case state is
 
when OFF =>
app_data_out_enable <= '0';
app_data_out_strobe <= '0';
app_data_out <= "00000000";
app_force_packet_error <= 'Z';
app_dsc_done <= '0';
app_network_reg_clk <= '0';
app_network_reg_addr <= "000000";
app_network_reg_data_out <= "00000000";
app_network_reg_we <= "0";
last_data_in_strobe <= '0';
node_count <= "0000";
nodes_received <= "00000";
cmd_received <= '0';
node_address <= "0000";
 
when IDLE =>
app_data_out_enable <= '0';
app_data_out_strobe <= '0';
app_dsc_done <= '0';
app_network_reg_clk <= '0';
app_network_reg_we <= "0";
when CLEAR_NETWORKREG =>
app_network_reg_we <= "1";
if(counter(0) = '0') then
app_network_reg_clk <= '0';
app_network_reg_addr <= counter(6 downto 1);
app_network_reg_data_out <= "00000000";
else
app_network_reg_clk <= '1';
end if;
when DSC_SEND => --Send discovery packet (master only)
if(counter(8 downto 1) = 0) then
app_data_out_enable <= '1';
app_data_out <= CMD_NET_DSC & "0001";
app_data_out_strobe <= '1';
elsif(counter(8 downto 1) = 1) then
app_data_out_strobe <= '0';
elsif(counter(8 downto 1) = 2) then
app_data_out <= "0000" & app_node_id;
app_data_out_strobe <= '1';
else
app_data_out_enable <= '0';
app_data_out_strobe <= '0';
end if;
 
when DSC_RECEIVE => --Receive discovery packet
if(app_data_in_strobe = '1' and last_data_in_strobe = '0') then
if(node_count = 0 and app_data_in(7 downto 4) = CMD_NET_DSC and cmd_received = '0') then
node_count <= app_data_in(3 downto 0);
node_address <= app_data_in(3 downto 0);
nodes_received <= "00000";
cmd_received <= '1';
else
app_network_reg_addr <= nodes_received(3 downto 0) & "00";
app_network_reg_data_out <= app_data_in;
app_network_reg_we <= "1";
app_network_reg_clk <= '0';
nodes_received <= nodes_received + 1;
end if;
elsif(app_data_in_strobe = '0' and last_data_in_strobe = '1' and app_network_reg_we = "1") then
app_network_reg_clk <= '1';
else
app_network_reg_clk <= '0';
end if;
 
when DSC_RESPOND => --Forward discovery packet (slave only)
app_network_reg_we <= "0";
 
if(counter(8 downto 1) = 0) then
app_network_reg_clk <= '0';
app_network_reg_addr <= counter(5 downto 2) & "00";
app_data_out_enable <= '1';
app_data_out_strobe <= '1';
app_data_out <= CMD_NET_DSC & (node_count + 1);
elsif(counter(5 downto 1) = node_count & '1') then
app_data_out_strobe <= '0';
elsif(counter(5 downto 1) = (node_count + 1) & '0') then
app_data_out_strobe <= '1';
app_data_out <= node_count & app_node_id;
elsif(counter(5 downto 1) = (node_count + 1) & '1') then
app_data_out_strobe <= '0';
app_data_out_enable <= '0';
node_count <= "0000"; --Reset node_count and nodes_received, as the combinatorial part doesn't work otherwise
nodes_received <= "00000";
cmd_received <= '0';
elsif(counter(1) = '1') then
app_data_out_strobe <= '0';
app_network_reg_clk <= '1';
else
app_data_out_strobe <= '1';
app_data_out <= app_network_reg_data_in;
app_network_reg_clk <= '0';
app_network_reg_addr <= counter(5 downto 2) & "00";
end if;
when SET_SEND => --Transmit set packet (master only)
app_network_reg_we <= "0";
if(counter(8 downto 1) = 0) then
app_network_reg_clk <= '0';
app_network_reg_addr <= counter(5 downto 2) & "00";
app_data_out_enable <= '1';
app_data_out_strobe <= '1';
app_data_out <= CMD_NET_SET & node_count;
elsif(counter(5 downto 1) = node_count & '1') then
app_network_reg_clk <= '0';
app_data_out_strobe <= '0';
app_data_out_enable <= '0';
node_count <= "0000"; --Reset node_count and nodes_received, as the combinatorial part doesn't work otherwise
nodes_received <= "00000";
cmd_received <= '0';
elsif(counter(1) = '1') then
app_data_out_strobe <= '0';
app_network_reg_clk <= '1';
else
app_data_out_strobe <= '1';
app_data_out <= app_network_reg_data_in;
app_network_reg_clk <= '0';
app_network_reg_addr <= counter(5 downto 2) & "00";
end if;
 
when SET_RECEIVE => --Receive set packet
if(app_data_in_strobe = '1' and last_data_in_strobe = '0') then
if(node_count = 0 and app_data_in(7 downto 4) = CMD_NET_SET and cmd_received = '0') then
node_count <= app_data_in(3 downto 0);
nodes_received <= "00000";
cmd_received <= '1';
else
app_network_reg_addr <= nodes_received(3 downto 0) & "00";
app_network_reg_data_out <= app_data_in;
app_network_reg_we <= "1";
app_network_reg_clk <= '0';
nodes_received <= nodes_received + 1;
end if;
elsif(app_data_in_strobe = '0' and last_data_in_strobe = '1' and app_network_reg_we = "1") then
app_network_reg_clk <= '1';
else
app_network_reg_clk <= '0';
end if;
 
when SET_RESPOND => --Forward set packet (slave only)
app_network_reg_we <= "0";
if(counter(8 downto 1) = 0) then
app_network_reg_clk <= '0';
app_network_reg_addr <= counter(5 downto 2) & "00";
app_data_out_enable <= '1';
app_data_out_strobe <= '1';
app_data_out <= CMD_NET_SET & node_count;
elsif(counter(5 downto 1) = node_count & '1') then
app_network_reg_clk <= '0';
app_data_out_strobe <= '0';
app_data_out_enable <= '0';
elsif(counter(1) = '1') then
app_data_out_strobe <= '0';
app_network_reg_clk <= '1';
else
app_data_out_strobe <= '1';
app_data_out <= app_network_reg_data_in;
app_network_reg_clk <= '0';
app_network_reg_addr <= counter(5 downto 2) & "00";
end if;
when DONE => --Done!
app_network_reg_we <= "0";
if(app_is_master = '1') then
app_node_address <= "0000";
else
app_node_address <= node_address;
end if;
app_node_count <= node_count;
app_network_reg_clk <= '0';
app_network_reg_addr <= "000000";
app_network_reg_data_out <= "00000000";
app_dsc_done <= '1';
app_data_out_enable <= '0';
app_data_out_strobe <= '0';
app_data_out <= "00000000";
app_force_packet_error <= 'Z';
end case;
last_data_in_strobe <= app_data_in_strobe;
end if;
end process;
 
process(state, app_enable, app_data_in_strobe, counter, node_count, nodes_received, app_is_master)
begin
case state is
 
when OFF =>
if(app_enable = '1') then
next_state <= IDLE;
else
next_state <= OFF;
end if;
 
when IDLE =>
next_state <= CLEAR_NETWORKREG;
when CLEAR_NETWORKREG =>
if(counter = 128) then
if(app_is_master = '1') then
next_state <= DSC_SEND;
else
next_state <= DSC_RECEIVE;
end if;
else
next_state <= CLEAR_NETWORKREG;
end if;
when DSC_SEND =>
if(counter(8 downto 1) = 3) then
next_state <= DSC_RECEIVE;
else
next_state <= DSC_SEND;
end if;
 
when DSC_RECEIVE =>
next_state <= DSC_RECEIVE;
if((nodes_received = node_count) and not (node_count = 0) and (app_data_in_strobe = '0')) then
if(app_is_master = '0') then
next_state <= DSC_RESPOND;
else
next_state <= SET_SEND;
end if;
end if;
 
when DSC_RESPOND =>
if(counter(5 downto 1) = (node_count + 1) & '1') then
next_state <= SET_RECEIVE;
else
next_state <= DSC_RESPOND;
end if;
 
when SET_SEND =>
if(counter(5 downto 1) = node_count & '1') then
next_state <= SET_RECEIVE;
else
next_state <= SET_SEND;
end if;
 
when SET_RECEIVE =>
next_state <= SET_RECEIVE;
if((nodes_received = node_count) and not (node_count = 0) and (app_data_in_strobe = '0')) then
if(app_is_master = '0') then
next_state <= SET_RESPOND;
else
next_state <= DONE;
end if;
end if;
 
when SET_RESPOND =>
if(counter(5 downto 1) = node_count & '1') then
next_state <= DONE;
else
next_state <= SET_RESPOND;
end if;
 
when DONE =>
next_state <= DONE;
 
end case;
end process;
 
end Behavioral;
 
/trunk/gateware/TosNet_rev3_2/ip_xc3s400an_fg400/network_register.xco
0,0 → 1,77
##############################################################
#
# Xilinx Core Generator version 11.4
# Date: Wed May 19 13:54:26 2010
#
##############################################################
#
# This file contains the customisation parameters for a
# Xilinx CORE Generator IP GUI. It is strongly recommended
# that you do not manually alter this file as it may cause
# unexpected and unsupported behavior.
#
##############################################################
#
# BEGIN Project Options
SET addpads = False
SET asysymbol = True
SET busformat = BusFormatAngleBracketNotRipped
SET createndf = False
SET designentry = VHDL
SET device = xc3s400an
SET devicefamily = spartan3a
SET flowvendor = Foundation_iSE
SET formalverification = False
SET foundationsym = False
SET implementationfiletype = Ngc
SET package = fgg400
SET removerpms = False
SET simulationfiles = Behavioral
SET speedgrade = -5
SET verilogsim = True
SET vhdlsim = True
# END Project Options
# BEGIN Select
SELECT Block_Memory_Generator family Xilinx,_Inc. 2.6
# END Select
# BEGIN Parameters
CSET algorithm=Minimum_Area
CSET assume_synchronous_clk=false
CSET byte_size=9
CSET coe_file=no_coe_file_loaded
CSET collision_warnings=ALL
CSET component_name=network_register
CSET disable_collision_warnings=false
CSET disable_out_of_range_warnings=false
CSET ecc=false
CSET enable_a=Always_Enabled
CSET enable_b=Always_Enabled
CSET fill_remaining_memory_locations=true
CSET load_init_file=false
CSET memory_type=True_Dual_Port_RAM
CSET operating_mode_a=WRITE_FIRST
CSET operating_mode_b=WRITE_FIRST
CSET output_reset_value_a=0
CSET output_reset_value_b=0
CSET pipeline_stages=0
CSET primitive=8kx2
CSET read_width_a=8
CSET read_width_b=32
CSET register_porta_output_of_memory_core=false
CSET register_porta_output_of_memory_primitives=false
CSET register_portb_output_of_memory_core=false
CSET register_portb_output_of_memory_primitives=false
CSET remaining_memory_locations=0
CSET single_bit_ecc=false
CSET use_byte_write_enable=false
CSET use_ramb16bwer_reset_behavior=false
CSET use_regcea_pin=false
CSET use_regceb_pin=false
CSET use_ssra_pin=false
CSET use_ssrb_pin=false
CSET write_depth_a=64
CSET write_width_a=8
CSET write_width_b=32
# END Parameters
GENERATE
# CRC: 6795887b
/trunk/gateware/TosNet_rev3_2/ip_xc3s400an_fg400/readme_ip_xc3s400an_fg400.txt
0,0 → 1,67
These .xco files are created by CoreGen for the following FPGA device:
 
Xilinx xc3s400an fg400
 
 
To generate ip-cores for other devices, use the following cores and settings:
 
network_register:
- Core: Block Memory Generator
- Memory Type: True Dual Port RAM
- Use Byte Write Enable: No
- Algorithm: Minimum Area
- Port A:
- Write Width: 8
- Write Depth: 64
- Operating Mode: Write First
- Enable: Always Enabled
- Port B:
- Write Width: 32
- Operating Mode: Write First
- Enable: Always Enabled
- Optional Output Registers: No
- Memory Initialization: Fill with 0
- Output Reset Pins: No
 
 
 
data_reg:
- Core: Block Memory Generator
- Memory Type: True Dual Port RAM
- Use Byte Write Enable: No
- Algorithm: Minimum Area
- Port A:
- Write Width: 8
- Write Depth: 8192
- Operating Mode: Write First
- Enable: Always Enabled
- Port B:
- Write Width: 32
- Operating Mode: Write First
- Enable: Always Enabled
- Optional Output Registers: No
- Memory Initialization: Fill with 0
- Output Reset Pins: No
 
 
 
async_fifo:
- Core: Fifo Generator
- FIFO Implementation: Independent Clocks / Block RAM
- Read Mode: First-Word Fall-Through
- Data Port Parameters:
- Write Width: 38
- Write Depth: 128
- Read Width: 38
- Optional Flags: No
- Write Port Handshaking: No
- Read Port Handshaking:
- Valid Flag: Yes / Active High
- Underflow Flag: No
- Initialization:
- Reset Pin: Yes
- Enable Reset Sync.: Yes
- Full Flags Reset Value: 0
- Use Dout Reset: Yes / Value: 0
- Programmable Flags: No
- Data Count Options: All off
/trunk/gateware/TosNet_rev3_2/ip_xc3s400an_fg400/async_fifo.xco
0,0 → 1,84
##############################################################
#
# Xilinx Core Generator version 11.4
# Date: Wed May 19 14:01:48 2010
#
##############################################################
#
# This file contains the customisation parameters for a
# Xilinx CORE Generator IP GUI. It is strongly recommended
# that you do not manually alter this file as it may cause
# unexpected and unsupported behavior.
#
##############################################################
#
# BEGIN Project Options
SET addpads = False
SET asysymbol = True
SET busformat = BusFormatAngleBracketNotRipped
SET createndf = False
SET designentry = VHDL
SET device = xc3s400an
SET devicefamily = spartan3a
SET flowvendor = Foundation_iSE
SET formalverification = False
SET foundationsym = False
SET implementationfiletype = Ngc
SET package = fgg400
SET removerpms = False
SET simulationfiles = Behavioral
SET speedgrade = -5
SET verilogsim = True
SET vhdlsim = True
# END Project Options
# BEGIN Select
SELECT Fifo_Generator family Xilinx,_Inc. 5.3
# END Select
# BEGIN Parameters
CSET almost_empty_flag=false
CSET almost_full_flag=false
CSET component_name=async_fifo
CSET data_count=false
CSET data_count_width=7
CSET disable_timing_violations=false
CSET dout_reset_value=0
CSET empty_threshold_assert_value=4
CSET empty_threshold_negate_value=5
CSET enable_ecc=false
CSET enable_int_clk=false
CSET enable_reset_synchronization=true
CSET fifo_implementation=Independent_Clocks_Block_RAM
CSET full_flags_reset_value=0
CSET full_threshold_assert_value=127
CSET full_threshold_negate_value=126
CSET inject_dbit_error=false
CSET inject_sbit_error=false
CSET input_data_width=38
CSET input_depth=128
CSET output_data_width=38
CSET output_depth=128
CSET overflow_flag=false
CSET overflow_sense=Active_High
CSET performance_options=First_Word_Fall_Through
CSET programmable_empty_type=No_Programmable_Empty_Threshold
CSET programmable_full_type=No_Programmable_Full_Threshold
CSET read_clock_frequency=1
CSET read_data_count=false
CSET read_data_count_width=7
CSET reset_pin=true
CSET reset_type=Asynchronous_Reset
CSET underflow_flag=false
CSET underflow_sense=Active_High
CSET use_dout_reset=true
CSET use_embedded_registers=false
CSET use_extra_logic=false
CSET valid_flag=true
CSET valid_sense=Active_High
CSET write_acknowledge_flag=false
CSET write_acknowledge_sense=Active_High
CSET write_clock_frequency=1
CSET write_data_count=false
CSET write_data_count_width=7
# END Parameters
GENERATE
# CRC: f9925ea8
/trunk/gateware/TosNet_rev3_2/ip_xc3s400an_fg400/data_reg.xco
0,0 → 1,77
##############################################################
#
# Xilinx Core Generator version 11.4
# Date: Wed May 19 14:00:27 2010
#
##############################################################
#
# This file contains the customisation parameters for a
# Xilinx CORE Generator IP GUI. It is strongly recommended
# that you do not manually alter this file as it may cause
# unexpected and unsupported behavior.
#
##############################################################
#
# BEGIN Project Options
SET addpads = False
SET asysymbol = True
SET busformat = BusFormatAngleBracketNotRipped
SET createndf = False
SET designentry = VHDL
SET device = xc3s400an
SET devicefamily = spartan3a
SET flowvendor = Foundation_iSE
SET formalverification = False
SET foundationsym = False
SET implementationfiletype = Ngc
SET package = fgg400
SET removerpms = False
SET simulationfiles = Behavioral
SET speedgrade = -5
SET verilogsim = True
SET vhdlsim = True
# END Project Options
# BEGIN Select
SELECT Block_Memory_Generator family Xilinx,_Inc. 2.6
# END Select
# BEGIN Parameters
CSET algorithm=Minimum_Area
CSET assume_synchronous_clk=false
CSET byte_size=9
CSET coe_file=no_coe_file_loaded
CSET collision_warnings=ALL
CSET component_name=data_reg
CSET disable_collision_warnings=false
CSET disable_out_of_range_warnings=false
CSET ecc=false
CSET enable_a=Always_Enabled
CSET enable_b=Always_Enabled
CSET fill_remaining_memory_locations=true
CSET load_init_file=false
CSET memory_type=True_Dual_Port_RAM
CSET operating_mode_a=WRITE_FIRST
CSET operating_mode_b=WRITE_FIRST
CSET output_reset_value_a=0
CSET output_reset_value_b=0
CSET pipeline_stages=0
CSET primitive=8kx2
CSET read_width_a=8
CSET read_width_b=32
CSET register_porta_output_of_memory_core=false
CSET register_porta_output_of_memory_primitives=false
CSET register_portb_output_of_memory_core=false
CSET register_portb_output_of_memory_primitives=false
CSET remaining_memory_locations=00
CSET single_bit_ecc=false
CSET use_byte_write_enable=false
CSET use_ramb16bwer_reset_behavior=false
CSET use_regcea_pin=false
CSET use_regceb_pin=false
CSET use_ssra_pin=false
CSET use_ssrb_pin=false
CSET write_depth_a=8192
CSET write_width_a=8
CSET write_width_b=32
# END Parameters
GENERATE
# CRC: c3be9dd1
/trunk/gateware/TosNet_rev3_2/ip_xc6slx16_csg324/network_register.xco
0,0 → 1,89
##############################################################
#
# Xilinx Core Generator version 11.4
# Date: Wed May 19 14:03:49 2010
#
##############################################################
#
# This file contains the customisation parameters for a
# Xilinx CORE Generator IP GUI. It is strongly recommended
# that you do not manually alter this file as it may cause
# unexpected and unsupported behavior.
#
##############################################################
#
# BEGIN Project Options
SET addpads = False
SET asysymbol = True
SET busformat = BusFormatAngleBracketNotRipped
SET createndf = False
SET designentry = VHDL
SET device = xc6slx16
SET devicefamily = spartan6
SET flowvendor = Foundation_ISE
SET formalverification = False
SET foundationsym = False
SET implementationfiletype = Ngc
SET package = csg324
SET removerpms = False
SET simulationfiles = Behavioral
SET speedgrade = -3
SET verilogsim = True
SET vhdlsim = True
# END Project Options
# BEGIN Select
SELECT Block_Memory_Generator family Xilinx,_Inc. 3.3
# END Select
# BEGIN Parameters
CSET additional_inputs_for_power_estimation=false
CSET algorithm=Minimum_Area
CSET assume_synchronous_clk=false
CSET byte_size=9
CSET coe_file=no_coe_file_loaded
CSET collision_warnings=ALL
CSET component_name=network_register
CSET disable_collision_warnings=false
CSET disable_out_of_range_warnings=false
CSET ecc=false
CSET enable_a=Always_Enabled
CSET enable_b=Always_Enabled
CSET error_injection_type=Single_Bit_Error_Injection
CSET fill_remaining_memory_locations=true
CSET load_init_file=false
CSET memory_type=True_Dual_Port_RAM
CSET operating_mode_a=WRITE_FIRST
CSET operating_mode_b=WRITE_FIRST
CSET output_reset_value_a=0
CSET output_reset_value_b=0
CSET pipeline_stages=0
CSET port_a_clock=100
CSET port_a_enable_rate=100
CSET port_a_write_rate=50
CSET port_b_clock=100
CSET port_b_enable_rate=100
CSET port_b_write_rate=50
CSET primitive=8kx2
CSET read_width_a=8
CSET read_width_b=32
CSET register_porta_output_of_memory_core=false
CSET register_porta_output_of_memory_primitives=false
CSET register_portb_output_of_memory_core=false
CSET register_portb_output_of_memory_primitives=false
CSET remaining_memory_locations=0
CSET reset_memory_latch_a=false
CSET reset_memory_latch_b=false
CSET reset_priority_a=CE
CSET reset_priority_b=CE
CSET reset_type=SYNC
CSET use_byte_write_enable=false
CSET use_error_injection_pins=false
CSET use_regcea_pin=false
CSET use_regceb_pin=false
CSET use_rsta_pin=false
CSET use_rstb_pin=false
CSET write_depth_a=64
CSET write_width_a=8
CSET write_width_b=32
# END Parameters
GENERATE
# CRC: 35903757
/trunk/gateware/TosNet_rev3_2/ip_xc6slx16_csg324/readme_ip_xc6slx16_csg324.txt
0,0 → 1,67
These .xco files are created by CoreGen for the following FPGA device:
 
Xilinx xc6slx16 CSG324
 
 
To generate ip-cores for other devices, use the following cores and settings:
 
network_register:
- Core: Block Memory Generator
- Memory Type: True Dual Port RAM
- Use Byte Write Enable: No
- Algorithm: Minimum Area
- Port A:
- Write Width: 8
- Write Depth: 64
- Operating Mode: Write First
- Enable: Always Enabled
- Port B:
- Write Width: 32
- Operating Mode: Write First
- Enable: Always Enabled
- Optional Output Registers: No
- Memory Initialization: Fill with 0
- Output Reset Pins: No
 
 
 
data_reg:
- Core: Block Memory Generator
- Memory Type: True Dual Port RAM
- Use Byte Write Enable: No
- Algorithm: Minimum Area
- Port A:
- Write Width: 8
- Write Depth: 8192
- Operating Mode: Write First
- Enable: Always Enabled
- Port B:
- Write Width: 32
- Operating Mode: Write First
- Enable: Always Enabled
- Optional Output Registers: No
- Memory Initialization: Fill with 0
- Output Reset Pins: No
 
 
 
async_fifo:
- Core: Fifo Generator
- FIFO Implementation: Independent Clocks / Block RAM
- Read Mode: First-Word Fall-Through
- Data Port Parameters:
- Write Width: 38
- Write Depth: 128
- Read Width: 38
- Optional Flags: No
- Write Port Handshaking: No
- Read Port Handshaking:
- Valid Flag: Yes / Active High
- Underflow Flag: No
- Initialization:
- Reset Pin: Yes
- Enable Reset Sync.: Yes
- Full Flags Reset Value: 0
- Use Dout Reset: Yes / Value: 0
- Programmable Flags: No
- Data Count Options: All off
/trunk/gateware/TosNet_rev3_2/ip_xc6slx16_csg324/async_fifo.xco
0,0 → 1,84
##############################################################
#
# Xilinx Core Generator version 11.4
# Date: Wed May 19 14:07:35 2010
#
##############################################################
#
# This file contains the customisation parameters for a
# Xilinx CORE Generator IP GUI. It is strongly recommended
# that you do not manually alter this file as it may cause
# unexpected and unsupported behavior.
#
##############################################################
#
# BEGIN Project Options
SET addpads = False
SET asysymbol = True
SET busformat = BusFormatAngleBracketNotRipped
SET createndf = False
SET designentry = VHDL
SET device = xc6slx16
SET devicefamily = spartan6
SET flowvendor = Foundation_ISE
SET formalverification = False
SET foundationsym = False
SET implementationfiletype = Ngc
SET package = csg324
SET removerpms = False
SET simulationfiles = Behavioral
SET speedgrade = -3
SET verilogsim = True
SET vhdlsim = True
# END Project Options
# BEGIN Select
SELECT Fifo_Generator family Xilinx,_Inc. 5.3
# END Select
# BEGIN Parameters
CSET almost_empty_flag=false
CSET almost_full_flag=false
CSET component_name=async_fifo
CSET data_count=false
CSET data_count_width=7
CSET disable_timing_violations=false
CSET dout_reset_value=0
CSET empty_threshold_assert_value=4
CSET empty_threshold_negate_value=5
CSET enable_ecc=false
CSET enable_int_clk=false
CSET enable_reset_synchronization=true
CSET fifo_implementation=Independent_Clocks_Block_RAM
CSET full_flags_reset_value=0
CSET full_threshold_assert_value=127
CSET full_threshold_negate_value=126
CSET inject_dbit_error=false
CSET inject_sbit_error=false
CSET input_data_width=38
CSET input_depth=128
CSET output_data_width=38
CSET output_depth=128
CSET overflow_flag=false
CSET overflow_sense=Active_High
CSET performance_options=First_Word_Fall_Through
CSET programmable_empty_type=No_Programmable_Empty_Threshold
CSET programmable_full_type=No_Programmable_Full_Threshold
CSET read_clock_frequency=1
CSET read_data_count=false
CSET read_data_count_width=7
CSET reset_pin=true
CSET reset_type=Asynchronous_Reset
CSET underflow_flag=false
CSET underflow_sense=Active_High
CSET use_dout_reset=true
CSET use_embedded_registers=false
CSET use_extra_logic=false
CSET valid_flag=true
CSET valid_sense=Active_High
CSET write_acknowledge_flag=false
CSET write_acknowledge_sense=Active_High
CSET write_clock_frequency=1
CSET write_data_count=false
CSET write_data_count_width=7
# END Parameters
GENERATE
# CRC: c6e669d0
/trunk/gateware/TosNet_rev3_2/ip_xc6slx16_csg324/data_reg.xco
0,0 → 1,89
##############################################################
#
# Xilinx Core Generator version 11.4
# Date: Wed May 19 14:06:45 2010
#
##############################################################
#
# This file contains the customisation parameters for a
# Xilinx CORE Generator IP GUI. It is strongly recommended
# that you do not manually alter this file as it may cause
# unexpected and unsupported behavior.
#
##############################################################
#
# BEGIN Project Options
SET addpads = False
SET asysymbol = True
SET busformat = BusFormatAngleBracketNotRipped
SET createndf = False
SET designentry = VHDL
SET device = xc6slx16
SET devicefamily = spartan6
SET flowvendor = Foundation_ISE
SET formalverification = False
SET foundationsym = False
SET implementationfiletype = Ngc
SET package = csg324
SET removerpms = False
SET simulationfiles = Behavioral
SET speedgrade = -3
SET verilogsim = True
SET vhdlsim = True
# END Project Options
# BEGIN Select
SELECT Block_Memory_Generator family Xilinx,_Inc. 3.3
# END Select
# BEGIN Parameters
CSET additional_inputs_for_power_estimation=false
CSET algorithm=Minimum_Area
CSET assume_synchronous_clk=false
CSET byte_size=9
CSET coe_file=no_coe_file_loaded
CSET collision_warnings=ALL
CSET component_name=data_reg
CSET disable_collision_warnings=false
CSET disable_out_of_range_warnings=false
CSET ecc=false
CSET enable_a=Always_Enabled
CSET enable_b=Always_Enabled
CSET error_injection_type=Single_Bit_Error_Injection
CSET fill_remaining_memory_locations=true
CSET load_init_file=false
CSET memory_type=True_Dual_Port_RAM
CSET operating_mode_a=WRITE_FIRST
CSET operating_mode_b=WRITE_FIRST
CSET output_reset_value_a=0
CSET output_reset_value_b=0
CSET pipeline_stages=0
CSET port_a_clock=100
CSET port_a_enable_rate=100
CSET port_a_write_rate=50
CSET port_b_clock=100
CSET port_b_enable_rate=100
CSET port_b_write_rate=50
CSET primitive=8kx2
CSET read_width_a=8
CSET read_width_b=32
CSET register_porta_output_of_memory_core=false
CSET register_porta_output_of_memory_primitives=false
CSET register_portb_output_of_memory_core=false
CSET register_portb_output_of_memory_primitives=false
CSET remaining_memory_locations=0
CSET reset_memory_latch_a=false
CSET reset_memory_latch_b=false
CSET reset_priority_a=CE
CSET reset_priority_b=CE
CSET reset_type=SYNC
CSET use_byte_write_enable=false
CSET use_error_injection_pins=false
CSET use_regcea_pin=false
CSET use_regceb_pin=false
CSET use_rsta_pin=false
CSET use_rstb_pin=false
CSET write_depth_a=8192
CSET write_width_a=8
CSET write_width_b=32
# END Parameters
GENERATE
# CRC: 51002eda
/trunk/gateware/TosNet_rev3_2/tdl_app_master.vhd
0,0 → 1,211
----------------------------------------------------------------------------------
-- Company: University of Southern Denmark
-- Engineer: Simon Falsig
--
-- Create Date: 11/5/2010
-- Design Name TosNet
-- Module Name: app_master - Behavioral
-- File Name: app_master.vhd
-- Project Name: TosNet
-- Target Devices: Spartan3/6
-- Tool versions: Xilinx ISE 12.2
-- Description: The master discovery module performs master discovery and
-- setup during startup. The node with the lowest node_id is
-- designated as the master, and transmits this information to
-- all other nodes in the network.
--
-- Revision:
-- Revision 3.2 - Initial release
--
-- Copyright 2010
--
-- This module 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 3 of the License, or
-- (at your option) any later version.
--
-- This module 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 module. If not, see <http://www.gnu.org/licenses/>.
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use work.commandpack.all;
 
 
entity tdl_app_master is
Port ( app_enable : in STD_LOGIC;
app_data_in : in STD_LOGIC_VECTOR(7 downto 0);
app_data_in_strobe : in STD_LOGIC;
app_data_out : out STD_LOGIC_VECTOR(7 downto 0);
app_data_out_strobe : out STD_LOGIC;
app_data_out_enable : out STD_LOGIC;
app_buffer_full : in STD_LOGIC;
app_packet_error : in STD_LOGIC;
app_force_packet_error : out STD_LOGIC;
app_cmd_valid : in STD_LOGIC;
app_sync_strobe : in STD_LOGIC;
app_is_master : out STD_LOGIC;
app_dsc_done : out STD_LOGIC;
app_node_id : in STD_LOGIC_VECTOR(3 downto 0);
app_clk : in STD_LOGIC;
app_reset : in STD_LOGIC);
end tdl_app_master;
 
architecture Behavioral of tdl_app_master is
 
type STATES is (OFF, IDLE, DSC, CMP, SET, SET_RESPOND, WAIT_FOR_SET, DONE);
signal state : STATES := OFF;
signal next_state : STATES := OFF;
signal last_data_in_strobe : STD_LOGIC;
signal lowest_current_id : STD_LOGIC_VECTOR(3 downto 0);
 
signal counter : STD_LOGIC_VECTOR(2 downto 0) := "000";
 
begin
 
process(app_clk)
begin
if(app_clk = '1' and app_clk'EVENT) then
if(app_reset = '1') then
state <= OFF;
else
state <= next_state;
end if;
if(app_buffer_full = '1') then
counter <= counter;
elsif(state = next_state) then
counter <= counter + 1;
else
counter <= "000";
end if;
 
case state is
 
when OFF =>
app_data_out_enable <= '0';
app_data_out_strobe <= '0';
app_data_out <= "00000000";
app_force_packet_error <= 'Z';
app_is_master <= '0';
app_dsc_done <= '0';
last_data_in_strobe <= '0';
lowest_current_id <= app_node_id;
 
when IDLE =>
app_data_out_enable <= '0';
app_data_out_strobe <= '0';
app_dsc_done <= '0';
app_is_master <= '0';
 
when DSC => --Transmit discovery packet
app_data_out_enable <= '1';
app_data_out <= CMD_MASTER_DSC & lowest_current_id;
app_data_out_strobe <= '1';
 
when CMP => --Compare received packets to lowest known id
app_data_out_enable <= '0';
app_data_out_strobe <= '0';
if(app_data_in_strobe = '1' and last_data_in_strobe = '0' and app_cmd_valid = '1') then
if(app_data_in(7 downto 4) = CMD_MASTER_DSC) then
if(app_data_in(3 downto 0) = app_node_id) then
app_is_master <= '1';
elsif(app_data_in(3 downto 0) < app_node_id) then
lowest_current_id <= app_data_in(3 downto 0);
end if;
end if;
end if;
 
when SET => --Transmit set packet (master only)
app_data_out_enable <= '1';
app_data_out <= CMD_MASTER_SET & lowest_current_id;
app_data_out_strobe <= '1';
when SET_RESPOND => --Forward set packet (slave only)
app_data_out_enable <= '1';
app_data_out <= app_data_in(7 downto 0);
app_data_out_strobe <= '1';
 
when WAIT_FOR_SET => --Wait until set is received again (master only)
app_data_out_enable <= '0';
app_data_out_strobe <= '0';
when DONE => --Done!
app_dsc_done <= '1';
app_data_out_enable <= '0';
app_data_out_strobe <= '0';
app_data_out <= "00000000";
app_force_packet_error <= 'Z';
end case;
last_data_in_strobe <= app_data_in_strobe;
end if;
end process;
 
process(state, app_enable, app_data_in, app_data_in_strobe, last_data_in_strobe, app_node_id, app_cmd_valid)
begin
case state is
when OFF =>
if(app_enable = '1') then
next_state <= IDLE;
else
next_state <= OFF;
end if;
when IDLE =>
next_state <= DSC;
when DSC =>
next_state <= CMP;
when CMP =>
next_state <= CMP;
 
if(app_data_in_strobe = '1' and last_data_in_strobe = '0' and app_cmd_valid = '1') then
if(app_data_in(7 downto 4) = CMD_MASTER_DSC) then
if(app_data_in(3 downto 0) = app_node_id) then
next_state <= SET;
else
next_state <= DSC;
end if;
elsif(app_data_in(7 downto 4) = CMD_MASTER_SET) then
if(app_data_in(3 downto 0) > app_node_id) then --Make a quick sanity check on the received master node id, if it is larger than the id of this node, then something is wrong...
next_state <= IDLE;
else
next_state <= SET_RESPOND;
end if;
end if;
end if;
when SET =>
next_state <= WAIT_FOR_SET;
 
when SET_RESPOND =>
next_state <= DONE;
when WAIT_FOR_SET =>
next_state <= WAIT_FOR_SET;
if(app_data_in_strobe = '1' and last_data_in_strobe = '0' and app_cmd_valid = '1') then
if(app_data_in(7 downto 4) = CMD_MASTER_SET) then
next_state <= DONE;
end if;
end if;
when DONE =>
next_state <= DONE;
end case;
end process;
 
end Behavioral;
 

powered by: WebSVN 2.1.0

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