`timescale 1 ns / 1 ps module upload_protocol_ql# ( parameter CLK_PERIOD = 10 , parameter CHANNLE_QTY = 64 , parameter PRE_MSG_LEN = 128 ) ( input clk , input rst_n , input enable , output interrupt , input pulse_ms , input [64-1:0] run_time_ms , input [ 8*PRE_MSG_LEN-1:0]pre_message_array , input [ 8-1:0] pre_message_length , input [32-1:0] upload_round_qty_set , input reset_package_id , input [32-1:0] package_overtime_ms , input [32-1:0] s_axis_trigger_tdata , input s_axis_trigger_tvalid , output reg s_axis_trigger_tready , input [ 8-1:0] s_axis_eeg_tdata , input s_axis_eeg_tlast , output reg s_axis_eeg_tready , input s_axis_eeg_tvalid , input [48-1:0] accel_data , input m_axis_record_tfull , output reg [ 8-1:0] m_axis_record_tdata , output reg [ 1-1:0] m_axis_record_tkeep , output reg m_axis_record_tlast , input m_axis_record_tready , output reg m_axis_record_tvalid ); //***************************************************************************** // localparam definition //***************************************************************************** localparam ST_IDLE = 4'd0 ; localparam ST_MSG_HEAD = 4'd1 ; localparam ST_WAIT = 4'd2 ; localparam ST_READ_TRIGGER = 4'd3 ; localparam ST_MSG_TRIGGER = 4'd4 ; localparam ST_MSG_RECORD = 4'd5 ; localparam ST_MSG_CRC = 4'd6 ; localparam ST_ADDITIONAL = 4'd7 ; localparam ADDL_NUM = 12 ; //***************************************************************************** // Internal register and wire declarations //***************************************************************************** reg [ 4-1:0] cstate ; reg [ 4-1:0] nstate ; reg [32-1:0] overtime_ms ; reg [32-1:0] package_id ; wire [ 8-1:0] pre_message[0:PRE_MSG_LEN-1]; reg [32-1:0] trigger_word ; wire [ 8-1:0] trigger_byte[0:3] ; wire [ 8-1:0] msg_crc[0:1] ; reg [32-1:0] upload_round_qty ; reg [32-1:0] upload_bytes_cnt ; wire [32-1:0] upload_bytes_cnt_add1 ; reg [32-1:0] upload_rounds_cnt ; reg [32-1:0] upload_record_bytes_cnt ; wire [16-1:0] crc16_out ; reg [16-1:0] crc16 ; wire [ 8-1:0] upload_addl[0:ADDL_NUM-1] ; reg [ 8-1:0] byte_cnt ; reg upload_break ; reg upload_disable ; wire [ 4-1:0] debug_sig_sort ; genvar i; //***************************************************************************** // Instantiation //***************************************************************************** //***************************************************************************** // Function //***************************************************************************** function automatic [15:0] crc16_d8; input [15:0] crcIn; input [7:0] data; begin crc16_d8[0] = crcIn[0] ^ crcIn[1] ^ crcIn[2] ^ crcIn[3] ^ crcIn[4] ^ crcIn[5] ^ crcIn[6] ^ crcIn[7] ^ crcIn[8] ^ data[0] ^ data[1] ^ data[2] ^ data[3] ^ data[4] ^ data[5] ^ data[6] ^ data[7]; crc16_d8[1] = crcIn[9]; crc16_d8[2] = crcIn[10]; crc16_d8[3] = crcIn[11]; crc16_d8[4] = crcIn[12]; crc16_d8[5] = crcIn[13]; crc16_d8[6] = crcIn[0] ^ crcIn[14] ^ data[0]; crc16_d8[7] = crcIn[0] ^ crcIn[1] ^ crcIn[15] ^ data[0] ^ data[1]; crc16_d8[8] = crcIn[1] ^ crcIn[2] ^ data[1] ^ data[2]; crc16_d8[9] = crcIn[2] ^ crcIn[3] ^ data[2] ^ data[3]; crc16_d8[10] = crcIn[3] ^ crcIn[4] ^ data[3] ^ data[4]; crc16_d8[11] = crcIn[4] ^ crcIn[5] ^ data[4] ^ data[5]; crc16_d8[12] = crcIn[5] ^ crcIn[6] ^ data[5] ^ data[6]; crc16_d8[13] = crcIn[6] ^ crcIn[7] ^ data[6] ^ data[7]; crc16_d8[14] = crcIn[0] ^ crcIn[1] ^ crcIn[2] ^ crcIn[3] ^ crcIn[4] ^ crcIn[5] ^ crcIn[6] ^ data[0] ^ data[1] ^ data[2] ^ data[3] ^ data[4] ^ data[5] ^ data[6]; crc16_d8[15] = crcIn[0] ^ crcIn[1] ^ crcIn[2] ^ crcIn[3] ^ crcIn[4] ^ crcIn[5] ^ crcIn[6] ^ crcIn[7] ^ data[0] ^ data[1] ^ data[2] ^ data[3] ^ data[4] ^ data[5] ^ data[6] ^ data[7]; end endfunction //***************************************************************************** always@( posedge clk or negedge rst_n ) begin if( !rst_n ) cstate <= ST_IDLE; else cstate <= nstate; end always@( * ) begin case ( cstate ) ST_IDLE: if ( enable && s_axis_eeg_tvalid ) nstate <= ST_MSG_HEAD; else nstate <= ST_IDLE; ST_MSG_HEAD: if ( byte_cnt == pre_message_length - 1 ) nstate <= ST_WAIT; else nstate <= ST_MSG_HEAD; ST_WAIT: if ( !enable || upload_rounds_cnt == upload_round_qty || overtime_ms == package_overtime_ms || (m_axis_record_tfull && !upload_disable) ) nstate <= ST_MSG_CRC; else if ( s_axis_eeg_tvalid ) nstate <= ST_READ_TRIGGER; else nstate <= ST_WAIT; ST_READ_TRIGGER: nstate <= ST_MSG_TRIGGER; ST_MSG_TRIGGER: if ( byte_cnt == 4-1 ) nstate <= ST_MSG_RECORD; else nstate <= ST_MSG_TRIGGER; ST_MSG_RECORD: if ( s_axis_eeg_tready && s_axis_eeg_tvalid && s_axis_eeg_tlast ) nstate <= ST_WAIT; else nstate <= ST_MSG_RECORD; ST_MSG_CRC: if ( byte_cnt == 2-1 ) nstate <= ST_ADDITIONAL; else nstate <= ST_MSG_CRC; ST_ADDITIONAL: if ( byte_cnt == ADDL_NUM-1 ) nstate <= upload_break? ST_WAIT:ST_IDLE; else nstate <= ST_ADDITIONAL; default: nstate <= ST_IDLE; endcase end always @ ( posedge clk or negedge rst_n ) begin if ( !rst_n ) upload_break <= 1'b0; else if ( cstate == ST_WAIT && (upload_rounds_cnt != upload_round_qty && overtime_ms != package_overtime_ms) && m_axis_record_tfull && !upload_disable ) upload_break <= 1'b1; else if ( cstate == ST_ADDITIONAL && nstate != ST_ADDITIONAL ) upload_break <= 1'b0; end always @ ( posedge clk or negedge rst_n ) begin if ( !rst_n ) upload_disable <= 1'b0; else if ( cstate == ST_ADDITIONAL && nstate != ST_ADDITIONAL ) upload_disable <= m_axis_record_tfull; end always @ ( posedge clk or negedge rst_n ) begin if ( !rst_n ) package_id <= 0; else if ( reset_package_id ) package_id <= 0; else if ( cstate == ST_MSG_CRC && nstate == ST_ADDITIONAL ) package_id <= package_id + 1'b1; end always @ ( posedge clk or negedge rst_n ) begin if ( !rst_n ) upload_round_qty <= 0; else if ( cstate == ST_IDLE ) upload_round_qty <= upload_round_qty_set; end always @ ( posedge clk or negedge rst_n ) begin if ( !rst_n ) s_axis_trigger_tready <= 1'b0; else if ( nstate == ST_READ_TRIGGER ) s_axis_trigger_tready <= 1'b1; else s_axis_trigger_tready <= 1'b0; end always @ ( posedge clk or negedge rst_n ) begin if ( !rst_n ) trigger_word <= 0; else if ( s_axis_trigger_tvalid && s_axis_trigger_tready ) trigger_word <= s_axis_trigger_tdata; else if ( cstate != ST_MSG_TRIGGER ) trigger_word <= 0; end always @ ( posedge clk or negedge rst_n ) begin if ( !rst_n ) s_axis_eeg_tready <= 1'b0; else if ( cstate == ST_MSG_RECORD || nstate == ST_MSG_RECORD ) s_axis_eeg_tready <= 1'b1; else s_axis_eeg_tready <= 1'b0; end always @ ( posedge clk or negedge rst_n ) begin if ( !rst_n ) upload_rounds_cnt <= 0; else if ( cstate == ST_IDLE ) upload_rounds_cnt <= 0; else if ( s_axis_eeg_tready && s_axis_eeg_tvalid && s_axis_eeg_tlast ) upload_rounds_cnt <= upload_rounds_cnt + 1'b1; end always @ ( posedge clk or negedge rst_n ) begin if ( !rst_n ) overtime_ms <= 0; else if ( s_axis_eeg_tvalid ) overtime_ms <= 0; else if ( pulse_ms ) overtime_ms <= overtime_ms + 1'b1; end always @ ( posedge clk or negedge rst_n ) begin if ( !rst_n ) byte_cnt <= 0; else if ( cstate != nstate ) byte_cnt <= 0; else byte_cnt <= byte_cnt + 1'b1; end always @ ( posedge clk or negedge rst_n ) begin if ( !rst_n ) begin m_axis_record_tdata <= 0; m_axis_record_tkeep <= 1'b1; m_axis_record_tvalid <= 1'b0; end else if ( cstate == ST_MSG_HEAD ) begin m_axis_record_tdata <= pre_message[byte_cnt]; m_axis_record_tvalid <= upload_disable? 1'b0:1'b1; end else if ( cstate == ST_MSG_TRIGGER ) begin m_axis_record_tdata <= trigger_byte[byte_cnt]; m_axis_record_tvalid <= upload_disable? 1'b0:1'b1; end else if ( cstate == ST_MSG_RECORD && s_axis_eeg_tvalid && s_axis_eeg_tready ) begin m_axis_record_tdata <= s_axis_eeg_tdata; m_axis_record_tvalid <= upload_disable? 1'b0:1'b1; end else if ( cstate == ST_MSG_CRC ) begin m_axis_record_tdata <= msg_crc[byte_cnt]; m_axis_record_tvalid <= upload_disable? 1'b0:1'b1; end else if ( cstate == ST_ADDITIONAL ) begin m_axis_record_tdata <= upload_addl[byte_cnt]; m_axis_record_tvalid <= upload_disable? 1'b0:1'b1; end else m_axis_record_tvalid <= 1'b0; end always @ ( posedge clk ) begin if ( cstate == ST_IDLE ) crc16 <= 16'hFFFF; else if ( cstate != ST_MSG_CRC && m_axis_record_tvalid && m_axis_record_tready ) crc16 <= crc16_out; end always @ ( posedge clk or negedge rst_n ) begin if ( !rst_n ) begin m_axis_record_tlast <= 1'b0; end else if ( cstate == ST_ADDITIONAL && (byte_cnt == ADDL_NUM-1) ) begin m_axis_record_tlast <= 1'b1; end else m_axis_record_tlast <= 1'b0; end always @ ( posedge clk or negedge rst_n ) begin if ( !rst_n ) upload_bytes_cnt <= 0; else if ( cstate == ST_IDLE ) upload_bytes_cnt <= 0; else if ( (cstate != ST_ADDITIONAL) && m_axis_record_tvalid && m_axis_record_tready ) upload_bytes_cnt <= upload_bytes_cnt + 1'b1; end always @ ( posedge clk or negedge rst_n ) begin if ( !rst_n ) upload_record_bytes_cnt <= 0; else if ( cstate == ST_IDLE ) upload_record_bytes_cnt <= 0; else if ( cstate == ST_MSG_RECORD && s_axis_eeg_tvalid && s_axis_eeg_tready ) upload_record_bytes_cnt <= upload_record_bytes_cnt + 1'b1; end //***************************************************************************** // Wire assignment //***************************************************************************** //pre_message[21:14] is run_time_ms //pre_message[26:23] is package_id generate for(i=0;i 13 && i < 22 ) assign pre_message[i] = run_time_ms[8*(i-14)+7 : 8*(i-14)]; else if ( i > 22 && i < 27 ) assign pre_message[i] = package_id[8*(i-23)+7 : 8*(i-23)]; else assign pre_message[i] = pre_message_array[8*i+7 : 8*i]; end endgenerate assign trigger_byte[0] = trigger_word[ 7: 0]; assign trigger_byte[1] = trigger_word[15: 8]; assign trigger_byte[2] = trigger_word[23:16]; assign trigger_byte[3] = trigger_word[31:24]; assign crc16_out = crc16_d8(crc16, m_axis_record_tdata); assign msg_crc[0] = crc16[15: 8]; assign msg_crc[1] = crc16[ 7: 0]; assign upload_bytes_cnt_add1 = upload_bytes_cnt + 1'b1; assign upload_addl[ 0] = upload_bytes_cnt_add1[ 7: 0]; assign upload_addl[ 1] = upload_bytes_cnt_add1[15: 8]; assign upload_addl[ 2] = upload_bytes_cnt_add1[23:16]; assign upload_addl[ 3] = upload_bytes_cnt_add1[31:24]; assign upload_addl[ 4] = upload_rounds_cnt[ 7: 0]; assign upload_addl[ 5] = upload_rounds_cnt[15: 8]; assign upload_addl[ 6] = upload_rounds_cnt[23:16]; assign upload_addl[ 7] = upload_rounds_cnt[31:24]; assign upload_addl[ 8] = upload_record_bytes_cnt[ 7: 0]; assign upload_addl[ 9] = upload_record_bytes_cnt[15: 8]; assign upload_addl[10] = upload_record_bytes_cnt[23:16]; assign upload_addl[11] = upload_record_bytes_cnt[31:24]; endmodule