FPGA总线实现形式
文章目录
- 用选择器实现总线
- 用三态门实现总线
用选择器实现总线
用选择器的思想来实现总线:总线从宏观上看是“多写多读”的,但是从微观上来看是“一写多读”,因为系统中的各个部件只能分时使用总线,而无法同时使用。也就是在某一固定时刻,总线是“一写多读”的,只不过通过一写控制电路,我们貌似可以在不同时刻为总线分配不同的驱动源,以达到宏观上的“多写多读”。
下面用FPGA来简单地实现总线:
利用多路选择器的选通特性,可以实现总线的功能,这也是FPGA芯片内部设计总线时最常用的方法,因为FPGA芯片内部有些非常丰富的MUX资源。
原理就是通过MUX的选通特性,通过改变选通信号的值来改变写入总线数据的来源。
module Bus(input request0,input request1,input request2,input request3,input [7:0] device0Out,input [7:0] device1Out,input [7:0] device2Out,input [7:0] device3Out,output [7:0] device0In,output [7:0] device1In,output [7:0] device2In,output [7:0] device3In);reg [1:0] sel;reg [7:0] bus;//generate selalways@(request0,request1,request2,request3)begin//Priority decodercase({request0,request1,request2,request3})4'b0001: sel = 2'b11;4'b0010 - 4'b0011: sel = 2'b10;4'b0100 - 4'b0111: sel = 2'b01;default: sel = 2'b00;endcaseend//write busalways@(sel,device0Out,device1Out,device2Out,device3Out)begincase(sel)2'b00: bus = device0Out;2'b01: bus = device1Out;2'b10: bus = device2Out;2'b11: bus = device3Out;default: bus = device0Out;endcaseend//read busassign device0In = bus;assign device1In = bus;assign device2In = bus;assign device3In = bus;
endmodule
使用liberoSoc综合之后的Technology Schematic map如下:
MicroSemi芯片内部通过大量选择器实现该总线。
用三态门实现总线
三态门(Three-state gate)是一种重要的总线接口电路。
三态指其输出既可以是一般二值逻辑电路,即正常的高电平(逻辑1)或低电平(逻辑0),又可以保持特有的高阻抗状态。高阻态相当于隔断状态(电阻很大,相当于开路)。
高阻态是一个数字电路里常见的术语,指的是电路的一种输出状态,既不是高电平也不是低电平,如果高阻态再输入下一级电路的话,对下级电路无任何影响,和没接一样,如果用万用表测的话有可能是高电平也有可能是低电平,随它后面接的东西定。
处于高阻抗状态时,输出电阻很大,相当于开路,没有任何逻辑控制功能。高阻态的意义在于实际电路中不可能断开电路。三态电路的输出逻辑状态的控制,是通过一个输入引脚实现的。
三态门都有一个EN控制使能端,来控制门电路的通断。 可以具备这三种状态的器件就叫做三态器件。当EN有效时,三态电路呈现正常的“0”或“1”的输出;当EN无效时,三态电路给出高阻态输出。
三态门的高阻特性,实际上就是为这里利用这个特性做准备的。
两种总线(选择器实现和三态门实现)的实现方式类似,也就是二者的硬件描述都是分为三个部分:
1、选择器控制信号产生部分,采用抢占式优先级译码器(【 FPGA 】抢占式优先级译码器电路)的思路,根据四个外围器件的请求信号产生多路选择器的选择控制信号。
2、写总线部分,即将四个三态门的输出连接到总线上。
3、读总线部分,各个外围器件根据自己的情况将总线数据读入器件内部进行运算和处理。
下面讲讲三态门的东西:
利用三态门的高阻特性,可以实现总线的功能。由于三态门资源大多存在于FPGA芯片的接口资源中而非FPGA内部,因此一般当总线位于FPGA芯片外部时,常采用这种方式。
再讲讲代码中的赋值冲突问题:
下面的代码是错误的,存在赋值冲突:
assign c = (sel[0] == 1'b1) ? a:1'b0;
assign c = (sel[1] == 1'b1) ? b:1'b1;
这个例子代码,两条赋值语句肯定都是一直有效的,因此必然产生赋值冲突,从而导致出错。下面的代码就是对的:
assign c = (sel[0] == 1'b1) ? a:1'bz;
assign c = (sel[1] == 1'b1) ? b:1'bz;
这个代码的写法和上面的唯一区别就是高组态的使用,为什么使用了高阻态,代码就是正确的了呢?
这是因为高阻态实际上就是电路中的断路,通过合理切换到高阻态,可以让上述有高阻态的例子中的两条赋值语句不会在同一时刻生效,因此不会产生赋值冲突。
下面给出三态门实现总线的代码:
module Bus_Three(input request0,input request1,input request2,input request3,input [7:0] device0Out,input [7:0] device1Out,input [7:0] device2Out,input [7:0] device3Out,output [7:0] device0In,output [7:0] device1In,output [7:0] device2In,output [7:0] device3In);reg [3:0] en;wire [7:0] bus;//generate selalways@(request0,request1,request2,request3)begincase({request0,request1,request2,request3})4'b0000: en = 4'b0000;4'b0001: en = 4'b1000; // the most high bit of en is available when request3 is high4'b0010-4'b0011: en = 4'b0100; // the second bit of en is available when request2 is high 4'b0100-4'b0111: en = 4'b0010; // the first bit of en is available when request1 is high default: en = 4'b0001; // the zero bit of en is available when request0 is high endcaseend//write busassign bus = (en[0] == 1'b1) ? device0Out:8'hzz;assign bus = (en[1] == 1'b1) ? device1Out:8'hzz;assign bus = (en[2] == 1'b1) ? device2Out:8'hzz;assign bus = (en[3] == 1'b1) ? device3Out:8'hzz;//read bus assign device0In = bus;assign device1In = bus;assign device2In = bus;assign device3In = bus;
endmodule
综合后的视图和选择器实现的总线视图基本一样:
————————————————
版权声明:本文为CSDN博主「李锐博恩」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Reborn_Lee/article/details/83753290
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
