1.总线Code管理
- 首先,对前面编写的代码进行一个管理创建一个文件夹命名为bus存放总线设计的代码,
- 在此目录下创建inc文件夹来存放bus所需要的头文件,
- 总线的实现的代码放在bus文件下。
2.总线设计概要
1. bus_arbiter.v :实现了总线总裁器的设计,解决了4个总线主控在请求总线时,总线该赋予哪个主控的仲裁问题。
2. bus_master_mux:实现了总线主控多路复用器的设计,这个是基于总线仲裁器的总线赋予信号:赋予信号一旦选择某个主控,该主控成为总线的使用者,该主控的有关信号将输出到总线上。
这里以举个例子,当总线赋予信号m0_grnt使能,也就是赋予信号选择了0号主控,0号主控就把相关信号输出总线上。相关信号指的是地址信号(m0_addr),地址选通(m0_as),读写信号(m0_rw)和写入的数据(m0_wr_data)。
为什么要用总线这个机制?不能每个主控与从属之间都搞一条线来进行通信吗?我的答案是:可以,前提你得很有钱!总线就像公路,是属于行人和车辆之间共享的,选择信号就像红绿灯,来选择某个时刻这条公路是属于行人还是车辆。后面的地址解码器也是这个原理。
3. bus_addr_dec.v:实现了地址解码器(亦叫做地址译码器)。是基于主控的地址信号(上面提到),这里依然以0号主控来举例。当0号主控将地址信号m0_addr输出到总线上时,地址解码器通过这个地址信号来选择0号主控所需要的几号总线从属(这里作者一共设计了7个总线从属)。 这个过程我们称为片选过程 ,IIC通信之间的片选信号也是这个原理。
4. bus_slave_mux.v:实现了总线从属多路复用器的设计。当地址解码器片选0号总线从属时(也就是s0_cs信号使能),总线从属多路复用器将根据s0_cs信号,将来自0号总线从属输出的s0_rd_data(读出的数据)与s0_rdy(就绪信号)发送到总线上,来达到通信的目的,这就是总线的具体设计。
3.总线顶层模块源码
总线顶层模块我们命名为bus , 由总线仲裁器,总线主控多路复用器,地址解码器,总线从属多路复用器组成。这些单独模块我们在前面一个个的实现了,最后在bus这个总线顶层模块中,例化这些单独的模块。
`include "stddef.h"
`include "global_config.h"
`include "bus.h"
module bus(
input wire clk,
input wire reset,
output wire [`WordDataBus] m_rd_data,
output wire m_rdy_,
input wire m0_req_,
input wire [`WordAddrBus] m0_addr,
input wire m0_as_,
input wire m0_rw,
input wire [`WordDataBus] m0_wr_data,
output wire m0_grnt_,
input wire m1_req_,
input wire [`WordAddrBus] m1_addr,
input wire m1_as_,
input wire m1_rw,
input wire [`WordDataBus] m1_wr_data,
output wire m1_grnt_,
input wire m2_req_,
input wire [`WordAddrBus] m2_addr,
input wire m2_as_,
input wire m2_rw,
input wire [`WordDataBus] m2_wr_data,
output wire m2_grnt_,
input wire m3_req_,
input wire [`WordAddrBus] m3_addr,
input wire m3_as_,
input wire m3_rw,
input wire [`WordDataBus] m3_wr_data,
output wire m3_grnt_,
output wire [`WordAddrBus] s_addr,
output wire s_as_,
output wire s_rw,
output wire [`WordDataBus] s_wr_data,
input wire [`WordDataBus] s0_rd_data,
input wire s0_rdy_,
output wire s0_cs_,
input wire [`WordDataBus] s1_rd_data,
input wire s1_rdy_,
output wire s1_cs_,
input wire [`WordDataBus] s2_rd_data,
input wire s2_rdy_,
output wire s2_cs_,
input wire [`WordDataBus] s3_rd_data,
input wire s3_rdy_,
output wire s3_cs_,
input wire [`WordDataBus] s4_rd_data,
input wire s4_rdy_,
output wire s4_cs_,
input wire [`WordDataBus] s5_rd_data,
input wire s5_rdy_,
output wire s5_cs_,
input wire [`WordDataBus] s6_rd_data,
input wire s6_rdy_,
output wire s6_cs_,
input wire [`WordDataBus] s7_rd_data,
input wire s7_rdy_,
output wire s7_cs_
);
bus_arbiter bus_arbiter(
.clk (clk) ,
.reset (reset),
.m0_req_ (m0_req_),
.m0_grnt_ (m0_grnt_),
.m1_req_ (m1_req_),
.m1_grnt_ (m1_grnt_),
.m2_req_ (m2_req_),
.m2_grnt_ (m2_grnt_),
.m3_req_ (m3_req_),
.m3_grnt_ (m3_grnt_)
);
bus_master_mux bus_master_mux(
.m0_addr (m0_addr),
.m0_as_ (m0_as_),
.m0_rw (m0_rw),
.m0_wr_data (m0_wr_data),
.m0_grnt_ (m0_grnt_),
.m1_addr (m1_addr),
.m1_as_ (m1_as_),
.m1_rw (m1_rw),
.m1_wr_data (m1_wr_data),
.m1_grnt_ (m1_grnt_),
.m2_addr (m2_addr),
.m2_as_ (m2_as_),
.m2_rw (m2_rw),
.m2_wr_data (m2_wr_data),
.m2_grnt_ (m2_grnt_),
.m3_addr (m3_addr),
.m3_as_ (m3_as_),
.m3_rw (m3_rw),
.m3_wr_data (m3_wr_data),
.m3_grnt_ (m3_grnt_),
.s_addr (s_addr),
.s_as_ (s_as_),
.s_rw (s_rw),
.s_wr_data(s_wr_data)
);
bus_addr_dec bus_addr_dec(
.s_addr (s_addr),
.s0_cs_ (s0_cs_),
.s1_cs_ (s1_cs_),
.s2_cs_ (s2_cs_),
.s3_cs_ (s3_cs_),
.s4_cs_ (s4_cs_),
.s5_cs_ (s5_cs_),
.s6_cs_ (s6_cs_),
.s7_cs_ (s7_cs_)
);
bus_slave_mux bus_slave_mux(
.s0_cs_ (s0_cs_),
.s0_rd_data (s0_rd_data),
.s0_rdy_ (s0_rdy_),
.s1_cs_ (s0_cs_),
.s1_rd_data (s0_rd_data),
.s1_rdy_ (s0_rdy_),
.s2_cs_ (s0_cs_),
.s2_rd_data (s0_rd_data),
.s2_rdy_ (s0_rdy_),
.s3_cs_ (s0_cs_),
.s3_rd_data (s0_rd_data),
.s3_rdy_ (s0_rdy_),
.s4_cs_ (s0_cs_),
.s4_rd_data (s0_rd_data),
.s4_rdy_ (s0_rdy_),
.s5_cs_ (s0_cs_),
.s5_rd_data (s0_rd_data),
.s5_rdy_ (s0_rdy_),
.s6_cs_ (s0_cs_),
.s6_rd_data (s0_rd_data),
.s6_rdy_ (s0_rdy_),
.s7_cs_ (s0_cs_),
.s7_rd_data (s0_rd_data),
.s7_rdy_ (s0_rdy_),
.m_rd_data (m_rd_data),
.m_rdy_ (m_rdy_)
);
endmodule
记得在bus工程中加入例化模块的具体实现.v文件和所需要的头文件
4.错误集锦
1.Error (10267): Verilog HDL Module Instantiation error at bus.v(155): cannot connect instance ports both by order and by name
例化模块复制粘贴时多加一个逗号,错误找了半天……
2.Error (169281): There are 526 IO input pads in the design, but only 180 IO input pad locations available on the device.
报错原因:为了验证FPGA工程中的某个模块的功能和时序的正确性,常常需要对其单独进行验证,但是这些模块通常都与内部的众多信号相连(如系统总线,中断信号线等),往往一个模块的对外接口引脚会多达几百个,对其单独仿真的话,可能会对目标FPGA造成IO资源不足的情况。即使IO资源满足,当众多内部信号变成IO信号时,模块内部的信号将增加额外的IO延时,增加了时序约束的复杂度,在编译时会出现此类报错。
【参考博客https://blog.csdn.net/qq_41109998/article/details/123824555 附上解决方式设置虚拟管脚Virtual Pin】
Error 解决方法 一:有些报错英文翻译即可找到错误之处 二:网上网友见解,效率高,但解决方法不一,需要个人甄别 三:去官网社区搜错误Error序号,解决问题强,但对初学者可能不太友好。
5.专栏目录
《从0开始设计和实现CPU》32寄存器堆_记录篇(1) 《从0开始设计和实现CPU》总线设计(一)之总线仲裁器的实现 《从0开始设计和实现CPU》总线设计(二)之总线主控多路复用器的实现 《从0开始设计和实现CPU》总线设计(三)之地址解码器的实现 《从0开始设计和实现CPU》总线设计(四)之总线从属多路复用器的实现 《从0开始设计和实现CPU》bus总线顶层模块设计 正在更新!
|