誌面に掲載できなかったリストを掲載します.

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

Verilog
// 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)

Verilog
// 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:

●リスト3 UDPデータの組み立て(udp_tx.v)

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

module udp_tx(
  clk,
  nrst,
  i_pkt_start,
  i_data_tmp_dec,
  o_pkt_end,
  o_pkt_cnt,
  o_wen,
  o_packet
);

  parameter P_SRC_MAC   = 48'h00_00_5e_00_53_02;
  parameter P_SRC_ADDR  = {8'd192,8'd168,8'd001,8'd100};
  parameter P_SRC_PORT  = 16'd3457;
  parameter P_DST_MAC   = 48'h3c_97_0e_be_99_29;
  parameter P_DST_ADDR  = {8'd192,8'd168,8'd001,8'd102};
  parameter P_DST_PORT  = 16'd3456;
  parameter P_TYPE      = 16'h0800;
  parameter P_VERSION   =  4'h4;
  parameter P_HLEN      =  4'h5;
  parameter P_SERVICE   =  8'h00;
  parameter P_PLEN      = 16'h002E;
  parameter P_FLAG      =  3'b000;
  parameter P_FOFFSET   = 14'd0;
  parameter P_TTL       =  8'h80;
  parameter P_PROTOCOL  =  8'h11;
  parameter P_SLEN      = 16'h001A;
  parameter P_ZERO      =  8'h00;
  parameter P_ELEN      =  7'h40; // 64

  input           clk;
  input           nrst;
  input           i_pkt_start;
  input   [15:0]  i_data_tmp_dec;
  output          o_pkt_end;
  output  [ 6:0]  o_pkt_cnt;
  output          o_wen;
  output  [ 7:0]  o_packet;

  logic [ 7:0]  w_pkt [67];
  wire  [15:0]  w_hcsum;
  wire  [15:0]  w_hcsum0;
  wire  [15:0]  w_hcsum1;
  wire  [15:0]  w_hcsum2;
  wire  [15:0]  w_hcsum3;
  wire  [15:0]  w_hcsum01;
  wire  [15:0]  w_hcsum23;
  wire  [15:0]  w_hcsum0123;
  wire  [15:0]  w_hcsum4;
  wire  [15:0]  w_hcsum01234;
  wire  [15:0]  w_csum0;
  wire  [15:0]  w_csum1;
  wire  [15:0]  w_csum2;
  wire  [15:0]  w_csum3;
  wire  [15:0]  w_csum4;
  wire  [15:0]  w_csum5;
  wire  [15:0]  w_csum6;
  wire  [15:0]  w_csum7;
  wire  [15:0]  w_csum8;
  wire  [15:0]  w_csum9;
  wire  [15:0]  w_csum01;
  wire  [15:0]  w_csum23;
  wire  [15:0]  w_csum45;
  wire  [15:0]  w_csum67;
  wire  [15:0]  w_csum89;
  wire  [15:0]  w_csum0123;
  wire  [15:0]  w_csum4567;
  wire  [15:0]  w_csum01234567;
  wire  [15:0]  w_csum0123456789;
  wire  [15:0]  w_csum;
  wire  [31:0]  w_crc;
  reg   [15:0]  r_ident;
  reg   [ 6:0]  r_cnt_wfifo;
  reg           r_flg;
  reg           r_flg_d;
  reg           r_crcflg;
  wire  [ 7:0]  w_packet;
  reg   [ 7:0]  r_packet;
  reg           r_pkt_end;
  reg           r_pkt_end_tx0;
  reg           r_pkt_end_tx1;
  reg           r_pkt_end_tx2;
  reg           r_pkt_end_tx;

  assign w_pkt[ 0] = P_DST_MAC[47:40];
  assign w_pkt[ 1] = P_DST_MAC[39:32];
  assign w_pkt[ 2] = P_DST_MAC[31:24];
  assign w_pkt[ 3] = P_DST_MAC[23:16];
  assign w_pkt[ 4] = P_DST_MAC[15: 8];
  assign w_pkt[ 5] = P_DST_MAC[ 7: 0];

  assign w_pkt[ 6] = P_SRC_MAC[47:40];
  assign w_pkt[ 7] = P_SRC_MAC[39:32];
  assign w_pkt[ 8] = P_SRC_MAC[31:24];
  assign w_pkt[ 9] = P_SRC_MAC[23:16];
  assign w_pkt[10] = P_SRC_MAC[15: 8];
  assign w_pkt[11] = P_SRC_MAC[ 7: 0];

  assign w_pkt[12] = P_TYPE[15: 8];
  assign w_pkt[13] = P_TYPE[ 7: 0];

  assign w_pkt[14] = {P_VERSION,P_HLEN};
  assign w_pkt[15] = P_SERVICE;
  assign w_pkt[16] = P_PLEN[15: 8];
  assign w_pkt[17] = P_PLEN[ 7: 0];
  assign w_pkt[18] = r_ident[15: 8];
  assign w_pkt[19] = r_ident[ 7: 0];
  assign w_pkt[20] = {P_FLAG,P_FOFFSET[12:8]};
  assign w_pkt[21] = P_FOFFSET[7:0];
  assign w_pkt[22] = P_TTL;
  assign w_pkt[23] = P_PROTOCOL;
  assign w_pkt[24] = w_hcsum[15: 8];
  assign w_pkt[25] = w_hcsum[ 7: 0];
  assign w_pkt[26] = P_SRC_ADDR[31:24];
  assign w_pkt[27] = P_SRC_ADDR[23:16];
  assign w_pkt[28] = P_SRC_ADDR[15: 8];
  assign w_pkt[29] = P_SRC_ADDR[ 7: 0];
  assign w_pkt[30] = P_DST_ADDR[31:24];
  assign w_pkt[31] = P_DST_ADDR[23:16];
  assign w_pkt[32] = P_DST_ADDR[15: 8];
  assign w_pkt[33] = P_DST_ADDR[ 7: 0];

  assign w_pkt[34] = P_SRC_PORT[15: 8];
  assign w_pkt[35] = P_SRC_PORT[ 7: 0];
  assign w_pkt[36] = P_DST_PORT[15: 8];
  assign w_pkt[37] = P_DST_PORT[ 7: 0];
  assign w_pkt[38] = P_SLEN[15: 8];
  assign w_pkt[39] = P_SLEN[ 7: 0];
  assign w_pkt[40] = w_csum[15: 8];
  assign w_pkt[41] = w_csum[ 7: 0];

  assign w_pkt[42] = 8'h54; // T
  assign w_pkt[43] = 8'h65; // e
  assign w_pkt[44] = 8'h6D; // m
  assign w_pkt[45] = 8'h70; // p
  assign w_pkt[46] = 8'h65; // e
  assign w_pkt[47] = 8'h72; // r
  assign w_pkt[48] = 8'h61; // a
  assign w_pkt[49] = 8'h74; // t
  assign w_pkt[50] = 8'h75; // u
  assign w_pkt[51] = 8'h72; // r
  assign w_pkt[52] = 8'h65; // e
  assign w_pkt[53] = 8'h20; // SP
  assign w_pkt[54] = 8'h3D; // =
  assign w_pkt[55] = 8'h20; // SP
  assign w_pkt[56] = i_data_tmp_dec[15: 8];
  assign w_pkt[57] = i_data_tmp_dec[ 7: 0];
  assign w_pkt[58] = 8'h0D; // CR
  assign w_pkt[59] = 8'h0A; // LF

  assign w_pkt[60] = frev(w_crc[31:24]);
  assign w_pkt[61] = frev(w_crc[23:16]);
  assign w_pkt[62] = frev(w_crc[15: 8]);
  assign w_pkt[63] = frev(w_crc[ 7: 0]);
  assign w_pkt[64] = P_ZERO;

  always @(posedge clk or negedge nrst)begin
    if(nrst==1'b0)
      r_ident <= 16'd0;
    else
      if(r_pkt_end_tx)
        r_ident <= r_ident + 16'd1;
      else
        r_ident <= r_ident;
  end

  function [15:0] fsum(input [15:0] data0,input [15:0] data1); 
    reg [16:0] w_sum;
  begin
    w_sum = {1'b0,data0} + {1'b0,data1};
    if(w_sum[16]==1'b1) return (w_sum[15:0] + 16'd1);
    else return (w_sum[15:0]);
  end
  endfunction

  assign w_hcsum0 = fsum({w_pkt[14],w_pkt[15]},{w_pkt[16],w_pkt[17]});
  assign w_hcsum1 = fsum({w_pkt[18],w_pkt[19]},{w_pkt[20],w_pkt[21]});
  assign w_hcsum2 = fsum({w_pkt[22],w_pkt[23]},{P_ZERO   ,P_ZERO   });
  assign w_hcsum3 = fsum({w_pkt[26],w_pkt[27]},{w_pkt[28],w_pkt[29]});
  assign w_hcsum4 = fsum({w_pkt[30],w_pkt[31]},{w_pkt[32],w_pkt[33]});
  assign w_hcsum01  = fsum(w_hcsum0,w_hcsum1);
  assign w_hcsum23  = fsum(w_hcsum2,w_hcsum3);
  assign w_hcsum0123  = fsum(w_hcsum01,w_hcsum23);
  assign w_hcsum01234 = fsum(w_hcsum0123,w_hcsum4);
  assign w_hcsum  = ~(w_hcsum01234);

  assign w_csum0 = fsum({w_pkt[26],w_pkt[27]},{w_pkt[28],w_pkt[29]});
  assign w_csum1 = fsum({w_pkt[30],w_pkt[31]},{w_pkt[32],w_pkt[33]});
  assign w_csum2 = fsum({P_ZERO   ,w_pkt[23]},{w_pkt[38],w_pkt[39]});
  assign w_csum3 = fsum({w_pkt[34],w_pkt[35]},{w_pkt[36],w_pkt[37]});
  assign w_csum4 = fsum({w_pkt[38],w_pkt[39]},{P_ZERO   ,P_ZERO   });
  assign w_csum5 = fsum({w_pkt[42],w_pkt[43]},{w_pkt[44],w_pkt[45]});
  assign w_csum6 = fsum({w_pkt[46],w_pkt[47]},{w_pkt[48],w_pkt[49]});
  assign w_csum7 = fsum({w_pkt[50],w_pkt[51]},{w_pkt[52],w_pkt[53]});
  assign w_csum8 = fsum({w_pkt[54],w_pkt[55]},{w_pkt[56],w_pkt[57]});
  assign w_csum9 = fsum({w_pkt[58],w_pkt[59]},{P_ZERO   ,P_ZERO   });
  assign w_csum01 = fsum(w_csum0,w_csum1);
  assign w_csum23 = fsum(w_csum2,w_csum3);
  assign w_csum45 = fsum(w_csum4,w_csum5);
  assign w_csum67 = fsum(w_csum6,w_csum7);
  assign w_csum89 = fsum(w_csum8,w_csum9);
  assign w_csum0123 = fsum(w_csum01,w_csum23);
  assign w_csum4567 = fsum(w_csum45,w_csum67);
  assign w_csum01234567 = fsum(w_csum0123,w_csum4567);
  assign w_csum0123456789 = fsum(w_csum01234567,w_csum89);
  assign w_csum = ~(w_csum0123456789);

  always @(posedge clk or negedge nrst)begin
    if(nrst==1'b0)
      r_flg <= 1'b0;
    else
      if(i_pkt_start)
        r_flg <= 1'b1;
      else if(r_cnt_wfifo == (P_ELEN-7'd1))
        r_flg <= 1'b0;
      else
        r_flg <= r_flg;
  end

  always @(posedge clk or negedge nrst)begin
    if(nrst==1'b0)
      r_flg_d <= 1'b0;
    else
      r_flg_d <= r_flg;
  end

  always @(posedge clk or negedge nrst)begin
    if(nrst==1'b0)
      r_crcflg <= 1'b0;
    else
      if(i_pkt_start)
        r_crcflg <= 1'b1;
      else if(r_cnt_wfifo >= (P_ELEN-7'd5))
        r_crcflg <= 1'b0;
      else
        r_crcflg <= r_flg;
  end

  always @(posedge clk or negedge nrst)begin
    if(nrst==1'b0)
      r_cnt_wfifo <= 7'd0;
    else
      if(r_flg==1'b0)
        r_cnt_wfifo <= 7'd0;
      else if(r_cnt_wfifo <= (P_ELEN-7'd1))
        r_cnt_wfifo <= r_cnt_wfifo + 7'd1;
      else
        r_cnt_wfifo <= r_cnt_wfifo;
  end

  assign w_packet = w_pkt[r_cnt_wfifo];

  always @(posedge clk or negedge nrst)begin
    if(nrst==1'b0)
      r_packet <= 8'h00;
    else
      r_packet <= w_packet;
  end

  udp_crc udp_crc
  (
    .clk      (clk        ), // I
    .nrst     (nrst       ), // I
    .i_sreset (i_pkt_start), // I
    .i_dat    (w_packet   ), // I
    .i_enable (r_crcflg   ), // I
    .o_crc    (w_crc      )  // O
  );

  function [7:0] frev(input [7:0] crcin);
    return (~({crcin[0],crcin[1],crcin[2],crcin[3],crcin[4],crcin[5],crcin[6],crcin[7]}));
  endfunction

  assign o_packet = (r_packet);

  assign o_wen = r_flg_d;

  always @(posedge clk or negedge nrst)begin
    if(nrst==1'b0)
      r_pkt_end <= 1'b0;
    else
      r_pkt_end <= (r_cnt_wfifo==P_ELEN);
  end

  always @(posedge clk or negedge nrst)begin
    if(nrst==1'b0)begin
      r_pkt_end_tx0 <= 1'b0;
      r_pkt_end_tx1 <= 1'b0;
      r_pkt_end_tx2 <= 1'b0;
      r_pkt_end_tx  <= 1'b0;
    end
    else
    begin
      r_pkt_end_tx0 <= r_pkt_end;
      r_pkt_end_tx1 <= r_pkt_end_tx0;
      r_pkt_end_tx2 <= r_pkt_end_tx1;
      r_pkt_end_tx  <= r_pkt_end_tx2 & ~r_pkt_end_tx1;
    end
  end

  assign o_pkt_end = r_pkt_end_tx;
  assign o_pkt_cnt = P_ELEN;

endmodule

●リスト4 CRCの計算(udp_crc.v)

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

module udp_crc (
  clk,
  nrst,
  i_sreset,
  i_dat,
  i_enable,
  o_crc
);

  input           clk;
  input           nrst;
  input           i_sreset;
  input   [ 7:0]  i_dat;
  input           i_enable;
  output  [31:0]  o_crc;

  reg     [31:0]  r_crc;
  wire    [ 7:0]  w_dat;
  wire    [31:0]  w_crcn;

  assign w_dat={i_dat[0],i_dat[1],i_dat[2],i_dat[3],i_dat[4],i_dat[5],i_dat[6],i_dat[7]};

  assign w_crcn[ 0] = r_crc[24] ^ r_crc[30] ^ w_dat[ 0] ^ w_dat[ 6];
  assign w_crcn[ 1] = r_crc[24] ^ r_crc[25] ^ r_crc[30] ^ r_crc[31] ^ w_dat[ 0] ^ w_dat[ 1] ^ w_dat[ 6] ^ w_dat[7];
  assign w_crcn[ 2] = r_crc[24] ^ r_crc[25] ^ r_crc[26] ^ r_crc[30] ^ r_crc[31] ^ w_dat[ 0] ^ w_dat[ 1] ^ w_dat[2] ^ w_dat[6] ^ w_dat[7];
  assign w_crcn[ 3] = r_crc[25] ^ r_crc[26] ^ r_crc[27] ^ r_crc[31] ^ w_dat[ 1] ^ w_dat[ 2] ^ w_dat[ 3] ^ w_dat[7];
  assign w_crcn[ 4] = r_crc[24] ^ r_crc[26] ^ r_crc[27] ^ r_crc[28] ^ r_crc[30] ^ w_dat[ 0] ^ w_dat[ 2] ^ w_dat[3] ^ w_dat[4] ^ w_dat[6];
  assign w_crcn[ 5] = r_crc[24] ^ r_crc[25] ^ r_crc[27] ^ r_crc[28] ^ r_crc[29] ^ r_crc[30] ^ r_crc[31] ^ w_dat[0] ^ w_dat[1] ^ w_dat[3] ^ w_dat[4] ^ w_dat[5] ^ w_dat[6] ^ w_dat[7];
  assign w_crcn[ 6] = r_crc[25] ^ r_crc[26] ^ r_crc[28] ^ r_crc[29] ^ r_crc[30] ^ r_crc[31] ^ w_dat[ 1] ^ w_dat[2] ^ w_dat[4] ^ w_dat[5] ^ w_dat[6] ^ w_dat[7];
  assign w_crcn[ 7] = r_crc[24] ^ r_crc[26] ^ r_crc[27] ^ r_crc[29] ^ r_crc[31] ^ w_dat[ 0] ^ w_dat[ 2] ^ w_dat[3] ^ w_dat[5] ^ w_dat[7];
  assign w_crcn[ 8] = r_crc[ 0] ^ r_crc[24] ^ r_crc[25] ^ r_crc[27] ^ r_crc[28] ^ w_dat[ 0] ^ w_dat[ 1] ^ w_dat[3] ^ w_dat[4];
  assign w_crcn[ 9] = r_crc[ 1] ^ r_crc[25] ^ r_crc[26] ^ r_crc[28] ^ r_crc[29] ^ w_dat[ 1] ^ w_dat[ 2] ^ w_dat[4] ^ w_dat[5];
  assign w_crcn[10] = r_crc[ 2] ^ r_crc[24] ^ r_crc[26] ^ r_crc[27] ^ r_crc[29] ^ w_dat[ 0] ^ w_dat[ 2] ^ w_dat[3] ^ w_dat[5];
  assign w_crcn[11] = r_crc[ 3] ^ r_crc[24] ^ r_crc[25] ^ r_crc[27] ^ r_crc[28] ^ w_dat[ 0] ^ w_dat[ 1] ^ w_dat[3] ^ w_dat[4];
  assign w_crcn[12] = r_crc[ 4] ^ r_crc[24] ^ r_crc[25] ^ r_crc[26] ^ r_crc[28] ^ r_crc[29] ^ r_crc[30] ^ w_dat[0] ^ w_dat[1] ^ w_dat[2] ^ w_dat[4] ^ w_dat[5] ^ w_dat[6];
  assign w_crcn[13] = r_crc[ 5] ^ r_crc[25] ^ r_crc[26] ^ r_crc[27] ^ r_crc[29] ^ r_crc[30] ^ r_crc[31] ^ w_dat[1] ^ w_dat[2] ^ w_dat[3] ^ w_dat[5] ^ w_dat[6] ^ w_dat[7];
  assign w_crcn[14] = r_crc[ 6] ^ r_crc[26] ^ r_crc[27] ^ r_crc[28] ^ r_crc[30] ^ r_crc[31] ^ w_dat[ 2] ^ w_dat[3] ^ w_dat[4] ^ w_dat[6] ^ w_dat[7];
  assign w_crcn[15] = r_crc[ 7] ^ r_crc[27] ^ r_crc[28] ^ r_crc[29] ^ r_crc[31] ^ w_dat[ 3] ^ w_dat[ 4] ^ w_dat[5] ^ w_dat[7];
  assign w_crcn[16] = r_crc[ 8] ^ r_crc[24] ^ r_crc[28] ^ r_crc[29] ^ w_dat[ 0] ^ w_dat[ 4] ^ w_dat[ 5];
  assign w_crcn[17] = r_crc[ 9] ^ r_crc[25] ^ r_crc[29] ^ r_crc[30] ^ w_dat[ 1] ^ w_dat[ 5] ^ w_dat[ 6];
  assign w_crcn[18] = r_crc[10] ^ r_crc[26] ^ r_crc[30] ^ r_crc[31] ^ w_dat[ 2] ^ w_dat[ 6] ^ w_dat[ 7];
  assign w_crcn[19] = r_crc[11] ^ r_crc[27] ^ r_crc[31] ^ w_dat[ 3] ^ w_dat[ 7];
  assign w_crcn[20] = r_crc[12] ^ r_crc[28] ^ w_dat[ 4];
  assign w_crcn[21] = r_crc[13] ^ r_crc[29] ^ w_dat[ 5];
  assign w_crcn[22] = r_crc[14] ^ r_crc[24] ^ w_dat[ 0];
  assign w_crcn[23] = r_crc[15] ^ r_crc[24] ^ r_crc[25] ^ r_crc[30] ^ w_dat[ 0] ^ w_dat[ 1] ^ w_dat[ 6];
  assign w_crcn[24] = r_crc[16] ^ r_crc[25] ^ r_crc[26] ^ r_crc[31] ^ w_dat[ 1] ^ w_dat[ 2] ^ w_dat[ 7];
  assign w_crcn[25] = r_crc[17] ^ r_crc[26] ^ r_crc[27] ^ w_dat[ 2] ^ w_dat[ 3];
  assign w_crcn[26] = r_crc[18] ^ r_crc[24] ^ r_crc[27] ^ r_crc[28] ^ r_crc[30] ^ w_dat[ 0] ^ w_dat[ 3] ^ w_dat[4] ^ w_dat[6];
  assign w_crcn[27] = r_crc[19] ^ r_crc[25] ^ r_crc[28] ^ r_crc[29] ^ r_crc[31] ^ w_dat[ 1] ^ w_dat[ 4] ^ w_dat[5] ^ w_dat[7];
  assign w_crcn[28] = r_crc[20] ^ r_crc[26] ^ r_crc[29] ^ r_crc[30] ^ w_dat[ 2] ^ w_dat[ 5] ^ w_dat[ 6];
  assign w_crcn[29] = r_crc[21] ^ r_crc[27] ^ r_crc[30] ^ r_crc[31] ^ w_dat[ 3] ^ w_dat[ 6] ^ w_dat[ 7];
  assign w_crcn[30] = r_crc[22] ^ r_crc[28] ^ r_crc[31] ^ w_dat[ 4] ^ w_dat[ 7];
  assign w_crcn[31] = r_crc[23] ^ r_crc[29] ^ w_dat[ 5];

  always @(posedge clk or negedge nrst) begin
    if (!nrst) begin
      r_crc <={32{1'b1}};
    end
    else begin
     if(i_sreset)
       r_crc <={32{1'b1}};
     else if (i_enable)
      r_crc <=w_crcn;
    end
  end

  assign o_crc  = r_crc;

endmodule

●リスト5 パケット送信(udp_gmii_tx.v)

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

module udp_gmii_tx(
  ARSTN,

  TCLK,
  TXD,
  TXEN,
  TXER,
  TX_START,
  TX_END,
  FIFO_RDAT,
  FIFO_REN,
  FIFO_RCNT
);

  parameter ST_IDLE   = 3'b000, // Idole
            ST_PREA   = 3'b001, // Preamble
            ST_SFD    = 3'b010, // Start Frame Delimter
            ST_BDY    = 3'b011, // Packet Data
            ST_IFG    = 3'b100, // Inter Frame Gap
            ST_END    = 3'b101; // End

  parameter P_PREAMBL = 4'd7-4'd1;
  parameter P_IFG_GAP = 4'd12-4'd3;
  parameter P_RDELAY  = 7'd1;

  input           ARSTN;

  input           TCLK;
  output  [7:0]   TXD;
  output          TXEN;
  output          TXER;
  input           TX_START;
  output          TX_END;

  input   [7:0]   FIFO_RDAT;
  output          FIFO_REN;
  input   [6:0]   FIFO_RCNT;

  reg     [2:0]   r_st;
  reg     [2:0]   w_st;

  reg     [7:0]   r_txd;
  reg             r_txen;
  reg             r_fifo_ren;
  reg     [6:0]   r_bcnt;
  reg     [3:0]   r_pcnt;
  
  reg     [3:0]   r_tx_start;
  reg             r_tx_end;

  assign  TXD[7:0]  = {r_txd[3:0],r_txd[7:4]};
  assign  TXEN      = r_txen;
  assign  TXER      = r_txen;
  assign  FIFO_REN  = r_fifo_ren;

  always @( posedge TCLK or negedge ARSTN)begin
    if(ARSTN == 1'b0) begin
      r_tx_start[3:0] <= 4'd0;
    end else begin
      r_tx_start[2:0] <= {r_tx_start[1:0],TX_START};
      r_tx_start[  3] <= ~r_tx_start[2] & r_tx_start[1];
    end
  end

  // State Machine
  always @( posedge TCLK or negedge ARSTN)begin
    if(ARSTN == 1'b0) begin
      r_st[2:0] <= ST_IDLE;
    end else begin
      r_st[2:0] <= w_st[2:0];
    end
  end

  // State Control
  always @(r_st or r_tx_start or r_pcnt or r_bcnt or FIFO_RCNT)begin
    case(r_st[2:0])
      ST_IDLE:
        if(r_tx_start[3] == 1'b1)
          w_st[2:0] = ST_PREA;
        else
          w_st[2:0] = r_st[2:0];
      ST_PREA:
        if(r_pcnt[3:0] == P_PREAMBL)
          w_st[2:0] = ST_SFD;
        else
          w_st[2:0] = r_st[2:0];
      ST_SFD:
          w_st[2:0] = ST_BDY;
      ST_BDY:
        if(r_bcnt[6:0] == (FIFO_RCNT-P_RDELAY))
          w_st[2:0] = ST_IFG;
        else
          w_st[2:0] = r_st[2:0];
      ST_IFG:
        if(r_pcnt[3:0] == P_IFG_GAP)
          w_st[2:0] = ST_END;
        else
          w_st[2:0] = r_st[2:0];
      ST_END:
          w_st[2:0] = ST_IDLE;
      default:
          w_st[2:0] = ST_IDLE;
    endcase
  end

  // Packet Data
  always @( posedge TCLK or negedge ARSTN)begin
    if(ARSTN == 1'b0) begin
      r_txd[7:0] <= 8'hDD;
    end else begin
      case(r_st[2:0])
        ST_PREA:
          r_txd[7:0] <= 8'h55;
        ST_SFD:
          r_txd[7:0] <= 8'hD5;
        ST_BDY:
          r_txd[7:0] <= FIFO_RDAT[7:0];
        default:
          r_txd[7:0] <= 8'hDD;
      endcase
    end
  end

  // Trans Enable
  always @( posedge TCLK or negedge ARSTN)begin
    if(ARSTN == 1'b0) begin
      r_txen <= 1'b0;
    end else begin
      case(r_st[2:0])
        ST_PREA:
          r_txen <= 1'b1;
        ST_SFD:
          r_txen <= 1'b1;
        ST_BDY:
          r_txen <= 1'b1;
        default:
          r_txen <= 1'b0;
      endcase
    end
  end

  // FIFO Read Enable
  always @( posedge TCLK or negedge ARSTN)begin
    if(ARSTN == 1'b0) begin
      r_fifo_ren <= 1'b0;
    end else begin
      case(w_st[2:0])
        ST_BDY:
          r_fifo_ren <= 1'b1;
        default:
          r_fifo_ren <= 1'b0;
      endcase
    end
  end

  // Preamble and Gap Count
  always @( posedge TCLK or negedge ARSTN)begin
    if(ARSTN == 1'b0) begin
      r_pcnt[3:0] <= 4'd0;
    end else begin
      case(r_st[2:0])
        ST_PREA:
          r_pcnt[3:0] <= r_pcnt[3:0] + 4'd1;
        ST_IFG:
          r_pcnt[3:0] <= r_pcnt[3:0] + 4'd1;
        default:
          r_pcnt[3:0] <= 4'd0;
      endcase
    end
  end

  // Packet Count
  always @( posedge TCLK or negedge ARSTN)begin
    if(ARSTN == 1'b0) begin
      r_bcnt[6:0] <= 7'd0;
    end else begin
      case(r_st[2:0])
        ST_BDY:
          r_bcnt[6:0] <= r_bcnt[6:0] + 7'd1;
        default:
          r_bcnt[6:0] <= 7'd0;
      endcase
    end
  end

  // TX END
  always @( posedge TCLK or negedge ARSTN)begin
    if(ARSTN == 1'b0) begin
      r_tx_end <= 1'b0;
    end else begin
      case(w_st[2:0])
        ST_IFG:
          r_tx_end <= 1'b1;
        default:
          r_tx_end <= 1'b0;
      endcase
    end
  end

  assign TX_END = r_tx_end;

endmodule

●リスト6 トップ・モジュール(udp_top.v)

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

module udp_top(
  ARSTN,
  PHYRSTN,
  PLL_LOCK,
  LED,

  RCLK_0,
  PLL_RCLK_0,
  PLL_RCLK_0_90,
  I2C_CLK,

  TCLK_0_0,
  TCLK_1_0,
  TXD_0,
  TXEN_0,
  TXER_0,
  RSTN_0,
  MST_SCL_IN,
  MST_SDA_IN, 
  MST_SCL_OUT,
  MST_SDA_OUT,
  MST_SCL_OE,
  MST_SDA_OE
);

  parameter P_INIT_WAIT = 20'd500000; // 10ms@50MHz
//  parameter P_INIT_WAIT = 20'd10; // 10ms@50MHz for sim

  input           ARSTN;          // ネアエ・・サ・テ・ネ
  input           PHYRSTN;        // ・ラ・テ・キ・藉W(PHY・・サ・テ・ネ)
  input           PLL_LOCK;       // PLL・愠テ・ッ
  output  [ 7:2]  LED;            // ・筵ヒ・ソLED
  input           RCLK_0;         // ショ・ッ・愠テ・ッ 0
  input           PLL_RCLK_0;     // ショ・ッ・愠テ・ッPLL 0
  input           PLL_RCLK_0_90;  // ショ・ッ・愠テ・ッPLL 0 ーフチ・0ナル
  input           I2C_CLK;        // I2C・ッ・愠テ・ッ
  output          TCLK_1_0;       // チョ・ッ・愠テ・ッタ゚ト・1
  output          TCLK_0_0;       // チョ・ッ・愠テ・ッタ゚ト・0
  output  [ 7:0]  TXD_0;          // チョ・ヌ。シ・ソ 0
  output          TXEN_0;         // チョイト 0
  output          TXER_0;         // チョ・ィ・鬘シ 0
  output          RSTN_0;         // ・・サ・テ・ネ 0
  input           MST_SCL_IN;     // I2C・ッ・愠テ・ッニホマ
  input           MST_SDA_IN;     // I2C・ヌ。シ・ソニホマ
  output          MST_SCL_OUT;    // I2C・ッ・愠テ・ッスミホマ
  output          MST_SDA_OUT;    // I2C・ヌ。シ・ソスミホマ
  output          MST_SCL_OE;     // I2C・ッ・愠テ・ッスミホマヘュク・  output          MST_SDA_OE;     // I2C・ヌ。シ・ソスミホマヘュク・
  wire            TCLK_0;
  wire            TCLK_1;
  wire    [ 7:0]  FIFO_WDAT_0;
  wire            FIFO_WEN_0;
  wire            FIFO_AFULL_0;
  wire    [10:0]  FIFO_WCNT_0;
  wire    [ 7:0]  FIFO_RDAT_0;
  wire            FIFO_REN_0;
  wire            FIFO_VALID_0;
  wire    [10:0]  FIFO_RCNT_0;
  reg     [27:0]  r_tclk_0;
  reg     [27:0]  r_rclk_0;
  reg     [27:0]  r_rclk90_0;
  reg     [27:0]  r_i2cclk_0;
  wire    [15:0]  w_data_tmp_dec;
  wire            w_i2c_start;
  wire            w_i2c_end;
  wire            w_pkt_start;
  wire            w_pkt_end;
  wire            w_tx_start;
  wire            w_tx_end;
  wire    [ 6:0]  w_pkt_cnt;
  wire            w_wen;
  wire    [ 7:0]  w_packet;
  reg     [19:0]  r_rstcnt;
  reg             r_nrst;

  assign  TCLK_0_0  = 1'b0;
  assign  TCLK_1_0  = 1'b1;
  assign  TCLK_0    = PLL_RCLK_0;
  assign  RSTN_0    = ~PHYRSTN;
  assign  LED[2]    = r_tclk_0[27];
  assign  LED[3]    = r_rclk_0[27];
  assign  LED[4]    = r_rclk90_0[27];
  assign  LED[5]    = r_i2cclk_0[27];
  assign  LED[6]    = r_nrst;
  assign  LED[7]    = RSTN_0;

  always @(posedge TCLK_0 or negedge ARSTN )begin
    if(~ARSTN)
      r_tclk_0 <= 28'd0;
    else
      r_tclk_0 <= r_tclk_0 + 28'd1;
  end

  always @(posedge RCLK_0 or negedge ARSTN )begin
    if(~ARSTN)
      r_rclk_0 <= 28'd0;
    else
      r_rclk_0 <= r_rclk_0 + 28'd1;
  end

  always @(posedge PLL_RCLK_0_90 or negedge ARSTN )begin
    if(~ARSTN)
      r_rclk90_0 <= 28'd0;
    else
      r_rclk90_0 <= r_rclk90_0 + 28'd1;
  end

  always @(posedge I2C_CLK or negedge ARSTN )begin
    if(~ARSTN)
      r_i2cclk_0 <= 28'd0;
    else
      r_i2cclk_0 <= r_i2cclk_0 + 28'd1;
  end

  always @(posedge I2C_CLK or negedge ARSTN )begin
    if(~ARSTN)
      r_rstcnt <= 20'd0;
    else
     if(PLL_LOCK==1'b0)
        r_rstcnt <= 20'd0;
     else if( r_rstcnt > P_INIT_WAIT)
      r_rstcnt <= r_rstcnt;
     else
      r_rstcnt <= r_rstcnt + 20'd1;
  end

  always @(posedge I2C_CLK or negedge ARSTN )begin
    if(~ARSTN)
      r_nrst <= 1'b0;
    else
      if( r_rstcnt > P_INIT_WAIT)
        r_nrst <= 1'b1;
      else
        r_nrst <= 1'b0;
  end

  udp_state udp_state(
    .clk          (I2C_CLK    ), // I
    .nrst         (r_nrst     ), // I
    .i_ready      (PLL_LOCK   ), // I
    .i_i2c_end    (w_i2c_end  ), // I
    .i_pkt_end    (w_pkt_end  ), // I
    .i_tx_end     (w_tx_end   ), // I
    .o_i2c_start  (w_i2c_start), // O
    .o_pkt_start  (w_pkt_start), // O
    .o_tx_start   (w_tx_start )  // O
);

  udp_i2c_cnt udp_i2c_cnt(
    .arstn          (r_nrst         ), // I
    .i2c_clk        (I2C_CLK        ), // I
    .i_i2c_start    (w_i2c_start    ), // I
    .o_i2c_end      (w_i2c_end      ), // O
    .o_data_tmp_dec (w_data_tmp_dec ), // O
    .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
  );

  udp_tx udp_tx(
    .clk            (I2C_CLK        ), // I
    .nrst           (r_nrst         ), // I
    .i_pkt_start    (w_pkt_start    ), // I
    .i_data_tmp_dec (w_data_tmp_dec ), // I
    .o_pkt_end      (w_pkt_end      ), // O
    .o_pkt_cnt      (w_pkt_cnt      ), // O
    .o_wen          (w_wen          ), // O
    .o_packet       (w_packet       )  // O
  );

  udp_gmii_fifo udp_gmii_fifo(
    .almost_full_o  (                   ), // O
    .full_o         (                   ), // O
    .overflow_o     (                   ), // O
    .wr_ack_o       (                   ), // O
    .empty_o        (                   ), // O
    .almost_empty_o (                   ), // O
    .underflow_o    (                   ), // O
    .rd_valid_o     (                   ), // O
    .rdata          ( FIFO_RDAT_0[7:0]  ), // O
    .wr_clk_i       ( I2C_CLK           ), // I
    .rd_clk_i       ( TCLK_0            ), // I
    .wr_en_i        ( w_wen             ), // I
    .rd_en_i        ( FIFO_REN_0        ), // I
    .wdata          ( w_packet[7:0]     ), // I
    .wr_datacount_o (                   ), // O
    .rst_busy       (                   ), // O
    .rd_datacount_o (                   ), // O
    .a_rst_i        ( ~r_nrst           )  // I
  );

  udp_gmii_tx udp_gmii_tx (
    .ARSTN        (r_nrst             ),  // I
    .TCLK         (TCLK_0             ),  // I
    .FIFO_RDAT    (FIFO_RDAT_0  [7:0] ),  // I
    .FIFO_RCNT    (w_pkt_cnt    [6:0] ),  // I
    .TX_START     (w_tx_start         ),  // I
    .TX_END       (w_tx_end           ),  // O
    .TXD          (TXD_0        [7:0] ),  // O
    .TXEN         (TXEN_0             ),  // O
    .TXER         (TXER_0             ),  // O
    .FIFO_REN     (FIFO_REN_0         )   // O
  );

endmodule

コメントを残す