📄 cardbus_wrapper.vhd
字号:
-----------------------------------------------------------------------
-- File : cardbus_wrapper.vhd
--
-- DESCRIPTION:
-- This file provides all CardBus signals (in addition to PCI signals),
-- as well as registers and logic to support those new signals.
--
-- HIERARCHY:
-- This file is used in the top-level design, to "wrap-around" the PCI core
--
-- AUTHOR: Claire Pian Tu
--
-- HISTORY:
-- Date Author Version
-- 02/04/04 Claire Pian Tu 1.0
-- - Initial release, translated from verilog version
--
-- Copyright (C) 2004, Licensed Customers of QuickLogic may copy and modify this
-- file for use in designing QuickLogic devices only.
--
-- IMPORTANT NOTICE: DISCLAIMER OF WARRANTY
-- This design is provided without warranty of any kind.
-- QuickLogic Corporation does not warrant, guarantee or make any representations
-- regarding the use, or the results of the use, of this design. QuickLogic
-- disclaims all implied warranties, including but not limited to implied
-- warranties of merchantability and fitness for a particular purpose. In addition
-- and without limiting the generality of the foregoing, QuickLogic does not make
-- any warranty of any kind that any item developed based on this design, or any
-- portion of it, will not infringe any copyright, patent, trade secret or other
-- intellectual property right of any person or entity in any country. It is the
-- responsibility of the user of the design to seek licenses for such intellectual
-- property rights where applicable. QuickLogic shall not be liable for any
-- damages arising out of or in connection with the use of the design including
-- liability for lost profit, business interruption, or any other damages whatsoever.
--
-----------------------------------------------------------------------*/
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
--use work.cfgtaddr_5632_280_pkg.all;
entity cardbus_wrapper is
port (
-- outputs
CINT_n : out std_logic;
CSTSCHG : out std_logic;
CAUDIO : out std_logic;
clk_stopped : out std_logic;
locked : out std_logic;
owner_access : out std_logic;
cstschg_rdy : out std_logic;
-- CIS_Hit : out std_logic;
-- inouts
cstschg_regs_in: in std_logic_vector(31 downto 0);
CCLKRUN_n_in: in std_logic;
CBLOCK_n: in std_logic;
cstschg_regs_out: out std_logic_vector(31 downto 0);
CCLKRUN_n_out: out std_logic;
cstschg_regs_oe: out std_logic;
CCLKRUN_n_oe: out std_logic;
-- inputs
BAM_in: in std_logic;
PWM_in: in std_logic;
clk: in std_logic;
reset: in std_logic;
clk_resume: in std_logic;
addr_phase: in std_logic;
-- last_cycle : in std_logic;
framen_d1: in std_logic;
usr_read: in std_logic;
usr_write: in std_logic;
user_addr: in std_logic_vector(9 downto 0);
intr_ps: in std_logic;
gwake_ps: in std_logic;
bvd_ps: in std_logic_vector(2 downto 1);
ready_ps: in std_logic;
wp_ps: in std_logic;
BAR_match: in std_logic
);
end cardbus_wrapper;
architecture behavioral of cardbus_wrapper is
--signal declaration
--constants
-- CAUDIO internal signals
signal BAM_en: std_logic; -- bit 5 of FcnEvenMaskReg
signal PWM_en: std_logic; -- bit 6 of FcnEvenMaskReg
signal BAM_PWM: std_logic_vector(1 downto 0);
-- CBLOCK# internal signals
signal cblockn_d1: std_logic;
signal find_lock: std_logic_vector(1 downto 0);
--CCLKRUN# internal signals
signal clk_cnt: std_logic_vector(1 downto 0);
signal locked_int: std_logic;
signal owner_access_int: std_logic;
signal clk_stopped_int: std_logic;
-- CSTSCHG internal signals
signal FcnEventReg: std_logic_vector(15 downto 0);
signal FcnMaskReg: std_logic_vector(15 downto 0);
signal gwake_ls: std_logic;
signal bvd_ls: std_logic_vector(2 downto 1);
signal ready_ls: std_logic;
signal wp_ls: std_logic;
--signal cstschg_regs_out_int: std_logic_vector(31 downto 0);
signal xfer_on_going: std_logic; -- flag to indicate xfer going on
signal gwake_intr: std_logic; --masked GWAKE
signal bvd_intr: std_logic; --masked BVD
signal ready_intr: std_logic; --masked READY
signal wp_intr: std_logic; --masked WP
signal event_reg_cs: std_logic; -- addr decoding for FcnEvent related regs
-- regs are located in mem space indicated by
-- CISTPL_CONFIG_CB in CIS
signal cstschg_rdy_int: std_logic;
begin
-- CIS interface implemented externally to this module
-- CIS FLASH data bus connected to core, via large data mux
-- read CIS FLASH when BAR5 matches, starting offset 0x00
-- ie config space usr_addr = addr to CIS
-- bAR_match is also select for the MUX
--assigns
clk_stopped <= clk_stopped_int;
locked <= locked_int;
cstschg_rdy <= cstschg_rdy_int;
CINT_n <= not ((FcnEventReg(15) or intr_ps) and FcnMaskReg(15));
-- CSTSCHG PC Card Spec Chapter 2, section 5.2.11
gwake_intr <= FcnEventReg(4) and FcnMaskReg(4);
bvd_intr <= FcnMaskReg(2) and FcnMaskReg(3) and (FcnEventReg(2) or FcnEventReg(3));
ready_intr <= FcnEventReg(1) and FcnMaskReg(1);
wp_intr <= FcnEventReg(0) and FcnMaskReg(0);
-- WKUP enable GWAK BVD[2:1] READY Write Protect
CSTSCHG <= FcnMaskReg(14) and (gwake_intr or bvd_intr or ready_intr or wp_intr);
-- see metaformat volumn, 3.3.5 and 3.3.5.3
event_reg_cs <= '1' when (xfer_on_going = '1') and (user_addr(9 downto 4) = "110000") else '0';
-- note: comparison width depends on desired BAR width
-- comparison value depends on the value specified
-- in the CISTPL_CONFIG_CB tuple
process (clk, reset)
begin
if reset = '1' then
xfer_on_going <= '0';
elsif clk'event and clk = '1' then
if (BAR_match = '1') then
xfer_on_going <= '1';
elsif (usr_read = '0' and usr_write = '0') then
xfer_on_going <= '0';
end if;
end if;
end process;
cstschg_regs_oe <= usr_read and event_reg_cs;
process (clk, reset)
begin
if reset = '1' then
FcnEventReg(15) <= '0';
FcnEventReg(4 downto 0) <= "00000";
FcnMaskReg(15 downto 14) <= "00";
FcnMaskReg(6 downto 0) <= "0000000";
cstschg_regs_out <= x"00000000";
gwake_ls <= '0';
bvd_ls <= "00";
ready_ls <= '0';
wp_ls <= '0';
cstschg_rdy_int <= '0';
FcnEventReg(14 downto 5) <= "0000000000";
FcnMaskReg(13 downto 7) <= "0000000";
elsif clk'event and clk = '1' then
if event_reg_cs = '1' then
cstschg_rdy_int <= '1'; --ensure Usr_Rdy is not stuck high
case user_addr(3 downto 2) is
when "00" => -- 0x0: Function Event
if usr_read = '1' then -- return FcnEventReg value
cstschg_regs_out <= x"0000" &
FcnEventReg(15) &
x"00" & "00" &
FcnEventReg(4 downto 0);
elsif usr_write = '1' and cstschg_rdy_int = '1' then --write 1 to clear, 0 has no effect
FcnEventReg(15) <= not cstschg_regs_in(15) and FcnEventReg(15);
FcnEventReg(4) <= not cstschg_regs_in(4) and FcnEventReg(4);
FcnEventReg(3) <= not cstschg_regs_in(3) and FcnEventReg(3);
FcnEventReg(2) <= not cstschg_regs_in(2) and FcnEventReg(2);
FcnEventReg(1) <= not cstschg_regs_in(1) and FcnEventReg(1);
FcnEventReg(0) <= not cstschg_regs_in(0) and FcnEventReg(0);
end if;
when "01" => -- 0x4: Function Event Mask
if usr_read = '1' then
cstschg_regs_out <= x"0000" &
FcnMaskReg(15 downto 14) &
"0000000" &
FcnMaskReg(6 downto 0);
elsif usr_write = '1' then
FcnMaskReg(15 downto 14) <= cstschg_regs_in(15 downto 14);
FcnMaskReg(6 downto 0) <= cstschg_regs_in(6 downto 0);
-- note that the mask for BVD[2:1] should be "11" or "00"
-- value of "01" or "10" will be treated as "00"
end if;
when "10" => -- 0x8: Function Present State
if usr_read = '1' then
cstschg_regs_out <= x"0000" &
intr_ps &
x"00" & "00" &
gwake_ps &
bvd_ps(1) &
bvd_ps(2) &
ready_ps &
wp_ps;
end if;
-- these values are not affected by CRST#
when "11" => --0x12 Function Force Event
-- this is an address port where FcnEventReg can be modified for debug
if usr_read = '1' then
cstschg_regs_out <= x"0000" &
FcnEventReg(15) &
x"00" & "00" &
FcnEventReg(4 downto 0);
elsif usr_write = '1' and cstschg_rdy_int = '1' then
--// write 1 to set; write 0 has no effect
FcnEventReg(15) <= cstschg_regs_in(15) or FcnEventReg(15);
FcnEventReg(4) <= cstschg_regs_in(4) or FcnEventReg(4);
FcnEventReg(3) <= cstschg_regs_in(3) or FcnEventReg(3);
FcnEventReg(2) <= cstschg_regs_in(2) or FcnEventReg(2);
FcnEventReg(1) <= cstschg_regs_in(1) or FcnEventReg(1);
FcnEventReg(0) <= cstschg_regs_in(0) or FcnEventReg(0);
end if;
when others => null;
end case;
else
-- when PCI is not accessing CSTSCHG registers
-- register the last state of present status
gwake_ls <= gwake_ps;
bvd_ls <= bvd_ps;
ready_ls <= ready_ps;
wp_ls <= wp_ps;
cstschg_rdy_int <= '0';
-- if present state changed, update the bits accordingly in FcnEventReg
if gwake_ls /= gwake_ps then
FcnEventReg(4) <= '1';
end if;
if bvd_ls(1) /= bvd_ps(1) then
FcnEventReg(3) <= '1';
end if;
if bvd_ls(2) /= bvd_ps(2) then
FcnEventReg(2) <= '1';
end if;
if ready_ls /= ready_ps then
FcnEventReg(1) <= '1';
end if;
if wp_ls /= wp_ps then
FcnEventReg(0) <= '1';
end if;
end if;
end if;
end process;
-- CAUDIO 5.2.12
BAM_en <= FcnMaskReg(5);
PWM_en <= FcnMaskReg(6);
BAM_PWM <= BAM_en & PWM_en;
process (BAM_in, PWM_in, BAM_PWM)
begin
case BAM_PWM is
when "01" => CAUDIO <= PWM_in;
when "10" => CAUDIO <= BAM_in;
when others => CAUDIO <= '0';
end case;
end process;
-- CCLKRUN# 5.2.10
clk_stopped_int <= clk_cnt(1);
CCLKRUN_n_oe <= clk_resume and clk_stopped_int;
CCLKRUN_n_out <= '0';
-- CCLKRUN_n_out is always set to 0
-- assert (ie OE = 1) if need to resume, else it's input
-- if FGPA wants clk to remain normal (ie running), it must respond
-- within 2 clock cycles of sampling clk_stopped high
-- by driving clk_resume
process(clk, reset)
begin
if reset = '1' then
clk_cnt <= "00";
elsif clk'event and clk = '1' then
case clk_cnt is
when "00" =>
if CCLKRUN_n_in = '1' then
clk_cnt <= "01";
end if;
when "01" =>
if CCLKRUN_n_in = '1' then
clk_cnt <= "10";
else
clk_cnt <= "00";
end if;
when "10" =>
if CCLKRUN_n_in = '0' then
clk_cnt <= "11";
end if;
when "11" =>
if CCLKRUN_n_in = '0' then
clk_cnt <= "00";
else
clk_cnt <= "10";
end if;
when others => null;
end case;
end if;
end process;
-- CBLOCK# 5.2.6
process(clk, reset)
begin
if reset = '1' then
find_lock <= "00";
cblockn_d1 <= '0';
locked_int <= '0';
owner_access <= '0';
elsif clk'event and clk = '1' then
cblockn_d1 <= CBLOCK_n;
case find_lock is
when "00" =>
if addr_phase = '1' and cblockn_d1 = '1' then
find_lock <= "01";
end if;
if framen_d1 = '1' and cblockn_d1 = '1' then
locked_int <= '0';
end if;
when "01" =>
if (usr_read or usr_write) = '1' and cblockn_d1 = '0' then
locked_int <= '1';
find_lock <= "10";
else
find_lock <= "00";
end if;
when "10" =>
find_lock <= "00";
when others => null;
end case;
if locked_int = '1' and find_lock(1) = '1' then
owner_access <= '1';
elsif framen_d1 = '1' and not (usr_read or usr_write) = '1' then
owner_access <= '0';
end if;
end if;
end process;
end behavioral;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -