URL
https://opencores.org/ocsvn/plb2wbbridge/plb2wbbridge/trunk
Subversion Repositories plb2wbbridge
[/] [plb2wbbridge/] [trunk/] [systems/] [EDK_Libs/] [WishboneIPLib/] [pcores/] [plb2wb_bridge_v1_00_a/] [hdl/] [vhdl/] [plb2wb_tcu.vhd] - Rev 2
Compare with Previous | Blame | View Log
---------------------------------------------------------------------- ---- ---- ---- PLB2WB-Bridge ---- ---- ---- ---- This file is part of the PLB-to-WB-Bridge project ---- ---- http://opencores.org/project,plb2wbbridge ---- ---- ---- ---- Description ---- ---- Implementation of a PLB-to-WB-Bridge according to ---- ---- PLB-to-WB Bridge specification document. ---- ---- ---- ---- To Do: ---- ---- Nothing ---- ---- ---- ---- Author(s): ---- ---- - Christian Haettich ---- ---- feddischson@opencores.org ---- ---- ---- ---------------------------------------------------------------------- ---- ---- ---- Copyright (C) 2010 Authors ---- ---- ---- ---- This source file may be used and distributed without ---- ---- restriction provided that this copyright statement is not ---- ---- removed from the file and that any derivative work contains ---- ---- the original copyright notice and the associated disclaimer. ---- ---- ---- ---- This source file is free software; you can redistribute it ---- ---- and/or modify it under the terms of the GNU Lesser General ---- ---- Public License as published by the Free Software Foundation; ---- ---- either version 2.1 of the License, or (at your option) any ---- ---- later version. ---- ---- ---- ---- This source is distributed in the hope that it will be ---- ---- useful, but WITHOUT ANY WARRANTY; without even the implied ---- ---- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ---- ---- PURPOSE. See the GNU Lesser General Public License for more ---- ---- details. ---- ---- ---- ---- You should have received a copy of the GNU Lesser General ---- ---- Public License along with this source; if not, download it ---- ---- from http://www.opencores.org/lgpl.shtml ---- ---- ---- ---------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use ieee.std_logic_unsigned.all; library plb2wb_bridge_v1_00_a; use plb2wb_bridge_v1_00_a.plb2wb_pkg.all; entity plb2wb_tcu is generic( C_SPLB_NUM_MASTERS : integer := 1; C_SPLB_MID_WIDTH : integer := 3; C_SPLB_SIZE_WIDTH : integer := 4; C_SPLB_NATIVE_BE_WIDTH : integer := 4; C_SPLB_DWIDTH : integer := 128; C_SPLB_TYPE_WIDTH : integer := 4; C_SPLB_SUPPORT_BUR_LINE : integer := 1; WB_PIC_INTS : integer := 0; WB_PIC_INT_LEVEL : std_logic := '1'; WB_TIMEOUT_CYCLES : integer := 10; WB_SUPPORT_BLOCK : integer := 1 ); port( wb_clk_i : in std_logic; wb_ack_i : in std_logic; wb_err_i : in std_logic; wb_rty_i : in std_logic; wb_rst_i : in std_logic; wb_pic_int_i : in std_logic_vector( WB_PIC_INTS-1 downto 0 ); AMU_deviceSelect : in std_logic; AMU_statusSelect : in std_logic; AMU_bufEmpty : in std_logic; AMU_bufFull : in std_logic; AMU_buf_RNW : in std_logic; AMU_buf_size : in std_logic_vector( C_SPLB_SIZE_WIDTH-1 downto 0 ); AMU_buf_BE : in std_logic_vector( C_SPLB_NATIVE_BE_WIDTH-1 downto 0 ); AMU_pipe_size : in std_logic_vector( 0 to C_SPLB_SIZE_WIDTH-1 ); AMU_pipe_rmID : in std_logic_vector( 0 to C_SPLB_MID_WIDTH -1 ); AMU_pipe_wmID : in std_logic_vector( 0 to C_SPLB_MID_WIDTH -1 ); AMU_pipe_BE : in std_logic_vector( 0 to C_SPLB_NATIVE_BE_WIDTH-1 ); AMU_pipe_rStatusSelect : in std_logic; AMU_pipe_wStatusSelect : in std_logic; WBF_empty : in std_logic; WBF_full : in std_logic; RBF_empty : in std_logic; RBF_almostEmpty : in std_logic; RBF_full : in std_logic; SPLB_Clk : in std_logic; plb2wb_rst : in std_logic; PLB_MSize : in std_logic_vector( 0 to 1 ); PLB_TAttribute : in std_logic_vector( 0 to 15 ); PLB_lockErr : in std_logic; PLB_abort : in std_logic; PLB_rdBurst : in std_logic; PLB_wrBurst : in std_logic; PLB_RNW : in std_logic; PLB_PAValid : in std_logic; PLB_masterID : in std_logic_vector( 0 to C_SPLB_MID_WIDTH-1 ); PLB_rdPrim : in std_logic; PLB_wrPrim : in std_logic; PLB_size : in std_logic_vector( 0 to C_SPLB_SIZE_WIDTH-1 ); PLB_BE : in std_logic_vector( 0 to C_SPLB_DWIDTH/8-1 ); PLB_type : in std_logic_vector( 0 to C_SPLB_TYPE_WIDTH -1 ); STU_abort : in std_logic; STU_continue : in std_logic; RBF_rdErrOut : in std_logic; RBF_rdErrIn : out std_logic; Sl_MRdErr : out std_logic_vector( 0 to C_SPLB_NUM_MASTERS-1 ); Sl_MWrErr : out std_logic_vector( 0 to C_SPLB_NUM_MASTERS-1 ); Sl_wrDAck : out std_logic; Sl_wrComp : out std_logic; Sl_wrBTerm : out std_logic; Sl_rdDAck : out std_logic; Sl_rdComp : out std_logic; Sl_rdBTerm : out std_logic; Sl_rdWdAddr : out std_logic_vector( 0 to 3 ); Sl_wait : out std_logic; Sl_rearbitrate : out std_logic; TCU_wbufWEn : out std_logic; TCU_wbufREn : out std_logic; TCU_rbufWEn : out std_logic; TCU_rbufREn : out std_logic; TCU_adrBufWEn : out std_logic; TCU_adrBufREn : out std_logic; TCU_rpipeRdEn : out std_logic; TCU_wpipeRdEn : out std_logic; TCU_enRdDBus : out std_logic; TCU_MRBusy : out std_logic_vector( 0 to C_SPLB_NUM_MASTERS-1 ); TCU_addrAck : out std_logic; TCU_adr_offset : out std_logic_vector( 3 downto 0 ); TCU_stuLatchPA : out std_logic; TCU_stuLatchSA : out std_logic; TCU_stuWritePA : out std_logic; TCU_stuWriteSA : out std_logic; TCU_stat2plb_en : out std_logic; TCU_enStuRdDBus : out std_logic; TCU_wb_status_info : out std_logic_vector( STATUS2PLB_INFO_SIZE-1 downto 0 ); TCU_wb_irq_info : out std_logic_vector( IRQ_INFO_SIZE-1 downto 0 ); wb_lock_o : out std_logic; wb_stb_o : out std_logic; wb_we_o : out std_logic; wb_cyc_o : out std_logic ); end entity plb2wb_tcu; architecture IMP of plb2wb_tcu is signal TCU_wbufWEn_t : std_logic; signal TCU_wbufREn_t : std_logic; signal TCU_adrBufWEn_w : std_logic; signal TCU_adrBufWEn_r : std_logic; signal TCU_rbufWEn_t : std_logic; signal TCU_rbufREn_t : std_logic; signal TCU_stuWritePA_t : std_logic; signal TCU_stuWriteSA_t : std_logic; signal Sl_rdComp_t : std_logic; signal Sl_wrComp_t : std_logic; signal Sl_rdDAck_t : std_logic; signal TCU_rpipeRdEn_t : std_logic; signal TCU_wpipeRdEn_t : std_logic; -- -- Wishbone current and next state type wb_trans_state is ( wb_idle, wb_write, wb_read, wb_write_rty, wb_read_rty, wb_write_stall ); type wb_trans_state_type is record state : wb_trans_state; transfer_count : std_logic_vector( 3 downto 0 ); abort : std_logic; end record; signal c_wb_state, n_wb_state : wb_trans_state_type; -- -- PLB current and next state type plb_wtrans_state is( plb_widle, plb_write, plb_burst_write ); type plb_rtrans_state is( plb_ridle, plb_read, plb_read_ack, plb_line_read, plb_line_read_ack, plb_burst_read, plb_burst_read_ack, plb_wait_line_read, plb_wait_burst_read ); type plb_rtrans_state_type is record state : plb_rtrans_state; r_master_id : std_logic_vector( C_SPLB_MID_WIDTH-1 downto 0 ); r_secondary : std_logic; transfer_count : std_logic_vector( 0 to 3 ); transfer_size : std_logic_vector( 0 to C_SPLB_SIZE_WIDTH-1 ); status_transfer : std_logic; end record; type plb_wtrans_state_type is record state : plb_wtrans_state; w_master_id : std_logic_vector( C_SPLB_MID_WIDTH-1 downto 0 ); w_secondary : std_logic; transfer_count : std_logic_vector( 0 to 3 ); transfer_size : std_logic_vector( 0 to C_SPLB_SIZE_WIDTH-1 ); status_transfer : std_logic; end record; signal c_plb_wstate : plb_wtrans_state_type; -- current write state signal n_plb_wstate : plb_wtrans_state_type; -- next write state signal c_plb_rstate : plb_rtrans_state_type; -- current read state signal n_plb_rstate : plb_rtrans_state_type; -- next read state signal mbusy_read_out : std_logic_vector( 0 to C_SPLB_NUM_MASTERS-1 ); signal mbusy_write_out : std_logic_vector( 0 to C_SPLB_NUM_MASTERS-1 ); signal start_plb_w : std_logic; -- start plb write (to wb side) signal start_plb_r : std_logic; -- start plb read (from wb side) signal start_plb_stat_w : std_logic; -- start plb status write signal start_plb_stat_r : std_logic; -- start plb status read signal start_plb_sec_w : std_logic; -- start plb write (to wb side, pipelined) signal start_plb_sec_r : std_logic; -- start plb read (from wb side, pipelined) signal start_plb_sec_stat_r : std_logic; -- start plb write to status (pipelined) signal start_plb_sec_stat_w : std_logic; -- start plb read from status (pipelined) signal start_wb_w : std_logic; -- start wb write signal start_wb_r : std_logic; -- start wb read signal wb_ack : std_logic; signal wb_rty : std_logic; signal wb_err : std_logic; signal addrAck_w : std_logic; signal addrAck_r : std_logic; signal TCU_stuLatchPA_r : std_logic; signal TCU_stuLatchSA_r : std_logic; signal TCU_stuLatchPA_w : std_logic; signal TCU_stuLatchSA_w : std_logic; signal wb_rst_short : std_logic; signal pic_int_ahigh : std_logic_vector( WB_PIC_INTS-1 downto 0 ); signal pic_int_ahigh_short : std_logic_vector( WB_PIC_INTS-1 downto 0 ); signal pic_int2plb_en : std_logic; ----- -- wishbone timeout counter -- constant WB_TOUT_COUNTER_SIZE : integer := log2( WB_TIMEOUT_CYCLES ); constant WB_TOUT_MAX_VALUE : std_logic_vector( WB_TOUT_COUNTER_SIZE-1 downto 0 ) := std_logic_vector( to_unsigned( WB_TIMEOUT_CYCLES-1, WB_TOUT_COUNTER_SIZE ) ); constant WB_TOUT_MIN_VALUE : std_logic_vector( WB_TOUT_COUNTER_SIZE-1 downto 0 ) := ( others => '0' ); signal wb_tout_counter : std_logic_vector( WB_TOUT_COUNTER_SIZE-1 downto 0 ); signal wb_tout_count : std_logic; signal wb_tout_reset : std_logic; signal wb_tout_alarm : std_logic; begin TCU_wbufWEn <= TCU_wbufWEn_t; TCU_wbufREn <= TCU_wbufREn_t; TCU_adrBufWEn <= TCU_adrBufWEn_w or TCU_adrBufWEn_r; TCU_rbufWEn <= TCU_rbufWEn_t; TCU_rbufREn <= TCU_rbufREn_t; Sl_rdComp <= Sl_rdComp_t; Sl_wrComp <= Sl_wrComp_t; Sl_rdDAck <= Sl_rdDAck_t; TCU_rpipeRdEn <= TCU_rpipeRdEn_t; TCU_wpipeRdEn <= TCU_wpipeRdEn_t; TCU_stuWritePA <= TCU_stuWritePA_t; TCU_stuWriteSA <= TCU_stuWriteSA_t; TCU_stuLatchSA <= TCU_stuLatchSA_r or TCU_stuLatchSA_w; TCU_stuLatchPA <= TCU_stuLatchPA_r or TCU_stuLatchPA_w; TCU_addrAck <= addrAck_w or addrAck_r; Sl_rearbitrate <= '0'; -- there is no situation, where we want to reabitrate Sl_wait <= '1' when addrAck_w = '0' and addrAck_r = '0' and AMU_deviceSelect = '1' and PLB_PAValid = '1' and PLB_RNW = '0' and AMU_bufFull = '1'; ------ -- -- interrupt signals: they are converted to active-high signals, -- which are only for one clock cycle '1' -- pic_ints : if WB_PIC_INTS > 0 generate -- -- Generate the active-high interrupt levels -- (we work internaly only with active-high interrupt levels) -- gen_active_high1 : if WB_PIC_INT_LEVEL = '0' generate pic_int_ahigh <= not wb_pic_int_i; end generate gen_active_high1; gen_active_high2 : if WB_PIC_INT_LEVEL = '1' generate pic_int_ahigh <= wb_pic_int_i; end generate gen_active_high2; -- -- Generate short impulses (of one clock cycle) -- gen_active_high_short : for i in 0 to WB_PIC_INTS-1 generate ah_short : entity plb2wb_bridge_v1_00_a.plb2wb_short_impulse( IMP ) port map( CLK => wb_clk_i, RESET => plb2wb_rst, IMPULSE => pic_int_ahigh(i), SHORT_IMPULSE => pic_int_ahigh_short(i) ); end generate; end generate; -- ----- short_impulse : entity plb2wb_bridge_v1_00_a.plb2wb_short_impulse( IMP ) port map ( CLK => wb_clk_i, RESET => plb2wb_rst, IMPULSE => wb_rst_i, SHORT_IMPULSE => wb_rst_short ); ------------------------------ -- -- This signals are '1' if a transfer is started: -- (burst and line transfers are supported) -- -- start_plb_w: start a write transfer to the WB side -- start_plb_r: start a read transfer from the WB side -- start_plb_stat_w: start a write transfer to the status registers -- start_plb_stat_r: start a read transfer from the status registers -- -- with_plb_bursts : if C_SPLB_SUPPORT_BUR_LINE > 0 generate start_plb_w <= '1' when ( -- we are in the idle state c_plb_wstate.state = plb_widle -- Address in our range, primary-addr is valid and it is a write transfer and AMU_deviceSelect = '1' and PLB_PAValid = '1' and PLB_RNW = '0' -- this transfer-type is implemented --(normal, line and burst -> all fixed-length word bursts) and ( PLB_size( 0 to 1 ) = "00" or ( PLB_size = "1010" and PLB_BE( 0 to 3 ) /= "0000" ) ) -- we are not transfering data from the read pipe and TCU_rpipeRdEn_t /= '1' -- the address buffer is not full and AMU_bufFull = '0' -- supported transfer-type (only mem-type is supported, see PLB-Spec. page 43) and ( PLB_type = "000" or PLB_type = "110" ) ) else '0'; start_plb_r <= '1' when( -- we are in the idle state c_plb_rstate.state = plb_ridle -- Address in our range, primary-addr is valid and it is a read transfer and AMU_deviceSelect = '1' and PLB_PAValid = '1' and PLB_RNW = '1' -- this transfer-type is implemented (normal and line) and ( PLB_size( 0 to 1 ) = "00" or ( PLB_size = "1010" and PLB_BE( 0 to 3 ) /="0000" ) ) -- we are not transfering data from the write-pipe and TCU_wpipeRdEn_t /= '1' -- the address buffer is not full and AMU_bufFull = '0' -- supported transfer-type (only mem-type is supported, see PLB-Spec. page 43) and ( PLB_type = "000" or PLB_type = "110" ) ) else '0'; start_plb_stat_w <= '1' when ( -- we are in the idle state c_plb_wstate.state = plb_widle -- Address in our range, primary-addr is valid and it is a write transfer and AMU_statusSelect = '1' and PLB_PAValid = '1' and PLB_RNW = '0' -- this transfer-type is implemented --(normal, line and burst -> all fixed-length word bursts) and ( PLB_size( 0 to 1 ) = "00" or ( PLB_size = "1010" and PLB_BE( 0 to 3 ) /= "0000" ) ) -- supported transfer-type (only mem-type is supported, see PLB-Spec. page 43) and ( PLB_type = "000" or PLB_type = "110" ) ) else '0'; start_plb_stat_r <= '1' when ( -- we are in the idle state c_plb_rstate.state = plb_ridle -- Address in our range, primary-addr is valid and it is a write transfer and AMU_statusSelect = '1' and PLB_PAValid = '1' and PLB_RNW = '1' -- this transfer-type is implemented --(normal, line and burst -> all fixed-length word bursts) and ( PLB_size( 0 to 1 ) = "00" or ( PLB_size = "1010" and PLB_BE( 0 to 3 ) /= "0000" ) ) -- supported transfer-type (only mem-type is supported, see PLB-Spec. page 43) and ( PLB_type = "000" or PLB_type = "110" ) ) else '0'; end generate with_plb_bursts; ------------------------------ -- -- This signals are '1' if a transfer is started: -- (burst and line transfers are not supported) -- -- start_plb_w: start a write transfer to the WB side -- start_plb_r: start a read transfer from the WB side -- start_plb_stat_w: start a write transfer to the status registers -- start_plb_stat_r: start a read transfer from the status registers -- -- without_plb_bursts : if C_SPLB_SUPPORT_BUR_LINE = 0 generate start_plb_w <= '1' when ( -- we are in the idle state c_plb_wstate.state = plb_widle -- Address in our range, primary-addr is valid and it is a write transfer and AMU_deviceSelect = '1' and PLB_PAValid = '1' and PLB_RNW = '0' -- this transfer-type is implemented (only single) and ( PLB_size = "0000" ) -- we are not transfering data from the read pipe and TCU_rpipeRdEn_t /= '1' -- the address buffer is not full and AMU_bufFull = '0' -- supported transfer-type (only mem-type is supported, see PLB-Spec. page 43) and ( PLB_type = "000" or PLB_type = "110" ) ) else '0'; start_plb_r <= '1' when( -- we are in the idle state c_plb_rstate.state = plb_ridle -- Address in our range, primary-addr is valid and it is a read transfer and AMU_deviceSelect = '1' and PLB_PAValid = '1' and PLB_RNW = '1' -- this transfer-type is implemented (only single) and ( PLB_size = "0000" ) -- we are not transfering data from the write-pipe and TCU_wpipeRdEn_t /= '1' -- the address buffer is not full and AMU_bufFull = '0' -- supported transfer-type (only mem-type is supported, see PLB-Spec. page 43) and ( PLB_type = "000" or PLB_type = "110" ) ) else '0'; start_plb_stat_w <= '1' when ( -- we are in the idle state c_plb_wstate.state = plb_widle -- Address in our range, primary-addr is valid and it is a write transfer and AMU_statusSelect = '1' and PLB_PAValid = '1' and PLB_RNW = '0' -- this transfer-type is implemented (only single) and ( PLB_size = "0000" ) -- supported transfer-type (only mem-type is supported, see PLB-Spec. page 43) and ( PLB_type = "000" or PLB_type = "110" ) ) else '0'; start_plb_stat_r <= '1' when ( -- we are in the idle state c_plb_rstate.state = plb_ridle -- Address in our range, primary-addr is valid and it is a write transfer and AMU_statusSelect = '1' and PLB_PAValid = '1' and PLB_RNW = '1' -- this transfer-type is implemented (only single) and ( PLB_size = "0000" ) -- supported transfer-type (only mem-type is supported, see PLB-Spec. page 43) and ( PLB_type = "000" or PLB_type = "110" ) ) else '0'; end generate without_plb_bursts; start_plb_sec_w <= '1' when( c_plb_wstate.state = plb_widle -- ---- and c_plb_wstate.w_secondary = '1' -- This is the case, when there is a write and AMU_bufFull = '0' -- from a secondary request directly after a write and AMU_pipe_wStatusSelect = '0' -- (this transfer does not write to our status regs) -- and TCU_rpipeRdEn_t /= '1' -- note: start_plb_sec_w has a higher priority -- than start_plb_sec_r, (we can't check -- TCU_rpipeRdEn_t, because this generates a -- combinatorial loop!!) ) -- ---- else '0'; start_plb_sec_stat_w <= '1' when( c_plb_wstate.state = plb_widle -- ---- and c_plb_wstate.w_secondary = '1' -- This is the case, when there is a write and AMU_pipe_wStatusSelect = '1' -- from a secondary request (we write to our status regs) ) -- ---- else '0'; start_plb_sec_r <= '1' when( c_plb_rstate.state = plb_ridle -- ---- and c_plb_rstate.r_secondary = '1' -- This is the case, when there is a read and AMU_bufFull = '0' -- from a secondary request directly after a read and AMU_pipe_rStatusSelect = '0' -- (this transfer does not read from our status regs) and TCU_wpipeRdEn_t /= '1' ) -- ---- else '0'; start_plb_sec_stat_r <= '1' when( c_plb_rstate.state = plb_ridle -- ---- and c_plb_rstate.r_secondary = '1' -- This is the case, when there is a read and AMU_pipe_rStatusSelect = '1' -- from a secondary request (we read from our status regs) ) -- ---- else '0'; c_plb_state_p : process( SPLB_Clk, plb2wb_rst ) begin if plb2wb_rst='1' then c_plb_rstate <= ( state => plb_ridle, r_master_id => ( others => '0' ), transfer_count => ( others => '0' ), transfer_size => ( others => '0' ), status_transfer => '0', r_secondary => '0' ); c_plb_wstate <= ( state => plb_widle, w_master_id => ( others => '0' ), transfer_count => ( others => '0' ), transfer_size => ( others => '0' ), status_transfer => '0', w_secondary => '0' ); elsif SPLB_Clk'event and SPLB_Clk='1' then c_plb_rstate <= n_plb_rstate; c_plb_wstate <= n_plb_wstate; end if; end process; n_plb_wstate_p : process( c_plb_wstate, PLB_PAValid, PLB_RNW, PLB_masterID, PLB_wrPrim, PLB_size, PLB_BE, AMU_deviceSelect, AMU_statusSelect, AMU_bufFull, WBF_full, AMU_pipe_size, AMU_pipe_wmID, AMU_pipe_BE, start_plb_sec_w, start_plb_sec_stat_w, start_plb_w, start_plb_stat_w, TCU_rpipeRdEn_t ) begin Sl_MWrErr <= ( others => '0' ); -- default output logic Sl_wrDAck <= '0'; Sl_wrComp_t <= '0'; Sl_wrBTerm <= '0'; TCU_wbufWEn_t <= '0'; TCU_adrBufWEn_w <= '0'; TCU_wpipeRdEn_t <= '0'; addrAck_w <= '0'; TCU_stuLatchSA_w <= '0'; TCU_stuLatchPA_w <= '0'; -- default state n_plb_wstate <= c_plb_wstate; mbusy_write_out <= ( others => '0' ); TCU_stuWritePA_t <= '0'; TCU_stuWriteSA_t <= '0'; if PLB_wrPrim = '1' then n_plb_wstate.w_secondary <= '1'; end if; if start_plb_sec_w = '1' then -- read from pipe and add it to the buffer TCU_wpipeRdEn_t <= '1'; TCU_adrBufWEn_w <= '1'; n_plb_wstate.w_secondary <= '0'; n_plb_wstate.status_transfer <= '0'; -- we latch the masterID n_plb_wstate.w_master_id <= AMU_pipe_wmID; -- buffer is not full, this is a implemented transfer and this is a normal/single transfer if WBF_full = '0' and AMU_pipe_size = "0000" then -- add data to the buffer TCU_wbufWEn_t <= '1'; -- ack transfer to PLB Sl_wrDAck <= '1'; Sl_wrComp_t <= '1'; -- we stay in the idle state -- buffer is not full, this is a line transfer elsif WBF_full = '0' and AMU_pipe_size( 0 to 1 ) = "00" and AMU_pipe_size( 2 to 3 ) /= "00" then -- add data to the buffer TCU_wbufWEn_t <= '1'; -- ack transfer to PLB Sl_wrDAck <= '1'; n_plb_wstate.state <= plb_write; n_plb_wstate.transfer_size <= AMU_pipe_size; -- we did one transfer in this clock cycle n_plb_wstate.transfer_count <= "0001"; -- buffer is full, we switch to the wait-state and wait until we can write to the buffer elsif WBF_full = '1' and AMU_pipe_size( 0 to 1 ) = "00" then n_plb_wstate.state <= plb_write; n_plb_wstate.transfer_size <= AMU_pipe_size; -- we did one transfer in this clock cycle n_plb_wstate.transfer_count <= "0000"; -- this is a burst transfer -- and the buffer is not full elsif WBF_full = '0' and AMU_pipe_size( 0 to 1 ) /= "00" then -- add data to the buffer TCU_wbufWEn_t <= '1'; -- ack transfer to PLB Sl_wrDAck <= '1'; n_plb_wstate.state <= plb_burst_write; n_plb_wstate.transfer_size <= AMU_pipe_BE; -- we did one transfer in this clock cycle n_plb_wstate.transfer_count <= "0001"; -- this is a burst transfer -- and the buffer is full elsif WBF_full = '1' and AMU_pipe_size( 0 to 1 ) /= "00" then n_plb_wstate.state <= plb_burst_write; n_plb_wstate.transfer_size <= AMU_pipe_BE; -- we did one transfer in this clock cycle n_plb_wstate.transfer_count <= "0000"; end if; -- -- NOTE: it is not allowed to write with a burst or line transfer to the status -- registers, so TCU_stuWriteSA_t is only '1' for a single transfer! -- elsif start_plb_sec_stat_w = '1' then TCU_wpipeRdEn_t <= '1'; -- we latch the masterID n_plb_wstate.w_master_id <= AMU_pipe_wmID; n_plb_wstate.w_secondary <= '0'; -- ack transfer to PLB Sl_wrDAck <= '1'; if AMU_pipe_size = "1010" and AMU_pipe_BE( 0 to 3 ) /= "0000" then -- burst transfer Sl_MWrErr( to_integer( unsigned'( unsigned( AMU_pipe_wmID ) ) ) ) <= '1'; -- we switch to the burst_write state: -- we write until transfer_count = transfer_size n_plb_wstate.state <= plb_burst_write; n_plb_wstate.transfer_size <= AMU_pipe_BE( 0 to 3 ); -- we did no transfer in this clock cycle n_plb_wstate.transfer_count <= "0001"; n_plb_wstate.status_transfer <= '1'; elsif AMU_pipe_size( 0 to 1 ) = "00" and AMU_pipe_size( 2 to 3 ) /= "00" then -- line transfer Sl_MWrErr( to_integer( unsigned'( unsigned( AMU_pipe_wmID ) ) ) ) <= '1'; -- we switch to the write state: -- we write until transfer_count = transfer_size n_plb_wstate.state <= plb_write; n_plb_wstate.transfer_size <= AMU_pipe_size; -- we did one transfer in this clock cycle n_plb_wstate.transfer_count <= "0001"; n_plb_wstate.status_transfer <= '1'; else -- single transfer TCU_stuWriteSA_t <= '1'; Sl_wrComp_t <= '1'; end if; -- -- start write transfer, initiated through PLB_PAValid -- elsif start_plb_w = '1' then -- we can accept the address -- add address and data to the fifos/buffers -- this implicit acks the address (see plb2wb_amu.vhd) TCU_adrBufWEn_w <= '1'; addrAck_w <= '1'; -- we latch the masterID n_plb_wstate.w_master_id <= PLB_masterID; n_plb_wstate.status_transfer <= '0'; -- buffer is not full and this is a single/normal transfer -- (we stay in the idle state) if WBF_full = '0' and PLB_size = "0000" then -- add data to the buffer TCU_wbufWEn_t <= '1'; -- ack transfer to PLB Sl_wrDAck <= '1'; Sl_wrComp_t <= '1'; -- this is a line transfer elsif WBF_full = '0' and PLB_size( 0 to 1 ) = "00" and PLB_size( 2 to 3 ) /= "00" then -- add data to the buffer TCU_wbufWEn_t <= '1'; -- ack transfer to PLB Sl_wrDAck <= '1'; -- we switch to the write state: -- we write until transfer_count = transfer_size n_plb_wstate.state <= plb_write; n_plb_wstate.transfer_size <= PLB_size; -- we did one transfer in this clock cycle n_plb_wstate.transfer_count <= "0001"; -- the buffer is full: -- if this is a single or line transfer, we switch to the plb_write state elsif WBF_full = '1' and PLB_size( 0 to 1 ) = "00" then -- we switch to the write state: -- we write until transfer_count = transfer_size n_plb_wstate.state <= plb_write; n_plb_wstate.transfer_size <= PLB_size; -- we did no transfer in this clock cycle n_plb_wstate.transfer_count <= "0000"; -- this is a burst transfer -- and the buffer is not full elsif WBF_full = '0' and PLB_size( 0 to 1 ) /= "00" then -- add data to the buffer TCU_wbufWEn_t <= '1'; -- ack transfer to PLB Sl_wrDAck <= '1'; -- we switch to the burst_write state: -- we write until transfer_count = transfer_size n_plb_wstate.state <= plb_burst_write; n_plb_wstate.transfer_size <= PLB_BE( 0 to 3 ); -- we did no transfer in this clock cycle n_plb_wstate.transfer_count <= "0001"; -- this is a burst transfer -- and the buffer is full elsif WBF_full = '1' and PLB_size( 0 to 1 ) /= "00" then -- we switch to the burst_write state: -- we write until transfer_count = transfer_size n_plb_wstate.state <= plb_burst_write; n_plb_wstate.transfer_size <= PLB_BE( 0 to 3 ); -- we did no transfer in this clock cycle n_plb_wstate.transfer_count <= "0000"; end if; -- -- start write transfer to state-register, initiated through PLB_PAValid -- -- -- NOTE: it is not allowed to write with a burst or line transfer to the status -- registers, so TCU_stuWritePA_t is only '1' for a single transfer! -- elsif start_plb_stat_w = '1' then addrAck_w <= '1'; -- we latch the masterID n_plb_wstate.w_master_id <= PLB_masterID; -- ack transfer to PLB Sl_wrDAck <= '1'; if PLB_size = "1010" and PLB_BE( 0 to 3 ) /= "0000" then -- burst transfer Sl_MWrErr( to_integer( unsigned'( unsigned( PLB_masterID ) ) ) ) <= '1'; -- we switch to the burst_write state: -- we write until transfer_count = transfer_size n_plb_wstate.state <= plb_burst_write; n_plb_wstate.transfer_size <= PLB_BE( 0 to 3 ); -- we did no transfer in this clock cycle n_plb_wstate.transfer_count <= "0001"; n_plb_wstate.status_transfer <= '1'; elsif PLB_size( 0 to 1 ) = "00" and PLB_size( 2 to 3 ) /= "00" then -- line transfer Sl_MWrErr( to_integer( unsigned'( unsigned( PLB_masterID ) ) ) ) <= '1'; -- we switch to the write state: -- we write until transfer_count = transfer_size n_plb_wstate.state <= plb_write; n_plb_wstate.transfer_size <= PLB_size; -- we did one transfer in this clock cycle n_plb_wstate.transfer_count <= "0001"; n_plb_wstate.status_transfer <= '1'; else -- single transfer TCU_stuWritePA_t <= '1'; Sl_wrComp_t <= '1'; end if; end if; -- -- write transfer: we are here because -- - the write buffer was full and the adress buffer not, or -- - this is a line transfer -- if ( c_plb_wstate.state = plb_write and ( c_plb_wstate.status_transfer = '1' or ( WBF_full = '0' and c_plb_wstate.status_transfer = '0' ) ) ) then -- we can accept data -- ack transfer to PLB Sl_wrDAck <= '1'; if ( ( c_plb_wstate.transfer_size( 0 to 3 ) = "0001" and c_plb_wstate.transfer_count = "0011" ) or ( c_plb_wstate.transfer_size( 0 to 3 ) = "0010" and c_plb_wstate.transfer_count = "0111" ) or ( c_plb_wstate.transfer_size( 0 to 3 ) = "0011" and c_plb_wstate.transfer_count = "1111" ) or ( c_plb_wstate.transfer_size( 0 to 3 ) = "0000" ) -- single transfer ) then -- we are at the end of this transfer Sl_wrComp_t <= '1'; n_plb_wstate.state <= plb_widle; else n_plb_wstate.transfer_count <= std_logic_vector( unsigned'( unsigned(c_plb_wstate.transfer_count) +1 ) ); end if; if c_plb_wstate.status_transfer = '1' then Sl_MWrErr( to_integer( unsigned'( unsigned( c_plb_wstate.w_master_id ) ) ) ) <= '1'; elsif WBF_full = '0' then -- add data to the buffer TCU_wbufWEn_t <= '1'; end if; end if; -- -- burst write transfer: we are here because -- - this is a burst transfer if( c_plb_wstate.state = plb_burst_write and ( ( WBF_full = '0' and c_plb_wstate.status_transfer = '0' ) or c_plb_wstate.status_transfer = '1' ) )then -- we can accept data if c_plb_wstate.status_transfer = '1' then Sl_MWrErr( to_integer( unsigned'( unsigned( c_plb_wstate.w_master_id ) ) ) ) <= '1'; elsif WBF_full = '0' then -- add data to the buffer TCU_wbufWEn_t <= '1'; end if; -- ack transfer to PLB Sl_wrDAck <= '1'; -- we show that the burst-transfer ends after the next cycle if c_plb_wstate.transfer_count = std_logic_vector( unsigned'( unsigned( c_plb_wstate.transfer_size ) -1 ) ) then Sl_wrBTerm <= '1'; end if; if c_plb_wstate.transfer_size = c_plb_wstate.transfer_count then -- we are at the end of this transfer Sl_wrComp_t <= '1'; n_plb_wstate.state <= plb_widle; else n_plb_wstate.transfer_count <= std_logic_vector( unsigned'( unsigned(c_plb_wstate.transfer_count) +1 ) ); end if; end if; if c_plb_wstate.state = plb_write or c_plb_wstate.state = plb_burst_write then mbusy_write_out( to_integer( unsigned'( unsigned( c_plb_wstate.w_master_id ) ) ) ) <= '1'; elsif c_plb_wstate.w_secondary = '1' then mbusy_write_out( to_integer( unsigned'( unsigned( AMU_pipe_wmID ) ) ) ) <= '1'; end if; end process; n_plb_rstate_p : process( c_plb_rstate, PLB_PAValid, PLB_RNW, PLB_masterID, PLB_rdPrim, PLB_size, PLB_BE, AMU_deviceSelect, AMU_bufFull, AMU_pipe_size, AMU_pipe_rmID, AMU_pipe_BE, AMU_statusSelect, RBF_empty, RBF_almostEmpty, start_plb_sec_r, start_plb_sec_stat_r, start_plb_r, start_plb_stat_r, TCU_wpipeRdEn_t ) begin Sl_rdDAck_t <= '0'; Sl_rdComp_t <= '0'; Sl_rdBTerm <= '0'; TCU_rbufREn_t <= '0'; TCU_adrBufWEn_r <= '0'; TCU_enRdDBus <= '0'; TCU_rpipeRdEn_t <= '0'; -- TCU_rbufPreLoad <= '0'; -- TODO -- TCU_rbufPreEn <= '0'; -- TODO addrAck_r <= '0'; TCU_stuLatchSA_r <= '0'; TCU_stuLatchPA_r <= '0'; TCU_enStuRdDBus <= '0'; Sl_rdWdAddr <= ( others => '0' ); mbusy_read_out <= ( others => '0' ); n_plb_rstate <= c_plb_rstate; if PLB_rdPrim = '1' then n_plb_rstate.r_secondary <= '1'; end if; if start_plb_sec_r = '1' then TCU_adrBufWEn_r <= '1'; TCU_rpipeRdEn_t <= '1'; n_plb_rstate.r_secondary <= '0'; -- latch the master-id from AMU n_plb_rstate.r_master_id <= AMU_pipe_rmID; n_plb_rstate.status_transfer <= '0'; -- this is a line transfer if AMU_pipe_size( 0 to 1 ) = "00" and AMU_pipe_size( 2 to 3 ) /= "00" and C_SPLB_SUPPORT_BUR_LINE > 0 then n_plb_rstate.state <= plb_line_read; n_plb_rstate.transfer_count <= ( others => '0' ); n_plb_rstate.transfer_size <= AMU_pipe_size; -- this is a burst transfer elsif AMU_pipe_size( 0 to 1 ) /= "00" and C_SPLB_SUPPORT_BUR_LINE > 0 then n_plb_rstate.state <= plb_burst_read; n_plb_rstate.transfer_count <= ( others => '0' ); n_plb_rstate.transfer_size <= AMU_pipe_BE( 0 to 3 ); -- this is a single transfer else n_plb_rstate.state <= plb_read; end if; -- -- start read transfer from state-register, initiated through secondary request -- elsif start_plb_sec_stat_r = '1' then TCU_rpipeRdEn_t <= '1'; n_plb_rstate.r_secondary <= '0'; -- latch the master-id from AMU n_plb_rstate.r_master_id <= AMU_pipe_rmID; -- tell the stu, that it should latch the secondary address TCU_stuLatchSA_r <= '1'; n_plb_rstate.status_transfer <= '1'; -- this is a line transfer if AMU_pipe_size( 0 to 1 ) = "00" and AMU_pipe_size( 2 to 3 ) /= "00" and C_SPLB_SUPPORT_BUR_LINE > 0 then n_plb_rstate.state <= plb_line_read; n_plb_rstate.transfer_count <= ( others => '0' ); n_plb_rstate.transfer_size <= AMU_pipe_size; -- this is a burst transfer elsif AMU_pipe_size( 0 to 1 ) /= "00" and C_SPLB_SUPPORT_BUR_LINE > 0 then n_plb_rstate.state <= plb_burst_read; n_plb_rstate.transfer_count <= ( others => '0' ); n_plb_rstate.transfer_size <= AMU_pipe_BE( 0 to 3 ); -- this is a single transfer else n_plb_rstate.state <= plb_read; end if; -- -- start read transfer, initiated through PLB_PAValid -- elsif start_plb_r = '1' then -- add address to the buffer/fifo TCU_adrBufWEn_r <= '1'; addrAck_r <= '1'; -- latch the master-id from plb-bus n_plb_rstate.r_master_id <= PLB_masterID; n_plb_rstate.status_transfer <= '0'; n_plb_rstate.transfer_count <= "0000"; -- this is a line transfer if PLB_size( 0 to 1 ) = "00" and PLB_size( 2 to 3 ) /= "00" and C_SPLB_SUPPORT_BUR_LINE > 0 then n_plb_rstate.transfer_size <= PLB_size; n_plb_rstate.state <= plb_wait_line_read; n_plb_rstate.transfer_count <= ( others => '0' ); -- this is a burst transfer elsif PLB_size( 0 to 1 ) /= "00" and C_SPLB_SUPPORT_BUR_LINE > 0 then n_plb_rstate.state <= plb_wait_burst_read; n_plb_rstate.transfer_count <= ( others => '0' ); n_plb_rstate.transfer_size <= PLB_BE( 0 to 3 ); -- this is a single transfer else n_plb_rstate.transfer_size <= PLB_size; n_plb_rstate.state <= plb_read; end if; -- -- start read transfer from state-register, initiated through PLB_PAValid -- elsif start_plb_stat_r = '1' then -- single transfer addrAck_r <= '1'; -- tell the stu, that it should latch the primary address TCU_stuLatchPA_r <= '1'; -- latch the master-id from plb-bus n_plb_rstate.r_master_id <= PLB_masterID; n_plb_rstate.transfer_count <= "0000"; n_plb_rstate.status_transfer <= '1'; -- this is a line transfer if PLB_size( 0 to 1 ) = "00" and PLB_size( 2 to 3 ) /= "00" and C_SPLB_SUPPORT_BUR_LINE > 0 then n_plb_rstate.transfer_size <= PLB_size; n_plb_rstate.state <= plb_wait_line_read; n_plb_rstate.transfer_count <= ( others => '0' ); -- this is a burst transfer elsif PLB_size( 0 to 1 ) /= "00" and C_SPLB_SUPPORT_BUR_LINE > 0 then n_plb_rstate.state <= plb_wait_burst_read; n_plb_rstate.transfer_count <= ( others => '0' ); n_plb_rstate.transfer_size <= PLB_BE( 0 to 3 ); -- this is a single transfer else n_plb_rstate.transfer_size <= PLB_size; n_plb_rstate.state <= plb_read; end if; end if; -- the wb-side read the data and added it to the fifo -- -> fifo is not empty any more if ( ( c_plb_rstate.state = plb_read and c_plb_rstate.status_transfer = '0' and RBF_empty = '0' ) -- this transfer reads from status register or ( c_plb_rstate.state = plb_read and c_plb_rstate.status_transfer = '1' ) ) then -- complete read transfer Sl_rdComp_t <= '1'; -- switch to the ack state n_plb_rstate.state <= plb_read_ack; end if; if c_plb_rstate.state = plb_read_ack then -- switch to idle state n_plb_rstate.state <= plb_ridle; -- ack. the read transfer Sl_rdDAck_t <= '1'; if c_plb_rstate.status_transfer = '0' then -- read from the buffer TCU_rbufREn_t <= '1'; end if; end if; if c_plb_rstate.state = plb_line_read then -- /----- We know, that the fifo contains min. 2 elements if ( c_plb_rstate.status_transfer = '1' or -- \/ ( c_plb_rstate.status_transfer = '0' and RBF_almostEmpty = '0' ) ) then n_plb_rstate.transfer_count <= std_logic_vector( unsigned'( unsigned(c_plb_rstate.transfer_count) + 1 ) ); Sl_rdDAck_t <= '1'; if ( ( c_plb_rstate.transfer_size( 0 to 3 ) = "0001" and c_plb_rstate.transfer_count = "0010" ) or ( c_plb_rstate.transfer_size( 0 to 3 ) = "0010" and c_plb_rstate.transfer_count = "0110" ) or ( c_plb_rstate.transfer_size( 0 to 3 ) = "0011" and c_plb_rstate.transfer_count = "1110" ) ) then -- we are finished after the next clock cycle Sl_rdComp_t <= '1'; n_plb_rstate.state <= plb_line_read_ack; end if; end if; if ( c_plb_rstate.status_transfer = '0' and RBF_almostEmpty = '0' ) then TCU_rbufREn_t <= '1'; end if; end if; if c_plb_rstate.state = plb_burst_read then -- /----- We know, that the fifo contains min. 2 elements if ( c_plb_rstate.status_transfer = '1' or -- \/ ( c_plb_rstate.status_transfer = '0' and RBF_almostEmpty = '0' ) ) then n_plb_rstate.transfer_count <= std_logic_vector( unsigned'( unsigned(c_plb_rstate.transfer_count) + 1 ) ); Sl_rdDAck_t <= '1'; if c_plb_rstate.transfer_count = std_logic_vector( unsigned'( unsigned ( c_plb_rstate.transfer_size ) -1 ) ) then -- we are finished after the next clock cycle Sl_rdComp_t <= '1'; Sl_rdBTerm <= '1'; n_plb_rstate.state <= plb_burst_read_ack; end if; end if; if ( c_plb_rstate.status_transfer = '0' and RBF_almostEmpty = '0' ) then TCU_rbufREn_t <= '1'; end if; end if; -- the wait cycles if c_plb_rstate.state = plb_wait_burst_read then n_plb_rstate.state <= plb_burst_read; end if; if c_plb_rstate.state = plb_wait_line_read then n_plb_rstate.state <= plb_line_read; end if; if c_plb_rstate.state = plb_line_read_ack or c_plb_rstate.state = plb_burst_read_ack then Sl_rdDAck_t <= '1'; n_plb_rstate.state <= plb_ridle; if c_plb_rstate.status_transfer = '0' then TCU_rbufREn_t <= '1'; end if; end if; if ( ( c_plb_rstate.state = plb_read or c_plb_rstate.state = plb_read_ack or c_plb_rstate.state = plb_line_read or c_plb_rstate.state = plb_line_read_ack or c_plb_rstate.state = plb_burst_read or c_plb_rstate.state = plb_burst_read_ack) and c_plb_rstate.status_transfer = '0' ) then -- we enable the read bus on plb side TCU_enRdDBus <= '1'; elsif ( ( c_plb_rstate.state = plb_read or c_plb_rstate.state = plb_read_ack or c_plb_rstate.state = plb_line_read or c_plb_rstate.state = plb_line_read_ack or c_plb_rstate.state = plb_burst_read or c_plb_rstate.state = plb_burst_read_ack) and c_plb_rstate.status_transfer = '1' ) then TCU_enStuRdDBus <= '1'; end if; if c_plb_rstate.state = plb_read or c_plb_rstate.state = plb_read_ack or c_plb_rstate.state = plb_line_read or c_plb_rstate.state = plb_line_read_ack or c_plb_rstate.state = plb_burst_read or c_plb_rstate.state = plb_burst_read_ack or c_plb_rstate.state = plb_wait_line_read or c_plb_rstate.state = plb_wait_burst_read then mbusy_read_out( to_integer( unsigned'( unsigned( c_plb_rstate.r_master_id ) ) ) ) <= '1'; end if; if c_plb_rstate.r_secondary = '1' then mbusy_read_out( to_integer( unsigned'( unsigned( AMU_pipe_rmID ) ) ) ) <= '1'; end if; if c_plb_rstate.state = plb_line_read or c_plb_rstate.state = plb_line_read_ack or c_plb_rstate.state = plb_burst_read or c_plb_rstate.state = plb_burst_read_ack then Sl_rdWdAddr <= c_plb_rstate.transfer_count; end if; end process; TCU_MRBusy <= mbusy_read_out or mbusy_write_out; Sl_MRdErr <= mbusy_read_out when Sl_rdDAck_t = '1' and RBF_rdErrOut = '1' else ( others => '0' ); -- ====================================================================================================| -- | -- ========================= W I S H B O N E -- S I D E =========================================| -- | -- ====================================================================================================| ------- -- WB-timeout counter -- -> counts from WB_TOUT_MIN_VALUE to WB_TOUT_MAX_VALUE -- -> is reseted by driving wb_tout_reset high -- -> if counter reaches WB_TOUT_MAX_VALUE, wb_tout_alarm becomes '1' -- wb_tout_process : process( wb_clk_i, plb2wb_rst, wb_tout_counter, wb_tout_reset ) begin wb_tout_alarm <= '0'; if plb2wb_rst = '1' or wb_tout_reset = '1' then wb_tout_counter <= WB_TOUT_MIN_VALUE; elsif wb_clk_i'event and wb_clk_i = '1' then if ( wb_tout_count = '1' and wb_tout_counter /= WB_TOUT_MAX_VALUE ) then wb_tout_counter <= wb_tout_counter + 1; end if; end if; if wb_tout_counter = WB_TOUT_MAX_VALUE then wb_tout_alarm <= '1'; end if; end process; -- ----- c_wb_state_p : process( wb_clk_i, plb2wb_rst ) begin if plb2wb_rst='1' then c_wb_state.state <= wb_idle; c_wb_state.transfer_count <= ( others => '0' ); elsif wb_clk_i'event and wb_clk_i='1' then c_wb_state <= n_wb_state; end if; end process; -- -- Note: we have fall-through fifo's, so the address is assigned when AMU_bufEmpty becomes '0' -- start_wb_w <= '1' when ( c_wb_state.state = wb_idle and AMU_buf_RNW = '0' and AMU_bufEmpty = '0' and WBF_empty = '0' ) else '0'; start_wb_r <= '1' when ( c_wb_state.state = wb_idle and AMU_buf_RNW = '1' and RBF_full = '0' and AMU_bufEmpty = '0' ) else '0'; wb_ack <= wb_ack_i and not wb_err_i and not wb_rty_i; wb_rty <= wb_rty_i and not wb_err_i; wb_err <= wb_err_i; n_wb_state_p : process( c_wb_state, AMU_buf_size, AMU_buf_BE, WBF_empty, start_wb_w, start_wb_r, wb_ack, wb_rty, wb_err, wb_tout_alarm, STU_continue, STU_abort, wb_rst_short,pic_int_ahigh_short ) begin wb_we_o <= '0'; wb_stb_o <= '0'; wb_cyc_o <= '0'; wb_lock_o <= '0'; TCU_wbufREn_t <= '0'; TCU_rbufWEn_t <= '0'; TCU_adrBufREn <= '0'; TCU_wb_status_info <= ( others => '0' ); TCU_stat2plb_en <= '0'; wb_tout_count <= '0'; wb_tout_reset <= '0'; n_wb_state <= c_wb_state; if start_wb_w = '1' then wb_stb_o <= '1'; wb_cyc_o <= '1'; wb_we_o <= '1'; n_wb_state.abort <= '0'; wb_tout_reset <= '1'; if wb_ack = '1' then TCU_wbufREn_t <= '1'; if AMU_buf_size /= "0000" then -- this is a line or burst transfer n_wb_state.state <= wb_write; n_wb_state.transfer_count <= "0001"; else -- this is a single transfer: -- we read from the address buffer, -- because this transfer is complete TCU_adrBufREn <= '1'; end if; elsif wb_err = '1' then -- add error info to the status pipe -- and switch to the stall state n_wb_state.state <= wb_write_stall; TCU_wb_status_info( STATUS2PLB_W_ERR ) <= '1'; TCU_stat2plb_en <= '1'; elsif wb_rty = '1' then -- retry this transfer n_wb_state.state <= wb_write_rty; else n_wb_state.state <= wb_write; end if; end if; if start_wb_r = '1' then wb_stb_o <= '1'; wb_cyc_o <= '1'; wb_we_o <= '0'; n_wb_state.abort <= '0'; wb_tout_reset <= '1'; if wb_ack = '1' or wb_err = '1' then TCU_rbufWEn_t <= '1'; if AMU_buf_size /= "0000" then -- this is a line or burst transfer n_wb_state.state <= wb_read; n_wb_state.transfer_count <= "0001"; else -- this is a single transfer: -- we read from the address buffer, -- because this transfer is complete TCU_adrBufREn <= '1'; end if; elsif wb_rty = '1' then n_wb_state.state <= wb_read_rty; else n_wb_state.state <= wb_read; end if; end if; -- -- write-transfer without writing -- -->> we have to empty the write-pipe if c_wb_state.state = wb_write and WBF_empty ='0' and c_wb_state.abort = '1' then TCU_wbufREn_t <= '1'; if AMU_buf_size = "0000" then -- single write transfer n_wb_state.state <= wb_idle; TCU_adrBufREn <= '1'; elsif AMU_buf_size( 3 downto 2 ) = "00" then -- write line transfer if ( ( AMU_buf_size( 1 downto 0 ) = "01" and c_wb_state.transfer_count = "0011" ) or ( AMU_buf_size( 1 downto 0 ) = "10" and c_wb_state.transfer_count = "0111" ) or ( AMU_buf_size( 1 downto 0 ) = "11" and c_wb_state.transfer_count = "1111" ) ) then -- we are at the end of this transfer n_wb_state.transfer_count <= ( others => '0' ); n_wb_state.state <= wb_idle; TCU_adrBufREn <= '1'; else n_wb_state.transfer_count <= std_logic_vector( unsigned'( unsigned(c_wb_state.transfer_count) +1 ) ); end if; else -- write burst transfer if c_wb_state.transfer_count = AMU_buf_BE then -- we are at the end of this transfer n_wb_state.transfer_count <= ( others => '0' ); n_wb_state.state <= wb_idle; TCU_adrBufREn <= '1'; else n_wb_state.transfer_count <= std_logic_vector( unsigned'( unsigned(c_wb_state.transfer_count) +1 ) ); end if; end if; elsif c_wb_state.state = wb_write and WBF_empty ='0' and c_wb_state.abort = '0' then wb_stb_o <= '1'; wb_cyc_o <= '1'; wb_we_o <= '1'; wb_tout_count <= '1'; if wb_ack = '1' then TCU_wbufREn_t <= '1'; wb_tout_reset <= '1'; if AMU_buf_size = "0000" then -- single write transfer n_wb_state.state <= wb_idle; TCU_adrBufREn <= '1'; elsif AMU_buf_size( 3 downto 2 ) = "00" then -- write line transfer if ( ( AMU_buf_size( 1 downto 0 ) = "01" and c_wb_state.transfer_count = "0011" ) or ( AMU_buf_size( 1 downto 0 ) = "10" and c_wb_state.transfer_count = "0111" ) or ( AMU_buf_size( 1 downto 0 ) = "11" and c_wb_state.transfer_count = "1111" ) ) then -- we are at the end of this transfer n_wb_state.transfer_count <= ( others => '0' ); n_wb_state.state <= wb_idle; TCU_adrBufREn <= '1'; else n_wb_state.transfer_count <= std_logic_vector( unsigned'( unsigned(c_wb_state.transfer_count) +1 ) ); end if; else -- write burst transfer if c_wb_state.transfer_count = AMU_buf_BE then -- we are at the end of this transfer n_wb_state.transfer_count <= ( others => '0' ); n_wb_state.state <= wb_idle; TCU_adrBufREn <= '1'; else n_wb_state.transfer_count <= std_logic_vector( unsigned'( unsigned(c_wb_state.transfer_count) +1 ) ); end if; end if; elsif wb_err = '1' then -- add error info to the status pipe -- and switch to the stall state n_wb_state.state <= wb_write_stall; TCU_wb_status_info( STATUS2PLB_W_ERR ) <= '1'; TCU_stat2plb_en <= '1'; wb_tout_reset <= '1'; elsif wb_rty = '1' then n_wb_state.state <= wb_write_rty; wb_tout_reset <= '1'; elsif wb_tout_alarm = '1' then n_wb_state.state <= wb_write_stall; TCU_wb_status_info( STATUS2PLB_W_ERR ) <= '1'; TCU_stat2plb_en <= '1'; end if; end if; -- -- The WB-spec says, that wb_rty_i terminates a cycle, so wb_stb_o and wb_cyc_o is '0' -- if c_wb_state.state = wb_write_rty then n_wb_state.state <= wb_write; end if; if c_wb_state.state = wb_read then wb_stb_o <= '1'; wb_cyc_o <= '1'; wb_we_o <= '0'; wb_tout_count <= '1'; if wb_ack = '1' or wb_err = '1' then wb_tout_reset <= '1'; TCU_rbufWEn_t <= '1'; if AMU_buf_size = "0000" then -- single read transfer n_wb_state.state <= wb_idle; TCU_adrBufREn <= '1'; elsif AMU_buf_size( 3 downto 2 ) = "00" then -- read line transfer if ( ( AMU_buf_size( 1 downto 0 ) = "01" and c_wb_state.transfer_count = "0011" ) or ( AMU_buf_size( 1 downto 0 ) = "10" and c_wb_state.transfer_count = "0111" ) or ( AMU_buf_size( 1 downto 0 ) = "11" and c_wb_state.transfer_count = "1111" ) ) then n_wb_state.transfer_count <= ( others => '0' ); n_wb_state.state <= wb_idle; TCU_adrBufREn <= '1'; else n_wb_state.transfer_count <= std_logic_vector( unsigned'( unsigned(c_wb_state.transfer_count) +1 ) ); end if; else -- burst read transfer if c_wb_state.transfer_count = AMU_buf_BE then n_wb_state.transfer_count <= ( others => '0' ); n_wb_state.state <= wb_idle; TCU_adrBufREn <= '1'; -- add info to the status fifo else n_wb_state.transfer_count <= std_logic_vector( unsigned'( unsigned(c_wb_state.transfer_count) +1 ) ); end if; end if; elsif wb_rty = '1' then n_wb_state.state <= wb_read_rty; wb_tout_reset <= '1'; ----- -- NOTE: This must be done after all other if-cases (ack, err, rty) -- doing this together with ack and err, it results into a wrong behavior, -- because the slave gives us a retry in the last timeout cycle -- -- we are still waiting for an reaction of the slave ... -- we abort this cycle (we need to drive cyc and stb low) -- and continue with the next datum (if its a burst or line transfer) -- elsif wb_tout_alarm = '1' then n_wb_state.state <= wb_read_rty; TCU_rbufWEn_t <= '1'; if AMU_buf_size = "0000" then -- single read transfer n_wb_state.state <= wb_idle; TCU_adrBufREn <= '1'; elsif AMU_buf_size( 3 downto 2 ) = "00" then -- read line transfer if ( ( AMU_buf_size( 1 downto 0 ) = "01" and c_wb_state.transfer_count = "0011" ) or ( AMU_buf_size( 1 downto 0 ) = "10" and c_wb_state.transfer_count = "0111" ) or ( AMU_buf_size( 1 downto 0 ) = "11" and c_wb_state.transfer_count = "1111" ) ) then n_wb_state.transfer_count <= ( others => '0' ); n_wb_state.state <= wb_idle; TCU_adrBufREn <= '1'; else -- we use the retry state to drive stb and cyc low n_wb_state.state <= wb_read_rty; n_wb_state.transfer_count <= std_logic_vector( unsigned'( unsigned(c_wb_state.transfer_count) +1 ) ); end if; else -- burst read transfer if c_wb_state.transfer_count = AMU_buf_BE then n_wb_state.transfer_count <= ( others => '0' ); n_wb_state.state <= wb_idle; TCU_adrBufREn <= '1'; -- add info to the status fifo else -- we use the retry state to drive stb and cyc low n_wb_state.state <= wb_read_rty; n_wb_state.transfer_count <= std_logic_vector( unsigned'( unsigned(c_wb_state.transfer_count) +1 ) ); end if; end if; end if; end if; -- -- The generation of the lock-signal. If we are in a transfer (or starting a transfer), which is on -- the plb-size a line or burst transfer and if block transfers are supported, we lock the bus (block transfer) -- -- if ( ( c_wb_state.state = wb_read or c_wb_state.state = wb_write or c_wb_state.state = wb_read_rty or c_wb_state.state = wb_write_rty or start_wb_w = '1' or start_wb_r = '1' ) and AMU_buf_size /= "0000" and WB_SUPPORT_BLOCK > 0 ) then wb_lock_o <= '1'; end if; -- -- The WB-spec says, that wb_rty_i terminates a cycle, so wb_stb_o and wb_cyc_o is '0' -- if c_wb_state.state = wb_read_rty then n_wb_state.state <= wb_read; wb_tout_reset <= '1'; end if; if ( c_wb_state.state = wb_write_stall and ( STU_continue = '1' or STU_abort = '1' ) )then if STU_abort = '1' then n_wb_state.abort <= '1'; end if; n_wb_state.state <= wb_write; wb_tout_reset <= '1'; end if; if wb_rst_short = '1' then TCU_wb_status_info( STATUS2PLB_RST ) <= '1'; TCU_stat2plb_en <= '1'; end if; for i in 0 to WB_PIC_INTS-1 loop if pic_int_ahigh_short( i ) = '1' then TCU_stat2plb_en <= '1'; TCU_wb_status_info( STATUS2PLB_IRQ ) <= '1'; end if; end loop; TCU_wb_irq_info <= ( others => '0' ); TCU_wb_irq_info( IRQ_INFO_SIZE-1 downto IRQ_INFO_SIZE-WB_PIC_INTS ) <= pic_int_ahigh_short; end process; TCU_adr_offset <= c_wb_state.transfer_count; -- We drive this signal high, if -- -> there is a wb-error -- -> there is a timeout and if we are not getting any response in this clock cycle RBF_rdErrIn <= '1' when ( wb_err_i = '1' or ( wb_tout_alarm = '1' and wb_rty_i = '0' and wb_ack_i = '0' ) ) else '0'; end architecture IMP;