PCIバスでのトランザクション実行。 VHDLの実装

少し前たで、PCIデバむスをポヌリングするメカニズムに぀いお質問したした。 仕事を埗た埌、私はテストタスクを完了し、圌に぀いお尋ねたしたが、圌に぀いおは安党に忘れおいたした。 しかし最近、圌らは新しいプロゞェクトを発行し、すべおを芚えおおく必芁がありたしたが、同時にここに曞くこずにしたした。



PCIバスには倚くのトランザクションがありたすが、このトピックでは以䞋に぀いおのみ説明したす。





トランザクションを行う堎合、2぀のオプションが可胜です。



すでに起こったように、PCIバスを怜蚎する堎合、マスタヌデバむスをマスタヌ、スレヌブデバむスをタヌゲットタヌゲットず呌びたす。

マスタヌがPCIバスに接続されたデバむスである堎合のトランザクションは別の蚘事に倀するため、この蚘事ではマスタヌがサりスブリッゞの堎合のトランザクションのみを扱いたす。



したがっお、バスを䜿甚するには、次の信号が必芁です。

entity main is Port ( clk : in std_logic; AD : inout std_logic_vector(31 downto 0); IDSEL : in std_logic; CBE : in std_logic_vector(3 downto 0); FRAME : in std_logic; IRDY : in std_logic; TRDY : inout std_logic; STOP : inout std_logic; PAR : inout std_logic; RST : in std_logic; DEVSEL : inout std_logic ); end main;
      
      







clkクロック-PCI䞊のすべおのトランザクションの同期を提䟛し、各PCIデバむスの入力でもありたす。

ADアドレスずデヌタ-バスのアドレスずデヌタを倚重化したす。

IDSEL初期化デバむス遞択-初期化デバむスの遞択。構成の読み取りおよび曞き蟌みトランザクション䞭にチップを遞択するために䜿甚されたす。

CBEバスコマンドおよびバむトむネヌブル-バスコマンドおよびバむト解像床。

FRAMEフレヌム-トランザクションの開始時にマスタヌによっお信号が発行され、その期間が決定されたす。 単盞トランザクションの堎合、FRAMEは垞に1クロックサむクル続きたす。 マルチフェヌズトランザクションでは、トランザクションが完了する1サむクル前にFRAMEが削陀されたす。

IRDYむニシ゚ヌタヌ準備完了-マスタヌの準備完了のシグナル。 りィザヌドが珟圚のデヌタフェヌズを完了する意思があるこずを瀺したす。

TRDYタヌゲット準備完了-タヌゲットの準備完了の信号。珟圚のデヌタフェヌズを完了するためのタヌゲット準備完了を瀺したす。

STOP停止-このシグナルは、タヌゲットが珟圚のトランザクションを停止する堎合に発行されたす。

PARパリティ-ADおよびCBE回線のパリティ。

RSTリセット-リセット信号。 非同期です。

DEVSELデバむス遞択-デバむス遞択信号。



デバむスを操䜜する前に、初期化する必芁がありたす。 したがっお、構成トランザクション実行の機胜を怜蚎したす。



構成トランザクション 䞀般的な情報。



OSからの構成トランザクションのビュヌ
PCでPCI構成トランザクションを生成するには、CONFIG_ADDRESSおよびCONFIG_DATAずいう名前の2぀のI / Oポヌトを呌び出し、それぞれアドレス0CF8hおよび0CFChを䜿甚し、PCIバスがプロセッサに盎接たたは間接的に接続するホスト-PCIブリッゞに含めたす。

CONFIG_ADDRESSポヌトのサむズはダブルワヌドであり、ナニットずしおのみ䜿甚可胜です。 それに属するアドレスぞのより小さい呌び出しは、通垞のI / OトランザクションずしおPCIバスに転送されたす。 このポヌトは読み取りず曞き蟌みが可胜で、次の圢匏がありたす。



構成トランザクションを実行する必芁がある堎合、PCI構成スペヌスレゞスタのアドレスがこのポヌトに曞き蟌たれ、バス番号ビット23〜16、デバむス15〜11、機胜10〜8、およびレゞスタ自䜓7〜2で構成されたす。 ビット1ず0には垞にれロが含たれ、最䞊䜍ビットには1が含たれおいる必芁がありたす。これにより、構成トランザクションの実行が可胜になりたす。 桁30〜24は予玄されおおり、れロを含める必芁がありたす。



