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

Subversion Repositories iso7816_3_master

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /iso7816_3_master
    from Rev 1 to Rev 2
    Reverse comparison

Rev 1 → Rev 2

/trunk/test/tb_HalfDuplexUartIf.v
0,0 → 1,275
`timescale 1ns / 1ps
 
////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 22:45:51 10/31/2010
// Design Name: HalfDuplexUartIf
// Module Name: /home/seb/dev/hardware/Uart/tb_HalfDuplexUartIf.v
// Project Name: Uart
// Target Device:
// Tool versions:
// Description:
//
// Verilog Test Fixture created by ISE for module: HalfDuplexUartIf
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
////////////////////////////////////////////////////////////////////////////////
 
module tb_HalfDuplexUartIf;
parameter CLK_PERIOD = 10;//should be %2
parameter DIVIDER_WIDTH = 16;
// Inputs
reg nReset;
reg clk;
reg [DIVIDER_WIDTH-1:0] clkPerCycle;
reg [7:0] dataIn;
reg nWeDataIn;
reg nCsDataOut;
reg nCsStatusOut;
wire serialIn;
 
// Outputs
wire [7:0] dataOut;
wire [7:0] statusOut;
wire serialOut;
wire isTx;
 
// Inputs
reg [7:0] dataIn2;
reg nWeDataIn2;
reg nCsDataOut2;
reg nCsStatusOut2;
wire serialIn2;
 
// Outputs
wire [7:0] dataOut2;
wire [7:0] statusOut2;
wire serialOut2;
wire isTx2;
 
// Bidirs
wire serialLine = isTx ? serialOut : isTx2 ? serialOut2 : 1'bz;
pullup(serialLine);
 
assign serialIn = serialLine;
assign serialIn2 = serialLine;
// Instantiate the Unit Under Test (UUT)
HalfDuplexUartIf #(.DIVIDER_WIDTH(DIVIDER_WIDTH))
uut (
.nReset(nReset),
.clk(clk),
.clkPerCycle(clkPerCycle),
.dataIn(dataIn),
.nWeDataIn(nWeDataIn),
.dataOut(dataOut),
.nCsDataOut(nCsDataOut),
.statusOut(statusOut),
.nCsStatusOut(nCsStatusOut),
.serialIn(serialIn),
.serialOut(serialOut),
.isTx(isTx)
);
HalfDuplexUartIf #(.DIVIDER_WIDTH(DIVIDER_WIDTH))
uut2 (
.nReset(nReset),
.clk(clk),
.clkPerCycle(clkPerCycle),
.dataIn(dataIn2),
.nWeDataIn(nWeDataIn2),
.dataOut(dataOut2),
.nCsDataOut(nCsDataOut2),
.statusOut(statusOut2),
.nCsStatusOut(nCsStatusOut2),
.serialIn(serialIn2),
.serialOut(serialOut2),
.isTx(isTx2)
);
integer tbErrorCnt;
wire bufferFull = statusOut[0];
wire bufferFull2 = statusOut2[0];
wire txPending = statusOut[6];
wire txPending2 = statusOut2[6];
 
/*//this is sensitive to glitch in combo logic so we cannot use wait(txRun == 0) or @negedge(txRun)...
wire bufferFull = statusOut[0];
wire rxRun = statusOut[5];
wire txRun = statusOut[6];
 
wire bufferFull2 = statusOut2[0];
wire rxRun2 = statusOut2[5];
wire txRun2 = statusOut2[6];
*/
//reg bufferFull ;//already registered
reg rxRun ;
reg txRun ;
 
//reg bufferFull2 ;
reg rxRun2 ;
reg txRun2 ;
always @(posedge clk) begin
//bufferFull <= statusOut[0];
rxRun <= statusOut[5];
txRun <= statusOut[7];
//bufferFull2 <= statusOut2[0];
rxRun2 <= statusOut2[5];
txRun2 <= statusOut2[7];
end
 
task sendByte;
input [7:0] data;
begin
wait(bufferFull==1'b0);
dataIn=data;
nWeDataIn=0;
@(posedge clk);
dataIn=8'hxx;
nWeDataIn=1;
@(posedge clk);
end
endtask
 
task sendByte2;
input [7:0] data;
begin
wait(bufferFull2==1'b0);
dataIn2=data;
nWeDataIn2=0;
@(posedge clk);
dataIn2=8'hxx;
nWeDataIn2=1;
@(posedge clk);
end
endtask
 
task receiveByte;
input [7:0] data;
begin
wait(txPending==1'b0);//wait start of last tx if any
wait(txRun==1'b0);//wait end of previous transmission if any
wait(bufferFull==1'b1);//wait reception of a byte
@(posedge clk);
nCsDataOut=0;
@(posedge clk);
nCsDataOut=1;
if(data!=dataOut) begin
tbErrorCnt=tbErrorCnt+1;
$display("ERROR %d: uart1 received %x instead of %x",tbErrorCnt, dataOut, data);
end
@(posedge clk);
end
endtask
 
task receiveByte2;
input [7:0] data;
begin
wait(txPending2==1'b0);//wait start of last tx if any
wait(txRun2==1'b0);//wait end of previous transmission if any
wait(bufferFull2==1'b1);//wait reception of a byte
@(posedge clk);
nCsDataOut2=0;
@(posedge clk);
nCsDataOut2=1;
if(data!=dataOut2) begin
tbErrorCnt=tbErrorCnt+1;
$display("ERROR %d: uart2 received %x instead of %x (time=%d)",tbErrorCnt, dataOut2, data,$time);
end else
$display("INFO: uart2 received %x (time=%d)",dataOut2,$time);
@(posedge clk);
end
endtask
 
integer tbSequenceDone;
integer tbSequenceDone2;
initial begin
// Initialize Inputs
nReset = 0;
clk = 0;
dataIn = 0;
clkPerCycle = 0;
nWeDataIn = 1;
nCsDataOut = 1;
nCsStatusOut = 1;
nWeDataIn2 = 1;
nCsDataOut2 = 1;
nCsStatusOut2 = 1;
tbErrorCnt=0;
tbSequenceDone=0;
tbSequenceDone2=0;
// Wait 100 ns for global reset to finish
#(CLK_PERIOD*10);
#(CLK_PERIOD/2);
nReset = 1;
// Add stimulus here
@(posedge clk);
dataIn=8'h3B;
nWeDataIn=0;
@(posedge clk);
dataIn=8'h00;
nWeDataIn=1;
@(posedge clk);
if(bufferFull==1'b0) begin
tbErrorCnt=tbErrorCnt+1;
$display("ERROR %d: bufferFull==1'b0",tbErrorCnt);
end
@(posedge clk);
@(posedge clk);
if(bufferFull==1'b1) begin
tbErrorCnt=tbErrorCnt+1;
$display("ERROR %d: bufferFull==1'b1",tbErrorCnt);
end
//sendByte(8'h3B);
sendByte(8'h97);
sendByte(8'h12);
sendByte(8'h34);
receiveByte(8'h55);
sendByte(8'h56);
sendByte(8'h78);
tbSequenceDone=1;
end
initial begin
receiveByte2(8'h3B);
receiveByte2(8'h97);
receiveByte2(8'h12);
receiveByte2(8'h34);
sendByte2(8'h55);
receiveByte2(8'h56);
receiveByte2(8'h78);
tbSequenceDone2=1;
end
initial begin
wait(tbSequenceDone & tbSequenceDone2);
if(tbErrorCnt)
$display("INFO: Test FAILED (%d errors)", tbErrorCnt);
else
$display("INFO: Test PASSED");
#10;
$finish;
end
initial begin
// timeout
#10000;
tbErrorCnt=tbErrorCnt+1;
$display("ERROR: timeout expired");
#10;
$finish;
end
always
#(CLK_PERIOD/2) clk = ! clk;
endmodule
 
/trunk/test/tb_BasicHalfDuplexUart.v
0,0 → 1,87
`timescale 1ns / 1ps
 
