阅读:12188回复:45
想用CPLD/FPGA做PCI接口? follow me
从今天起,偶们共同来探讨如何用CPLD/FPGA来实现PCI接口,内容由浅入深,实现的PCI功能由简到繁,从简单slave接口到master的总线仲裁。望大家积极参与和验证。
申明一下,偶本人之前并没有做过用逻辑来实现PCI接口的东西,只是用AMCC5933、PLX9054之类的东西做过几个项目。倘若在设计过程中有不妥的地方,望高手指正和补充。另外,如果有人正在从事此类开发,希望将验证结果及时反馈,以shi大众。 好乐,偶们从零开始,先来学一下状态机吧。 |
|
|
沙发#
发布于:2004-12-27 20:07
从根本上说,状态机是一种设计方法,最终都要用组合和时序逻辑来表现。在大学里我们学状态机时,我们根据题目需求,设立寄存器组,列出其状态转换各种限制和推动条件,然后化简,得到逻辑关系式,再用寄存器和门电路来实现,就得到了题目的应用解答。
现在,有了CPLD/FPGA芯片的成熟应用,软件会帮助我们去完成逻辑的综合和化简,我们只需用VHDL语言直接定义和描述状态机的转换条件及输入输出关系就可以了。爽呼。 好乐,下面偶们先来学习一个状态机的例子。 |
|
|
板凳#
发布于: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; |
|
|
地板#
发布于:2004-12-27 20:25
可恶,为什么代码前面的空格都没了,叫偶的代码如此难看。偶们晚班车要走了,明天继续讨论。
|
|
|
地下室#
发布于:2004-12-27 22:38
支持斑竹的义举!什么时候介绍PCI总线的状态机?
|
|
5楼#
发布于:2004-12-28 09:38
呵呵,我加入,谢谢斑竹
|
|
|
6楼#
发布于:2004-12-28 15:55
前几天 我也发了同样的帖子 你的回复率就是高 斑竹是不同啊
我正打算用6000系列来完成这一任务 不知道 如何进展 你那里如何 如果只是理论也是满好的 |
|
|
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的状态机。 |
|
|
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代码。 |
|
|
9楼#
发布于:2004-12-29 20:25
抱歉,把KEEP状态的转换拉掉了。
4.5 KEEP状态下,如果FRAME#、IRDY#都有效,回到TRANS状态;如果FRAME#、IRDY#都无效,总线异常,结束操作回到IDLE,如果FRAME#无效而IRDY#有效,进入OPEND状态;其余保持KEEP状态。 |
|
|
10楼#
发布于:2004-12-30 16:08
看过。。。。。。。。。
|
|
|
11楼#
发布于:2004-12-30 16:35
看过, 是什么意思?
以前看过?还是刚看过? 偶很敏感的噢~~~~~ |
|
|
12楼#
发布于:2004-12-31 08:18
刚看过 我是说 继续。。。。。。。
|
|
|
13楼#
发布于:2004-12-31 08:31
义无反顾底支持一下!斑竹继续!在理论之后,希望能多谈点实践问题!
嘿嘿,如果写的好的话,俺帮你做.chm文件! 先说说你用那种开发工具啊,俺先装上的说! [编辑 - 12/31/04 by lsn_061] :D [编辑 - 12/31/04 by lsn_061] |
|
|
14楼#
发布于:2004-12-31 09:00
等待中...............................
|
|
|
15楼#
发布于:2004-12-31 09:31
偶需要花些时间来写状态机的转换代码,另外要详细考虑各状态下的动作,还要经过初步验证(在QUARTUS II上),――而我还要给公司干活,所以请各位等两天吧。其实状态机的转换关系已经列出来了,大家可以一起来写这个状态机提交大家审查,这样也有利于对设计的深入掌握。大家写状态机的时候心里一定要想SLAVE设备在这个状态下应该做什么。 写错了没关系,大家一起来纠正。
|
|
|
16楼#
发布于:2005-01-04 16:00
最近忙的很 没来?
|
|
|
17楼#
发布于:2005-01-04 20:07
你好,别听我老弟lucaer在这里瞎诈唬啊!
我仔细的看了您写得文章,真是太好了,我看了这么多帖子和pdf也没搞明白怎么会事,现在很是明白了,不过我还有个小小的提议,能不能开个专门的至顶帖子,这样便于讨论,也不至于打断您的思路,不过到最后如能在软件上面仿真或者您能提供开发板就好了,不过我好像很懒,主要俺还有个工程,郁闷!能不能带兄弟们在您理论的基础上分析一下源代码,那俺就感激不尽了!最好您能提供开发板啊!提个建议,从opencore的winshond结构开始行么?或者老大有什么主意? |
|
|
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; |
|
|
19楼#
发布于:2005-01-05 19:00
求助:
以前写比较复杂一点的逻辑,在QUARTUS II里,都是在顶层用框图(BLOCK diagram)来描述各个模块的关系,然后对各个模块用VHDL或A-HDL语言来实施。但受BBS的限制,目前只能全部用VHDL来写。偶的问题是如何用VHDL来做层次化的设计? 比如,上面代码里的DEVSEL应当是另一个模块对AD[31..0]的译码输出,在VHDL里应当如何来关联他们的关系? 偶手头没书,各位能不能赐教一下? |
|
|
上一页
下一页