`timescale 1 ns / 1 ps module upload_top# ( parameter CLK_PERIOD = 10 , parameter CHANNLE_QTY = 64 , parameter PRE_MSG_LEN = 128 ) ( input clk , input rst_n , input [13-1:0] bram_addr , input bram_clk , input [32-1:0] bram_din , output [32-1:0] bram_dout , input bram_en , input bram_rst , input [ 4-1:0] bram_we , output interrupt , input [32-1:0] s_axis_trigger_tdata , input s_axis_trigger_tvalid , output reg s_axis_trigger_tready , input [32-1:0] s_axis_eeg16_tdata , input s_axis_eeg16_tlast , output s_axis_eeg16_tready , input s_axis_eeg16_tvalid , input [32-1:0] s_axis_eeg24_tdata , input s_axis_eeg24_tlast , output s_axis_eeg24_tready , input s_axis_eeg24_tvalid , input [32-1:0] s_axis_emg_tdata , input s_axis_emg_tlast , output s_axis_emg_tready , input s_axis_emg_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 , output [ 4-1:0] debug_sig ); //***************************************************************************** // 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_END = 4'd6 ; localparam ST_ADDITIONAL = 4'd7 ; localparam ADDL_NUM = 12 ; //***************************************************************************** // Internal register and wire declarations //***************************************************************************** wire pulse_ms ; wire [64-1:0] run_time_ms ; wire reset_package_id ; wire [32-1:0] package_overtime_ms ; reg [32-1:0] overtime_ms ; reg [32-1:0] package_id ; wire [ 8*PRE_MSG_LEN-1:0] pre_message_array ; wire [ 8-1:0] pre_message[0:PRE_MSG_LEN-1]; wire [ 8-1:0] pre_message_length ; reg [ 4-1:0] cstate ; reg [ 4-1:0] nstate ; wire [ 8*CHANNLE_QTY-1:0] ch_mapping2pc_array ; wire [ CHANNLE_QTY-1:0] upload_ch_array ; wire select_eeg24 ; wire [16-1:0] message_end ; reg [32-1:0] trigger_word ; wire [ 8-1:0] trigger_byte[0:3] ; wire [ 8-1:0] msg_end[0:1] ; wire [32-1:0] upload_round_qty_set ; 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 ; wire [ 8-1:0] m_axis_eeg_tdata ; wire m_axis_eeg_tlast ; reg m_axis_eeg_tready ; wire m_axis_eeg_tvalid ; reg upload_break ; reg upload_disable ; wire [ 4-1:0] debug_sig_sort ; genvar i; //***************************************************************************** // Instantiation //***************************************************************************** upload_config# ( .CHANNLE_QTY ( CHANNLE_QTY ), .PRE_MSG_LEN ( PRE_MSG_LEN ) ) u_upload_config ( .clk ( clk ), .rst_n ( rst_n ), .bram_addr ( bram_addr ), .bram_clk ( bram_clk ), .bram_din ( bram_din ), .bram_dout ( bram_dout ), .bram_en ( bram_en ), .bram_rst ( bram_rst ), .bram_we ( bram_we ), .pre_message_array ( pre_message_array ), .pre_message_length ( pre_message_length ), .upload_round_qty_set ( upload_round_qty_set ), .ch_mapping2pc_array ( ch_mapping2pc_array ), .upload_ch_array ( upload_ch_array ), .select_eeg24 ( select_eeg24 ), .reset_package_id ( reset_package_id ), .package_overtime_ms ( package_overtime_ms ), .message_end ( message_end ) //TODO: unused ); upload_sort# ( .CLK_PERIOD ( CLK_PERIOD ), .CHANNLE_QTY ( CHANNLE_QTY ) ) u_upload_sort ( .clk ( clk ), .rst_n ( rst_n ), .ch_mapping2pc_array ( ch_mapping2pc_array ), .upload_ch_array ( upload_ch_array ), .select_eeg24 ( 1'b1 ), //------------------------------------------ PL logic .s_axis_eeg16_tdata ( s_axis_eeg16_tdata ), .s_axis_eeg16_tlast ( s_axis_eeg16_tlast ), .s_axis_eeg16_tready ( s_axis_eeg16_tready ), .s_axis_eeg16_tvalid ( s_axis_eeg16_tvalid ), .s_axis_eeg24_tdata ( s_axis_eeg24_tdata ), .s_axis_eeg24_tlast ( s_axis_eeg24_tlast ), .s_axis_eeg24_tready ( s_axis_eeg24_tready ), .s_axis_eeg24_tvalid ( s_axis_eeg24_tvalid ), //------------------------------------------ PC logic .m_axis_eeg_tdata ( m_axis_eeg_tdata ), .m_axis_eeg_tlast ( m_axis_eeg_tlast ), .m_axis_eeg_tready ( m_axis_eeg_tready ), .m_axis_eeg_tvalid ( m_axis_eeg_tvalid ), .debug_sig_sort ( debug_sig_sort ) ); run_time# ( .CLK_PERIOD ( CLK_PERIOD ) ) u_run_time ( .clk ( clk ), .rst_n ( rst_n ), .pulse_ms ( pulse_ms ), .run_time_ms ( run_time_ms ) ); //***************************************************************************** // 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 ( m_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 ( upload_rounds_cnt == upload_round_qty || overtime_ms == package_overtime_ms ) nstate <= ST_MSG_END; else if ( m_axis_record_tfull && !upload_disable ) nstate <= ST_MSG_END; else if ( m_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 ( m_axis_eeg_tready && m_axis_eeg_tvalid && m_axis_eeg_tlast ) nstate <= ST_WAIT; else nstate <= ST_MSG_RECORD; ST_MSG_END: if ( byte_cnt == 2-1 ) nstate <= ST_ADDITIONAL; else nstate <= ST_MSG_END; 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_END && 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 ) m_axis_eeg_tready <= 1'b0; else if ( cstate == ST_MSG_RECORD || nstate == ST_MSG_RECORD ) m_axis_eeg_tready <= 1'b1; else m_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 ( m_axis_eeg_tready && m_axis_eeg_tvalid && m_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 ( m_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; 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; end else if ( cstate == ST_MSG_RECORD && m_axis_eeg_tvalid && m_axis_eeg_tready ) begin m_axis_record_tdata <= m_axis_eeg_tdata; m_axis_record_tvalid <= upload_disable? 1'b0:1; end else if ( cstate == ST_MSG_END ) begin m_axis_record_tdata <= msg_end[byte_cnt]; m_axis_record_tvalid <= upload_disable? 1'b0:1; end else if ( cstate == ST_ADDITIONAL ) begin m_axis_record_tdata <= upload_addl[byte_cnt]; m_axis_record_tvalid <= upload_disable? 1'b0:1; 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_END && 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 && m_axis_eeg_tvalid && m_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_end[0] = crc16[15: 8]; assign msg_end[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]; assign debug_sig[0] = m_axis_record_tvalid; assign debug_sig[1] = m_axis_record_tready; assign debug_sig[2] = m_axis_record_tfull; assign debug_sig[3] = 1'b0; endmodule