📄 tb.v
字号:
`timescale 1ns/10ps
`define mbsr {mcf,maas,mbb,mal,reserved_mbsr,srw,mif,rxak}
`define mbcr {men,mien,msta,mtx,txak,rsta,reserved_mbcr}
module tb();
reg clk,reset;
wire sda,scl;
parameter EEPROM_Address = 7'b1010000; // Device Address
parameter I2C_Address_base=16'h0000;
parameter I2C_MADR_ADDR={I2C_Address_base,8'b10001101};
parameter I2C_MBCR_ADDR={I2C_Address_base,8'b10010001};
parameter I2C_MBSR_ADDR={I2C_Address_base,8'b10010011};
parameter I2C_MBDR_ADDR={I2C_Address_base,8'b10010101};
//************ MBCR ***********
reg men;
reg mien;
reg msta;
reg mtx;
reg txak;
reg rsta;
reg[1:0] reserved_mbcr;
wire mcf_wire;
//*********** MBSR ************
reg mcf;
reg maas;
reg mbb;
reg mal;
reg reserved_mbsr;
reg srw;
reg mif;
reg rxak;
//********** MBDR ***********
reg[7:0] mbdr;
reg[23:0] addr_bus;
reg[7:0] data_bus;
trireg[7:0] data_bus_tri;
reg as;
reg ds;
reg r_w;
wire dtack;
wire irq;
reg[7:0] count;
reg[7:0] data_in_uc;
reg[7:0] read_out;
reg data_bus_drive;
assign data_bus_tri=(data_bus_drive==1'b1)? data_bus:8'bz;
initial
begin
`mbcr=8'b0;
`mbsr=8'b0;
mbb=1'b1; //set i2c busy
as=1;
ds=1;
r_w=1;
addr_bus=0;
data_bus=0;
data_bus_drive=0;
reset=0;
#300 reset=1;
current_write_eeprom;
#100000;
current_read_eeprom;
#100000 $finish;
end
initial
begin
clk=0;
forever #250 clk=~clk;
end
//************* read data from EEPROM ****************
task current_read_eeprom;
begin
`mbcr=8'b0; //mtx be cleared
men=1'b1;
txak=1'b0; //ack
mbb=1'b1;
uc_write_i2c(I2C_MBCR_ADDR,`mbcr); //enable I2C
while(mbb==1) // =1, bus busy
begin
uc_read_i2c(read_out,I2C_MBSR_ADDR);
`mbsr=read_out;
end
uc_write_i2c(I2C_MBDR_ADDR,{EEPROM_Address,1'b1}); //write i2c header in MBDR; 1'b1: master requests data
msta=1'b1;//Set MSTA in MBCR to Generate START
uc_write_i2c(I2C_MBCR_ADDR,`mbcr);
@(posedge mcf_wire);
count=8'd255; //number of data to read
while(count!=0)
begin
@(posedge mcf_wire)
uc_read_i2c(read_out,I2C_MBDR_ADDR); //read data from MBDR
data_in_uc=read_out;
$display("data out: %d",read_out);
if (count==2) begin
txak=1'b1;//reset txak in MBCR to make master generate a zero ack
uc_write_i2c(I2C_MBCR_ADDR,`mbcr);
end
count=count-1;
end
@(posedge mcf_wire);
msta=1'b0;//reset MSTA in MBCR to Generate stop
uc_write_i2c(I2C_MBCR_ADDR,`mbcr);
end
endtask
//*********** write data to EEPROM ****************
task current_write_eeprom;
begin
`mbcr=8'b0;
men=1'b1;
mbb=1'b1;
txak=1'b0; //ack
uc_write_i2c(I2C_MBCR_ADDR,`mbcr); //enable I2C
while(mbb==1) // =1, bus busy
begin
uc_read_i2c(read_out,I2C_MBSR_ADDR);
`mbsr=read_out;
end
uc_write_i2c(I2C_MBDR_ADDR,{EEPROM_Address,1'b0}); //write i2c header in MBDR; 1'b0 means master write data
mtx=1; //necessary
msta=1; //Set MSTA in MBCR to Generate START
uc_write_i2c(I2C_MBCR_ADDR,`mbcr);
@(posedge mcf_wire);
for(count=255;count>=1;count=count-1)
begin
@(posedge mcf_wire)
uc_write_i2c(I2C_MBDR_ADDR,count); //write data to MBDR
$display("tb: write data: %d",count);
end
@(posedge mcf_wire);
msta=1'b0;//reset MSTA in MBCR to Generate stop
uc_write_i2c(I2C_MBCR_ADDR,`mbcr);
end
endtask
task uc_write_i2c;
input [23:0] addr;
input [7:0] data;
begin
@(negedge clk)
r_w=1'b0;
addr_bus=addr;
as=1'b0;
data_bus=data;
ds=1'b0;
data_bus_drive=1;
@(negedge dtack)
as=1'b1;
ds=1'b1;
data_bus=8'hzz;
r_w=1'b1; //reset the r_w line
data_bus_drive=0;
#1000; //2clk, wait for uc_interface to transit to idle state
end
endtask
task uc_read_i2c;
output [7:0] data;
input [23:0] addr;
begin
@(negedge clk) //write i2c header in MBDR
r_w=1'b1;
addr_bus=addr;
as=1'b0;
ds=1'b0; //wait for state transition from addr to data_trs
data_bus_drive=1'b0;
@(negedge dtack)
as=1'b1;
ds=1'b1;
data=data_bus_tri;
#1000 ; //2clk, wait for uc_interface to transite to idle state
end
endtask
i2c my_i2c(
//-- I2C bus signals
.sda(sda), //: inout std_logic;
.scl(scl), //: inout std_logic;
//-- uC interface signals
.addr_bus(addr_bus), //: in std_logic_vector(23 downto 0);
.data_bus(data_bus_tri), //: inout std_logic_vector(7 downto 0);
.as(as) , //: in std_logic; -- address strobe, active low
.ds(ds), //: in std_logic; -- data strobe, active low
.r_w(r_w), //: in std_logic; -- read/write
.dtack(dtack), //: out std_logic; -- data transfer acknowledge
.irq(irq), //: out std_logic; -- interrupt request
.mcf(mcf_wire), //: inout std_logic; -- temporary output for testing
//-- clock and reset
.clk(clk), //: in std_logic;
.reset(reset) //: in std_logic
);
AT24C02 eeprom(
.sda(sda),
.scl(scl),
.wp(1'b0));
pullup pullup_sda(sda);
pullup pullup_scl(scl);
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -