搜索
bottom↓
回复: 43

FPGA 串口接收超大数据问题

[复制链接]

出0入0汤圆

发表于 2013-4-29 13:51:01 | 显示全部楼层 |阅读模式
请问有没有人试过 用FPGA做 串口  接受几百 Kbytes 数据的啊?
最近做了个串口郁闷死了!
波特率设置19200, 系统时钟125MHZ

接收数据只接一帧,几百个字节都没有问题, 连续起来接收的时候 中间就老是 时不时有丢帧现象!间隔100ms 都有问题

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

发表于 2013-4-30 16:48:35 | 显示全部楼层
用FIFO过度,木有问题

出0入0汤圆

 楼主| 发表于 2013-5-1 17:03:45 | 显示全部楼层
wang110 发表于 2013-4-30 16:48
用FIFO过度,木有问题

现在是我的主频时钟跑了125Mhz  接到中间就有那么几帧出错!!FIFO 我是用了!

出0入0汤圆

发表于 2013-5-1 17:09:32 | 显示全部楼层
不应当的,相对FGPA工作速度,串口即使115200都是非常慢的

出0入0汤圆

 楼主| 发表于 2013-5-1 20:15:10 | 显示全部楼层
NJ8888 发表于 2013-5-1 17:09
不应当的,相对FGPA工作速度,串口即使115200都是非常慢的

我知道115200对于FPGA 来说,对接收到的数据进行解析的时间是绰绰有余的!

问题是 现在接收的时候总是发送中间有那么几帧数据接错!
我的串口模块是模仿特权同学写的那个,全局时钟用125mhz,通过判断下降沿,来决定串口是否开始接收数据!
现在怀疑中间如果有个大于8ns毛刺 那么整个串口模块就误认为数据来了,于是导致错误!

出0入0汤圆

发表于 2013-5-1 20:55:18 | 显示全部楼层
suxilong 发表于 2013-5-1 20:15
我知道115200对于FPGA 来说,对接收到的数据进行解析的时间是绰绰有余的!

问题是 现在接收的时候总是发 ...


不能这样的,应当按波特率的8 16或近似(当你无法严格按波特倍乘时)的速率做采样时钟,然后8中取中间3 16取中间7要求多数作为数据电平,125M的时钟非常不合适

出0入0汤圆

 楼主| 发表于 2013-5-2 12:25:36 | 显示全部楼层
NJ8888 发表于 2013-5-1 20:55
不能这样的,应当按波特率的8 16或近似(当你无法严格按波特倍乘时)的速率做采样时钟,然后8中取中间3 1 ...

我的采样时钟的就是一个脉冲(宽度即为 主频时钟(8ns))!

cnt 在两种情况下会清零,
1。计数到BPS_PARA的时候                          ---         BPS_PARA =  主频时钟(125 ) * 1000 000  /  波特率(115200)
2。 RS232_RX 脚下降沿来了的时候

cnt 计数器 计数到中间的时候就产生采样时钟,采样时钟的就是一个脉冲(宽度即为 主频时钟(8ns))!采样一个BIT   然后每次采样完1bit    就又用另外的计数Rx_bit_cnt  计数1次    计数10次就算一个byte结束

波特倍乘? 何解?

出0入0汤圆

发表于 2013-5-2 14:21:56 | 显示全部楼层
altera FPGA IP串口使用中断模式,结果发送数据和接收数据老丢数,请问一下遇到过没?

出0入0汤圆

 楼主| 发表于 2013-5-2 15:35:23 | 显示全部楼层
lfeng105 发表于 2013-5-2 14:21
altera FPGA IP串口使用中断模式,结果发送数据和接收数据老丢数,请问一下遇到过没? ...

哇!! 你用IP核啊!!! 我是模仿特权同学代码改的! 不一样 !所以我也不清楚IP核的丢数是否和我一样!


但个人感觉一个好的串口 接收发送 程序必须经得住以下几个考验
1。单个字节 一次性接收或发送  不出错
2。单个字节 间隔接收或发送   不出错
3。单帧数据 一次性连续接收或发送  几百 bytes  不出错
4。多帧数据 (每帧几百bytes)间隔接收或发送   不出错

只可惜现在前三个考验都经过了,就是第四个 没能完成,一个多星期了 郁闷无助。。。。。

