ping.vhd
来自「xilinx官方PCIcore 有详细说明文档」· VHDL 代码 · 共 594 行 · 第 1/2 页
VHD
594 行
WRITE_MY_MEM_REG: process(RST, CLK) begin if RST = '1' then my_mem_reg <= "00110010001100100011001000110010"; elsif (CLK'event and CLK = '1') then if S_DATA_VLD = '1' and bar1_wr_cs = '1' then if S_CBE(0) = '0' then my_mem_reg( 7 downto 0) <= ADIO( 7 downto 0); end if; if S_CBE(1) = '0' then my_mem_reg(15 downto 8) <= ADIO(15 downto 8); end if; if S_CBE(2) = '0' then my_mem_reg(23 downto 16) <= ADIO(23 downto 16); end if; if S_CBE(3) = '0' then my_mem_reg(31 downto 24) <= ADIO(31 downto 24); end if; end if; end if; end process; oe_mem_reg <= bar1_rd_cs and S_DATA; ADIO(31 downto 0) <= my_mem_reg when (oe_mem_reg = '1') else (others=>'Z'); ----------------------------------------------------------------------- -- This section contains the MEM64 implementation. ----------------------------------------------------------------------- WRITE_MY_WIDE_REG: process(RST, CLK) begin if RST = '1' then my_wide_reg <= "01100100011001000110010001100100" & "01100100011001000110010001100100"; elsif (CLK'event and CLK = '1') then if S_DATA_VLD = '1' and bar2_wr_cs = '1' then if S_CBE(0) = '0' then my_wide_reg( 7 downto 0) <= ADIO( 7 downto 0); end if; if S_CBE(1) = '0' then my_wide_reg(15 downto 8) <= ADIO(15 downto 8); end if; if S_CBE(2) = '0' then my_wide_reg(23 downto 16) <= ADIO(23 downto 16); end if; if S_CBE(3) = '0' then my_wide_reg(31 downto 24) <= ADIO(31 downto 24); end if; if S_CBE(4) = '0' then my_wide_reg(39 downto 32) <= ADIO(39 downto 32); end if; if S_CBE(5) = '0' then my_wide_reg(47 downto 40) <= ADIO(47 downto 40); end if; if S_CBE(6) = '0' then my_wide_reg(55 downto 48) <= ADIO(55 downto 48); end if; if S_CBE(7) = '0' then my_wide_reg(63 downto 56) <= ADIO(63 downto 56); end if; end if; end if; end process; oe_wide_reg <= bar2_rd_cs and S_DATA; ADIO(63 downto 0) <= my_wide_reg when (oe_wide_reg = '1') else (others=>'Z'); ----------------------------------------------------------------------- -- This section contains the initiator logic. ----------------------------------------------------------------------- -- Bus addresses are obtained from the MEM32 register. -- Direction is from IO32(31) and burst length is IO32(3:0). -- A general purpose register file is used for the source -- or destination depending on the data transfer direction. PING_FSM: process(ping_state, start32, start64, mdata_fell, dir) begin case ping_state is -- IDLE_S is the idle state. If the state machine is -- signaled to start, proceed to the next state. when IDLE_S => if start64 = '1' and dir = '1' then nxt_ping_state <= WRITE64_S; elsif start64 = '1' and dir = '0' then nxt_ping_state <= READ64_S; elsif start32 = '1' and dir = '1' then nxt_ping_state <= WRITE32_S; elsif start32 = '1' and dir = '0' then nxt_ping_state <= READ32_S; else nxt_ping_state <= IDLE_S; end if; -- WRITE64_S stays put until it sees a deassertion of -- the M_DATA signal indicating that a transfer is over. -- More elaborate FSMs may check error conditions at -- the time mdata_fell is asserted. when WRITE64_S => if mdata_fell = '1' then nxt_ping_state <= IDLE_S; else nxt_ping_state <= WRITE64_S; end if; -- WRITE32_S stays put until it sees a deassertion of -- the M_DATA signal indicating that a transfer is over. -- More elaborate FSMs may check error conditions at -- the time mdata_fell is asserted. when WRITE32_S => if mdata_fell = '1' then nxt_ping_state <= IDLE_S; else nxt_ping_state <= WRITE32_S; end if; -- READ64_S stays put until it sees a deassertion of -- the M_DATA signal indicating that a transfer is over. -- More elaborate FSMs may check error conditions at -- the time mdata_fell is asserted. when READ64_S => if mdata_fell = '1' then nxt_ping_state <= IDLE_S; else nxt_ping_state <= READ64_S; end if; -- READ32_S stays put until it sees a deassertion of -- the M_DATA signal indicating that a transfer is over. -- More elaborate FSMs may check error conditions at -- the time mdata_fell is asserted. when READ32_S => if mdata_fell = '1' then nxt_ping_state <= IDLE_S; else nxt_ping_state <= READ32_S; end if; -- Include a default state just in case we have any -- accidents with the state machine. when others => nxt_ping_state <= IDLE_S; end case; end process; PING_FSM_SEQ: process(RST, CLK) begin if RST = '1' then ping_state <= IDLE_S; elsif (CLK'event and CLK = '1') then ping_state <= nxt_ping_state; end if; end process; -- Need a delayed version of M_DATA and also -- a delayed version of the transfer length -- counter load signal. MISC_SIGNALS: process(RST, CLK) begin if RST = '1' then mdata_delay <= '0'; xfer_load_delay <= '0'; pre_done <= '0'; reg_preq32 <= '0'; reg_preq64 <= '0'; elsif (CLK'event and CLK = '1') then mdata_delay <= M_DATA; xfer_load_delay <= xfer_load; pre_done <= ns_done; reg_preq32 <= PING_REQUEST32; reg_preq64 <= PING_REQUEST64; end if; end process; -- This is the "set/reset" implementation -- for the COMPLETE logic. HOLD_IT: process(RST, CLK) begin if RST = '1' then feedback <= '0'; elsif (CLK'event and CLK = '1') then if mdata_fell = '1' then feedback <= '0'; elsif assert_complete = '1' then feedback <= '1'; end if; end if; end process; -- This is the transfer length counter. -- Transfer lengths may be anywhere from -- one to sixteen data phases. TRANSFER_COUNTER: process(RST, CLK) begin if RST = '1' then xfer_len <= "0000"; elsif (CLK'event and CLK = '1') then if xfer_load = '1' then xfer_len <= my_io_reg(3 downto 0); elsif M_DATA_VLD = '1' then xfer_len <= xfer_len - 1; end if; end if; end process; -- Decode some things for the complete logic. cnt3 <= '1' when (xfer_len = "0011") else '0'; cnt2 <= '1' when (xfer_len = "0010") else '0'; cnt1 <= '1' when (xfer_len = "0001") else '0'; fin3 <= cnt3 and M_DATA_VLD; fin2 <= cnt2 and mdata_delay; fin1 <= cnt1 and xfer_load_delay; -- Generate some internal signals. start32 <= reg_preq32; start64 <= reg_preq64; dir <= my_io_reg(31); mdata_fell <= not M_DATA and mdata_delay; xfer_load <= (start32 or start64) when (ping_state = IDLE_S) else '0'; assert_complete <= fin1 or fin2 or fin3; hold_complete <= feedback; ns_done <= mdata_fell when (ping_state /= IDLE_S) else '0'; -- Drive outputs to the PCI interface. M_WRDN <= dir; REQUEST <= start32 when (ping_state = IDLE_S) else '0'; REQUEST64 <= start64 when (ping_state = IDLE_S) else '0'; COMPLETE <= assert_complete or hold_complete; ADIO(63 downto 0) <= ("00000000000000000000000000000000" & my_mem_reg) when (M_ADDR_N = '0') else (others =>'Z'); M_CBE(7 downto 0) <= ("0000" & my_io_reg(7 downto 5) & dir) when (M_ADDR_N = '0') else (others =>'0'); PING_DONE <= pre_done; -- A simple 64-bit register for data transfer. xlr <= '1' when ((ping_state=READ32_S) or (ping_state=READ64_S)) else '0'; xlw <= '1' when ((ping_state=WRITE32_S) or (ping_state=WRITE64_S)) else '0'; xhr <= '1' when (ping_state = READ64_S) else '0'; WRITE_MY_INIT_REG: process(RST, CLK) begin if RST = '1' then my_init_reg <= "00000000000000000000000000000000" & "00000000000000000000000000000000"; elsif (CLK'event and CLK = '1') then if M_DATA_VLD = '1' then if xlr = '1' then my_init_reg( 7 downto 0) <= ADIO( 7 downto 0); end if; if xlr = '1' then my_init_reg(15 downto 8) <= ADIO(15 downto 8); end if; if xlr = '1' then my_init_reg(23 downto 16) <= ADIO(23 downto 16); end if; if xlr = '1' then my_init_reg(31 downto 24) <= ADIO(31 downto 24); end if; if xhr = '1' then my_init_reg(39 downto 32) <= ADIO(39 downto 32); end if; if xhr = '1' then my_init_reg(47 downto 40) <= ADIO(47 downto 40); end if; if xhr = '1' then my_init_reg(55 downto 48) <= ADIO(55 downto 48); end if; if xhr = '1' then my_init_reg(63 downto 56) <= ADIO(63 downto 56); end if; end if; end if; end process; oe_init_reg <= M_DATA and xlw; ADIO(63 downto 0) <= my_init_reg when (oe_init_reg = '1') else (others=>'Z'); ----------------------------------------------------------------------- -- This section contains unused signals. ----------------------------------------------------------------------- C_TERM <= '1'; C_READY <= '1'; KEEPOUT <= '0'; CFG_SELF <= '0'; REQUESTHOLD <= '0'; SUB_DATA <= "00000000000000000000000000000000"; DONT_OPTIMIZE_PLEASE: process(RST, CLK) begin if RST = '1' then intr_n_reg <= '0'; s_term_reg <= '1'; s_ready_reg <= '0'; m_ready_reg <= '0'; elsif (CLK'event and CLK = '1') then intr_n_reg <= '1'; s_term_reg <= '0'; s_ready_reg <= '1'; m_ready_reg <= '1'; end if; end process; INTR_N <= intr_n_reg; S_TERM <= s_term_reg; S_READY <= s_ready_reg; S_ABORT <= S_CYCLE64 and ADDR(2); M_READY <= m_ready_reg; SLOT64 <= not my_cfg_reg(0);end rtl;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?