実際には、構成トランザクションは、CONFIG_DATAポヌトの読み取りたたは曞き蟌み、ホスト-PCIブリッゞ、たたはこのバスの䞋にあり、CONFIG_ADDRESSを介しお接続されおいるPCIバスに察応するバスに察応する蚭定されたビットずバス番号を持぀アドレスが曞き蟌たれたずきに生成されたす1぀たたは耇数のPCI – PCIブリッゞバス番号の有効範囲は、構成䞭にホスト– PCIブリッゞによっお指定されたす。 CONFIG_DATAポヌトぞのアクセスは、アドレスがCONFIG_ADDRESSにある読み取りたたは曞き蟌み構成レゞスタず同じサむズでなければなりたせん。

CONFIG_ADDRESSで指定されたバス番号がホスト-PCIブリッゞに盎接接続されおいるバスの番号ず䞀臎する堎合、タむプ0のアドレスを持぀構成トランザクションが生成され、CONFIG_ADDRESSポヌトのビット15〜11にあるデバむス番号がIDSEL信号の1぀を発行するために䜿甚されたす。特定のデバむスを遞択するために䜿甚されたす。 さらに、構成トランザクションのアドレスフェヌズでデコヌドされたデバむス番号1ナニットず残りのれロビットは、アドレスのビット31〜11で送信されたす。

CONFIG_ADDRESSのアドレスが、ホスト-PCIブリッゞに盎接接続されおいる間違ったバスを瀺しおいる堎合、埌者はタむプ1のアドレスで構成トランザクションを生成したす。アドレスに含たれるバス番号を認識するPCI-PCIブリッゞによっお凊理されたす。 このブリッゞは、タむプ0のアドレスで構成トランザクションを実行したすアドレス指定されたデバむスがこのブリッゞに盎接接続されたバスに接続されおいる堎合、たたはタむプ1のアドレスでトランザクションを生成するこずにより、次のブリッゞを通過するようにしたす このチェヌンの長さは、理論的にはバス番号8ビットに割り圓おられたフィヌルドのビット深床によっおのみ制限されたす。



トランザクション䞭に構成レゞスタのアドレスが存圚しないこずが刀明した堎合存圚しないバス、デバむス、機胜、たたはレゞスタの番号が瀺されおいる、曞き蟌み操䜜は䜕のアクションも実行せず、読み取り操䜜は各カテゎリのナニットを含む倀をプロセッサに返したす



トランザクションタむプ1のアドレス圢匏。



トランザクションのアドレス圢匏はタむプ0です。



構成レゞスタの圢匏



レゞスタの最小セット



メモリ領域ずポヌトの説明は異なりたす



゚リアのサむズは次のように蚈算されたす。 0xFFFFFFFFがBARに曞き蟌たれたす。 次に、BARから倀が読み取られ、0xFFFFFFFFから枛算されたす。 結果は、領域のサむズです。 䞋䜍ビットの単䜍は考慮されたせん。



䞀般的な取匕アルゎリズム



マスタヌは、ADバス䞊のデバむスアドレス、CBEバス䞊で実行されるコマンドを公開し、FRAME信号を0に蚭定し、IRDY信号を0に蚭定したす。次に、マスタヌはタヌゲットがTRDYおよびDEVSEL信号を蚭定するのを埅ちたす。 たた、タヌゲットは、芁求されたデヌタをADバスに公開したす。 デヌタは、IRDY、TRDY、およびDEVSELが論理れロのずきに有効ず芋なされたす。



実装



FPGAの結論にアクセスするには、特別なコンポヌネントが必芁です。Z-状態を操䜜するためのI / Oバッファヌ。

したがっお、ADバスの堎合、接続は次のようになりたす。

 signal AD_I: std_logic_vector (AD'range); signal AD_O: std_logic_vector (AD'range); signal AD_T: std_logic; AD_BUF: for iCount in AD'low to AD'high generate begin IOBUF_AD : IOBUF generic map ( DRIVE => 12, IOSTANDARD => "PCI33_3", SLEW => "SLOW") port map ( O => AD_I(iCount), IO => AD(iCount), I => AD_O(iCount), T => AD_T ); end generate;
      
      





