?? 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 + -