📄 tst_bench_top.v
字号:
`include "timescale.v"
module tst_bench_top();
//连线和寄存器
reg clk;
reg rstn;
wire [31:0] adr;
wire [ 7:0] dat_i, dat_o;
wire we;
wire stb;
wire cyc;
wire ack;
wire inta;
//q保存状态寄存器内容
reg [7:0] q, qq;
wire scl, scl_o, scl_oen;
wire sda, sda_o, sda_oen;
//寄存器地址
parameter PRER_LO = 3'b000;//分频寄存器低位地址
parameter PRER_HI = 3'b001;//高位地址
parameter CTR = 3'b010;//控制寄存器地址,(7)使能位|6中断使能位|5-0其余保留位
parameter RXR = 3'b011;//接受寄存器地址,(7)接受到的最后一个字节的数据
parameter TXR = 3'b011;//传输寄存器地址,(7)传输地址时最后一位为读写位,1为读
parameter CR = 3'b100;//命令寄存器地址,
//(7)开始|6结束|5读|4写|3应答(作为接受方时,发送应答信号,“0”为应答,“1”为不应答)|2保留位|1保留位|0中断应答位,这八位自动清除
parameter SR = 3'b100;//状态寄存器地址,(7)接受应答位(“0”为接受到应答)|6忙位(产生开始信号后变为1,结束信号后变为0)|5仲裁位|4-2保留位|1传输中位(1表示正在传输数据,0表示传输结束)|中断标志位
parameter TXR_R = 3'b101; // undocumented / reserved output
parameter CR_R = 3'b110; // undocumented / reserved output
// 产生时钟信号,一个时间单位为1ns,周期为10ns,频率为100MHz。
always #5 clk = ~clk;
//连接master模拟模块
wb_master_model #(8, 32) u0 (
.clk(clk),//时钟
.rst(rstn),//重起
.adr(adr),//地址
.din(dat_i),//输入的数据
.dout(dat_o),//输出的数据
.cyc(cyc),
.stb(stb),
.we(we),
.sel(),
.ack(ack),//应答
.err(1'b0),
.rty(1'b0)
);
//连接i2c接口
i2c_master_top i2c_top (
//连接到master模拟模块部分
.wb_clk_i(clk), //时钟
.wb_rst_i(1'b0), //同步重起位
.arst_i(rstn), //异步重起
.wb_adr_i(adr[2:0]), //地址输入
.wb_dat_i(dat_o), //数据输入接口
.wb_dat_o(dat_i), //数据从接口输出
.wb_we_i(we), //写使能信号
.wb_stb_i(stb), //片选信号,应该一直为高
.wb_cyc_i(cyc), //?
.wb_ack_o(ack), //应答信号输出到master模拟模块
.wb_inta_o(inta),//中断信号输出,到master模拟模块
//输出的i2c信号,连接到slave模拟模块
.scl_pad_i(scl),
.scl_pad_o(scl_o),
.scl_padoen_o(scl_oen),
.sda_pad_i(sda),
.sda_pad_o(sda_o),
.sda_padoen_o(sda_oen)
);
//连接到slave模拟模块
i2c_slave_model #(7'b1010_000) i2c_slave (
.scl(scl),
.sda(sda)
);
//为master模拟模块产生scl和sda的三态缓冲
assign scl = scl_oen ? 1'bz : scl_o; // create tri-state buffer for i2c_master scl line
assign sda = sda_oen ? 1'bz : sda_o; // create tri-state buffer for i2c_master sda line
//上拉
pullup p1(scl); // pullup scl line
pullup p2(sda); // pullup sda line
//初始化
initial
begin
// force i2c_slave.debug = 1'b1; // enable i2c_slave debug information
// force i2c_slave.debug = 1'b0; // disable i2c_slave debug information
$display("\n状态: %t I2C接口测试开始!\n\n", $time);
// 初始值
clk = 0;
//重起系统
rstn = 1'b1; // negate reset
#2;
rstn = 1'b0; // assert reset
repeat(20) @(posedge clk);
rstn = 1'b1; // negate reset
$display("状态: %t 完成系统重起!", $time);
@(posedge clk);
// 对接口编程
// 写内部寄存器
// 分频100M/100K*5=O'200=h'C8
u0.wb_write(1, PRER_LO, 8'hc7);
u0.wb_write(1, PRER_HI, 8'h00);
$display("状态: %t 完成分频寄存器操作!", $time);
//读分频寄存器内容
u0.wb_cmp(0, PRER_LO, 8'hc8);
u0.wb_cmp(0, PRER_HI, 8'h00);
$display("状态: %t 完成分频寄存器确认操作!", $time);
//接口使能
u0.wb_write(1, CTR, 8'h80);
$display("状态: %t 完成接口使能!", $time);
// 驱动slave地址
// h'a0=b'1010_0000,地址+写状态,写入的地址为h'50
u0.wb_write(1, TXR, 8'ha0);
//命令内容为b'1001_0000,产生开始位,并设置写状态
u0.wb_write(0, CR, 8'h90);
$display("状态: %t 产生开始位, 然后写命令a0(地址+写),命令开始!", $time);
// 检查状态位信息
// 检查传输是否结束
u0.wb_read(1, SR, q);
while(q[1])
u0.wb_read(0, SR, q);
$display("状态: %t 地址驱动写操作完成!", $time);
// 待写的地址为h'01
u0.wb_write(1, TXR, 8'h01);
// 产生写命令b'0001_0000
u0.wb_write(0, CR, 8'h10);
$display("状态: %t 待写地址为01,命令开始!", $time);
// 检查状态位
u0.wb_read(1, SR, q);
while(q[1])
u0.wb_read(0, SR, q);
$display("状态: %t 写操作完成!", $time);
// 写入内容
u0.wb_write(1, TXR, 8'ha5);
u0.wb_write(0, CR, 8'h10);
$display("状态: %t 写入内容为a5,开始写入过程!", $time);
u0.wb_read(1, SR, q);
while(q[1])
u0.wb_read(1, SR, q);
$display("状态: %t 写a5到地址h'01中完成!", $time);
// 写入下一个地址5a
u0.wb_write(1, TXR, 8'h5a); // present data
// 写入并停止
u0.wb_write(0, CR, 8'h50); // set command (stop, write)
$display("状态: %t 写5a到下一个地址,产生停止位!", $time);
u0.wb_read(1, SR, q);
while(q[1])
u0.wb_read(1, SR, q); // poll it until it is zero
$display("状态: %t 写第二个地址结束!", $time);
// #100000; // wait for 100us.
// $display("status: %t wait 100us", $time);
// 读
// 驱动slave地址
u0.wb_write(1, TXR, 8'ha0);
u0.wb_write(0, CR, 8'h90);
$display("状态: %t 产生开始位,写命令a0 (slave地址+write)", $time);
u0.wb_read(1, SR, q);
while(q[1])
u0.wb_read(1, SR, q); // poll it until it is zero
$display("状态: %t slave地址驱动完成!", $time);
// 发送地址
u0.wb_write(1, TXR, 8'h01);
u0.wb_write(0, CR, 8'h10);
$display("状态: %t 发送地址01!", $time);
u0.wb_read(1, SR, q);
while(q[1])
u0.wb_read(1, SR, q);
$display("状态: %t 地址发送完成!", $time);
// 驱动slave地址,1010_0001,h'50+read
u0.wb_write(1, TXR, 8'ha1);
u0.wb_write(0, CR, 8'h90);
$display("状态: %t 产生重复开始位, 读地址+开始位", $time);
u0.wb_read(1, SR, q);
while(q[1])
u0.wb_read(1, SR, q);
$display("状态: %t 命令结束!", $time);
// 读数据
u0.wb_write(1, CR, 8'h20);
$display("状态: %t 读+应答命令", $time);
u0.wb_read(1, SR, q);
while(q[1])
u0.wb_read(1, SR, q);
$display("状态: %t 读结束!", $time);
// 检查读的内容
u0.wb_read(1, RXR, qq);
if(qq !== 8'ha5)
$display("\n错误: 需要的是a5, received %x at time %t", qq, $time);
// 读下一个地址内容
u0.wb_write(1, CR, 8'h20);
$display("状态: %t 读+ 应答", $time);
u0.wb_read(1, SR, q);
while(q[1])
u0.wb_read(1, SR, q);
$display("状态: %t 第二个地址读结束!", $time);
u0.wb_read(1, RXR, qq);
if(qq !== 8'h5a)
$display("\n错误: 需要的是5a, received %x at time %t", qq, $time);
// 读
u0.wb_write(1, CR, 8'h20);
$display("状态: %t 读 + 应答", $time);
u0.wb_read(1, SR, q);
while(q[1])
u0.wb_read(1, SR, q);
$display("状态: %t 第三个地址读完成!", $time);
u0.wb_read(1, RXR, qq);
$display("状态: %t 第三个地址内容是 %x !", $time, qq);
// 读
u0.wb_write(1, CR, 8'h28);
$display("状态: %t 读 + 不应答!", $time);
u0.wb_read(1, SR, q);
while(q[1])
u0.wb_read(1, SR, q);
$display("状态: %t 第四个地址读完成!", $time);
u0.wb_read(1, RXR, qq);
$display("状态: %t 第四个地址内容为 %x !", $time, qq);
// 检查不存在的slave地址
// drive slave address
u0.wb_write(1, TXR, 8'ha0);
u0.wb_write(0, CR, 8'h90);
$display("状态: %t 产生开始位, 发送命令 a0 (slave地址+写). 检查非法地址!", $time);
u0.wb_read(1, SR, q);
while(q[1])
u0.wb_read(1, SR, q); // poll it until it is zero
$display("状态: %t 命令结束!", $time);
// 发送内存地址
u0.wb_write(1, TXR, 8'h10);
u0.wb_write(0, CR, 8'h10);
$display("状态: %t 发送slave内存地址10!", $time);
u0.wb_read(1, SR, q);
while(q[1])
u0.wb_read(1, SR, q);
$display("状态: %t 地址发送完毕!", $time);
// slave发送不应答
$display("状态: %t 检查不应答位!", $time);
if(!q[7])
$display("\n错误: 需要 NACK, 接受到 ACK\n");
// 从slave读数据
u0.wb_write(1, CR, 8'h40);
$display("状态: %t 产生'stop'位", $time);
u0.wb_read(1, SR, q);
while(q[1])
u0.wb_read(1, SR, q); // poll it until it is zero
$display("状态: %t 结束!", $time);
#25000; // wait 25us
$display("\n\n状态: %t 测试结束!", $time);
$finish;
end
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -