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; |
|