通用串行异步收发器8251的VerilogHDL源代码.docx
《通用串行异步收发器8251的VerilogHDL源代码.docx》由会员分享,可在线阅读,更多相关《通用串行异步收发器8251的VerilogHDL源代码.docx(34页珍藏版)》请在冰豆网上搜索。
通用串行异步收发器8251的VerilogHDL源代码
/*****************************************************************************
通用串行异步收发器8251的VerilogHDL源代码
******************************************************************************/
moduleI8251A(dbus,rcd,gnd,txc_,write_,chipsel_,comdat_,
read_,rxrdy,txrdy,syndet,cts_,txe,txd,
clk,reset,dsr_,rts_,dtr_,rxc_,vcc);
/*timingconstants,forA.C.timingcheck,onlynon-zerotimesare
specified,innano-sec*/
/*readcycle*/
`defineTRR250
`defineTRD200
`defineTDF100//max.timeused
/*writecycle*/
`defineTWW250
`defineTDW150
`defineTWD20
`defineTRV6//intermsofclockcycles
/*othertiming*/
`defineTTXRDY8//8clockcycle
inputrcd,//receivedata
rxc_,//receiveclock
txc_,//transmitclock
chipsel_,//chipselectedwhenlow
comdat_,//command/data_select
read_,write_,
dsr_,//datasetready
cts_,//cleartosend
reset,//resetwhenhigh
clk,//atleast30timesofthetransmit/rexeibedatabitrates
gnd,
vcc;
outputrxrdy,//receivedatareadywhenhigh
txd,//transmitdatalone
txrdy,//transmitbufferreadytoacceptanotherbytetotransfer
txe,//transmitbufferempty
rts_,//requesttosend
dtr_;//dataterminalready
inout[7:
0]dbus;
inoutsyndet;//outsidesynchonousdetectoroutputtoindicatesyndet
supply0gnd;
supply1vcc;
regtxd,rxrdy,txe,dtr_,rts_;
reg[7:
0]receivebuf,rdata,status;
//*****ADDBYFWN
reg[3:
0]dflags;
reg[7:
0]instance_id;
regread,chipel_;
//*****
regrecvdrv,statusdrv;
//ifrecvdrv1dbusisdrivenbyrdata
assigndbus=recvdrv?
rdata:
8'bz;//*****:
->;
assigndbus=statusdrv?
status:
8'bz;//*****:
->;assignabscent
reg[7:
0]command,
tdata_out,//databeingtransmittedserially
tdata_hold,//datatobetransmittednextiftdata_outisfull
sync1,sync2,//synchronousdatabytes
modreg;
and(txrdy,status[0],command[0],~cts_);
regtransmitter_reset,//setto1uponareset,cleareduponwritedata
tdata_out_full,//1ifdataintdata_outhasnotbeentransmitted.
tdata_hold_full,//1ifdataintdata_holdhasnotbeentransferred
//totdata_outforserialtransmission.
tdata_hold_cts;//1iftdata_hold_fullanditwasctswhendata
//wastransferredtotdata_hold.
//0iftdata_holdisemptyorisfullbutwas
//filledwhileitwasnotcts.
regtdata_out_wait;//0ifastopbitwasjustsentandwedonotneed
//towaitforanegedgeontxcbeforetransmitting
reg[7:
0]syncmask;
nmossyndet_gate1(syndet,status[6],~modreg[6]);
regsync_to_receive;//1
(2)iflookingfor1st(2nd)synconrxd
regsyncs_received;//1ifsynccharsreceived,0iflookinfforsync
regrec_sync_index;//indicatingthesyn.charactertobematched
integerbreakcount_period;//numberofclockperiodstocountasbreak
regsync_to_transmit;//1
(2)if1st(2nd)synccharshouldbesentnext
reg[7:
0]data_mask;//masksoffthedatabits(ifcharsizeisnot8)
//temporaryregisters
reg[1:
0]csel;//indicateswhatnextwritemeansifcomdat_=1:
//(0=modeinstruction,1=sync1,2=sync2,3=command)
reg[5:
0]baudmx,
tbaudcnt,
rbaudcnt;//baudrate
reg[7:
0]tstoptotal;//no.oftranmitclockpulsesforstopbit(0ifsyncmode
reg[3:
0]databits;//no.ofdatabitsinacharacter(5,6,7or8)
regrdatain;//adatabyteisreadinif1
regwas_cts_when_received;//0:
ifcts_washighwhencharwasreceived
//1:
ifcts_waslowwhebcharwasreceived
//(andsocharwassentbeforeshutdown)
eventresete,start_receiver_e,hunt_sysnc1_e;
regreceive_in_progress;
eventtxende;
/***COMMUNICATIONERRORS***/
taskframe_error;
begin
if(dflags[4])
$display("I8251A(%h)at%d:
***frameerror",instance_id,$time);
status[5]=1;
end
endtask
taskparity_error;
begin
if(dflags[4])
$display("I8251A(%h)at%d:
***parityerrordata:
%b",
instance_id,$time,receivebuf);
status[3]=1;
end
endtask
taskoverrun_error;
begin
if(dflags[4])
$display("I8251A(%h)at%d:
***oerrunerror",instance_id,$time);
status[4]=1;
end
endtask
/***TIMINGVIOLATIONS***/
integertime_dbus_setup,
time_write_begin,
time_write_end,
time_read_begin,
time_read_end,
between_write_clks;//tocheckbetweenwriterecovery
regreset_signal_in;//tochecktheresetsignalpulsewidth
initial
begin
time_dbus_setup=-9999;
time_write_begin=-9999;
time_write_end=-9999;
time_read_begin=-9999;
time_read_end=-9999;
between_write_clks=`TRV;//start:
TRVclkperiodssincelastwrite
end
/***Timinganalysisforreadcycles***/
always@(negedgeread_)
if(chipsel_==0)
begin
time_read_begin=$time;
read_address_watch;
end
/*Timingviolation:
readpulsemustbeTRRns*/
always@(posedgeread_)
if(chipsel_==0)
begin
disableread_address_watch;
time_read_end=$time;
if(dflags[3]&&(($time-time_read_begin)<`TRR))
$display("I8251A(%h)at%d:
***readpulsewidthviolation",
instance_id,$time);
end
/*Timingviolation:
address(comdat_andchipsel_)mustbestable*/
/*stablethroughoutread*/
taskread_address_watch;
@(comdat_orchipsel_)//ifthe"address"changes
if(read==0)//andread_didnotchangeatthesametime
if(dflags[3])
$display("I8251A(%h)at%d:
***addressholderroronready",
instance_id,$time);
endtask
/**Timinganalysisforwritecycles**/
always@(negedgewrite_)
if(chipsel_==0)
begin
time_write_begin=$time;
write_address_watch;
end
/*Timingviolation:
readpulsemustbeTRRns*/
/*Timingviolation:
TDWnsbussetuptimebeforeposedgewrite_*/
/*Timingviolation:
TWDnsbusholdtimeafterposedgewrite_*/
always@(posedgewrite_)
if(chipsel_==0)
begin
disablewrite_address_watch;
time_write_end=$time;
if(dflags[3]&&(($time-time_write_begin)<`TWW))
$display("I8251A(%h)at%d:
***writepulse
widthviolation",instance_id,$time);
end
always@dbus
begin
time_dbus_setup=$time;
if(dflags[3]&&(($time-time_write_end<`TWD)))
$display("I8251A(%h)at%d:
***dataholdviolationonwrite",
instance_id,$time);
end
/*Timingviolation:
address(comdat_andchipsel_)mustbestable*/
/*stablethroughoutwrite*/
taskwrite_address_watch;
@(comdat_orchipsel_)//ifthe"address"changes
if(write_==0)//andwrite_didnotchangeatthesametime
if(dflags[3])
$display("I8251A(%h)at%d:
***addressholderroronwrite",
instance_id,$time);
endtask
/*Timingviolation:
minimumofTRVclkcyclesbetweenwrites*/
always@(negedgewrite_)
if(chipel_==0)
begin
time_write_begin=$time;
if(dflags[3]&&between_write_clks<`TRV)
$display("I8251A(%h)at%d:
***betweenwriterecoveryviolation",
instance_id,$time);
end
always@(negedgewrite_)
repeat(`TRV)@(posedgeclk)
between_write_clks=between_write_clks+1;
/**Timinganalysisforresetsequence**/
/*Timingviolation:
resetpulsemustbe6clkcycles*/
always@(posedgereset)
begin:
reset_block
reset_signal_in=1;
repeat(6)@(posedgeclk);
reset_signal_in=0;
//externalreset
->resete;
end
always@(negedgereset)
begin
if(dflags[3]&&(reset_signal_in==1))
$display("I8251A(%h)at%d:
***resetpulsetooshort",instance_id,
$time);//lackof;
disablereset_block;
end
/***BEHAVIORALDESCRIPTION***/
/*Resetsequence*/
initial
begin//power-onreset
reset_signal_in=0;
->resete;
end
always@resete
begin
if(dflags[5])
$display("I8251A(%h)at%d:
performingresetsequence",
instance_id,$time);
csel=0;
transmitter_reset=1;
tdata_out_full=0;
tdata_out_wait=0;
tdata_hold_full=0;
tdata_hold_cts=0;
rdatain=0;
status=4;//onlytxeisset
txe=1;
statusdrv=0;
recvdrv=0;
txd=1;//lineatmarkstateuponresetuntildataistransmitted
//assignnotallowedforstatus,etc.
rxrdy=0;
command=0;
dtr_=1;
rts_=1;
status[6]=0;//syndatisresettooutputlow
sync_to_transmit=1;//transmitsyncchar#1whensyncaretransmit
sync_to_receive=1;
between_write_clks=`TRV;
receive_in_progress=0;
disableread_address_watch;
disablewrite_address_watch;
disabletrans1;
disabletrans2;
disabletrans3;
disabletrans4;
disablercv_blk;
disablesync_hunt_blk;
disabledouble_sync_hunt_blk;
disableparity_sync_hunt_blk;
disablesyn_receive_internal;
disableasyn_receive;
disablebreak_detect_blk;
disablebreak_delay_blk;
end
always@(negedgeread_)
if(chipsel_==0)
begin
#(`TRD)//timefordatatoshowonthedatabus
if(comdat_==0)//8251ADATA==>DATABUS
begin
recvdrv=1;
rdatain=0;//noreceivebyteisready
rxrdy=0;
status[1]=0;
end
else//8251ASTATUS==>DATABUS
begin
statusdrv=1;
if(modreg[1:
0]==2'b00)//ifsyncmode
status[6]=0;//resetsyndetuponstatusready
//note:
isonlyresetuponresetorrxd=1inasyncmode
end
end
always@(posedgeread_)
begin
#(`TDF)//datafromreadstaysonthebusafterposedgeread_
recvdrv=0;
statusdrv=0;
end
always@(negedgewrite_)
begin
if((chipsel_==0)&&(comdat_==0))
begin
txe=0;
status[2]=0;//transmitternotemptyafterreceivingdata
status[0]=0;//transmitternotreadyafterreceivingdata
end
end
always@(posedgewrite_)//readthecommand/datafromtheCPU
if(chipsel_==0)
begin
if(comdat_==0)//DATABUS==>8251ADATA
begin
case(command[0]&~cts_)
0:
//ifitisnotcleartosend
begin
tdata_hold=dbus;
tdata_hold_full=1;//thenmarkthedataasreceivedand
tdata_hold_