基于CPLD的单片机PCI接口设计
时间:09-14
来源:互联网
点击:
2 PCI设计接口实现
2.1 CPLD ABEL HDL程序设计
我们针对8位单片机控制PCI以太网卡进行了程序设计,CPLD器件选用ALTERA的MAX7000系列。针对以太网卡的特点在逻辑上进行了再次简化,最张程序将适配进EPM7128芯片中,并在实践中检验通过。
以太网卡仅支持对配置空间和I/O空间的读写操作,而且这两个空间的地址都可以设置在0xFF以内,所以可以只用一个pci_address0寄存器,其它地址都直接设为“0”;如果再限制,每次只往网卡写入一个字节数据,则可以只用一个pci_datas0寄存器,其它数值在具体操作时设成与pci_datas0寄存器的一样即可。
以下是ABEL HDL主要源码。其中16dmux是4~16位译码器,用于地址译码,选通CPLD内的寄存器;8dffe是8位的DFFE;abelcounter是8位移位计数器;mylatch8与mylatch1分别为8位与1位锁存器,而mylatchc是带清零1位锁存器;其它以“my”开始的变量都是三态缓冲器,以“out”开始的变量是三态节点,以“e”开始的变量是普通节点。这此在程序中不再声明。
SUBDESIGN abelpci
(
P2[7..3] : INPUT;
READ0 : INPUT
WRITE0 : INPUT;
P0[7..0] : BIDIR;
CLK : INPUT;
TRDY0 : INPUT;
AD[31..] : BIDIR;
CBE[3..0] : BIDIR;
IRDY0 : OUTPUT;
FRAME0 : OUTPUT;
)
VARIABLE
decoder : 16dmux;
mycounter : abelcounter;
pci_c
be : 8DFFE;
PCI_address0 : 8DFFE;
pci_datas0 : 8DFFE;
pci_request[6..0] : mylatch1;
pci_request7 : mylatchc;
pci_data0 : mylatch8;
pci_data1 : mylatch8;
pci_data2 : mylatch8;
pci_data3 : mylatch8;
ss : MACHINE OF BITS (FRAME0,IRDY0)
WITH STATES(s0 = B"11",
s1=B"01");
s2=B"10";
S3=B"11");
BEGIN
decoder.(d,c,b,a)=P2[6..3];
enareg[]=decoder.q[];
pci_che.ena=enareg[0]&p2;
pci_cbe.d[]=p0[];
pci_cbe.clk=!WRITE0;
pci_address0.ena=enareg&p2l
pci_address0.d[]=P0[];
pci_datas0.ena=enareg&P2;
pci_datas0.d[]=P0[];
pci_datas0.clk=!WRITE0;
pci_data0.gate=!TRDY0;
pci_data0.data[]=AD[7..0];
pci_data1.gate=!TRDY0;
pci_data1.data[]=AD[15..8];
pci_data2.gate=!TRDY0;
pci_data2.data[]=AD[23..16];
pci_data3.gate=!TRDY0;
pci_data3.data[]=AD[31..24];
pci_request[3..0].gate=!TRDY0;
pci_request7.gate=!TRDY0;
pci_request7.aclr=P2&!WRITE0;
pci_request[3..0].data=CBE[];
pci_request.data=IRDY0;
pci_request.data=FRAME0;
pci_request.data=Vcc;
pci_request7.data=Vcc;
eread=P2&!READ0 & WRITE0;
my_P0_data0[].in=pci_data0.q[];
my_P0_data0[].oe=enareg&eread;
my_P0_data1[].in=pci_data1.q[];
my_P0_data1[].oe=enareg&eread;
my_P0_data2[].in=pci_data2.q[];
my_P0_data2[].oe=enareg&eread;
my_P0_data3[].in=pci_data3.q[];
my_P0_data3[].oe=enareg&eread;
my_P0_request[6..0].in=pci_request[6..0].q;
my_P0_request.in=pci_request7.q;
my_P0_request[].oe=enareg[13]&eread;
out_P0[]=my_P0_data0[];
out_P0[]=my_P0_data1[];
out_P0[]=my_P0_data2[];
out_P0[]=my_P0_data3[];
out_P0[]=my_P0_request[];
P0[]=out_P0[];
enclr=enareg[0]&P2&!WRITE0;
mycounter.clock=CLK;
mycounter.cnt_en=!IRDY0;
mycounter.aclr=!FRAME0;
mycounter.sset=!TRDY0;
ss.clk=!CLK;
ss.reset=enclr;
ss.ena=Vcc;
CASE ss IS
WHEN s0 => ss="s1";
WHEN s1 => ss="s2";
WHEN s2 => IF mycounter.cout THEN ss =s3;ELSE ss="s2";
END IF;
WHENf s3 => ss="s3";
END CASE;
my_AD_address[7..0].in=in=pci_
address0;
my_AD_address[31..8].in=GND;
my_AD_address[31..0].oe=!FRAME0;
my_CBE_c[].in=PCI_cbe.d[3..0];
my_CBE_c[].oe=!FRAME0;
my_AD_data[31..0].in=pci_datas0.q[8..1];
my_AD_data[31..0].oe=pci_cbe_[0]&FRAME0;
my_CBE_be[].in=pci_cbe.d[7..4];
my_CBE_be[].oe=FRAME0;
out_AD[]=my_AD_address[];
out_AD[]=my_AD_data[];
AD[]=out_AD[];
out_CBE[]=my_CBE_c[];
out_CBE[]=my_CBE_be[];
CBE[]=out_CBE[];
END;
2.1 CPLD ABEL HDL程序设计
我们针对8位单片机控制PCI以太网卡进行了程序设计,CPLD器件选用ALTERA的MAX7000系列。针对以太网卡的特点在逻辑上进行了再次简化,最张程序将适配进EPM7128芯片中,并在实践中检验通过。
以太网卡仅支持对配置空间和I/O空间的读写操作,而且这两个空间的地址都可以设置在0xFF以内,所以可以只用一个pci_address0寄存器,其它地址都直接设为“0”;如果再限制,每次只往网卡写入一个字节数据,则可以只用一个pci_datas0寄存器,其它数值在具体操作时设成与pci_datas0寄存器的一样即可。
以下是ABEL HDL主要源码。其中16dmux是4~16位译码器,用于地址译码,选通CPLD内的寄存器;8dffe是8位的DFFE;abelcounter是8位移位计数器;mylatch8与mylatch1分别为8位与1位锁存器,而mylatchc是带清零1位锁存器;其它以“my”开始的变量都是三态缓冲器,以“out”开始的变量是三态节点,以“e”开始的变量是普通节点。这此在程序中不再声明。
SUBDESIGN abelpci
(
P2[7..3] : INPUT;
READ0 : INPUT
WRITE0 : INPUT;
P0[7..0] : BIDIR;
CLK : INPUT;
TRDY0 : INPUT;
AD[31..] : BIDIR;
CBE[3..0] : BIDIR;
IRDY0 : OUTPUT;
FRAME0 : OUTPUT;
)
VARIABLE
decoder : 16dmux;
mycounter : abelcounter;
pci_c
be : 8DFFE;
PCI_address0 : 8DFFE;
pci_datas0 : 8DFFE;
pci_request[6..0] : mylatch1;
pci_request7 : mylatchc;
pci_data0 : mylatch8;
pci_data1 : mylatch8;
pci_data2 : mylatch8;
pci_data3 : mylatch8;
ss : MACHINE OF BITS (FRAME0,IRDY0)
WITH STATES(s0 = B"11",
s1=B"01");
s2=B"10";
S3=B"11");
BEGIN
decoder.(d,c,b,a)=P2[6..3];
enareg[]=decoder.q[];
pci_che.ena=enareg[0]&p2;
pci_cbe.d[]=p0[];
pci_cbe.clk=!WRITE0;
pci_address0.ena=enareg&p2l
pci_address0.d[]=P0[];
pci_datas0.ena=enareg&P2;
pci_datas0.d[]=P0[];
pci_datas0.clk=!WRITE0;
pci_data0.gate=!TRDY0;
pci_data0.data[]=AD[7..0];
pci_data1.gate=!TRDY0;
pci_data1.data[]=AD[15..8];
pci_data2.gate=!TRDY0;
pci_data2.data[]=AD[23..16];
pci_data3.gate=!TRDY0;
pci_data3.data[]=AD[31..24];
pci_request[3..0].gate=!TRDY0;
pci_request7.gate=!TRDY0;
pci_request7.aclr=P2&!WRITE0;
pci_request[3..0].data=CBE[];
pci_request.data=IRDY0;
pci_request.data=FRAME0;
pci_request.data=Vcc;
pci_request7.data=Vcc;
eread=P2&!READ0 & WRITE0;
my_P0_data0[].in=pci_data0.q[];
my_P0_data0[].oe=enareg&eread;
my_P0_data1[].in=pci_data1.q[];
my_P0_data1[].oe=enareg&eread;
my_P0_data2[].in=pci_data2.q[];
my_P0_data2[].oe=enareg&eread;
my_P0_data3[].in=pci_data3.q[];
my_P0_data3[].oe=enareg&eread;
my_P0_request[6..0].in=pci_request[6..0].q;
my_P0_request.in=pci_request7.q;
my_P0_request[].oe=enareg[13]&eread;
out_P0[]=my_P0_data0[];
out_P0[]=my_P0_data1[];
out_P0[]=my_P0_data2[];
out_P0[]=my_P0_data3[];
out_P0[]=my_P0_request[];
P0[]=out_P0[];
enclr=enareg[0]&P2&!WRITE0;
mycounter.clock=CLK;
mycounter.cnt_en=!IRDY0;
mycounter.aclr=!FRAME0;
mycounter.sset=!TRDY0;
ss.clk=!CLK;
ss.reset=enclr;
ss.ena=Vcc;
CASE ss IS
WHEN s0 => ss="s1";
WHEN s1 => ss="s2";
WHEN s2 => IF mycounter.cout THEN ss =s3;ELSE ss="s2";
END IF;
WHENf s3 => ss="s3";
END CASE;
my_AD_address[7..0].in=in=pci_
address0;
my_AD_address[31..8].in=GND;
my_AD_address[31..0].oe=!FRAME0;
my_CBE_c[].in=PCI_cbe.d[3..0];
my_CBE_c[].oe=!FRAME0;
my_AD_data[31..0].in=pci_datas0.q[8..1];
my_AD_data[31..0].oe=pci_cbe_[0]&FRAME0;
my_CBE_be[].in=pci_cbe.d[7..4];
my_CBE_be[].oe=FRAME0;
out_AD[]=my_AD_address[];
out_AD[]=my_AD_data[];
AD[]=out_AD[];
out_CBE[]=my_CBE_c[];
out_CBE[]=my_CBE_be[];
CBE[]=out_CBE[];
END;
- 采用EEPROM对大容量FPGA芯片数据实现串行加载(03-18)
- 周立功:如何兼顾学习ARM与FPGA(05-23)
- 初学者如何学习FPGA(08-06)
- 为何、如何学习FPGA(05-23)
- FPGA作为协处理器在实时系统中的应用(04-08)
- 我的FPGA学习历程(05-23)