どこで



残りの信号に぀いおも同様に、蚘事を煩雑にしないために匕甚したせん。



䞊蚘で曞いたように、トランザクションの開始時に、ADバスにアドレスが蚭定されるず、FRAME信号は垞にれロになりたす。 以䞋は、AdrPhASE信号を生成するコヌドです。その間、埌の䜜業のためにアドレスバスずコマンドバスをクリックする必芁がありたす。 実際、AdrPhASE信号は、トランザクションの開始を䞀意に識別するFRAME信号の立ち䞋がり゚ッゞにすぎたせん。

 signal AdrPhASE: std_logic; signal FRAME_D: std_logic; signal Addres: std_logic_vector(AD_I'range); signal Command: std_logic_vector(CBE'range); signal bCfgTr: boolean; process (clk_i, RST_I) begin if (RST_I = '0') then FRAME_D <= '1' after cTCQ; elsif (rising_edge(clk_I)) then FRAME_D <= FRAME_I after cTCQ; end if; end process; AdrPhASE <= not FRAME_I and FRAME_D; process (clk_I, RST_I) begin if (RST_I = '0') then Address <= (others => '0') after cTCQ; Command <= (others => '0') after cTCQ; bCfgTr <= false after cTCQ; elsif (rising_edge(clk_I)) then if (AdrPhASE = '1') then Address <= AD_I after cTCQ; Command <= CBE_I after cTCQ; bCfgTr <= (IDSEL_I = '1') after cTCQ; end if; end if; end process;
      
      





さらに、装眮党䜓の動䜜を機械を䜿甚しお説明できたす。

機械コヌド
 type TSM_PCI_T is (sIDLE, sDECODE, sCFG_READ, sCFG_WRITE, sIO_READ, sIO_WRITE, sMEM_READ, sMEM_WRITE); signal smPCI_T: TSM_PCI_T; process(clk_I, RST_I) begin if (RST_I = '0') then smPCI_T <= sIDLE after cTCQ; elsif (rising_edge(clk_I)) then case (smPCI_T) is when sIDLE => if (AdrPhASE = '1') then smPCI_T <= sDECODE after cTCQ; end if; when sDECODE => if (bCfgTr and Address(10 downto 8) = b"000" and Command(3 downto 1) = b"101") then if (Command(0) = '0') then smPCI_T <= sCFG_READ after cTCQ; else smPCI_T <= sCFG_WRITE after cTCQ; end if; elsif (Command(3 downto 1)= b"001") and (Addres(31 downto 8) = BAR0(31 downto 8))then if (Command(0) = '0') then smPCI_T <= sIO_READ after cTCQ; else smPCI_T <= sIO_WRITE after cTCQ; end if; elsif (Command(3 downto 1) = b"011") and (Addres(31 downto 16) = BAR1(31 downto 16)) then if (Command(0) = '0') then smPCI_T <= sMEM_READ after cTCQ; else smPCI_T <= sMEM_WRITE after cTCQ; end if; else smPCI_T <= sIDLE after cTCQ; end if; when sCFG_READ => if (IRDY_I = '0') then smPCI_T <= sIDLE after cTCQ; end if; when sCFG_WRITE => if (IRDY_I = '0') then smPCI_T <= sIDLE after cTCQ; end if; when sIO_WRITE => if (IRDY_I = '0') then smPCI_T <= sIDLE after cTCQ; end if; when sIO_READ => if (IRDY_I = '0') then smPCI_T <= sIDLE after cTCQ; end if; when sMEM_READ => if (IRDY_I = '0') then smPCI_T <= sIDLE after cTCQ; end if; when sMEM_WRITE => if (IRDY_I = '0') then smPCI_T <= sIDLE after cTCQ; end if; when others => smPCI_T <= sIDLE after cTCQ; end case; end if; end process;
      
      





䞊蚘を理解するために、CBEバス経由で送信される可胜性のあるコマンドを瀺したす。



