预计阅读时间:3 分钟
这几天突发奇想,如果不会Verilog,AI可不可以帮助我进行硬件的开发?于是我就尝试利用AI写一个I2C的Master的控制器。
我之前尝试直接让AI写一个I2C的控制器,结果生成的代码根本用不了。后来,我尝试了分步给AI指令,让它一步步去完善代码。 这样得到的结果会好很多,但代码很容易变成屎山。
几次尝试之后,发现比较可行的方案是把整个模块的细节描述清楚,放到一个md文件中,让AI用这个文件做为spec去写verilog。p 这样一来,省去了一步步交互的麻烦,代码质量也更好了。
本文就是我之前用来生成I2C控制器的Prompt.
我需要一个I2C控制器模块,该模块可以在10MHz系统时钟下工作,支持连续读写操作。SCL总线频率100KHz 接口定义如下:
module I2C_Controller (
input wire clk_10MHz,
input wire rst_n,
input wire [1:0] cmd,
input wire en,
input wire [7:0] wr_data,
output reg [7:0] rd_data,
inout wire sda,
output wire scl,
output reg busy
);
CMD命令定义如下:
- cmd[1:0] = 2'b00:发送启动位(CMD_START)
- cmd[1:0] = 2'b01:发送停止位(CMD_STOP)
- cmd[1:0] = 2'b10:发送字节(CMD_WRITE)
- cmd[1:0] = 2'b11:读取字节(CMD_READ)
en是使能信号,高电平有效。保持en高电平一个时钟周期,模块开始执行当前命令。 开始执行命令时,busy被拉高,在执行完当前命令,进入DONE或IDLE状态,busy信号会被拉低。 其它信号的功能和名字一致,这里不做详细说明。
接下来是状态机的状态定义:
- S_IDLE:空闲状态
- S_START:发送启动位状态
- S_READ:读取字节状态
- S_WRITE:发送字节状态
- S_STOP:发送停止位状态
- S_DONE:完成状态
-
IDLE状态:
- 在IDLE状态下,SDA释放,为Z, SCL为高电平
- IDLE状态只能接受CMD_START命令,其他命令会被忽略
-
DONE状态:
- 在DONE状态下,SDA, SCL都为低电平
- DONE状态下可以接受CMD_STOP, CMD_WRITE, CMD_READ命令
-
START状态:
- 在START状态下,先将SDA拉低,保留半个SCL周期
- 再将SCL拉低,保留半个SCL周期
- 发送启动位完成后,进入DONE状态
-
STOP状态:
- 在STOP状态下,先将SCL拉高,保留半个SCL周期
- 再将SDA拉高,保留半个SCL周期
- 发送停止位完成后,进入IDLE状态
-
READ状态:
- 暂时留空,后续再实现
-
WRITE状态:
- 包含9个SCL周期,每个SCL周期,前半个低电平,后半个高电平。
- 先发送8bit数据。
- 发送数据时,在SCL低电平周期开始延后后5个系统时钟周期改变SDA.
- 在第九个周期SCL低电平延后5个系统周期时释放SDA,等待下位机发送ACK位
- 第九个SCL周期结束后,SCL拉低,延后5个系统周期把SDA拉低。保持半个SCL周期后期进入Done状态。
本文由 tengda 原创,转载请注明出处。