📄 pl4_lite_data_monitor.v
字号:
begin
// If the word is an SOP, check for spacing violations
if (TDat[12] == 1)
begin
if (TDatSopCnt < 7)
$display("TDat Error: Protocol Violation #6. Minimum SOP spacing not met. %0d ps", $time);
TDatSopCnt <= #`TFF 'b0;
end
// For non-SOP control words, increment the counter
else if (TDatSopCnt < 7)
TDatSopCnt <= #`TFF TDatSopCnt + 1;
else
TDatSopCnt <= #`TFF 'd7;
end
end
end
//******************************************************************************
// The following processes are used to generate dip4 and compare them with
// the incoming dip4's from TDat
//******************************************************************************
//******************************************************************************
// pipeline
//******************************************************************************
// This process defines the pipeline delay registers.
//******************************************************************************
always @(TDClk_align or negedge Reset_n or negedge TDatResetComplete)
begin: pipeline
if (!Reset_n || !TDatResetComplete)
begin
TCtl_s <= #`TFF 1'b1;
TCtl_d1 <= #`TFF 1'b1;
TDat_s <= #`TFF 16'h000f;
TDat_d1 <= #`TFF 16'h000f;
end
else
begin
TCtl_s <= #`TFF TCtl;
TDat_s <= #`TFF TDat;
TCtl_d1 <= #`TFF TCtl_s;
TDat_d1 <= #`TFF TDat_s;
end
end // pipeline
//******************************************************************************
// train_detect
//******************************************************************************
// This process detects when Training words are being sent.
//******************************************************************************
always @(TDClk_align or negedge Reset_n or negedge TDatResetComplete)
begin: train_detect
if (!Reset_n || !TDatResetComplete)
Training <= #`TFF 1'b0;
else
if((TCtl_s == 1'b1) && (TDat_s == `TRAINING_CTL))
Training <= #`TFF 1'b1;
else if ((TCtl_s == 1'b1) &&
(TDat_s != `TRAINING_CTL))
Training <= #`TFF 1'b0;
end // train_detect
//******************************************************************************
// data_reg
//***************************************************************************
// This process registers the DIP4 and DIP16 calculations
//***************************************************************************
always @(TDClk_align or negedge Reset_n or negedge TDatResetComplete)
begin: data_reg
if (!Reset_n || !TDatResetComplete)
begin
DIP16<= #`TFF 16'hFFFF;
DIP4 <= #`TFF 4'hF;
end
else
begin
DIP16 <= #`TFF NextDIP16;
DIP4 <= #`TFF NextDIP4;
end
end // data_reg
//*****************************************************************************
// dip16_calc
//****************************************************************************
// This process detects the type of word, data or control, and calculates the
// DIP16 word.
//****************************************************************************
always @(DIP16, TCtl_s, TCtl_d1, TDat_s)
begin: dip16_calc
// If this is the first data word, load it into DIP16
if((TCtl_s == 1'b0) && (TCtl_d1 == 1'b1))
NextDIP16 = TDat_s;
// else if this is a subsequent data word, ^ it with DIP16
else if((TCtl_s == 1'b0) && (TCtl_d1 == 1'b0))
NextDIP16 = TDat_s ^ {DIP16[0], DIP16[15:1]} ;
// else if this is terminating control word, ^ it with DIP16
else if((TCtl_s == 1'b1) && (TCtl_d1 == 1'b0))
NextDIP16 = {TDat_s[15:4],4'b1111} ^ {DIP16[0],DIP16[15:1]};
// else if this is a subsequent control word, load it into DIP16
else if((TCtl_s == 1'b1) && (TCtl_d1 == 1'b1))
NextDIP16 = {TDat_s[15:4],4'b1111};
else
NextDIP16 = DIP16;
end
//******************************************************************************
// DIP4 calculations (combinitorial). It gets registered in data_reg.
//******************************************************************************
assign NextDIP4[3]= NextDIP16[15] ^ NextDIP16[11] ^ NextDIP16[7] ^ NextDIP16[3];
assign NextDIP4[2]= NextDIP16[14] ^ NextDIP16[10] ^ NextDIP16[6] ^ NextDIP16[2];
assign NextDIP4[1]= NextDIP16[13] ^ NextDIP16[9] ^ NextDIP16[5] ^ NextDIP16[1];
assign NextDIP4[0]= NextDIP16[12] ^ NextDIP16[8] ^ NextDIP16[4] ^ NextDIP16[0];
//*****************************************************************************
// check_dip4
//*****************************************************************************
// This process uses the pipelined signals to check the DIP4 value.
//*****************************************************************************
always @(TDClk_align or negedge Reset_n or negedge TDatResetComplete)
begin: check_dip4
if (!Reset_n || !TDatResetComplete)
;
else
begin
if ((TCtl_d1 == 1) && (TDat_d1[3:0] != DIP4))
$display("TDat Error: DIP4 Error. Expected %h, Received: %h. %0d ps", $time, DIP4, TDat_d1[3:0]);
end
end
//*****************************************************************************
// Check for Buffer Overflow
//*****************************************************************************
always @(posedge RDClk or negedge RDClk or negedge Reset_n)
begin: buf_ovflw
if (!Reset_n)
BufferOverflow <= 1'b0;
else
begin
if (RDatDataIndexPlus1 == TDatDataIndex)
begin
if (BufferOverflow == 1'b0)
begin
$display("Testbench Monitor Fifo Overflow: Expect Data Mismatches. %0d ps", $time);
BufferOverflow <= 1'b1;
end
end
end
end
//*****************************************************************************
// Check that simulation has completed and last data has been verified
//*****************************************************************************
always @(posedge RDClk or negedge RDClk or negedge Reset_n)
begin: buf_empty
if (!Reset_n)
BufferEmpty <= 1'b0;
else
begin
// Last data sent by testbench has been received
if (TDatDataIndex+1 == RDatDataIndex)
begin
if (GotFirstTDat == 1'b1)
begin
$display("Source core sent its last data. %0d ps", $time); // rle
end
if (TCComplete == 1'b1)
begin
// Check to make sure core is enabled, sink clk-data alignment is completed,
// sink received first data and source sent first data
if ((GotFirstTDat == 1'b1) && (RDatFirst == 1'b1) && (BothEnabled_d2 == 1'b1)
&& (ValidCheck == 1'b1))
begin
$display("Simulation stopped %0d ps", $time);
end
else
$display("ERROR: TEST FAILED %0d ps", $time);
BufferEmpty <= 1'b1;
$finish;
end
end
end
end
//*****************************************************************************
// Check for both Sink and Source core enabled
//*****************************************************************************
always @(posedge RDClk or negedge RDClk or negedge Reset_n)
begin: align
if (!Reset_n)
begin
BothEnabled_d1 <= #`TFF 1'b0;
BothEnabled_d2 <= #`TFF 1'b0;
ValidCheck <= #`TFF 1'b0;
end
else
begin
BothEnabled_d1 <= #`TFF SrcEn & SnkEn;
BothEnabled_d2 <= #`TFF BothEnabled_d1;
if ((BothEnabled_d1 == 1'b1) && (BothEnabled_d2 == 1'b0) && (ValidCheck == 1'b0))
begin
ValidCheck <= #`TFF 1'b1;
$display("Timing checks are valid. %0d ps", $time);
end
end
end
//*****************************************************************************
// Check SnkOof
//*****************************************************************************
always @(posedge RDClk or negedge RDClk or negedge Reset_n)
begin: snkf
if (!Reset_n)
begin
SnkOof_d1 <= #`TFF 1'b0;
SnkOof_d2 <= #`TFF 1'b0;
end
else
begin
SnkOof_d1 <= #`TFF SnkOof;
SnkOof_d2 <= #`TFF SnkOof_d1;
if ((SnkOof_d1 == 1'b0) && (SnkOof_d2 == 1'b1))
begin
$display("Sink core in frame. %0d ps", $time);
end
end
end
//*****************************************************************************
// Check SrcOof
//*****************************************************************************
always @(posedge RDClk or negedge RDClk or negedge Reset_n)
begin: srcf
if (!Reset_n)
begin
SrcOof_d1 <= #`TFF 1'b0;
SrcOof_d2 <= #`TFF 1'b0;
end
else
begin
SrcOof_d1 <= #`TFF SrcOof;
SrcOof_d2 <= #`TFF SrcOof_d1;
if ((SrcOof_d1 == 1'b0) && (SrcOof_d2 == 1'b1))
begin
$display("Source core in frame. %0d ps", $time);
end
end
end
//*****************************************************************************
// Check for sink and source core alignment
//*****************************************************************************
always @(posedge RDClk or negedge RDClk or negedge Reset_n)
begin: snknsrcf
if (!Reset_n)
begin
BothInFrame_d1 <= #`TFF 1'b0;
BothInFrame_d2 <= #`TFF 1'b0;
end
else
begin
BothInFrame_d1 <= #`TFF !(SnkOof | SrcOof);
BothInFrame_d2 <= #`TFF BothInFrame_d1;
if ((BothInFrame_d1 == 1'b1) && (BothInFrame_d2 == 1'b0))
begin
$display("Both Sink and Source core are synchronized. %0d ps", $time);
end
end
end
//*****************************************************************************
// Check for sink core received its first data
//*****************************************************************************
always @(posedge RDClk or negedge RDClk or negedge Reset_n)
begin: snkd
if (!Reset_n)
begin
SnkFFEmpty_n_d1 <= #`TFF 1'b0;
SnkFFEmpty_n_d2 <= #`TFF 1'b0;
RDatFirst <= #`TFF 1'b0;
end
else
begin
SnkFFEmpty_n_d1 <= #`TFF SnkFFEmpty_n;
SnkFFEmpty_n_d2 <= #`TFF SnkFFEmpty_n_d1;
if ((SnkFFEmpty_n_d1 == 1'b1) && (SnkFFEmpty_n_d2 == 1'b0) && (RDatFirst == 1'b0))
begin
$display("Sink core received its first data. %0d ps", $time);
RDatFirst <= #`TFF 1'b1;
end
end
end
//*****************************************************************************
// Check for source core sent its first data
//*****************************************************************************
always @(posedge RDClk or negedge RDClk or negedge Reset_n)
begin: srcd
if (!Reset_n)
begin
GotFirstTDat <= #`TFF 1'b0;
end
else
begin
if ((TDatFirst == 1'b1) && (GotFirstTDat == 1'b0))
begin
$display("Source core sent its first data. %0d ps", $time);
GotFirstTDat <= #`TFF 1'b1;
end
end
end
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -