●リスト1 全体のシーケンスを制御するモジュール(udp_state.v)

// UDP  EFINIX Trion Ti180 M484 Development Kit
// @shibatchii  2024/06/30
`timescale 1ns/1ps
module udp_state(
  clk,          nrst,      i_ready,      i_i2c_end,
  i_pkt_end,    i_tx_end,  o_i2c_start,  o_pkt_start,
  o_tx_start
);
  parameter P_1S = 28'd125000000;
  parameter P_IDLE      = 3'd0;
  parameter P_I2CSTART  = 3'd1;
  parameter P_I2CEND    = 3'd2;
  parameter P_PKTSTART  = 3'd3;
  parameter P_PKTEND    = 3'd4;
  parameter P_TXSTART   = 3'd5;
  parameter P_TXEND     = 3'd6;
  parameter P_WAIT1S    = 3'd7;

  input         clk;
  input         nrst;
  input         i_ready;
  input         i_i2c_end;
  input         i_pkt_end;
  input         i_tx_end;
  output        o_i2c_start;
  output        o_pkt_start;
  output        o_tx_start;
  reg   [ 2:0]  r_state;
  reg   [ 2:0]  w_state;
  reg   [27:0]  r_cnt_wait;
  reg           r_i2c_start;
  reg           r_pkt_start;
  reg           r_tx_start;
  reg   [3:0]   r_tx_end;

  always @( posedge clk or negedge nrst)begin
    if(nrst == 1'b0) begin
      r_tx_end[3:0] <= 4'd0;
    end else begin
      r_tx_end[2:0] <= {r_tx_end[1:0],i_tx_end};
      r_tx_end[  3] <= ~r_tx_end[2] & r_tx_end[1];
    end
  end

  always @(posedge clk or negedge nrst)begin
    if(nrst == 1'b0)begin
      r_state <= P_IDLE;
    end else begin
      r_state <= w_state;
    end
  end

  always @(r_state or i_ready or i_i2c_end or 
i_pkt_end or r_tx_end or r_cnt_wait)begin
    case(r_state)
      P_IDLE:
        if(i_ready==1'b1)
          w_state = P_I2CSTART;
        else
          w_state = r_state;
      P_I2CSTART:
          w_state = P_I2CEND;
      P_I2CEND:
        if(i_i2c_end==1'b1)
          w_state = P_PKTSTART;
        else
          w_state = r_state;
      P_PKTSTART:
          w_state = P_PKTEND;
      P_PKTEND:
        if(i_pkt_end)
          w_state = P_TXSTART;
        else
          w_state = r_state;
      P_TXSTART:
          w_state = P_TXEND;
      P_TXEND:
        if(r_tx_end)
          w_state = P_WAIT1S;
        else
          w_state = r_state;
      P_WAIT1S:
        if(r_cnt_wait==P_1S)
          w_state = P_IDLE;
        else
          w_state = r_state;
      default:
        w_state = P_IDLE;
    endcase
  end

  always @(posedge clk or negedge nrst)begin
    if(nrst == 1'b0)begin
      r_cnt_wait <= 28'd0;
    end else begin
      case(r_state)
        P_WAIT1S:
          r_cnt_wait <= r_cnt_wait + 28'd1;
        default:
          r_cnt_wait <= 28'd0;
      endcase
    end
  end

  always @(posedge clk or negedge nrst)begin
    if(nrst == 1'b0)begin
      r_i2c_start <= 1'b0;
    end else begin
      case(r_state)
        P_I2CSTART:
          r_i2c_start <= 1'b1;
        default:
      r_i2c_start <= 1'b0;
      endcase
    end
  end

  assign o_i2c_start = r_i2c_start;

  always @(posedge clk or negedge nrst)begin
    if(nrst == 1'b0)begin
      r_pkt_start <= 1'b0;
    end else begin
      case(r_state)
        P_PKTSTART:
          r_pkt_start <= 1'b1;
        default:
      r_pkt_start <= 1'b0;
      endcase
    end
  end

  assign o_pkt_start = r_pkt_start;

  always @(posedge clk or negedge nrst)begin
    if(nrst == 1'b0)begin
      r_tx_start <= 1'b0;
    end else begin
      case(r_state)
        P_TXSTART:
          r_tx_start <= 1'b1;
        default:
      r_tx_start <= 1'b0;
      endcase
    end
  end

  assign o_tx_start = r_tx_start;

endmodule

●リスト2 I2CのIPを制御してセンサ・データを取り込む(udp_i2c_cnt.v)

// UDP  EFINIX Trion Ti180 M484 Development Kit
// @shibatchii  2024/06/30
`timescale 1ns/1ps