////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 19:45:19 10/31/2010
// Design Name: BasicHalfDuplexUart
// Module Name: /home/seb/dev/hardware/Uart/tb_BasicHalfDuplexUart.v
// Project Name: Uart
// Target Device:
// Tool versions:
// Description:
//
// Verilog Test Fixture created by ISE for module: BasicHalfDuplexUart
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
////////////////////////////////////////////////////////////////////////////////
 
module tb_BasicHalfDuplexUart;
 
// Inputs
reg [7:0] txData;
reg [12:0] clocksPerBit;
reg stopBit2;
reg startTx;
reg ackFlags;
reg clk;
reg nReset;
 
// Outputs
wire [7:0] rxData;
wire overrunErrorFlag;
wire dataOutReadyFlag;
wire frameErrorFlag;
wire run;
wire rxStartBit;
wire txFull;
wire isTx;
 
// Bidirs
wire serialLine;
 
// Instantiate the Unit Under Test (UUT)
BasicHalfDuplexUart uut (
.rxData(rxData),
.overrunErrorFlag(overrunErrorFlag),
.dataOutReadyFlag(dataOutReadyFlag),
.frameErrorFlag(frameErrorFlag),
.run(run),
.rxStartBit(rxStartBit),
.txFull(txFull),
.isTx(isTx),
.serialLine(serialLine),
.txData(txData),
.clocksPerBit(clocksPerBit),
.stopBit2(stopBit2),
.startTx(startTx),
.ackFlags(ackFlags),
.clk(clk),
.nReset(nReset)
);
 
initial begin
// Initialize Inputs
txData = 0;
clocksPerBit = 0;
stopBit2 = 0;
startTx = 0;
ackFlags = 0;
clk = 0;
reset = 0;
 
// Wait 100 ns for global reset to finish
#100;
// Add stimulus here
 
end
endmodule
 
/trunk/test/RxCoreTestBench.v
0,0 → 1,665
`timescale 1ns / 1ps
 
////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 21:02:24 09/02/2010
// Design Name: RxCore
// Module Name: D:/Hardware/Uart/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;
 
 
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),
.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
 
/trunk/test/TxCoreTestBench.v
0,0 → 1,102
`timescale 1ns / 1ps
 
////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer: Sebastien Riou
//
// Create Date: 22:53:00 08/29/2010
// Design Name: TxCore
// Module Name: D:/Hardware/Uart/tb_TxCore.v
// Project Name: Uart
// Target Device:
// Tool versions:
// Description:
//
// Verilog Test Fixture created by ISE for module: TxCore
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
////////////////////////////////////////////////////////////////////////////////
 
module tb_TxCore;
parameter PARITY = 1;
parameter CLK_PERIOD = 10;//should be %2
// Inputs
reg [7:0] dataIn;
reg loadDataIn;
reg [12:0] clocksPerBit;
reg stopBit2;
wire oddParity=0; //if 1, parity bit is such that data+parity have an odd number of 1
wire msbFirst=0; //if 1, bits will be send in the order startBit, b7, b6, b5...b0, parity
reg clk;
reg nReset;
 
// Outputs
wire serialOut;
wire run;
wire full;
wire stopBits;
 
// Instantiate the Unit Under Test (UUT)
TxCore #(.PARITY_POLARITY(PARITY)) uut (
.serialOut(serialOut),
.run(run),
.full(full),
.stopBits(stopBits),
.dataIn(dataIn),
.clocksPerBit(clocksPerBit),
.stopBit2(stopBit2),
.oddParity(oddParity),
.msbFirst(msbFirst),
.loadDataIn(loadDataIn),
.clk(clk),
.nReset(nReset)
);
//test bench signals
reg tbClock;
reg tbBitCounter;
 
initial begin
tbClock=0;
tbBitCounter=0;
// Initialize Inputs
dataIn = 0;
loadDataIn = 0;
clocksPerBit = 8;
stopBit2=0;
clk = 0;
nReset = 0;
#(CLK_PERIOD*10);
nReset = 1;
#(CLK_PERIOD*10);
// Add stimulus here
dataIn = 8'b1000_0000;
loadDataIn = 1;
wait(full==1);
wait(full==0);
//loadDataIn=0;
dataIn = 8'b0111_1111;
//loadDataIn = 1;
wait(full==1);
wait(full==0);
loadDataIn=0;
end
initial begin
// timeout
#10000;
$finish;
end
always
#1 tbClock = ! tbClock;
always
#(CLK_PERIOD/2) clk = ! clk;
endmodule
 
/trunk/sources/Uart.v
0,0 → 1,138
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer: Sebastien Riou
//
// Create Date: 23:57:02 08/31/2010
// Design Name:
// Module Name: Uart
// Project Name:
// Target Devices:
// Tool versions:
// Description: Half duplex UART with 1 byte buffer
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module BasicHalfDuplexUart(
output [7:0] rxData,
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 txRun, //tx is started
output endOfRx, //one cycle pulse: 1 during last cycle of last stop bit of rx
output rxRun, //rx is definitely started, one of the three flag will be set
output rxStartBit, //rx is started, but we don't know yet if real rx or just a glitch
output txFull,
output isTx, //1 only when tx is ongoing. Indicates the direction of the com line.
input serialIn, //signals to merged into a inout signal according to "isTx"
output serialOut,
output comClk,
input [DIVIDER_WIDTH-1:0] clkPerCycle,
input [7:0] txData,
input [CLOCK_PER_BIT_WIDTH-1:0] clocksPerBit,
input stopBit2,//0: 1 stop bit, 1: 2 stop bits
input oddParity, //if 1, parity bit is such that data+parity have an odd number of 1
input msbFirst, //if 1, bits order is: startBit, b7, b6, b5...b0, parity
input startTx,
input ackFlags,
input clk,
input nReset
);
 
//parameters to override
parameter DIVIDER_WIDTH = 1;
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'b1;
//default conventions
parameter START_BIT = 1'b0;
parameter STOP_BIT1 = 1'b1;
parameter STOP_BIT2 = 1'b1;
 
//constant definition for states
localparam IDLE_STATE = 3'b000;
localparam RX_STATE = 3'b001;
localparam TX_STATE = 3'b011;
 
wire rxSerialIn = isTx ? STOP_BIT1 : serialIn;
//wire serialOut;
wire loadDataIn;
 
wire txStopBits;
 
assign isTx = txRun & ~txStopBits;
//let this to top level to avoid inout signal
//assign serialLine = isTx ? serialOut : 1'bz;
 
assign loadDataIn = startTx & ~rxStartBit & (~rxRun | endOfRx);
 
/*//complicated approach... instead we can simply divide the clock at lower levels
wire useEarlyComClk = |clkPerCycle ? 1'b1:1'b0;
reg dividedClk;
wire earlyComClk;//earlier than comClk by 1 cycle of clk (use to make 1 cycle pulse signals)
always @(posedge clk)begin
if(useEarlyComClk)
dividedClk <= earlyComClk;
end
assign comClk=useEarlyComClk ? dividedClk : clk;//clock for communication
wire endOfRxComClk;//pulse of 1 cycle of comClk
assign endOfRx = useEarlyComClk ? endOfRxComClk & earlyComClk & ~comClk : endOfRxComClk;//pulse of 1 cycle of clk
ClkDivider #(.DIVIDER_WIDTH(DIVIDER_WIDTH))
clkDivider(
.nReset(nReset),
.clk(clk),
.divider(clkPerCycle),
.dividedClk(earlyComClk)
);
*/
 
