1/34FPGA实现RS-232串口收发的仿真过程(Quartus+Synplify+ModelSim)(2007-09-1112:17:37)结合FPGA的开发流程,主要走了以下几步:1.文本程序输入(VerilogHDL)2.功能仿真(ModelSim,查看逻辑功能是否正确,要写一个TestBench)3.综合(SynplifyPro,程序综合成网表)4.布局布线(QuartusII,根据我选定的FPGA器件型号,将网表布到器件中,并估算出相应的时延)b5E2RGbCAP5.时序仿真(ModelSim,根据时延做进一步仿真)0.原理略一、文本程序输入(VerilogHDL)发送端:moduletrans(clk,rst,TxD_start,TxD_data,TxD,TxD_busy);inputclk,rst,TxD_start;input[7:0]TxD_data;//待发送的数据outputTxD,//输出端口发送的串口数据TxD_busy;p1EanqFDPwregTxD;reg[7:0]TxD_dataReg;//寄存器发送模式,因为在串口发送过程中输入端不可能一直保持有效电平reg[3:0]state;parameterClkFrequency=25000000;//时钟频率-25MHzparameterBaud=115200;//串口波特率-115200DXDiTa9E3d//波特率产生parameterBaudGeneratorAccWidth=16;reg[BaudGeneratorAccWidth:0]BaudGeneratorAcc;2/34wire[BaudGeneratorAccWidth:0]BaudGeneratorInc=((Baud(BaudGeneratorAccWidth-4))+(ClkFrequency5))/(ClkFrequency4);wireBaudTick=BaudGeneratorAcc[BaudGeneratorAccWidth];wireTxD_busy;always@(posedgeclkornegedgerst)if(~rst)BaudGeneratorAcc=0;elseif(TxD_busy)BaudGeneratorAcc=BaudGeneratorAcc[BaudGeneratorAccWidth-1:0]+BaudGeneratorInc;RTCrpUDGiT//发送端状态wireTxD_ready=(state==0);//当state=0时,处于准备空闲状态,TxD_ready=1assignTxD_busy=~TxD_ready;//空闲状态时TxD_busy=05PCzVD7HxA//把待发送数据放入缓存寄存器TxD_dataRegalways@(posedgeclkornegedgerst)if(~rst)TxD_dataReg=8'b00000000;elseif(TxD_ready&TxD_start)TxD_dataReg=TxD_data;//发送状态机always@(posedgeclkornegedgerst)if(~rst)beginstate=4'b0000;//复位时,状态为0000,发送端一直发1电平TxD=1'b1;endelsecase(state)4'b0000:if(TxD_start)beginstate=4'b0100;//接受到发送信号,进入发送状态end4'b0100:if(BaudTick)beginstate=4'b1000;//发送开始位-0电平TxD=1'b0;end4'b1000:if(BaudTick)beginstate=4'b1001;//bit0TxD=TxD_dataReg[0];end4'b1001:if(BaudTick)begin3/34state=4'b1010;//bit1TxD=TxD_dataReg[1];end4'b1010:if(BaudTick)beginstate=4'b1011;//bit2TxD=TxD_dataReg[2];end4'b1011:if(BaudTick)beginstate=4'b1100;//bit3TxD=TxD_dataReg[3];end4'b1100:if(BaudTick)beginstate=4'b1101;//bit4TxD=TxD_dataReg[4];end4'b1101:if(BaudTick)beginstate=4'b1110;//bit5TxD=TxD_dataReg[5];end4'b1110:if(BaudTick)beginstate=4'b1111;//bit6TxD=TxD_dataReg[6];end4'b1111:if(BaudTick)beginstate=4'b0010;//bit7TxD=TxD_dataReg[7];end4'b0010:if(BaudTick)beginstate=4'b0011;//stop1TxD=1'b1;endjLBHrnAILg4'b0011:if(BaudTick)beginstate=4'b0000;//stop2TxD=1'b1;enddefault:if(BaudTick)beginstate=4'b0000;TxD=1'b1;4/34endendcaseendmodulexHAQX74J0X接收端:modulercv(clk,rst,RxD,RxD_data,RxD_data_ready,);inputclk,rst,RxD;output[7:0]RxD_data;//接收数据寄存器outputRxD_data_ready;//接收完8位数据,RxD_data值有效时,RxD_data_ready输出读信号LDAYtRyKfEparameterClkFrequency=25000000;//时钟频率-25MHzparameterBaud=115200;//波特率-115200Zzz6ZB2Ltkreg[2:0]bit_spacing;regRxD_delay;regRxD_start;reg[3:0]state;reg[7:0]RxD_data;regRxD_data_ready;dvzfvkwMI1//波特率产生,使用8倍过采样parameterBaud8=Baud*8;parameterBaud8GeneratorAccWidth=16;wire[Baud8GeneratorAccWidth:0]Baud8GeneratorInc=((Baud8(Baud8GeneratorAccWidth-7))+(ClkFrequency8))/(ClkFrequency7);reg[Baud8GeneratorAccWidth:0]Baud8GeneratorAcc;rqyn14ZNXIalways@(posedgeclkornegedgerst)if(~rst)Baud8GeneratorAcc=0;5/34elseBaud8GeneratorAcc=Baud8GeneratorAcc[Baud8GeneratorAccWidth-1:0]+Baud8GeneratorInc;EmxvxOtOco//Baud8Tick为波特率的8倍-115200*8=921600wireBaud8Tick=Baud8GeneratorAcc[Baud8GeneratorAccWidth];SixE2yXPq5//next_bit为波特率-115200always@(posedgeclkornegedgerst)if(~rst||(state==0))bit_spacing=0;elseif(Baud8Tick)bit_spacing=bit_spacing+1;wirenext_bit=(bit_spacing==7);6ewMyirQFL//检测到RxD有下跳沿时,RxD_start置1,准备接收数据always@(posedgeclk)if(Baud8Tick)beginRxD_delay=RxD;RxD_start=(Baud8Tick&RxD_delay&(~RxD));endkavU42VRUs//状态机接收数据always@(posedgeclkornegedgerst)if(~rst)state=4'b0000;elseif(Baud8Tick)case(state)4'b0000:if(RxD_start)state=4'b1000;//检测到下跳沿4'b1000:if(next_bit)state=4'b1001;//bit04'b1001:if(next_bit)state=4'b1010;//bit14'b1010:if(next_bit)state=4'b1011;//bit24'b1011:if(next_bit)state=4'b1100;//bit34'b1100:if(next_bit)state=4'b1101;//bit44'b1101:if(next_bit)state=4'b1110;//bit54'b1110:if(next_bit)state=4'b1111;//bit64'b1111:if(next_bit)state=4'b0001;//bit74'b0001:if(next_bit)state=4'b0000;//停止位default:state=4'b0000;endcasey6v3ALoS89//保存接收数据到RxD_data中always@(posedgeclkornegedgerst)6/34if(~rst)RxD_data=8'b00000000;elseif(Baud8Tick&&next_bit&&state[3])RxD_data={RxD,RxD_data[7:1]};M2ub6vSTnP//RxD_data_ready置位信号always@(posedgeclkornegedgerst)if(~rst)RxD_data_ready=0;elseRxD_data_ready=(Baud8Tick&&next_bit&&state==4'b0001);0YujCfmUCwendmodule为了测试收发是否正常,写的TestBench`timescale1ns/1nsmodulers232_test;regclk,rst,TxD_start;reg[7:0]TxD_data;wire[7:0]RxD_data;wire//RxD,TxD,TxD_busy,RxD_data_ready;transtrans(.clk(clk),.rst(rst),.TxD_start(TxD_start),.TxD_busy(TxD_busy),.TxD_data(TxD_data),.TxD(TxD));rcvrcv(.clk(clk),.rst(rst),.RxD(TxD),//收发相接时RxD=TxD7/34.RxD_data(RxD_data),.RxD_data_ready(RxD_data_ready));initialbeginTxD_start=0;TxD_data=0;clk=0;rst=1;#54rst=0;#70rst=1;#40TxD_start=1'b1;#10TxD_data=8'b11011001;#100TxD_start=1'b0;endeUts8ZQVRdalwaysbegin#30clk=~clk;#10clk=~clk;endendmodulesQsAEJkW5T二、综合三、FPGA与PC串口自收发通信串口通信其实简单实用,这里我就不多说,只把自己动手写的verilog代码共享下。实现的功能如题,就是FPGA里实现从PC接收数据,然后把接收到的数据发