まだまだ作成途上なので汚いですが、pciコアのソースコードです。
- PCIコア部分です。RAMを読む部分とPCIコアを分けていて、appcore_start、appcore_doneという信号で同期をとっています(その割には分離性が高くないですが)。このあたりをきちんと考えて設計しないと、バースト転送で速度を上げるのは難しそう。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity pcicore is
Port (PCI_CLK : in STD_LOGIC;
N_INTA : out STD_LOGIC;
N_RST_I : in STD_LOGIC;
N_FRAME_IO : inout STD_LOGIC;
N_TRDY_IO : inout STD_LOGIC;
N_GNT_I : in STD_LOGIC;
N_STOP_IO : inout STD_LOGIC;
PAR_IO : inout STD_LOGIC;
IDSEL_I : in STD_LOGIC;
N_IRDY_IO : inout STD_LOGIC;
N_DEVSEL_IO : inout STD_LOGIC;
N_PERR_IO : inout STD_LOGIC;
N_SERR_IO : inout STD_LOGIC;
N_REQ_Q : inout STD_LOGIC;
N_CBE_IO : inout STD_LOGIC_VECTOR(3 downto 0);
AD_IO : inout STD_LOGIC_VECTOR(31 downto 0);
SEG_LED_SELECT : out STD_LOGIC_VECTOR(4 downto 0);
SEG_LED_DATA : out STD_LOGIC_VECTOR(7 downto 0);
LED_2 : out STD_LOGIC;
LED_3 : out STD_LOGIC;
LED_4 : out STD_LOGIC;
LED_5 : out STD_LOGIC);
end pcicore;
architecture Behavioral of pcicore is
component SEGDISP
Port (PCI_CLK : in STD_LOGIC;
RESET: in STD_LOGIC;
SEL : out STD_LOGIC_VECTOR(4 downto 0);
DAT : out STD_LOGIC_VECTOR(7 downto 0);
DIGIT0: in std_logic_vector (3 downto 0);
DIGIT1: in std_logic_vector (3 downto 0);
DIGIT2: in std_logic_vector (3 downto 0);
DIGIT3: in std_logic_vector (3 downto 0));
end component;
component ram
port (
clka: IN std_logic;
dina: IN std_logic_VECTOR(31 downto 0);
addra: IN std_logic_VECTOR(8 downto 0);
wea: IN std_logic_vector(0 downto 0);
douta: OUT std_logic_VECTOR(31 downto 0));
end component;
signal AD_PORT: std_logic_vector(31 downto 0);
signal DEVSEL_PORT: std_logic;
signal TRDY_PORT: std_logic;
signal STOP_PORT: std_logic;
signal SERR_PORT : std_logic := 'Z';
signal PERR_PORT : std_logic := 'Z';
signal PAR_PORT : std_logic := 'Z';
signal buscommand : std_logic_vector(3 downto 0);
signal address : std_logic_vector(31 downto 0);
signal idsel : std_logic;
signal Hit_device : std_logic;
signal Hit_Memory0 : std_logic;
signal Hit_Memory1 : std_logic;
signal Hit_Config : std_logic;
signal curstate: std_logic_vector(3 downto 0);
signal nxtstate: std_logic_vector(3 downto 0);
constant IDLE : std_logic_vector(3 downto 0) := "0000";
constant ADDR : std_logic_vector(3 downto 0) := "0001";
constant BUSY : std_logic_vector(3 downto 0) := "0010";
constant IRDY : std_logic_vector(3 downto 0) := "0011";
constant LOCALWAIT : std_logic_vector(3 downto 0) := "0100";
constant COMP : std_logic_vector(3 downto 0) := "0101";
constant COMP2 : std_logic_vector(3 downto 0) := "0110";
constant DISCON : std_logic_vector(3 downto 0) := "0111";
constant INIT : std_logic_vector(3 downto 0) := "1000";
constant ERR : std_logic_vector(3 downto 0) := "1111";
signal l_curstate: std_logic_vector(3 downto 0) := "0000";
signal l_nxtstate: std_logic_vector(3 downto 0) := "0000";
constant L_IDLE : std_logic_vector(3 downto 0) := "0000";
constant L_CFG : std_logic_vector(3 downto 0) := "0001";
constant L_MEM0 : std_logic_vector(3 downto 0) := "0010";
constant L_MEM1 : std_logic_vector(3 downto 0) := "0011";
constant L_COMP : std_logic_vector(3 downto 0) := "0101";
constant L_ERR : std_logic_vector(3 downto 0) := "1111";
signal appcore_start : std_logic;
signal appcore_done : std_logic;
constant CMD_MemRead : std_logic_vector(3 downto 0) := ("0110");
constant CMD_MemWrite : std_logic_vector(3 downto 0) := ("0111");
constant CMD_ConfRead : std_logic_vector(3 downto 0) := ("1010");
constant CMD_ConfWrite : std_logic_vector(3 downto 0) := ("1011");
signal CFG_vendorID : std_logic_vector(15 downto 0) := (X"3449");
signal CFG_deviceID : std_logic_vector(15 downto 0) := (X"8000");
signal CFG_command : std_logic_vector(15 downto 0) := (X"0000");
signal CFG_status : std_logic_vector(15 downto 0) := (X"0200");
signal CFG_baseclass : std_logic_vector(7 downto 0) := (X"05");
signal CFG_subclass : std_logic_vector(7 downto 0) := (X"00");
signal CFG_programIF : std_logic_vector(7 downto 0) := (X"00");
signal CFG_revisionID : std_logic_vector(7 downto 0) := (X"01");
signal CFG_headertype : std_logic_vector(7 downto 0) := (X"00");
signal CFG_BAR0 : std_logic_vector(31 downto 4);
signal CFG_BAR1 : std_logic_vector(31 downto 20);
signal regtest0 : std_logic_vector(31 downto 0) := (X"00100000");
signal Ram_din : std_logic_vector(31 downto 0);
signal Ram_dout : std_logic_vector(31 downto 0);
signal Ram_addr : std_logic_vector(8 downto 0);
signal Ram_we : std_logic_vector(0 downto 0);
begin
LED_2 <= N_FRAME_IO;
LED_3 <= N_DEVSEL_IO;
LED_4 <= N_IRDY_IO;
LED_5 <= DEVSEL_Port;
segs : SEGDISP port map(
PCI_CLK => PCI_CLK,
RESET => N_RST_I,
SEL => SEG_LED_SELECT,
DAT => SEG_LED_DATA,
DIGIT0 => curstate,
DIGIT1 => regtest0(23 downto 20),
DIGIT2 => regtest0(27 downto 24),
DIGIT3 => regtest0(31 downto 28));
raminst : ram
port map (
clka => PCI_CLK,
dina => Ram_din,
addra => Ram_addr,
wea => Ram_we,
douta => Ram_dout);
Hit_device <= Hit_memory0 or Hit_memory1 or Hit_config;
process(idsel, buscommand, address, CFG_BAR0, CFG_BAR1, CFG_command)
begin
if ((buscommand = CMD_MemRead or buscommand = CMD_MemWrite) and
CFG_command(1) = '1') then
if (address(31 downto 4) = CFG_BAR0(31 downto 4)) then
Hit_memory0 <= '1';
Hit_memory1 <= '0';
elsif (address(31 downto 20) = CFG_BAR1(31 downto 20)) then
Hit_memory0 <= '0';
Hit_memory1 <= '1';
else
Hit_memory0 <= '0';
Hit_memory1 <= '0';
end if;
else
Hit_memory0 <= '0';
Hit_memory1 <= '0';
end if;
if ((buscommand = CMD_ConfRead or buscommand = CMD_ConfWrite) and
idsel = '1' and
address(10 downto 8) = "000" and address(1 downto 0) = "00")
then
Hit_config <= '1';
else
Hit_config <= '0';
end if;
end process;
Ram_addr <= address(10 downto 2);
process(PCI_CLK, N_RST_I)
begin
if (N_RST_I = '0') then
l_curstate <= L_IDLE;
l_nxtstate <= L_IDLE;
appcore_done <= '0';
CFG_BAR0 <= (others => '0');
CFG_BAR1 <= (others => '0');
CFG_command <= (others => '0');
Ram_we <= "0";
elsif (PCI_CLK'event and PCI_CLK='1') then
l_curstate <= l_nxtstate;
case l_curstate is
when L_IDLE =>
if (appcore_start = '1') then
if (Hit_config = '1') then
l_nxtstate <= L_CFG;
end if;
if (Hit_memory0 = '1') then
l_nxtstate <= L_MEM0;
end if;
if (Hit_memory1 = '1') then
l_nxtstate <= L_MEM1;
end if;
else
l_nxtstate <= L_IDLE;
end if;
when L_CFG =>
if (buscommand(0) = '1') then
case address(7 downto 2) is
when "000001" =>
if (N_CBE_IO(0) = '0') then
CFG_command(1) <= AD_IO(1);
end if;
when "000100" =>
if (N_CBE_IO(3) = '0') then
CFG_BAR0(31 downto 24) <= AD_IO(31 downto 24);
end if;
if (N_CBE_IO(2) = '0') then
CFG_BAR0(23 downto 16) <= AD_IO(23 downto 16);
end if;
if (N_CBE_IO(1) = '0') then
CFG_BAR0(15 downto 8) <= AD_IO(15 downto 8);
end if;
if (N_CBE_IO(0) = '0') then
CFG_BAR0(7 downto 4) <= AD_IO(7 downto 4);
end if;
when "000101" =>
if (N_CBE_IO(3) = '0') then
CFG_BAR1(31 downto 24) <= AD_IO(31 downto 24);
end if;
if (N_CBE_IO(2) = '0') then
CFG_BAR1(23 downto 20) <= AD_IO(23 downto 20);
end if;
when others =>
null;
end case;
else
case address(7 downto 2) is
when "000000" =>
AD_Port(31 downto 16) <= CFG_deviceID;
AD_Port(15 downto 0) <= CFG_vendorID;
when "000001" =>
AD_Port(31 downto 16) <= CFG_status;
AD_Port(15 downto 0) <= CFG_command;
when "000010" =>
AD_Port(31 downto 24) <= CFG_baseclass;
AD_Port(23 downto 16) <= CFG_subclass;
AD_Port(15 downto 8) <= CFG_programIF;
AD_Port(7 downto 0) <= CFG_revisionID;
when "000011" =>
AD_Port(31 downto 24) <= (others => '0');
AD_Port(23 downto 16) <= CFG_headertype;
AD_Port(15 downto 0) <= (others => '0');
when "000100" =>
AD_Port(31 downto 4) <= CFG_BAR0(31 downto 4);
AD_Port(3 downto 0) <= (others => '0');
when "000101" =>
AD_Port(31 downto 20) <= CFG_BAR1(31 downto 20);
AD_Port(19 downto 0) <= (others => '0');
when "001011" =>
AD_Port(31 downto 16) <= CFG_deviceID;
AD_Port(15 downto 0) <= CFG_vendorID;
when others =>
AD_Port(31 downto 0) <= (others => '0');
end case;
end if;
appcore_done <= '1';
l_nxtstate <= L_COMP;
when L_MEM0 =>
if (buscommand(0) = '1') then
case address(7 downto 0) is
when "00000000" =>
if (N_CBE_IO(3) = '0') then
regtest0(31 downto 24) <= AD_IO(31 downto 24);
end if;
if (N_CBE_IO(2) = '0') then
regtest0(23 downto 16) <= AD_IO(23 downto 16);
end if;
if (N_CBE_IO(1) = '0') then
regtest0(15 downto 8) <= AD_IO(15 downto 8);
end if;
if (N_CBE_IO(0) = '0') then
regtest0(7 downto 0) <= AD_IO(7 downto 0);
end if;
when others =>
null;
end case;
else
case address(7 downto 0) is
when "00000000" =>
AD_Port <= regtest0;
when others =>
AD_Port <= (others => '0');
end case;
end if;
appcore_done <= '1';
l_nxtstate <= L_COMP;
when L_MEM1 =>
if (buscommand(0) = '1') then
Ram_din <= AD_IO;
Ram_we <= "1";
else
Ram_we <= "0";
AD_Port <= Ram_dout;
end if;
appcore_done <= '1';
l_nxtstate <= L_COMP;
when L_COMP =>
appcore_done <= '0';
AD_Port <= (others => 'Z');
Ram_we <= "0";
l_nxtstate <= L_IDLE;
when L_ERR =>
l_nxtstate <= L_ERR;
when others =>
l_nxtstate <= L_ERR;
end case;
end if;
end process;
process(PCI_CLK, N_RST_I)
begin
if (N_RST_I = '0') then
curstate <= INIT;
nxtstate <= INIT;
elsif (PCI_CLK'event and PCI_CLK='1') then
curstate <= nxtstate;
case curstate is
when INIT =>
appcore_start <= '0';
DEVSEL_PORT <= 'Z';
TRDY_PORT <= 'Z';
STOP_PORT <= 'Z';
AD_Port <= (others => 'Z');
nxtstate <= IDLE;
when IDLE =>
if (N_FRAME_IO = '0' and N_IRDY_IO = '1') then
buscommand <= N_CBE_IO;
address <= AD_IO;
idsel <= IDSEL_I;
nxtstate <= ADDR;
else
nxtstate <= IDLE;
end if;
when ADDR =>
if (Hit_device = '1') then
DEVSEL_PORT <= '0';
TRDY_PORT <= '1';
STOP_PORT <= '1';
nxtstate <= IRDY;
else
nxtstate <= BUSY;
end if;
when BUSY =>
if (N_FRAME_IO = '1' and N_IRDY_IO = '1') then
nxtstate <= IDLE;
else
nxtstate <= BUSY;
end if;
when IRDY =>
if (N_IRDY_IO = '0') then
appcore_start <= '1';
nxtstate <= LOCALWAIT;
else
nxtstate <= IRDY;
end if;
when LOCALWAIT =>
appcore_start <= '0';
if (appcore_done = '1') then
TRDY_PORT <= '0';
STOP_PORT <= '0';
nxtstate <= COMP;
else
nxtstate <= LOCALWAIT;
end if;
when COMP =>
TRDY_PORT <= '1';
AD_Port <= (others => 'Z');
if (N_FRAME_IO = '0') then
nxtstate <= DISCON;
else
DEVSEL_PORT <= '1';
STOP_PORT <= '1';
nxtstate <= COMP2;
end if;
when DISCON =>
if (N_FRAME_IO = '0') then
nxtstate <= DISCON;
else
DEVSEL_PORT <= '1';
STOP_PORT <= '1';
nxtstate <= COMP2;
end if;
when COMP2 =>
TRDY_PORT <= 'Z';
DEVSEL_PORT <= 'Z';
STOP_PORT <= 'Z';
nxtstate <= IDLE;
when ERR =>
nxtstate <= ERR;
when others =>
nxtstate <= ERR;
end case;
end if;
end process;
N_DEVSEL_IO <= DEVSEL_PORT;
N_TRDY_IO <= TRDY_PORT;
N_STOP_IO <= STOP_PORT;
AD_IO <= AD_Port;
N_SERR_IO <= SERR_PORT;
N_PERR_IO <= PERR_PORT;
PAR_IO <= PAR_PORT;
N_INTA <= '1';
end Behavioral;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity SEGDISP is
Port (PCI_CLK : in STD_LOGIC;
RESET: in STD_LOGIC;
SEL : out STD_LOGIC_VECTOR(4 downto 0);
DAT : out STD_LOGIC_VECTOR(7 downto 0);
DIGIT0: in std_logic_vector (3 downto 0);
DIGIT1: in std_logic_vector (3 downto 0);
DIGIT2: in std_logic_vector (3 downto 0);
DIGIT3: in std_logic_vector (3 downto 0));
end SEGDISP;
architecture rtl of SEGDISP is
signal cnt : std_logic_vector(15 downto 0);
signal SEG_curdigit : std_logic_vector(1 downto 0);
signal SEG_segval : std_logic_vector(3 downto 0);
type digits_t is array (3 downto 0) of std_logic_vector (3 downto 0);
signal SEG_digits : digits_t;
signal SEG_SEL: std_logic_vector(3 downto 0);
signal SEG_DATA: std_logic_vector(6 downto 0);
begin
process(PCI_CLK, RESET)
begin
if (RESET = '0') then
cnt <= (others => '0');
SEG_curdigit <= "00";
elsif (PCI_CLK'event and PCI_CLK='1') then
SEG_digits(0) <= DIGIT0;
SEG_digits(1) <= DIGIT1;
SEG_digits(2) <= DIGIT2;
SEG_digits(3) <= DIGIT3;
cnt <= cnt + '1';
if (cnt = "0") then
SEG_curdigit <= SEG_curdigit + '1';
end if;
end if;
end process;
SEG_segval <= SEG_digits((CONV_INTEGER(SEG_curdigit(1 downto 0))));
with SEG_curdigit select
SEG_SEL <=
"0001" when "00",
"0010" when "01",
"0100" when "10",
"1000" when "11",
"1111" when others;
with SEG_segval select
SEG_DATA <=
"1111110" when "0000",
"0110000" when "0001",
"1101101" when "0010",
"1111001" when "0011",
"0110011" when "0100",
"1011011" when "0101",
"1011111" when "0110",
"1110000" when "0111",
"1111111" when "1000",
"1111011" when "1001",
"1110111" when "1010",
"0011111" when "1011",
"1001110" when "1100",
"0111101" when "1101",
"1001111" when "1110",
"1000111" when "1111",
"0110111" when others;
SEL <= '0' & SEG_SEL;
DAT <= not ('0' & SEG_DATA);
end rtl;
0 件のコメント:
コメントを投稿