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 |