lllggg
驱动小牛
驱动小牛
  • 注册日期2002-05-04
  • 最后登录2007-01-07
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:12188回复:45

想用CPLD/FPGA做PCI接口? follow me

楼主#
更多 发布于:2004-12-27 20:04
    从今天起,偶们共同来探讨如何用CPLD/FPGA来实现PCI接口,内容由浅入深,实现的PCI功能由简到繁,从简单slave接口到master的总线仲裁。望大家积极参与和验证。
    申明一下,偶本人之前并没有做过用逻辑来实现PCI接口的东西,只是用AMCC5933、PLX9054之类的东西做过几个项目。倘若在设计过程中有不妥的地方,望高手指正和补充。另外,如果有人正在从事此类开发,希望将验证结果及时反馈,以shi大众。
   好乐,偶们从零开始,先来学一下状态机吧。
(DEEP + BROAD + SIMPLE) & delicate
lllggg
驱动小牛
驱动小牛
  • 注册日期2002-05-04
  • 最后登录2007-01-07
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2004-12-27 20:07
    从根本上说,状态机是一种设计方法,最终都要用组合和时序逻辑来表现。在大学里我们学状态机时,我们根据题目需求,设立寄存器组,列出其状态转换各种限制和推动条件,然后化简,得到逻辑关系式,再用寄存器和门电路来实现,就得到了题目的应用解答。
   现在,有了CPLD/FPGA芯片的成熟应用,软件会帮助我们去完成逻辑的综合和化简,我们只需用VHDL语言直接定义和描述状态机的转换条件及输入输出关系就可以了。爽呼。
  好乐,下面偶们先来学习一个状态机的例子。
(DEEP + BROAD + SIMPLE) & delicate
lllggg
驱动小牛
驱动小牛
  • 注册日期2002-05-04
  • 最后登录2007-01-07
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2004-12-27 20:21
     在这个例子里,偶们的需求有两个状态,一个复位输入,一个条件输入,一个输出,以及一个推动状态转换的时钟。要求:在复位信号有效时,无条件进入状态0;在时钟推动下,如果状态为0,则进入状态1,如果状态为1,则根据输入情况来决定下一个状态:如果输入为1进入状态0,如果输入为0则保持状态1。
     可能你们大失所望:靠,用一个寄存器和几个门连一下线就行了,搞什么状态机啊? 说的是,可是如果象PCI总线一样有它N个状态,你还准备去连线么,那你今年就准备在办公室过年吧,呵呵。

library IEEE;
use IEEE.std_logic_1164.all;

ENTITY state_machine IS
PORT(
clk:IN STD_LOGIC;
input:IN STD_LOGIC;
reset:IN STD_LOGIC;
output:OUT STD_LOGIC
     );
END state_machine;

