上篇博文讲了三态门:https://blog.csdn.net/Reborn_Lee/article/details/83753290
姊妹篇:【 FPGA 】总线实现形式之选择器
三态门的高阻特性,实际上就是为这里利用这个特性做准备的。
两种总线的实现方式类似,也就是二者的硬件描述都是分为三个部分:
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;
这个代码的写法和上面的唯一区别就是高组态的使用,为什么使用了高阻态,代码就是正确的了呢?
这是因为高阻态实际上就是电路中的断路,通过合理切换到高阻态,可以让上述有高阻态的例子中的两条赋值语句不会在同一时刻生效,因此不会产生赋值冲突。
下面直接给出一个简单的三态门式总线的FPGA实现方式。功能代码分为三个部分,上面也已经说了:
1、选择器控制信号产生部分,采用抢占式优先级译码器(【 FPGA 】抢占式优先级译码器电路)的思路,根据四个外围器件的请求信号产生多路选择器的选择控制信号。
2、写总线部分,即将四个三态门的输出连接到总线上。
3、读总线部分,各个外围器件根据自己的情况将总线数据读入器件内部进行运算和处理。
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 20:05:53 11/05/2018
// Design Name:
// Module Name: Bus_Three
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
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 sel
always@(request0,request1,request2,request3)
begin
case({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 high
4'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
endcase
end
//write bus
assign 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
RTL Schematic:
Technology Schematic:
随便给出局部图,因为总图太大,放不下,缩小了又看不清楚:
废话不必多说,Technology Schematic给出了FPGA内部是如何实现这个电路的,不用想,是查找表和一些输入输出缓冲器。