如何使用Modelsim仿真I2C控制器

博主:旭日财富者旭日财富者 2026-01-11 3402

ModelSim是Model Technology(Mentor Graphics的子公司)的HDL硬件描述语言的仿真软件。该软件可以用来实现对设计的VHDL、Verilog HDL 或是两种语言混合的程序进行仿真。这里的仿真是对设计进行功能仿真(也称之为前仿真),其目的是验证电路功能是否符合设计要求。

本篇主要是对I2C_Controller模块进行功能仿真。test_bench的核心是模拟FPGA给出数据24'h729803,同时也模拟I2C外设来接收该数据并给出应答反馈。

505e9206-eb67-11f0-92de-92fbcf53809c.png

1. 首先用Quartus打开HDMI_block_move工程(HDMI_block_move工程下载链接:https://pan.baidu.com/s/1XxFFj-3UTfB_Er-yz0f_Cg提取码: tera),然后在该工程路径下新建一个Verilog test bench仿真文件。右击File——New, 选择Verilog HDL File,然后点击OK:

2. 将下面代码拷贝到新建的.v文件当中:

`timescale 1ns/1ps


module tb_I2C_Controller();
 // 输出信号定义
 regCLOCK;
 reg [23:0]I2C_DATA;
 regGO;
 regRESET;


// 双向信号定义(I2C_SDAT需要上拉电阻模拟总线特性)
 wireI2C_SDAT;
 reg sdat_drive; // 用于模拟从机应答的驱动信号


// 输入信号定义
 wireI2C_SCLK;
 wireEND;
 wireACK;


// 上拉电阻模拟(I2C总线默认高电平)
 assignI2C_SDAT=sdat_drive?1'bz :1'b0;


// 例化被测试模块
I2C_Controlleruut (
 .CLOCK(CLOCK),
 .I2C_DATA(I2C_DATA),
 .GO(GO),
 .RESET(RESET),
 .I2C_SDAT(I2C_SDAT),
 .I2C_SCLK(I2C_SCLK),
 .END(END),
 .ACK(ACK)
);


reg [7:0] cnt_I2Cclk;  
// 时钟生成(100MHz,周期10ns)
initial begin
CLOCK=0;
 forever #5CLOCK=~CLOCK;
end


// 主仿真过程
initial begin
// 初始化信号
I2C_DATA=24'h729803; // 待写入的目标数据
GO=0;
RESET=0;
 sdat_drive=1; // 初始释放总线(上拉为高)


// 复位过程
 #20RESET=1; // 20ns后释放复位


// 等待模块进入空闲状态
 #50;


// 启动I2C写入过程
GO=1;
 #10GO=0;   // 提供一个时钟周期的GO脉冲
 cnt_I2Cclk=0;   
// 模拟从机应答(在每个字节传输的第9个时钟周期拉低SDA)
// 监控时钟线,在需要应答时拉低SDA
 forever @(negedgeI2C_SCLK) begin
  cnt_I2Cclk<= cnt_I2Cclk +1 ;
    if (cnt_I2Cclk == 29) begin
      $stop;
    end
    if (uut.CNT == 8) begin  // 第9位传输时
      sdat_drive = 0;  // 产生应答信号(低电平)
    end 
    else begin
      sdat_drive = 1;  // 其他时间释放总线
    end
  end        
end
endmodule

3. 点击Save按钮,将文件保存为tb_I2C_Controller.v。

4. 安装Quartus软件的时候也记得安装Modelsim 工具(这些安装步骤在后期文章里面会发布),接下来要将Modelsim 的安装路径设置一下就才可以在仿真时自动调用指定的仿真工具。首先是在Tools菜单下面找到Options:

513c3e44-eb67-11f0-92de-92fbcf53809c.png

5. 在弹出的对话框中选择EDA Tool Options ,点击...指定软件路径: D:intelFPGA_lite17.1modelsim_asewin32aloem:

6. 接下来设置仿真文件路径。点击Assignments——Settings:

51f5e86c-eb67-11f0-92de-92fbcf53809c.png

7. 点击 Simulation,仿真工具选择ModelSim-Altera, 然后点选Compile test bench圆圈,点击Test Benches...

5279a6fc-eb67-11f0-92de-92fbcf53809c.png

8. 点击New...

52d8e554-eb67-11f0-92de-92fbcf53809c.png

9. 然后填写Test bench name 名称为tb_I2C_Controller,接着点击File name处对应的...按钮:

533111a2-eb67-11f0-92de-92fbcf53809c.png

10. 选择tb_I2C_Controller.v文件,然后点击Open:

539dd300-eb67-11f0-92de-92fbcf53809c.png

11. 接着点击Add将仿真文件添加到Test Bench,依次点击OK、OK、Apply和 OK退出窗口:

53f9e064-eb67-11f0-92de-92fbcf53809c.png

54574bf0-eb67-11f0-92de-92fbcf53809c.png

54c91c9e-eb67-11f0-92de-92fbcf53809c.png

12. 在仿真之前要先点击Start Analysis&Synthesis按钮进行分析和综合:

5524db42-eb67-11f0-92de-92fbcf53809c.png

13. 再点击Tools——Run Simulation Tool_RTL Simulation进行仿真:

5586c80c-eb67-11f0-92de-92fbcf53809c.png

14. 点击Zoom Full按钮将显示全部波形。

55f96fce-eb67-11f0-92de-92fbcf53809c.png

15. 最后波形生成如下:

5655eeac-eb67-11f0-92de-92fbcf53809c.png

通过波形可以看到,用于触发I2C写操作的GO信号拉高一个时钟周期后,I2C开始写数据的操作。现在要写的数据是24'h729803,二进制是0111_0010_1001_1000_0000_0011, 将波形放大分三段截图将看到如下内容:

56b4aabe-eb67-11f0-92de-92fbcf53809c.png

571e36b4-eb67-11f0-92de-92fbcf53809c.png

5779bc64-eb67-11f0-92de-92fbcf53809c.png

数据发送的状态循环是ST=2 → ST=3 → ST=4 → ST=5 → ST=2,这个循环发送1位数据,共循环9次(8位数据+ACK),第9位(1'b1)是确保在第9个时钟周期主机释放SDA总线。