OpenCores
URL https://opencores.org/ocsvn/iso7816_3_master/iso7816_3_master/trunk

Subversion Repositories iso7816_3_master

[/] [iso7816_3_master/] [trunk/] [test/] [RxCoreTestBench.v] - Rev 5

Go to most recent revision | Compare with Previous | Blame | View Log

`timescale 1ns / 1ps
 
////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer:
//
// Create Date:   21:02:24 09/02/2010
// Design Name:   RxCore
// Module Name:   tb_RxCore.v
// Project Name:  Uart
// Target Device:  
// Tool versions:  
// Description: 
//
// Verilog Test Fixture created by ISE for module: RxCore
//
// Dependencies:
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
////////////////////////////////////////////////////////////////////////////////
 
module tb_RxCoreComparator(
	output reg implMismatch,
    output [7:0] dataOut,
    output overrunErrorFlag,	//new data has been received before dataOut was read
    output dataOutReadyFlag,	//new data available
    output frameErrorFlag,		//bad parity or bad stop bits
    output endOfRx,
    output run,					//rx is definitely started, one of the three flag will be set
    output startBit,				//rx is started, but we don't know yet if real rx or just a glitch
	 input [CLOCK_PER_BIT_WIDTH-1:0] clocksPerBit,			
	 input stopBit2,//0: 1 stop bit, 1: 2 stop bits
	 input ackFlags,
	 input serialIn,
    input clk,
    input nReset
    );
 
parameter CLK_PERIOD = 10;//should be %2
//parameters to override
parameter CLOCK_PER_BIT_WIDTH = 13;	//allow to support default speed of ISO7816
//invert the polarity of the output or not
parameter IN_POLARITY = 1'b0;
parameter PARITY_POLARITY = 1'b0;
//default conventions
parameter START_BIT = 1'b0;
parameter STOP_BIT1 = 1'b1;
parameter STOP_BIT2 = 1'b1;
 
wire [7:0] ref_dataOut; 
wire ref_overrunErrorFlag;
wire ref_dataOutReadyFlag;
wire ref_frameErrorFlag;
wire ref_endOfRx;
wire ref_run;
wire ref_startBit; 
 
RxCoreSpec #(.PARITY_POLARITY(PARITY_POLARITY)) ref (
		.dataOut(ref_dataOut), 
		.overrunErrorFlag(ref_overrunErrorFlag), 
		.dataOutReadyFlag(ref_dataOutReadyFlag), 
		.frameErrorFlag(ref_frameErrorFlag), 
		.endOfRx(ref_endOfRx),
      .run(ref_run), 
		.startBit(ref_startBit), 
		.clocksPerBit(clocksPerBit),
		.stopBit2(stopBit2),
		.ackFlags(ackFlags), 
		.serialIn(serialIn),
		.clk(clk), 
		.nReset(nReset)
	);
 
RxCoreSelfContained #(.PARITY_POLARITY(PARITY_POLARITY)) uut (
	.dataOut(dataOut), 
	.overrunErrorFlag(overrunErrorFlag), 
	.dataOutReadyFlag(dataOutReadyFlag), 
	.frameErrorFlag(frameErrorFlag), 
	.endOfRx(endOfRx),
   .run(run), 
	.startBit(startBit), 
	.clocksPerBit(clocksPerBit),
	.stopBit2(stopBit2),
	.ackFlags(ackFlags), 
	.serialIn(serialIn),
	.clk(clk), 
	.nReset(nReset)
);
 
initial 
	implMismatch=0;
 
always @(posedge clk, posedge nReset) begin
	implMismatch=0;
	if(dataOut!=ref_dataOut) begin
		implMismatch=1;
		$display ("ERROR: dataOut!=ref_dataOut");
	end
	if(overrunErrorFlag!=ref_overrunErrorFlag) begin
		implMismatch=1;
		$display ("ERROR: overrunErrorFlag!=ref_overrunErrorFlag");
	end
	if(dataOutReadyFlag!=ref_dataOutReadyFlag) begin
		implMismatch=1;
		$display ("ERROR: dataOutReadyFlag!=ref_dataOutReadyFlag");
	end
	if(frameErrorFlag!=ref_frameErrorFlag) begin
		implMismatch=1;
		$display ("ERROR: frameErrorFlag!=ref_frameErrorFlag");
	end
	if(endOfRx!=ref_endOfRx) begin
		implMismatch=1;
		$display ("ERROR: endOfRx!=ref_endOfRx");
	end
	if(run!=ref_run) begin
		implMismatch=1;
		$display ("ERROR: run!=ref_run");
	end
	if(startBit!=ref_startBit) begin
		implMismatch=1;
		$display ("ERROR: startBit!=ref_startBit");
	end
end
 
endmodule
 
 
module tb_RxCore;
parameter PARITY	= 1;
parameter CLK_PERIOD = 10;//should be %2
	// Inputs
	reg [12:0] clocksPerBit;
	reg stopBit2;
	reg ackFlags;
	wire realSerialIn;
	reg clk;
	reg nReset;
 
	// Outputs
	wire [7:0] dataOut;
	wire overrunErrorFlag;
	wire dataOutReadyFlag;
	wire frameErrorFlag;
	wire run;
	wire startBit;
	wire stopBit;
 
 
reg serialIn;
assign #1 realSerialIn = serialIn;
 
	// Instantiate the Unit Under Test (UUT)
	wire implMismatch;
	tb_RxCoreComparator #(.PARITY_POLARITY(PARITY)) uut (
		.implMismatch(implMismatch),
		.dataOut(dataOut), 
		.overrunErrorFlag(overrunErrorFlag), 
		.dataOutReadyFlag(dataOutReadyFlag), 
		.frameErrorFlag(frameErrorFlag), 
		.endOfRx(endOfRx),
      .run(run), 
		.startBit(startBit), 
		.stopBit(stopBit),
      .clocksPerBit(clocksPerBit),
		.stopBit2(stopBit2),
		.ackFlags(ackFlags), 
		.serialIn(realSerialIn),
		.clk(clk), 
		.nReset(nReset)
	);
 
 
//test bench signals
reg tbClock;
integer tbError;
integer tbClockCounter;
integer tbBitTime;
integer tbStartBitTime,tbRunBitFallTime, tbByteTime, tbByteMinTime, tbByteClockCounter;
integer tbLastStartBit;
reg tbStartBitEn;//set this to 0 to turn of start bit detection (useful when testing glitch)
 
event TrigResetDut;
event TrigResetDutRelease;
event TrigTerminateSim;
 
initial
begin
 $display ("###################################################");
 clk = 0;
 nReset = 0;
 tbError = 0;
 tbClockCounter=0;
end
 
initial
@ (TrigTerminateSim)  begin
 $display ("Terminating simulation");
 if (tbError == 0) begin
   $display ("Simulation Result : PASSED");
 end
 else begin
   $display ("Simulation Result : FAILED, %d error(s)", tbError);
 end
 $display ("###################################################");
 #1 $finish;
end
 
//parameter values for SendByte task
localparam WRONG_PARITY=8;
localparam ACKFLAGS=4;
localparam EXPECT_OVERRUN=2;
localparam EXPECT_FRAME_ERROR=1;	
 
initial
forever begin
 @ (TrigResetDut);
 $display ("Applying nReset");
   nReset = 0;
	#(CLK_PERIOD*10);
   nReset = 1;
 $display ("Reset release");
 -> TrigResetDutRelease;
end	
 
	initial begin
		//tb signals
		tbBitTime=8;
		tbStartBitEn=1;
		// DUT Inputs
		clocksPerBit = tbBitTime-1;
		stopBit2=0;
		ackFlags = 0;
		clk = 0;
		nReset = 0;
		tbClock=0;
		tbError=0;
		serialIn=1;
 
		//tb signals which depends on DUT config
		//those times are in clock cycle unit
		tbByteTime=(11+stopBit2)*tbBitTime;
		tbByteMinTime=tbByteTime-(tbBitTime/4);
		tbdataOutReadyBitMinTime=9*tbBitTime+(tbBitTime/2)-1;
		tbdataOutReadyBitMaxTime=tbdataOutReadyBitMinTime+(tbBitTime/4)+1;
 
		tc01_basicTransfer();
		tc02_earliestAckFlags();
		tc03_ackFlagsPolling();
		tc04_contiuousTransfer();
		tc05_parityError();
		tc06_basicOverrun();
		tc07_abortedStart();
		tc08_stopBitViolation();
		tc09_ackFlagsPollingFrameError();
 
		#(CLK_PERIOD*12);
		-> TrigTerminateSim;
	end
 
reg ackFlagsDone;
task ackFlagsTask;
	begin
		ackFlags=1;
		#(CLK_PERIOD*1);
		ackFlagsDone=1;
		ackFlags=0;
		#(CLK_PERIOD*1);
		if(dataOutReadyFlag) begin
			tbError=tbError+1;
			$display("Error %d: dataOutReadyFlag is still set",tbError);
		end
	end
endtask
 
task tc01_basicTransfer;
	begin
		//uut.dataOut=8'b0;//to see the point where it becomes undefined when a rx started
		-> TrigResetDut;@(TrigResetDutRelease);
		#(CLK_PERIOD*2);
		SendByte(8'h55, 0);
		#(CLK_PERIOD*tbBitTime*2);
		ackFlagsTask();
	end
endtask
 
task tc02_earliestAckFlags;
	begin
		//uut.dataOut=8'b0;//to see the point where it becomes undefined when a rx started
		-> TrigResetDut;@(TrigResetDutRelease);
		#(CLK_PERIOD*2);
		SendByte(8'h00, ACKFLAGS);
		fork
			SendByte(8'h55, 0);
			begin
				wait(dataOutReadyFlag===1);
				ackFlagsTask();
			end
		join
	end
endtask
 
task tc03_ackFlagsPolling;
	begin
		//uut.dataOut=8'b0;//to see the point where it becomes undefined when a rx started
		-> TrigResetDut;@(TrigResetDutRelease);
		#(CLK_PERIOD*2);
		SendByte(8'h00, ACKFLAGS);
		ackFlags=1;//stuck it to one to simulate intensive polling
		#(CLK_PERIOD*2);
		fork
			SendByte(8'h55, 0);
			begin
				wait(dataOutReadyFlag===1);//check that dataOutReadyFlag is set even if ackFlags is set continuously
				#1;
				ackFlagsDone=1;//set ackFlagsDone to avoid to get dummy error due to the check within SendByte
			end
		join
		ackFlags=0;
	end
endtask
 
task tc04_contiuousTransfer;
	integer i,tc04Done;
	begin
		tc04Done=0;
		//uut.dataOut=8'b0;//to see the point where it becomes undefined when a rx started
		-> TrigResetDut;@(TrigResetDutRelease);
		#(CLK_PERIOD*2);
		SendByte(8'h00, ACKFLAGS);
		lateAckFlagsEnable=1;
		fork
			begin
				for(i=0;i<256;i=i+1) begin
					SendByte(i, 0);
					//not supported by ISE12.2 (AR#  	36304)
					//replaced by LATE_ACKFLAGS
					/*fork
						SendByte(i, 0);
						begin//ackFlags at the latest time possible for continuous transfer
							#(CLK_PERIOD*((tbBitTime/2)+tbBitTime-1));
							ackFlagsTask();
						end
					join*/
				end
				tc04Done=1;
			end
			begin
				wait(run===1);
				@(negedge tbIsRx);
            //Spec change, run goes low one cycles earlier so a negedge happen even during continuous transfers
            //to emulate old behavior, a signal following run can be implement using a flip flop and combine run and following signal with an or gate...
				/*if(0==tc04Done) begin
					tbError=tbError+1;
					$display("Error %d: tbIsRx went low during continuous transfer",tbError);
				end*/
			end
		join
		lateAckFlagsEnable=0;
	end
endtask
 
task tc05_parityError;
	begin
		-> TrigResetDut;@(TrigResetDutRelease);
		#(CLK_PERIOD*2);
		SendByte(8'h00, ACKFLAGS);
		SendByte(8'h55, WRONG_PARITY|EXPECT_FRAME_ERROR);
		#(CLK_PERIOD*10);
		ackFlagsTask();
		#(CLK_PERIOD*10);
		SendByte(8'hAA, ACKFLAGS);
	end
endtask
 
task tc06_basicOverrun;
	begin
		-> TrigResetDut;@(TrigResetDutRelease);
		#(CLK_PERIOD*2);
		SendByte(8'h00, ACKFLAGS);
		SendByte(8'h55, 0);
		SendByte(8'hAA, EXPECT_OVERRUN);
	end
endtask
 
task tc07_abortedStart;
	begin
		-> TrigResetDut;@(TrigResetDutRelease);
		#(CLK_PERIOD*2);
		SendByte(8'h00, ACKFLAGS);
		tbStartBitEn=0;
		serialIn=0;
		#(CLK_PERIOD*((tbBitTime/2)-1));
		serialIn=1;
		tbStartBitEn=1;
		#(CLK_PERIOD*(tbBitTime/2));
		SendByte(8'h55, ACKFLAGS);
	end
endtask
 
task tc08_stopBitViolation;
	begin
		-> TrigResetDut;@(TrigResetDutRelease);
		#(CLK_PERIOD*2);
		SendByteEarlyExit(8'h00, ACKFLAGS);
		SendByte(8'h55, ACKFLAGS|EXPECT_FRAME_ERROR);
	end
endtask
 
task tc09_ackFlagsPollingFrameError;
	begin
		//uut.dataOut=8'b0;//to see the point where it becomes undefined when a rx started
		-> TrigResetDut;@(TrigResetDutRelease);
		#(CLK_PERIOD*2);
		SendByte(8'h00, ACKFLAGS);
		ackFlags=1;//stuck it to one to simulate intensive polling
		#(CLK_PERIOD*2);
		fork
			SendByte(8'h55, WRONG_PARITY|EXPECT_FRAME_ERROR);
			begin
				wait(frameErrorFlag===1);//check that frameErrorFlag is set even if ackFlags is set continuously
				#1;
				ackFlagsDone=1;//set ackFlagsDone to avoid to get dummy error due to the check within SendByte
			end
		join
		ackFlags=0;
	end
endtask
 
	/*always 
		#1	tbClock =  ! tbClock;*/
	always
		#(CLK_PERIOD/2) clk =  ! clk;
 
	always @(posedge clk) begin
		tbClockCounter = tbClockCounter + 1;
		if(implMismatch)
			tbError=tbError+1;
	end
 
 
reg tbIsRx;
always @(posedge clk) begin
	case({run, startBit})
		2'bx0:	tbIsRx<=1'b0;
		2'b0x:	tbIsRx<=1'b0;
		2'b00:	tbIsRx<=1'b0;
		2'b01:	tbIsRx<=1'b1;
		2'b10:	tbIsRx<=1'b1;
		2'bx1:	tbIsRx<=1'b1;
		2'b1x:	tbIsRx<=1'b1;
		2'b11:	begin
			tbError=tbError+1;
			$display("Error %d: run & StartBit are set simultaneously during clock rising edge",tbError);
		end
	endcase
end
 
reg lateAckFlagsEnable;
initial
	lateAckFlagsEnable=0;
 
always @(posedge SendByteStart) begin:LATE_ACKFLAGS
	if(lateAckFlagsEnable) begin
		#(CLK_PERIOD*(tbBitTime-1));
		//#(CLK_PERIOD);//to test it is really the latest cycle to ack the flags
		ackFlagsTask();
	end
end
 
 
function  computeParity;
input [7:0] data;
integer parity;
begin
	parity = 0;
	parity = ^data;
	parity = parity  ^ PARITY ^ 1;
	computeParity = parity;
end
endfunction
 
integer tbStartBitTimeSampler;
initial
forever begin
	@ (posedge startBit);
	if(tbStartBitEn && (1===startBit)) begin //ignore posedge from 0 to x.
		tbStartBitTimeSampler = tbClockCounter;
		tbByteClockCounter=0;
		tbLastStartBit=startBit;
		fork
			begin
				#(CLK_PERIOD*tbBitTime);
				tbStartBitTime=tbStartBitTimeSampler;
			end
			for(tbByteClockCounter=0;tbByteClockCounter<tbByteTime;tbByteClockCounter=tbByteClockCounter+1) begin
				@ (posedge clk);
				if((tbLastStartBit ==0) && (startBit == 1)) begin //this is to handle early start bit (happens before end of previous byte)
					$display("Early start bit (%d)",tbClockCounter);
					if(tbClockCounter-tbStartBitTime < tbByteMinTime) begin //frame error case
						if(frameErrorFlag != 1) begin
							tbError=tbError+1;
							$display("Error %d: start bit too early but frameErrorFlag is not set",tbError);
						end
					end else begin
						if(frameErrorFlag != 0) begin
							tbError=tbError+1;
							$display("Error %d: start bit within tolerated advance but frameErrorFlag is set",tbError);
						end
					end
					tbStartBitTime = tbClockCounter;
					tbByteClockCounter=0;
				end
				tbLastStartBit=startBit;
			end
		join
	end
end
initial
forever begin
	@ (negedge run);
	if(0===run) begin //ignore negedge from 1 to x.
		tbRunBitFallTime = tbClockCounter;
		if(tbRunBitFallTime-tbStartBitTime < tbByteMinTime) begin
			tbError=tbError+1;
			$display("Error %d: tbRunBitFallTime-tbStartBitTime =%d, >= %d was expected",tbError, tbRunBitFallTime-tbStartBitTime, tbByteMinTime );
		end
		if(tbRunBitFallTime-tbStartBitTime > tbByteTime) begin
			tbError=tbError+1;
			$display("Error %d: tbRunBitFallTime-tbStartBitTime =%d, <=%d was expected",tbError, tbRunBitFallTime-tbStartBitTime, tbByteTime );
		end
	end
end
initial
forever begin
	wait(dataOutReadyFlag===1);
	ackFlagsDone=0;
	wait(dataOutReadyFlag===0);
end	
 
reg [7:0] latchedDataOut;
integer tbdataOutReadyBitTime;
integer tbdataOutReadyBitMinTime,tbdataOutReadyBitMaxTime;
initial
forever begin
	@ (posedge dataOutReadyFlag);
	if(1===dataOutReadyFlag) begin //ignore posedge from 0 to x.
		latchedDataOut<=dataOut;
		tbdataOutReadyBitTime = tbClockCounter;
		if(tbdataOutReadyBitTime-tbStartBitTime < tbdataOutReadyBitMinTime) begin
			tbError=tbError+1;
			$display("Error %d: tbdataOutReadyBitTime-tbStartBitTime =%d, >= %d was expected",tbError, tbdataOutReadyBitTime-tbStartBitTime, tbdataOutReadyBitMinTime );
		end
		if(tbdataOutReadyBitTime-tbStartBitTime > tbdataOutReadyBitMaxTime) begin
			tbError=tbError+1;
			$display("Error %d: tbdataOutReadyBitTime-tbStartBitTime =%d, <=%d was expected",tbError, tbdataOutReadyBitTime-tbStartBitTime, tbdataOutReadyBitMaxTime );
		end
	end
end
 
reg SendByteStart;
task SendByte;
  input [7:0] data;
  input [3:0] flags;
  begin
	SendByteEarlyExit(data,flags);
	#(CLK_PERIOD*(tbBitTime-3));
	end
endtask
task SendByteEarlyExit;
  input [7:0] data;
  input [3:0] flags;
  reg wrongParity;
  reg ackFlagsWhenReady;
  reg expectOverrunError;
  reg expectFrameError;
  reg [7:0] initialData;
  begin
		{wrongParity,ackFlagsWhenReady,expectOverrunError,expectFrameError}=flags;
		initialData=data;
		serialIn=0;//start bit
		fork
			begin
				SendByteStart=1;
				#1;
				SendByteStart=0;
			end
			#(CLK_PERIOD*tbBitTime);
		join
		serialIn=data[0];//0
		#(CLK_PERIOD*tbBitTime);
		serialIn=data[1];//1
		#(CLK_PERIOD*tbBitTime);
		serialIn=data[2];//2
		#(CLK_PERIOD*tbBitTime);
		serialIn=data[3];//3
		`ifdef TEST_TB
			force uut.internalIn=1;
		`endif
		#(CLK_PERIOD*tbBitTime);
		`ifdef TEST_TB
			release uut.internalIn;
		`endif
		serialIn=data[4];//4
		#(CLK_PERIOD*tbBitTime);
		serialIn=data[5];//5
		#(CLK_PERIOD*tbBitTime);
		serialIn=data[6];//6
		#(CLK_PERIOD*tbBitTime);
		serialIn=data[7];//7
		#(CLK_PERIOD*tbBitTime);
		if(wrongParity)
			serialIn=~computeParity(data);//wrong parity
		else
			serialIn=computeParity(data);//parity
		#(CLK_PERIOD*tbBitTime);
		if(expectOverrunError & ~ackFlagsDone) begin
			if(overrunErrorFlag != 1) begin
				tbError=tbError+1;
				$display("Error %d: Overrun error expected but overrunErrorFlag is not set",tbError);
			end else if(data!=initialData) begin
				tbError=tbError+1;
				$display("Error %d: Data changed despite overrun condition",tbError);
			end
		end
		if(expectFrameError & ~ackFlagsDone) begin
			if(frameErrorFlag != 1) begin
				tbError=tbError+1;
				$display("Error %d: Frame error expected but frameErrorFlag is not set",tbError);
			end
			serialIn=1;
			#(CLK_PERIOD*tbBitTime*12);//make sure the receiver return to idle state
		end
		if(~expectOverrunError & ~expectFrameError) begin
			if(dataOut!=latchedDataOut)begin
				tbError=tbError+1;
				$display("Error %d: latchedDataOut mismatch-->dataOut changed after dataOutReadyFlag edge, dataOut=0x%x, latchedDataOut=0x%x",tbError, dataOut, latchedDataOut);
			end
			if(data!==dataOut)begin
				tbError=tbError+1;
				$display("Error %d: dataOut mismatch, dataOut=0x%x, 0x%x was expected",tbError, dataOut, data);
			end
			if(~dataOutReadyFlag & ~ackFlagsDone)begin
				tbError=tbError+1;
				$display("Error %d: dataOutReadyFlag is not set",tbError);
			end
			if(frameErrorFlag|overrunErrorFlag)begin
				tbError=tbError+1;
				$display("Error %d: frameErrorFlag|overrunErrorFlag not expected but set",tbError);
			end
		end
		serialIn=1;//stop1
		fork
			if(ackFlagsWhenReady) begin
				#(CLK_PERIOD*1);
				ackFlagsTask();
			end else
				#(CLK_PERIOD*3);
		join
  end
endtask
 
 
endmodule
 
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.