From d44e52c4a37f22ef2deacec9be5d0094f64e8532 Mon Sep 17 00:00:00 2001 From: Pavel Pisa Date: Fri, 20 May 2016 16:43:49 +0200 Subject: [PATCH] AXI PWM Coprocessor: PWM generation logic roughly implemented. Signed-off-by: Pavel Pisa --- .../hdl/axi_pwm_coprocessor_v1_0.vhd | 41 +- .../hdl/axi_pwm_coprocessor_v1_0_M00_AXI.vhd | 892 +++++++++--------- .../hdl/axi_pwm_coprocessor_v1_0_S00_AXI.vhd | 180 ++-- 3 files changed, 617 insertions(+), 496 deletions(-) diff --git a/system/ip/axi_pwm_coprocessor_1.0/hdl/axi_pwm_coprocessor_v1_0.vhd b/system/ip/axi_pwm_coprocessor_1.0/hdl/axi_pwm_coprocessor_v1_0.vhd index 1ad103b..a7e8024 100644 --- a/system/ip/axi_pwm_coprocessor_1.0/hdl/axi_pwm_coprocessor_v1_0.vhd +++ b/system/ip/axi_pwm_coprocessor_1.0/hdl/axi_pwm_coprocessor_v1_0.vhd @@ -52,7 +52,6 @@ entity axi_pwm_coprocessor_v1_0 is s00_axi_rready : in std_logic; -- Ports of Axi Master Bus Interface M00_AXI - m00_axi_init_axi_txn : in std_logic; m00_axi_error : out std_logic; m00_axi_txn_done : out std_logic; m00_axi_aclk : in std_logic; @@ -88,6 +87,14 @@ architecture arch_imp of axi_pwm_coprocessor_v1_0 is C_S_AXI_ADDR_WIDTH : integer := 5 ); port ( + pwm_state_o : out std_logic_vector(1 downto 0); + pwm_enabled_o : out std_logic; + + pwm_wr_addr : out std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); + pwm_wr0 : out std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); + pwm_wr1 : out std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); + pwm_wr2 : out std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); + 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); @@ -121,6 +128,14 @@ architecture arch_imp of axi_pwm_coprocessor_v1_0 is C_M_TRANSACTIONS_NUM : integer := 4 ); port ( + pwm_state_i : in std_logic_vector(1 downto 0); + pwm_enabled_i : in std_logic; + + pwm_wr_addr : in std_logic_vector(C_M_AXI_DATA_WIDTH-1 downto 0); + pwm_wr0 : in std_logic_vector(C_M_AXI_DATA_WIDTH-1 downto 0); + pwm_wr1 : in std_logic_vector(C_M_AXI_DATA_WIDTH-1 downto 0); + pwm_wr2 : in std_logic_vector(C_M_AXI_DATA_WIDTH-1 downto 0); + INIT_AXI_TXN : in std_logic; ERROR : out std_logic; TXN_DONE : out std_logic; @@ -148,6 +163,13 @@ architecture arch_imp of axi_pwm_coprocessor_v1_0 is ); end component axi_pwm_coprocessor_v1_0_M00_AXI; + signal pwm_state : std_logic_vector(1 downto 0); + signal pwm_enabled : std_logic; + + signal pwm_wr_addr : std_logic_vector(C_S00_AXI_DATA_WIDTH-1 downto 0); + signal pwm_wr0 : std_logic_vector(C_S00_AXI_DATA_WIDTH-1 downto 0); + signal pwm_wr1 : std_logic_vector(C_S00_AXI_DATA_WIDTH-1 downto 0); + signal pwm_wr2 : std_logic_vector(C_S00_AXI_DATA_WIDTH-1 downto 0); begin -- Instantiation of Axi Bus Interface S00_AXI @@ -157,6 +179,14 @@ axi_pwm_coprocessor_v1_0_S00_AXI_inst : axi_pwm_coprocessor_v1_0_S00_AXI C_S_AXI_ADDR_WIDTH => C_S00_AXI_ADDR_WIDTH ) port map ( + pwm_state_o => pwm_state, + pwm_enabled_o => pwm_enabled, + + pwm_wr_addr => pwm_wr_addr, + pwm_wr0 => pwm_wr0, + pwm_wr1 => pwm_wr1, + pwm_wr2 => pwm_wr2, + S_AXI_ACLK => s00_axi_aclk, S_AXI_ARESETN => s00_axi_aresetn, S_AXI_AWADDR => s00_axi_awaddr, @@ -190,7 +220,14 @@ axi_pwm_coprocessor_v1_0_M00_AXI_inst : axi_pwm_coprocessor_v1_0_M00_AXI C_M_TRANSACTIONS_NUM => C_M00_AXI_TRANSACTIONS_NUM ) port map ( - INIT_AXI_TXN => m00_axi_init_axi_txn, + pwm_state_i => pwm_state, + pwm_enabled_i => pwm_enabled, + + pwm_wr_addr => pwm_wr_addr, + pwm_wr0 => pwm_wr0, + pwm_wr1 => pwm_wr1, + pwm_wr2 => pwm_wr2, + ERROR => m00_axi_error, TXN_DONE => m00_axi_txn_done, M_AXI_ACLK => m00_axi_aclk, diff --git a/system/ip/axi_pwm_coprocessor_1.0/hdl/axi_pwm_coprocessor_v1_0_M00_AXI.vhd b/system/ip/axi_pwm_coprocessor_1.0/hdl/axi_pwm_coprocessor_v1_0_M00_AXI.vhd index 06fbdac..5e21369 100644 --- a/system/ip/axi_pwm_coprocessor_1.0/hdl/axi_pwm_coprocessor_v1_0_M00_AXI.vhd +++ b/system/ip/axi_pwm_coprocessor_1.0/hdl/axi_pwm_coprocessor_v1_0_M00_AXI.vhd @@ -14,24 +14,30 @@ entity axi_pwm_coprocessor_v1_0_M00_AXI is -- The master requires a target slave base address. -- The master will initiate read and write transactions on the slave with base address specified here as a parameter. C_M_TARGET_SLAVE_BASE_ADDR : std_logic_vector := x"40000000"; - -- Width of M_AXI address bus. + -- Width of M_AXI address bus. -- The master generates the read and write addresses of width specified as C_M_AXI_ADDR_WIDTH. C_M_AXI_ADDR_WIDTH : integer := 32; - -- Width of M_AXI data bus. + -- Width of M_AXI data bus. -- The master issues write data and accept read data where the width of the data bus is C_M_AXI_DATA_WIDTH C_M_AXI_DATA_WIDTH : integer := 32; - -- Transaction number is the number of write + -- Transaction number is the number of write -- and read transactions the master will perform as a part of this example memory test. - C_M_TRANSACTIONS_NUM : integer := 4 + C_M_TRANSACTIONS_NUM : integer := 1 ); port ( -- Users to add ports here + pwm_state_i : in std_logic_vector(1 downto 0); + pwm_enabled_i : in std_logic; + pwm_wr_addr : in std_logic_vector(C_M_AXI_DATA_WIDTH-1 downto 0); + pwm_wr0 : in std_logic_vector(C_M_AXI_DATA_WIDTH-1 downto 0); + pwm_wr1 : in std_logic_vector(C_M_AXI_DATA_WIDTH-1 downto 0); + pwm_wr2 : in std_logic_vector(C_M_AXI_DATA_WIDTH-1 downto 0); -- User ports ends -- Do not modify the ports beyond this line -- Initiate AXI transactions - INIT_AXI_TXN : in std_logic; + -- INIT_AXI_TXN : in std_logic; -- Asserts when ERROR is detected ERROR : out std_logic; -- Asserts when AXI transactions is complete @@ -46,15 +52,15 @@ entity axi_pwm_coprocessor_v1_0_M00_AXI is -- This signal indicates the privilege and security level of the transaction, -- and whether the transaction is a data access or an instruction access. M_AXI_AWPROT : out std_logic_vector(2 downto 0); - -- Write address valid. + -- Write address valid. -- This signal indicates that the master signaling valid write address and control information. M_AXI_AWVALID : out std_logic; - -- Write address ready. + -- Write address ready. -- This signal indicates that the slave is ready to accept an address and associated control signals. M_AXI_AWREADY : in std_logic; -- Master Interface Write Data Channel ports. Write data (issued by master) M_AXI_WDATA : out std_logic_vector(C_M_AXI_DATA_WIDTH-1 downto 0); - -- Write strobes. + -- 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. M_AXI_WSTRB : out std_logic_vector(C_M_AXI_DATA_WIDTH/8-1 downto 0); @@ -62,24 +68,24 @@ entity axi_pwm_coprocessor_v1_0_M00_AXI is M_AXI_WVALID : out std_logic; -- Write ready. This signal indicates that the slave can accept the write data. M_AXI_WREADY : in std_logic; - -- Master Interface Write Response Channel ports. + -- Master Interface Write Response Channel ports. -- This signal indicates the status of the write transaction. M_AXI_BRESP : in std_logic_vector(1 downto 0); - -- Write response valid. + -- Write response valid. -- This signal indicates that the channel is signaling a valid write response M_AXI_BVALID : in std_logic; -- Response ready. This signal indicates that the master can accept a write response. M_AXI_BREADY : out std_logic; -- Master Interface Read Address Channel ports. Read address (issued by master) M_AXI_ARADDR : out std_logic_vector(C_M_AXI_ADDR_WIDTH-1 downto 0); - -- Protection type. - -- This signal indicates the privilege and security level of the transaction, + -- 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. M_AXI_ARPROT : out std_logic_vector(2 downto 0); - -- Read address valid. + -- Read address valid. -- This signal indicates that the channel is signaling valid read address and control information. M_AXI_ARVALID : out std_logic; - -- Read address ready. + -- Read address ready. -- This signal indicates that the slave is ready to accept an address and associated control signals. M_AXI_ARREADY : in std_logic; -- Master Interface Read Data Channel ports. Read data (issued by slave) @@ -97,24 +103,24 @@ architecture implementation of axi_pwm_coprocessor_v1_0_M00_AXI is -- function called clogb2 that returns an integer which has the -- value of the ceiling of the log base 2 - function clogb2 (bit_depth : integer) return integer is - variable depth : integer := bit_depth; - variable count : integer := 1; - begin + function clogb2 (bit_depth : integer) return integer is + variable depth : integer := bit_depth; + variable count : integer := 1; + begin for clogb2 in 1 to bit_depth loop -- Works for up to 32 bit integers - if (bit_depth <= 2) then - count := 1; - else - if(depth <= 1) then - count := count; - else - depth := depth / 2; - count := count + 1; - end if; - end if; - end loop; - return(count); - end; + if (bit_depth <= 2) then + count := 1; + else + if(depth <= 1) then + count := count; + else + depth := depth / 2; + count := count + 1; + end if; + end if; + end loop; + return(count); + end; -- Example user application signals @@ -122,22 +128,22 @@ architecture implementation of axi_pwm_coprocessor_v1_0_M00_AXI is -- number of write or read transaction.. constant TRANS_NUM_BITS : integer := clogb2(C_M_TRANSACTIONS_NUM-1); - -- Example State machine to initialize counter, initialize write transactions, - -- initialize read transactions and comparison of read data with the + -- Example State machine to initialize counter, initialize write transactions, + -- initialize read transactions and comparison of read data with the -- written data words. type state is ( IDLE, -- This state initiates AXI4Lite transaction -- after the state machine changes state to INIT_WRITE -- when there is 0 to 1 transition on INIT_AXI_TXN INIT_WRITE, -- This state initializes write transaction, - -- once writes are done, the state machine - -- changes state to INIT_READ + -- once writes are done, the state machine + -- changes state to INIT_READ INIT_READ, -- This state initializes read transaction - -- once reads are done, the state machine - -- changes state to INIT_COMPARE - INIT_COMPARE);-- This state issues the status of comparison + -- once reads are done, the state machine + -- changes state to INIT_COMPARE + INIT_COMPARE);-- This state issues the status of comparison -- of the written data with the read data - signal mst_exec_state : state ; + signal mst_exec_state : state ; -- AXI4LITE signals --write address valid @@ -193,14 +199,22 @@ architecture implementation of axi_pwm_coprocessor_v1_0_M00_AXI is signal init_txn_edge : std_logic; signal init_txn_pulse : std_logic; + signal INIT_AXI_TXN : std_logic := '0'; + + signal pwm_state_prev : std_logic_vector(1 downto 0) := "00"; + signal pwm_state_inpr : std_logic_vector(1 downto 0) := "00"; begin -- I/O Connections assignments --Adding the offset address to the base addr of the slave - M_AXI_AWADDR <= std_logic_vector (unsigned(C_M_TARGET_SLAVE_BASE_ADDR) + unsigned(axi_awaddr)); + -- M_AXI_AWADDR <= std_logic_vector (unsigned(C_M_TARGET_SLAVE_BASE_ADDR) + unsigned(axi_awaddr)); + M_AXI_AWADDR <= pwm_wr_addr; --AXI 4 write data - M_AXI_WDATA <= axi_wdata; + M_AXI_WDATA <= pwm_wr1 when (pwm_state_inpr = "01") + else pwm_wr2 when (pwm_state_inpr = "01") + else pwm_wr0; + M_AXI_AWPROT <= "000"; M_AXI_AWVALID <= axi_awvalid; --Write Data(W) @@ -219,28 +233,45 @@ begin TXN_DONE <= compare_done; init_txn_pulse <= ( not init_txn_ff2) and init_txn_ff; + process(M_AXI_ACLK) + begin + if (rising_edge (M_AXI_ACLK)) then + -- Initiates AXI transaction delay + if (M_AXI_ARESETN = '0' ) or (pwm_enabled_i = '0') then + INIT_AXI_TXN <= '0'; + else + pwm_state_inpr <= pwm_state_inpr; + if (pwm_state_prev = pwm_state_i) or (mst_exec_state /= IDLE) then + INIT_AXI_TXN <= '0'; + else + INIT_AXI_TXN <= '1'; + pwm_state_inpr <= pwm_state_inpr; + end if; + end if; + end if; + end process; --Generate a pulse to initiate AXI transaction. - process(M_AXI_ACLK) - begin - if (rising_edge (M_AXI_ACLK)) then - -- Initiates AXI transaction delay - if (M_AXI_ARESETN = '0' ) then - init_txn_ff <= '0'; - init_txn_ff2 <= '0'; - else + process(M_AXI_ACLK) + begin + if (rising_edge (M_AXI_ACLK)) then + -- Initiates AXI transaction delay + if (M_AXI_ARESETN = '0' ) then + init_txn_ff <= '0'; + init_txn_ff2 <= '0'; + else init_txn_ff <= INIT_AXI_TXN; - init_txn_ff2 <= init_txn_ff; - end if; - end if; - end process; + init_txn_ff2 <= init_txn_ff; + end if; + end if; + end process; ---------------------- --Write Address Channel ---------------------- - -- The purpose of the write address channel is to request the address and + -- The purpose of the write address channel is to request the address and -- command information for the entire transaction. It is a single beat -- of information. @@ -252,49 +283,49 @@ begin -- A data transfer is accepted by the slave when a master has -- VALID data and the slave acknoledges it is also READY. While the master - -- is allowed to generated multiple, back-to-back requests by not + -- is allowed to generated multiple, back-to-back requests by not -- deasserting VALID, this design will add rest cycle for -- simplicity. -- Since only one outstanding transaction is issued by the user design, -- there will not be a collision between a new request and an accepted - -- request on the same clock cycle. - - process(M_AXI_ACLK) - begin - if (rising_edge (M_AXI_ACLK)) then - --Only VALID signals must be deasserted during reset per AXI spec - --Consider inverting then registering active-low reset for higher fmax - if (M_AXI_ARESETN = '0' or init_txn_pulse = '1') then - axi_awvalid <= '0'; - else - --Signal a new address/data command is available by user logic - if (start_single_write = '1') then - axi_awvalid <= '1'; - elsif (M_AXI_AWREADY = '1' and axi_awvalid = '1') then + -- request on the same clock cycle. + + process(M_AXI_ACLK) + begin + if (rising_edge (M_AXI_ACLK)) then + --Only VALID signals must be deasserted during reset per AXI spec + --Consider inverting then registering active-low reset for higher fmax + if (M_AXI_ARESETN = '0' or init_txn_pulse = '1') then + axi_awvalid <= '0'; + else + --Signal a new address/data command is available by user logic + if (start_single_write = '1') then + axi_awvalid <= '1'; + elsif (M_AXI_AWREADY = '1' and axi_awvalid = '1') then --Address accepted by interconnect/slave (issue of M_AXI_AWREADY by slave) - axi_awvalid <= '0'; - end if; - end if; - end if; - end process; - - -- start_single_write triggers a new write - -- transaction. write_index is a counter to - -- keep track with number of write transaction - -- issued/initiated - process(M_AXI_ACLK) - begin - if (rising_edge (M_AXI_ACLK)) then - if (M_AXI_ARESETN = '0' or init_txn_pulse = '1') then - write_index <= (others => '0'); - elsif (start_single_write = '1') then - -- Signals a new write address/ write data is - -- available by user logic - write_index <= std_logic_vector (unsigned(write_index) + 1); - end if; - end if; - end process; + axi_awvalid <= '0'; + end if; + end if; + end if; + end process; + + -- start_single_write triggers a new write + -- transaction. write_index is a counter to + -- keep track with number of write transaction + -- issued/initiated + process(M_AXI_ACLK) + begin + if (rising_edge (M_AXI_ACLK)) then + if (M_AXI_ARESETN = '0' or init_txn_pulse = '1') then + write_index <= (others => '0'); + elsif (start_single_write = '1') then + -- Signals a new write address/ write data is + -- available by user logic + write_index <= std_logic_vector (unsigned(write_index) + 1); + end if; + end if; + end process; ---------------------- @@ -302,25 +333,26 @@ begin ---------------------- --The write data channel is for transfering the actual data. - --The data generation is speific to the example design, and + --The data generation is speific to the example design, and --so only the WVALID/WREADY handshake is shown here - process(M_AXI_ACLK) - begin - if (rising_edge (M_AXI_ACLK)) then - if (M_AXI_ARESETN = '0' or init_txn_pulse = '1' ) then - axi_wvalid <= '0'; - else - if (start_single_write = '1') then - --Signal a new address/data command is available by user logic - axi_wvalid <= '1'; - elsif (M_AXI_WREADY = '1' and axi_wvalid = '1') then + process(M_AXI_ACLK) + begin + if (rising_edge (M_AXI_ACLK)) then + if (M_AXI_ARESETN = '0' or init_txn_pulse = '1' ) then + axi_wvalid <= '0'; + pwm_state_prev <= "00"; + else + if (start_single_write = '1') then + --Signal a new address/data command is available by user logic + axi_wvalid <= '1'; + elsif (M_AXI_WREADY = '1' and axi_wvalid = '1') then --Data accepted by interconnect/slave (issue of M_AXI_WREADY by slave) - axi_wvalid <= '0'; - end if; - end if; - end if; - end process; + axi_wvalid <= '0'; + end if; + end if; + end if; + end process; ------------------------------ @@ -338,24 +370,24 @@ begin --While not necessary per spec, it is advisable to reset READY signals in --case of differing reset latencies between master/slave. - process(M_AXI_ACLK) - begin - if (rising_edge (M_AXI_ACLK)) then - if (M_AXI_ARESETN = '0' or init_txn_pulse = '1') then - axi_bready <= '0'; - else - if (M_AXI_BVALID = '1' and axi_bready = '0') then - -- accept/acknowledge bresp with axi_bready by the master - -- when M_AXI_BVALID is asserted by slave - axi_bready <= '1'; - elsif (axi_bready = '1') then - -- deassert after one clock cycle - axi_bready <= '0'; - end if; - end if; - end if; - end process; - --Flag write errors + process(M_AXI_ACLK) + begin + if (rising_edge (M_AXI_ACLK)) then + if (M_AXI_ARESETN = '0' or init_txn_pulse = '1') then + axi_bready <= '0'; + else + if (M_AXI_BVALID = '1' and axi_bready = '0') then + -- accept/acknowledge bresp with axi_bready by the master + -- when M_AXI_BVALID is asserted by slave + axi_bready <= '1'; + elsif (axi_bready = '1') then + -- deassert after one clock cycle + axi_bready <= '0'; + end if; + end if; + end if; + end process; + --Flag write errors write_resp_error <= (axi_bready and M_AXI_BVALID and M_AXI_BRESP(1)); @@ -366,72 +398,72 @@ begin --start_single_read triggers a new read transaction. read_index is a counter to --keep track with number of read transaction issued/initiated - process(M_AXI_ACLK) - begin - if (rising_edge (M_AXI_ACLK)) then - if (M_AXI_ARESETN = '0' or init_txn_pulse = '1') then - read_index <= (others => '0'); - else - if (start_single_read = '1') then - -- Signals a new read address is - -- available by user logic - read_index <= std_logic_vector (unsigned(read_index) + 1); - end if; - end if; - end if; - end process; - - -- A new axi_arvalid is asserted when there is a valid read address - -- available by the master. start_single_read triggers a new read - -- transaction - process(M_AXI_ACLK) - begin - if (rising_edge (M_AXI_ACLK)) then - if (M_AXI_ARESETN = '0' or init_txn_pulse = '1') then - axi_arvalid <= '0'; - else - if (start_single_read = '1') then - --Signal a new read address command is available by user logic - axi_arvalid <= '1'; - elsif (M_AXI_ARREADY = '1' and axi_arvalid = '1') then + process(M_AXI_ACLK) + begin + if (rising_edge (M_AXI_ACLK)) then + if (M_AXI_ARESETN = '0' or init_txn_pulse = '1') then + read_index <= (others => '0'); + else + if (start_single_read = '1') then + -- Signals a new read address is + -- available by user logic + read_index <= std_logic_vector (unsigned(read_index) + 1); + end if; + end if; + end if; + end process; + + -- A new axi_arvalid is asserted when there is a valid read address + -- available by the master. start_single_read triggers a new read + -- transaction + process(M_AXI_ACLK) + begin + if (rising_edge (M_AXI_ACLK)) then + if (M_AXI_ARESETN = '0' or init_txn_pulse = '1') then + axi_arvalid <= '0'; + else + if (start_single_read = '1') then + --Signal a new read address command is available by user logic + axi_arvalid <= '1'; + elsif (M_AXI_ARREADY = '1' and axi_arvalid = '1') then --RAddress accepted by interconnect/slave (issue of M_AXI_ARREADY by slave) - axi_arvalid <= '0'; - end if; - end if; - end if; - end process; + axi_arvalid <= '0'; + end if; + end if; + end if; + end process; ---------------------------------- --Read Data (and Response) Channel ---------------------------------- - --The Read Data channel returns the results of the read request + --The Read Data channel returns the results of the read request --The master will accept the read data by asserting axi_rready --when there is a valid read data available. --While not necessary per spec, it is advisable to reset READY signals in --case of differing reset latencies between master/slave. - process(M_AXI_ACLK) - begin - if (rising_edge (M_AXI_ACLK)) then - if (M_AXI_ARESETN = '0' or init_txn_pulse = '1') then - axi_rready <= '1'; - else - if (M_AXI_RVALID = '1' and axi_rready = '0') then + process(M_AXI_ACLK) + begin + if (rising_edge (M_AXI_ACLK)) then + if (M_AXI_ARESETN = '0' or init_txn_pulse = '1') then + axi_rready <= '1'; + else + if (M_AXI_RVALID = '1' and axi_rready = '0') then -- accept/acknowledge rdata/rresp with axi_rready by the master - -- when M_AXI_RVALID is asserted by slave - axi_rready <= '1'; - elsif (axi_rready = '1') then - -- deassert after one clock cycle - axi_rready <= '0'; - end if; - end if; - end if; - end process; - - --Flag write errors - read_resp_error <= (axi_rready and M_AXI_RVALID and M_AXI_RRESP(1)); + -- when M_AXI_RVALID is asserted by slave + axi_rready <= '1'; + elsif (axi_rready = '1') then + -- deassert after one clock cycle + axi_rready <= '0'; + end if; + end if; + end if; + end process; + + --Flag write errors + read_resp_error <= (axi_rready and M_AXI_RVALID and M_AXI_RRESP(1)); ---------------------------------- @@ -444,261 +476,265 @@ begin --match. --Modify these as desired for different address patterns. - -- Write Addresses - process(M_AXI_ACLK) - begin - if (rising_edge (M_AXI_ACLK)) then - if (M_AXI_ARESETN = '0' or init_txn_pulse = '1') then - axi_awaddr <= (others => '0'); - elsif (M_AXI_AWREADY = '1' and axi_awvalid = '1') then - -- Signals a new write address/ write data is - -- available by user logic - axi_awaddr <= std_logic_vector (unsigned(axi_awaddr) + 4); - end if; - end if; - end process; - - -- Read Addresses - process(M_AXI_ACLK) - begin - if (rising_edge (M_AXI_ACLK)) then - if (M_AXI_ARESETN = '0' or init_txn_pulse = '1' ) then - axi_araddr <= (others => '0'); - elsif (M_AXI_ARREADY = '1' and axi_arvalid = '1') then - -- Signals a new write address/ write data is - -- available by user logic - axi_araddr <= std_logic_vector (unsigned(axi_araddr) + 4); - end if; - end if; - end process; - - -- Write data - process(M_AXI_ACLK) - begin - if (rising_edge (M_AXI_ACLK)) then - if (M_AXI_ARESETN = '0' or init_txn_pulse = '1') then - axi_wdata <= C_M_START_DATA_VALUE; - elsif (M_AXI_WREADY = '1' and axi_wvalid = '1') then - -- Signals a new write address/ write data is - -- available by user logic - axi_wdata <= std_logic_vector (unsigned(C_M_START_DATA_VALUE) + unsigned(write_index)); - end if; - end if; - end process; - - - -- Expected read data - process(M_AXI_ACLK) - begin - if (rising_edge (M_AXI_ACLK)) then - if (M_AXI_ARESETN = '0' or init_txn_pulse = '1' ) then - expected_rdata <= C_M_START_DATA_VALUE; - elsif (M_AXI_RVALID = '1' and axi_rready = '1') then - -- Signals a new write address/ write data is - -- available by user logic - expected_rdata <= std_logic_vector (unsigned(C_M_START_DATA_VALUE) + unsigned(read_index)); - end if; - end if; - end process; - --implement master command interface state machine - MASTER_EXECUTION_PROC:process(M_AXI_ACLK) - begin - if (rising_edge (M_AXI_ACLK)) then - if (M_AXI_ARESETN = '0' ) then - -- reset condition - -- All the signals are ed default values under reset condition - mst_exec_state <= IDLE; - start_single_write <= '0'; - write_issued <= '0'; - start_single_read <= '0'; - read_issued <= '0'; - compare_done <= '0'; - ERROR <= '0'; - else - -- state transition - case (mst_exec_state) is - - when IDLE => + -- Write Addresses + process(M_AXI_ACLK) + begin + if (rising_edge (M_AXI_ACLK)) then + if (M_AXI_ARESETN = '0' or init_txn_pulse = '1') then + axi_awaddr <= (others => '0'); + elsif (M_AXI_AWREADY = '1' and axi_awvalid = '1') then + -- Signals a new write address/ write data is + -- available by user logic + axi_awaddr <= std_logic_vector (unsigned(axi_awaddr) + 4); + end if; + end if; + end process; + + -- Read Addresses + process(M_AXI_ACLK) + begin + if (rising_edge (M_AXI_ACLK)) then + if (M_AXI_ARESETN = '0' or init_txn_pulse = '1' ) then + axi_araddr <= (others => '0'); + elsif (M_AXI_ARREADY = '1' and axi_arvalid = '1') then + -- Signals a new write address/ write data is + -- available by user logic + axi_araddr <= std_logic_vector (unsigned(axi_araddr) + 4); + end if; + end if; + end process; + + -- Write data + process(M_AXI_ACLK) + begin + if (rising_edge (M_AXI_ACLK)) then + if (M_AXI_ARESETN = '0' or init_txn_pulse = '1') then + axi_wdata <= C_M_START_DATA_VALUE; + elsif (M_AXI_WREADY = '1' and axi_wvalid = '1') then + -- Signals a new write address/ write data is + -- available by user logic + axi_wdata <= std_logic_vector (unsigned(C_M_START_DATA_VALUE) + unsigned(write_index)); + end if; + end if; + end process; + + + -- Expected read data + process(M_AXI_ACLK) + begin + if (rising_edge (M_AXI_ACLK)) then + if (M_AXI_ARESETN = '0' or init_txn_pulse = '1' ) then + expected_rdata <= C_M_START_DATA_VALUE; + elsif (M_AXI_RVALID = '1' and axi_rready = '1') then + -- Signals a new write address/ write data is + -- available by user logic + expected_rdata <= std_logic_vector (unsigned(C_M_START_DATA_VALUE) + unsigned(read_index)); + end if; + end if; + end process; + --implement master command interface state machine + MASTER_EXECUTION_PROC:process(M_AXI_ACLK) + begin + if (rising_edge (M_AXI_ACLK)) then + if (M_AXI_ARESETN = '0' ) then + -- reset condition + -- All the signals are ed default values under reset condition + mst_exec_state <= IDLE; + start_single_write <= '0'; + write_issued <= '0'; + start_single_read <= '0'; + read_issued <= '0'; + compare_done <= '0'; + ERROR <= '0'; + pwm_state_prev <= "00"; + else + pwm_state_prev <= pwm_state_prev; + -- state transition + case (mst_exec_state) is + + when IDLE => -- This state is responsible to initiate - -- AXI transaction when init_txn_pulse is asserted - if ( init_txn_pulse = '1') then - mst_exec_state <= INIT_WRITE; + -- AXI transaction when init_txn_pulse is asserted + if ( init_txn_pulse = '1') then + mst_exec_state <= INIT_WRITE; ERROR <= '0'; compare_done <= '0'; - else - mst_exec_state <= IDLE; - end if; - - when INIT_WRITE => - -- This state is responsible to issue start_single_write pulse to - -- initiate a write transaction. Write transactions will be - -- issued until last_write signal is asserted. - -- write controller - if (writes_done = '1') then - mst_exec_state <= INIT_READ; - else - mst_exec_state <= INIT_WRITE; - - if (axi_awvalid = '0' and axi_wvalid = '0' and M_AXI_BVALID = '0' and - last_write = '0' and start_single_write = '0' and write_issued = '0') then - start_single_write <= '1'; - write_issued <= '1'; - elsif (axi_bready = '1') then - write_issued <= '0'; - else - start_single_write <= '0'; --Negate to generate a pulse - end if; - end if; - - when INIT_READ => - -- This state is responsible to issue start_single_read pulse to - -- initiate a read transaction. Read transactions will be - -- issued until last_read signal is asserted. - -- read controller - if (reads_done = '1') then - mst_exec_state <= INIT_COMPARE; - else - mst_exec_state <= INIT_READ; - - if (axi_arvalid = '0' and M_AXI_RVALID = '0' and last_read = '0' and - start_single_read = '0' and read_issued = '0') then - start_single_read <= '1'; - read_issued <= '1'; - elsif (axi_rready = '1') then - read_issued <= '0'; - else - start_single_read <= '0'; --Negate to generate a pulse - end if; - end if; - - when INIT_COMPARE => - -- This state is responsible to issue the state of comparison - -- of written data with the read data. If no error flags are set, - -- compare_done signal will be asseted to indicate success. - ERROR <= error_reg; - mst_exec_state <= IDLE; - compare_done <= '1'; - - when others => - mst_exec_state <= IDLE; - end case ; - end if; - end if; - end process; - - --Terminal write count - process(M_AXI_ACLK) - begin - if (rising_edge (M_AXI_ACLK)) then - if (M_AXI_ARESETN = '0' or init_txn_pulse = '1') then - -- reset condition - last_write <= '0'; - else - --The last write should be associated with a write address ready response + else + mst_exec_state <= IDLE; + end if; + + when INIT_WRITE => + -- This state is responsible to issue start_single_write pulse to + -- initiate a write transaction. Write transactions will be + -- issued until last_write signal is asserted. + -- write controller + if (writes_done = '1') then + -- mst_exec_state <= INIT_READ; + mst_exec_state <= IDLE; + pwm_state_prev <= pwm_state_inpr; + else + mst_exec_state <= INIT_WRITE; + + if (axi_awvalid = '0' and axi_wvalid = '0' and M_AXI_BVALID = '0' and + last_write = '0' and start_single_write = '0' and write_issued = '0') then + start_single_write <= '1'; + write_issued <= '1'; + elsif (axi_bready = '1') then + write_issued <= '0'; + else + start_single_write <= '0'; --Negate to generate a pulse + end if; + end if; + + when INIT_READ => + -- This state is responsible to issue start_single_read pulse to + -- initiate a read transaction. Read transactions will be + -- issued until last_read signal is asserted. + -- read controller + if (reads_done = '1') then + mst_exec_state <= INIT_COMPARE; + else + mst_exec_state <= INIT_READ; + + if (axi_arvalid = '0' and M_AXI_RVALID = '0' and last_read = '0' and + start_single_read = '0' and read_issued = '0') then + start_single_read <= '1'; + read_issued <= '1'; + elsif (axi_rready = '1') then + read_issued <= '0'; + else + start_single_read <= '0'; --Negate to generate a pulse + end if; + end if; + + when INIT_COMPARE => + -- This state is responsible to issue the state of comparison + -- of written data with the read data. If no error flags are set, + -- compare_done signal will be asseted to indicate success. + ERROR <= error_reg; + mst_exec_state <= IDLE; + compare_done <= '1'; + + when others => + mst_exec_state <= IDLE; + end case ; + end if; + end if; + end process; + + --Terminal write count + process(M_AXI_ACLK) + begin + if (rising_edge (M_AXI_ACLK)) then + if (M_AXI_ARESETN = '0' or init_txn_pulse = '1') then + -- reset condition + last_write <= '0'; + else + --The last write should be associated with a write address ready response if (write_index = STD_LOGIC_VECTOR(TO_UNSIGNED(C_M_TRANSACTIONS_NUM, TRANS_NUM_BITS+1)) and M_AXI_AWREADY = '1') then - last_write <= '1'; - end if; - end if; - end if; - end process; - - --/* - -- Check for last write completion. - -- - -- This logic is to qualify the last write count with the final write - -- response. This demonstrates how to confirm that a write has been - -- committed. - -- */ - process(M_AXI_ACLK) - begin - if (rising_edge (M_AXI_ACLK)) then - if (M_AXI_ARESETN = '0' or init_txn_pulse = '1') then - -- reset condition - writes_done <= '0'; - else - if (last_write = '1' and M_AXI_BVALID = '1' and axi_bready = '1') then - --The writes_done should be associated with a bready response - writes_done <= '1'; - end if; - end if; - end if; - end process; - - -------------- - --Read example - -------------- - - --Terminal Read Count - - process(M_AXI_ACLK) - begin - if (rising_edge (M_AXI_ACLK)) then - if (M_AXI_ARESETN = '0' or init_txn_pulse = '1') then - last_read <= '0'; - else + last_write <= '1'; + end if; + end if; + end if; + end process; + + --/* + -- Check for last write completion. + -- + -- This logic is to qualify the last write count with the final write + -- response. This demonstrates how to confirm that a write has been + -- committed. + -- */ + process(M_AXI_ACLK) + begin + if (rising_edge (M_AXI_ACLK)) then + if (M_AXI_ARESETN = '0' or init_txn_pulse = '1') then + -- reset condition + writes_done <= '0'; + else + if (last_write = '1' and M_AXI_BVALID = '1' and axi_bready = '1') then + --The writes_done should be associated with a bready response + writes_done <= '1'; + end if; + end if; + end if; + end process; + + -------------- + --Read example + -------------- + + --Terminal Read Count + + process(M_AXI_ACLK) + begin + if (rising_edge (M_AXI_ACLK)) then + if (M_AXI_ARESETN = '0' or init_txn_pulse = '1') then + last_read <= '0'; + else if (read_index = STD_LOGIC_VECTOR(TO_UNSIGNED(C_M_TRANSACTIONS_NUM, TRANS_NUM_BITS+1)) and (M_AXI_ARREADY = '1') ) then - --The last read should be associated with a read address ready response - last_read <= '1'; - end if; - end if; - end if; - end process; - - - --/* - -- Check for last read completion. - -- - -- This logic is to qualify the last read count with the final read - -- response/data. - -- */ - process(M_AXI_ACLK) - begin - if (rising_edge (M_AXI_ACLK)) then - if (M_AXI_ARESETN = '0' or init_txn_pulse = '1') then - reads_done <= '0'; - else - if (last_read = '1' and M_AXI_RVALID = '1' and axi_rready = '1') then - --The reads_done should be associated with a read ready response - reads_done <= '1'; - end if; - end if; - end if; - end process; - - - ------------------------------/ - --Example design error register - ------------------------------/ - - --Data Comparison - process(M_AXI_ACLK) - begin - if (rising_edge (M_AXI_ACLK)) then - if (M_AXI_ARESETN = '0' or init_txn_pulse = '1') then - read_mismatch <= '0'; - else - if ((M_AXI_RVALID = '1' and axi_rready = '1') and M_AXI_RDATA /= expected_rdata) then - --The read data when available (on axi_rready) is compared with the expected data - read_mismatch <= '1'; - end if; - end if; - end if; - end process; - - -- Register and hold any data mismatches, or read/write interface errors - process(M_AXI_ACLK) - begin - if (rising_edge (M_AXI_ACLK)) then - if (M_AXI_ARESETN = '0' or init_txn_pulse = '1') then - error_reg <= '0'; - else - if (read_mismatch = '1' or write_resp_error = '1' or read_resp_error = '1') then - --Capture any error types - error_reg <= '1'; - end if; - end if; - end if; - end process; + --The last read should be associated with a read address ready response + last_read <= '1'; + end if; + end if; + end if; + end process; + + + --/* + -- Check for last read completion. + -- + -- This logic is to qualify the last read count with the final read + -- response/data. + -- */ + process(M_AXI_ACLK) + begin + if (rising_edge (M_AXI_ACLK)) then + if (M_AXI_ARESETN = '0' or init_txn_pulse = '1') then + reads_done <= '0'; + else + if (last_read = '1' and M_AXI_RVALID = '1' and axi_rready = '1') then + --The reads_done should be associated with a read ready response + reads_done <= '1'; + end if; + end if; + end if; + end process; + + + ------------------------------/ + --Example design error register + ------------------------------/ + + --Data Comparison + process(M_AXI_ACLK) + begin + if (rising_edge (M_AXI_ACLK)) then + if (M_AXI_ARESETN = '0' or init_txn_pulse = '1') then + read_mismatch <= '0'; + else + if ((M_AXI_RVALID = '1' and axi_rready = '1') and M_AXI_RDATA /= expected_rdata) then + --The read data when available (on axi_rready) is compared with the expected data + read_mismatch <= '1'; + end if; + end if; + end if; + end process; + + -- Register and hold any data mismatches, or read/write interface errors + process(M_AXI_ACLK) + begin + if (rising_edge (M_AXI_ACLK)) then + if (M_AXI_ARESETN = '0' or init_txn_pulse = '1') then + error_reg <= '0'; + else + if (read_mismatch = '1' or write_resp_error = '1' or read_resp_error = '1') then + --Capture any error types + error_reg <= '1'; + end if; + end if; + end if; + end process; -- Add user logic here diff --git a/system/ip/axi_pwm_coprocessor_1.0/hdl/axi_pwm_coprocessor_v1_0_S00_AXI.vhd b/system/ip/axi_pwm_coprocessor_1.0/hdl/axi_pwm_coprocessor_v1_0_S00_AXI.vhd index b7190c5..bf1deaf 100644 --- a/system/ip/axi_pwm_coprocessor_1.0/hdl/axi_pwm_coprocessor_v1_0_S00_AXI.vhd +++ b/system/ip/axi_pwm_coprocessor_1.0/hdl/axi_pwm_coprocessor_v1_0_S00_AXI.vhd @@ -16,7 +16,13 @@ entity axi_pwm_coprocessor_v1_0_S00_AXI is ); port ( -- Users to add ports here + signal pwm_state_o : out std_logic_vector(1 downto 0); + signal pwm_enabled_o : out std_logic; + signal pwm_wr_addr : out std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); + signal pwm_wr0 : out std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); + signal pwm_wr1 : out std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); + signal pwm_wr2 : out std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); -- User ports ends -- Do not modify the ports beyond this line @@ -36,11 +42,11 @@ entity axi_pwm_coprocessor_v1_0_S00_AXI is -- 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) + -- 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. + -- 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. @@ -121,6 +127,11 @@ architecture arch_imp of axi_pwm_coprocessor_v1_0_S00_AXI is signal reg_data_out :std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); signal byte_index : integer; + constant PWM_BITS : integer := 30; + + signal pwm_state : std_logic_vector(1 downto 0); + signal pwm_enabled : std_logic; + begin -- I/O Connections assignments @@ -137,17 +148,20 @@ begin -- S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_awready is -- de-asserted when reset is low. + pwm_state_o <= pwm_state; + pwm_enabled_o <= pwm_enabled; + process (S_AXI_ACLK) begin - if rising_edge(S_AXI_ACLK) then + if rising_edge(S_AXI_ACLK) then if S_AXI_ARESETN = '0' then axi_awready <= '0'; else if (axi_awready = '0' and S_AXI_AWVALID = '1' and S_AXI_WVALID = '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. + -- on the write address and data bus. This design + -- expects no outstanding transactions. axi_awready <= '1'; else axi_awready <= '0'; @@ -157,12 +171,12 @@ begin 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. + -- 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 rising_edge(S_AXI_ACLK) then if S_AXI_ARESETN = '0' then axi_awaddr <= (others => '0'); else @@ -171,32 +185,32 @@ begin axi_awaddr <= S_AXI_AWADDR; end if; end if; - end if; - end process; + 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. + -- 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 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') then - -- slave is ready to accept write data when + -- 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. + -- 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; + end process; -- Implement memory mapped register select and write logic generation -- The write data is accepted and written to memory mapped registers when @@ -208,9 +222,12 @@ begin 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); + variable loc_addr :std_logic_vector(OPT_MEM_ADDR_BITS downto 0); + variable pwm_val : natural range 0 to (2**PWM_BITS - 1); + variable pwm_per : natural range 0 to (2**PWM_BITS - 1); + variable pwm_cnt : natural range 0 to (2**PWM_BITS - 1); begin - if rising_edge(S_AXI_ACLK) then + if rising_edge(S_AXI_ACLK) then if S_AXI_ARESETN = '0' then slv_reg0 <= (others => '0'); slv_reg1 <= (others => '0'); @@ -220,14 +237,54 @@ begin slv_reg5 <= (others => '0'); slv_reg6 <= (others => '0'); slv_reg7 <= (others => '0'); + pwm_state <= "00"; + pwm_enabled <= '0'; else + pwm_per := to_integer(unsigned(slv_reg0(PWM_BITS - 1 downto 0))); + pwm_val := to_integer(unsigned(slv_reg1(PWM_BITS - 1 downto 0))); + pwm_cnt := to_integer(unsigned(slv_reg2(PWM_BITS - 1 downto 0))); + + pwm_wr_addr <= slv_reg3; + pwm_wr0 <= slv_reg4; + pwm_wr1 <= slv_reg5; + pwm_wr2 <= slv_reg6; + + slv_reg0 <= slv_reg0; + slv_reg1 <= slv_reg1; + slv_reg2 <= slv_reg2; + slv_reg3 <= slv_reg3; + slv_reg4 <= slv_reg4; + slv_reg5 <= slv_reg5; + slv_reg6 <= slv_reg6; + slv_reg7 <= slv_reg7; + + if (slv_reg0(31) = '0') then -- The most significant bit of the period enables PWM + pwm_state <= "00"; + pwm_enabled <= '0'; + slv_reg2(PWM_BITS - 1 downto 0) <= (others => '0'); + else + pwm_enabled <= '1'; + if pwm_cnt >= pwm_per then + slv_reg2(PWM_BITS - 1 downto 0) <= std_logic_vector(to_unsigned(0, PWM_BITS)); + else + slv_reg2(PWM_BITS - 1 downto 0) <= std_logic_vector(to_unsigned(pwm_cnt + 1, PWM_BITS)); + end if; + if (pwm_cnt >= pwm_val) then + pwm_state <= "00"; + elsif pwm_cnt = 0 then + pwm_state <= slv_reg1(31 downto 30); -- Two MSB bits of the PWM value controls direction + else + pwm_state <= pwm_state; + end if; + end if; + 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"000" => 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 + -- 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; @@ -235,7 +292,7 @@ begin when b"001" => 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 + -- 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; @@ -243,7 +300,7 @@ begin when b"010" => 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 + -- 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; @@ -251,7 +308,7 @@ begin when b"011" => 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 + -- 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; @@ -259,7 +316,7 @@ begin when b"100" => 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 + -- Respective byte enables are asserted as per write strobes -- slave registor 4 slv_reg4(byte_index*8+7 downto byte_index*8) <= S_AXI_WDATA(byte_index*8+7 downto byte_index*8); end if; @@ -267,7 +324,7 @@ begin when b"101" => 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 + -- Respective byte enables are asserted as per write strobes -- slave registor 5 slv_reg5(byte_index*8+7 downto byte_index*8) <= S_AXI_WDATA(byte_index*8+7 downto byte_index*8); end if; @@ -275,7 +332,7 @@ begin when b"110" => 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 + -- Respective byte enables are asserted as per write strobes -- slave registor 6 slv_reg6(byte_index*8+7 downto byte_index*8) <= S_AXI_WDATA(byte_index*8+7 downto byte_index*8); end if; @@ -283,59 +340,50 @@ begin when b"111" => 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 + -- Respective byte enables are asserted as per write strobes -- slave registor 7 slv_reg7(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; - slv_reg4 <= slv_reg4; - slv_reg5 <= slv_reg5; - slv_reg6 <= slv_reg6; - slv_reg7 <= slv_reg7; end case; end if; end if; - end if; - end process; + 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 + -- 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 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"; + 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; + 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 + -- 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 rising_edge(S_AXI_ACLK) then if S_AXI_ARESETN = '0' then axi_arready <= '0'; axi_araddr <= (others => '1'); @@ -343,23 +391,23 @@ begin 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; + -- Read Address latching + axi_araddr <= S_AXI_ARADDR; else axi_arready <= '0'; end if; end if; - end if; - end process; + 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). + -- 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 @@ -374,7 +422,7 @@ begin 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 if; end process; @@ -409,7 +457,7 @@ begin when others => reg_data_out <= (others => '0'); end case; - end process; + end process; -- Output register or memory read data process( S_AXI_ACLK ) is @@ -419,12 +467,12 @@ begin 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 + -- 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 if; end process; -- 2.39.2