UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Participant bahadirozk
Participant
1,517 Views
Registered: ‎02-06-2019

AXI Counter

Hello,

I designed a 32 bit counter in VHDL. The codes of the design are picture 1.

I packed this counter to Axi peripheral. Then I used the Axi custom ip in my block desing. (Picture 2).

I send the teraterm program via uart to the instant value of the counter. But it only shows the initial value of the counter. Subsequent values are always the same.(picture 3)

my SDK code(picture 4)

picture1.jpg
picture2.jpg
picture3.jpeg
picture4.jpg
0 Kudos
19 Replies
Xilinx Employee
Xilinx Employee
1,461 Views
Registered: ‎11-30-2007

Re: AXI Counter

when you want to create a new peripheral - then I would highly recommend to create a sample peripheral via the wizard first - then verify what is being created.

 

The wizard will usually create two files - one that covers the AXI peripheral interface - and a second file that contains all the user code - means e.g. your sample counter.

The wrapper for the AXI peripheral will take care that ll signals will be treated correctly and all values/registers are forwarded correctly.

It is NOT sufficient just to write an ordinary VHDL code that has NO AXI interface description at all - and then hope that the packager can wrap this fully up into an AXI capable IP.

 

I am assuming that the VHDL code you have written became part of the IP - but is not connected to any AXI signal/port at all - and therefore you can't see any change.

Scholar dgisselq
Scholar
1,440 Views
Registered: ‎05-21-2015

Re: AXI Counter

Can you share your counter design with us at all?  I'd love to have the opportunity to check its AXI interface ...

Thanks,

Dan

0 Kudos
1,437 Views
Registered: ‎07-23-2019

Re: AXI Counter

@bahadirozk 

What does the warning on the xil_printf say?

How do you know result is mapped to base + 0?

0 Kudos
1,435 Views
Registered: ‎07-23-2019

Re: AXI Counter

 

Oh, I see... As @ktrott  says, you cannot simply write something like:

result <= something;

in your VHDL bit even if it has an AXI interface. You still need to implement the AXI stuff.

0 Kudos
Participant bahadirozk
Participant
1,359 Views
Registered: ‎02-06-2019

Re: AXI Counter

So how can I do. Can you use your counter code to get a sample? I'm going to apply it to another design.

0 Kudos
Participant bahadirozk
Participant
1,358 Views
Registered: ‎02-06-2019

Re: AXI Counter

the code you say is above
0 Kudos
Xilinx Employee
Xilinx Employee
1,330 Views
Registered: ‎11-30-2007

Re: AXI Counter

