用AI来写Verilog


预计阅读时间: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 原创,转载请注明出处。