在FPGA开发中,I2C总线是最常用的低速外设控制接口之一。这次我们要在DE10-Nano开发板上实现一个HDMI方块移动的案例,其中关键一环就是通过I2C总线配置HDMI芯片ADV7513。为了确保I2C控制器的可靠性,我们决定先用ModelSim进行功能仿真。
ModelSim作为业界标准的HDL仿真工具,能让我们在实际烧录FPGA前,验证I2C_Controller模块的逻辑正确性。这个案例中,我们将模拟FPGA向I2C外设发送24'h729803数据的过程,并观察I2C总线的时序是否符合协议规范。
首先需要获取HDMI_block_move工程文件(下载链接见原文)。用Quartus Prime打开工程后,建议先检查以下几点:
提示:如果使用Lite版Quartus,可能需要单独安装ModelSim-Altera Starter Edition。完整版通常已包含该组件。
在工程目录下新建Verilog测试文件:
测试代码中的几个关键点需要注意:
ModelSim路径配置不当是导致仿真失败的常见原因。具体设置步骤:
常见问题:如果路径中包含空格或特殊字符,可能导致调用失败。建议安装在简单路径下。
在Assignments → Settings中需要特别注意以下设置:
在Simulation选项卡:
在Test Benches对话框中:
开始仿真前必须执行:
经验:如果仿真无法启动,先检查Quartus控制台是否有错误信息。常见问题包括路径包含中文、权限不足等。
仿真成功后,重点关注以下信号:
| 信号名称 | 预期行为 | 检查要点 |
|---|---|---|
| CLOCK | 100MHz方波 | 周期是否为10ns |
| I2C_SCLK | ~100kHz时钟 | 是否符合I2C标准模式 |
| I2C_SDAT | 数据/应答波形 | 起始条件、数据位、应答位是否规范 |
| GO | 单周期脉冲 | 是否成功触发传输 |
| END | 传输结束标志 | 数据发送完成后是否拉高 |
放大观察数据传输阶段(示例数据24'h729803):
可能原因及解决方案:
ModelSim路径错误:
License问题:
测试文件未添加:
常见波形问题及对策:
SCLK无输出:
SDA一直为高:
数据错位:
在testbench中插入$display语句,实时监控状态变化:
verilog复制always @(posedge CLOCK) begin
if(uut.ST == 2)
$display("Time=%t: State=2, SDA=%b", $time, I2C_SDAT);
// 其他状态监控...
end
修改testbench实现多组数据测试:
verilog复制// 定义测试数据集
reg [23:0] test_data [0:2];
initial begin
test_data[0] = 24'h729803;
test_data[1] = 24'h724105;
test_data[2] = 24'h72FF00;
// 循环测试
for(int i=0; i<3; i++) begin
I2C_DATA = test_data[i];
GO = 1; #10 GO = 0;
wait(END); #100;
end
$stop;
end
添加时序检查语句,确保符合I2C规范:
verilog复制// 检查起始条件
always @(negedge I2C_SDAT) begin
if(I2C_SCLK) begin
$display("Start condition met at %t", $time);
end
end
// 检查建立/保持时间
always @(posedge I2C_SCLK) begin
#1; // 检查建立时间
if($past(I2C_SDAT,1) !== I2C_SDAT) begin
$display("SDA changed near SCLK rising edge at %t", $time);
end
end
版本控制:
持续集成:
文档记录:
性能优化:
在实际项目中,完善的仿真验证可以节省大量调试时间。通过这个I2C控制器的仿真案例,我们不仅验证了基本功能,还建立了一套可复用的验证方法。当需要修改I2C控制器时,只需运行这个testbench就能快速验证改动是否影响了原有功能。