<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 <= <span class="hljs-number">8</span><span class="hljs-string">'h00;
else if(RD_Enable == 1'</span>b1)
RX_data_fm_usb <= data_fm_usb;
<span class="hljs-comment">// else</span>
<span class="hljs-comment">// RX_data_fm_usb <= 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 <= <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)&&(checktime_signal==1'</span>b0)</span>)
begin
data_to_usb_buffer <</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 <= TX_data_to_usb1;
end
else
begin
data_to_usb_buffer <= 8'</span>b00;
end
end
<span class="hljs-keyword">else</span>
begin
data_to_usb_buffer <= <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<=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 && RD_Enable == 1'</span>b1)</span>||<span class="hljs-params">(USB_TXE==<span class="hljs-number">1</span><span class="hljs-string">'b0 && WR_Enable==1'</span>b1)</span>)
USB_busy<</span>=<span class="hljs-number">1</span><span class="hljs-string">'b1; //状态机忙碌
else
USB_busy<=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<=<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<=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<=<span class="hljs-number">8</span><span class="hljs-string">'b0;
//******************************************************
always@(posedge sclk or negedge rst_n)
if(!rst_n)
WR_time_cont<=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<=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<=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<=RX_state0;
USB_RD <=<span class="hljs-number">1</span><span class="hljs-string">'b1;
end
else if(USB_RXF==1'</span>b0 && 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<=<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<=RX_state1;
end
RX_state1:
<span class="hljs-function">begin
<span class="hljs-title">if</span><span class="hljs-params">((RD_time_cont>=<span class="hljs-number">8</span><span class="hljs-string">'d6)&&(RD_time_cont<8'</span>d27)</span>) <span class="hljs-comment">//3|13|RD_time_cont==5'd3 产生读信号的下降沿140ns后读数据</span>
data_fm_usb<</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<=1'</span>b1;
end
endcase
end
<span class="hljs-keyword">else</span>
begin
RX_state<=RX_state0;
USB_RD<=<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<=TX_state0;
USB_WR <=<span class="hljs-number">1</span><span class="hljs-string">'b0;
end
else
begin
if(USB_TXE==1'</span>b0 && 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<=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<=TX_state1;
end
TX_state1:
begin
if((WR_time_cont>=8'</span>d6)</span>&&<span class="hljs-params">(WR_time_cont<<span class="hljs-number">8</span><span class="hljs-string">'d27)) //3|12(WR_time_cont>=5'</span>d3)</span>&&<span class="hljs-params">(WR_time_cont<<span class="hljs-number">5</span><span class="hljs-string">'d8) //产生写信号的上升沿60ns发送数据
data_to_usb <=data_to_usb_buffer; //写一个字节到FIFO,data_to_usb_buffer为发送缓冲寄存器
else if(WR_time_cont==8'</span>d27)</span>
USB_WR <</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<=1'b1; //产生写信号的上升沿</span>
<span class="hljs-comment">// else if(WR_time_cont==5'd5) //产生写信号的上升沿120ns后转到写状态1</span>
<span class="hljs-comment">// TX_state<=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 <=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 <=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<=TX_state0;</span>
<span class="hljs-comment">// USB_WR <=1'b0;</span>
<span class="hljs-comment">// end</span>
<span class="hljs-comment">// end</span>
<span class="hljs-keyword">else</span>
begin
TX_state<=TX_state0;
USB_WR <=<span class="hljs-number">1</span><span class="hljs-string">'b0;
end
end
endmodule</span></code></pre><br>
<p><br></p>
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
一周热门 更多>