CPU设计之总线
23 Oct 2019 219286字 731分 次 Digital IC Design打赏作者 CC BY 4.0 (除特别声明或转载文章外)
1 前言
总线负责将CPU、内存、IO等相互连接的共享通道。
- 开发环境:
- Quartus Prime Standard 18.1
- 操作系统:
- Windows 10 Pro 1903
2 总线总体规划
本设计的总线主控为4通道,总线从属为8通道。结构如图所示:
总线控制器的左边的接口接总线主控,右边的接口接从属设备。两边接口的浅色部分为接多条总线设备,深色部分为接常用的总线,也就是选中后的总线。红色虚线上半部分负责主控选通,下半部分负责从属设备选通。
接口信号如下:
信号名 | 位宽 | 方向 | 含义 |
---|---|---|---|
clk | 1 | input | 时钟 |
rst_n | 1 | input | 异步复位 |
m*_req_ | 1×4 | input | 总线使用请求信号 |
m*_grnt_ | 1×4 | output | 总线使用许可信号 |
m*_as_ | 1×4 | input | 主控设备访问有效信号 |
m*_rw | 1×4 | input | 主控设备读写控制信号 |
m*_wr_data | 32×4 | input | 写入数据 |
m*_addr | 30×4 | input | 主控设备要访问的地址 |
m_rdy_ | 1 | output | 访问结束信号 |
m_rd_data | 32 | output | 读取数据 |
s_as_ | 1 | output | 访问从属设备有效信号 |
s_rw | 1 | output | 控制从属设备读写信号 |
s_wr_data | 32 | output | 写入从属设备数据 |
s_addr | 30 | output | 访问从属设备地址 |
s*_cs_ | 1×8 | output | 从属设备访问有效信号 |
s*_rdy_ | 1×8 | input | 从属设备访问结束信号 |
s*_rd_data | 32×8 | input | 从属设备读取数据 |
其中,总线仲裁器根据四个主控发来的请求信号来判断当前许可哪条主控使用总线。一旦总线主控被许可使用总线,即可以开始总线访问。总线主机多路复用器根据仲裁后的结果选通那一组主机总线。地址解码器通过选通后的主机访问地址判断访问哪一个从机。总线从属多路复用器根据解码后的结果选通那一组从机总线。
3 总线仲裁器
3.1 接口
总线仲裁器要根据四个主控的请求信号生成四个主控的许可信号,所以有以下信号接口:
信号名 | 位宽 | 方向 | 含义 |
---|---|---|---|
clk | 1 | input | 时钟 |
rst_n | 1 | input | 异步复位 |
m0_req_ | 1 | input | 0号主控请求信号 |
m0_grnt_ | 1 | output | 0号总线使用许可信号 |
m1_req_ | 1 | input | 1号主控请求信号 |
m1_grnt_ | 1 | output | 1号总线使用许可信号 |
m2_req_ | 1 | input | 2号主控请求信号 |
m2_grnt_ | 1 | output | 2号总线使用许可信号 |
m3_req_ | 1 | input | 3号主控请求信号 |
m3_grnt_ | 1 | output | 3号总线使用许可信号 |
3.2 实现
四个请求信号是有优先级的,默认情况下许可0号主控。
当前总线所有者为0号时,优先顺序为:0>1>2>3。也就是如果0号还在请求,那么总线所有者保持为0号总线;如果0号没有请求,1号请求,当前总线所有者变为1号;如果0号、1号没请求,2号请求,那么当前总线所有者变为2号;如果0号、1号、2号没请求,3号请求,那么当前总线所有者变为3号;如果都不请求,则恢复默认状态,即许可0号主控。
当前总线所有者为1号时,优先顺序为:1>2>3>0;当前总线所有者为2号时,优先顺序为:2>3>0>1;当前总线所有者为3号时,优先顺序为:3>0>1>2。
所以用状态机来完成:
//------------------------------------------------------------------------------
//
//Module Name: bus_arbiter.sv
//Department: Xidian University
//Function Description: 总线仲裁器
//
//------------------------------------------------------------------------------
//
//Version Design Coding Simulata Review Rel data
//V1.0 Verdvana Verdvana Verdvana 2020-1-31
//
//-----------------------------------------------------------------------------------
//
//Version Modified History
//V1.0
//
//-----------------------------------------------------------------------------------
`timescale 1ns/1ns
module bus_arbiter (
/**********时钟&复位**********/
input clk, //时钟
input rst_n, //异步复位
/**********仲裁信号***********/
// 0号总线主控
input m0_req_, //请求信号
output reg m0_grnt_, //总线使用许可信号
// 1号总线主控
input m1_req_, //请求信号
output reg m1_grnt_, //总线使用许可信号
// 2号总线主控
input m2_req_, //请求信号
output reg m2_grnt_, //总线使用许可信号
// 3号总线主控
input m3_req_, //请求信号
output reg m3_grnt_ //总线使用许可信号
);
//=========================================================
//仲裁状态机(三段式)
//---------------------------------------------------------
//枚举所有状态(reg四状态)
enum reg [1:0] {
BUS_OWNER_MASTER_0, //总线所有者:0号总线主控
BUS_OWNER_MASTER_1, //总线所有者:1号总线主控
BUS_OWNER_MASTER_2, //总线所有者:2号总线主控
BUS_OWNER_MASTER_3 //总线所有者:3号总线主控
} state,next_state;
//---------------------------------------------------------
//第一段 状态译码
always_comb begin
case (state)
BUS_OWNER_MASTER_0: begin //当前总线所有者为0号时,优先顺序为:0>1>2>3
if(!m0_req_) //如果0号仍在请求
next_state = BUS_OWNER_MASTER_0; //当前总线所有者继续为0号
else if(!m1_req_) //0号没有请求,1号请求
next_state = BUS_OWNER_MASTER_1; //当前总线所有者变为1号
else if(!m2_req_) //0号、1号没请求,2号请求
next_state = BUS_OWNER_MASTER_2; //当前总线所有者变为2号
else if(!m3_req_) //0号、1号、2号没请求,3号请求
next_state = BUS_OWNER_MASTER_3; //当前总线所有者变为3号
else //都不请求
next_state = BUS_OWNER_MASTER_0; //恢复为默认状态
end
BUS_OWNER_MASTER_1: begin //当前总线所有者为1号时,优先顺序为:1>2>3>0
if(!m1_req_)
next_state = BUS_OWNER_MASTER_1;
else if(!m2_req_)
next_state = BUS_OWNER_MASTER_2;
else if(!m3_req_)
next_state = BUS_OWNER_MASTER_3;
else if(!m0_req_)
next_state = BUS_OWNER_MASTER_0;
else
next_state = BUS_OWNER_MASTER_0;
end
BUS_OWNER_MASTER_2: begin //当前总线所有者为2号时,优先顺序为:2>3>0>1
if(!m2_req_)
next_state = BUS_OWNER_MASTER_2;
else if(!m3_req_)
next_state = BUS_OWNER_MASTER_3;
else if(!m0_req_)
next_state = BUS_OWNER_MASTER_0;
else if(!m1_req_)
next_state = BUS_OWNER_MASTER_1;
else
next_state = BUS_OWNER_MASTER_0;
end
BUS_OWNER_MASTER_3: begin //当前总线所有者为3号时,优先顺序为:3>0>1>2
if(!m3_req_)
next_state = BUS_OWNER_MASTER_3;
else if(!m0_req_)
next_state = BUS_OWNER_MASTER_0;
else if(!m1_req_)
next_state = BUS_OWNER_MASTER_1;
else if(!m2_req_)
next_state = BUS_OWNER_MASTER_2;
else
next_state = BUS_OWNER_MASTER_0;
end
default: begin //恢复默认
next_state = BUS_OWNER_MASTER_0;
end
endcase
end
//---------------------------------------------------------
//第二段 更新状态寄存器
always_ff@(posedge clk, negedge rst_n)begin
if(!rst_n)
state <= BUS_OWNER_MASTER_0;
else
state <= next_state;
end
//---------------------------------------------------------
//第三段 利用状态寄存器输出控制结果
always_comb begin
{m0_grnt_,m1_grnt_,m2_grnt_,m3_grnt_} = '1; //产生默认值,防止产生锁存器
case (state)
BUS_OWNER_MASTER_0: {m0_grnt_,m1_grnt_,m2_grnt_,m3_grnt_} = 4'b0111;
BUS_OWNER_MASTER_1: {m0_grnt_,m1_grnt_,m2_grnt_,m3_grnt_} = 4'b1011;
BUS_OWNER_MASTER_2: {m0_grnt_,m1_grnt_,m2_grnt_,m3_grnt_} = 4'b1101;
BUS_OWNER_MASTER_3: {m0_grnt_,m1_grnt_,m2_grnt_,m3_grnt_} = 4'b1110;
default: {m0_grnt_,m1_grnt_,m2_grnt_,m3_grnt_} = 4'b0111;
endcase
end
endmodule
4 总线主控用多路复用器
4.1 接口
其实就是一个多路选择器,控制信号为上一节中产生的许可信号,四个主控的各种信号被选通为一组:
信号名 | 位宽 | 方向 | 含义 |
---|---|---|---|
m0_grnt_ | 1 | input | 0号总线使用许可信号 |
m0_as_ | 1 | input | 0号主控设备访问有效信号 |
m0_rw | 1 | input | 0号主控设备读写控制信号 |
m0_wr_data | 32 | input | 0号主控写入数据 |
m0_addr | 30 | input | 0号主控设备要访问的地址 |
m1_grnt_ | 1 | input | 1号总线使用许可信号 |
m1_as_ | 1 | input | 1号主控设备访问有效信号 |
m1_rw | 1 | input | 1号主控设备读写控制信号 |
m1_wr_data | 32 | input | 1号主控写入数据 |
m1_addr | 30 | input | 1号主控设备要访问的地址 |
m2_grnt_ | 1 | input | 2号总线使用许可信号 |
m2_as_ | 1 | input | 2号主控设备访问有效信号 |
m2_rw | 1 | input | 2号主控设备读写控制信号 |
m2_wr_data | 32 | input | 2号主控写入数据 |
m2_addr | 30 | input | 2号主控设备要访问的地址 |
m3_grnt_ | 1 | input | 3号总线使用许可信号 |
m3_as_ | 1 | input | 3号主控设备访问有效信号 |
m3_rw | 1 | input | 3号主控设备读写控制信号 |
m3_wr_data | 32 | input | 3号主控写入数据 |
m3_addr | 30 | input | 3号主控设备要访问的地址 |
s_as_ | 1 | output | 访问从属设备有效信号 |
s_rw | 1 | output | 控制从属设备读写信号 |
s_wr_data | 32 | output | 写入从属设备数据 |
s_addr | 30 | output | 访问从属设备地址 |
4.2 实现
控制信号在上一模块(主控仲裁器)生成,通过判断这四个信号就可以知道选通哪一路:
//------------------------------------------------------------------------------
//
//Module Name: bus_master_mux.sv
//Department: Xidian University
//Function Description: 总线主控用多路复用器
//
//------------------------------------------------------------------------------
//
//Version Design Coding Simulata Review Rel data
//V1.0 Verdvana Verdvana Verdvana 2020-1-29
//
//-----------------------------------------------------------------------------------
//
//Version Modified History
//V1.0
//
//-----------------------------------------------------------------------------------
`timescale 1ns/1ns
module bus_master_mux #(
parameter DATA_W = 32, //数据宽度
ADDR_W = 30 //地址宽度
)(
/********** 总线主信号 **********/
// 0号总线主控
input [ADDR_W-1:0] m0_addr, //访问地址
input m0_as_, //从属访问选择信号
input m0_rw, //读/写表示信号
input [DATA_W-1:0] m0_wr_data, //写入数据
input m0_grnt_, //总线使用许可信号
// 1号总线主控
input [ADDR_W-1:0] m1_addr, //访问地址
input m1_as_, //从属访问选择信号
input m1_rw, //读/写表示信号
input [DATA_W-1:0] m1_wr_data, //写入数据
input m1_grnt_, //总线使用许可信号
// 2号总线主控
input [ADDR_W-1:0] m2_addr, //访问地址
input m2_as_, //从属访问选择信号
input m2_rw, //读/写表示信号
input [DATA_W-1:0] m2_wr_data, //写入数据
input m2_grnt_, //总线使用许可信号
// 3号总线主控
input [ADDR_W-1:0] m3_addr, //访问地址
input m3_as_, //从属访问选择信号
input m3_rw, //读/写表示信号
input [DATA_W-1:0] m3_wr_data, //写入数据
input m3_grnt_, //总线使用许可信号
/********** 总线从机常用信号 **********/
output reg [ADDR_W-1:0] s_addr, //访问地址
output reg s_as_, //从属访问选择信号
output reg s_rw, //读/写表示信号
output reg [DATA_W-1:0] s_wr_data //写入数据
);
always_comb begin
case ({m0_grnt_,m1_grnt_,m2_grnt_,m3_grnt_})
4'b0111: begin // 0号总线主控
s_addr = m0_addr;
s_as_ = m0_as_;
s_rw = m0_rw;
s_wr_data = m0_wr_data;
end
4'b1011: begin // 1号总线主控
s_addr = m1_addr;
s_as_ = m1_as_;
s_rw = m1_rw;
s_wr_data = m1_wr_data;
end
4'b1101: begin // 2号总线主控
s_addr = m2_addr;
s_as_ = m2_as_;
s_rw = m2_rw;
s_wr_data = m2_wr_data;
end
4'b1110: begin // 3号总线主控
s_addr = m3_addr;
s_as_ = m3_as_;
s_rw = m3_rw;
s_wr_data = m3_wr_data;
end
default: begin // 默认值
s_addr = '0;
s_as_ = '1;
s_rw = '1; //1是写,0是读
s_wr_data = '0;
end
endcase
end
endmodule
5 地址解码器
5.1 接口
因为要连接八个从属设备,所以将地址空间八等分,地址映射如下表:
总线从属 | 地址 | 地址最高3位 | 分配 |
---|---|---|---|
0 | 0x0000_0000 ~ 0x1FFF_FFFF | 3’b000 | ROM |
1 | 0x2000_0000 ~ 0x3FFF_FFFF | 3’b001 | SPM |
2 | 0x4000_0000 ~ 0x5FFF_FFFF | 3’b010 | Timer |
3 | 0x6000_0000 ~ 0x7FFF_FFFF | 3’b011 | UART |
4 | 0x8000_0000 ~ 0x9FFF_FFFF | 3’b100 | GPIO |
5 | 0xA000_0000 ~ 0xBFFF_FFFF | 3’b101 | 没想好 |
6 | 0xC000_0000 ~ 0xDFFF_FFFF | 3’b110 | …… |
7 | 0xE000_0000 ~ 0xFFFF_FFFF | 3’b111 | …… |
可以看出每一种设备地址的前三位是相同的,既在总线主控用多路复用器选通后的信号组里的地址的最高三位为选通从机的地址:
所以接口为:
信号名 | 位宽 | 方向 | 含义 |
---|---|---|---|
s_addr | 30 | input | 访问从属设备地址 |
s0_cs_ | 1 | output | 从属设备0访问有效信号 |
s1_cs_ | 1 | output | 从属设备1访问有效信号 |
s2_cs_ | 1 | output | 从属设备2访问有效信号 |
s3_cs_ | 1 | output | 从属设备3访问有效信号 |
s4_cs_ | 1 | output | 从属设备4访问有效信号 |
s5_cs_ | 1 | output | 从属设备5访问有效信号 |
s6_cs_ | 1 | output | 从属设备6访问有效信号 |
s7_cs_ | 1 | output | 从属设备7访问有效信号 |
5.2 实现
就是根据地址的高三位来判断八个片选信号哪一个是低电平:
//------------------------------------------------------------------------------
//
//Module Name: bus_addr_dec.sv
//Department: Xidian University
//Function Description: 地址解码器
//
//------------------------------------------------------------------------------
//
//Version Design Coding Simulata Review Rel data
//V1.0 Verdvana Verdvana Verdvana 2020-1-30
//
//-----------------------------------------------------------------------------------
//
//Version Modified History
//V1.0
//
//-----------------------------------------------------------------------------------
`timescale 1ns/1ns
/********** 模块 **********/
module bus_addr_dec #(
parameter ADDR_W = 30 //地址宽度
)(
/********** 地址 **********/
input [ADDR_W-1:0] s_addr, //地址
/********** 片选 **********/
output reg s0_cs_, //0号总线从机
output reg s1_cs_, //1号总线从机
output reg s2_cs_, //2号总线从机
output reg s3_cs_, //3号总线从机
output reg s4_cs_, //4号总线从机
output reg s5_cs_, //5号总线从机
output reg s6_cs_, //6号总线从机
output reg s7_cs_ //7号总线从机
);
wire [2:0] s_index = s_addr[ADDR_W-1-:3]; //总线从机索引
always_comb begin
{s0_cs_,s1_cs_,s2_cs_,s3_cs_,s4_cs_,s5_cs_,s6_cs_,s7_cs_} = '1; //初始化
case (s_index)
3'h0: begin // 0号总线从机
{s0_cs_,s1_cs_,s2_cs_,s3_cs_,s4_cs_,s5_cs_,s6_cs_,s7_cs_} = 8'b0111_1111;
end
3'h1: begin // 1号总线从机
{s0_cs_,s1_cs_,s2_cs_,s3_cs_,s4_cs_,s5_cs_,s6_cs_,s7_cs_} = 8'b1011_1111;
end
3'h2: begin // 2号总线从机
{s0_cs_,s1_cs_,s2_cs_,s3_cs_,s4_cs_,s5_cs_,s6_cs_,s7_cs_} = 8'b1101_1111;
end
3'h3: begin // 3号总线从机
{s0_cs_,s1_cs_,s2_cs_,s3_cs_,s4_cs_,s5_cs_,s6_cs_,s7_cs_} = 8'b1110_1111;
end
3'h4: begin // 4号总线从机
{s0_cs_,s1_cs_,s2_cs_,s3_cs_,s4_cs_,s5_cs_,s6_cs_,s7_cs_} = 8'b1111_0111;
end
3'h5: begin // 5号总线从机
{s0_cs_,s1_cs_,s2_cs_,s3_cs_,s4_cs_,s5_cs_,s6_cs_,s7_cs_} = 8'b1111_1011;
end
3'h6: begin // 6号总线从机
{s0_cs_,s1_cs_,s2_cs_,s3_cs_,s4_cs_,s5_cs_,s6_cs_,s7_cs_} = 8'b1111_1101;
end
3'h7: begin // 7号总线从机
{s0_cs_,s1_cs_,s2_cs_,s3_cs_,s4_cs_,s5_cs_,s6_cs_,s7_cs_} = 8'b1111_1110;
end
default: begin //默认
{s0_cs_,s1_cs_,s2_cs_,s3_cs_,s4_cs_,s5_cs_,s6_cs_,s7_cs_} = 8'b0111_1111;
end
endcase
end
endmodule
6 总线从属用多路复用器
6.1 接口
和总线主控用多路复用器类似,通过从属设备的片选信号选择当前选通哪一路从属设备信号组,接口:
信号名 | 位宽 | 方向 | 含义 |
---|---|---|---|
m_rdy_ | 1 | output | 访问结束信号 |
m_rd_data | 32 | output | 读取数据 |
s0_cs_ | 1 | input | 从属设备0访问有效信号 |
s0_rdy_ | 1 | input | 从属设备0访问结束信号 |
s0_rd_data | 32 | input | 从属设备0读取数据 |
s1_cs_ | 1 | input | 从属设备1访问有效信号 |
s1_rdy_ | 1 | input | 从属设备1访问结束信号 |
s1_rd_data | 32 | input | 从属设备1读取数据 |
s2_cs_ | 1 | input | 从属设备2访问有效信号 |
s2_rdy_ | 1 | input | 从属设备2访问结束信号 |
s2_rd_data | 32 | input | 从属设备2读取数据 |
s3_cs_ | 1 | input | 从属设备3访问有效信号 |
s3_rdy_ | 1 | input | 从属设备3访问结束信号 |
s3_rd_data | 32 | input | 从属设备3读取数据 |
s4_cs_ | 1 | input | 从属设备4访问有效信号 |
s4_rdy_ | 1 | input | 从属设备4访问结束信号 |
s4_rd_data | 32 | input | 从属设备4读取数据 |
s5_cs_ | 1 | input | 从属设备5访问有效信号 |
s5_rdy_ | 1 | input | 从属设备5访问结束信号 |
s5_rd_data | 32 | input | 从属设备5读取数据 |
s6_cs_ | 1 | input | 从属设备6访问有效信号 |
s6_rdy_ | 1 | input | 从属设备6访问结束信号 |
s6_rd_data | 32 | input | 从属设备6读取数据 |
s7_cs_ | 1 | input | 从属设备7访问有效信号 |
s7_rdy_ | 1 | input | 从属设备7访问结束信号 |
s7_rd_data | 32 | input | 从属设备7读取数据 |
6.2 实现
和总线主控用多路复用器类似:
//------------------------------------------------------------------------------
//
//Module Name: bus_slave_mux.sv
//Department: Xidian University
//Function Description: 总线从属用多路复用器
//
//------------------------------------------------------------------------------
//
//Version Design Coding Simulata Review Rel data
//V1.0 Verdvana Verdvana Verdvana 2020-1-29
//
//-----------------------------------------------------------------------------------
//
//Version Modified History
//V1.0
//
//-----------------------------------------------------------------------------------
`timescale 1ns/1ns
/********** 模块 **********/
module bus_slave_mux #(
parameter DATA_W = 32 //数据宽度
)(
/********** 片选 **********/
input s0_cs_, //0号总线从机
input s1_cs_, //1号总线从机
input s2_cs_, //2号总线从机
input s3_cs_, //3号总线从机
input s4_cs_, //4号总线从机
input s5_cs_, //5号总线从机
input s6_cs_, //6号总线从机
input s7_cs_, //7号总线从机
/********** 总线从机信号 **********/
// 0号总线从机
input [DATA_W-1:0] s0_rd_data, //读出数据
input s0_rdy_, //访问结束表示信号
// 1号总线从机
input [DATA_W-1:0] s1_rd_data, //读出数据
input s1_rdy_, //访问结束表示信号
// 2号总线从机
input [DATA_W-1:0] s2_rd_data, //读出数据
input s2_rdy_, //访问结束表示信号
// 3号总线从机
input [DATA_W-1:0] s3_rd_data, //读出数据
input s3_rdy_, //访问结束表示信号
// 4号总线从机
input [DATA_W-1:0] s4_rd_data, //读出数据
input s4_rdy_, //访问结束表示信号
// 5号总线从机
input [DATA_W-1:0] s5_rd_data, //读出数据
input s5_rdy_, //访问结束表示信号
// 6号总线从机
input [DATA_W-1:0] s6_rd_data, //读出数据
input s6_rdy_, //访问结束表示信号
// 7号总线从机
input [DATA_W-1:0] s7_rd_data, //读出数据
input s7_rdy_, //访问结束表示信号
/********** 总线主控通用信号 **********/
output reg [DATA_W-1:0] m_rd_data, //读出数据
output reg m_rdy_ //访问结束表示信号
);
always_comb begin
case ({s0_cs_,s1_cs_,s2_cs_,s3_cs_,s4_cs_,s5_cs_,s6_cs_,s7_cs_})
8'b0111_1111: begin //0号总线从机
m_rd_data = s0_rd_data;
m_rdy_ = s0_rdy_;
end
8'b1011_1111: begin //1号总线从机
m_rd_data = s1_rd_data;
m_rdy_ = s1_rdy_;
end
8'b1101_1111: begin //2号总线从机
m_rd_data = s2_rd_data;
m_rdy_ = s2_rdy_;
end
8'b1110_1111: begin //3号总线从机
m_rd_data = s3_rd_data;
m_rdy_ = s3_rdy_;
end
8'b1111_0111: begin //4号总线从机
m_rd_data = s4_rd_data;
m_rdy_ = s4_rdy_;
end
8'b1111_1011: begin //5号总线从机
m_rd_data = s5_rd_data;
m_rdy_ = s5_rdy_;
end
8'b1111_1101: begin //6号总线从机
m_rd_data = s6_rd_data;
m_rdy_ = s6_rdy_;
end
8'b1111_1110: begin //7号总线从机
m_rd_data = s7_rd_data;
m_rdy_ = s7_rdy_;
end
default: begin //默认值
m_rd_data = '0;
m_rdy_ = '1;
end
endcase
end
endmodule
7 总线顶层
按照总体规划那一节设计接口,然后将以上四个模块连起来即可:
//------------------------------------------------------------------------------
//
//Module Name: bus.sv
//Department: Xidian University
//Function Description: 总线顶层模块
//
//------------------------------------------------------------------------------
//
//Version Design Coding Simulata Review Rel data
//V1.0 Verdvana Verdvana Verdvana 2020-1-31
//
//-----------------------------------------------------------------------------------
//
//Version Modified History
//V1.0
//
//-----------------------------------------------------------------------------------
`timescale 1ns/1ns
module bus #(
parameter DATA_W = 32, //数据宽度
ADDR_W = 30 //地址宽度
)(
/********** 时钟 & 复位 **********/
input clk, //时钟
input rst_n, //异步复位
/********** 总线主信号 **********/
// 总线主通用信号
output [DATA_W-1:0] m_rd_data, //读数据
output m_rdy_, //访问结束表示信号
// 0号总线主控
input m0_req_, //总线请求
input [ADDR_W-1:0] m0_addr, //访问地址
input m0_as_, //从属访问选择信号
input m0_rw, //读/写表示信号
input [DATA_W-1:0] m0_wr_data, //写入数据
output m0_grnt_, //总线使用许可信号
// 1号总线主控
input m1_req_, //总线请求
input [ADDR_W-1:0] m1_addr, //访问地址
input m1_as_, //从属访问选择信号
input m1_rw, //读/写表示信号
input [DATA_W-1:0] m1_wr_data, //写入数据
output m1_grnt_, //总线使用许可信号
// 2号总线主控
input m2_req_, //总线请求
input [ADDR_W-1:0] m2_addr, //访问地址
input m2_as_, //从属访问选择信号
input m2_rw, //读/写表示信号
input [DATA_W-1:0] m2_wr_data, //写入数据
output m2_grnt_, //总线使用许可信号
// 3号总线主控
input m3_req_, //总线请求
input [ADDR_W-1:0] m3_addr, //访问地址
input m3_as_, //从属访问选择信号
input m3_rw, //读/写表示信号
input [DATA_W-1:0] m3_wr_data, //写入数据
output m3_grnt_, //总线使用许可信号
/********** 总线从机信号 **********/
// 总线从机常用信号
output [ADDR_W-1:0] s_addr, //地址
output s_as_, //从属访问选择信号
output s_rw, //读/写表示信号
output [DATA_W-1:0] s_wr_data, //写入数据
// 0号总线从属
input [DATA_W-1:0] s0_rd_data, //读取数据
input s0_rdy_, //访问结束表示信号
output s0_cs_, //从属访问选择信号
// 1号总线从属
input [DATA_W-1:0] s1_rd_data, //读取数据
input s1_rdy_, //访问结束表示信号
output s1_cs_, //从属访问选择信号
// 2号总线从属
input [DATA_W-1:0] s2_rd_data, //读取数据
input s2_rdy_, //访问结束表示信号
output s2_cs_, //从属访问选择信号
// 3号总线从属
input [DATA_W-1:0] s3_rd_data, //读取数据
input s3_rdy_, //访问结束表示信号
output s3_cs_, //从属访问选择信号
// 4号总线从属
input [DATA_W-1:0] s4_rd_data, //读取数据
input s4_rdy_, //访问结束表示信号
output s4_cs_, //从属访问选择信号
// 5号总线从属
input [DATA_W-1:0] s5_rd_data, //读取数据
input s5_rdy_, //访问结束表示信号
output s5_cs_, //从属访问选择信号
// 6号总线从属
input [DATA_W-1:0] s6_rd_data, //读取数据
input s6_rdy_, //访问结束表示信号
output s6_cs_, //从属访问选择信号
// 7号总线从属
input [DATA_W-1:0] s7_rd_data, //读取数据
input s7_rdy_, //访问结束表示信号
output s7_cs_ //从属访问选择信号
);
//=================================================
//总线仲裁器
bus_arbiter u_bus_arbiter (.*);
//=================================================
//总线主机多路复用器
bus_master_mux #(
.DATA_W(DATA_W),
.ADDR_W(ADDR_W)
)u_bus_master_mux (.*);
//=================================================
//地址解码器
bus_addr_dec #(
.ADDR_W(ADDR_W)
)u_bus_addr_dec (.*);
//=================================================
//总线从属多路复用器
bus_slave_mux #(
.DATA_W(DATA_W)
)u_bus_slave_mux (.*);
endmodule
告辞。