t is not sufficient just to write a simple VHDL file - like you did - and package this as an AXI interface. You need an additional file that covers the AXI interface handling before you can package these two files up to a complete AXI interface. You need to take care that all AXI signals are treated correctly. AXI lite usually has some registers - and one of them would be the config register - to start/stop timers, other registers can contain the timer value. As long as the AXI interface does not know how to connect the timer value/control to these AXI available registers - there is no way to see any updates. The easiest way to get such a working is to use the IP package creation wizard - see Vivado menu: tools => Create and package new IP Create a new IP add a new axi 4 lite peripheral interface and pick a slave interface with the default 4 registers (can be changed later in the code). And continue with creation. Then the IP wizard will create two files - one for the AXI interface - you can take this as is - the second file contains the user code - that will be your way to implement the timer with start/stop/load/... You can modify this file. After everything is modified - you need to package the IP again. Here is the std-created file for AXI4-lite to get AXI to work (with default 4 registers): library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity myip_v1_0 is generic ( -- Users to add parameters here -- User parameters ends -- Do not modify the parameters beyond this line -- Parameters of Axi Slave Bus Interface S00_AXI C_S00_AXI_DATA_WIDTH : integer := 32; C_S00_AXI_ADDR_WIDTH : integer := 4 ); port ( -- Users to add ports here -- User ports ends -- Do not modify the ports beyond this line -- 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(C_S00_AXI_ADDR_WIDTH-1 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(C_S00_AXI_DATA_WIDTH-1 downto 0); s00_axi_wstrb : in std_logic_vector((C_S00_AXI_DATA_WIDTH/8)-1 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(C_S00_AXI_ADDR_WIDTH-1 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(C_S00_AXI_DATA_WIDTH-1 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 myip_v1_0; architecture arch_imp of myip_v1_0 is -- component declaration component myip_v1_0_S00_AXI is generic ( C_S_AXI_DATA_WIDTH : integer := 32; C_S_AXI_ADDR_WIDTH : integer := 4 ); port ( 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 myip_v1_0_S00_AXI; begin -- Instantiation of Axi Bus Interface S00_AXI myip_v1_0_S00_AXI_inst : myip_v1_0_S00_AXI generic map ( C_S_AXI_DATA_WIDTH => C_S00_AXI_DATA_WIDTH, C_S_AXI_ADDR_WIDTH => C_S00_AXI_ADDR_WIDTH ) port map ( 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 ); -- Add user logic here -- User logic ends end arch_imp; The second file is this one - this contains all the statemachines for AXI as well as the interfaces to the user codes... ======================================== library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity myip_v1_0_S00_AXI is generic ( -- Users to add parameters here -- User parameters ends -- Do not modify the parameters beyond this line -- 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 := 4 ); port ( -- Users to add ports here -- User ports ends -- Do not modify the ports beyond this line -- Global Clock Signal S_AXI_ACLK : in std_logic; -- Global Reset Signal. This Signal is Active LOW S_AXI_ARESETN : in std_logic; -- Write address (issued by master, acceped by Slave) S_AXI_AWADDR : in std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0); -- Write channel Protection type. This signal indicates the -- privilege and security level of the transaction, and whether -- the transaction is a data access or an instruction access. S_AXI_AWPROT : in std_logic_vector(2 downto 0); -- Write address valid. This signal indicates that the master signaling -- valid write address and control information. S_AXI_AWVALID : in std_logic; -- Write address ready. This signal indicates that the slave is ready -- to accept an address and associated control signals. S_AXI_AWREADY : out std_logic; -- Write data (issued by master, acceped by Slave) S_AXI_WDATA : in std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); -- Write strobes. This signal indicates which byte lanes hold -- valid data. There is one write strobe bit for each eight -- bits of the write data bus. S_AXI_WSTRB : in std_logic_vector((C_S_AXI_DATA_WIDTH/8)-1 downto 0); -- Write valid. This signal indicates that valid write -- data and strobes are available. S_AXI_WVALID : in std_logic; -- Write ready. This signal indicates that the slave -- can accept the write data. S_AXI_WREADY : out std_logic; -- Write response. This signal indicates the status -- of the write transaction. S_AXI_BRESP : out std_logic_vector(1 downto 0); -- Write response valid. This signal indicates that the channel -- is signaling a valid write response. S_AXI_BVALID : out std_logic; -- Response ready. This signal indicates that the master -- can accept a write response. S_AXI_BREADY : in std_logic; -- Read address (issued by master, acceped by Slave) S_AXI_ARADDR : in std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0); -- Protection type. This signal indicates the privilege -- and security level of the transaction, and whether the -- transaction is a data access or an instruction access. S_AXI_ARPROT : in std_logic_vector(2 downto 0); -- Read address valid. This signal indicates that the channel -- is signaling valid read address and control information. S_AXI_ARVALID : in std_logic; -- Read address ready. This signal indicates that the slave is -- ready to accept an address and associated control signals. S_AXI_ARREADY : out std_logic; -- Read data (issued by slave) S_AXI_RDATA : out std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); -- Read response. This signal indicates the status of the -- read transfer. S_AXI_RRESP : out std_logic_vector(1 downto 0); -- Read valid. This signal indicates that the channel is -- signaling the required read data. S_AXI_RVALID : out std_logic; -- Read ready. This signal indicates that the master can -- accept the read data and response information. S_AXI_RREADY : in std_logic ); end myip_v1_0_S00_AXI; architecture arch_imp of myip_v1_0_S00_AXI is -- AXI4LITE signals signal axi_awaddr : std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0); signal axi_awready : std_logic; signal axi_wready : std_logic; signal axi_bresp : std_logic_vector(1 downto 0); signal axi_bvalid : std_logic; signal axi_araddr : std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0); signal axi_arready : std_logic; signal axi_rdata : std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); 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 := 1; ------------------------------------------------ ---- Signals for user logic register space example -------------------------------------------------- ---- Number of Slave Registers 4 signal slv_reg0 :std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); signal slv_reg1 :std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); signal slv_reg2 :std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); signal slv_reg3 :std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); 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; begin -- I/O Connections assignments S_AXI_AWREADY <= axi_awready; S_AXI_WREADY <= axi_wready; 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_RVALID <= axi_rvalid; -- Implement axi_awready generation -- axi_awready 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 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'; aw_en <= '0'; elsif (S_AXI_BREADY = '1' and axi_bvalid = '1') then aw_en <= '1'; axi_awready <= '0'; else axi_awready <= '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 axi_wready generation -- axi_wready is asserted for one S_AXI_ACLK clock cycle when both -- S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_wready 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_wready <= '0'; else if (axi_wready = '0' and S_AXI_WVALID = '1' and S_AXI_AWVALID = '1' and aw_en = '1') then -- slave is ready to accept write 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_wready <= '1'; else axi_wready <= '0'; 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 ; process (S_AXI_ACLK) variable loc_addr :std_logic_vector(OPT_MEM_ADDR_BITS downto 0); begin if rising_edge(S_AXI_ACLK) then if S_AXI_ARESETN = '0' then slv_reg0 <= (others => '0'); slv_reg1 <= (others => '0'); slv_reg2 <= (others => '0'); slv_reg3 <= (others => '0'); else loc_addr := axi_awaddr(ADDR_LSB + OPT_MEM_ADDR_BITS downto ADDR_LSB); if (slv_reg_wren = '1') then case loc_addr is when b"00" => for byte_index in 0 to (C_S_AXI_DATA_WIDTH/8-1) loop if ( S_AXI_WSTRB(byte_index) = '1' ) then -- Respective byte enables are asserted as per write strobes -- slave registor 0 slv_reg0(byte_index*8+7 downto byte_index*8) <= S_AXI_WDATA(byte_index*8+7 downto byte_index*8); end if; end loop; when b"01" => for byte_index in 0 to (C_S_AXI_DATA_WIDTH/8-1) loop if ( S_AXI_WSTRB(byte_index) = '1' ) then -- Respective byte enables are asserted as per write strobes -- slave registor 1 slv_reg1(byte_index*8+7 downto byte_index*8) <= S_AXI_WDATA(byte_index*8+7 downto byte_index*8); end if; end loop; when b"10" => for byte_index in 0 to (C_S_AXI_DATA_WIDTH/8-1) loop if ( S_AXI_WSTRB(byte_index) = '1' ) then -- Respective byte enables are asserted as per write strobes -- slave registor 2 slv_reg2(byte_index*8+7 downto byte_index*8) <= S_AXI_WDATA(byte_index*8+7 downto byte_index*8); end if; end loop; when b"11" => for byte_index in 0 to (C_S_AXI_DATA_WIDTH/8-1) loop if ( S_AXI_WSTRB(byte_index) = '1' ) then -- Respective byte enables are asserted as per write strobes -- slave registor 3 slv_reg3(byte_index*8+7 downto byte_index*8) <= S_AXI_WDATA(byte_index*8+7 downto byte_index*8); end if; end loop; when others => slv_reg0 <= slv_reg0; slv_reg1 <= slv_reg1; slv_reg2 <= slv_reg2; slv_reg3 <= slv_reg3; end case; end if; end if; end if; end process; -- 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; -- 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) ; process (slv_reg0, slv_reg1, slv_reg2, slv_reg3, axi_araddr, S_AXI_ARESETN, slv_reg_rden) variable loc_addr :std_logic_vector(OPT_MEM_ADDR_BITS downto 0); begin -- Address decoding for reading registers loc_addr := axi_araddr(ADDR_LSB + OPT_MEM_ADDR_BITS downto ADDR_LSB); case loc_addr is when b"00" => reg_data_out <= slv_reg0; when b"01" => reg_data_out <= slv_reg1; when b"10" => reg_data_out <= slv_reg2; when b"11" => reg_data_out <= slv_reg3; when others => reg_data_out <= (others => '0'); end case; end process; -- 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 -- User logic ends end arch_imp;
0 Kudos
Participant bahadirozk
Participant
1,312 Views
Registered: ‎02-06-2019