出0入0汤圆

发表于 2013-5-2 16:31:44 | 显示全部楼层
我的跑2.25Mbps都没问题啊,可能是你串口代码问题

出0入0汤圆

 楼主| 发表于 2013-5-2 19:50:58 | 显示全部楼层
denike 发表于 2013-5-2 16:31
我的跑2.25Mbps都没问题啊,可能是你串口代码问题

求指教!我用的 是特权同学的代码!

出0入0汤圆

发表于 2013-5-2 21:30:43 | 显示全部楼层
我的项目里用了9个串口,115200,8,1。
8路同时接收都没问题,MB+uarilite,SP6的芯片。

出0入0汤圆

 楼主| 发表于 2013-5-2 22:04:16 | 显示全部楼层
tennokoe 发表于 2013-5-2 21:30
我的项目里用了9个串口,115200,8,1。
8路同时接收都没问题,MB+uarilite,SP6的芯片。 ...

网上见到很多: 

UART在发送或接收数据时,使用的时钟信号频率f是波特率(b=9 600 b/s)的16倍,由外部系统时钟进行16分频得到。UART每16个波特时钟发送或接收一个二进制位,设计中采用的晶振频率c=25 MHz,那么波特率发生器输出的时钟信号周期为: k = 25*1000 000 / 16* 96000

这个十六到底是怎么回事?


如果我用的是125MHZ  用一个cnt 来计数, 计数到 BPS_PA 就清零或者检测到下降沿就清零, 数到中间 产生一个脉冲进行bit 采样!

BPS_PA = 125*1000 000/ 9600

这样可以吗?

两者有什么区别?  

出0入0汤圆

发表于 2013-5-2 22:31:58 | 显示全部楼层
本帖最后由 tennokoe 于 2013-5-2 22:36 编辑

给一个基于FSL总线的串口IP,直接看串口部分的实现你就明白了。

如果撸主的串口是用软核+IP实现的,那么很可能是软件代码的问题。
贴出来看看。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

 楼主| 发表于 2013-5-3 10:54:59 | 显示全部楼层
tennokoe 发表于 2013-5-2 22:31
给一个基于FSL总线的串口IP,直接看串口部分的实现你就明白了。

如果撸主的串口是用软核+IP实现的,那么很 ...

谢谢! 我没有用软核,  我全部用硬件语言实现在!  VHDL 写在, 当然一切都得感谢特权 同学.VERILOG 版本也有  直接可以参照 特权同学在代码

等我把代码注释一下再贴出来请教大家, 现在没注释很乱....


其实我有一个相当困惑在问题! 为什么大家都说  采样频率 最好是波特率的 8 ,或16 倍



最终无非是保证能够在BIT 中间进行采样,    那如果我 用以下在思路实现是否有问题呢

FPGA  主频125MHZ   ,波特率使用 115200   

定义一个 CNT ,                    范围为 0 到 BPS_PA  ,                            BPS_PA =  (125 * 1000 000 / 115200 ) -1
其次计数到1/2 BPS_PA   产生一个脉冲 进行采样一个BIT


正常情况下不停在计数, 只有在以下两种情况进行清零
1.   计数计满 BPS_PA
2.   检测到RS232_RX 接收端 有电平跳变  (作用,不停在矫正计数器保证计数到1/2 BPS_PA   产生在脉冲处于 BIT  采样在中间点 )


这样的话, 误差是否就不会累积 呢?

出0入0汤圆

发表于 2013-5-4 10:34:06 | 显示全部楼层
看看人家的波特率产生
parameter ClkFrequency = 36000000;        // 25MHz
parameter Baud = 57600;
parameter RegisterInputData = 1;        // in RegisterInputData mode, the input doesn't have to stay valid while the character is been transmitted