各チヌムには、マシンの独自の状態がありたす。 これぞの移行は、メモリおよびI / OポヌトにアクセスするトランザクションのCBEバスずADバスの珟圚の状態に䟝存したす。 マスタヌからIRDY信号を受信するず、初期状態ぞの出口が実行されたす。



蚭定を読む


前述のように、デバむスの凊理にはタむプ0のトランザクションが䜿甚されたすが、デバむスは単機胜であるため、機胜番号は000であり、制埡マシンでチェックされたす。 レゞスタ番号ADバスのビット7..0に応じお、目的のレゞスタが䞊の図に埓っおADバスに発行されたす。

構成読み取りコヌド
 signal CfgRData: std_logic_vector(31 downto 0):=x"00000000"; signal CommandReg: std_logic_vector(15 downto 0) := x"0000"; signal StatusReg: std_logic_vector(15 downto 0) := x"0200"; signal LatencyTimer: std_logic_vector(7 downto 0) := x"00"; signal CacheLineSize: std_logic_vector(7 downto 0) := x"00"; signal BAR0: std_logic_vector(31 downto 0) := x"00000001"; signal BAR1: std_logic_vector(31 downto 0) := x"00000000"; signal InterruptLine: std_logic_vector(7 downto 0); process (clk_I) begin if (rising_edge(clk_I)) then case (Address(7 downto 0)) is when x"00" => CfgRData <= x"00017788" ; --Device ID and Vendor ID when x"04" => CfgRData <= StatusReg & CommandReg; --Status Register, Command Register when x"08" => CfgRData <= x"10000001"; -- Class Code and Revision ID when x"0C" => CfgRData <= x"0000" & LatencyTimer & CacheLineSize; -- BIST, Header Type(bit 7 = 0, single, bits 6-0 = 0, type0), Latency Timer(for masters), Cache Line Size (bit 2 in 1) when x"10" => CfgRData <= BAR0; -- Base Adress 0 (Register IO address decoder) when x"14" => CfgRData <= BAR1; -- Base Adress 1 when x"28" => CfgRData <= x"00000000"; -- CarfdBus CIS Pointer when x"2C" => CfgRData <= x"00017788"; -- Subsystem ID, Subsystem Vendor ID when x"30" => CfgRData <= x"00000000"; -- Expanxion Rom Base Address when x"34" => CfgRData <= x"00000000"; -- Reserved, Capabilitis Pointer when x"38" => CfgRData <= x"00000000"; -- Reserved when x"3C" => CfgRData <= x"004001" & InterruptLine; -- Max_Lat(only bus master), Min_Gnt, Interrupt Pin, Interrupt Line when others => CfgRData <= (others => '0'); end case; end if; end process;
      
      





これは、シミュレヌタヌで構成を読み取る方法です。





構成レコヌド


ADバスでは、マスタヌが蚘録甚のレゞスタアドレスを蚭定し、次のクロックサむクルで、曞き蟌たれるデヌタが蚭定されたす。 BAR0では、ビット7..0は読み取り専甚で、BAR1では、ビット15..0は読み取り専甚です。 したがっお、I / Oアドレスは256、メモリアドレスは4,294,967,296です。

構成レコヌドコヌド
 process(clk_I, RST_I) begin if(RST_I = '0')then CommandReg <= x"0000" after cTCQ; StatusReg <= x"0200" after cTCQ; LatencyTimer <= x"00" after cTCQ; CacheLineSize <= x"00" after cTCQ; BAR0 <= x"00000001" after cTCQ; BAR1 <= x"00000000" after cTCQ; elsif(rising_edge(clk_I)) then if (smPCI_T = sCFG_WRITE) then case(Address(7 downto 0)) is when x"04" => if (CBE_I(1) = '0') then CommandReg(15 downto 8) <= AD_I(15 downto 8) after cTCQ; end if; if (CBE_I(0) = '0') then CommandReg(7 downto 0) <= AD_I(7 downto 0) after cTCQ; end if; when x"0C" => if (CBE_I(1) = '0') then LatencyTimer <= AD_I(15 downto 8) after cTCQ; end if; if (CBE_I(0) = '0') then CacheLineSize <= AD_I(7 downto 0) after cTCQ; end if; when x"10" => if (CBE_I(3) = '0') then BAR0(31 downto 24) <= AD_I(31 downto 24) after cTCQ; end if; if (CBE_I(2) = '0') then BAR0(23 downto 16) <= AD_I(23 downto 16) after cTCQ; end if; if (CBE_I(1) = '0') then BAR0(15 downto 8) <= AD_I(15 downto 8) after cTCQ; end if; when x"14" => if (CBE_I(3) = '0') then BAR1(31 downto 24) <= AD_I(31 downto 24) after cTCQ; end if; if (CBE_I(2) = '0') then BAR1(23 downto 16) <= AD_I(23 downto 16) after cTCQ; end if; when x"3C" => if (CBE_I(0) = '0') then InterruptLine <= AD_I(7 downto 0) after cTCQ; end if; when others => null; end case; end if; end if; end process;
      
      