ARCHITECTURE examp OF state_machine IS
TYPE STATE_TYPE IS(st0,st1);
SIGNAL state:STATE_TYPE;

   BEGIN
      PROCESS(clk)
      BEGIN
       if (reset = '1') then
     state <= st0;
     else if (clk'EVENT AND clk = '1') then  
     CASE state IS
         WHEN st0=>
           state <= st1;
         WHEN st1=>
            if (input = '1') then
               state <= st0;
            else
               state <= st1;--千万别漏了这句噢
            end if;
       end CASE;
     end if;
END if;
   END PROCESS;
  
   output <= '1' WHEN state = st1 ELSE '0';
 END examp;
(DEEP + BROAD + SIMPLE) & delicate
lllggg
驱动小牛
驱动小牛
  • 注册日期2002-05-04
  • 最后登录2007-01-07
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地板#
发布于:2004-12-27 20:25
可恶,为什么代码前面的空格都没了,叫偶的代码如此难看。偶们晚班车要走了,明天继续讨论。
(DEEP + BROAD + SIMPLE) & delicate
cover_me
驱动牛犊
驱动牛犊
  • 注册日期2004-04-25
  • 最后登录2006-04-29
  • 粉丝0
  • 关注0
  • 积分58分
  • 威望9点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2004-12-27 22:38
支持斑竹的义举!什么时候介绍PCI总线的状态机?
hongshanger
驱动小牛
驱动小牛
  • 注册日期2004-07-19
  • 最后登录2006-04-06
  • 粉丝0
  • 关注0
  • 积分20分
  • 威望3点
  • 贡献值0点
  • 好评度6点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2004-12-28 09:38
呵呵,我加入,谢谢斑竹
新手上路,各位大侠莫不理睬
lucaer
驱动老牛
驱动老牛
  • 注册日期2004-09-21
  • 最后登录2007-09-26
  • 粉丝0
  • 关注0
  • 积分518分
  • 威望60点
  • 贡献值0点
  • 好评度48点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2004-12-28 15:55
前几天 我也发了同样的帖子 你的回复率就是高 斑竹是不同啊

我正打算用6000系列来完成这一任务 不知道 如何进展 你那里如何

如果只是理论也是满好的
只要回帖,别忘给分。 支持灌水,多多送分。 [img]http://www.hotik.com/sign.png[/img]
lllggg
驱动小牛
驱动小牛
  • 注册日期2002-05-04
  • 最后登录2007-01-07
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2004-12-28 17:50
偶们先探讨PCI SLAVE的实现。为此先讨论一下PCI信号的分析和处理,然后探讨PCI SLAVE DECVICES的状态机。之后再探讨芯片选型问题。

下面大致介绍一下PCI的信号,大家不要嫌偶烦,把它们真正弄清楚不是那么简单的。记住下面的输入输出是针对SLAVE 设备的。

CLK:输入信号, PCI总线的系统时钟,频率范围为33MHZ火66MHZ 。PCI:输入 总线是同步总线,除信号RST# INTA# INTB# INTC# INTD#外所有信号都应当在系统时钟上升沿处被采样,记住噢。
RST:输入信号,PCI总线复位信号,所有寄存器都必须在RST有效时复位至明确的状态。另:RST有效时,系统中所有输出信号一般都须驱动到三态――就是用RST来把信号关了。
AD[31 00]:复用的双向数据/地址信号 好象没什么可说的。
C/BE[3 0]#: 输入信号 总线操作命令和字节使能,由主设备驱动,在地址期间指示当前的总线操作类型,共可指示16种总线操作类型,实际只用了12种;而在数据期间则指示AD[31 00]中哪些字节是有效的,C/BE[3]和C/BE[0]分别是最高字节使能位和最低字节使能位低电平有效

PAR: 输入 较验位,由主设备驱动。它在有效地址期或数据期的后一时钟周期出现,持续一个时钟周期。传输无错时AD[31::00] C/BE[3 0]# 和PAR中1 的个数必为偶数。为了进行奇偶校验每次数据期或地址期间AD[31 00]上无效的字节都被主设备驱动到稳定电平例(如0 电平)。图简单的话,这个信号偶们可以不用。

FRAME# 输入信号 帧周期信号,由Master驱动。具体规则偶不罗嗦乐。但要注意,当它变为高电平无效时,相应的时钟周期为该次总线传输的最后时钟周期,这时IRDY#是有效的。这是一种结束本次传输操作的既定规则,不要认为FRAME#无效了就不传数据了,那样你会丢一个数据(突发)或根本收布道数据(单个)。只有当FRAME#和IRDY#都无效时才表示总线操作结束。

IRDY# 输入 Master准备好信号,由Master驱动

TRDY# 输出 Target准备好信号,由Target(SLAVE DEVICE)驱动

STOP# 输出 Target要求终止当前传输的信号,由Target驱动。你忙不过来就终止吧,一般也用不上。

LOCK# 输入信号 资源锁定信号该信号,有关资源互斥访问,不用理它

IDSEL: 输入 PCI总线外设初始化选择信号,若某个总线访问的地址期中AD[1:0]=00且此时IDSEL有效,则意味着当前的总线访问是该外设的配置读或写周期。IDSEL是由主设备发出的。理解了IDSEL和DEVSEL,PCI总线协议的实际过程就知一大半了。――看清楚,它是高电平有效噢。

DEVSEL# 输出 PCI外设选择信号,每次总线访问的地址期后,如果当前访问的地址落在某个PCI外设的内存或I/O的映射空间(映射是配置完成的),则在第一或第二或第三个时钟周期期间,该外设就要将DEVSEL#驱动到有效状态表示这次访问是针对它的由它来参与完成。

PERR# 输出 数据奇偶校验错信号,由从设备输出,你要是不想做校验,就输出高电平。
SERR# 输出(OD开路输出) 系统错误报告信号,重大错误报告,懒得管它。

INTA# INTB# INTC# INTD# 输出 电平敏感的PCI 外设中断请求信号,可选。用得话一般只用INTA#。

有点累了,也不知说错了没有。

下面来讨论PCI SLAVE的状态机。
(DEEP + BROAD + SIMPLE) & delicate
lllggg
驱动小牛
驱动小牛
  • 注册日期2002-05-04
  • 最后登录2007-01-07
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2004-12-29 20:16
PCI TARGET 的状态机可以有多种定义方式,取决于设计者对PCI时序的理解角度、设备实现的功能以及器件的速度。假设我们设计的SLAVE PCI设备需要在LOCAL端实现1M字节的MEM空间和256字节的IO空间的接口,而且所带的存储芯片速度足够快(15ns左右的器件就可以了),我们可以定义如下几个状态:
IDLE:空闲状态。
READY:准备状态。
TRANS:数据传输状态。
KEEP:总线保持状态。该状态下,主设备没有放弃数据传输(FRAME#仍有效),但IRDY#无效,这时数据是不能要的噢。这个状态容易被人忽视,――虽然这个状态很少出现。
OPEND:操作结束状态。传最后一个数据(有可能也是第一个――单个数据传输周期)

状态转换关系描述(CLK推动下):
1、PCI复位或单板上电后无条件进入IDEL该状态
2、IDLE状态下FRAME#有效并且IRDY#无效,进入READY状态,否则仍留在IDEL状态
3、READY状态下,如果DEVSEL#(它同时是输出信号)、IRDY#和FRAME#都有效,进入TRANS状态;如果DEVSEL#、IRDY#有效但FRAME#无效,则是单个数据传输,直接进入OPEND状态;如果DEVSEL#无效,返回IDLE状态(说明不是对本设备操作);其余留在READY状态(等IRDY#)。
4、TRANS状态下,如果FRAME#有效而IRDY#无效,进入KEEP状态;如果FRAME#无效而IRDY#有效,进入OPEND状态,准备传输最后一个数据;都有效保持在TRANS状态;都无效,表明操作异常结束,回到IDLE。
5、OPEND状态下,如果IRDY#无效,回到IDLE。如果IRDY#还有效,说明总线异常,终止传输。

该状态机的转换除了与PCI输入信号有关,还与DEVSEL#有关,这个信号是判断本次访问是否针对本设备的结果(包括配置空间访问),如果是读操作,该信号需延迟一个周期以实现插入一个环回。

可惜偶上传不了文件,不然弄个转换图给同志们讨论。

上面只是根据要求设置了状态机,要实现这个接口光有状态机远远不够的。不过这是接口设计的基础,偶们先把它做好吧。下面来写这个状态机的VHDL代码。
(DEEP + BROAD + SIMPLE) & delicate
lllggg
驱动小牛
驱动小牛
  • 注册日期2002-05-04
  • 最后登录2007-01-07
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2004-12-29 20:25
抱歉,把KEEP状态的转换拉掉了。

4.5  KEEP状态下,如果FRAME#、IRDY#都有效,回到TRANS状态;如果FRAME#、IRDY#都无效,总线异常,结束操作回到IDLE,如果FRAME#无效而IRDY#有效,进入OPEND状态;其余保持KEEP状态。

(DEEP + BROAD + SIMPLE) & delicate
lucaer
驱动老牛
驱动老牛
  • 注册日期2004-09-21
  • 最后登录2007-09-26
  • 粉丝0
  • 关注0
  • 积分518分
  • 威望60点
  • 贡献值0点
  • 好评度48点
  • 原创分0分
  • 专家分0分
10楼#
发布于:2004-12-30 16:08
看过。。。。。。。。。
只要回帖,别忘给分。 支持灌水,多多送分。 [img]http://www.hotik.com/sign.png[/img]
lllggg
驱动小牛
驱动小牛
  • 注册日期2002-05-04
  • 最后登录2007-01-07
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
11楼#
发布于:2004-12-30 16:35
看过,  是什么意思?
以前看过?还是刚看过?  偶很敏感的噢~~~~~
(DEEP + BROAD + SIMPLE) & delicate
lucaer
驱动老牛
驱动老牛
  • 注册日期2004-09-21
  • 最后登录2007-09-26
  • 粉丝0
  • 关注0
  • 积分518分
  • 威望60点
  • 贡献值0点
  • 好评度48点
  • 原创分0分
  • 专家分0分
12楼#
发布于:2004-12-31 08:18
刚看过 我是说 继续。。。。。。。
只要回帖,别忘给分。 支持灌水,多多送分。 [img]http://www.hotik.com/sign.png[/img]
lsn_061
驱动老牛
驱动老牛
  • 注册日期2002-05-09
  • 最后登录2006-10-06
  • 粉丝0
  • 关注0
  • 积分1000分
  • 威望261点
  • 贡献值0点
  • 好评度169点
  • 原创分0分
  • 专家分0分
13楼#
发布于:2004-12-31 08:31
义无反顾底支持一下!斑竹继续!在理论之后,希望能多谈点实践问题!

嘿嘿,如果写的好的话,俺帮你做.chm文件!

先说说你用那种开发工具啊,俺先装上的说!

[编辑 -  12/31/04 by  lsn_061] :D

[编辑 -  12/31/04 by  lsn_061]
[img]http://bbs.zndev.com/image/medal/5.gif[/img]
lucaer
驱动老牛
驱动老牛
  • 注册日期2004-09-21
  • 最后登录2007-09-26
  • 粉丝0
  • 关注0
  • 积分518分
  • 威望60点
  • 贡献值0点
  • 好评度48点
  • 原创分0分
  • 专家分0分
14楼#
发布于:2004-12-31 09:00
等待中...............................
只要回帖,别忘给分。 支持灌水,多多送分。 [img]http://www.hotik.com/sign.png[/img]
lllggg
驱动小牛
驱动小牛
  • 注册日期2002-05-04
  • 最后登录2007-01-07
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
15楼#
发布于:2004-12-31 09:31
偶需要花些时间来写状态机的转换代码,另外要详细考虑各状态下的动作,还要经过初步验证(在QUARTUS II上),――而我还要给公司干活,所以请各位等两天吧。其实状态机的转换关系已经列出来了,大家可以一起来写这个状态机提交大家审查,这样也有利于对设计的深入掌握。大家写状态机的时候心里一定要想SLAVE设备在这个状态下应该做什么。 写错了没关系,大家一起来纠正。
(DEEP + BROAD + SIMPLE) & delicate
lucaer
驱动老牛
驱动老牛
  • 注册日期2004-09-21
  • 最后登录2007-09-26
  • 粉丝0
  • 关注0
  • 积分518分
  • 威望60点
  • 贡献值0点
  • 好评度48点
  • 原创分0分
  • 专家分0分
16楼#
发布于:2005-01-04 16:00
最近忙的很 没来?
只要回帖,别忘给分。 支持灌水,多多送分。 [img]http://www.hotik.com/sign.png[/img]
lsn_061
驱动老牛
驱动老牛
  • 注册日期2002-05-09
  • 最后登录2006-10-06
  • 粉丝0
  • 关注0
  • 积分1000分
  • 威望261点
  • 贡献值0点
  • 好评度169点
  • 原创分0分
  • 专家分0分
17楼#
发布于:2005-01-04 20:07
你好,别听我老弟lucaer在这里瞎诈唬啊!
我仔细的看了您写得文章,真是太好了,我看了这么多帖子和pdf也没搞明白怎么会事,现在很是明白了,不过我还有个小小的提议,能不能开个专门的至顶帖子,这样便于讨论,也不至于打断您的思路,不过到最后如能在软件上面仿真或者您能提供开发板就好了,不过我好像很懒,主要俺还有个工程,郁闷!能不能带兄弟们在您理论的基础上分析一下源代码,那俺就感激不尽了!最好您能提供开发板啊!提个建议,从opencore的winshond结构开始行么?或者老大有什么主意?
附件名称/大小 下载次数 最后更新
2005-01-04_PCICORE.zip (130KB)  74
[img]http://bbs.zndev.com/image/medal/5.gif[/img]
lllggg
驱动小牛
驱动小牛
  • 注册日期2002-05-04
  • 最后登录2007-01-07
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
18楼#
发布于:2005-01-04 20:28
先把今晚写的状态机提上来大家琢磨一下,项目的整体架构偶还要研究一下。这里头DEVSEL是对地址期的地址进行译码输出的信号,在这里作为状态机的输入。ERR是错误标志,如果为1需要往PCI上发STOP信号的。
具体讨论偶明天另提一个。

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;

ENTITY PCI_INTERFACE_SLAVE IS
PORT(

pwrrst:IN STD_LOGIC;
pciclk:IN STD_LOGIC;
pcirst:IN STD_LOGIC;
frame:IN STD_LOGIC;
irdy:IN STD_LOGIC;
devsel:IN STD_LOGIC;
err:OUT STD_LOGIC
     );
END PCI_INTERFACE_SLAVE;

ARCHITECTURE state OF PCI_INTERFACE_SLAVE  IS
TYPE STATE_TYPE IS(IDLE,READY,TRANS,KEEP,OPEND);
SIGNAL state:STATE_TYPE;

   BEGIN
      PROCESS(pciclk)
      BEGIN
       if ((pcirst = '1') or (pwrrst = '1'))then
     state <= IDLE;
     else if (pciclk'EVENT AND pciclk = '1') then  
     CASE state IS
         WHEN IDLE=>
if((frame = '0') and (irdy = '1'))then
           state <= READY;err <= '0';
else state <= IDLE;err <= '0';
end if;
         WHEN READY=>
            if (devsel = '0') then
if((frame = '0') and (irdy = '0')) then
state <= TRANS;err <= '0';
else if((frame = '1') and (irdy = '0')) then
state <= OPEND;err <= '0';
else
state <= READY;err <= '0';
end if;
end if;
 else
state <= IDLE;err <= '0';
 end if;
WHEN TRANS=>
    if((frame = '0') and (irdy = '1')) then
state <= KEEP;err <= '0';
else if((frame = '1') and (irdy = '0')) then
state <= OPEND;err <= '0';
else if((frame = '0') and (irdy = '0')) then
state <= TRANS;err <= '0';
else
state <= IDLE;err <= '1';
end if;
end if;
end if;
            WHEN KEEP=>  
if((frame = '0') and (irdy = '0')) then
state <= TRANS;err <= '0';
else if((frame = '0') and (irdy = '1')) then
state <= KEEP;err <= '0';
else if((frame = '1') and (irdy = '0')) then
state <= OPEND;err <= '0';
else
state <= IDLE;err <= '1';
end if;
end if;
  end if;
 WHEN OPEND=>
if(irdy = '1') then
state <= IDLE;err <= '0';
else
state <= IDLE;err <= '1';
end if;

       END CASE;
     end if;
end if;
   END PROCESS;
 

 END state;
(DEEP + BROAD + SIMPLE) & delicate
lllggg
驱动小牛
驱动小牛
  • 注册日期2002-05-04
  • 最后登录2007-01-07
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
19楼#
发布于:2005-01-05 19:00
求助:
以前写比较复杂一点的逻辑,在QUARTUS II里,都是在顶层用框图(BLOCK diagram)来描述各个模块的关系,然后对各个模块用VHDL或A-HDL语言来实施。但受BBS的限制,目前只能全部用VHDL来写。偶的问题是如何用VHDL来做层次化的设计? 比如,上面代码里的DEVSEL应当是另一个模块对AD[31..0]的译码输出,在VHDL里应当如何来关联他们的关系? 偶手头没书,各位能不能赐教一下?
(DEEP + BROAD + SIMPLE) & delicate
上一页
游客

返回顶部