// Instantiate the module
RxCoreSelfContained #(
.DIVIDER_WIDTH(DIVIDER_WIDTH),
.PARITY_POLARITY(PARITY_POLARITY))
rxCore (
.dataOut(rxData),
.overrunErrorFlag(overrunErrorFlag),
.dataOutReadyFlag(dataOutReadyFlag),
.frameErrorFlag(frameErrorFlag),
.endOfRx(endOfRx),
.run(rxRun),
.startBit(rxStartBit),
.clkPerCycle(clkPerCycle),
.clocksPerBit(clocksPerBit),
.stopBit2(stopBit2),
.oddParity(oddParity),
.msbFirst(msbFirst),
.ackFlags(ackFlags),
.serialIn(rxSerialIn),
.comClk(comClk),
.clk(clk),
.nReset(nReset)
);
TxCore #(.DIVIDER_WIDTH(DIVIDER_WIDTH))
txCore (
.serialOut(serialOut),
.run(txRun),
.full(txFull),
.stopBits(txStopBits),
.dataIn(txData),
.clkPerCycle(clkPerCycle),
.clocksPerBit(clocksPerBit),
.stopBit2(stopBit2),
.oddParity(oddParity),
.msbFirst(msbFirst),
.loadDataIn(loadDataIn),
.comClk(comClk),
.clk(clk),
.nReset(nReset)
);
 
endmodule
/trunk/sources/Iso7816_3_Master.v
0,0 → 1,111
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 17:16:40 01/09/2011
// Design Name:
// Module Name: Iso7816_3_Master
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module Iso7816_3_Master(
input nReset,
input clk,
//input [15:0] clkPerCycle,//not supported yet
input startActivation,//Starts activation sequence
input startDeactivation,//Starts deactivation sequence
input [7:0] dataIn,
input nWeDataIn,
input [12:0] cyclePerEtu,
output [7:0] dataOut,
input nCsDataOut,
output [7:0] statusOut,
input nCsStatusOut,
output reg isActivated,//set to high by activation sequence, set to low by deactivation sequence
output useIndirectConvention,
output tsError,//high if TS character is wrong
output atrIsEarly,//high if TS received before 400 cycles after reset release
output atrIsLate,//high if TS is still not received after 40000 cycles after reset release
//ISO7816 signals
inout isoSio,
output isoClk,
output isoReset,
output isoVdd
);
 
assign isoSio = isTx ? serialOut : 1'bz;
 
