设为首页收藏本站淘宝杂货铺

从F到0 - From F to 0

 找回密码
 注册已关闭
搜索
查看: 166|回复: 1
收起左侧

Quartus Verilog HDL/FPGA I2C协议实现读写 AT24C02 串行256字节可编程EEPROM存储芯片

[复制链接]
发表于 2023-7-12 09:03:37 | 显示全部楼层 |阅读模式
main.png
  1. module i2c_at24cxx(                        //AT24Cxx I2C模块
  2.         input clk,                                        //50Mhz 时钟输入
  3.         input [1:0] cmd,                        //[2位宽] I2C命令 0:I2C开始 1:I2C停止 2:I2C读 3:I2C写
  4.         input call,                                        //上升沿执行命令
  5.         input [7:0] wb,                        //[8位宽] I2C写数据
  6.         output reg [7:0] rb,                //[8位宽] I2C读数据
  7.         output reg ret,                        //命令执行完毕 发出上升沿
  8.         output reg err,                        //ACK应答超时 发出上升沿
  9.         inout sda,                                        //[双向IO] 接24Cxx SDA脚
  10.         output reg scl                        //接24Cxx SCL脚       
  11. );

  12. reg rw = 1'b1;                        //SDA读写 1:输出 0:输入
  13. reg dat = 1'b1;                //SDA写数据
  14. initial begin
  15.         scl = 1'b1;
  16.         err = 1'b0;
  17. end
  18. assign sda = rw ? dat : 1'bz;
  19. reg [4:0] state = 5'd0;
  20. reg [7:0] delay = 8'd0;
  21. wire [7:0] dclk = 8'd255;
  22. reg [15:0] timeout = 16'd0;
  23. reg [2:0] pc = 3'd0;
  24. reg [7:0] w = 8'd0;

  25. always @(posedge clk) begin
  26.         if(|delay) begin                        //延时
  27.                 delay <= delay - 8'd1;
  28.         end else begin
  29.                 case(state)
  30.                         5'd0:begin
  31.                                 err <= 1'b0;
  32.                                 rw <= 1'b1;
  33.                                 dat <= 1'b1;
  34.                                 scl <= 1'b1;
  35.                                 ret <= 1'b0;
  36.                                 pc <= 3'd0;
  37.                                 if(call) begin
  38.                                         state <= {3'd0,cmd} + 5'd1;
  39.                                 end else begin
  40.                                         state <= 5'd0;
  41.                                 end
  42.                         end
  43.                        
  44.                         5'd1:begin                //I2C开始
  45.                                 rw <= 1'b1;                //SDA输出
  46.                                 dat <= 1'b1;        //SDA=1
  47.                                 scl <= 1'b1;        //SCL=1
  48.                                 delay <= dclk;        //I2C_Delay();
  49.                                 state <= 5'd5;
  50.                         end
  51.                        
  52.                         5'd2:begin                //I2C停止
  53.                                 rw <= 1'b1;                //SDA输出
  54.                                 dat <= 1'b0;
  55.                                 scl <= 1'b0;
  56.                                 delay <= dclk;
  57.                                 state <= 5'd8;
  58.                         end
  59.                        
  60.                         5'd3:begin                //I2C读
  61.                                 rw <= 1'b1;                //SDA输出
  62.                                 rb <= 8'd0;
  63.                                 scl <= 1'b0;                //SCL=0
  64.                                 delay <= dclk;
  65.                                 state <= 5'd10;
  66.                         end
  67.                        
  68.                         5'd4:begin                //I2C写
  69.                                 rw <= 1'b1;                //SDA输出
  70.                                 w <= wb;
  71.                                 state <= 5'd14;
  72.                         end
  73.                        
  74.                         5'd5:begin
  75.                                 dat <= 1'b0;
  76.                                 delay <= dclk;
  77.                                 state <= 5'd6;
  78.                         end
  79.                        
  80.                         5'd6:begin
  81.                                 scl <= 1'b0;
  82.                                 delay <= dclk;
  83.                                 state <= 5'd7;
  84.                         end
  85.                        
  86.                         5'd7:begin                //返回
  87.                                 ret <= 1'b1;
  88.                                 state <= call ? 5'd7 : 5'd0;
  89.                         end
  90.                        
  91.                         5'd8:begin
  92.                                 scl <= 1'b1;
  93.                                 delay <= dclk;
  94.                                 state <= 5'd9;
  95.                         end
  96.                        
  97.                         5'd9:begin
  98.                                 dat <= 1'b1;
  99.                                 state <= 5'd7;
  100.                         end
  101.                        
  102.                         5'd10:begin
  103.                                 dat <= 1'b1;        //SDA=1
  104.                                 delay <= dclk;
  105.                                 state <= 5'd11;
  106.                         end
  107.                        
  108.                         5'd11:begin                //读 do
  109.                                 rw <= 1'b0;                //SDA输入
  110.                                 scl <= 1'b1;
  111.                                 delay <= dclk;
  112.                                 state <= 5'd12;
  113.                         end
  114.                        
  115.                         5'd12:begin
  116.                                 rb[~pc] = sda;
  117.                                 state <= 5'd13;
  118.                         end
  119.                        
  120.                         5'd13:begin
  121.                                 scl <= 1'b0;
  122.                                 delay <= dclk;
  123.                                 if(&pc) begin
  124.                                         state <= 5'd7;
  125.                                 end else begin
  126.                                         state <= 5'd11;
  127.                                 end
  128.                                 pc <= pc + 3'd1;
  129.                         end
  130.                        
  131.                         5'd14:begin                //写 do
  132.                                 scl <= 1'b0;
  133.                                 delay <= dclk;
  134.                                 state <= 5'd15;
  135.                         end
  136.                        
  137.                         5'd15:begin
  138.                                 dat <= w[~pc];
  139.                                 delay <= dclk;
  140.                                 state <= 5'd16;
  141.                         end
  142.                        
  143.                         5'd16:begin
  144.                                 scl <= 1'b1;
  145.                                 delay <= dclk;
  146.                                 if(&pc) begin
  147.                                         state <= 5'd17;
  148.                                 end else begin
  149.                                         state <= 5'd14;
  150.                                 end
  151.                                 pc <= pc + 3'd1;
  152.                         end
  153.                        
  154.                         5'd17:begin
  155.                                 scl <= 1'b0;
  156.                                 delay <= dclk;
  157.                                 state <= 5'd18;
  158.                         end
  159.                        
  160.                         5'd18:begin
  161.                                 dat <= 1'b1;
  162.                                 delay <= dclk;
  163.                                 state <= 5'd19;
  164.                         end
  165.                        
  166.                         5'd19:begin                //ACK
  167.                                 rw <= 1'b0;                //SDA输入
  168.                                 scl <= 1'b1;
  169.                                 delay <= dclk;
  170.                                 timeout <= 16'd0;
  171.                                 state <= 5'd20;
  172.                         end
  173.                        
  174.                         5'd20:begin
  175.                                 if(sda) begin                //等待ACK应答
  176.                                         if(&timeout) begin                //应答超时
  177.                                                 err <= 1'b1;
  178.                                                 state <= 5'd21;
  179.                                         end else begin
  180.                                                 state <= 5'd20;       
  181.                                                 timeout <= timeout + 16'd1;       
  182.                                         end
  183.                                 end else begin
  184.                                         state <= 5'd21;
  185.                                 end
  186.                         end
  187.                        
  188.                         5'd21:begin
  189.                                 scl <= 1'b0;
  190.                                 delay <= dclk;
  191.                                 state <= 5'd7;
  192.                         end
  193.                        
  194.                         default:state <= 5'd0;
  195.                 endcase
  196.         end
  197. end
  198. endmodule

  199. module at24c02(
  200.         input clk,                                //50Mhz 时钟输入
  201.         input rw,                                //高电平:读 低电平:写
  202.         input call,                                //上升沿 开始执行操作
  203.         input [7:0] pc,                //[8位宽输入] 地址:0~255
  204.         input [7:0] wb,                //[8位宽输入] 写字节
  205.         output reg [7:0] rb,        //[8位宽输出] 读字节
  206.         output reg ret,                //操作完毕 发出上升沿
  207.         output reg err,                //高电平读写失败,低电平成功
  208.         inout sda,                                //[双向IO] 接24C02 SDA脚
  209.         output scl                                //接24C02 SCL脚
  210. );

  211. initial begin
  212.         rb <= 8'd0;
  213.         ret <= 1'b0;
  214.         err <= 1'b0;
  215. end

  216. reg [7:0] i2c_w;
  217. wire [7:0] i2c_r;
  218. reg [1:0] i2c_cmd;
  219. reg [7:0] w;
  220. reg i2c_call;
  221. wire i2c_ret;
  222. wire i2c_err;
  223. reg [5:0] state = 6'd0;

  224. i2c_at24cxx i2c_at24cxx(
  225.         .clk(!clk),
  226.         .cmd(i2c_cmd),
  227.         .call(i2c_call),
  228.         .wb(i2c_w),
  229.         .rb(i2c_r),
  230.         .ret(i2c_ret),
  231.         .err(i2c_err),
  232.         .sda(sda),
  233.         .scl(scl)
  234. );

  235. reg [17:0] delay = 18'd0;
  236. always @(posedge clk) begin
  237.         if(|delay) begin
  238.                 delay <= delay - 18'd1;
  239.         end else begin
  240.         case(state)
  241.                 6'd0:begin
  242.                         err <= 1'b0;
  243.                         ret <= 1'b0;
  244.                         if(call) begin
  245.                                 state <= rw ? 6'd1 : 6'd2;
  246.                         end else begin
  247.                                 state <= 6'd0;
  248.                         end
  249.                 end
  250.                
  251.                 6'd1:begin                //读
  252.                         i2c_cmd <= 2'd0;
  253.                         state <= 6'd3;
  254.                 end
  255.                
  256.                 6'd2:begin                //写
  257.                         w <= wb;
  258.                         i2c_cmd <= 2'd0;
  259.                         state <= 6'd25;
  260.                 end
  261.                
  262.                 6'd3:begin
  263.                         i2c_call <= 1'b1;
  264.                         state <= 6'd4;
  265.                 end

  266.                 6'd4:begin
  267.                         state <= i2c_ret ? 6'd5 : 6'd4;
  268.                 end
  269.                
  270.                 6'd5:begin
  271.                         i2c_call <= 1'b0;
  272.                         i2c_cmd <= 2'd3;
  273.                         i2c_w <= 8'hA0;
  274.                         state <= 6'd6;
  275.                 end
  276.                
  277.                 6'd6:begin
  278.                         i2c_call <= 1'b1;
  279.                         state <= 6'd7;
  280.                 end

  281.                 6'd7:begin
  282.                         state <= i2c_ret ? 6'd8 : 6'd7;
  283.                 end
  284.                
  285.                 6'd8:begin
  286.                         i2c_call <= 1'b0;
  287.                         i2c_cmd <= 2'd3;
  288.                         i2c_w <= pc;
  289.                         state <= i2c_err ? 6'd41 : 6'd9;
  290.                 end
  291.                
  292.                 6'd9:begin
  293.                         i2c_call <= 1'b1;
  294.                         state <= 6'd10;
  295.                 end

  296.                 6'd10:begin
  297.                         state <= i2c_ret ? 6'd11 : 6'd10;
  298.                 end
  299.                
  300.                 6'd11:begin
  301.                         i2c_call <= 1'b0;
  302.                         i2c_cmd <= 2'd0;
  303.                         state <= i2c_err ? 6'd41 : 6'd12;
  304.                 end
  305.                
  306.                 6'd12:begin
  307.                         i2c_call <= 1'b1;
  308.                         state <= 6'd13;
  309.                 end

  310.                 6'd13:begin
  311.                         state <= i2c_ret ? 6'd14 : 6'd13;
  312.                 end
  313.                
  314.                 6'd14:begin
  315.                         i2c_call <= 1'b0;
  316.                         i2c_cmd <= 2'd3;
  317.                         i2c_w <= 8'hA1;
  318.                         state <= 6'd15;
  319.                 end
  320.                
  321.                 6'd15:begin
  322.                         i2c_call <= 1'b1;
  323.                         state <= 6'd16;
  324.                 end

  325.                 6'd16:begin
  326.                         state <= i2c_ret ? 6'd17 : 6'd16;
  327.                 end
  328.                
  329.                 6'd17:begin
  330.                         i2c_call <= 1'b0;
  331.                         i2c_cmd <= 2'd2;
  332.                         state <= 6'd18;
  333.                 end

  334.                 6'd18:begin
  335.                         i2c_call <= 1'b1;
  336.                         state <= 6'd19;
  337.                 end

  338.                 6'd19:begin
  339.                         state <= i2c_ret ? 6'd20 : 6'd19;
  340.                 end
  341.                
  342.                 6'd20:begin
  343.                         i2c_call <= 1'b0;
  344.                         rb <= i2c_r;
  345.                         i2c_cmd <= 2'd1;
  346.                         state <= 6'd21;
  347.                 end
  348.                
  349.                 6'd21:begin
  350.                         i2c_call <= 1'b1;
  351.                         state <= 6'd22;
  352.                 end

  353.                 6'd22:begin
  354.                         state <= i2c_ret ? 6'd23 : 6'd22;
  355.                 end
  356.                
  357.                 6'd23:begin
  358.                         i2c_call <= 1'b0;
  359.                         state <= 6'd24;
  360.                 end
  361.                
  362.                 6'd24:begin                //返回
  363.                         ret <= 1'b1;
  364.                         state <= call ? 6'd24 : 6'd0;
  365.                 end
  366.                
  367.                 6'd25:begin
  368.                         i2c_call <= 1'b1;
  369.                         state <= 6'd26;
  370.                 end
  371.                
  372.                 6'd26:begin
  373.                         state <= i2c_ret ? 6'd27 : 6'd26;
  374.                 end
  375.                
  376.                 6'd27:begin
  377.                         i2c_call <= 1'b0;
  378.                         i2c_cmd <= 2'd3;
  379.                         i2c_w <= 8'hA0;
  380.                         state <= 6'd28;
  381.                 end
  382.                
  383.                 6'd28:begin
  384.                         i2c_call <= 1'b1;
  385.                         state <= 6'd29;
  386.                 end
  387.                
  388.                 6'd29:begin
  389.                         state <= i2c_ret ? 6'd30 : 6'd29;
  390.                 end
  391.                
  392.                 6'd30:begin
  393.                         i2c_call <= 1'b0;
  394.                         i2c_cmd <= 2'd3;
  395.                         i2c_w <= pc;
  396.                         state <= i2c_err ? 6'd41 : 6'd31;
  397.                 end
  398.                
  399.                 6'd31:begin
  400.                         i2c_call <= 1'b1;
  401.                         state <= 6'd32;               
  402.                 end
  403.                
  404.                 6'd32:begin
  405.                         state <= i2c_ret ? 6'd33 : 6'd32;
  406.                 end
  407.                
  408.                 6'd33:begin
  409.                         i2c_call <= 1'b0;
  410.                         i2c_cmd <= 2'd3;
  411.                         i2c_w <= w;       
  412.                         state <= i2c_err ? 6'd41 : 6'd34;
  413.                 end
  414.                
  415.                 6'd34:begin
  416.                         i2c_call <= 1'b1;
  417.                         state <= 6'd35;
  418.                 end
  419.                
  420.                 6'd35:begin
  421.                         state <= i2c_ret ? 6'd36 : 6'd35;
  422.                 end
  423.                
  424.                 6'd36:begin
  425.                         i2c_call <= 1'b0;
  426.                         i2c_cmd <= 2'd1;
  427.                         state <= i2c_err ? 6'd41 : 6'd37;
  428.                 end
  429.                
  430.                 6'd37:begin
  431.                         i2c_call <= 1'b1;
  432.                         state <= 6'd38;
  433.                 end
  434.                
  435.                 6'd38:begin
  436.                         state <= i2c_ret ? 6'd39 : 6'd38;
  437.                 end
  438.                
  439.                 6'd39:begin
  440.                         i2c_call <= 1'b0;
  441.                         state <= 6'd40;
  442.                 end
  443.                
  444.                 6'd40:begin                                        //写完延时5ms
  445.                         delay <= 18'd250000;               
  446.                         state <= 6'd24;
  447.                 end
  448.                
  449.                 6'd41:begin                                //读写错误
  450.                         err <= 1'b1;
  451.                         state <= 6'd24;
  452.                 end

  453.                 default:begin                        //其他状态
  454.                         state <= 6'd0;
  455.                 end
  456.         endcase
  457.         end
  458. end
  459. endmodule

  460. module main(
  461.         input clk,                        //50Mhz 有源晶振 Pin17
  462.         output reg led,        //LED (低电平点亮) Pin3 闪烁:错误 熄灭:正在读写 点亮:完成
  463.         inout sda,                        //AT24C02 Pin42
  464.         output scl                        //AT24C02 Pin40
  465. );

  466. reg rw = 1'b1;
  467. wire ret;
  468. wire err;
  469. reg call = 1'b0;
  470. reg [7:0] pc = 8'd0;
  471. reg [7:0] wb = 8'd0;
  472. wire [7:0] rb;
  473. reg [3:0] state = 4'd0;
  474. reg [7:0] z;
  475. wire [7:0] b = ~z;
  476. integer i;

  477. at24c02 U1(
  478.         .clk(clk),
  479.         .rw(rw),
  480.         .call(call),
  481.         .pc(pc),
  482.         .wb(wb),
  483.         .rb(rb),
  484.         .ret(ret),
  485.         .err(err),
  486.         .sda(sda),
  487.         .scl(scl)
  488. );

  489. always @(posedge clk) begin
  490.         case(state)
  491.                 4'd0:begin
  492.                         led <= 1'b1;
  493.                         rw <= 1'b0;
  494.                         pc <= z;
  495.                         wb <= b;
  496.                         state <= 4'd1;
  497.                 end
  498.                
  499.                 4'd1:begin
  500.                         call <= 1'b1;
  501.                         state <= 4'd2;
  502.                 end
  503.                        
  504.                        
  505.                 4'd2:begin
  506.                         state <= ret ? 4'd3 : 4'd2;
  507.                 end
  508.                        
  509.                 4'd3:begin
  510.                         call <= 1'b0;
  511.                         state <= err ? 4'd4 : 4'd5;
  512.                 end
  513.                
  514.                 4'd4:begin
  515.                         i = i + 1;
  516.                         if(i >= 50000000/2/8) begin
  517.                                 i = 0;
  518.                                 led <= !led;
  519.                         end
  520.                         state <= 4'd4;
  521.                 end
  522.                
  523.                 4'd5:begin
  524.                         rw <= 1'b1;
  525.                         pc <= z;
  526.                         state <= 4'd6;
  527.                 end
  528.                
  529.                 4'd6:begin
  530.                         call <= 1'b1;
  531.                         state <= 4'd7;
  532.                 end
  533.                
  534.                 4'd7:begin
  535.                         state <= ret ? 4'd8 : 4'd7;
  536.                 end
  537.                
  538.                 4'd8:begin
  539.                         call <= 1'b0;
  540.                         state <= (err || (rb != b)) ? 4'd4 : 4'd9;
  541.                 end
  542.                
  543.                 4'd9:begin
  544.                         if(&z) begin
  545.                                 led <= 1'b0;
  546.                                 state <= 4'd9;
  547.                         end else begin
  548.                                 z <= z + 8'd1;
  549.                                 state <= 4'd0;
  550.                         end
  551.                 end
  552.         endcase
  553. end

  554. endmodule
复制代码

相关帖子

您需要登录后才可以回帖 登录 | 注册已关闭

本版积分规则

QQ|手机版|Archiver|从F到0 ( 蒙ICP备17002595号-1 )
蒙公网安备15010402000325号

腾讯云安全认证

GMT+8, 2024-4-28 21:53 , Processed in 1.491085 second(s), 23 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表