module udp_i2c_cnt(
  arstn, i2c_clk, i_i2c_start, o_i2c_end,
  o_data_tmp_dec, mst_scl_in, mst_sda_in, 
  mst_scl_out, mst_sda_out, mst_sda_oe, mst_scl_oe
);
  parameter P_I2CIDL = 3'd0;
  parameter P_I2CRD  = 3'd1;
  parameter P_I2CRD0 = 3'd2;
  parameter P_I2CRD1 = 3'd3;
  parameter P_I2CPKW = 3'd4;
  parameter P_ASCII  = 8'h30;

  input         arstn;  // 非同期リセット
  input         i2c_clk;
  input         i_i2c_start;
  output        o_i2c_end;
  output [15:0] o_data_tmp_dec;
  input         mst_scl_in;
  input         mst_sda_in;
  output        mst_scl_out;
  output        mst_sda_out;
  output        mst_sda_oe;
  output        mst_scl_oe;

  wire          mst_scl_in;
  wire          mst_sda_in;
  wire          mst_scl_out;
  wire          mst_sda_out;
  wire          mst_sda_oe;
  wire          mst_scl_oe;
  wire          i2c_busy;
  wire          i2c_soft_rst;
  wire          i2c_rxak;
  wire          i2c_arb_lost;
  wire          i2c_arb_lost_clr;
  wire  [ 7:0]  i2c_slave_addr;
  wire  [ 7:0]  mst_command_byte;
  wire  [ 7:0]  mst_num_bytes;
  wire          mst_data_out_valid;
  wire          mst_read;
  wire          mst_write;
  wire  [ 7:0]  mst_data_out;
  wire  [ 7:0]  mst_din;
  wire          mst_write_done;
  wire          rst;
  reg   [ 2:0]  r_state;
  reg   [ 2:0]  w_state;
  reg   [15:0]  r_odata;
  reg           r_mst_read;
  reg           r_i2c_end;
  wire  [ 8:0]  w_tmph;
  wire  [13:0]  w_tmpl;
  wire  [15:0]  w_data_tmp_dec;
  reg   [15:0]  r_data_tmp_dec;

  assign rst              = ~arstn;
  assign i2c_soft_rst     = 1'b0;
  assign i2c_arb_lost_clr = 1'b0;
  assign i2c_slave_addr   = 8'h96;
  assign mst_command_byte = 8'h00;
  assign mst_din          = 8'h00;
  assign mst_num_bytes    = 8'd3;
  assign mst_write        = 1'b0;

  always @(posedge i2c_clk or negedge arstn)begin
    if(arstn == 1'b0)begin
      r_state <= P_I2CIDL;
    end else begin
      r_state <= w_state;
    end
  end

  always @(r_state or i_i2c_start or mst_data_out_valid) begin
    case(r_state)
      P_I2CIDL:
        if(i_i2c_start==1'b1)
          w_state = P_I2CRD;
        else
          w_state = r_state;
      P_I2CRD:
        w_state = P_I2CRD0;
      P_I2CRD0:
        if(mst_data_out_valid==1'b1)
          w_state = P_I2CRD1;
        else
          w_state = r_state;
      P_I2CRD1:
        if(mst_data_out_valid==1'b1)
          w_state = P_I2CPKW;
        else
          w_state = r_state;
      P_I2CPKW:
        w_state = P_I2CIDL;
      default:
        w_state = P_I2CIDL;
    endcase
  end

  always @(posedge i2c_clk or negedge arstn)begin
    if(arstn == 1'b0)begin
      r_mst_read <= 1'd0;
    end else begin
      case(r_state)
        P_I2CRD:
          r_mst_read <= 1'b1;
        default:
          r_mst_read <= 1'b0;
      endcase
    end
  end

  assign mst_read      = r_mst_read;

  udp_i2c udp_i2c(
    .clk                ( i2c_clk             ), // I
    .rst                ( rst                 ), // I
    .mst_scl_in         ( mst_scl_in          ), // I
    .mst_sda_in         ( mst_sda_in          ), // I
    .mst_scl_out        ( mst_scl_out         ), // O
    .mst_sda_out        ( mst_sda_out         ), // O
    .mst_sda_oe         ( mst_sda_oe          ), // O
    .mst_scl_oe         ( mst_scl_oe          ), // O
    .i2c_busy           ( i2c_busy            ), // O
    .i2c_soft_rst       ( i2c_soft_rst        ), // I
    .i2c_rxak           ( i2c_rxak            ), // O
    .i2c_arb_lost       ( i2c_arb_lost        ), // O
    .i2c_arb_lost_clr   ( i2c_arb_lost_clr    ), // I
    .i2c_slave_addr     ( i2c_slave_addr      ), // I
    .mst_command_byte   ( mst_command_byte    ), // I
    .mst_num_bytes      ( mst_num_bytes       ), // I
    .mst_read           ( mst_read            ), // I
    .mst_write          ( mst_write           ), // I
    .mst_write_done     ( mst_write_done      ), // O
    .mst_data_out_valid ( mst_data_out_valid  ), // O
    .mst_data_out       ( mst_data_out        ), // O
    .mst_din            ( mst_din             )  // I
  );

  always @(posedge i2c_clk or negedge arstn)begin
    if(arstn == 1'b0)begin
      r_odata <= 16'd0;
    end else begin
      case(r_state)
        P_I2CRD0:
          if(mst_data_out_valid)
            r_odata[15: 8] <= mst_data_out;
        P_I2CRD1:

コメントを残す