// Baud generator
parameter BaudGeneratorAccWidth = 16;
reg [BaudGeneratorAccWidth:0] BaudGeneratorAcc;
`ifdef DEBUG
wire [BaudGeneratorAccWidth:0] BaudGeneratorInc = 17'h10000;
`else
wire [BaudGeneratorAccWidth:0] BaudGeneratorInc = ((Baud<<(BaudGeneratorAccWidth-8))+(ClkFrequency>>9))/(ClkFrequency>>8);
`endif

wire BaudTick = BaudGeneratorAcc[BaudGeneratorAccWidth];
wire TxD_busy;
always @(posedge clk) if(TxD_busy) BaudGeneratorAcc <= BaudGeneratorAcc[BaudGeneratorAccWidth-1:0] + BaudGeneratorInc;

出0入0汤圆

发表于 2013-5-4 10:35:36 | 显示全部楼层
// Transmitter state machine
reg [3:0] state;
wire TxD_ready = (state==0);
assign TxD_busy = ~TxD_ready;

reg [7:0] TxD_dataReg;
always @(posedge clk) if(TxD_ready & TxD_start) TxD_dataReg <= TxD_data;
wire [7:0] TxD_dataD = RegisterInputData ? TxD_dataReg : TxD_data;

//The RS-232 parameters used are fixed: 8-bits data, 2 stop bits, no-parity.
always @(posedge clk)
case(state)
        4'b0000: if(TxD_start) state <= 4'b0100;
        //4'b0001: if(BaudTick) state <= 4'b0100;
        4'b0100: if(BaudTick) state <= 4'b1000;  // start
        4'b1000: if(BaudTick) state <= 4'b1001;  // bit 0
        4'b1001: if(BaudTick) state <= 4'b1010;  // bit 1
        4'b1010: if(BaudTick) state <= 4'b1011;  // bit 2
        4'b1011: if(BaudTick) state <= 4'b1100;  // bit 3
        4'b1100: if(BaudTick) state <= 4'b1101;  // bit 4
        4'b1101: if(BaudTick) state <= 4'b1110;  // bit 5
        4'b1110: if(BaudTick) state <= 4'b1111;  // bit 6
        4'b1111: if(BaudTick) state <= 4'b0010;  // bit 7
        4'b0010: if(BaudTick) state <= 4'b0000;  // stop1
        //4'b0011: if(BaudTick) state <= 4'b0000;  // stop2
        default: if(BaudTick) state <= 4'b0000;
endcase

// Output mux
reg muxbit;
always @( * )
//always @( state[2:0] )
case(state[2:0])
        3'd0: muxbit <= TxD_dataD[0];
        3'd1: muxbit <= TxD_dataD[1];
        3'd2: muxbit <= TxD_dataD[2];
        3'd3: muxbit <= TxD_dataD[3];
        3'd4: muxbit <= TxD_dataD[4];
        3'd5: muxbit <= TxD_dataD[5];
        3'd6: muxbit <= TxD_dataD[6];
        3'd7: muxbit <= TxD_dataD[7];
endcase

// Put together the start, data and stop bits
reg TxD;
always @(posedge clk) TxD <= (state<4) | (state[3] & muxbit);  // register the output to make it glitch free

出0入0汤圆

发表于 2013-5-4 10:36:05 | 显示全部楼层
这个发送部分 你参考下

出0入0汤圆

发表于 2013-5-4 20:43:20 | 显示全部楼层
tennokoe 发表于 2013-5-2 22:31
给一个基于FSL总线的串口IP,直接看串口部分的实现你就明白了。

如果撸主的串口是用软核+IP实现的,那么很 ...

static void uart1_ISR(void)
{   
    if(UART1->STATUS.BITS.TRDY && UART1->CONTROL.BITS.ITRDY)
    {
        if (uart1.TxTail != uart1.TxHead)                                               //如果itrdy中断已打开,判断发送缓冲区是否为空
        {
            UART1->TXDATA.BITS.TRANSMIT_DATA = uart1.TxBuf[uart1.TxTail];               //如果发送缓冲区中还有发送数据,发送一个字节数据
            if (++uart1.TxTail > (TXBUFSIZE - 1))                                       //如果已到达数组尾部,TxTail索引值返回数组头部
                    uart1.TxTail = 0;
        }
        else                                                                            //已经没有待发送数据,关闭发送中断,使能接收中断
        {   
            UART1->CONTROL.BITS.ITRDY=0;                                                //关发送中断
        }
    }
    if(UART1->STATUS.BITS.RRDY)
    {
        if(uart1.receive_count < RXBUFSIZE)
            {
                    uart1.receive_buffertmp[uart1.receive_count++] = UART1->RXDATA.BITS.RECEIVE_DATA;
                    if(uart1.receive_buffertmp[uart1.receive_count-1]==';')
                  {
                        uart1.receive_flag = 1;
                        uart1.RxTail = uart1.receive_count-1;
                  }
            }
        else
            {
                    uart1.receive_count = 0;
                    uart1.receive_buffertmp[uart1.receive_count++] = UART1->RXDATA.BITS.RECEIVE_DATA;
                    if(uart1.receive_buffertmp[uart1.receive_count-1]==';')
                  {
                        uart1.receive_flag = 1;
                        uart1.RxTail = uart1.receive_count-1;
                  }
            }
    }
}  

这是软核IP的接受发送中断代码,RXBUFSIZE = 1024,程序判断字尾‘;’。在主程序中循环处理uart1.receive_buffertmp[] 内容

出0入0汤圆

 楼主| 发表于 2013-5-4 22:35:24 | 显示全部楼层
denike 发表于 2013-5-4 10:34
看看人家的波特率产生
parameter ClkFrequency = 36000000;        // 25MHz
parameter Baud = 57600;

谢谢! 这段代码 与FPGA4fun 上面的差不多!  

只是首先我现在用的VHDL,VHDL 里面移位还不是很懂,

其次verilog 好久没用 虽然大概清楚思路,但是最让我不解的还是  为什么一定要这样来做计数! 直接用主频除以波特率 得到一个数取整不就可以了吗?
这样每次rs232 ——rx  电平跳变就矫正一次, 这样不是很精确吗?

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2013-5-6 13:21:05 | 显示全部楼层
避免毛刺可以在6,7,8的时候采样三次,然后依据两次为高取1,两次为低取0;好像这个论坛上有代码和文档的;
另外,你是采用中断的方式还是轮询的方式来进行数据传输的;可以在上位机加延时看看是什么效果;

出0入0汤圆

发表于 2013-5-6 21:56:19 | 显示全部楼层
楼主真是执着到固执,你的方法对付毛刺没招

出0入0汤圆

 楼主| 发表于 2013-5-8 23:07:26 | 显示全部楼层
denike 发表于 2013-5-4 10:34
看看人家的波特率产生
parameter ClkFrequency = 36000000;        // 25MHz
parameter Baud = 57600;

类似这种移位,在VHDL 里面如何实现得了呢?

出0入0汤圆

 楼主| 发表于 2013-5-8 23:10:35 | 显示全部楼层
NJ8888 发表于 2013-5-6 21:56
楼主真是执着到固执,你的方法对付毛刺没招

谢谢NJ 不辞劳苦回复, 今天回头去看看FPGA4fun  的例子,发现原来是我自己一直没有彻底理解16分频的目的
http://www.erg.abdn.ac.uk/~gorry/course/phy-pages/async.html
后来看了他后面的链接 才发现自己原来一直误解了~~~

出0入0汤圆

 楼主| 发表于 2013-5-9 10:54:36 | 显示全部楼层
denike 发表于 2013-5-4 10:36
这个发送部分 你参考下

请问你这个部分的代码 有没有testbech 啊?

fpga4fun 上面的rs232  例子大家用的人很多,但实际代码很多都不是很明了, 我想跑一下仿真看看 信号的变化是怎样的, 但是老是跑不出波形 不知哪里出错~~~

出0入0汤圆

 楼主| 发表于 2013-5-9 11:01:48 | 显示全部楼层
NJ8888 发表于 2013-5-6 21:56
楼主真是执着到固执,你的方法对付毛刺没招

NJ ,这是fpga4fun  上面rs232  的例子 用这个testbech  总是跑不出 波形  能否指点一下

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2013-5-9 11:14:29 | 显示全部楼层
我的就是fpga4fun  的例子啊 很好用啊 修改一下可以跑1Mbps以上了

出0入0汤圆

 楼主| 发表于 2013-5-9 14:02:24 | 显示全部楼层
denike 发表于 2013-5-9 11:14
我的就是fpga4fun  的例子啊 很好用啊 修改一下可以跑1Mbps以上了

判断下降沿的 那部分我看不懂

我想跑一下rtl  仿真 看看是怎么个原理  但是 跑不起来

出0入0汤圆

发表于 2013-5-9 22:52:32 | 显示全部楼层
我和楼主一样,用的的是特权同学的代码,也参考了fpga4fun的代码,应该没什么问题...

出0入0汤圆

 楼主| 发表于 2013-5-9 23:15:28 | 显示全部楼层
深海烟花 发表于 2013-5-9 22:52
我和楼主一样,用的的是特权同学的代码,也参考了fpga4fun的代码,应该没什么问题... ...


fpga4fun的代码看不懂啊, 太久没动verilog~~~ 写个testbech 又仿真不出来~~~~
尤其以下两个进程
////////////////////////////
reg [1:0] RxD_sync_inv;
always @(posedge clk) if(Baud8Tick) RxD_sync_inv <= {RxD_sync_inv[0], ~RxD};
// we invert RxD, so that the idle becomes "0", to prevent a phantom character to be received at startup

reg [1:0] RxD_cnt_inv;
reg RxD_bit_inv;

always @(posedge clk)
if(Baud8Tick)
begin
        if( RxD_sync_inv[1] && RxD_cnt_inv!=2'b11) RxD_cnt_inv <= RxD_cnt_inv + 2'h1;
        else
        if(~RxD_sync_inv[1] && RxD_cnt_inv!=2'b00) RxD_cnt_inv <= RxD_cnt_inv - 2'h1;

        if(RxD_cnt_inv==2'b00) RxD_bit_inv <= 1'b0;
        else
        if(RxD_cnt_inv==2'b11) RxD_bit_inv <= 1'b1;
end








reg [3:0] state;
reg [3:0] bit_spacing;

// "next_bit" controls when the data sampling occurs
// depending on how noisy the RxD is, different values might work better
// with a clean connection, values from 8 to 11 work
wire next_bit = (bit_spacing==4'd10);

always @(posedge clk)
if(state==0)
        bit_spacing <= 4'b0000;
else
if(Baud8Tick)
        bit_spacing <= {bit_spacing[2:0] + 4'b0001} | {bit_spacing[3], 3'b000};

出0入0汤圆

发表于 2013-6-20 00:11:35 | 显示全部楼层
用我的UART代码,保证没问题。

出0入0汤圆

发表于 2013-11-22 15:22:12 | 显示全部楼层
不错 学习了

出0入0汤圆

发表于 2013-11-22 16:06:26 | 显示全部楼层
代码本身有bug,可能是数据接收完成时的设置flag有问题

我曾经写过一个uart,就是这种问题

用modelsim弄大量的数据进行功能仿真也许就可以看得出来了
这种出错条件应该很固定

出0入0汤圆

发表于 2014-3-19 14:17:43 | 显示全部楼层
请问楼主最后怎么解决的?谢谢

出0入0汤圆

发表于 2014-3-19 14:32:09 | 显示全部楼层
有没有作IO毛刺过滤

出0入0汤圆

发表于 2014-3-21 11:44:30 来自手机 | 显示全部楼层
串口收发问题以后看看,mark

出0入0汤圆

发表于 2014-8-28 14:43:57 | 显示全部楼层
收藏了慢慢看  最近也被这个串口搞的头大

出0入0汤圆

发表于 2014-9-6 09:54:01 | 显示全部楼层
000000000000000000000000000000000000000000000000

出0入0汤圆

发表于 2014-12-24 20:20:13 | 显示全部楼层
感谢大家,项目上正要用类似的接口。

出0入0汤圆

发表于 2018-9-29 14:41:51 | 显示全部楼层
使用特权同学源码测试串口收发,发现发送字节数大于3个时在刚上电第一次发送,固定第二个字节会丢失

出0入0汤圆

发表于 2018-9-29 22:38:26 | 显示全部楼层
低级错误

出0入0汤圆

发表于 2018-9-30 10:09:54 | 显示全部楼层
其实同步采样,用16倍时钟,每个字节都重新调整同步,没有累积误差是又简单又稳定的做法。

出10入12汤圆

发表于 2018-11-12 17:57:16 | 显示全部楼层
一定要多倍过采样!!!!!!!

出10入12汤圆

发表于 2018-11-16 13:46:18 | 显示全部楼层
用fifo  放m4k里面
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-26 17:03

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表