module receiver
( BCLK,
reset_n,
decode_error,
decode_complete,
data_payload,
stcmp,
quad_fill, //from parallel processable memory, available at negedge BCLK for single period
header_length,
CTRL_PINS,
CALC_CRC,
parallel_data, // from parallel process memory
ERROR,
decode,
reset_decoder,
write_csr, // write signal to CSR
crc_in,
DATA_CSR,
ADDR_CSR,
DATA_FIFO_CRC_DEC,
packet_error,
packet_good,
push,
fifo_mode, // set fifo mode for reception
reset_crc
// internal flags
/* current_state, //////////
next_state,
data_length,
statusflag,statusword,status_value,push_word,status_push,reception_complete,
write_csr_flag,check_parity_flag,error_reg_flag,before_ackflag,ackflag,quad_flag,stcmp_flag,reset_decoder_flag,receiveflag,
error_reg,crc_alert,receive_state_flag,reset_crc_flag,
temp_reg,d_payload,d_error,h_length,rec_counter,head_complete,packet_complete,data_available
*/);
///////////STATE PARAMETERS/////////////
parameter IDLE = 2'b00;
parameter STATUS = 2'b01;
parameter ACKRECEIVE = 2'b10;
parameter RECEIVE = 2'b11;
//////////OTHER PARAMETERS//////////////
parameter Idle =3'b000;
parameter Status =3'b101;
parameter Ack_Receive=3'b010;
parameter Receive =3'b011;
//////////Outputs///////////////////////
output push,fifo_mode,packet_good,packet_error,reset_crc,reset_decoder,write_csr,decode,crc_in,ERROR;
output [3:0] ADDR_CSR;
output [15:0] DATA_CSR;
output [31:0] DATA_FIFO_CRC_DEC;
reg fifo_mode,packet_good,packet_error,reset_crc,reset_decoder,write_csr,decode,crc_in,ERROR;
reg [3:0] ADDR_CSR;
reg [15:0] DATA_CSR;
wire [31:0] DATA_FIFO_CRC_DEC;
wire push;
/////////Inputs//////////////////////////
input BCLK,reset_n,decode_error, decode_complete,data_payload,stcmp,quad_fill;
input [2:0] header_length;
input [2:0] CTRL_PINS;
input [31:0] CALC_CRC;
input [31:0] parallel_data;
wire BCLK,reset_n,decode_error, decode_complete,data_payload,stcmp,quad_fill;
wire [2:0] header_length;
wire [2:0] CTRL_PINS;
wire [31:0] CALC_CRC;
wire [31:0] parallel_data;
////////State Registers///////////////////////
/*output [1:0] current_state,next_state;*/
reg [1:0] current_state;
reg [1:0] next_state;
/////////Internal Registers///////////////////
/*output d_payload,d_error,head_complete,status_value,statusword,push_word,status_push;
output [3:0] error_reg;
output [7:0] temp_reg;
output [9:0] rec_counter;
output [2:0] h_length;
output [15:0] data_length;
*/
reg d_payload,d_error,head_complete,status_value,statusword,push_word,status_push;
reg [3:0] error_reg;
reg [7:0] temp_reg;
reg [9:0] rec_counter;
reg [2:0] h_length;
reg [15:0] data_length;
////////Internal Flags////////////////////////
//output crc_alert,statusflag,write_csr_flag,check_parity_flag,error_reg_flag,before_ackflag,ackflag,quad_flag,stcmp_flag,receiveflag,receive_state_flag,reset_decoder_flag;
reg crc_alert,statusflag,write_csr_flag,check_parity_flag,error_reg_flag,before_ackflag,ackflag,quad_flag,stcmp_flag,receiveflag,reset_decoder_flag;
//output reset_crc_flag,packet_complete,data_available,reception_complete;
reg reset_crc_flag,packet_complete,data_available,reception_complete;
//................................................................................................................................................
//Module : receiver_seq
//Purpose: receiver state machine state register
//Inputs : BCLK,reset_n,next_state
//Outputs: current_state
//................................................................................................................................................
always @(posedge BCLK or negedge reset_n)
begin
if(!reset_n)
current_state <= IDLE;
else
current_state <= next_state;
end
//................................................................................................................................................
always @(current_state or CTRL_PINS or statusflag or ackflag or receiveflag)
begin
case(current_state)
IDLE:
if(CTRL_PINS == Receive)
next_state <= RECEIVE;
else if(CTRL_PINS == Ack_Receive)
next_state <= ACKRECEIVE;
else if(CTRL_PINS == Status)
next_state <= STATUS;
else
next_state <= IDLE;
STATUS:
if(/*CTRL_PINS == Idle &&*/ statusflag==1)
next_state<=IDLE;
else
next_state<=STATUS;
ACKRECEIVE:
if(/*CTRL_PINS == Idle && */ackflag == 1)
next_state<=IDLE;
else
next_state<=ACKRECEIVE;
RECEIVE:
if(/*CTRL_PINS == Idle && */receiveflag == 1)
next_state <=IDLE;
else
next_state<=RECEIVE;
endcase
end
//................................................................................................................................................
//Module : receiver_operations
//Purpose: verification and transfer of data to FIFO
//Inputs :
//Outputs:
//................................................................................................................................................
always@(posedge BCLK or negedge reset_n)
begin
if(!reset_n)
begin
// fifo_mode <= 1'b0;
write_csr_flag <= 1'b0;
write_csr <= 1'b0;
statusflag <= 1'b0;
check_parity_flag <= 1'b0;
error_reg_flag <= 1'b0;
before_ackflag <= 1'b0;
ackflag <= 1'b0;
receiveflag <= 1'b0;
fifo_mode <= 1'b0;
ERROR <= 1'b0;
error_reg <= 4'b0000;
temp_reg <= 8'h00;
DATA_CSR <= 16'h0000;
ADDR_CSR <= 4'b0000;
end
else
case(next_state)
IDLE:
begin
// fifo_mode <= 1'b0;
write_csr_flag <= 1'b0;
write_csr <= 1'b0;
statusflag <= 1'b0;
check_parity_flag <= 1'b0;
error_reg_flag <= 1'b0;
before_ackflag <= 1'b0;
ackflag <= 1'b0;
receiveflag <= 1'b0;
fifo_mode <= 1'b0;
ERROR <= 1'b0;
error_reg <= 4'b0000;
temp_reg <= 8'h00;DATA_CSR <= 16'h0000;
ADDR_CSR <= 4'b0000;
end
STATUS:
begin
if(quad_fill && !write_csr_flag)
begin
DATA_CSR<={4'b0000, parallel_data[7:0], 4'b0000};
ADDR_CSR<=4'h3; //ADDRESS OF CSR
write_csr_flag <= 1;
end
else if(write_csr_flag)
begin
write_csr<=1;
write_csr_flag<=0;
statusflag<=1;
end
end
ACKRECEIVE:
begin
if( ( stcmp_flag && quad_flag ) && !check_parity_flag )
begin
temp_reg<=parallel_data[7:0];
check_parity_flag<=1;
end
else if(check_parity_flag && !error_reg_flag)
begin
error_reg<=temp_reg [7:4] ^ temp_reg[3:0];
check_parity_flag<=0;
error_reg_flag<=1;
end
else if(error_reg_flag && !before_ackflag)
begin
ADDR_CSR <= 4'h1;
error_reg_flag <= 0;
before_ackflag<=1;
if(error_reg == 4'hf) // no error
DATA_CSR<={temp_reg[7:4],1'b0, 1'b1, 10'b0000000000};
// !!!Alert!!! check whether temp_reg[7:4] or [3:0] ?
// {temp_reg(4 bits), 0=no error : 1= error, valid ack, six zeros}
//valid ack: this bit should be reset by transaction layer after it has retrieved the ack code
else
DATA_CSR<={temp_reg[7:4],1'b1, 1'b1, 10'b0000000000};
end
else if(before_ackflag)
begin
before_ackflag<=0;
write_csr<=1;
ackflag<=1;
end
end
RECEIVE:
begin
fifo_mode <= 1'b1;
if(!reset_decoder ) //check, this statement may be written as else if with upper if block.
begin
case(d_error)
1'b0:
begin
receiveflag <= 1'b0;
ERROR <= 1'b0; //Universal Error due to destination
// fifo_mode <= 1'b1; // or t_code
end
1'b1:
begin
receiveflag <= 1'b1;
ERROR <= 1;
// fifo_mode <= 1'b0;
end
endcase
end
else if(reception_complete)
begin
receiveflag <= 1'b1;
ERROR <= 1'b0; // This signal doesnot indicate corrupt CRC
// fifo_mode <= 1'b0;
end
/*else begin
receiveflag <= 1'b0;
ERROR <= 1'b0;
fifo_mode <= 1'b0; end */
end
endcase
end
always @(posedge stcmp or posedge check_parity_flag )
begin
if(check_parity_flag)
stcmp_flag <= 1'b0;
else
stcmp_flag <= 1'b1;
end
always @(posedge quad_fill or posedge check_parity_flag or posedge statusflag )
begin
if(check_parity_flag)
quad_flag <= 1'b0;
else if(statusflag)
quad_flag <= 1'b0;
else
quad_flag <= 1'b1;
end
always @(posedge quad_fill or posedge receiveflag or negedge reset_n or posedge reset_crc)
begin
if(!reset_n)
rec_counter <= 10'h0;
else if(reset_crc)
rec_counter <= 10'h0;
else if(receiveflag)
rec_counter <= 10'h0;
else if(fifo_mode)
rec_counter <= rec_counter + 1;
end
always @(posedge BCLK)
begin
if(rec_counter == 1 && !data_available) // No problem if decode remains high as long as rec_counter = 1
decode <= 1'b1; // because decoder works on the positive edge of decode so if
// decode remains high for more than one clock periods than it
//will cause no harm i.e. all is OKAY.
else
decode <= 1'b0;
end
always @(posedge BCLK or negedge reset_n)
begin
if(!reset_n)
begin
h_length <= 3'b101;
d_payload <= 1'b0;
d_error <= 1'b0;
end
else if(decode_complete)
begin
h_length <= header_length;
d_payload <= data_payload;
d_error <= decode_error; // In decoder provide the facility for checking broadcast address i.e. FFFF for deciding error
end
else if(reset_crc_flag)
begin
h_length <= 3'b000;
d_payload <= 1'b0;
d_error <= 1'b0;
end
else if(receiveflag)
begin
h_length <= 3'b101;
d_payload <= 1'b0;
d_error <= 1'b0;
end
end
always @ (posedge BCLK or negedge reset_n)
begin
if(!reset_n)
begin
reset_decoder <= 1'b1;
reset_decoder_flag <= 1'b0;
end
else if(decode_complete && !reset_decoder_flag)
begin
reset_decoder_flag <= 1'b1;
reset_decoder <= 1'b1;
end
else if(reset_decoder_flag)
begin
reset_decoder <= 1'b0;
reset_decoder_flag <= 1'b0;
end
else
begin
reset_decoder <= 1'b1;
reset_decoder_flag <= 1'b0;
end
end
always @(negedge quad_fill or posedge crc_in)
begin
if(crc_in)
crc_alert <= 1'b0;
else if(data_available && !packet_complete && fifo_mode)
crc_alert <= 1'b1;
else if(!head_complete && fifo_mode && !data_available)
crc_alert <= 1'b1;
end
always @(posedge BCLK or negedge reset_n)
begin
if(!reset_n)
head_complete <= 1'b0;
else if(head_complete)
head_complete <= 1'b0;
else if( rec_counter == (h_length+1) && !data_available)
head_complete <= 1'b1;
end
always @(posedge BCLK or negedge reset_n)
begin
if(!reset_n)
packet_complete <= 1'b0;
else if(packet_complete)
packet_complete <= 1'b0;
else if( (rec_counter == (data_length+1) && data_available) || (packet_error && d_payload) )
packet_complete <= 1'b1;
end
always @(posedge BCLK)
begin
if(crc_alert)
begin
crc_in <= 1'b1;
push_word <= 1'b1;
end
else
begin
crc_in <= 1'b0;
push_word <= 1'b0;
end
end
always @(negedge BCLK)
begin
if(reset_crc_flag)
begin
packet_good <= 1'b0;
packet_error <= 1'b0;
reset_crc_flag <= 1'b0;
reset_crc <= 1'b1;
end
else if( (rec_counter == (h_length + 1) || rec_counter == (data_length + 1)) && rec_counter > 1)
begin
if(parallel_data == CALC_CRC)
begin
packet_good <= 1'b1;
packet_error <= 1'b0;
reset_crc_flag <= 1'b1;
reset_crc <= 1'b0;
end
else
begin
packet_good <= 1'b0;
packet_error <= 1'b1;
reset_crc_flag <= 1'b1;
reset_crc <= 1'b0;
end
end
else
begin
packet_good <= 1'b0;
packet_error <= 1'b0;
reset_crc_flag <= 1'b0;
reset_crc <= 1'b0;
end
if(receiveflag)
statusword <= 1'b0;
else if(head_complete && !d_payload)
statusword <= 1'b1;
else if(packet_complete)
statusword <= 1'b1;
if(status_push)
reception_complete <= 1'b1;
else
reception_complete <= 1'b0;
end
always @(posedge packet_good or posedge packet_error or negedge reset_n)
begin
if(!reset_n)
status_value <= 1'b0;
else if(packet_good)
status_value <= 1'b1; // All one in status word
else
status_value <= 1'b0; // All zero in status word
end
always @(posedge reset_crc_flag or posedge receiveflag)
begin
if(receiveflag)
data_available <= 1'b0;
else if(d_payload)
data_available <= 1'b1;
end
always @(posedge BCLK or posedge receiveflag)
begin
if(receiveflag)
data_length = 16'h0000;
else if(rec_counter == 4 && !data_available)
data_length = parallel_data[31:16] >> 2; // divide by 4 to get number of quadlets.
if(!reset_n)
status_push <= 1'b0;
else if(status_push)
status_push <= 1'b0;
else if(reset_crc && statusword)
status_push <= 1'b1;
end
assign push = push_word | status_push;
assign DATA_FIFO_CRC_DEC = statusword ? (status_value ? 31'hffffffff : 31'h00000000) : parallel_data;
// good packet // bad packet
endmodule