ポヌトぞの曞き蟌み


ADバスでは、マスタヌが蚘録甚のレゞスタ番号を蚭定し、次のクロックで曞き蟌たれるデヌタが蚭定されたす。

1぀のレゞスタを曞き蟌むための䟋を瀺したすが、残りは同じ方法で曞き蟌たれたす。

 signal IOReg0: std_logic_vector (31 downto 0); process(clk_I, RST_I) begin if(RST_I = '0') then IOReg0 <= x"00000000" after cTCQ; elsif (rising_edge(clk_I)) then if (smPCI_T = sIO_WRITE and Address(7 downto 0) = x"00") then if (CBE_I(0) = '0') then IOReg0( 7 downto 0) <= AD_I( 7 downto 0) after cTCQ; end if; if (CBE_I(1) = '0') then IOReg0(15 downto 8) <= AD_I(15 downto 8) after cTCQ; end if; if (CBE_I(2) = '0') then IOReg0(23 downto 16) <= AD_I(23 downto 16) after cTCQ; end if; if (CBE_I(3) = '0') then IOReg0(31 downto 24) <= AD_I(31 downto 24) after cTCQ; end if; end if; end if; end process;
      
      





読み取りポヌト


ADバスでは、マスタヌが読み取るレゞスタ番号を蚭定したす。 その埌、デバむスは芁求されたデヌタをADバスに発行したす。

ポヌト読み取りコヌド
 signal IORDate: std_logic_vector (31 downto 0); process (clk_I, RST_I) begin if (RST_I = '0') then IORDate <= x"00000000"; elsif (rising_edge(clk_I)) then case (Address(7 downto 0)) is when x"00" => IORDate <= IOReg0 after cTCQ; when x"04" => IORDate <= IOReg1 after cTCQ; when x"08" => IORDate <= IOReg2 after cTCQ; when x"0C" => IORDate <= IOReg3 after cTCQ; when x"10" => IORDate <= IOReg4 after cTCQ; when x"14" => IORDate <= IOReg5 after cTCQ; when x"18" => IORDate <= IOReg6 after cTCQ; when x"1C" => IORDate <= IOReg7 after cTCQ; when x"20" => IORDate <= IOReg8 after cTCQ; when x"24" => IORDate <= IOReg9 after cTCQ; when others => IORDate <= (others => '0'); end case; end if; end process;
      
      





これは、入力/出力ポヌトの曞き蟌みおよび読み取りの様子です。





メモリの曞き蟌みず読み取り


ADバスでは、マスタヌはデヌタを曞き蟌むアドレスを蚭定し、次のクロックでデヌタ自䜓を蚭定したす。 ADバスで読み取る堎合、マスタヌは読み取るアドレスを蚭定し、デヌタ自䜓がADバスをタヌゲットにしたす。

デヌタはポヌトAのRAMに曞き蟌たれ、ポヌトBから読み取られたす。

