⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tst_bench_top.v

📁 USB_I2C_MAC_FPGA_Code.rar
💻 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 + -