FPGA驱动USB2.0芯片-FT245的问题

2019-11-21 13:45发布

<p>近期在处理一个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,如下:</p><br><pre style="max-width: 100%;"><code class="cpp hljs" codemark="1">` ti mescale <span class="hljs-number">1</span>ns/<span class="hljs-number">1</span><span class="hljs-function">ps module <span class="hljs-title">FT245test</span><span class="hljs-params">( <span class="hljs-comment">//系统信号</span> input sclk, <span class="hljs-comment">//sclk为FPGA工作时钟,默认50MHz.</span> input rst_n, <span class="hljs-comment">//异步复位信号,低有效.</span> <span class="hljs-comment">//FPGA和FT245MB间的USB</span> 接口 input USB_RXF, input USB_TXE, output reg USB_RD, output reg USB_WR, inout tri [<span class="hljs-number">7</span>:<span class="hljs-number">0</span>] USB_DATA, <span class="hljs-comment">//USB和FPGA间的双向数据库总线</span> <span class="hljs-comment">//模块内部和其他模块或器件间的接口</span> output reg [<span class="hljs-number">7</span>:<span class="hljs-number">0</span>] RX_data_fm_usb, <span class="hljs-comment">//其他模块或器件从本模块读取来自USB接口的数据</span> input wire [<span class="hljs-number">7</span>:<span class="hljs-number">0</span>] TX_data_to_usb, <span class="hljs-comment">//其他模块或器件向本模块写入发到USB接口的数据</span> input wire [<span class="hljs-number">7</span>:<span class="hljs-number">0</span>]TX_data_to_u sb1 , input wire RD_Enable, <span class="hljs-comment">//其他模块或器件从本模块读取来自USB接口数据的读使能,高有效</span> input wire WR_Enable, <span class="hljs-comment">//其他模块或器件向本模块写入发到USB接口数据的写使能,高有效</span> output reg USB_busy, <span class="hljs-comment">//USB接口忙/空闲状态信号,高为忙碌,低为空闲</span> input wire start_signal,<span class="hljs-comment">//启动信号</span> input wire checktime_signal<span class="hljs-comment">//读取积分时间信号</span> )</span></span>; <span class="hljs-comment">//处于读状态时,由忙碌状态变为空闲状表示上一个数据开始有效</span> <span class="hljs-comment">//******************************************************</span> <span class="hljs-comment">//内部寄存器定义</span> reg [<span class="hljs-number">7</span>:<span class="hljs-number">0</span>] data_fm_usb; <span class="hljs-comment">//从USB接收数据</span> reg [<span class="hljs-number">7</span>:<span class="hljs-number">0</span>] data_to_usb; <span class="hljs-comment">//发送数据到USB</span> reg [<span class="hljs-number">7</span>:<span class="hljs-number">0</span>] data_to_usb_buffer; <span class="hljs-comment">//发送缓冲寄存器</span> reg [<span class="hljs-number">4</span>:<span class="hljs-number">0</span>] RD_time_cont; <span class="hljs-comment">//读等待时间计数器</span> reg [<span class="hljs-number">4</span>:<span class="hljs-number">0</span>] WR_time_cont; <span class="hljs-comment">//写等待时间计数器</span> parameter RX_state0 = <span class="hljs-number">2</span><span class="hljs-string">'b01; //读状态0 parameter RX_state1 = 2'</span>b10; <span class="hljs-comment">//读状态1</span> parameter TX_state0 = <span class="hljs-number">2</span><span class="hljs-string">'b01; //写状态0 parameter TX_state1 = 2'</span>b10; <span class="hljs-comment">//写状态1</span> reg [<span class="hljs-number">1</span>:<span class="hljs-number">0</span>] RX_state; <span class="hljs-comment">//读状态</span> reg [<span class="hljs-number">1</span>:<span class="hljs-number">0</span>] TX_state; <span class="hljs-comment">//写状态</span> <span class="hljs-comment">//******************************************************</span> <span class="hljs-comment">//本模块与FT245B间的数据总线</span> <span class="hljs-comment">//******************************************************</span> assign USB_DATA=(USB_WR==<span class="hljs-number">1</span><span class="hljs-string">'b1)?data_to_usb:8'</span>bzz; <span class="hljs-comment">//******************************************************</span> <span class="hljs-comment">//其他模块与本模块之间的数据交换</span> <span class="hljs-comment">//******************************************************</span> always@(posedge sclk or negedge rst_n)<span class="hljs-comment">//接收数据</span> <span class="hljs-keyword">if</span>(!rst_n) RX_data_fm_usb &lt;= <span class="hljs-number">8</span><span class="hljs-string">'h00; else if(RD_Enable == 1'</span>b1) RX_data_fm_usb &lt;= data_fm_usb; <span class="hljs-comment">// else</span> <span class="hljs-comment">// RX_data_fm_usb &lt;= 8'haf;</span> <span class="hljs-comment">////////////////////////////////// </span> always@(posedge sclk or negedge rst_n)<span class="hljs-comment">//发送数据</span> <span class="hljs-keyword">if</span>(!rst_n) data_to_usb_buffer &lt;= <span class="hljs-number">8</span><span class="hljs-string">'b00; else begin if(WR_Enable == 1'</span>b1) <span class="hljs-function">begin <span class="hljs-title">if</span><span class="hljs-params">((start_signal==<span class="hljs-number">1</span><span class="hljs-string">'b1)&amp;&amp;(checktime_signal==1'</span>b0)</span>) begin data_to_usb_buffer &lt;</span>= TX_data_to_usb; <span class="hljs-function">end <span class="hljs-keyword">else</span> <span class="hljs-title">if</span><span class="hljs-params">(checktime_signal==<span class="hljs-number">1</span><span class="hljs-string">'b1) begin data_to_usb_buffer &lt;= TX_data_to_usb1; end else begin data_to_usb_buffer &lt;= 8'</span>b00; end end <span class="hljs-keyword">else</span> begin data_to_usb_buffer &lt;= <span class="hljs-number">8</span><span class="hljs-string">'b00; end end //****************************************************** //USB接口忙/空闲状态信号USB_busy处理 //****************************************************** always@(posedge sclk or negedge rst_n) if(!rst_n) USB_busy&lt;=1'</span>b0; <span class="hljs-comment">//状态机复位到空闲</span> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>((USB_RXF==<span class="hljs-number">1</span><span class="hljs-string">'b0 &amp;&amp; RD_Enable == 1'</span>b1)</span>||<span class="hljs-params">(USB_TXE==<span class="hljs-number">1</span><span class="hljs-string">'b0 &amp;&amp; WR_Enable==1'</span>b1)</span>) USB_busy&lt;</span>=<span class="hljs-number">1</span><span class="hljs-string">'b1; //状态机忙碌 else USB_busy&lt;=1'</span>b0; <span class="hljs-comment">//状态机空闲</span> <span class="hljs-comment">//******************************************************</span> <span class="hljs-comment">//读/写FT254BM相关等待时间计数</span> <span class="hljs-comment">//******************************************************</span> always@(posedge sclk or negedge rst_n) <span class="hljs-keyword">if</span>(!rst_n) RD_time_cont&lt;=<span class="hljs-number">8</span><span class="hljs-string">'b0; else if(USB_RD==1'</span>b0) <span class="hljs-comment">//读使能到来开始计数.</span> RD_time_cont&lt;=RD_time_cont + <span class="hljs-number">1</span><span class="hljs-string">'b1; else if(USB_RXF == 1'</span>b1) <span class="hljs-comment">//USB_RXF == 1'b1//RD_time_cont == 5'd5 //USB_RXF没拉高之前不允许有其他跨读(写)操作</span> RD_time_cont&lt;=<span class="hljs-number">8</span><span class="hljs-string">'b0; //****************************************************** always@(posedge sclk or negedge rst_n) if(!rst_n) WR_time_cont&lt;=8'</span>b0; <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(USB_WR==<span class="hljs-number">1</span><span class="hljs-string">'b1) //写使能到来开始计数. WR_time_cont&lt;=WR_time_cont + 1'</span>b1; <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(USB_TXE == <span class="hljs-number">1</span><span class="hljs-string">'b1) //USB_TXE没拉高之前不允许有其他跨读(写)操作 WR_time_cont&lt;=8'</span>b0; <span class="hljs-comment">//******************************************************</span> <span class="hljs-comment">//本模块读FT254BM状态机</span> <span class="hljs-comment">//****************************************************** </span> always@(posedge sclk or negedge rst_n) <span class="hljs-comment">//sclk为FPGA工作时钟,默认50MHz.</span> <span class="hljs-keyword">if</span>(!rst_n) begin RX_state&lt;=RX_state0; USB_RD &lt;=<span class="hljs-number">1</span><span class="hljs-string">'b1; end else if(USB_RXF==1'</span>b0 &amp;&amp; RD_Enable == <span class="hljs-number">1</span><span class="hljs-string">'b1) //RD_Enable 高有效 begin case(RX_state) RX_state0: begin if(RD_time_cont==8'</span>b0) USB_RD&lt;=<span class="hljs-number">1</span><span class="hljs-string">'b0; //产生读信号的下降沿 else if(RD_time_cont==8'</span>d5) <span class="hljs-comment">//2|产生读信号的下降沿120ns后转到读状态1</span> RX_state&lt;=RX_state1; end RX_state1: <span class="hljs-function">begin <span class="hljs-title">if</span><span class="hljs-params">((RD_time_cont&gt;=<span class="hljs-number">8</span><span class="hljs-string">'d6)&amp;&amp;(RD_time_cont&lt;8'</span>d27)</span>) <span class="hljs-comment">//3|13|RD_time_cont==5'd3 产生读信号的下降沿140ns后读数据</span> data_fm_usb&lt;</span>=USB_DATA; <span class="hljs-comment">//读FT245BM芯片FIFO的当前字节</span> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(RD_time_cont==<span class="hljs-number">8</span><span class="hljs-string">'d27) USB_RD&lt;=1'</span>b1; end endcase end <span class="hljs-keyword">else</span> begin RX_state&lt;=RX_state0; USB_RD&lt;=<span class="hljs-number">1</span><span class="hljs-string">'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'</span>d0; <span class="hljs-comment">// end</span> <span class="hljs-comment">// else</span> <span class="hljs-comment">// begin</span> <span class="hljs-comment">// if(crc_cnt1==total)</span> <span class="hljs-comment">// begin</span> <span class="hljs-comment">// rev_cnt = 4'd0;</span> <span class="hljs-comment">// end</span> <span class="hljs-comment">// else</span> <span class="hljs-comment">// begin</span> <span class="hljs-comment">// rev_data[rev_cnt]=RX_data_fm_usb;</span> <span class="hljs-comment">// rev_cnt=rev_cnt+ 1;</span> <span class="hljs-comment">// end</span> <span class="hljs-comment">// end</span> <span class="hljs-comment">//</span> <span class="hljs-comment">//</span> <span class="hljs-comment">////启动和积分时间信号控制 </span> <span class="hljs-comment">//always @(posedge sclk or negedge rst_n)</span> <span class="hljs-comment">// if(!rst_n)</span> <span class="hljs-comment">// begin</span> <span class="hljs-comment">// start_signal=1'b1;</span> <span class="hljs-comment">// checktime_signal=1'b1;</span> <span class="hljs-comment">// end</span> <span class="hljs-comment">// else if(rev_data[4]==8'h1E)</span> <span class="hljs-comment">// begin</span> <span class="hljs-comment">// start_signal=1'b0;</span> <span class="hljs-comment">// checktime_signal=1'b1;</span> <span class="hljs-comment">// end</span> <span class="hljs-comment">// else if(rev_data[4]==8'h41)</span> <span class="hljs-comment">// begin</span> <span class="hljs-comment">// start_signal=1'b1;</span> <span class="hljs-comment">// checktime_signal=1'b0;</span> <span class="hljs-comment">// end</span> <span class="hljs-comment">// else</span> <span class="hljs-comment">// begin</span> <span class="hljs-comment">// start_signal=1'b1;</span> <span class="hljs-comment">// checktime_signal=1'b1;</span> <span class="hljs-comment">// end</span> <span class="hljs-comment">//******************************************************</span> <span class="hljs-comment">//本模块写FT254BM状态机</span> <span class="hljs-comment">//******************************************************</span> always@(posedge sclk or negedge rst_n) <span class="hljs-comment">//sclk为FPGA工作时钟,默认50MHz.</span> <span class="hljs-keyword">if</span>(!rst_n) begin TX_state&lt;=TX_state0; USB_WR &lt;=<span class="hljs-number">1</span><span class="hljs-string">'b0; end else begin if(USB_TXE==1'</span>b0 &amp;&amp; WR_Enable==<span class="hljs-number">1</span><span class="hljs-string">'b1) //WR_Enable 高有效 begin // if(start_signal==1'</span>b1|) <span class="hljs-comment">// begin</span> <span class="hljs-keyword">case</span>(TX_state) TX_state0: <span class="hljs-function">begin <span class="hljs-title">if</span><span class="hljs-params">(WR_time_cont==<span class="hljs-number">8</span><span class="hljs-string">'b0) USB_WR&lt;=1'</span>b1; <span class="hljs-comment">//2|产生写信号的上升沿</span> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(WR_time_cont==<span class="hljs-number">8</span><span class="hljs-string">'d5) //产生写信号的上升沿120ns后转到写状态1 TX_state&lt;=TX_state1; end TX_state1: begin if((WR_time_cont&gt;=8'</span>d6)</span>&amp;&amp;<span class="hljs-params">(WR_time_cont&lt;<span class="hljs-number">8</span><span class="hljs-string">'d27)) //3|12(WR_time_cont&gt;=5'</span>d3)</span>&amp;&amp;<span class="hljs-params">(WR_time_cont&lt;<span class="hljs-number">5</span><span class="hljs-string">'d8) //产生写信号的上升沿60ns发送数据 data_to_usb &lt;=data_to_usb_buffer; //写一个字节到FIFO,data_to_usb_buffer为发送缓冲寄存器 else if(WR_time_cont==8'</span>d27)</span> USB_WR &lt;</span>=<span class="hljs-number">1</span><span class="hljs-string">'b0; end endcase end // else if(checktime_signal==1'</span>b1) <span class="hljs-comment">// begin</span> <span class="hljs-comment">// case(TX_state)</span> <span class="hljs-comment">// TX_state0:</span> <span class="hljs-comment">// begin</span> <span class="hljs-comment">// if(WR_time_cont==5'b0)</span> <span class="hljs-comment">// USB_WR&lt;=1'b1; //产生写信号的上升沿</span> <span class="hljs-comment">// else if(WR_time_cont==5'd5) //产生写信号的上升沿120ns后转到写状态1</span> <span class="hljs-comment">// TX_state&lt;=TX_state1;</span> <span class="hljs-comment">// end</span> <span class="hljs-comment">// TX_state1:</span> <span class="hljs-comment">// begin</span> <span class="hljs-comment">// if(WR_time_cont==5'd6) //产生写信号的上升沿140ns发送数据</span> <span class="hljs-comment">// data_to_usb &lt;=data_to_usb_buffer; //写一个字节到FIFO,data_to_usb_buffer为发送缓冲寄存器</span> <span class="hljs-comment">// else if(WR_time_cont==5'd7) //USB_WR有效脉冲宽度最小为50ns,这里用70ns.</span> <span class="hljs-comment">// USB_WR &lt;=1'b0;</span> <span class="hljs-comment">// end</span> <span class="hljs-comment">// endcase </span> <span class="hljs-comment">// end</span> <span class="hljs-comment">// else</span> <span class="hljs-comment">// begin</span> <span class="hljs-comment">// TX_state&lt;=TX_state0;</span> <span class="hljs-comment">// USB_WR &lt;=1'b0;</span> <span class="hljs-comment">// end</span> <span class="hljs-comment">// end</span> <span class="hljs-keyword">else</span> begin TX_state&lt;=TX_state0; USB_WR &lt;=<span class="hljs-number">1</span><span class="hljs-string">'b0; end end endmodule</span></code></pre><br> <p><br></p>
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。