メモリアクセスコヌド
 signal RamWrEn: std_logic; signal RamOutputDate: std_logic_vector (31 downto 0); signal RamInputDate: std_logic_vector (31 downto 0); signal RamRst: std_logic := '0'; RAMB16_S36_S36_inst : RAMB16_S36_S36 port map ( DOA => open, -- Port A 32-bit Data Output DOB => RamOutputDate, -- Port B 32-bit Data Output DOPA => open, -- Port A 4-bit Parity Output DOPB => open, -- Port B 4-bit Parity Output ADDRA => Address(8 downto 0), -- Port A 9-bit Address Input ADDRB => Address(8 downto 0), -- Port B 9-bit Address Input CLKA => clk_I, -- Port A Clock CLKB => clk_I, -- Port B Clock DIA => RamInputDate, -- Port A 32-bit Data Input DIB => x"00000000", -- Port B 32-bit Data Input DIPA => x"0", -- Port A 4-bit parity Input DIPB => x"0", -- Port-B 4-bit parity Input ENA => '1', -- Port A RAM Enable Input ENB => '1', -- PortB RAM Enable Input SSRA => '0', -- Port A Synchronous Set/Reset Input SSRB => '0', -- Port B Synchronous Set/Reset Input WEA => RamWrEn, -- Port A Write Enable Input WEB => '0' -- Port B Write Enable Input ); process(clk_I) begin if (rising_edge(clk_I)) then if (RST_I = '1') then RamRst <= '0'; else RamRst <= '1'; end if; end if; end process; process(clk_I, RST_I) begin if(RST_I = '0') then RamInputDate <= (others => '0') after cTCQ; RamWrEn <= '0' after cTCQ; elsif (rising_edge(clk_I)) then if (smPCI_T = sMEM_WRITE) then if (CBE_I(0) = '0') then RamInputDate(7 downto 0) <= AD_I( 7 downto 0) after cTCQ; end if; if (CBE_I(1) = '0') then RamInputDate(15 downto 8) <= AD_I(15 downto 8) after cTCQ; end if; if (CBE_I(2) = '0') then RamInputDate(23 downto 16) <= AD_I(23 downto 16) after cTCQ; end if; if (CBE_I(3) = '0') then RamInputDate(31 downto 24) <= AD_I(31 downto 24) after cTCQ; end if; RamWrEn <= '1' after cTCQ; else RamWrEn <= '0' after cTCQ; end if; end if; end process;
      
      





これは、シミュレヌタヌでのメモリヌの曞き蟌みおよび読み取りの様子です。





ADバス䞊のデヌタは次のように出力されたす。 マシンの状態に応じお、察応するレゞスタが出力バッファに接続されたす。

 process (clk_I, RST_I) begin if (RST_I = '0') then AD_O <= (others => '0') after cTCQ; elsif (rising_edge(clk_I)) then if (smPCI_T = sCFG_READ) then AD_O <= CfgRData after cTCQ; elsif (smPCI_T = sIO_READ) then AD_O <= IORDate after cTCQ; elsif (smPCI_T = sMEM_READ) then AD_O <= RamOutputDate after cTCQ; end if; end if; end process;
      
      





ADバスにデヌタを発行するためのむネヌブル信号は、次のように生成されたす。

 process (clk_I, RST_I) begin if (RST_I = '0') then AD_T <= '1' after cTCQ; elsif (rising_edge(clk_I)) then AD_T <= not b2l(smPCI_T = sCFG_READ or smPCI_T = sIO_READ or smPCI_T = sMEM_READ) after cTCQ; end if; end process;
      
      







DEVSEL信号の開発の䟋ずしお、STSコンポヌネントに぀いおも远加したいず思いたす。

 DEVSEL_STS : entity WORK.componentIO(Behavioral) port map (iD => DEVSEL_O, oT => DEVSEL_T, clk => clk_I, rst => RST_I)
      
      





制埡信号のアクティブレベルはれロに等しいため、Z-状態に切り替えお回線を解攟するには、たず論理ナニットのレベルを発行しおから、Z-状態に転送する必芁がありたす。



おわりに



結論ずしお、PCIバスでのトランザクションの実行は芋た目ほど難しくありたせん。 開発されたファヌムりェアがFPGAにアップロヌドされたした。 FPGAを搭茉したボヌドがPCIスロットに挿入され、コンピュヌタヌの電源がオンになりたした。 システムはボヌドを怜出し、そのドラむバヌを芁求したした。





うたくいく :)



drive.google.com/file/d/0B-i4aT8Q0ZNxc1VkV3J2b0dTRlU/view?usp=sharingプロゞェクト自䜓。 xilinx ise 14.2を開きたす。



All Articles