Commit 5d7ff8ee authored by Martin Jeřábek's avatar Martin Jeřábek

vivado IP component (WIP)

parent 1109adfb
......@@ -2,7 +2,7 @@ library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity myip_v1_0_S00_AXI is
entity axi_ifc is
generic (
-- Users to add parameters here
......@@ -12,14 +12,16 @@ entity myip_v1_0_S00_AXI is
-- Width of S_AXI data bus
C_S_AXI_DATA_WIDTH : integer := 32;
-- Width of S_AXI address bus
C_S_AXI_ADDR_WIDTH : integer := 8
C_S_AXI_ADDR_WIDTH : integer := 24
);
port (
-- Users to add ports here
reg_data_in_o : out std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
reg_data_out_i : in std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
reg_addr_o : out std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
reg_addr_o : out std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0);
reg_be_o : out std_logic_vector((C_S_AXI_DATA_WIDTH/8)-1 downto 0);
reg_rden_o : out std_logic;
reg_wren_o : out std_logic;
-- User ports ends
-- Do not modify the ports beyond this line
......@@ -84,9 +86,9 @@ entity myip_v1_0_S00_AXI is
-- accept the read data and response information.
S_AXI_RREADY : in std_logic
);
end myip_v1_0_S00_AXI;
end entity axi_ifc;
architecture arch_imp of myip_v1_0_S00_AXI is
architecture rtl of axi_ifc is
-- AXI4LITE signals
signal axi_awaddr : std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0);
......@@ -100,201 +102,33 @@ architecture arch_imp of myip_v1_0_S00_AXI is
signal axi_rresp : std_logic_vector(1 downto 0);
signal axi_rvalid : std_logic;
-- Example-specific design signals
-- local parameter for addressing 32 bit / 64 bit C_S_AXI_DATA_WIDTH
-- ADDR_LSB is used for addressing 32/64 bit registers/memories
-- ADDR_LSB = 2 for 32 bits (n downto 2)
-- ADDR_LSB = 3 for 64 bits (n downto 3)
constant ADDR_LSB : integer := (C_S_AXI_DATA_WIDTH/32)+ 1;
constant OPT_MEM_ADDR_BITS : integer := 4;
------------------------------------------------
---- Signals for user logic register space example
--------------------------------------------------
signal slv_reg_rden : std_logic;
signal slv_reg_wren : std_logic;
signal reg_data_out :std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
signal byte_index : integer;
signal aw_en : std_logic;
signal want_to_read : std_logic;
signal want_to_write : std_logic;
signal want_to_write_q : std_logic;
signal reg_addr_or : std_logic;
signal write_precedence_set, write_precedence, write_precedence_r : std_logic;
begin
-- I/O Connections assignments
S_AXI_AWREADY <= axi_awready;
S_AXI_AWREADY <= axi_awready;
S_AXI_WREADY <= axi_wready;
S_AXI_BRESP <= axi_bresp;
S_AXI_BRESP <= axi_bresp;
S_AXI_BVALID <= axi_bvalid;
S_AXI_ARREADY <= axi_arready;
S_AXI_RDATA <= axi_rdata;
S_AXI_RRESP <= axi_rresp;
S_AXI_ARREADY <= axi_arready;
S_AXI_RDATA <= axi_rdata;
S_AXI_RRESP <= axi_rresp;
S_AXI_RVALID <= axi_rvalid;
-- Implement axi_awready & axi_awready generation
-- axi_(a)wready is asserted for one S_AXI_ACLK clock cycle when both
-- S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_awready is
-- de-asserted when reset is low.
process (S_AXI_ACLK)
begin
if rising_edge(S_AXI_ACLK) then
if S_AXI_ARESETN = '0' then
axi_awready <= '0';
aw_en <= '1';
else
if (axi_awready = '0' and S_AXI_AWVALID = '1' and S_AXI_WVALID = '1' and aw_en = '1') then
-- slave is ready to accept write address/data when
-- there is a valid write address and write data
-- on the write address and data bus. This design
-- expects no outstanding transactions.
axi_awready <= '1';
axi_wready <= '1';
elsif (S_AXI_BREADY = '1' and axi_bvalid = '1') then
aw_en <= '1';
axi_awready <= '0';
axi_wready <= '0';
else
axi_awready <= '0';
axi_wready <= '0';
end if;
end if;
end if;
end process;
-- Implement axi_awaddr latching
-- This process is used to latch the address when both
-- S_AXI_AWVALID and S_AXI_WVALID are valid.
process (S_AXI_ACLK)
begin
if rising_edge(S_AXI_ACLK) then
if S_AXI_ARESETN = '0' then
axi_awaddr <= (others => '0');
else
if (axi_awready = '0' and S_AXI_AWVALID = '1' and S_AXI_WVALID = '1' and aw_en = '1') then
-- Write Address latching
axi_awaddr <= S_AXI_AWADDR;
end if;
end if;
end if;
end process;
-- Implement memory mapped register select and write logic generation
-- The write data is accepted and written to memory mapped registers when
-- axi_awready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted. Write strobes are used to
-- select byte enables of slave registers while writing.
-- These registers are cleared when reset (active low) is applied.
-- Slave register write enable is asserted when valid address and data are available
-- and the slave is ready to accept the write address and write data.
slv_reg_wren <= axi_wready and S_AXI_WVALID and axi_awready and S_AXI_AWVALID ;
-- Implement write response logic generation
-- The write response and response valid signals are asserted by the slave
-- when axi_wready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted.
-- This marks the acceptance of address and indicates the status of
-- write transaction.
process (S_AXI_ACLK)
begin
if rising_edge(S_AXI_ACLK) then
if S_AXI_ARESETN = '0' then
axi_bvalid <= '0';
axi_bresp <= "00"; --need to work more on the responses
else
if (axi_awready = '1' and S_AXI_AWVALID = '1' and axi_wready = '1' and S_AXI_WVALID = '1' and axi_bvalid = '0' ) then
axi_bvalid <= '1';
axi_bresp <= "00";
elsif (S_AXI_BREADY = '1' and axi_bvalid = '1') then --check if bready is asserted while bvalid is high)
axi_bvalid <= '0'; -- (there is a possibility that bready is always asserted high)
end if;
end if;
end if;
end process;
-- Implement axi_arready generation
-- axi_arready is asserted for one S_AXI_ACLK clock cycle when
-- S_AXI_ARVALID is asserted. axi_awready is
-- de-asserted when reset (active low) is asserted.
-- The read address is also latched when S_AXI_ARVALID is
-- asserted. axi_araddr is reset to zero on reset assertion.
process (S_AXI_ACLK)
begin
if rising_edge(S_AXI_ACLK) then
if S_AXI_ARESETN = '0' then
axi_arready <= '0';
axi_araddr <= (others => '1');
else
if (axi_arready = '0' and S_AXI_ARVALID = '1') then
-- indicates that the slave has acceped the valid read address
axi_arready <= '1';
-- Read Address latching
axi_araddr <= S_AXI_ARADDR;
else
axi_arready <= '0';
end if;
end if;
end if;
end process;
-- Implement axi_arvalid generation
-- axi_rvalid is asserted for one S_AXI_ACLK clock cycle when both
-- S_AXI_ARVALID and axi_arready are asserted. The slave registers
-- data are available on the axi_rdata bus at this instance. The
-- assertion of axi_rvalid marks the validity of read data on the
-- bus and axi_rresp indicates the status of read transaction.axi_rvalid
-- is deasserted on reset (active low). axi_rresp and axi_rdata are
-- cleared to zero on reset (active low).
process (S_AXI_ACLK)
begin
if rising_edge(S_AXI_ACLK) then
if S_AXI_ARESETN = '0' then
axi_rvalid <= '0';
axi_rresp <= "00";
else
if (axi_arready = '1' and S_AXI_ARVALID = '1' and axi_rvalid = '0') then
-- Valid read data is available at the read data bus
axi_rvalid <= '1';
axi_rresp <= "00"; -- 'OKAY' response
elsif (axi_rvalid = '1' and S_AXI_RREADY = '1') then
-- Read data is accepted by the master
axi_rvalid <= '0';
end if;
end if;
end if;
end process;
--slv_reg_wren <= want_to_write and (not want_to_read or write_precedence);
--slv_reg_rden <= want_to_read and not write_precedence;
-- Implement memory mapped register select and read logic generation
-- Slave register read enable is asserted when valid address is available
-- and the slave is ready to accept the read address.
slv_reg_rden <= axi_arready and S_AXI_ARVALID and (not axi_rvalid) ;
-- Output register or memory read data
process( S_AXI_ACLK ) is
begin
if (rising_edge (S_AXI_ACLK)) then
if ( S_AXI_ARESETN = '0' ) then
axi_rdata <= (others => '0');
else
if (slv_reg_rden = '1') then
-- When there is a valid read address (S_AXI_ARVALID) with
-- acceptance of read address by the slave (axi_arready),
-- output the read dada
-- Read address mux
axi_rdata <= reg_data_out; -- register read data
end if;
end if;
end if;
end process;
-- Add user logic here
reg_data_out <= reg_data_out_i;
reg_data_in_o <= S_AXI_WDATA;
S_AXI_RDATA <= reg_data_out_i;
-- arbitrate
want_to_write <= S_AXI_WVALID and S_AXI_AWVALID and S_AXI_BREADY;
-- "the slave must not wait for the master to assert BREADY before asserting BVALID"!
want_to_write <= S_AXI_WVALID and S_AXI_AWVALID;
want_to_read <= S_AXI_RREADY and S_AXI_ARVALID;
process
......@@ -306,38 +140,63 @@ begin
end if;
end process;
write_precedence_set <= want_to_write and not want_to_write_q;
write_precedence <= write_precedence_set or write_precedence_r;
process
variable write_precedence : std_logic;
begin
if (S_AXI_ARESETN = '0') then
write_precedence := '0';
write_precedence_r <= '0';
reg_addr_o <= (others => '0');
reg_be_o <= (others => '0');
reg_rden_o <= '0';
reg_wren_o <= '0';
axi_arready <= '0';
axi_rvalid <= '0';
axi_awready <= '0';
axi_wready <= '0';
axi_bvalid <= '0';
axi_bresp <= "00";
elsif (rising_edge(S_AXI_ACLK)) then
if (want_to_write and not want_to_write_q) then
write_precedence := not want_to_read;
if (want_to_write = '1' and want_to_write_q = '0') then
write_precedence_r <= not want_to_read;
end if;
if (not write_precedence and want_to_read) then
if (write_precedence = '0' and want_to_read = '1') then
reg_addr_o <= S_AXI_ARADDR;
reg_be_o <= (others => '1');
slv_reg_rden <= '1';
elsif (want_to_write) then
reg_rden_o <= '1';
axi_arready <= '1';
axi_rvalid <= '1';
elsif (want_to_write = '1') then
reg_addr_o <= S_AXI_AWADDR;
reg_be_o <= S_AXI_WSTRB;
slv_reg_wren <= '1';
reg_wren_o <= '1';
axi_awready <= '1';
axi_wready <= '1';
axi_bvalid <= '1';
axi_bresp <= "00"; -- OK
write_precedence_r <= '0';
end if;
-- pull it back down next cycle
if (slv_reg_rden) then
slv_reg_rden <= '0';
if (axi_bvalid = '1' and S_AXI_BREADY = '1') then
axi_awready <= '0';
axi_wready <= '0';
axi_bvalid <= '0';
reg_wren_o <= '0';
end if;
if (slv_reg_wren) then
slv_reg_wren <= '0';
if (axi_rvalid = '1' and S_AXI_RREADY = '1') then
axi_rvalid <= '0';
axi_arready <= '0';
reg_rden_o <= '0';
-- TODO: waitcycle?
end if;
end if;
end process;
--TODOTODOTODOTODOTODOTODOTODOTODO
-- edge on (S_AXI_WVALID and S_AXI_AWVALID and S_AXI_BREADY) -> want to write; write_precedence := not want_to_read
-- edge on (S_AXI_RREDY and S_AXI_ARVALID) -> want to read
......@@ -348,4 +207,4 @@ begin
-- User logic ends
end arch_imp;
end architecture rtl;
library ieee;
use ieee.std_logic_1164.all;
entity CTU_CAN_FD_v1_0 is
generic(
use_logger : boolean := true;
rx_buffer_size : natural range 4 to 512 := 128;
use_sync : boolean := true;
sup_filtA : boolean := true;
sup_filtB : boolean := true;
sup_filtC : boolean := true;
sup_range : boolean := true;
tx_time_sup : boolean := true;
sup_be : boolean := true;
logger_size : natural range 0 to 512 := 8
);
port(
-- system clock and reset from AXI
int : out std_logic;
CAN_tx : out std_logic;
CAN_rx : in std_logic;
time_quanta_clk : out std_logic;
timestamp : in std_logic_vector(63 downto 0);
-- Ports of Axi Slave Bus Interface S00_AXI
s00_axi_aclk : in std_logic;
s00_axi_aresetn : in std_logic;
s00_axi_awaddr : in std_logic_vector(23 downto 0);
s00_axi_awprot : in std_logic_vector(2 downto 0);
s00_axi_awvalid : in std_logic;
s00_axi_awready : out std_logic;
s00_axi_wdata : in std_logic_vector(31 downto 0);
s00_axi_wstrb : in std_logic_vector(3 downto 0);
s00_axi_wvalid : in std_logic;
s00_axi_wready : out std_logic;
s00_axi_bresp : out std_logic_vector(1 downto 0);
s00_axi_bvalid : out std_logic;
s00_axi_bready : in std_logic;
s00_axi_araddr : in std_logic_vector(23 downto 0);
s00_axi_arprot : in std_logic_vector(2 downto 0);
s00_axi_arvalid : in std_logic;
s00_axi_arready : out std_logic;
s00_axi_rdata : out std_logic_vector(31 downto 0);
s00_axi_rresp : out std_logic_vector(1 downto 0);
s00_axi_rvalid : out std_logic;
s00_axi_rready : in std_logic
);
end entity CTU_CAN_FD_v1_0;
architecture rtl of CTU_CAN_FD_v1_0 is
component CAN_top_level is
generic(
constant use_logger : boolean := true;
constant rx_buffer_size : natural range 4 to 512 := 128;
constant use_sync : boolean := true;
constant ID : natural range 0 to 15 := 1;
constant sup_filtA : boolean := true;
constant sup_filtB : boolean := true;
constant sup_filtC : boolean := true;
constant sup_range : boolean := true;
constant tx_time_sup : boolean := true;
constant sup_be : boolean := true;
constant logger_size : natural range 0 to 512 := 8
);
port(
signal clk_sys : in std_logic;
signal res_n : in std_logic;
signal data_in : in std_logic_vector(31 downto 0);
signal data_out : out std_logic_vector(31 downto 0);
signal adress : in std_logic_vector(23 downto 0);
signal scs : in std_logic; --Chip select
signal srd : in std_logic; --Serial read
signal swr : in std_logic; --Serial write
signal sbe : in std_logic_vector(3 downto 0);
signal int : out std_logic;
signal CAN_tx : out std_logic;
signal CAN_rx : in std_logic;
signal time_quanta_clk : out std_logic;
signal timestamp : in std_logic_vector(63 downto 0)
);
end component;
component axi_ifc is
generic (
-- Width of S_AXI data bus
C_S_AXI_DATA_WIDTH : integer := 32;
-- Width of S_AXI address bus
C_S_AXI_ADDR_WIDTH : integer := 8
);
port (
reg_data_in_o : out std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
reg_data_out_i : in std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
reg_addr_o : out std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0);
reg_be_o : out std_logic_vector((C_S_AXI_DATA_WIDTH/8)-1 downto 0);
reg_rden_o : out std_logic;
reg_wren_o : out std_logic;
S_AXI_ACLK : in std_logic;
S_AXI_ARESETN : in std_logic;
S_AXI_AWADDR : in std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0);
S_AXI_AWPROT : in std_logic_vector(2 downto 0);
S_AXI_AWVALID : in std_logic;
S_AXI_AWREADY : out std_logic;
S_AXI_WDATA : in std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
S_AXI_WSTRB : in std_logic_vector((C_S_AXI_DATA_WIDTH/8)-1 downto 0);
S_AXI_WVALID : in std_logic;
S_AXI_WREADY : out std_logic;
S_AXI_BRESP : out std_logic_vector(1 downto 0);
S_AXI_BVALID : out std_logic;
S_AXI_BREADY : in std_logic;
S_AXI_ARADDR : in std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0);
S_AXI_ARPROT : in std_logic_vector(2 downto 0);
S_AXI_ARVALID : in std_logic;
S_AXI_ARREADY : out std_logic;
S_AXI_RDATA : out std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
S_AXI_RRESP : out std_logic_vector(1 downto 0);
S_AXI_RVALID : out std_logic;
S_AXI_RREADY : in std_logic
);
end component axi_ifc;
signal reg_data_in : std_logic_vector(31 downto 0);
signal reg_data_out : std_logic_vector(31 downto 0);
signal reg_addr : std_logic_vector(23 downto 0);
signal reg_be : std_logic_vector(3 downto 0);
signal reg_rden : std_logic;
signal reg_wren : std_logic;
begin
i_can: CAN_top_level
generic map (
use_logger => use_logger,
rx_buffer_size => rx_buffer_size,
use_sync => use_sync,
sup_filtA => sup_filtA,
sup_filtB => sup_filtB,
sup_filtC => sup_filtC,
sup_range => sup_range,
tx_time_sup => tx_time_sup,
sup_be => sup_be,
logger_size => logger_size
)
port map (
clk_sys => s00_axi_aclk,
res_n => s00_axi_aresetn,
data_in => reg_data_in,
data_out => reg_data_out,
adress => reg_addr,
scs => '1',
srd => reg_rden,
swr => reg_wren,
sbe => reg_be,
int => int,
CAN_tx => CAN_tx,
CAN_rx => CAN_rx,
time_quanta_clk => time_quanta_clk,
timestamp => timestamp
);
i_axi: axi_ifc
generic map (
C_S_AXI_DATA_WIDTH => 32,
C_S_AXI_ADDR_WIDTH => 24
)
port map (
reg_data_in_o => reg_data_in,
reg_data_out_i => reg_data_out,
reg_addr_o => reg_addr,
reg_be_o => reg_be,
reg_rden_o => reg_rden,
reg_wren_o => reg_wren,
S_AXI_ACLK => s00_axi_aclk,
S_AXI_ARESETN => s00_axi_aresetn,
S_AXI_AWADDR => s00_axi_awaddr,
S_AXI_AWPROT => s00_axi_awprot,
S_AXI_AWVALID => s00_axi_awvalid,
S_AXI_AWREADY => s00_axi_awready,
S_AXI_WDATA => s00_axi_wdata,
S_AXI_WSTRB => s00_axi_wstrb,
S_AXI_WVALID => s00_axi_wvalid,
S_AXI_WREADY => s00_axi_wready,
S_AXI_BRESP => s00_axi_bresp,
S_AXI_BVALID => s00_axi_bvalid,
S_AXI_BREADY => s00_axi_bready,
S_AXI_ARADDR => s00_axi_araddr,
S_AXI_ARPROT => s00_axi_arprot,
S_AXI_ARVALID => s00_axi_arvalid,
S_AXI_ARREADY => s00_axi_arready,
S_AXI_RDATA => s00_axi_rdata,
S_AXI_RRESP => s00_axi_rresp,
S_AXI_RVALID => s00_axi_rvalid,
S_AXI_RREADY => s00_axi_rready
);
end architecture rtl;
proc init { cellpath otherInfo } {
set cell_handle [get_bd_cells $cellpath]
set all_busif [get_bd_intf_pins $cellpath/*]
set axi_standard_param_list [list ID_WIDTH AWUSER_WIDTH ARUSER_WIDTH WUSER_WIDTH RUSER_WIDTH BUSER_WIDTH]
set full_sbusif_list [list ]
foreach busif $all_busif {
if { [string equal -nocase [get_property MODE $busif] "slave"] == 1 } {
set busif_param_list [list]
set busif_name [get_property NAME $busif]
if { [lsearch -exact -nocase $full_sbusif_list $busif_name ] == -1 } {
continue
}
foreach tparam $axi_standard_param_list {
lappend busif_param_list "C_${busif_name}_${tparam}"
}
bd::mark_propagate_only $cell_handle $busif_param_list
}
}
}
proc pre_propagate {cellpath otherInfo } {
set cell_handle [get_bd_cells $cellpath]
set all_busif [get_bd_intf_pins $cellpath/*]
set axi_standard_param_list [list ID_WIDTH AWUSER_WIDTH ARUSER_WIDTH WUSER_WIDTH RUSER_WIDTH BUSER_WIDTH]
foreach busif $all_busif {
if { [string equal -nocase [get_property CONFIG.PROTOCOL $busif] "AXI4"] != 1 } {
continue
}
if { [string equal -nocase [get_property MODE $busif] "master"] != 1 } {
continue
}
set busif_name [get_property NAME $busif]
foreach tparam $axi_standard_param_list {
set busif_param_name "C_${busif_name}_${tparam}"
set val_on_cell_intf_pin [get_property CONFIG.${tparam} $busif]
set val_on_cell [get_property CONFIG.${busif_param_name} $cell_handle]
if { [string equal -nocase $val_on_cell_intf_pin $val_on_cell] != 1 } {
if { $val_on_cell != "" } {
set_property CONFIG.${tparam} $val_on_cell $busif
}
}
}
}
}
proc propagate {cellpath otherInfo } {
set cell_handle [get_bd_cells $cellpath]
set all_busif [get_bd_intf_pins $cellpath/*]
set axi_standard_param_list [list ID_WIDTH AWUSER_WIDTH ARUSER_WIDTH WUSER_WIDTH RUSER_WIDTH BUSER_WIDTH]
foreach busif $all_busif {
if { [string equal -nocase [get_property CONFIG.PROTOCOL $busif] "AXI4"] != 1 } {
continue
}
if { [string equal -nocase [get_property MODE $busif] "slave"] != 1 } {
continue
}
set busif_name [get_property NAME $busif]
foreach tparam $axi_standard_param_list {
set busif_param_name "C_${busif_name}_${tparam}"
set val_on_cell_intf_pin [get_property CONFIG.${tparam} $busif]
set val_on_cell [get_property CONFIG.${busif_param_name} $cell_handle]
if { [string equal -nocase $val_on_cell_intf_pin $val_on_cell] != 1 } {
#override property of bd_interface_net to bd_cell -- only for slaves. May check for supported values..
if { $val_on_cell_intf_pin != "" } {
set_property CONFIG.${busif_param_name} $val_on_cell_intf_pin $cell_handle
}
}
}