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

Subversion Repositories fade_ether_protocol

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /fade_ether_protocol
    from Rev 43 to Rev 44
    Reverse comparison

Rev 43 → Rev 44

/trunk/stable_jumbo_frames_version/fpga/afck_8ch_proj_def.tcl
0,0 → 1,15
set eprj_proj_name "afck_10g3_8ch"
set eprj_def_root "src/afck_8ch.eprj"
set eprj_top_entity "afck_10g_2"
set eprj_board_part "xilinx.com:kc705:part0:0.9"
set eprj_part "xc7k325tffg900-2"
set eprj_target_language "VHDL"
set eprj_simulator_language "Mixed"
set eprj_default_lib "work"
set eprj_synth_flow "Vivado Synthesis 2016"
set eprj_synth_strategy "Flow_PerfOptimized_high"
set eprj_impl_flow "Vivado Implementation 2016"
set eprj_impl_strategy "Performance_Retiming"
set eprj_vivado_version "2016.4"
set eprj_vivado_version_allow_upgrade false
 
/trunk/stable_jumbo_frames_version/fpga/afck_proj_def.tcl
0,0 → 1,15
set eprj_proj_name "afck_10g3_4ch"
set eprj_def_root "src/afck_4ch.eprj"
set eprj_top_entity "afck_10g_2"
set eprj_board_part "xilinx.com:kc705:part0:0.9"
set eprj_part "xc7k325tffg900-2"
set eprj_target_language "VHDL"
set eprj_simulator_language "Mixed"
set eprj_default_lib "work"
set eprj_synth_flow "Vivado Synthesis 2016"
set eprj_synth_strategy "Flow_PerfOptimized_high"
set eprj_impl_flow "Vivado Implementation 2016"
set eprj_impl_strategy "Performance_Retiming"
set eprj_vivado_version "2016.4"
set eprj_vivado_version_allow_upgrade false
 
/trunk/stable_jumbo_frames_version/fpga/build_proj_afck
1,4 → 1,5
#!/bin/bash
set -e
(
cd src
for i in *.rec; do
5,5 → 6,7
./rec_to_pkg.py $i
done
)
vivado -mode batch -source fade_afck.tcl
 
PROJ_DEF=afck_proj_def.tcl
vivado -mode batch -source $PROJ_DEF -source vextproj/eprj_create.tcl
vivado -mode batch -source $PROJ_DEF -source vextproj/eprj_write.tcl
vivado -mode batch -source $PROJ_DEF -source vextproj/eprj_build.tcl
/trunk/stable_jumbo_frames_version/fpga/build_proj_afck_8ch
1,4 → 1,5
#!/bin/bash
set -e
(
cd src
for i in *.rec; do
5,5 → 6,7
./rec_to_pkg.py $i
done
)
vivado -mode batch -source fade_afck_8ch.tcl
 
PROJ_DEF=afck_8ch_proj_def.tcl
vivado -mode batch -source $PROJ_DEF -source vextproj/eprj_create.tcl
vivado -mode batch -source $PROJ_DEF -source vextproj/eprj_write.tcl
vivado -mode batch -source $PROJ_DEF -source vextproj/eprj_build.tcl
/trunk/stable_jumbo_frames_version/fpga/build_proj_kc705
1,4 → 1,5
#!/bin/bash
set -e
(
cd src
for i in *.rec; do
5,5 → 6,7
./rec_to_pkg.py $i
done
)
vivado -mode batch -source fade_kc705.tcl
 
PROJ_DEF=kc705_proj_def.tcl
vivado -mode batch -source $PROJ_DEF -source vextproj/eprj_create.tcl
vivado -mode batch -source $PROJ_DEF -source vextproj/eprj_write.tcl
vivado -mode batch -source $PROJ_DEF -source vextproj/eprj_build.tcl
/trunk/stable_jumbo_frames_version/fpga/kc705_proj_def.tcl
0,0 → 1,15
set eprj_proj_name "kc705_10g3"
set eprj_def_root "src/kc705.eprj"
set eprj_top_entity "kc705_10g_2"
set eprj_board_part "xilinx.com:kc705:part0:0.9"
set eprj_part "xc7k325tffg900-2"
set eprj_target_language "VHDL"
set eprj_simulator_language "Mixed"
set eprj_default_lib "work"
set eprj_synth_flow "Vivado Synthesis 2016"
set eprj_synth_strategy "Flow_PerfOptimized_high"
set eprj_impl_flow "Vivado Implementation 2016"
set eprj_impl_strategy "Performance_Retiming"
set eprj_vivado_version "2016.4"
set eprj_vivado_version_allow_upgrade false
 
/trunk/stable_jumbo_frames_version/fpga/src/AFCK/AFCK_fade_top_8ch.vhd
294,6 → 294,20
);
end component;
 
component i2c_vio_ctrl is
port (
clk : in std_logic;
scl : inout std_logic;
sda : inout std_logic);
end component i2c_vio_ctrl;
 
component vio_frq is
port (
clk : in std_logic;
probe_in0 : in std_logic_vector (31 downto 0);
probe_in1 : in std_logic_vector (31 downto 0));
end component vio_frq;
 
begin -- beh1
si570_oe <= '1';
clk_updaten <= '1';
406,7 → 420,7
 
