完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
近期在处理一个USB2.0通信的问题,采用FPGA主控,FT245为USB芯片,Verilog编程控制。FT245有RD和WR两个读写控制端,RXF和TXE两个USB芯片工作状态反馈端。数据读操作很少,目前没问题;数据写量稍大,发送是从fifo模块发送的,先存,存到7296后停止,然后发,一次228个,分32次发完,然后发现漏数的问题,而且漏数不固定。首先我认为FPGA生成的时序本身应该是可以信任的,所以应该是编程本身的问题。我的思路是:通过控制程序中的一个写使能寄存器保证1M的发送时钟。WR端常低,写使能在1M的周期中给3/5的高电平。在写使能为高的情况下,判断TXE为低后,等待一段时间后开始将WR端置高,然后在置低。等待时间和发送时间通过一个计数器计数。时间都是超过说明书里的最小值的。我不了解这里怎么出问题了,有大神能给个参考设计或者修改思路吗,谢谢。程序是网上找然后修改的,clk为50M,如下:
`timescale 1ns/1ps module FT245test( //系统信号 input sclk, //sclk为FPGA工作时钟,默认50MHz. input rst_n, //异步复位信号,低有效. //FPGA和FT245MB间的USB接口 input USB_RXF, input USB_TXE, output reg USB_RD, output reg USB_WR, inout tri [7:0] USB_DATA, //USB和FPGA间的双向数据库总线 //模块内部和其他模块或器件间的接口 output reg [7:0] RX_data_fm_u***, //其他模块或器件从本模块读取来自USB接口的数据 input wire [7:0] TX_data_to_u***, //其他模块或器件向本模块写入发到USB接口的数据 input wire [7:0]TX_data_to_u***1, input wire RD_Enable, //其他模块或器件从本模块读取来自USB接口数据的读使能,高有效 input wire WR_Enable, //其他模块或器件向本模块写入发到USB接口数据的写使能,高有效 output reg USB_busy, //USB接口忙/空闲状态信号,高为忙碌,低为空闲 input wire start_signal,//启动信号 input wire checktime_signal//读取积分时间信号 ); //处于读状态时,由忙碌状态变为空闲状表示上一个数据开始有效 //****************************************************** //内部寄存器定义 reg [7:0] data_fm_u***; //从USB接收数据 reg [7:0] data_to_u***; //发送数据到USB reg [7:0] data_to_u***_buffer; //发送缓冲寄存器 reg [4:0] RD_time_cont; //读等待时间计数器 reg [4:0] WR_time_cont; //写等待时间计数器 parameter RX_state0 = 2'b01; //读状态0 parameter RX_state1 = 2'b10; //读状态1 parameter TX_state0 = 2'b01; //写状态0 parameter TX_state1 = 2'b10; //写状态1 reg [1:0] RX_state; //读状态 reg [1:0] TX_state; //写状态 //****************************************************** //本模块与FT245B间的数据总线 //****************************************************** assign USB_DATA=(USB_WR==1'b1)?data_to_u***:8'bzz; //****************************************************** //其他模块与本模块之间的数据交换 //****************************************************** always@(posedge sclk or negedge rst_n)//接收数据 if(!rst_n) RX_data_fm_u*** <= 8'h00; else if(RD_Enable == 1'b1) RX_data_fm_u*** <= data_fm_u***; // else // RX_data_fm_u*** <= 8'haf; ////////////////////////////////// always@(posedge sclk or negedge rst_n)//发送数据 if(!rst_n) data_to_u***_buffer <= 8'b00; else begin if(WR_Enable == 1'b1) begin if((start_signal==1'b1)&&(checktime_signal==1'b0)) begin data_to_u***_buffer <= TX_data_to_u***; end else if(checktime_signal==1'b1) begin data_to_u***_buffer <= TX_data_to_u***1; end else begin data_to_u***_buffer <= 8'b00; end end else begin data_to_u***_buffer <= 8'b00; end end //****************************************************** //USB接口忙/空闲状态信号USB_busy处理 //****************************************************** always@(posedge sclk or negedge rst_n) if(!rst_n) USB_busy<=1'b0; //状态机复位到空闲 else if((USB_RXF==1'b0 && RD_Enable == 1'b1)||(USB_TXE==1'b0 && WR_Enable==1'b1)) USB_busy<=1'b1; //状态机忙碌 else USB_busy<=1'b0; //状态机空闲 //****************************************************** //读/写FT254BM相关等待时间计数 //****************************************************** always@(posedge sclk or negedge rst_n) if(!rst_n) RD_time_cont<=8'b0; else if(USB_RD==1'b0) //读使能到来开始计数. RD_time_cont<=RD_time_cont + 1'b1; else if(USB_RXF == 1'b1) //USB_RXF == 1'b1//RD_time_cont == 5'd5 //USB_RXF没拉高之前不允许有其他跨读(写)操作 RD_time_cont<=8'b0; //****************************************************** always@(posedge sclk or negedge rst_n) if(!rst_n) WR_time_cont<=8'b0; else if(USB_WR==1'b1) //写使能到来开始计数. WR_time_cont<=WR_time_cont + 1'b1; else if(USB_TXE == 1'b1) //USB_TXE没拉高之前不允许有其他跨读(写)操作 WR_time_cont<=8'b0; //****************************************************** //本模块读FT254BM状态机 //****************************************************** always@(posedge sclk or negedge rst_n) //sclk为FPGA工作时钟,默认50MHz. if(!rst_n) begin RX_state<=RX_state0; USB_RD <=1'b1; end else if(USB_RXF==1'b0 && RD_Enable == 1'b1) //RD_Enable 高有效 begin case(RX_state) RX_state0: begin if(RD_time_cont==8'b0) USB_RD<=1'b0; //产生读信号的下降沿 else if(RD_time_cont==8'd5) //2|产生读信号的下降沿120ns后转到读状态1 RX_state<=RX_state1; end RX_state1: begin if((RD_time_cont>=8'd6)&&(RD_time_cont<8'd27)) //3|13|RD_time_cont==5'd3 产生读信号的下降沿140ns后读数据 data_fm_u***<=USB_DATA; //读FT245BM芯片FIFO的当前字节 else if(RD_time_cont==8'd27) USB_RD<=1'b1; end endcase end else begin RX_state<=RX_state0; USB_RD<=1'b1; end //reg [7:0] rev_data[0:8]; //reg [3:0] rev_cnt; //parameter total2=9; // //always @(posedge sclk or negedge rst_n) // if(!rst_n) // begin // $readmemb("test.txt",rev_data); // //idata=0; // rev_cnt=4'd0; // end // else // begin // if(crc_cnt1==total) // begin // rev_cnt = 4'd0; // end // else // begin // rev_data[rev_cnt]=RX_data_fm_u***; // rev_cnt=rev_cnt+ 1; // end // end // // ////启动和积分时间信号控制 //always @(posedge sclk or negedge rst_n) // if(!rst_n) // begin // start_signal=1'b1; // checktime_signal=1'b1; // end // else if(rev_data[4]==8'h1E) // begin // start_signal=1'b0; // checktime_signal=1'b1; // end // else if(rev_data[4]==8'h41) // begin // start_signal=1'b1; // checktime_signal=1'b0; // end // else // begin // start_signal=1'b1; // checktime_signal=1'b1; // end //****************************************************** //本模块写FT254BM状态机 //****************************************************** always@(posedge sclk or negedge rst_n) //sclk为FPGA工作时钟,默认50MHz. if(!rst_n) begin TX_state<=TX_state0; USB_WR <=1'b0; end else begin if(USB_TXE==1'b0 && WR_Enable==1'b1) //WR_Enable 高有效 begin // if(start_signal==1'b1|) // begin case(TX_state) TX_state0: begin if(WR_time_cont==8'b0) USB_WR<=1'b1; //2|产生写信号的上升沿 else if(WR_time_cont==8'd5) //产生写信号的上升沿120ns后转到写状态1 TX_state<=TX_state1; end TX_state1: begin if((WR_time_cont>=8'd6)&&(WR_time_cont<8'd27)) //3|12(WR_time_cont>=5'd3)&&(WR_time_cont<5'd8) //产生写信号的上升沿60ns发送数据 data_to_u*** <=data_to_u***_buffer; //写一个字节到FIFO,data_to_u***_buffer为发送缓冲寄存器 else if(WR_time_cont==8'd27) USB_WR <=1'b0; end endcase end // else if(checktime_signal==1'b1) // begin // case(TX_state) // TX_state0: // begin // if(WR_time_cont==5'b0) // USB_WR<=1'b1; //产生写信号的上升沿 // else if(WR_time_cont==5'd5) //产生写信号的上升沿120ns后转到写状态1 // TX_state<=TX_state1; // end // TX_state1: // begin // if(WR_time_cont==5'd6) //产生写信号的上升沿140ns发送数据 // data_to_u*** <=data_to_u***_buffer; //写一个字节到FIFO,data_to_u***_buffer为发送缓冲寄存器 // else if(WR_time_cont==5'd7) //USB_WR有效脉冲宽度最小为50ns,这里用70ns. // USB_WR <=1'b0; // end // endcase // end // else // begin // TX_state<=TX_state0; // USB_WR <=1'b0; // end // end else begin TX_state<=TX_state0; USB_WR <=1'b0; end end endmodule |
|
相关推荐
1个回答
|
|
不错,很好的经验分享,辛苦麻烦了,欠缺这方面的资料,非常感谢
|
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
1193 浏览 1 评论
1108 浏览 0 评论
矩阵4x4个按键,如何把识别结果按编号01-16(十进制)显示在两个七段数码管上?
1312 浏览 0 评论
902 浏览 0 评论
2136 浏览 0 评论
1395 浏览 32 评论
5593 浏览 113 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-19 09:24 , Processed in 0.756296 second(s), Total 69, Slave 53 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号