HalfDuplexUartIf uart (
.nReset(nReset),
.clk(clk),
.clkPerCycle(1'b0),
.dataIn(dataIn),
.nWeDataIn(nWeDataIn),
.dataOut(dataOut),
.nCsDataOut(nCsDataOut),
.statusOut(statusOut),
.nCsStatusOut(nCsStatusOut),
.serialIn(isoSio),
.serialOut(serialOut),
.isTx(isTx),
.comClk(comClk)
);
reg isoClkEn;
assign isoClk = isoClkEn ? comClk : 1'b0;
reg [16:0] resetCnt;
assign atrIsEarly = ~waitTs & (resetCnt<(16'h100+16'd400));
assign atrIsLate = resetCnt>(16'h100+16'd40000);
assign useIndirectConvention = ~waitTs & (ts==8'h3F);
assign tsError = ~waitTs & (ts!=8'h3B) & ~useIndirectConvention;
reg waitTs;
always @(posedge comClk, negedge nReset) begin
if(~nReset) begin
isoClkEn <= 1'b0;
resetCnt<=16'b0;
waitTs<=1'b1;
isoReset <= 1'b0;
isoVdd <= 1'b0;
isActivated <= 1'b0;
end else if(isActivated) begin
if(waitTs) begin
if(statusOut[0]) begin
waitTs<=1'b0;
ts<=dataOut;
end
resetCnt<=resetCnt+1;
end
if(startDeactivation) begin
isoVdd <= 1'b0;
isoClkEn <= 1'b0;
isoReset <= 1'b0;
resetCnt<=16'b0;
isActivated <= 1'b0;
end
end else begin
if(startActivation) begin
waitTs <= 1'b1;
isoVdd <= 1'b1;
isoClkEn <= 1'b1;
if(16'h100 == resetCnt) begin
isActivated <=1'b1;
isoReset <=1'b1;
end else
resetCnt<=resetCnt + 1;
end else begin
resetCnt<=16'b0;
end
end
end
endmodule
/trunk/sources/RxCoreSpec.v
0,0 → 1,368
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer: Sebastien Riou
//
// Create Date: 23:57:02 09/04/2010
// Design Name:
// Module Name: RxCore2
// Project Name:
// Target Devices:
// Tool versions:
// Description: non synthetizable model used as reference in test bench
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
/*
module Delay();
 
task WaitClocks;
input [CLOCK_PER_BIT_WIDTH-1:0] limit;
integer bitClocksCounter;
begin
for(bitClocksCounter=0;bitClocksCounter<limit;bitClocksCounter=bitClocksCounter+1) begin
@(posedge syncClk);
end
end
endtask
 
endmodule
*/
 
module RxCoreSpec(
output reg [7:0] dataOut,
output reg overrunErrorFlag, //new data has been received before dataOut was read
output reg dataOutReadyFlag, //new data available
output reg frameErrorFlag, //bad parity or bad stop bits
output reg endOfRx,
output reg run, //rx is definitely started, one of the three flag will be set
output reg 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;
 
//constant definition for states
localparam IDLE_BIT = ~START_BIT;
 
integer bitCounter;
 
reg parityBit;
reg rxStarted;
 
wire internalIn;
wire parityError;
 
assign internalIn = serialIn ^ IN_POLARITY;
assign parityError= parityBit ^ internalIn ^ PARITY_POLARITY ^ 1'b1;
reg syncClk;
 
/*logic to avoid race condition on flags
if internal logic set the flag and at the same time
the signal ackFlags is set (that normally clears the flags), the flag should be set
*/
reg setOverrunErrorFlag;
reg nResetOverrunErrorFlag;
always @(negedge clk) begin
setOverrunErrorFlag<=1'b0;
end
 
//flag set has priority over flag nReset
always @(setOverrunErrorFlag,nResetOverrunErrorFlag) begin
if((setOverrunErrorFlag===1'b1) || (setOverrunErrorFlag===1'bx)) begin
overrunErrorFlag<=setOverrunErrorFlag;
if(nResetOverrunErrorFlag)
nResetOverrunErrorFlag=0;
end else begin
if(nResetOverrunErrorFlag) begin
overrunErrorFlag<=0;
nResetOverrunErrorFlag=0;
end
end
end
 
reg setDataOutReadyFlag;
reg nResetDataOutReadyFlag;
always @(negedge clk) begin
setDataOutReadyFlag<=1'b0;
end
 
//flag set has priority over flag nReset
always @(setDataOutReadyFlag,nResetDataOutReadyFlag) begin
if((setDataOutReadyFlag===1'b1) || (setDataOutReadyFlag===1'bx)) begin
dataOutReadyFlag<=setDataOutReadyFlag;
if(nResetDataOutReadyFlag)
nResetDataOutReadyFlag=0;
end else begin
if(nResetDataOutReadyFlag) begin
dataOutReadyFlag<=0;
nResetDataOutReadyFlag=0;
end
end
end
 
reg setFrameErrorFlag;
reg nResetFrameErrorFlag;
always @(negedge clk) begin
setFrameErrorFlag<=1'b0;
end
 
//flag set has priority over flag nReset
always @(setFrameErrorFlag,nResetFrameErrorFlag) begin
if((setFrameErrorFlag===1'b1) || (setFrameErrorFlag===1'bx)) begin
frameErrorFlag<=setFrameErrorFlag;
if(nResetFrameErrorFlag)
nResetFrameErrorFlag=0;
end else begin
if(nResetFrameErrorFlag) begin
frameErrorFlag<=0;
nResetFrameErrorFlag=0;
end
end
end
 
reg dataOutReadyFlagAckDone;
reg frameErrorFlagAckDone;
 
always @(posedge clk) begin:ACK_FLAGS
if(ackFlags) begin
if(0==rxStarted)
nResetOverrunErrorFlag<=1;//otherwise, done in OVERRUN_BIT block
if(dataOutReadyFlag!==1'bx)
nResetDataOutReadyFlag<=1'b1;
dataOutReadyFlagAckDone<=1'b1;
if(frameErrorFlag!==1'bx)
nResetFrameErrorFlag<=1'b1;
frameErrorFlagAckDone<=1'b1;
end
end
 
reg internalStart;
integer clockCounter;
always@(posedge internalStart) begin:CLOCK_COUNTER
for(clockCounter=0;clockCounter<(11+stopBit2)*(clocksPerBit+1);clockCounter=clockCounter+1) begin
syncClk=0;
#(CLK_PERIOD/2);
syncClk=1;
#(CLK_PERIOD/2);
end
end
 
reg abortStart;
always@(posedge abortStart) begin:ABORT_START
abortStart<=0;
startBit<=1'bx;
#(CLK_PERIOD*(clocksPerBit+1)/4);
if(internalIn)
startBit<=0;
end
//Start bit spec
always@(negedge internalIn) begin:START_BIT_BLK
if(frameErrorFlag | overrunErrorFlag) begin
//nothing to do, wait clear from outside
end else begin
internalStart<=1;
startBit<=1'bx;
#(CLK_PERIOD*(clocksPerBit+1)/4);
internalStart<=0;
startBit<=1;
#(CLK_PERIOD*(clocksPerBit+1)/4);
if(internalIn==0) begin
startBit<=1'bx;
#(CLK_PERIOD*(clocksPerBit+1)/4);
startBit<=0;
#(CLK_PERIOD*(clocksPerBit+1)/4);
#(CLK_PERIOD*(10+stopBit2)*(clocksPerBit+1));//ignore falling edge until end of the byte
end else begin
abortStart<=1;
end
end
end
 
wire [31:0] stopStart=10*(clocksPerBit+1);
wire [31:0] stopEnd=((10+stopBit2)*(clocksPerBit+1)+((clocksPerBit+1)*3)/4);
wire isInStop=(clockCounter>=stopStart) && (clockCounter<stopEnd);
reg runBitSet;
//Run bit spec
always@(negedge internalIn) begin:RUN_BIT_SET
if(frameErrorFlag | overrunErrorFlag) begin
//nothing to do, wait clear from outside
end else if(~isInStop) begin
runBitSet<=1'b0;
#(CLK_PERIOD*(clocksPerBit+1)/2);
if(internalIn == 0) begin
fork
begin
runBitSet<=1'b1;
run<=1'bx;
#(CLK_PERIOD*(clocksPerBit+1)/4);
run<=1;
end
begin
#(CLK_PERIOD*(clocksPerBit+1)/2);
#(CLK_PERIOD*(9+stopBit2)*(clocksPerBit+1));
end
join
end
end
end
 
always@(posedge runBitSet) begin:RUN_BIT_CLEAR
#(CLK_PERIOD*(clocksPerBit+1)/2);
#(CLK_PERIOD*(((10+stopBit2)*(clocksPerBit+1))-2));
if(runBitSet)
endOfRx<=1'bx;
#(CLK_PERIOD);
if(runBitSet) begin//might be cleared by nReset
run<=1'bx;
#(CLK_PERIOD*(clocksPerBit+1)/4);
endOfRx<=1'b0;
run<=0;
end
end
 
//overrun bit spec
reg internalOv;
wire [31:0] minOvCount=(clocksPerBit+1);//WARNING: DATA_OUT block rely on this
wire [31:0] maxOvCount=((clocksPerBit+1)/2)+(clocksPerBit+1)+(clocksPerBit+1)/4;
always@(posedge syncClk) begin:OVERRUN_BIT
if(clockCounter<maxOvCount) begin//internal requests to set the flag have priority over clear by ackFlags
if(clockCounter==minOvCount)
if(dataOutReadyFlag)
setOverrunErrorFlag <= 1'bx;
end else if(clockCounter==maxOvCount) begin
if(1'bx===overrunErrorFlag)
setOverrunErrorFlag <= 1;
end else
if(ackFlags)
nResetOverrunErrorFlag <= 1;
end
 
reg [7:0] dataStorage;
reg waitStartBit;
//dataOut spec
//frameErrorFlag spec (1/2)
always@(negedge internalIn) begin:DATA_OUT
if(frameErrorFlag | overrunErrorFlag) begin
//nothing to do, wait clear from outside
end else begin
waitStartBit<=1'b0;
#(CLK_PERIOD*(clocksPerBit+1)/2);
if(internalIn==0) begin
#(CLK_PERIOD*(minOvCount-((clocksPerBit+1)/2)));
fork
if(0==dataOutReadyFlag) begin
dataOut<=8'bx;
#(CLK_PERIOD*(clocksPerBit+1)/2);
#(CLK_PERIOD*8*(clocksPerBit+1));//wait 8 bits + parity
parityBit <= ^dataStorage;
if(0==(^dataStorage) ^ internalIn ^ PARITY_POLARITY ^ 1'b1) begin
setDataOutReadyFlag<=1'bx;
dataOutReadyFlagAckDone<=1'b0;
#(CLK_PERIOD*2);//#(CLK_PERIOD*(clocksPerBit+1)/4);//allow 1/4 bit time latency
dataOut<=dataStorage;
if(~dataOutReadyFlagAckDone)
setDataOutReadyFlag<=1'b1;
else
nResetDataOutReadyFlag<=1'b1;
end else begin
setFrameErrorFlag <= 1'bx;
frameErrorFlagAckDone<=1'b0;
#(CLK_PERIOD*2);//#(CLK_PERIOD*(clocksPerBit+1)/4);//allow 1/4 bit time latency
if(~frameErrorFlagAckDone)
setFrameErrorFlag<=1'b1;
else
nResetFrameErrorFlag<=1'b1;
end
end
begin
#(CLK_PERIOD*(clocksPerBit+1)/4);//we can detect start bit a 1/4 of bit time before the actual end of the transfer
#(CLK_PERIOD*(9+stopBit2)*(clocksPerBit+1));
#(CLK_PERIOD*(clocksPerBit+1)/2);
end
join
end
waitStartBit<=1'b1;
end
end
 
//frameErrorFlag spec (2/2)
always@(negedge internalIn) begin:FRAME_ERROR
if(frameErrorFlag | overrunErrorFlag) begin
//nothing to do, wait clear from outside
end else begin
if(isInStop) begin
setFrameErrorFlag <= 1'bx;
frameErrorFlagAckDone<=1'b0;
#(CLK_PERIOD*(clocksPerBit+1)/1);//allow 1 bit time latency
if(~frameErrorFlagAckDone)
setFrameErrorFlag<=1'b1;
else
nResetFrameErrorFlag<=1'b1;
end
end
end
 
initial begin
internalStart=0;
clockCounter=0;
abortStart=0;
internalOv=0;
end
 
always @(negedge internalIn, negedge nReset) begin:MAIN
if(~nReset) begin
bitCounter <= 0;
parityBit <= 0;
nResetOverrunErrorFlag <= 1'b1;
setOverrunErrorFlag <= 1'b0;
nResetDataOutReadyFlag <= 1'b1;
setDataOutReadyFlag <= 1'b0;
nResetFrameErrorFlag <= 1'b1;
setFrameErrorFlag<=1'b0;
endOfRx<=1'b0;
run <= 0;
startBit <= 0;
runBitSet<=0;
end else if(frameErrorFlag | overrunErrorFlag) begin
//nothing to do, wait clear from outside
end else begin
rxStarted<=1'b1;
#(CLK_PERIOD*(clocksPerBit+1)/2);
if(internalIn == 0) begin
@(posedge clk);
for(bitCounter=0;bitCounter<8;bitCounter=bitCounter+1) begin
#(CLK_PERIOD*(clocksPerBit+1)/1);
if(~dataOutReadyFlag) begin
dataStorage[bitCounter]<=internalIn;
end
end
#(CLK_PERIOD*(clocksPerBit+1)/1);
#(CLK_PERIOD*(clocksPerBit+1)/1);
if(stopBit2) begin
#(CLK_PERIOD*(clocksPerBit+1)/1);
end
rxStarted <= 1'b0;
end
end
end
 
endmodule
/trunk/sources/Counter.v
0,0 → 1,88
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer: Sebastien Riou
//
// Create Date: 23:57:02 08/31/2010
// Design Name:
// Module Name: Counter
// Project Name:
// Target Devices:
// Tool versions:
// Description: A counter with increment and clear operation
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module Counter(
output reg [WIDTH-1:0] counter,
output earlyMatch,
output reg match,
output dividedClk,
input [DIVIDER_WIDTH-1:0] divider, // clock divide factor
input [WIDTH-1:0] compare,
input inc,
input clear,
input [WIDTH_INIT-1:0] initVal,
input clk,
input nReset
);
 
//parameters to override
parameter DIVIDER_WIDTH = 16;
parameter WIDTH = 8;
parameter WIDTH_INIT = 1;
 
wire divideBy1;
wire divMatch;
wire divRisingMatch;
wire divFallingMatch;
 
ClkDivider #(.DIVIDER_WIDTH(DIVIDER_WIDTH))
clkDivider(
.nReset(nReset),
.clk(clk),
.divider(divider),
.dividedClk(dividedClk),
.divideBy1(divideBy1),
.match(divMatch),
.risingMatch(divRisingMatch),
.fallingMatch(divFallingMatch)
);
 
wire [WIDTH-1:0] nextCounter = counter+1'b1;
 
wire doInc = divideBy1 ? inc :inc & divRisingMatch;
wire doEarlyMatch = divideBy1 ? (compare == nextCounter) : (compare == counter) & divRisingMatch;
 
reg earlyMatchReg;
assign earlyMatch = divideBy1 ? earlyMatchReg : doEarlyMatch;
 
always @(posedge clk, negedge nReset) begin
if(~nReset) begin
counter <= 0;//initVal;
earlyMatchReg <= 0;
match <= 0;
end else begin
if(clear) begin
counter <= initVal;
end else if(doInc) begin
if(compare == counter)
counter <= initVal;
else
counter <= nextCounter;
end
if(doEarlyMatch)
earlyMatchReg <= 1;
else begin
earlyMatchReg <= 0;
end
match <= divideBy1 ? earlyMatchReg : doEarlyMatch;
end
end
 
endmodule
/trunk/sources/ClkDivider.v
0,0 → 1,75
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer: Sebastien Riou
//
// Create Date: 18:05:27 01/09/2011
// Design Name:
// Module Name: clkDivider
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
 
/*
Basic clock divider
 
if divider=0
dividedClk=clk
else
F(dividedClk)=F(clk)/(divider*2)
dividedClk has a duty cycle of 50%
 
WARNING:
To change divider on the fly:
1. set it to 0 at least for one cycle
2. set it to the new value.
*/
module ClkDivider(
input nReset,
input clk, // input clock
input [DIVIDER_WIDTH-1:0] divider, // divide factor
output dividedClk, // divided clock
output divideBy1,
output match,
output risingMatch,
output fallingMatch
);
//parameters to override
parameter DIVIDER_WIDTH = 16;
reg out;//internal divided clock
reg [DIVIDER_WIDTH-1:0] cnt;
// if divider=0, dividedClk = clk.
assign divideBy1 = |divider ? 1'b0 : 1'b1;
assign dividedClk = divideBy1 ? clk : out;
assign match = (cnt==(divider-1));
assign risingMatch = match & ~out;
assign fallingMatch = match & out;
always @(posedge clk, negedge nReset)
begin
if(~nReset | divideBy1) begin
cnt <= 0;
out <= 1'b0;
end else if(~divideBy1) begin
if(match) begin
cnt <= 0;
out <= ~out;
end else begin
cnt <= cnt + 1'b1;
end
end
end
 
endmodule
/trunk/sources/RxCoreSelfContained.v
0,0 → 1,98
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer: Sebastien Riou
//
// Create Date: 23:57:02 08/31/2010
// Design Name:
// Module Name: RxCore
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module RxCoreSelfContained(
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, //one cycle pulse: 1 during last cycle of last stop bit
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 [DIVIDER_WIDTH-1:0] clkPerCycle,
input [CLOCK_PER_BIT_WIDTH-1:0] clocksPerBit,
input stopBit2,//0: 1 stop bit, 1: 2 stop bits
input oddParity, //if 1, parity bit is such that data+parity have an odd number of 1
input msbFirst, //if 1, bits order is: startBit, b7, b6, b5...b0, parity
input ackFlags,
input serialIn,
input comClk,//not used yet
input clk,
input nReset
);
 
//parameters to override
parameter DIVIDER_WIDTH = 1;
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'b1;
//default conventions
parameter START_BIT = 1'b0;
parameter STOP_BIT1 = 1'b1;
parameter STOP_BIT2 = 1'b1;
 
wire [CLOCK_PER_BIT_WIDTH-1:0] bitClocksCounter;
wire bitClocksCounterEarlyMatch;
wire bitClocksCounterMatch;
wire [CLOCK_PER_BIT_WIDTH-1:0] bitClocksCounterCompare;
wire bitClocksCounterInc;
wire bitClocksCounterClear;
wire bitClocksCounterInitVal;
Counter #( .DIVIDER_WIDTH(DIVIDER_WIDTH),
.WIDTH(CLOCK_PER_BIT_WIDTH),
.WIDTH_INIT(1))
bitClocksCounterModule(
.counter(bitClocksCounter),
.earlyMatch(bitClocksCounterEarlyMatch),
.match(bitClocksCounterMatch),
.divider(clkPerCycle),
.compare(bitClocksCounterCompare),
.inc(bitClocksCounterInc),
.clear(bitClocksCounterClear),
.initVal(bitClocksCounterInitVal),
.clk(clk),
.nReset(nReset));
 
RxCore rxCore (
.dataOut(dataOut),
.overrunErrorFlag(overrunErrorFlag),
.dataOutReadyFlag(dataOutReadyFlag),
.frameErrorFlag(frameErrorFlag),
.endOfRx(endOfRx),
.run(run),
.startBit(startBit),
.clocksPerBit(clocksPerBit),
.stopBit2(stopBit2),
.oddParity(oddParity),
.msbFirst(msbFirst),
.ackFlags(ackFlags),
.serialIn(serialIn),
.clk(clk),
.nReset(nReset),
.bitClocksCounterEarlyMatch(bitClocksCounterEarlyMatch),
.bitClocksCounterMatch(bitClocksCounterMatch),
.bitClocksCounterCompare(bitClocksCounterCompare),
.bitClocksCounterInc(bitClocksCounterInc),
.bitClocksCounterClear(bitClocksCounterClear),
.bitClocksCounterInitVal(bitClocksCounterInitVal)
);
 
endmodule
/trunk/sources/RxCore.v
0,0 → 1,255
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer: Sebastien Riou
//
// Create Date: 23:57:02 08/31/2010
// Design Name:
// Module Name: RxCore
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module RxCore(
output reg [7:0] dataOut,
output reg overrunErrorFlag, //new data has been received before dataOut was read
output reg dataOutReadyFlag, //new data available
output reg frameErrorFlag, //bad parity or bad stop bits
output reg endOfRx, //one cycle pulse: 1 during last cycle of last stop bit
output reg 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 oddParity, //if 1, parity bit is such that data+parity have an odd number of 1
input msbFirst, //if 1, bits order is: startBit, b7, b6, b5...b0, parity
input ackFlags,
input serialIn,
input clk,
input nReset,
//to connect to an instance of Counter.v (see RxCoreSelfContained.v for example)
output reg [CLOCK_PER_BIT_WIDTH-1:0] bitClocksCounterCompare,
output reg bitClocksCounterInc,
output reg bitClocksCounterClear,
output bitClocksCounterInitVal,
input bitClocksCounterEarlyMatch,
input bitClocksCounterMatch
);
 
//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'b1;
//default conventions
parameter START_BIT = 1'b0;
parameter STOP_BIT1 = 1'b1;
parameter STOP_BIT2 = 1'b1;
 
//constant definition for states
localparam IDLE_STATE = 3'b000;
localparam START_STATE = 3'b001;
localparam DATA_STATE = 3'b011;
localparam PARITY_STATE = 3'b010;
localparam STOP1_STATE = 3'b110;
localparam STOP2_STATE = 3'b111;
localparam END_STATE = 3'b101;
localparam END2_STATE = 3'b100;
 
localparam IDLE_BIT = ~START_BIT;
 
reg [2:0] nextState;
 
reg [2:0] bitCounter;
wire [2:0] bitIndex = msbFirst ? 7-bitCounter : bitCounter;
reg parityBit;
 
wire internalIn;
wire parityError;
 
assign startBit = (nextState == START_STATE);
assign internalIn = serialIn;
assign parityError= parityBit ^ internalIn ^ 1'b1;
reg flagsSet;
 
assign bitClocksCounterInitVal=(nextState==IDLE_STATE);
always @(nextState, clocksPerBit, run, bitClocksCounterMatch) begin
case(nextState)
IDLE_STATE: begin
bitClocksCounterCompare = (clocksPerBit/2);
bitClocksCounterInc = run & ~bitClocksCounterMatch;//stop when reach 0
bitClocksCounterClear = ~run;
end
START_STATE: begin
bitClocksCounterCompare = (clocksPerBit/2);
bitClocksCounterInc = 1;
bitClocksCounterClear = 0;
end
STOP2_STATE: begin
//make the rx operation is one cycle shorter,
//since we detect the start bit at least one cycle later it starts.
bitClocksCounterCompare = clocksPerBit-1;
bitClocksCounterInc = 1;
bitClocksCounterClear = 0;
end
default: begin
bitClocksCounterCompare = clocksPerBit;
bitClocksCounterInc = 1;
bitClocksCounterClear = 0;
end
endcase
end
 
always @(posedge clk, negedge nReset) begin
if(~nReset) begin
nextState <= #1 IDLE_STATE;
bitCounter <= #1 0;
parityBit <= #1 0;
overrunErrorFlag <= #1 0;
dataOutReadyFlag <= #1 0;
frameErrorFlag <= #1 0;
run <= #1 0;
endOfRx <= #1 0;
end else begin
case(nextState)
IDLE_STATE: begin
if(bitClocksCounterEarlyMatch)
endOfRx <= #1 1'b1;
if(bitClocksCounterMatch)
endOfRx <= #1 0;
if(ackFlags) begin
//overrunErrorFlag is auto cleared at PARITY_STATE
//meanwhile, it prevent dataOutReadyFlag to be set by the termination of the lost byte
dataOutReadyFlag <= #1 0;
frameErrorFlag <= #1 0;
end
if(START_BIT == internalIn) begin
if(frameErrorFlag | overrunErrorFlag) begin
//wait clear from outside
if(bitClocksCounterMatch) begin
//endOfRx <= #1 0;
run <= #1 0;
end
end else begin
parityBit <= #1 oddParity;
run <= #1 0;
nextState <= #1 START_STATE;
end
end else begin
if(bitClocksCounterMatch) begin
//endOfRx <= #1 0;
run <= #1 0;
end
end
end
START_STATE: begin
if(ackFlags) begin
dataOutReadyFlag <= #1 0;
frameErrorFlag <= #1 0;
end
if(bitClocksCounterMatch) begin
if(START_BIT != internalIn) begin
nextState <= #1 IDLE_STATE;
end else begin
run <= #1 1;
nextState <= #1 DATA_STATE;
end
end
end
DATA_STATE: begin
if(ackFlags) begin
dataOutReadyFlag <= #1 0;
frameErrorFlag <= #1 0;
end
if(bitClocksCounterMatch) begin
if(dataOutReadyFlag) begin
overrunErrorFlag <= #1 1;
end else
dataOut[bitIndex] <= #1 internalIn;
parityBit <= #1 parityBit ^ internalIn;
bitCounter <= #1 (bitCounter + 1'b1) & 3'b111;
if(bitCounter == 7)
nextState <= #1 PARITY_STATE;
end
end
PARITY_STATE: begin
if(bitClocksCounterMatch) begin
if(~overrunErrorFlag) begin
frameErrorFlag <= #1 parityError;
dataOutReadyFlag <= #1 ~parityError;
end else if(ackFlags) begin
frameErrorFlag <= #1 0;
end
flagsSet=1;
if(stopBit2)
nextState <= #1 STOP1_STATE;
else
nextState <= #1 STOP2_STATE;
end else if(ackFlags) begin
dataOutReadyFlag <= #1 0;
frameErrorFlag <= #1 0;
end
end
STOP1_STATE: begin
if(ackFlags) begin
dataOutReadyFlag <= #1 0;
end
if(bitClocksCounterMatch) begin
if(STOP_BIT1 != internalIn) begin
frameErrorFlag <= #1 parityError;
end else if(ackFlags) begin
frameErrorFlag <= #1 0;
end
nextState <= #1 STOP2_STATE;
end else if(ackFlags) begin
frameErrorFlag <= #1 0;
end
end
STOP2_STATE: begin
if(ackFlags) begin
dataOutReadyFlag <= #1 0;
end
if(bitClocksCounterMatch) begin
if(STOP_BIT2 != internalIn) begin
frameErrorFlag <= #1 1;
end else if(ackFlags) begin
frameErrorFlag <= #1 0;
end
nextState <= #1 IDLE_STATE;
end else if(ackFlags) begin
frameErrorFlag <= #1 0;
end
end
default: nextState <= #1 IDLE_STATE;
endcase
end
end
 
//how to use an internal counter rather than an external one:
//(need to be moved at top of the module)
/*wire [CLOCK_PER_BIT_WIDTH-1:0] bitClocksCounter;
wire bitClocksCounterMatch;
reg [CLOCK_PER_BIT_WIDTH-1:0] bitClocksCounterCompare;
reg bitClocksCounterInc;
reg bitClocksCounterClear;
wire bitClocksCounterInitVal;
Counter #( .WIDTH(CLOCK_PER_BIT_WIDTH),
.WIDTH_INIT(1))
bitClocksCounterModule(
.counter(bitClocksCounter),
.match(bitClocksCounterMatch),
.compare(bitClocksCounterCompare),
.inc(bitClocksCounterInc),
.clear(bitClocksCounterClear),
.initVal(bitClocksCounterInitVal),
.clk(clk),
.reset(reset));*/
 
endmodule
/trunk/sources/TxCore.v
0,0 → 1,179
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer: Sebastien Riou
//
// Create Date: 21:16:10 08/29/2010
// Design Name:
// Module Name: TxCore
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module TxCore(
output comClk,
output serialOut,
output run,
output full,
output stopBits, //1 during stop bits
input [7:0] dataIn,
input [DIVIDER_WIDTH-1:0] clkPerCycle,
input [CLOCK_PER_BIT_WIDTH-1:0] clocksPerBit,
input loadDataIn, //evaluated only when full=0, when full goes to one, dataIn has been read
input stopBit2,//0: 1 stop bit, 1: 2 stop bits
input oddParity, //if 1, parity bit is such that data+parity have an odd number of 1
input msbFirst, //if 1, bits will be send in the order startBit, b7, b6, b5...b0, parity
input clk,
input nReset
);
 
//parameters to override
parameter DIVIDER_WIDTH = 1;
parameter CLOCK_PER_BIT_WIDTH = 13;//allow to support default speed of ISO7816
//default conventions
parameter START_BIT = 1'b0;
parameter STOP_BIT1 = 1'b1;
 
//constant definition for state
localparam IDLE_STATE = 0;
localparam START_STATE = 1;
localparam SEND_DATA_STATE = 2;
localparam SEND_PARITY_STATE = 3;
localparam SEND_STOP1_STATE = 4;
localparam SEND_STOP2_STATE = 5;
 
localparam IDLE_BIT = ~START_BIT;
localparam STOP_BIT2 = STOP_BIT1;
 
wire [CLOCK_PER_BIT_WIDTH-1:0] bitClocksCounter;
wire bitClocksCounterEarlyMatch;
wire bitClocksCounterMatch;
reg [CLOCK_PER_BIT_WIDTH-1:0] bitClocksCounterCompare;
reg bitClocksCounterInc;
reg bitClocksCounterClear;
wire bitClocksCounterInitVal;
Counter #( .DIVIDER_WIDTH(DIVIDER_WIDTH),
.WIDTH(CLOCK_PER_BIT_WIDTH),
.WIDTH_INIT(1))
bitClocksCounterModule(
.counter(bitClocksCounter),
.earlyMatch(bitClocksCounterEarlyMatch),
.match(bitClocksCounterMatch),
.dividedClk(comClk),
.divider(clkPerCycle),
.compare(bitClocksCounterCompare),
.inc(bitClocksCounterInc),
.clear(bitClocksCounterClear),
.initVal(bitClocksCounterInitVal),
.clk(clk),
.nReset(nReset));
 
reg [2:0] nextState;
reg [2:0] bitCounter;
reg [7:0] dataBuffer;
 
reg parityBit;
 
wire internalOut;
wire dataBit;
//after a tx operation, during the first cycle in IDLE_STATE, run bit must be still set
//(it is entered one cycle before the completion of the operation, so we use bitClocksCounter[0]
//to implement this behavior)
assign run = (nextState == IDLE_STATE) ? bitClocksCounter[0] : 1'b1;
assign full = (nextState != IDLE_STATE);
assign stopBits = (nextState == SEND_STOP1_STATE)|(nextState == SEND_STOP2_STATE)|((nextState == IDLE_STATE) & bitClocksCounter[0]);
 
assign serialOut = internalOut;
wire [2:0] bitIndex = msbFirst ? 7-bitCounter : bitCounter;
assign dataBit = dataBuffer[bitIndex];
wire [0:5] bitSel;
assign bitSel = {IDLE_BIT, START_BIT, dataBit, parityBit, STOP_BIT1, STOP_BIT2};
assign internalOut = bitSel[nextState];
 
assign bitClocksCounterInitVal=0;
 
always @(nextState) begin
case(nextState)
START_STATE:
assign bitClocksCounterCompare = clocksPerBit-1;
SEND_STOP2_STATE:
assign bitClocksCounterCompare = clocksPerBit-1;
default:
assign bitClocksCounterCompare = clocksPerBit;
endcase
end
 
always @(nextState) begin
case(nextState)
IDLE_STATE: begin
bitClocksCounterInc = 0;
bitClocksCounterClear = 1;
end
default: begin
bitClocksCounterInc = 1;
bitClocksCounterClear = 0;
end
endcase
end
 
always @(posedge clk, negedge nReset) begin
if(~nReset) begin
nextState <= #1 IDLE_STATE;
bitCounter <= #1 0;
end else begin
case(nextState)
IDLE_STATE: begin
if(loadDataIn) begin
dataBuffer <= #1 dataIn;
parityBit <= #1 oddParity;
nextState <= #1 START_STATE;
end
end
START_STATE: begin
if(bitClocksCounterMatch) begin
nextState <= #1 SEND_DATA_STATE;
end
end
SEND_DATA_STATE: begin
if(bitClocksCounterMatch) begin
bitCounter <= #1 (bitCounter + 1'b1) & 3'b111;
parityBit <= #1 parityBit ^ dataBit;
if(bitCounter == 7)
nextState <= #1 SEND_PARITY_STATE;
end
end
SEND_PARITY_STATE: begin
if(bitClocksCounterMatch) begin
if(stopBit2)
nextState <= #1 SEND_STOP1_STATE;
else
nextState <= #1 SEND_STOP2_STATE;//if single stop bit, we skip STOP1 state
end
end
SEND_STOP1_STATE: begin
if(bitClocksCounterMatch)
nextState <= #1 SEND_STOP2_STATE;
end
SEND_STOP2_STATE: begin
/* if(bitClocksCounter[1:0]==2'b10)
nextState <= #1 SEND_STOP2_STATE2;
end
SEND_STOP2_STATE2: begin*/
if(bitClocksCounterMatch)
nextState <= #1 IDLE_STATE;
end
default: nextState <= #1 IDLE_STATE;
endcase
end
 
end
 
endmodule
/trunk/sources/HalfDuplexUartIf.v
0,0 → 1,134
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 19:57:35 10/31/2010
// Design Name:
// Module Name: HalfDuplexUartIf
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module HalfDuplexUartIf(
input nReset,
input clk,
input [DIVIDER_WIDTH-1:0] clkPerCycle,
input [7:0] dataIn,
input nWeDataIn,
output [7:0] dataOut,
input nCsDataOut,
output [7:0] statusOut,
input nCsStatusOut,
input serialIn,
output serialOut,
output isTx,
output comClk
);
//parameters to override
parameter DIVIDER_WIDTH = 1;
 
reg [7:0] dataReg;
 
// Inputs
wire [7:0] txData;
wire [12:0] clocksPerBit;
wire stopBit2=1;
wire oddParity=0; //if 1, parity bit is such that data+parity have an odd number of 1
wire msbFirst=0; //if 1, bits will be send in the order startBit, b7, b6, b5...b0, parity
reg txPending;
wire ackFlags;
 
// Outputs
wire [7:0] rxData;
wire overrunErrorFlag;
wire dataOutReadyFlag;
wire frameErrorFlag;
wire txRun;
wire endOfRx;
wire rxRun;
wire rxStartBit;
wire txFull;
//wire isTx;
wire rxFlagsSet = dataOutReadyFlag | overrunErrorFlag | frameErrorFlag;
reg bufferFull;
reg [1:0] flagsReg;
assign txData = dataReg;
assign clocksPerBit = 7;
 
assign dataOut=dataReg;
assign statusOut[7:0]={txRun, txPending, rxRun, rxStartBit, isTx, flagsReg, bufferFull};
 
reg waitTxFull0;//internal reg for managing bufferFull bit in Tx
 
assign ackFlags=~txPending & ~txRun & rxFlagsSet & ((bufferFull & ~nCsDataOut)| ~bufferFull);
 
always @(posedge clk, negedge nReset) begin
if(~nReset) begin
bufferFull <= 1'b0;
flagsReg <= 1'b0;
txPending <= 1'b0;
end else begin
if(ackFlags) begin
dataReg <= rxData;
flagsReg <= {overrunErrorFlag, frameErrorFlag};
if(rxFlagsSet)
bufferFull <= 1'b1;
else
bufferFull <= 1'b0;
end else if(txPending) begin
if(waitTxFull0) begin
if(~txFull)
waitTxFull0 <= 1'b0;
end else if(txFull) begin//tx actually started, clear txPending and free buffer
txPending <= 1'b0;
bufferFull <= 1'b0; //buffer is empty
end
end else if(~nCsDataOut) begin
bufferFull <= 1'b0;
end else if(~nWeDataIn) begin
dataReg <= dataIn;
bufferFull <= 1'b1;
txPending <= 1'b1;
waitTxFull0 <= txFull;
end
end
end
 
BasicHalfDuplexUart #(.DIVIDER_WIDTH(DIVIDER_WIDTH))
uart (
.rxData(rxData),
.overrunErrorFlag(overrunErrorFlag),
.dataOutReadyFlag(dataOutReadyFlag),
.frameErrorFlag(frameErrorFlag),
.txRun(txRun),
.endOfRx(endOfRx),
.rxRun(rxRun),
.rxStartBit(rxStartBit),
.txFull(txFull),
.isTx(isTx),
.serialIn(serialIn),
.serialOut(serialOut),
.txData(txData),
.clocksPerBit(clocksPerBit),
.stopBit2(stopBit2),
.oddParity(oddParity),
.msbFirst(msbFirst),
.startTx(txPending),
.ackFlags(ackFlags),
.clkPerCycle(clkPerCycle),
.clk(clk),
.nReset(nReset)
);
 
endmodule
/trunk/sources/RxCore - private counter.v
0,0 → 1,206
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer: Sebastien Riou
//
// Create Date: 23:57:02 08/31/2010
// Design Name:
// Module Name: RxCore
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module RxCore(
output reg [7:0] dataOut,
output reg overrunErrorFlag, //new data has been received before dataOut was read
output reg dataOutReadyFlag, //new data available
output reg frameErrorFlag, //bad parity or bad stop bits
output reg 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 reset
);
 
//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;
 
//constant definition for states
localparam IDLE_STATE = 3'b000;
localparam START_STATE = 3'b001;
localparam DATA_STATE = 3'b011;
localparam PARITY_STATE = 3'b010;
localparam STOP1_STATE = 3'b110;
localparam STOP2_STATE = 3'b111;
localparam END_STATE = 3'b101;
localparam END2_STATE = 3'b100;
 
localparam IDLE_BIT = ~START_BIT;
 
reg [2:0] nextState;
reg [CLOCK_PER_BIT_WIDTH-1:0] bitClocksCounter;
//Counter #()bitClocksCounter();
 
reg [2:0] bitCounter;
//reg [7:0] dataBuffer;
 
reg parityBit;
 
wire internalIn;
wire parityError;
 
//assign run = (nextState != IDLE_STATE) && (nextState != START_STATE);
assign startBit = (nextState == START_STATE);
assign internalIn = serialIn ^ IN_POLARITY;
assign parityError= parityBit ^ internalIn ^ PARITY_POLARITY ^ 1'b1;
reg flagsSet;
 
always @(posedge clk, negedge reset) begin
if(~reset) begin
nextState <= #1 IDLE_STATE;
bitCounter <= #1 0;
parityBit <= #1 0;
overrunErrorFlag <= #1 0;
dataOutReadyFlag <= #1 0;
frameErrorFlag <= #1 0;
run <= #1 0;
end else begin
if(ackFlags) begin
//overrunErrorFlag is auto cleared at PARITY_STATE
//meanwhile, it prevent dataOutReadyFlag to be set by the termination of the lost byte
//VERILOG_QUESTION: is that bad to assign flags here AND in PARITY_STATE ?
//If this is a problem, how to avoid to duplicate those assignement in all states ??
//TODO: check what happens if ackFlags=1 while PARITY_STATE, and decide what is the spec !
dataOutReadyFlag <= #1 0;
frameErrorFlag <= #1 0;
end
flagsSet=0;
case(nextState)
IDLE_STATE: begin
if(START_BIT == internalIn) begin
if(frameErrorFlag | overrunErrorFlag) begin
//wait clear from outside
if(run)
bitClocksCounter <= #1 bitClocksCounter+1'b1;
if((clocksPerBit/2)+1 == bitClocksCounter)//TODO: make a new state to avoid the +1 in comparison
run <= #1 0;
end else begin
bitClocksCounter <= #1 1;
parityBit <= #1 0;
run <= #1 0;
nextState <= #1 START_STATE;
end
end else begin
if(run)
bitClocksCounter <= #1 bitClocksCounter+1'b1;
if((clocksPerBit/2)+1 == bitClocksCounter)//TODO: make a new state to avoid the +1 in comparison
run <= #1 0;
end
end
START_STATE: begin
if(clocksPerBit/2 == bitClocksCounter) begin
if(START_BIT != internalIn) begin
bitClocksCounter <= #1 bitClocksCounter+1'b1;
nextState <= #1 IDLE_STATE;
end else begin
bitClocksCounter <= #1 0;
run <= #1 1;
nextState <= #1 DATA_STATE;
end
end else begin
bitClocksCounter <= #1 bitClocksCounter+1'b1;
end
end
DATA_STATE: begin
if(clocksPerBit == bitClocksCounter) begin
if(dataOutReadyFlag) begin
overrunErrorFlag <= #1 1;
//nextState <= #1 IDLE_STATE;
end else
dataOut[bitCounter] <= #1 internalIn;
parityBit <= #1 parityBit ^ internalIn;
bitCounter <= #1 (bitCounter + 1'b1) & 3'b111;
if(bitCounter == 7)
nextState <= #1 PARITY_STATE;
bitClocksCounter <= #1 0;
end else begin
bitClocksCounter <= #1 bitClocksCounter+1'b1;
end
end
PARITY_STATE: begin
if(clocksPerBit == bitClocksCounter) begin
if(~overrunErrorFlag) begin
frameErrorFlag <= #1 parityError;
dataOutReadyFlag <= #1 ~parityError;
end
flagsSet=1;
if(stopBit2)
nextState <= #1 STOP1_STATE;
else
nextState <= #1 STOP2_STATE;
bitClocksCounter <= #1 0;
end else begin
bitClocksCounter <= #1 bitClocksCounter+1'b1;
end
end
STOP1_STATE: begin
if(clocksPerBit == bitClocksCounter) begin
if(STOP_BIT1 != internalIn) begin
frameErrorFlag <= #1 parityError;
flagsSet=1;
end
bitClocksCounter <= #1 0;
nextState <= #1 STOP2_STATE;
end else begin
bitClocksCounter <= #1 bitClocksCounter+1'b1;
end
end
STOP2_STATE: begin
if(clocksPerBit == bitClocksCounter) begin
if(STOP_BIT2 != internalIn) begin
frameErrorFlag <= #1 1;
flagsSet=1;
end
bitClocksCounter <= #1 0;
nextState <= #1 IDLE_STATE;
end else begin
bitClocksCounter <= #1 bitClocksCounter+1'b1;
end
end
/*END_STATE: begin
if((clocksPerBit/2) == bitClocksCounter) begin
nextState <= #1 IDLE_STATE;
bitClocksCounter <= #1 1;
end else begin
bitClocksCounter <= #1 bitClocksCounter+1'b1;
end
end*/
/*END2_STATE: begin//just wait one last cycle to get exact timing for RUN bit
nextState <= #1 IDLE_STATE;
end*/
default: nextState <= #1 IDLE_STATE;
endcase
end
 
end
 
endmodule

powered by: WebSVN 2.1.0

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