Re: AXI Counter

I already did what you said. From slv_reg0 I read the counter value. But it only shows initial value.
(The easiest way to get such a working is to use the IP package creation wizard - see Vivado menu: tools => Create and package new IP Create a new IP add a new axi 4 lite peripheral interface and pick a slave interface with the default 4 registers)
0 Kudos
Participant bahadirozk
Participant
1,302 Views
Registered: ‎02-06-2019

Re: AXI Counter

I'm writing down all the codes. Please tell me where I am doing wrong.

------------------------------------------

my counter code :

------------------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity counter is
Port ( clk : in STD_LOGIC;
result : out STD_LOGIC_VECTOR(31 downto 0));
end counter;

architecture Behavioral of counter is
signal r_result : std_logic_vector(31 downto 0) := (others => '0');
begin

process(clk)
begin
if rising_edge(clk) then
if (r_result = x"FFFFFFFF") then
r_result <= (others => '0');
else
r_result <= r_result + 1;
end if;
end if;
end process;
result <= r_result;
end Behavioral;

-------------------------------------------

my_ip_counter_v1_0

-------------------------------------------

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity my_ip_counter_v1_0 is
generic (
-- Users to add parameters here

-- User parameters ends
-- Do not modify the parameters beyond this line


-- Parameters of Axi Slave Bus Interface S00_AXI
C_S00_AXI_DATA_WIDTH : integer := 32;
C_S00_AXI_ADDR_WIDTH : integer := 4
);
port (
-- Users to add ports here

-- User ports ends
-- Do not modify the ports beyond this line


-- 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(C_S00_AXI_ADDR_WIDTH-1 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(C_S00_AXI_DATA_WIDTH-1 downto 0);
s00_axi_wstrb : in std_logic_vector((C_S00_AXI_DATA_WIDTH/8)-1 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(C_S00_AXI_ADDR_WIDTH-1 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(C_S00_AXI_DATA_WIDTH-1 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 my_ip_counter_v1_0;

architecture arch_imp of my_ip_counter_v1_0 is

-- component declaration
component my_ip_counter_v1_0_S00_AXI is
generic (
C_S_AXI_DATA_WIDTH : integer := 32;
C_S_AXI_ADDR_WIDTH : integer := 4
);
port (
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 my_ip_counter_v1_0_S00_AXI;

begin

-- Instantiation of Axi Bus Interface S00_AXI
my_ip_counter_v1_0_S00_AXI_inst : my_ip_counter_v1_0_S00_AXI
generic map (
C_S_AXI_DATA_WIDTH => C_S00_AXI_DATA_WIDTH,
C_S_AXI_ADDR_WIDTH => C_S00_AXI_ADDR_WIDTH
)
port map (
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
);

-- Add user logic here

-- User logic ends

end arch_imp;

-------------------------------------------------

my_ip_counter_v1_0_S00_AXI

-------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity my_ip_counter_v1_0_S00_AXI is
generic (
-- Users to add parameters here

-- User parameters ends
-- Do not modify the parameters beyond this line

-- 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 := 4
);
port (
-- Users to add ports here

-- User ports ends
-- Do not modify the ports beyond this line

-- Global Clock Signal
S_AXI_ACLK : in std_logic;
-- Global Reset Signal. This Signal is Active LOW
S_AXI_ARESETN : in std_logic;
-- Write address (issued by master, acceped by Slave)
S_AXI_AWADDR : in std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0);
-- Write channel Protection type. This signal indicates the
-- privilege and security level of the transaction, and whether
-- the transaction is a data access or an instruction access.
S_AXI_AWPROT : in std_logic_vector(2 downto 0);
-- Write address valid. This signal indicates that the master signaling
-- valid write address and control information.
S_AXI_AWVALID : in std_logic;
-- Write address ready. This signal indicates that the slave is ready
-- to accept an address and associated control signals.
S_AXI_AWREADY : out std_logic;
-- Write data (issued by master, acceped by Slave)
S_AXI_WDATA : in std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
-- Write strobes. This signal indicates which byte lanes hold
-- valid data. There is one write strobe bit for each eight
-- bits of the write data bus.
S_AXI_WSTRB : in std_logic_vector((C_S_AXI_DATA_WIDTH/8)-1 downto 0);
-- Write valid. This signal indicates that valid write
-- data and strobes are available.
S_AXI_WVALID : in std_logic;
-- Write ready. This signal indicates that the slave
-- can accept the write data.
S_AXI_WREADY : out std_logic;
-- Write response. This signal indicates the status
-- of the write transaction.
S_AXI_BRESP : out std_logic_vector(1 downto 0);
-- Write response valid. This signal indicates that the channel
-- is signaling a valid write response.
S_AXI_BVALID : out std_logic;
-- Response ready. This signal indicates that the master
-- can accept a write response.
S_AXI_BREADY : in std_logic;
-- Read address (issued by master, acceped by Slave)
S_AXI_ARADDR : in std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0);
-- Protection type. This signal indicates the privilege
-- and security level of the transaction, and whether the
-- transaction is a data access or an instruction access.
S_AXI_ARPROT : in std_logic_vector(2 downto 0);
-- Read address valid. This signal indicates that the channel
-- is signaling valid read address and control information.
S_AXI_ARVALID : in std_logic;
-- Read address ready. This signal indicates that the slave is
-- ready to accept an address and associated control signals.
S_AXI_ARREADY : out std_logic;
-- Read data (issued by slave)
S_AXI_RDATA : out std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
-- Read response. This signal indicates the status of the
-- read transfer.
S_AXI_RRESP : out std_logic_vector(1 downto 0);
-- Read valid. This signal indicates that the channel is
-- signaling the required read data.
S_AXI_RVALID : out std_logic;
-- Read ready. This signal indicates that the master can
-- accept the read data and response information.
S_AXI_RREADY : in std_logic
);
end my_ip_counter_v1_0_S00_AXI;

architecture arch_imp of my_ip_counter_v1_0_S00_AXI is
component counter
Port ( clk : in STD_LOGIC;
result : out STD_LOGIC_VECTOR(31 downto 0));
end component;
signal result_c : std_logic_vector(31 downto 0);
-- AXI4LITE signals
signal axi_awaddr : std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0);
signal axi_awready : std_logic;
signal axi_wready : std_logic;
signal axi_bresp : std_logic_vector(1 downto 0);
signal axi_bvalid : std_logic;
signal axi_araddr : std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0);
signal axi_arready : std_logic;
signal axi_rdata : std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
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 := 1;
------------------------------------------------
---- Signals for user logic register space example
--------------------------------------------------
---- Number of Slave Registers 4
signal slv_reg0 :std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
signal slv_reg1 :std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
signal slv_reg2 :std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
signal slv_reg3 :std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
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;

begin
-- I/O Connections assignments

S_AXI_AWREADY <= axi_awready;
S_AXI_WREADY <= axi_wready;
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_RVALID <= axi_rvalid;
-- Implement axi_awready generation
-- axi_awready 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 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';
elsif (S_AXI_BREADY = '1' and axi_bvalid = '1') then
aw_en <= '1';
axi_awready <= '0';
else
axi_awready <= '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 axi_wready generation
-- axi_wready is asserted for one S_AXI_ACLK clock cycle when both
-- S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_wready 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_wready <= '0';
else
if (axi_wready = '0' and S_AXI_WVALID = '1' and S_AXI_AWVALID = '1' and aw_en = '1') then
-- slave is ready to accept write 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_wready <= '1';
else
axi_wready <= '0';
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 ;

process (S_AXI_ACLK)
variable loc_addr :std_logic_vector(OPT_MEM_ADDR_BITS downto 0);
begin
if rising_edge(S_AXI_ACLK) then
if S_AXI_ARESETN = '0' then
slv_reg0 <= (others => '0');
slv_reg1 <= (others => '0');
slv_reg2 <= (others => '0');
slv_reg3 <= (others => '0');
else
loc_addr := axi_awaddr(ADDR_LSB + OPT_MEM_ADDR_BITS downto ADDR_LSB);
if (slv_reg_wren = '1') then
case loc_addr is
when b"00" =>
for byte_index in 0 to (C_S_AXI_DATA_WIDTH/8-1) loop
if ( S_AXI_WSTRB(byte_index) = '1' ) then
-- Respective byte enables are asserted as per write strobes
-- slave registor 0
slv_reg0(byte_index*8+7 downto byte_index*8) <= S_AXI_WDATA(byte_index*8+7 downto byte_index*8);
end if;
end loop;
when b"01" =>
for byte_index in 0 to (C_S_AXI_DATA_WIDTH/8-1) loop
if ( S_AXI_WSTRB(byte_index) = '1' ) then
-- Respective byte enables are asserted as per write strobes
-- slave registor 1
slv_reg1(byte_index*8+7 downto byte_index*8) <= S_AXI_WDATA(byte_index*8+7 downto byte_index*8);
end if;
end loop;
when b"10" =>
for byte_index in 0 to (C_S_AXI_DATA_WIDTH/8-1) loop
if ( S_AXI_WSTRB(byte_index) = '1' ) then
-- Respective byte enables are asserted as per write strobes
-- slave registor 2
slv_reg2(byte_index*8+7 downto byte_index*8) <= S_AXI_WDATA(byte_index*8+7 downto byte_index*8);
end if;
end loop;
when b"11" =>
for byte_index in 0 to (C_S_AXI_DATA_WIDTH/8-1) loop
if ( S_AXI_WSTRB(byte_index) = '1' ) then
-- Respective byte enables are asserted as per write strobes
-- slave registor 3
slv_reg3(byte_index*8+7 downto byte_index*8) <= S_AXI_WDATA(byte_index*8+7 downto byte_index*8);
end if;
end loop;
when others =>
slv_reg0 <= slv_reg0;
slv_reg1 <= slv_reg1;
slv_reg2 <= slv_reg2;
slv_reg3 <= slv_reg3;
end case;
end if;
end if;
end if;
end process;

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

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

process (result_c, slv_reg1, slv_reg2, slv_reg3, axi_araddr, S_AXI_ARESETN, slv_reg_rden)
variable loc_addr :std_logic_vector(OPT_MEM_ADDR_BITS downto 0);
begin
-- Address decoding for reading registers
loc_addr := axi_araddr(ADDR_LSB + OPT_MEM_ADDR_BITS downto ADDR_LSB);
case loc_addr is
when b"00" =>
reg_data_out <= result_c;
when b"01" =>
reg_data_out <= slv_reg1;
when b"10" =>
reg_data_out <= slv_reg2;
when b"11" =>
reg_data_out <= slv_reg3;
when others =>
reg_data_out <= (others => '0');
end case;
end process;

-- 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
u1 : counter port map(S_AXI_ACLK, result_c);
-- User logic ends

end arch_imp;

 

0 Kudos
1,300 Views
Registered: ‎06-21-2017

Re: AXI Counter

Do you have a line in your code something like slv_reg0 <= result;  How does your counter result get into the register?

0 Kudos
Scholar dgisselq
Scholar
1,297 Views
Registered: ‎05-21-2015

Re: AXI Counter

@ktrott,

You do realize that the design component you just recommended to a new beginner has had bugs in it since 2016, right? Or that these bugs were reported back in December and that as of Vivado 2019.1 and the code you posted above, only one of them has been fixed?

1. In particular, there's no check for back pressure on S_AXI_RREADY. If S_AXI_RREADY isn't held high, this will fail

 

.readbug.png

2. The bug above isn't reported by your AXI VIP

3. This isn't a benign failure either. When this bug hits, the whole design will freeze, leaving the user wondering what happened.

4. The design gets rather poor performance too. It's recommended to all beginners, yet this design will get at best 30% write throughput and 50% read throughput.

 

crippled-read.png

5. It is possible to get 100% throughput, but without the bugs--and for a fairly reasonable logic cost as well

6. To answer the question of whether or not these bugs were relevant, I spent some time digging through your forums.  You are welcome read my report on ZipCPU.com if you are interested (Sorry, but it's a bit too long for a forum post or response.)

Dan

crippled-read.png
Participant bahadirozk
Participant
1,281 Views
Registered: ‎02-06-2019

Re: AXI Counter

I have a line in my code like reg_data_out <= result_c;
0 Kudos
Xilinx Employee
Xilinx Employee
1,240 Views
Registered: ‎11-30-2007

Re: AXI Counter

I just posted the std-default output of the AXI peripheral wizard of my 2018.3 installation.

Might be thatthere is a bug for back pressure that got fixed later on.

 

The main reason I posted this was to illustrate that you need more than just a RTL file that contains the timer.

You have to have at least one file for the AXI handling itself with the statemachins there.

The easiest way to get something that works is to use the Peripheral wizard - of course - please use the latest greatest version - 2019.1 is out - 2019.2 is coming pretty soon.

 

Karsten

0 Kudos
Adventurer
Adventurer
1,206 Views
Registered: ‎10-14-2013

Re: AXI Counter

@ktrott Any ETA when the mentioned AXI logic errors and bad throughoutput will be fixed?

0 Kudos
Scholar dgisselq
Scholar
1,200 Views
Registered: ‎05-21-2015

Re: AXI Counter

2019.1 is still broken.

Xilinx Employee
Xilinx Employee
1,183 Views
Registered: ‎11-30-2007

Re: AXI Counter

File an Service Request on this topic - and our develoeprs wil fix it.

0 Kudos
Participant bahadirozk
Participant
238 Views
Registered: ‎02-06-2019

Re: AXI Counter

My problem still continues. Can someone please do this and send it for me?

0 Kudos
Participant bahadirozk
Participant
234 Views
Registered: ‎02-06-2019

Re: AXI Counter

all my codes are above

0 Kudos
Highlighted
Scholar dgisselq
Scholar
199 Views
Registered: ‎05-21-2015

Re: AXI Counter

@bahadirozk,

Sorry, but no.  You're still not there.  The code you posted above still has protocol errors.

In this trace, you dropped a write return.

write-backpressure.png

And in this trace you dropped a read return.

read-backpressure.png

You might want to examine this link to see how a better AXI-lite slave might be written--one without protocol errors.  You can read about the (known) bugs that are present in the design you copied here.

Dan