426 lines
13 KiB
Verilog
426 lines
13 KiB
Verilog
`timescale 1 ns / 1 ps
|
|
|
|
module upload_protocol_intan#
|
|
(
|
|
parameter CLK_PERIOD = 10 ,
|
|
parameter CHANNLE_QTY = 64
|
|
)
|
|
(
|
|
input clk ,
|
|
input rst_n ,
|
|
|
|
input enable ,
|
|
output interrupt ,
|
|
|
|
input pulse_ms ,
|
|
|
|
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 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'h0 ;
|
|
localparam ST_WAIT = 4'h1 ;
|
|
localparam ST_MSG_HEAD = 4'h2 ;
|
|
localparam ST_MSG_DATA_H = 4'h3 ;
|
|
localparam ST_MSG_RECORD = 4'h4 ;
|
|
localparam ST_MSG_DATA_T = 4'h5 ;
|
|
localparam ST_MSG_REG_VAL = 4'h6 ;
|
|
localparam ST_MSG_DA_AD = 4'h7 ;
|
|
localparam ST_MSG_TRIG_IN = 4'h8 ;
|
|
localparam ST_MSG_TRIG_OUT = 4'h9 ;
|
|
localparam ST_MSG_CRC = 4'hA ;
|
|
localparam ST_ADDITIONAL = 4'hB ;
|
|
|
|
localparam HEAD_LTH = 12 ;
|
|
localparam REG_LTH = 32 ;
|
|
localparam DA_AD_LTH = 32 ;
|
|
localparam TRIG_IN_LTH = 2 ;
|
|
localparam TRIG_OUT_LTH = 2 ;
|
|
localparam ADDL_LTH = 12 ;
|
|
|
|
//*****************************************************************************
|
|
// Internal register and wire declarations
|
|
//*****************************************************************************
|
|
reg [ 4-1:0] cstate ;
|
|
reg [ 4-1:0] nstate ;
|
|
|
|
wire [ 8-1:0] msg_head[0:HEAD_LTH-1] ;
|
|
|
|
reg [32-1:0] package_id ;
|
|
reg [32-1:0] overtime_ms ;
|
|
|
|
reg [32-1:0] trigger_word ;
|
|
wire [ 8-1:0] trigger_in_byte[0:15] ;
|
|
// wire [ 8-1:0] trigger_out_byte[0:15] ;
|
|
|
|
wire [ 8-1:0] msg_crc[0:1] ;
|
|
|
|
reg [32-1:0] upload_round_qty ;
|
|
reg [32-1:0] upload_rounds_cnt ;
|
|
|
|
reg [32-1:0] upload_bytes_cnt ;
|
|
wire [32-1:0] upload_bytes_cnt_add1 ;
|
|
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:12-1] ;
|
|
|
|
reg [ 8-1:0] byte_cnt ;
|
|
|
|
reg upload_break ;
|
|
reg upload_disable ;
|
|
|
|
//*****************************************************************************
|
|
// 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_WAIT:
|
|
if ( !enable || upload_rounds_cnt == upload_round_qty || overtime_ms == package_overtime_ms || m_axis_record_tfull )
|
|
nstate <= ST_MSG_CRC;
|
|
else if ( s_axis_eeg_tvalid )
|
|
nstate <= ST_MSG_HEAD;
|
|
else
|
|
nstate <= ST_WAIT;
|
|
|
|
ST_MSG_HEAD:
|
|
if ( byte_cnt == HEAD_LTH-1 )
|
|
nstate <= ST_MSG_DATA_H;
|
|
else
|
|
nstate <= ST_MSG_HEAD;
|
|
|
|
ST_MSG_DATA_H:
|
|
if ( byte_cnt == 48-1 )
|
|
nstate <= ST_MSG_RECORD;
|
|
else
|
|
nstate <= ST_MSG_DATA_H;
|
|
|
|
ST_MSG_RECORD:
|
|
if ( s_axis_eeg_tready && s_axis_eeg_tvalid && s_axis_eeg_tlast )
|
|
nstate <= ST_MSG_DATA_T;
|
|
else
|
|
nstate <= ST_MSG_RECORD;
|
|
|
|
ST_MSG_DATA_T:
|
|
if ( byte_cnt == 16-1 )
|
|
nstate <= ST_MSG_REG_VAL;
|
|
else
|
|
nstate <= ST_MSG_DATA_T;
|
|
|
|
ST_MSG_REG_VAL:
|
|
if ( byte_cnt == REG_LTH-1 )
|
|
nstate <= ST_MSG_DA_AD;
|
|
else
|
|
nstate <= ST_MSG_REG_VAL;
|
|
|
|
ST_MSG_DA_AD:
|
|
if ( byte_cnt == DA_AD_LTH-1 )
|
|
nstate <= ST_MSG_TRIG_IN;
|
|
else
|
|
nstate <= ST_MSG_DA_AD;
|
|
|
|
ST_MSG_TRIG_IN:
|
|
if ( byte_cnt == TRIG_IN_LTH-1 )
|
|
nstate <= ST_MSG_TRIG_OUT;
|
|
else
|
|
nstate <= ST_MSG_TRIG_IN;
|
|
|
|
ST_MSG_TRIG_OUT:
|
|
if ( byte_cnt == TRIG_OUT_LTH-1 )
|
|
nstate <= ST_WAIT;
|
|
else
|
|
nstate <= ST_MSG_TRIG_OUT;
|
|
|
|
ST_MSG_CRC:
|
|
if ( byte_cnt == 2-1 )
|
|
nstate <= ST_ADDITIONAL;
|
|
else
|
|
nstate <= ST_MSG_CRC;
|
|
|
|
ST_ADDITIONAL:
|
|
if ( byte_cnt == ADDL_LTH-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_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 )
|
|
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 )
|
|
package_id <= 0;
|
|
else if ( reset_package_id )
|
|
package_id <= 0;
|
|
else if ( cstate == ST_MSG_TRIG_OUT && nstate == ST_WAIT )
|
|
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 ( cstate == ST_MSG_DA_AD && nstate == ST_MSG_TRIG_IN )
|
|
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 ( nstate == ST_WAIT )
|
|
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 )
|
|
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 ) 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 )
|
|
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 <= msg_head[byte_cnt];
|
|
m_axis_record_tvalid <= 1'b1;
|
|
end else if ( cstate == ST_MSG_DATA_H ) begin
|
|
m_axis_record_tdata <= 8'd0;
|
|
m_axis_record_tvalid <= 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 <= 1'b1;
|
|
end else if ( cstate == ST_MSG_DATA_T ) begin
|
|
m_axis_record_tdata <= 8'd0;
|
|
m_axis_record_tvalid <= 1'b1;
|
|
end else if ( cstate == ST_MSG_REG_VAL ) begin
|
|
m_axis_record_tdata <= 8'd0;
|
|
m_axis_record_tvalid <= 1'b1;
|
|
end else if ( cstate == ST_MSG_DA_AD ) begin
|
|
m_axis_record_tdata <= 8'd0;
|
|
m_axis_record_tvalid <= 1'b1;
|
|
end else if ( cstate == ST_MSG_TRIG_IN ) begin
|
|
m_axis_record_tdata <= trigger_in_byte[byte_cnt];
|
|
m_axis_record_tvalid <= 1'b1;
|
|
end else if ( cstate == ST_MSG_TRIG_OUT ) begin
|
|
m_axis_record_tdata <= 8'd0;
|
|
m_axis_record_tvalid <= 1'b1;
|
|
end else if ( cstate == ST_MSG_CRC ) begin
|
|
m_axis_record_tdata <= msg_crc[byte_cnt];
|
|
m_axis_record_tvalid <= 1'b1;
|
|
end else if ( cstate == ST_ADDITIONAL ) begin
|
|
m_axis_record_tdata <= upload_addl[byte_cnt];
|
|
m_axis_record_tvalid <= 1'b1;
|
|
end else
|
|
m_axis_record_tvalid <= 1'b0;
|
|
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_LTH-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_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 )
|
|
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
|
|
//*****************************************************************************
|
|
assign msg_head[ 0] = 8'h0b;
|
|
assign msg_head[ 1] = 8'h2f;
|
|
assign msg_head[ 2] = 8'h71;
|
|
assign msg_head[ 3] = 8'h49;
|
|
assign msg_head[ 4] = 8'h8a;
|
|
assign msg_head[ 5] = 8'h2c;
|
|
assign msg_head[ 6] = 8'h54;
|
|
assign msg_head[ 7] = 8'h8d;
|
|
assign msg_head[ 8] = package_id[ 7: 0];
|
|
assign msg_head[ 9] = package_id[15: 8];
|
|
assign msg_head[10] = package_id[23:16];
|
|
assign msg_head[11] = package_id[31:24];
|
|
|
|
assign trigger_in_byte[ 0] = trigger_word[ 7: 0];
|
|
assign trigger_in_byte[ 1] = trigger_word[15: 8];
|
|
assign trigger_in_byte[ 2] = trigger_word[23:16];
|
|
assign trigger_in_byte[ 3] = trigger_word[31:24];
|
|
assign trigger_in_byte[ 4] = 8'd0;
|
|
assign trigger_in_byte[ 5] = 8'd0;
|
|
assign trigger_in_byte[ 6] = 8'd0;
|
|
assign trigger_in_byte[ 7] = 8'd0;
|
|
assign trigger_in_byte[ 8] = 8'd0;
|
|
assign trigger_in_byte[ 9] = 8'd0;
|
|
assign trigger_in_byte[10] = 8'd0;
|
|
assign trigger_in_byte[11] = 8'd0;
|
|
assign trigger_in_byte[12] = 8'd0;
|
|
assign trigger_in_byte[13] = 8'd0;
|
|
assign trigger_in_byte[14] = 8'd0;
|
|
assign trigger_in_byte[15] = 8'd0;
|
|
|
|
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
|