0%

CPU设计04-总线仲裁器代码实现

本文是记录总线仲裁器verilog实现的开发调试和测试过程;其中测试代码是我自己写的。下面描述波形是电路的理想情况,要考虑电路的延迟情况,以及保证电路的可靠性方面,实现的硬件电路会稍微复杂,不过作为程序员的角度理解硬件,verilog的路径正好合适。

1. 工程目录说明

  • 根目录增加include目录,这个是后续需要的全局定义
  • 在src增加include目录,这个是总线需要的定义
  • bus_arbiter_tb.v是我写的,其余文件皆来自《CPU自制入门》作者

2. 测试用例注释

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
module bus_arbiter_tb;
// 时钟,重置信号
reg clk, reset,m0_req_,m1_req_,m2_req_,m3_req_;
wire m0_grnt_,m1_grnt_,m2_grnt_,m3_grnt_;

bus_arbiter ba1(.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_)
);

initial begin
// 初始化所有请求信号
m0_req_ = `DISABLE_;
m1_req_ = `DISABLE_;
m2_req_ = `DISABLE_;
m3_req_ = `DISABLE_;
end
initial begin
// 时钟信号每10ns翻转一次
clk = 0;
forever #10 clk = ~clk;
end
initial begin
// 重置信号15ns后关闭
// 35ns秒后m1_req_请求使用总线
// 过260ns后请求使用总线
reset = `RESET_ENABLE;
#15 reset = `RESET_DISABLE;
#20 m1_req_ = `ENABLE_;
#260 m1_req_ = `DISABLE_;
end
initial begin
// 和上面并行运行
// 60ns后m2_req_请求使用总线
// 请求460ns后停止
#60 m2_req_ = `ENABLE_;
#460 m2_req_ = `DISABLE_;
#200 $finish;
end

initial
begin
$dumpfile("bus_arbiter_tb.vcd"); //生成的vcd文件名称
$dumpvars(0, bus_arbiter_tb); //tb模块名称
end
endmodule

3. 波形分析

结合上面的代码来看波形,在第15ns秒时reset信号变为DISABLE(高电平),接着在35ns秒时m1_req请求使用总线,直到第50ns时(也就是在35ns后clk的第一个上升沿),允许m1使用总线,m1grnt变成ENABLE_(低电平)。

上图是增加了m2请求的情况,在第60ns时m2就已经请求使用总线,但这个时候优先级最高的m1正在使用,直到m1使用完毕,也就是在第300ns的时候结束了总线的请求使用,m1grnt在稍后的下一个上升沿变成DISABLE(高电平),同时m2被允许使用总线,m2_grnt变为ENABLE_(低电平)。

项目工程文件点击下载