【 FPGA 】总线实现形式之三态门

举报
李锐博恩 发表于 2021/07/15 04:47:02 2021/07/15
【摘要】 上篇博文讲了三态门:https://blog.csdn.net/Reborn_Lee/article/details/83753290 姊妹篇:【 FPGA 】总线实现形式之选择器 三态门的高阻特性,实际上就是为这里利用这个特性做准备的。 两种总线的实现方式类似,也就是二者的硬件描述都是分为三个部分: 1、选择器控制信号产生部分,采用抢占式优先级译码器(【 FPGA ...

上篇博文讲了三态门:https://blog.csdn.net/Reborn_Lee/article/details/83753290

姊妹篇:【 FPGA 】总线实现形式之选择器

三态门的高阻特性,实际上就是为这里利用这个特性做准备的。

两种总线的实现方式类似,也就是二者的硬件描述都是分为三个部分:

1、选择器控制信号产生部分,采用抢占式优先级译码器(【 FPGA 】抢占式优先级译码器电路)的思路,根据四个外围器件的请求信号产生多路选择器的选择控制信号。

2、写总线部分,即将四个三态门的输出连接到总线上。

3、读总线部分,各个外围器件根据自己的情况将总线数据读入器件内部进行运算和处理。



下面讲讲三态门的东西:

利用三态门的高阻特性,可以实现总线的功能。由于三态门资源大多存在于FPGA芯片的接口资源中而非FPGA内部,因此一般当总线位于FPGA芯片外部时,常采用这种方式。

再讲讲代码中的赋值冲突问题:

下面的代码是错误的,存在赋值冲突:


  
  1. assign c = (sel[0] == 1'b1) ? a:1'b0;
  2. assign c = (sel[1] == 1'b1) ? b:1'b1;

这个例子代码,两条赋值语句肯定都是一直有效的,因此必然产生赋值冲突,从而导致出错。

下面的代码就是对的:


  
  1. assign c = (sel[0] == 1'b1) ? a:1'bz;
  2. assign c = (sel[1] == 1'b1) ? b:1'bz;

这个代码的写法和上面的唯一区别就是高组态的使用,为什么使用了高阻态,代码就是正确的了呢?

这是因为高阻态实际上就是电路中的断路,通过合理切换到高阻态,可以让上述有高阻态的例子中的两条赋值语句不会在同一时刻生效,因此不会产生赋值冲突。


下面直接给出一个简单的三态门式总线的FPGA实现方式。功能代码分为三个部分,上面也已经说了:

1、选择器控制信号产生部分,采用抢占式优先级译码器(【 FPGA 】抢占式优先级译码器电路)的思路,根据四个外围器件的请求信号产生多路选择器的选择控制信号。

2、写总线部分,即将四个三态门的输出连接到总线上。

3、读总线部分,各个外围器件根据自己的情况将总线数据读入器件内部进行运算和处理。

 


  
  1. `timescale 1ns / 1ps
  2. //
  3. // Company:
  4. // Engineer:
  5. //
  6. // Create Date: 20:05:53 11/05/2018
  7. // Design Name:
  8. // Module Name: Bus_Three
  9. // Project Name:
  10. // Target Devices:
  11. // Tool versions:
  12. // Description:
  13. //
  14. // Dependencies:
  15. //
  16. // Revision:
  17. // Revision 0.01 - File Created
  18. // Additional Comments:
  19. //
  20. //
  21. module Bus_Three(
  22. input request0,
  23. input request1,
  24. input request2,
  25. input request3,
  26. input [7:0] device0Out,
  27. input [7:0] device1Out,
  28. input [7:0] device2Out,
  29. input [7:0] device3Out,
  30. output [7:0] device0In,
  31. output [7:0] device1In,
  32. output [7:0] device2In,
  33. output [7:0] device3In
  34. );
  35. reg [3:0] en;
  36. wire [7:0] bus;
  37. //generate sel
  38. always@(request0,request1,request2,request3)
  39. begin
  40. case({request0,request1,request2,request3})
  41. 4'b0000: en = 4'b0000;
  42. 4'b0001: en = 4'b1000; // the most high bit of en is available when request3 is high
  43. 4'b0010-4'b0011: en = 4'b0100; // the second bit of en is available when request2 is high
  44. 4'b0100-4'b0111: en = 4'b0010; // the first bit of en is available when request1 is high
  45. default: en = 4'b0001; // the zero bit of en is available when request0 is high
  46. endcase
  47. end
  48. //write bus
  49. assign bus = (en[0] == 1'b1) ? device0Out:8'hzz;
  50. assign bus = (en[1] == 1'b1) ? device1Out:8'hzz;
  51. assign bus = (en[2] == 1'b1) ? device2Out:8'hzz;
  52. assign bus = (en[3] == 1'b1) ? device3Out:8'hzz;
  53. //read bus
  54. assign device0In = bus;
  55. assign device1In = bus;
  56. assign device2In = bus;
  57. assign device3In = bus;
  58. endmodule

RTL Schematic:

Technology Schematic:

随便给出局部图,因为总图太大,放不下,缩小了又看不清楚:

废话不必多说,Technology Schematic给出了FPGA内部是如何实现这个电路的,不用想,是查找表和一些输入输出缓冲器。

 

 

 

文章来源: reborn.blog.csdn.net,作者:李锐博恩,版权归原作者所有,如需转载,请联系作者。

原文链接:reborn.blog.csdn.net/article/details/83756121

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。