//
// pli.V
//
// PLI provides the interface between the PHY and LINK
// The protocols are the same as described in the Annex J o fthe standard.
//LINK = Link Layer; PHY = Physical Layer
module PLI
(
BCLK,
SCLK, //Input from PHY: less freq than BCLK (49.152 MHz)
//The clock is used to clock data between physical and LINK
RE, //Read signal to Packet Memory
stcmp, //Status complete signal to receiver-(status transfer)
pipe_en, //enable signal to quad assem
reception, // To indicate transaction layer that LINK is busy in
//receiving a packet from PHY
lreq, //request signal to PHY
ctrl_pins, //used to transfer control information to receiver and transmitter
reset_n,
strobe, //to strobe Req_type from transmitter
ERROR, //destination error
packet_error, //bad header or data CRC
data_end, //data end signal from packet memory
broadcast, //transfer of a broadcast packet
monitor, //control pins from transmitter
Req_Type, //request information
ctl, //defines the state of the interface between physical an LINK
D //Data bus (8): packet data is delivered by the bus
);
input BCLK,SCLK,data_end,reset_n, strobe,packet_error,broadcast,ERROR;
wire BCLK,SCLK,data_end,reset_n, strobe,packet_error,broadcast,ERROR;
input [2:0] monitor;
wire [2:0] monitor;
input [0:16] Req_Type;
wire [0:16] Req_Type;
output RE,stcmp,pipe_en,reception,lreq;
wire lreq,reception;
reg RE,stcmp,pipe_en;
output [2:0] ctrl_pins;
reg [2:0] ctrl_pins;
inout [1:0] ctl;
input [7:0] D;
wire [1:0] ctl;
wire [7:0] D;
reg shift_en, run_timer, timeout, pli_ctl, data_flag, transmit_signal, requestsent;
reg transmit_allowed, imm_flag, error_pack, broadcast_flag;
reg [3:0] current_state, next_state;
reg [0:17] LREQ;
reg [15:0] timeoutclockperiods, counter;
reg [4:0] shift_length, count;
reg [1:0] ctl_driver;
assign lreq=LREQ[0];
////////////STATES//////////////
parameter IDLE =4'b0000;
parameter REQUEST =4'b0001;
parameter WAIT_state =4'b0010;
parameter LOST =4'b0011;
parameter WON =4'b0100;
parameter HOLD =4'b0101;
parameter TRANSMISSION =4'b0110;
parameter WAIT_ACK =4'b0111;
parameter ACK_RECEIVE =4'b1000;
parameter DATA_ON =4'b1001;
parameter RECEIVE =4'b1010;
parameter WAIT_FOR_GRANT =4'b1011;
parameter WON_ACK =4'b1100;
parameter READ_REQUEST =4'b1101;
parameter STATUS_RECEIVING =4'b1110;
parameter IMMREQ =4'b1111;
////////////////////////////////
/////////////CTRL_PINS/////////
parameter idle =3'b000;
parameter Timeout =3'b001;
parameter ack_receive =3'b010;
parameter receive =3'b011;
parameter won =3'b100;
parameter status =3'b101;
//////////////////////////////
////////////ctl///////////////
parameter Idle =2'b00;
parameter Status =2'b01;
parameter Receive =2'b10;
parameter Transmit =2'b11;
//////////////////////////////
////////////monitor///////////
parameter idle_m =3'b000;
parameter sop =3'b001;
parameter transmit =3'b010;
parameter hold =3'b011;
parameter Imm_req =3'b101;
parameter status_R =3'b110;
parameter status_W =3'b111;
//////////////////////////////
assign ctl= pli_ctl ? ctl_driver : 2'bzz; //when LINK is driving the ctl
assign reception = (ctl == Receive && !pli_ctl) ? 1'b1 : 1'b0;
/////////////current_state///////////
always @(posedge BCLK or negedge reset_n)
begin
if(!reset_n)
current_state = IDLE;
else
current_state = next_state;
end
/////////////////////////////////////
////////////state machine /////////////
always @(ctl or monitor or requestsent or timeout or data_end or D )
begin
case(current_state)
IDLE: ////0
begin
if(ctl == Idle && monitor == sop)
next_state = REQUEST;
else if(ctl == Receive && D == 8'hff)
next_state = DATA_ON;
else if(monitor == Imm_req)
next_state = IMMREQ;
else if(ctl == Idle && (monitor == status_R || monitor == status_W) )
next_state = READ_REQUEST;
else if(ctl == Status)
next_state = STATUS_RECEIVING;
else
next_state = IDLE;
end
REQUEST: ////1
begin
if(requestsent)
next_state = WAIT_state;
else if(ctl == Receive)
next_state = LOST;
else
next_state = REQUEST;
end
WAIT_state: //////2
begin
if(ctl == Transmit)
next_state = WON;
else if(ctl == Receive)
next_state = LOST;
else if(timeout)
next_state = IDLE;
else
next_state = WAIT_state;
end
LOST: ////3
next_state = IDLE;
WON: ////4
begin
if(monitor == hold)
next_state = HOLD;
else if(monitor == transmit)
next_state = TRANSMISSION;
else
next_state = WON;
end
HOLD: ////5
begin
if(monitor == transmit)
next_state = TRANSMISSION;
else
next_state = HOLD;
end
TRANSMISSION: ////6
begin
if(data_end && broadcast_flag)
next_state = IDLE;
else if(data_end)
next_state = WAIT_ACK;
else
next_state = TRANSMISSION;
end
WAIT_ACK: ////7
begin
if(ctl == Receive && !pli_ctl)
next_state = ACK_RECEIVE;
else if(timeout)
next_state = IDLE;
else
next_state = WAIT_ACK;
end
ACK_RECEIVE: ////8
begin
if(ctl == Idle)
next_state = IDLE;
else
next_state = ACK_RECEIVE;
end
DATA_ON: ////9
begin
if( D != 8'hff ) // && ctl == Receive)
next_state = RECEIVE;
else
next_state = DATA_ON;
end
RECEIVE: ////10
begin
if(packet_error)
next_state = IDLE;
else if(ctl == Idle && shift_length == 1 && imm_flag) // This statement
//automatically controls the arrival of immreq whether during
//reception of packet or immreq is received after reception.
next_state = WAIT_FOR_GRANT;
else if(ctl == Idle && broadcast_flag)
next_state = IDLE;
else
next_state = RECEIVE;
end
WAIT_FOR_GRANT: ////11
begin
if(ctl == Transmit)
next_state = WON_ACK;
else if(timeout)
next_state = IDLE;
else
next_state = WAIT_FOR_GRANT;
end
WON_ACK: ////12
begin
if(data_end)
next_state = IDLE;
else
next_state = WON_ACK;
end
READ_REQUEST: ////13
begin
if(requestsent)
next_state = IDLE;
else if(ctl == Receive)
next_state = LOST;
else
next_state = READ_REQUEST;
end
STATUS_RECEIVING: ////14
begin
if(ctl == Idle)
next_state = IDLE;
else if(ctl == Receive)
next_state = LOST;
else
next_state = STATUS_RECEIVING;
end
IMMREQ: ////15 // If there is packet error then this state will be helpful for
// transfer of acknowledgement
if(shift_length == 1 && ctl == Idle)
next_state = WAIT_FOR_GRANT;
else
next_state = IMMREQ;
endcase
end
//////////////////////////////
///////////CTRL_PINS//////////
always @(ctl or current_state or timeout)
begin
if(current_state == LOST)
ctrl_pins = receive;
else if(current_state == WON || current_state == HOLD)
ctrl_pins = won;
else if(current_state == WAIT_ACK && ctl == Receive && !pli_ctl)
ctrl_pins = ack_receive;
else if(timeout)
ctrl_pins = Timeout;
else if(current_state == RECEIVE && ctl == Receive && !error_pack)
ctrl_pins = receive;
else if(current_state == WAIT_FOR_GRANT && ctl == Transmit)
ctrl_pins = won;
else if(current_state == WAIT_FOR_GRANT)
ctrl_pins = idle;
else if(current_state == STATUS_RECEIVING)
ctrl_pins = status;
else if(current_state == IDLE)
ctrl_pins = idle;
end
///////////////shift_en/////////////
//to enable the shift register
always @(negedge BCLK or negedge reset_n)
begin
if(!reset_n) // || requestsent)
shift_en = 0;
else if(requestsent)
shift_en = 0;
else if(monitor == sop || monitor == Imm_req || monitor == status_R || monitor == status_W)
shift_en = 1;
end
/////////////////run_timer////////////
//to enable the timer
always @(posedge BCLK or negedge reset_n or posedge timeout)
begin
if(!reset_n)
run_timer <= 1'b0;
else if(timeout)
run_timer <= 1'b0;
else if(current_state == WAIT_state|| current_state == WAIT_ACK || current_state == WAIT_FOR_GRANT)
run_timer <= 1'b1;
else
run_timer <= 1'b0;
end
//////////////////shift_length///////////
//length of the request word
always @(negedge BCLK or negedge reset_n)
begin
if(!reset_n)
shift_length = 1;
else if(requestsent)
shift_length = 1;
else if(monitor == sop)
shift_length = 7;
else if(monitor == Imm_req)
shift_length = 7;
else if(monitor == status_R)
shift_length = 9;
else if(monitor == status_W)
shift_length = 17;
end
///////////////count for LREQ//////////////
always @(posedge BCLK or negedge reset_n)
begin
if(!reset_n)
begin
count = 0;
requestsent = 0;
end
else if(requestsent)
begin
count = 0;
requestsent =0;
end
else if(count == shift_length)
begin
count = 0;
requestsent = 1;
end
else if(shift_en)
begin
count = count + 1;
requestsent = 0;
end
end
/////////////////LREQ///////////////////
//to shift out the LREQ
always @(posedge BCLK or negedge reset_n)
begin
if(!reset_n)
LREQ <= 18'b000000000000000000;
else if(requestsent)
LREQ <= 18'b000000000000000000;
else if(strobe)
LREQ <= Req_Type;
else if(shift_en)
LREQ <= LREQ << 1;
end
//to latch the transmit request from transmitter
always @(negedge BCLK)
begin
if(RE)
transmit_signal = 1'b0;
else if(monitor == transmit)
transmit_signal = 1'b1;
end
//read enable the packet memory
always @(posedge SCLK)
begin
if(RE)
RE = 1'b0;
else if(transmit_signal)
RE = 1'b1;
end
//packet memory is transferring data
always @(negedge BCLK)
begin
if(data_end)
transmit_allowed <= 1'b0;
else if(RE)
transmit_allowed <= 1'b1;
end
///////////////CTL//////////////
always @(posedge SCLK)
begin
if(transmit_signal)
begin
ctl_driver <= 2'b01;
pli_ctl <= 1;
end
else if(monitor == hold)
begin
ctl_driver <= 2'b01; //hold
pli_ctl <= 1; ///////indicates control is driven by PLI//////
end
else if(transmit_allowed)
begin
ctl_driver <= 2'b10; //transmit
pli_ctl <= 1;
end
else if(data_end) //NOTE: data_end should remain HIGH for two clock cycles by PM
begin
ctl_driver <= 2'b00; //idle
pli_ctl <= 1;
end
else
begin
ctl_driver <= 2'b00;
pli_ctl <= 0;
end
end
////////////////////stcmp//////////////
always @(negedge BCLK)
begin
if( (current_state == ACK_RECEIVE || current_state == STATUS_RECEIVING)&& ctl == Idle)
stcmp = 1;
else
stcmp = 0;
end
///////////////////pipe_en////////////////
always @(negedge BCLK)
begin
if( data_flag && !error_pack) //Status == 01;
pipe_en = 1;
else
pipe_en = 0;
end
////////////data_flag indicates arrival of data after dataon /////////
always @(ctl or D or reset_n)
begin
if( ctl == Idle || !reset_n )
data_flag = 0;
else if( (ctl == Receive && pli_ctl == 1'b0) && D != 8'hff)
data_flag = 1;
end
/////////////////register to hold timeoutclockperiods//////////
always @(negedge BCLK or posedge timeout or negedge reset_n)
begin
if(!reset_n)
timeoutclockperiods = 1;
else if(timeout)
timeoutclockperiods = 1;
else if(monitor == sop)
timeoutclockperiods = 250; // need to change
else if(monitor == Imm_req)
timeoutclockperiods = 450;
else if(monitor == transmit)
timeoutclockperiods = 692;
end
always @(posedge BCLK)
begin
if(run_timer)
counter = counter + 1;
else
counter = 0;
end
always @(negedge BCLK)
begin
if(timeout)
timeout <= 1'b0;
else if(counter == timeoutclockperiods)
timeout <= 1'b1;
end
always @(negedge BCLK)
begin
if(run_timer)
imm_flag <= 1'b0;
else if(monitor == Imm_req)
imm_flag <= 1'b1;
end
always @(negedge BCLK or negedge data_flag)
begin
if(!data_flag)
error_pack <= 1'b0;
else if(packet_error || ERROR)
error_pack <= 1'b1;
end
always @(posedge BCLK or negedge reset_n)
begin
if(!reset_n)
broadcast_flag <= 1'b0; // There is no need to bring down broadcast_flag to
//logic LOW by some logic, because it is assumed that after complete transaction LINK
//must be externally reset_n.
else if(broadcast)
broadcast_flag <= 1'b1;
end
endmodule