誌面に掲載できなかったリストを掲載します.
●リスト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