end generate il1;
il2 : if n /= 0 generate
ten_gig_eth_pcs_pma_1_1 : entity work.ten_gig_eth_pcs_pma_1
ten_gig_eth_pcs_pma_1_1 : ten_gig_eth_pcs_pma_1
port map (
dclk => core_clk156_out(q),
rxrecclk_out => open, --??
520,7 → 534,7
clk_user <= core_clk156_out;
 
-- Frequency meters
vio_frq_1 : entity work.vio_frq
vio_frq_1 : vio_frq
port map (
clk => boot_clk,
probe_in0 => clk0_frq,
527,7 → 541,7
probe_in1 => clk1_frq);
 
-- Vio Link statuses
vio_stat_1 : entity work.vio_stat
vio_stat_1 : vio_stat
port map (
clk => boot_clk,
probe_in0 => core_status(0),
540,7 → 554,7
probe_in7 => core_status(7));
 
-- JTAG<->I2C part for clock-crossbar
i2c_vio_ctrl_1 : entity work.i2c_vio_ctrl
i2c_vio_ctrl_1 : i2c_vio_ctrl
port map (
clk => boot_clk,
scl => scl,
/trunk/stable_jumbo_frames_version/fpga/src/AFCK/i2c/i2c_vio_ctrl_top.vhd
7,7 → 7,7
-- License : PUBLIC DOMAIN
-- Company :
-- Created : 2015-05-03
-- Last update: 2015-05-07
-- Last update: 2017-01-22
-- Platform :
-- Standard : VHDL'93/02
-------------------------------------------------------------------------------
77,7 → 77,7
 
begin -- architecture beh
 
vio_0_1 : entity work.vio_0
vio_0_1 : vio_0
port map (
clk => clk,
probe_in0 => dout,
/trunk/stable_jumbo_frames_version/fpga/src/AFCK/i2c/main.eprj
0,0 → 1,5
vhdl work i2c_bus_wrap.vhd
vhdl work i2c_master_bit_ctrl.vhd
vhdl work i2c_master_byte_ctrl.vhd
vhdl work i2c_master_top.vhd
vhdl work i2c_vio_ctrl_top.vhd
/trunk/stable_jumbo_frames_version/fpga/src/AFCK/main_4ch.eprj
0,0 → 1,8
xci work ack_fifo/ack_fifo.xci
xci work ila_1/ila_1.xci
xci work ten_gig_eth_0/ten_gig_eth_pcs_pma_0.xci
xci work ten_gig_eth_1/ten_gig_eth_pcs_pma_1.xci
xdc fade_afck.xdc
vhdl work AFCK_fade_top_4ch.vhd
 
 
/trunk/stable_jumbo_frames_version/fpga/src/AFCK/main_8ch.eprj
0,0 → 1,11
xci work ack_fifo/ack_fifo.xci
xci work ila_1/ila_1.xci
xci work vio_0/vio_0.xci
xci work vio_frq/vio_frq.xci
xci work vio_stat/vio_stat.xci
xci work ten_gig_eth_0/ten_gig_eth_pcs_pma_0.xci
xci work ten_gig_eth_1/ten_gig_eth_pcs_pma_1.xci
xdc fade_afck_8ch.xdc
include i2c
vhdl work frq_counter.vhd
vhdl work AFCK_fade_top_8ch.vhd
/trunk/stable_jumbo_frames_version/fpga/src/afck_4ch.eprj
0,0 → 1,3
include common.eprj
vhdl work fade_one_channel.vhd
include AFCK/main_4ch.eprj
/trunk/stable_jumbo_frames_version/fpga/src/afck_8ch.eprj
0,0 → 1,3
include common.eprj
vhdl work fade_one_channel.vhd
include AFCK/main_8ch.eprj
/trunk/stable_jumbo_frames_version/fpga/src/common.eprj
0,0 → 1,13
vhdl work pkt_ack_pkg.vhd
vhdl work pkt_desc_pkg.vhd
vhdl work eth_sender64.vhd
vhdl work eth_receiver64.vhd
vhdl work pkg_newcrc32_d64.vhd
vhdl work pkg_newcrc32_d32.vhd
vhdl work pkg_newcrc32_d16.vhd
vhdl work desc_mgr_pkg.vhd
vhdl work dpram_inf.vhd
vhdl work desc_manager_simple.vhd
vhdl work cmd_proc.vhd
 
 
/trunk/stable_jumbo_frames_version/fpga/src/eth_receiver64.vhd
0,0 → 1,413
-------------------------------------------------------------------------------
-- Title : FPGA Ethernet interface - block receiving packets from MII PHY
-- Project :
-------------------------------------------------------------------------------
-- File : eth_receiver4.vhd
-- Author : Wojciech M. Zabolotny (wzab@ise.pw.edu.pl)
-- License : BSD License
-- Company :
-- Created : 2012-03-30
-- Last update: 2014-10-12
-- Platform :
-- Standard : VHDL'93
-------------------------------------------------------------------------------
-- Description: This file implements the state machine, responsible for
-- reception of packets and passing them to the acknowledgements and commands
-- FIFO
-------------------------------------------------------------------------------
-- Copyright (c) 2012
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2012-03-30 1.0 WZab Created
-------------------------------------------------------------------------------
 
-- Uwaga! Tu mamy rzeczywiste problemy z obsluga odebranych pakietow!
--
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.desc_mgr_pkg.all;
use work.pkt_ack_pkg.all;
use work.pkg_newcrc32_d64.all;
use work.pkg_newcrc32_d32.all;
use work.pkg_newcrc32_d16.all;
 
 
entity eth_receiver is
port (
-- Configuration
peer_mac : out std_logic_vector(47 downto 0);
my_mac : in std_logic_vector(47 downto 0);
my_ether_type : in std_logic_vector(15 downto 0);
transmit_data : out std_logic;
restart : out std_logic;
-- ACK FIFO interface
ack_fifo_full : in std_logic;
ack_fifo_wr_en : out std_logic;
ack_fifo_din : out std_logic_vector(pkt_ack_width-1 downto 0);
-- System interface
clk : in std_logic;
rst_n : in std_logic;
dbg : out std_logic_vector(3 downto 0);
cmd : out std_logic_vector(31 downto 0);
arg : out std_logic_vector(31 downto 0);
crc : out std_logic_vector(31 downto 0);
-- MAC interface
Rx_Clk : in std_logic;
RxC : in std_logic_vector(7 downto 0);
RxD : in std_logic_vector(63 downto 0)
);
 
end eth_receiver;
 
 
architecture beh1 of eth_receiver is
 
type T_STATE is (ST_RCV_IDLE, ST_RCV_PREAMB, ST_CHECK_PREAMB,
ST_RCV_HEADER1, ST_RCV_HEADER2, ST_RCV_CMD,
ST_RCV_WAIT_IDLE, ST_RCV_ARGS, ST_RCV_PROCESS, ST_RCV_UPDATE,
ST_RCV_TRAILER);
 
 
 
function rev(a : in std_logic_vector)
return std_logic_vector is
variable result : std_logic_vector(a'range);
alias aa : std_logic_vector(a'reverse_range) is a;
begin
for i in aa'range loop
result(i) := aa(i);
end loop;
return result;
end; -- function reverse_any_bus
 
constant C_PROTO_ID : std_logic_vector(31 downto 0) := x"fade0100";
 
type T_RCV_REGS is record
state : T_STATE;
swap_lanes : std_logic;
transmit_data : std_logic;
restart : std_logic;
update_flag : std_logic;
count : integer;
dbg : std_logic_vector(3 downto 0);
crc32 : std_logic_vector(31 downto 0);
cmd : std_logic_vector(31 downto 0);
arg : std_logic_vector(31 downto 0);
mac_addr : std_logic_vector(47 downto 0);
peer_mac : std_logic_vector(47 downto 0);
end record;
 
constant RCV_REGS_INI : T_RCV_REGS := (
state => ST_RCV_IDLE,
swap_lanes => '0',
transmit_data => '0',
restart => '0',
update_flag => '0',
count => 0,
dbg => (others => '0'),
crc32 => (others => '0'),
cmd => (others => '0'),
arg => (others => '0'),
mac_addr => (others => '0'),
peer_mac => (others => '0')
);
 
signal r, r_n : T_RCV_REGS := RCV_REGS_INI;
 
type T_RCV_COMB is record
ack_fifo_wr_en : std_logic;
Rx_mac_rd : std_logic;
ack_fifo_din : std_logic_vector(pkt_ack_width-1 downto 0);
restart : std_logic;
end record;
 
constant RCV_COMB_DEFAULT : T_RCV_COMB := (
ack_fifo_wr_en => '0',
Rx_mac_rd => '0',
ack_fifo_din => (others => '0'),
restart => '0'
);
 
signal c : T_RCV_COMB := RCV_COMB_DEFAULT;
 
signal rxd_sw, rxd_del : std_logic_vector(63 downto 0);
signal rxc_sw, rxc_del : std_logic_vector(7 downto 0);
 
signal rx_rst_n, rx_rst_n_0, rx_rst_n_1 : std_logic := '0';
signal update_flag_0, update_flag_1, update_flag : std_logic := '0';
 
begin -- beh1
 
ack_fifo_din <= c.ack_fifo_din;
ack_fifo_wr_en <= c.ack_fifo_wr_en;
 
--dbg <= r.dbg;
crc <= r.crc32;
cmd <= r.cmd;
arg <= r.arg;
-- Lane switcher processes
lsw_c1 : process (RxC, RxC(3 downto 0), RxC_del(7 downto 4), RxD,
RxD(31 downto 0), RxD_del(63 downto 32), r.swap_lanes) is
begin -- process lsw_c1
if r.swap_lanes = '1' then
RxD_Sw(63 downto 32) <= RxD(31 downto 0);
RxD_Sw(31 downto 0) <= RxD_del(63 downto 32);
RxC_Sw(7 downto 4) <= RxC(3 downto 0);
RxC_Sw(3 downto 0) <= RxC_del(7 downto 4);
else
RxD_Sw <= RxD;
RxC_Sw <= RxC;
end if;
end process lsw_c1;
 
process (Rx_Clk, rx_rst_n) is
begin -- process
if rx_rst_n = '0' then -- asynchronous reset (active low)
RxD_del <= (others => '0');
RxC_del <= (others => '0');
elsif Rx_Clk'event and Rx_Clk = '1' then -- rising clock edge
RxD_del <= RxD;
RxC_del <= RxC;
end if;
end process;
 
-- Reading of ethernet data
rdp1 : process (Rx_Clk, rx_rst_n)
begin -- process rdp1
if rx_rst_n = '0' then -- asynchronous reset (active low)
r <= RCV_REGS_INI;
elsif Rx_Clk'event and Rx_Clk = '1' then -- rising clock edge
r <= r_n;
end if;
end process rdp1;
 
rdp2 : process (RxC, RxC_Sw, RxD, RxD_Sw, ack_fifo_full, my_ether_type,
my_mac, r, r.arg(15 downto 10), r.arg(31 downto 16),
r.cmd(15 downto 0), r.cmd(31 downto 16), r.crc32, r.dbg(0),
r.dbg(1), r.dbg(2), r.dbg(3), r.mac_addr, r.state,
r.update_flag)
 
variable ack_pkt_in : pkt_ack;
variable v_mac_addr : std_logic_vector(47 downto 0);
variable v_cmd, v_arg : std_logic_vector(31 downto 0);
variable v_crc : std_logic_vector(31 downto 0);
variable v_proto : std_logic_vector(31 downto 0);
begin -- process
c <= RCV_COMB_DEFAULT;
r_n <= r;
dbg <= "1111";
case r.state is
when ST_RCV_IDLE =>
dbg <= "0000";
-- We must be prepared to one of two possible events
-- Either we receive the SOF in the 0-th lane (and then we proceed
-- normally) or we receive the SOF in the 4-th lane (and then we have
-- to switch lanes, delaying 4 of them).
if RxC = b"00011111" and RxD = x"55_55_55_fb_07_07_07_07" then
-- shifted lanes
-- switch on the "lane shifter" and go to the state,
-- where we can check the proper preamble after lane switching
r_n.swap_lanes <= '1';
r_n.state <= ST_CHECK_PREAMB;
elsif RxC = b"00000001" and RxD = x"d5_55_55_55_55_55_55_fb" then
-- normal lanes
r_n.swap_lanes <= '0';
r_n.crc32 <= (others => '1');
r_n.state <= ST_RCV_HEADER1;
end if;
when ST_CHECK_PREAMB =>
dbg <= "0001";
if RxC_Sw = b"00000001" and RxD_Sw = x"d5_55_55_55_55_55_55_fb" then
r_n.crc32 <= (others => '1');
r_n.state <= ST_RCV_HEADER1;
else
-- interrupted preamble reception
r_n.state <= ST_RCV_IDLE;
end if;
when ST_RCV_HEADER1 =>
dbg <= "0010";
if RxC_Sw = b"00000000" then
r_n.crc32 <= newcrc32_d64(RxD_Sw, r.crc32);
-- Change the order of bytes!
for i in 0 to 5 loop
v_mac_addr(47-i*8 downto 40-i*8) := RxD_Sw(i*8+7 downto i*8);
end loop; -- i
if v_mac_addr /= my_mac then
-- This packet is not for us - ignore it!
r_n.state <= ST_RCV_WAIT_IDLE;
else
-- Our packet!
r_n.count <= 0;
-- Read the lower 16 bits of the sender address
-- Again, we have to change the order of bytes!
r_n.mac_addr(39 downto 32) <= RxD_Sw(63 downto 56);
r_n.mac_addr(47 downto 40) <= RxD_Sw(55 downto 48);
r_n.state <= ST_RCV_HEADER2;
end if;
else
-- packet broken?
r_n.state <= ST_RCV_IDLE;
end if;
when ST_RCV_HEADER2 =>
dbg <= "0010";
if RxC_Sw = b"00000000" then
r_n.crc32 <= newcrc32_d64(RxD_Sw, r.crc32);
v_mac_addr := r.mac_addr;
for i in 0 to 3 loop
v_mac_addr(31-i*8 downto 24-i*8) := RxD_Sw(i*8+7 downto i*8);
end loop; -- i
--v_mac_addr(47 downto 16) := RxD_Sw(31 downto 0);
r_n.mac_addr <= v_mac_addr;
-- In the rest of this 64-bit word, we receive the protocol ID
-- and version
for i in 0 to 3 loop
v_proto(i*8+7 downto i*8) := RxD_Sw(63-i*8 downto 56-i*8);
end loop; -- i
-- Check if the proto id is correct
if v_proto = C_PROTO_ID then
r_n.state <= ST_RCV_CMD;
else
r_n.state <= ST_RCV_IDLE;
end if;
else
-- packet broken?
r_n.state <= ST_RCV_IDLE;
end if;
when ST_RCV_CMD =>
if RxC_Sw = b"0000_0000" then
r_n.crc32 <= newcrc32_d64(RxD_Sw, r.crc32);
-- Copy the command, changing order of bytes!
for i in 0 to 3 loop
r_n.cmd(i*8+7 downto i*8) <= RxD_Sw(31-i*8 downto 24-i*8);
end loop; -- i
-- Copy the argument, changing order of bytes!
for i in 0 to 3 loop
r_n.arg(i*8+7 downto i*8) <= RxD_Sw(63-i*8 downto 56-i*8);
end loop; -- i
r_n.state <= ST_RCV_TRAILER;
-- Currently we ignore rest of the packet!
else
-- packet broken?
r_n.state <= ST_RCV_IDLE;
end if;
when ST_RCV_TRAILER =>
-- No detection of too long frames!
dbg <= "0110";
if RxC_Sw /= b"0000_0000" then
-- It should be a packet with the checksum
-- The EOF may be on any of 8th positions.
-- To avoid too big combinational functions,
-- we handle it in a few states (but this increases requirements
-- on IFC!)
-- Current implementation assumes fixed length of frames
-- but the optimal one should probably pass received data for further
-- checking, why this machine continues to receive next frame...
if RxC_Sw = b"1111_1100" then
v_crc := r.crc32;
v_crc := newcrc32_d16(RxD_Sw(15 downto 0), v_crc);
r_n.crc32 <= v_crc;
if (RxD_Sw(23 downto 16) = x"fd") and
(v_crc = x"c704dd7b") then
-- Correct packet, go to processing
r_n.peer_mac <= r.mac_addr;
r_n.state <= ST_RCV_PROCESS;
else
-- Wrong CRC or EOF
r_n.state <= ST_RCV_IDLE;
end if;
else
-- Wrong packet
r_n.state <= ST_RCV_IDLE;
end if;
else
-- Ignore received data, only updating the checksum
r_n.crc32 <= newcrc32_d64(RxD_Sw, r.crc32);
end if;
when ST_RCV_PROCESS =>
dbg <= "0111";
case to_integer(unsigned(r.cmd(31 downto 16))) is
-- Handle commands, which require immediate action
when FCMD_START =>
r_n.dbg(0) <= not r.dbg(0);
-- Start transmission command
r_n.transmit_data <= '1';
when FCMD_STOP =>
r_n.dbg(1) <= not r.dbg(1);
-- Stop transmission command
r_n.transmit_data <= '0';
when FCMD_RESET =>
r_n.dbg(3) <= not r.dbg(3);
-- Restart the whole block(?)
r_n.restart <= '1';
when others =>
null;
end case;
-- All commands are written to the acknowledge and commands
-- FIFO, so that they will be handled by the descriptor manager
if ack_fifo_full = '0' then
ack_pkt_in.cmd := unsigned(r.cmd(31 downto 16));
ack_pkt_in.pkt := unsigned(r.arg);
ack_pkt_in.seq := unsigned(r.cmd(15 downto 0));
c.ack_fifo_din <= pkt_ack_to_stlv(ack_pkt_in);
c.ack_fifo_wr_en <= '1';
end if;
r_n.state <= ST_RCV_UPDATE;
when ST_RCV_UPDATE =>
dbg <= "1000";
r_n.update_flag <= not r.update_flag;
r_n.state <= ST_RCV_IDLE;
when ST_RCV_WAIT_IDLE =>
dbg <= "1001";
if RxC_Sw = b"1111_1111" then
r_n.state <= ST_RCV_IDLE;
end if;
when others => null;
end case;
end process rdp2;
 
-- Synchronization of the reset signal for the Rx_Clk domain
process (Rx_Clk, rst_n)
begin -- process
if rst_n = '0' then -- asynchronous reset (active low)
rx_rst_n_0 <= '0';
rx_rst_n_1 <= '0';
rx_rst_n <= '0';
elsif Rx_Clk'event and Rx_Clk = '1' then -- rising clock edge
rx_rst_n_0 <= rst_n;
rx_rst_n_1 <= rx_rst_n_0;
rx_rst_n <= rx_rst_n_1;
end if;
end process;
 
 
-- Synchronization of output signals between the clock domains
process (clk, rst_n)
begin -- process
if rst_n = '0' then -- asynchronous reset (active low)
peer_mac <= (others => '0');
transmit_data <= '0';
restart <= '0';
update_flag_0 <= '0';
update_flag_1 <= '0';
update_flag <= '0';
elsif clk'event and clk = '1' then -- rising clock edge
-- Synchronization of the update_flag
update_flag_0 <= r.update_flag;
update_flag_1 <= update_flag_0;
update_flag <= update_flag_1;
-- When update flag has changed, rewrite synchronized fields
if update_flag /= update_flag_1 then
peer_mac <= r.peer_mac;
transmit_data <= r.transmit_data;
restart <= r.restart;
end if;
end if;
end process;
 
end beh1;
/trunk/stable_jumbo_frames_version/fpga/src/eth_sender64.vhd
0,0 → 1,399
-------------------------------------------------------------------------------
-- Title : FPGA Ethernet interface - block sending packets via XGMII Phy
-- Project :
-------------------------------------------------------------------------------
-- File : eth_sender64.vhd
-- Author : Wojciech M. Zabolotny (wzab@ise.pw.edu.pl)
-- License : BSD License
-- Company :
-- Created : 2012-03-30
-- Last update: 2014-10-12
-- Platform :
-- Standard : VHDL'93
-------------------------------------------------------------------------------
-- Description: This file implements the state machine, which manages the
-- table of packet descriptors, used to resend only not confirmed packets
-------------------------------------------------------------------------------
-- Copyright (c) 2012
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2012-03-30 1.0 WZab Created
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.desc_mgr_pkg.all;
use work.pkg_newcrc32_d64.all;
 
entity eth_sender is
port (
-- Configuration
peer_mac : in std_logic_vector(47 downto 0);
my_mac : in std_logic_vector(47 downto 0);
my_ether_type : in std_logic_vector(15 downto 0);
pkt_number : in unsigned(31 downto 0);
seq_number : in unsigned(15 downto 0);
transm_delay : in unsigned(31 downto 0);
-- System interface
clk : in std_logic;
rst_n : in std_logic;
-- Control interface
ready : out std_logic;
flushed : in std_logic;
start : in std_logic;
cmd_start : in std_logic;
-- Data memory interface
tx_mem_addr : out std_logic_vector(LOG2_N_OF_PKTS+LOG2_NWRDS_IN_PKT-1 downto 0);
tx_mem_data : in std_logic_vector(63 downto 0);
-- User command response interface
cmd_response : in std_logic_vector(12*8-1 downto 0);
-- TX Phy interface
Tx_Clk : in std_logic;
TxC : out std_logic_vector(7 downto 0);
TxD : out std_logic_vector(63 downto 0)
);
 
end eth_sender;
 
 
architecture beh1 of eth_sender is
 
type T_ETH_SENDER_STATE is (WST_IDLE, WST_SEND_PREAMB_AND_SOF, WST_SEND_CMD_HEADER,
WST_SEND_CMD_TRAILER,
WST_SEND_HEADER, WST_SEND_DATA, WST_SEND_CRC_AND_EOF,
WST_SEND_COMPLETED);
 
type T_ETH_SENDER_REGS is record
state : T_ETH_SENDER_STATE;
ready : std_logic;
count : integer;
word : integer;
mem_addr : unsigned (LOG2_NWRDS_IN_PKT-1 downto 0);
crc32 : std_logic_vector(31 downto 0);
end record;
constant ETH_SENDER_REGS_INI : T_ETH_SENDER_REGS := (
state => WST_IDLE,
ready => '1',
count => 0,
word => 0,
mem_addr => (others => '0'),
crc32 => (others => '0')
) ;
 
signal r, r_n : T_ETH_SENDER_REGS := ETH_SENDER_REGS_INI;
 
type T_ETH_SENDER_COMB is record
TxD : std_logic_vector(63 downto 0);
TxC : std_logic_vector(7 downto 0);
mem_addr : unsigned(LOG2_NWRDS_IN_PKT-1 downto 0);
end record;
 
constant ETH_SENDER_COMB_DEFAULT : T_ETH_SENDER_COMB := (
TxD => x"07_07_07_07_07_07_07_07",
TxC => (others => '1'),
mem_addr => (others => '0')
);
 
signal c : T_ETH_SENDER_COMB := ETH_SENDER_COMB_DEFAULT;
 
signal s_header : std_logic_vector(8*40-1 downto 0) := (others => '0');
constant HEADER_LEN : integer := 5; -- 5 words, 8 bytes each
signal s_cmd_header : std_logic_vector(8*32-1 downto 0) := (others => '0');
constant CMD_HEADER_LEN : integer := 4; -- 4 words, 8 bytes each
 
signal cmd_only : std_logic := '0';
 
-- The function select_8bytes changes order of bytes, ensuring
-- that the MSB is transmitted first...
function select_8bytes (
constant vec : std_logic_vector;
constant chunk_num : integer)
return std_logic_vector is
variable byte_ofs : integer;
variable chunk_ofs : integer;
variable v_bytes : std_logic_vector(63 downto 0);
begin
chunk_ofs := chunk_num*64;
-- first select byte
for byte_num in 0 to 7 loop
byte_ofs := byte_num * 8;
v_bytes(byte_ofs+7 downto byte_ofs) := vec(vec'left-chunk_ofs-byte_ofs downto vec'left-chunk_ofs-byte_ofs-7);
end loop; -- byte_num
return v_bytes;
end select_8bytes;
 
 
function rev(a : in std_logic_vector)
return std_logic_vector is
variable result : std_logic_vector(a'range);
alias aa : std_logic_vector(a'reverse_range) is a;
begin
for i in aa'range loop
result(i) := aa(i);
end loop;
return result;
end; -- function reverse_any_bus
 
signal tx_rst_n, tx_rst_n_0, tx_rst_n_1 : std_logic := '0';
signal update_flag_0, update_flag_1, update_flag : std_logic := '0';
 
signal start_0, tx_start, tx_start_1, tx_start_0 : std_logic := '0';
signal tx_ready, ready_0, ready_1 : std_logic := '0';
 
type T_STATE1 is (ST1_IDLE, ST1_WAIT_NOT_READY, ST1_WAIT_NOT_START,
ST1_WAIT_READY);
signal state1 : T_STATE1;
 
type T_STATE2 is (ST2_IDLE, ST2_WAIT_NOT_READY, ST2_WAIT_READY);
signal state2 : T_STATE2;
 
signal dta_packet_type : std_logic_vector(15 downto 0) := (others => '0');
begin -- beh1
 
dta_packet_type <= x"a5a5" when flushed = '0' else x"a5a6";
-- Headers should contain n*8 bytes
-- Data packet header
s_header <= peer_mac & my_mac & my_ether_type & x"0100" &
dta_packet_type & std_logic_vector(seq_number(15 downto 0)) &
std_logic_vector(pkt_number) &
std_logic_vector(transm_delay) & cmd_response;
-- Command response packet header - we have unused 16 bits in the response packet...
s_cmd_header <= peer_mac & my_mac & my_ether_type & x"0100" &
x"a55a" & x"0000" & cmd_response;
 
-- Connection of the signals
 
-- The memory address is built from the packet number (6 bits) and word
-- number (8 bits)
tx_mem_addr <= std_logic_vector(pkt_number(LOG2_N_OF_PKTS-1 downto 0)) & std_logic_vector(c.mem_addr);
 
-- Main state machine used to send the packet
-- W calej maszynie trzeba jeszcze dodac obsluge kolizji!!!
-- Oprocz tego trzeba przeanalizowac poprawnosc przejsc miedzy domenami zegara
 
 
snd1 : process (Tx_Clk, tx_rst_n)
begin
if tx_rst_n = '0' then -- asynchronous reset (active low)
r <= ETH_SENDER_REGS_INI;
TxD <= x"07_07_07_07_07_07_07_07";
TxC <= (others => '1');
elsif Tx_Clk'event and Tx_Clk = '1' then -- rising clock edge
r <= r_n;
-- To minimize glitches and propagation delay, let's add pipeline register
TxC <= c.TxC;
TxD <= c.TxD;
end if;
end process snd1; -- snd1
 
snd2 : process (r, s_header, tx_mem_data, tx_start)
variable v_TxD : std_logic_vector(63 downto 0);
begin -- process snd1
-- default values
c <= ETH_SENDER_COMB_DEFAULT;
r_n <= r;
case r.state is
when WST_IDLE =>
c.TxD <= x"07_07_07_07_07_07_07_07";
c.TxC <= "11111111";
r_n.ready <= '1';
if tx_start = '1' then
r_n.ready <= '0';
r_n.state <= WST_SEND_PREAMB_AND_SOF;
r_n.count <= 7;
end if;
when WST_SEND_PREAMB_AND_SOF =>
-- Collision detection should be added?
c.TxD <= x"d5_55_55_55_55_55_55_fb";
c.TxC <= "00000001";
-- Prepare for sending of header
r_n.crc32 <= (others => '1');
if cmd_only = '1' then
r_n.state <= WST_SEND_CMD_HEADER;
else
r_n.state <= WST_SEND_HEADER;
end if;
r_n.count <= 0;
when WST_SEND_CMD_HEADER =>
v_TxD := select_8bytes(s_cmd_header, r.count);
c.TxD <= v_TxD;
c.TxC <= (others => '0');
r_n.crc32 <= newcrc32_d64(v_TxD, r.crc32);
if r.count < CMD_HEADER_LEN-1 then
r_n.count <= r.count + 1;
else
r_n.count <= 0;
r_n.word <= 0;
r_n.mem_addr <= (others => '0');
c.mem_addr <= (others => '0');
r_n.state <= WST_SEND_CMD_TRAILER;
end if;
when WST_SEND_CMD_TRAILER =>
v_TxD := (others => '0');
c.TxD <= v_TxD;
c.TxC <= (others => '0');
r_n.crc32 <= newcrc32_d64(v_TxD, r.crc32);
if r.count < 8-CMD_HEADER_LEN-1 then
r_n.count <= r.count + 1;
else
r_n.count <= 0;
r_n.word <= 0;
r_n.mem_addr <= (others => '0');
c.mem_addr <= (others => '0');
r_n.state <= WST_SEND_CRC_AND_EOF;
end if;
when WST_SEND_HEADER =>
v_TxD := select_8bytes(s_header, r.count);
c.TxD <= v_TxD;
c.TxC <= (others => '0');
r_n.crc32 <= newcrc32_d64(v_TxD, r.crc32);
if r.count < HEADER_LEN-1 then
r_n.count <= r.count + 1;
else
r_n.count <= 0;
r_n.word <= 0;
r_n.mem_addr <= (others => '0');
c.mem_addr <= (others => '0');
r_n.state <= WST_SEND_DATA;
end if;
when WST_SEND_DATA =>
-- send the data byte by byte
v_TxD := select_8bytes(tx_mem_data, 0);
r_n.crc32 <= newcrc32_d64(v_TxD, r.crc32);
c.TxD <= v_TxD;
c.TxC <= (others => '0');
-- Check, if we have sent all the data
if r.mem_addr < NWRDS_IN_PKT-1 then
r_n.mem_addr <= r.mem_addr + 1;
c.mem_addr <= r.mem_addr + 1;
else
-- We send the CRC
r_n.state <= WST_SEND_CRC_AND_EOF;
end if;
when WST_SEND_CRC_AND_EOF =>
-- The CRC should be send starting from the most significant bit, so
-- we don't need to reorder bytes in any way...
-- we only reverse it and complement it
v_TxD := x"07_07_07_fd" & not (rev(r.crc32));
c.TxD <= v_TxD;
c.TxC <= "11110000";
r_n.count <= 2; -- generate the IFG - 16 bytes = 2 words
r_n.state <= WST_SEND_COMPLETED;
when WST_SEND_COMPLETED =>
c.TxD <= x"07_07_07_07_07_07_07_07";
c.TxC <= "11111111";
if r.count > 0 then
r_n.count <= r.count - 1;
else
r_n.ready <= '1';
r_n.state <= WST_IDLE;
end if;
end case;
end process snd2;
 
 
-- Synchronization of the reset signal for the Tx_Clk domain
process (Tx_Clk, rst_n)
begin -- process
if rst_n = '0' then -- asynchronous reset (active low)
tx_rst_n_0 <= '0';
tx_rst_n_1 <= '0';
tx_rst_n <= '0';
elsif Tx_Clk'event and Tx_Clk = '1' then -- rising clock edge
tx_rst_n_0 <= rst_n;
tx_rst_n_1 <= tx_rst_n_0;
tx_rst_n <= tx_rst_n_1;
end if;
end process;
 
-- Synchronization of signals passing clock domains
-- Signal start is sent from the Clk domain.
-- When it is asserted, we must immediately deassert signal ready,
-- then generate the synchronized start and after internal ready
-- is asserted, we can output it again...
 
-- Ustawienie na 1 takt zegara "clk" sygnalu start powinno zainicjowac wysylanie
-- w tym bloku musimy zadbac o stosowne wydluzenie sygnalu start i jego synchronizacje
-- miedzy domenami zegara...
process (clk, rst_n)
begin -- process
if rst_n = '0' then -- asynchronous reset (active low)
ready <= '0';
ready_1 <= '0';
ready_0 <= '0';
cmd_only <= '0';
state2 <= ST2_IDLE;
elsif clk'event and clk = '1' then -- rising clock edge
ready_1 <= tx_ready;
ready_0 <= ready_1;
case state2 is
when ST2_IDLE =>
if start = '1' and ready_0 = '1' then
start_0 <= '1';
ready <= '0';
cmd_only <= '0';
state2 <= ST2_WAIT_NOT_READY;
elsif cmd_start = '1' and ready_0 = '1' then
start_0 <= '1';
ready <= '0';
cmd_only <= '1';
state2 <= ST2_WAIT_NOT_READY;
else
ready <= ready_0; -- Needed to provide correct start!
end if;
when ST2_WAIT_NOT_READY =>
if ready_0 = '0' then
start_0 <= '0';
state2 <= ST2_WAIT_READY;
end if;
when ST2_WAIT_READY =>
if ready_0 = '1' then
ready <= '1';
state2 <= ST2_IDLE;
end if;
when others => null;
end case;
end if;
end process;
 
process (Tx_Clk, tx_rst_n)
begin -- process
if tx_rst_n = '0' then -- asynchronous reset (active low)
tx_start <= '0';
tx_start_0 <= '0';
state1 <= ST1_IDLE;
tx_ready <= '1';
elsif Tx_Clk'event and Tx_Clk = '1' then -- rising clock edge
tx_start_0 <= start_0;
tx_start <= tx_start_0;
case state1 is
when ST1_IDLE =>
if tx_start = '1' then
tx_ready <= '0'; -- this should cause tx_start to go low
state1 <= ST1_WAIT_NOT_READY;
end if;
when ST1_WAIT_NOT_READY =>
if r.ready = '0' then
state1 <= ST1_WAIT_NOT_START;
end if;
when ST1_WAIT_NOT_START =>
if tx_start = '0' then
state1 <= ST1_WAIT_READY;
end if;
when ST1_WAIT_READY =>
if r.ready = '1' then
tx_ready <= '1';
state1 <= ST1_IDLE;
end if;
when others => null;
end case;
end if;
end process;
end beh1;
/trunk/stable_jumbo_frames_version/fpga/src/kc705/main.eprj
0,0 → 1,7
vhdl work kc705_fade_top.vhd
xci work ack_fifo/ack_fifo.xci
xci work ila_1/ila_1.xci
xci work ten_gig_eth/ten_gig_eth_pcs_pma_0.xci
xdc wzconstr.xdc
 
 
/trunk/stable_jumbo_frames_version/fpga/src/kc705.eprj
0,0 → 1,2
include common.eprj
include kc705/main.eprj
/trunk/stable_jumbo_frames_version/fpga/vextproj/eprj_build.tcl
0,0 → 1,36
open_project $eprj_proj_name/$eprj_proj_name.xpr
# set the current synth run
current_run -synthesis [get_runs synth_1]
# set the current impl run
current_run -implementation [get_runs impl_1]
puts "INFO: Project loaded:$eprj_proj_name"
reset_run synth_1
# Two lines below are the workaround for the problem reported here:
# https://forums.xilinx.com/t5/Synthesis/Vivado-incorrect-automatic-compilation-order-in-OOC-synthesis/td-p/698067
# In fact there should be the list of the OOC runs created by the eprj_create.tcl
# script. At the moment this list must be read from the file "ooc_synth_runs.txt"
# created by the eprj_create.tcl
set file_ooc_runs [open "ooc_synth_runs.txt" "r"]
set ooc_runs [read $file_ooc_runs]
close $file_ooc_runs
 
if [expr [llength $ooc_runs] > 0] {
foreach { run } $ooc_runs {
reset_run $run
}
launch_runs $ooc_runs -jobs 4
launch_runs synth_1 -scripts_only
foreach { run } $ooc_runs {
set_property NEEDS_REFRESH 0 [get_runs $run]
}
reset_run synth_1
}
# End of workaround
launch_runs synth_1 -jobs 4
wait_on_run synth_1
reset_run impl_1
launch_runs impl_1 -jobs 4
wait_on_run impl_1
launch_runs impl_1 -to_step write_bitstream
wait_on_run impl_1
puts "INFO: Project compiled:$eprj_proj_name"
/trunk/stable_jumbo_frames_version/fpga/vextproj/eprj_create.tcl
0,0 → 1,525
# Script prepared by Wojciech M. Zabolotny (wzab<at>ise.pw.edu.pl) to
# create a Vivado project from the hierarchical list of files
# (extended project files).
# This file is published as PUBLIC DOMAIN
#
# Set the reference directory for source file relative paths (by default the value is script directory path)
set origin_dir "."
 
# Check the Vivado version
set viv_version [ version -short ]
set ver_cmp_res [ string compare $viv_version $eprj_vivado_version ]
if { $eprj_vivado_version_allow_upgrade } {
if [ expr $ver_cmp_res < 0 ] {
error "Wrong Vivado version. Expected: $eprj_vivado_version or higher, found $viv_version"
}
} else {
if [ expr $ver_cmp_res != 0 ] {
error "Wrong Vivado version. Expected: $eprj_vivado_version , found $viv_version"
}
}
# Create project
create_project $eprj_proj_name ./$eprj_proj_name
 
# Set the directory path for the new project
set proj_dir [get_property directory [current_project]]
 
# Set project properties
set obj [get_projects $eprj_proj_name]
set_property "board_part" $eprj_board_part $obj
set_property "part" $eprj_part $obj
set_property "default_lib" $eprj_default_lib $obj
set_property "simulator_language" $eprj_simulator_language $obj
set_property "target_language" $eprj_target_language $obj
 
# Create the global variable which will keep the list of the OOC synthesis runs
global vextproj_ooc_synth_runs
set vextproj_ooc_synth_runs [list ]
 
# The procedure below changes the library "work" to "xil_defaultlib"
# to avoid problems with simulation in Vivado
# (see https://forums.xilinx.com/t5/Simulation-and-Verification/ERROR-XSIM-43-3225-Cannot-find-design-unit-xil-defaultlib-glbl/m-p/703641 )
proc fix_library { lib } {
global eprj_default_lib
if [ string match $eprj_default_lib "xil_defaultlib"] {
if [ string match "work" $lib ] {
set lib "xil_defaultlib"
}
}
return $lib
}
 
# The project reading procedure operates on objects storing the files
proc eprj_create_block {ablock mode setname } {
upvar $ablock block
#Set the last file_obj initially to "none"
set block(last_file_obj) "error"
#Set the mode of the block
#may be either IC - in context or OOC - out of context
set block(mode) $mode
if [string match -nocase $mode "IC"] {
# Create 'sources_1' fileset (if not found)
if {[string equal [get_filesets -quiet sources_1] ""]} {
create_fileset -srcset sources_1
}
set block(srcset) [get_filesets sources_1]
# Create 'constrs_1' fileset (if not found)
if {[string equal [get_filesets -quiet constrs_1] ""]} {
create_fileset -constrset constrs_1
}
set block(cnstrset) [get_filesets constrs_1]
} elseif [string match -nocase $mode "OOC"] {
# We create only a single blkset
# Create 'setname' fileset (if not found)
if {[string equal [get_filesets -quiet $setname] ""]} {
create_fileset -blockset $setname
}
# Both constraints and XDC should be added to the same set
set block(srcset) [get_filesets $setname]
set block(cnstrset) [get_filesets $setname]
} else {
eprj_error block "The block mode must be either IC - in context, or OOC - out of context. The $mode value is unacceptable"
}
}
 
#Add file to the sources fileset
proc add_file_sources {ablock args pdir fname} {
upvar $ablock block
set nfile [file normalize "$pdir/$fname"]
if {! [file exists $nfile]} {
eprj_error block "Requested file $nfile is not available!"
}
add_files -norecurse -fileset $block(srcset) $nfile
set file_obj [get_files -of_objects $block(srcset) $nfile]
set block(last_file_obj) $file_obj
#Check if the arguments contain "sim" and set the "simulation" properties if necessary
if [expr [lsearch $args "sim"] >= 0] {
set_property "used_in" "simulation" $file_obj
set_property "used_in_synthesis" "0" $file_obj
}
return $file_obj
}
 
proc handle_xci {ablock args pdir line} {
upvar $ablock block
#Handle XCI file
lassign $line lib fname
set file_obj [add_file_sources block $args $pdir $fname]
#set_property "synth_checkpoint_mode" "Singular" $file_obj
set_property "library" [ fix_library $lib ] $file_obj
}
 
proc handle_xcix {ablock args pdir line} {
upvar $ablock block
#Handle XCIX file
lassign $line lib fname
set file_obj [add_file_sources block $args $pdir $fname]
#set_property "synth_checkpoint_mode" "Singular" $file_obj
set_property "library" [ fix_library $lib ] $file_obj
export_ip_user_files -of_objects $file_obj -force -quiet
}
 
proc handle_vhdl {ablock args pdir line} {
upvar $ablock block
#Handle VHDL file
lassign $line lib fname
set file_obj [add_file_sources block $args $pdir $fname]
set_property "file_type" "VHDL" $file_obj
set_property "library" [ fix_library $lib ] $file_obj
}
 
proc handle_verilog {ablock args pdir line} {
upvar $ablock block
#Handle Verilog file
lassign $line fname
set file_obj [add_file_sources block $args $pdir $fname]
set_property "file_type" "Verilog" $file_obj
}
 
proc handle_sys_verilog {ablock args pdir line} {
upvar $ablock block
#Handle SystemVerilog file
lassign $line fname
set file_obj [add_file_sources block $args $pdir $fname]
set_property "file_type" "SystemVerilog" $file_obj
}
 
proc handle_verilog_header {ablock args pdir line} {
upvar $ablock block
#Handle SystemVerilog file
lassign $line fname
set file_obj [add_file_sources block $args $pdir $fname]
set_property "file_type" "Verilog Header" $file_obj
}
 
proc handle_global_verilog_header {ablock args pdir line} {
upvar $ablock block
#Handle Global Verilog Header file
lassign $line fname
set file_obj [add_file_sources block $args $pdir $fname]
set_property "file_type" "Verilog Header" $file_obj
set_property is_global_include true $file_obj
}
 
proc handle_bd {ablock args pdir line} {
upvar $ablock block
#Handle BD file
lassign $line fname
set file_obj [add_file_sources block $args $pdir $fname]
if { ![get_property "is_locked" $file_obj] } {
set_property "generate_synth_checkpoint" "0" $file_obj
}
}
 
proc handle_mif {ablock args pdir line} {
upvar $ablock block
#Handle MIF file
lassign $line lib fname
set file_obj [add_file_sources block $args $pdir $fname]
set_property "file_type" "Memory Initialization Files" $file_obj
set_property "library" [ fix_library $lib ] $file_obj
#set_property "synth_checkpoint_mode" "Singular" $file_obj
}
 
proc handle_xdc {ablock args pdir line} {
upvar $ablock block
#Handle XDC file
lassign $line fname
set nfile [file normalize "$pdir/$fname"]
if {![file exists $nfile]} {
eprj_error block "Requested file $nfile is not available!"
}
add_files -norecurse -fileset $block(cnstrset) $nfile
set file_obj [get_files -of_objects $block(cnstrset) $nfile]
set_property "file_type" "XDC" $file_obj
}
 
proc handle_xdc_ooc {ablock args pdir line} {
upvar $ablock block
#Handle XDC_OOC file
lassign $line fname
set nfile [file normalize "$pdir/$fname"]
if {![file exists $nfile]} {
eprj_error block "Requested file $nfile is not available!"
}
if {![string match -nocase $block(mode) "OOC"]} {
puts "Ignored file $nfile in IC mode"
#Clear "last file object" in the block array
set block(last_file_obj) "none"
} else {
add_files -norecurse -fileset $block(cnstrset) $nfile
set file_obj [get_files -of_objects $block(cnstrset) $nfile]
set_property "file_type" "XDC" $file_obj
set_property USED_IN {out_of_context synthesis implementation} $file_obj
}
}
 
proc handle_prop {ablock args pdir line} {
upvar $ablock block
if [string match $block(last_file_obj) "error"] {
eprj_error block "I don't know to which file apply the property $line"
} elseif [string match $block(last_file_obj) "none"] {
puts "Property ignored $line"
} else {
lassign $line property value
set_property $property $value $block(last_file_obj)
}
}
 
proc handle_propadd {ablock args pdir line} {
upvar $ablock block
if [string match $block(last_file_obj) "error"] {
eprj_error block "I don't know to which file apply the property $line"
} elseif [string match $block(last_file_obj) "none"] {
puts "Property ignored $line"
} else {
lassign $line property value
set old_val [ get_property $property $block(last_file_obj) ]
lappend old_val $value
set_property $property $old_val $block(last_file_obj)
}
}
 
proc handle_exec {ablock args pdir line} {
upvar $ablock block
#Handle EXEC line
lassign $line fname
set nfile [file normalize "$pdir/$fname"]
if {![file exists $nfile]} {
eprj_error block "Requested file $nfile is not available!"
}
#Execute the program in its directory
set old_dir [ pwd ]
cd $pdir
exec "./$fname"
cd $old_dir
}
 
# Handlers for VCS systems
proc handle_git_local {ablock args pdir line} {
upvar $ablock block
lassign $line clone_dir commit_or_tag_id exported_dir strip_num
set old_dir [ pwd ]
cd $pdir
file delete -force -- "ext_src"
file mkdir "ext_src"
#Prepare the git command
set strip_cmd ""
if { $strip_num ne ""} {
append strip_cmd " --strip-components=$strip_num"
}
set git_cmd "( cd $clone_dir ; git archive --format tar $commit_or_tag_id $exported_dir ) | ( cd ext_src ; tar -xf - $strip_cmd )"
exec bash -c "$git_cmd"
cd $old_dir
}
 
proc handle_git_remote {ablock args pdir line} {
upvar $ablock block
lassign $line repository_url tag_id exported_dir strip_num
set old_dir [ pwd ]
cd $pdir
file delete -force -- "ext_src"
file mkdir "ext_src"
#Prepare the git command
set strip_cmd ""
if { $strip_num ne ""} {
append strip_cmd " --strip-components=$strip_num"
}
set git_cmd "( git archive --format tar --remote $repository_url $tag_id $exported_dir ) | ( cd ext_src ; tar -xf - $strip_cmd )"
exec bash -c "$git_cmd"
cd $old_dir
}
 
proc handle_svn {ablock args pdir line} {
upvar $ablock block
lassign $line repository_with_path revision
set old_dir [ pwd ]
cd $pdir
file delete -force -- "ext_src"
file mkdir "ext_src"
#Prepare the SVN command
set rev_cmd ""
if { $revision ne ""} {
append rev_cmd " -r $revision"
}
set svn_cmd "( cd ext_src ; svn export $rev_cmd $repository_with_path )"
exec bash -c "$svn_cmd"
cd $old_dir
}
 
#Procedure exctracting the args from the text: "type[arg1,arg2,arg3]"
#Returns the two-element list {type args}, where args is the list" {arg1 arg2 arg3}
proc type_parse_args { type_args } {
regexp {([^\[]*)(\[(.*)\])*} $type_args whole_type type arg_part arg_list
if [string match arg_list ""] {
set args {}
} else {
set args [split $arg_list ","]
}
return [list $type $args]
}
 
 
# Array with line handlers, used by the line handling procedure
array set line_handlers {
xci handle_xci
xcix handle_xcix
header handle_verilog_header
global_header handle_global_verilog_header
sys_verilog handle_sys_verilog
verilog handle_verilog
mif handle_mif
bd handle_bd
vhdl handle_vhdl
prop handle_prop
propadd handle_propadd
ooc handle_ooc
xdc handle_xdc
xdc_ooc handle_xdc_ooc
exec handle_exec
git_local handle_git_local
git_remote handle_git_remote
svn handle_svn
}
 
#Line handling procedure
proc handle_line { ablock pdir line } {
upvar $ablock block
global line_handlers
set rest [lassign $line type_args]
#First we attempt to separate possible arguments from type
lassign [type_parse_args $type_args] type args
#Find the procedure to be called depending on the type of the line
set ptc [lindex [array get line_handlers [string tolower $type]] 1]
if [ string equal $ptc "" ] {
eprj_error block "Unknown line of type: $type"
} else {
$ptc block $args $pdir $rest
}
}
 
proc handle_ooc { ablock args pdir line } {
global eprj_impl_strategy
global eprj_impl_flow
global eprj_synth_strategy
global eprj_synth_flow
global eprj_flow
global eprj_part
global vextproj_ooc_synth_runs
 
upvar $ablock block
#The OOC blocks can't be nested
#detect the attempt to nest the block and return an error
if {[string match -nocase $block(mode) "OOC"]} {
eprj_error block "The OOC blocks can't be nested: $line"
}
lassign $line stub fname blksetname
#Create the new block of type OOC and continue parsing in it
array set ooc_block {}
eprj_create_block ooc_block "OOC" $blksetname
if {[string match -nocase $stub "noauto"]} {
set_property "use_blackbox_stub" "0" [get_filesets $blksetname]
} elseif {![string match -nocase $stub "auto"]} {
eprj_error block "OOC stub creation mode must be either 'auto' or 'noauto' not: $stub"
}
read_prj ooc_block $pdir/$fname
set_property TOP $blksetname [get_filesets $blksetname]
update_compile_order -fileset $blksetname
#Create synthesis run for the blockset (if not found)
set ooc_synth_run_name ${blksetname}_synth_1
if {[string equal [get_runs -quiet ${ooc_synth_run_name}] ""]} {
create_run -name ${ooc_synth_run_name} -part $eprj_part -flow {$eprj_flow} -strategy $eprj_synth_strategy -constrset $blksetname
} else {
set_property strategy $eprj_synth_strategy [get_runs ${ooc_synth_run_name}]
set_property flow $eprj_synth_flow [get_runs ${ooc_synth_run_name}]
}
lappend vextproj_ooc_synth_runs ${ooc_synth_run_name}
set_property constrset $blksetname [get_runs ${ooc_synth_run_name}]
set_property part $eprj_part [get_runs ${ooc_synth_run_name}]
# Create implementation run for the blockset (if not found)
set ooc_impl_run_name ${blksetname}_impl_1
if {[string equal [get_runs -quiet ${ooc_impl_run_name}] ""]} {
create_run -name impl_1 -part $eprj_part -flow {$eprj_flow} -strategy $eprj_impl_strategy -constrset $blksetname -parent_run ${ooc_synth_run_name}
} else {
set_property strategy $eprj_impl_strategy [get_runs ${ooc_impl_run_name}]
set_property flow $eprj_impl_flow [get_runs ${ooc_impl_run_name}]
}
set_property constrset $blksetname [get_runs ${ooc_impl_run_name}]
set_property part $eprj_part [get_runs ${ooc_impl_run_name}]
set_property include_in_archive "0" [get_runs ${ooc_impl_run_name}]
}
 
# Prepare the main block
array set main_block {}
eprj_create_block main_block "IC" ""
 
# Procedure reporting the errors
proc eprj_error { ablock message } {
upvar $ablock block
puts "ERROR in file: $block(file_name), line: $block(line_count)"
error $message
}
 
# Procedure below reads the source files from PRJ files, extended with
# the "include file" statement
#Important thing - path to the source files should be given relatively
#to the location of the PRJ file.
proc read_prj { ablock prj } {
upvar $ablock block
#parray block
#Clear information about the "last file_obj" to avoid wrong assignment of properties
set block(last_file_obj) "error"
#allow to use just the directory names. In this case add
#the "/main.eprj" to it
if {[file isdirectory $prj]} {
append prj "/main.eprj"
puts "Added default main.eprj to the directory name: $prj"
}
if {[file exists $prj]} {
puts "\tReading PRJ file: $prj"
set source [open $prj r]
set source_data [read $source]
close $source
#Extract the directory of the PRJ file, as all paths to the
#source files must be given relatively to that directory
set prj_dir [ file dirname $prj ]
regsub -all {\"} $source_data {} source_data
set prj_lines [split $source_data "\n" ]
#Set line counter and file name for error reporting function
set block(line_count) 0
set block(file_name) $prj
foreach line $prj_lines {
incr block(line_count)
#Ignore empty and commented lines
if {[llength $line] > 0 && ![string match -nocase "#*" $line]} {
#Detect the inlude line and ooc line
lassign $line type fname
if {[string match -nocase $type "include"]} {
puts "\tIncluding PRJ file: $prj_dir/$fname"
read_prj block $prj_dir/$fname
# Clear information about the last file_obj to avoid wrong assignment of properties
set block(last_file_obj) "error"
} else {
handle_line block $prj_dir $line
}
}
}
} else {
eprj_error block "Requested file $prj is not available!"
}
}
 
 
# Read project definitions
set main_block(file_name) ""
set main_block(line_count) 0
read_prj main_block $eprj_def_root
 
set_property "top" $eprj_top_entity $main_block(srcset)
update_compile_order -fileset sources_1
# Create 'synth_1' run (if not found)
if {[string equal [get_runs -quiet synth_1] ""]} {
create_run -name synth_1 -part $eprj_part -flow {$eprj_flow} -strategy $eprj_synth_strategy -constrset constrs_1
} else {
set_property strategy $eprj_synth_strategy [get_runs synth_1]
set_property flow $eprj_synth_flow [get_runs synth_1]
}
set obj [get_runs synth_1]
 
# set the current synth run
current_run -synthesis [get_runs synth_1]
 
# Create 'impl_1' run (if not found)
if {[string equal [get_runs -quiet impl_1] ""]} {
create_run -name impl_1 -part $eprj_part -flow {$eprj_flow} -strategy $eprj_impl_strategy -constrset constrs_1 -parent_run synth_1
} else {
set_property strategy $eprj_impl_strategy [get_runs impl_1]
set_property flow $eprj_impl_flow [get_runs impl_1]
}
set obj [get_runs impl_1]
 
# set the current impl run
current_run -implementation [get_runs impl_1]
 
# Write the list of the OOC synthesis runs to the file
set file_ooc_runs [open "ooc_synth_runs.txt" "w"]
puts $file_ooc_runs $vextproj_ooc_synth_runs
close $file_ooc_runs
 
puts "INFO: Project created:$eprj_proj_name"
 
# Create the Tcl file with the initial state of the project
# In theory it should be enough to write it now:
# write_project_tcl -force -no_copy_sources {initial_state.tcl}
# But unfortunately it will differ significantly from the Tcl file created after opening of the saved
# XPR file.
# Therefore we delegate it to the another script...
 
#launch_runs synth_1
#wait_on_run synth_1
#launch_runs impl_1
#wait_on_run impl_1
#launch_runs impl_1 -to_step write_bitstream
#wait_on_run impl_1
 
/trunk/stable_jumbo_frames_version/fpga/vextproj/eprj_write.tcl
0,0 → 1,9
# This script creates the project Tcl file.
# To keep it as similar as possible to the one created from GUI
# we change directory first
set old_dir [ pwd ]
cd ${eprj_proj_name}
open_project ./${eprj_proj_name}.xpr
write_project_tcl -force -no_copy_sources {initial_state.tcl}
puts "INFO: Project $eprj_proj_name written to the initial_state.tcl file"
cd $old_dir

powered by: WebSVN 2.1.0

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