【中科亿海微EQ6HL45开发平台测评体验】+07.USB测试与仿真(zmj)
<p><strong>【中科亿海微EQ6HL45开发平台测评体验】+07.USB测试与仿真(zmj)</strong></p><p cid="n470" mdtype="paragraph">中科亿海微EQ6HL45开发平台包含一个USB2.0通信接口,它可以实现FPGA和PC之间的USB通信。</p>
<p cid="n471" mdtype="paragraph">本篇内容主要包含USB2.0接口、测试和仿真。其中,实测PC和FPGA之间的USB2.0通信存在误码情况;经过代码功能仿真,FPGA的USB2.0接口程序在仿真环境中数据收发正常,因此推测是USB固件与FPGA接口程序不匹配导致误码。</p>
<h1 cid="n472" mdtype="heading">1. USB2.0接口</h1>
<h2 cid="n473" mdtype="heading">1.1 FT232H芯片</h2>
<p cid="n474" mdtype="paragraph">中科亿海微EQ6HL45开发平台采用了FTDI Chip公司的FT232H单通道高速USB芯片为开发板实现和电脑之间的USB2.0数据通信。</p>
<p cid="n475" mdtype="paragraph">FT232H芯片支持USB2.0高速通信(HS速度480Mb/s)和全速通信(FS速度12Mb/s),数据接口支持不同的数据通信模式(FIFO,I2C,SPI,JTAG),上电后读取外置的EEPROM配置内容来决定数据通信模式,也可以通过PC方便的修改配置方式。USB芯片的接口管脚的功能是复用的,具体请参考FT232H的芯片手册。其中读写缓存的深度均为1k字节。</p>
<p cid="n476" mdtype="paragraph"><span style="background-color:#f39c12;">//------FT232H手册</span></p>
<p cid="n476" mdtype="paragraph"></p>
<h2 cid="n479" mdtype="heading">1.2 工作模式</h2>
<p cid="n480" mdtype="paragraph">FT232H支持转UART或FIFO模式,并可配置成多种工业串行或并行接口:</p>
<pre style="background:#555; padding:10px; color:#ddd !important;">
//------FT232H芯片支持多种接口模式
可配置成 UART 接口
FT245 同步 FIFO 接口
FT245 异步 FIFO 接口
同步或异步 Bit-Bang 接口
MPSSE 接口
Fast 串口
CPU FIFO 接口
FT1248 接口</pre>
<p cid="n482" mdtype="paragraph"> </p>
<p cid="n483" mdtype="paragraph">在开发板中通过EEPROM内的固件配置成“FT245同步FIFO接口”。</p>
<p cid="n484" mdtype="paragraph">在开发板中通过EEPROM内的固件配置成“FT245同步FIFO接口”。</p>
<p cid="n485" mdtype="paragraph">需要特别指出的是,FT232H芯片需要外部12MHz晶振输入时钟信号,同时它通过Pin-29对外输出60MHz时钟信号以供外设使用。</p>
<p cid="n486" mdtype="paragraph"> </p>
<h2 cid="n487" mdtype="heading">1.3 USB2.0接口实现</h2>
<p cid="n488" mdtype="paragraph">USB芯片FT232H的工作模式由EEPROM内提前烧录好的固件设定,数据接口信号与FPGA的IO相连,通过FPGA的编程来对FT232H进行数据通信,FT232H的硬件连接是按照“FT245同步FIFO接口”方式连接的,如图所示:</p>
<p cid="n488" mdtype="paragraph"></p>
<p cid="n488" mdtype="paragraph">//------原理图</p>
<p cid="n488" mdtype="paragraph"></p>
<h2 cid="n495" mdtype="heading">1.4 USB2.0部分接口定义</h2>
<p cid="n496" mdtype="paragraph">了解FT232H芯片的接口功能才能更好的理解其工作原理。</p>
<p cid="n728" mdtype="paragraph">USB2.0部分重要接口信号定义:</p>
<pre>
<code class="language-cs">//------FT232H_Interfaces
//---1.clock_nc
a.ft_clk
//Output 60MHz clock signals.
b.ft_siwu_n 立刻发送/唤醒功能
//Tied to "1'b1" if not used.
//---2.RD: usb-> fpga
a.ft_rxf_n 低表示接收FIFO数据可读
//When high, do not read data from the FIFO.
//When low, there is data available in the FIFO which can be read by driving RD# low.
//When in synchronous mode, data is transferred on every clock that RXF# and RD# are both low.
//Note that the OE# pin must be driven low at least 1 clock period before asserting RD# low.
b.ft_oe_n USB数据输出使能
//Output enable when low to drive data onto D0-7.
//This should be driven low at least 1 clock period
//before driving RD# low to allow for data buffer turn-around.
c.ft_rd_n 数据接收 FIFO 读信号,低有效
//Enables the current FIFO data byte to be driven onto D0...D7 when RD# goes low.
//The next FIFO data byte (if available) is fetched from the receive FIFO buffer each CLKOUT cycle until RD# goes high.
//---3.WR: fpga -> usb
a.ft_txe_n 低表示发送FIFO数据可以写
//When high, do not write data into the FIFO.
//When low, data can be written into the FIFO by driving WR# low.
//When in synchronous mode, data is transferred on every clock that TXE# and WR# are both low.
b.ft_wr_n 数据发送FIFO写信号,低有效
//Enables the data byte on the D0...D7 pins to be written into the transmit FIFO buffer when WR# is low.
//The next FIFO data byte is written to the transmit FIFO buffer each CLKOUT cycle until WR# goes high.
//---4.DATA: inout
a.ft_data
//D7 to D0 bidirectional FIFO data.
//This bus is normally input unless OE# is low.</code></pre>
<p cid="n728" mdtype="paragraph"> </p>
<h2 cid="n725" mdtype="heading">1.5 FT245同步FIFO模式的时序</h2>
<p cid="n734" mdtype="paragraph">FT245同步FIFO模式的时序(详细时序参考FT232H手册):</p>
<pre style="background:#555; padding:10px; color:#ddd !important;">
//------FT245同步FIFO模式的时序:
读时序中,首先FT232H将RXF#拉低,此时可以读取FIFO里的数据,FPGA可将OE#先拉低,过至少一个时钟周期,再将RD#拉低,在CLKOUT上升沿采集数据;
写时序中,FT232H将TXE#拉低,表示现在可写,FPGA可将WR#拉低,在CLKOUT上升沿写入数据。</pre>
<p cid="n488" mdtype="paragraph"> </p>
<p cid="n488" mdtype="paragraph"></p>
<p cid="n488" mdtype="paragraph"> </p>
<h1 cid="n500" mdtype="heading">2. USB2.0测试</h1>
<p cid="n747" mdtype="paragraph">FPGA代码实现了FT245同步FIFO模式的回环loopback功能。</p>
<p cid="n501" mdtype="paragraph">操作流程:</p>
<pre style="background:#555; padding:10px; color:#ddd !important;">
//------操作流程:
a.连接电源、JTAG接口和mini-USB接口;
b.打开上位机“USB测试工具/usbtools”;
c.烧录程序,打开Debug界面,通过上位机观察发送数据和接收数据。
//------异常现象:
a.PC收发数据不一致,接收数据比发送数据多一个,且误码;
b.FPGA通过Debug窗口发现接收的数据异常;
c.由此判断,数据异常的环节在FT232H芯片。</pre>
<p> </p>
<p>//------USB2.0接口在扩展板的实物图</p>
<p></p>
<p>//------上位机测试结果</p>
<p></p>
<p>//------eLINX的Debug信号</p>
<p></p>
<h1 cid="n752" mdtype="heading">3. USB2.0接口仿真</h1>
<h2 cid="n754" mdtype="heading">3.1 仿真功能设计</h2>
<p cid="n795" mdtype="paragraph">仿真代码具备以下几个功能:</p>
<ul cid="n796" data-mark="*" mdtype="list">
<li cid="n798" mdtype="list_item">
<p cid="n799" mdtype="paragraph">激励时钟和复位信号。</p>
</li>
<li cid="n802" mdtype="list_item">
<p cid="n800" mdtype="paragraph">依据“FT245同步FIFO模式”的时序,模拟先发送数据后接收数据,重复10次。</p>
</li>
<li cid="n808" mdtype="list_item">
<p cid="n806" mdtype="paragraph">实时监视monitor代码内部的收发数据并打印。</p>
</li>
</ul>
<p cid="n793" mdtype="paragraph">//------激励时钟和数据</p>
<pre>
<code class="language-cpp">//------clock
initial begin
sys_clk = 0 ;
end
always #(PERIOD_100MHz / 2) sys_clk = ~sys_clk ;
/*
initial begin
sys_clk = 0 ;
forever #(PERIOD_100MHz / 2) sys_clk = !sys_clk ;
end
*/
assign ft_clk = sys_clk ;
//------reset
initial begin
sys_rst_n = 1'b0 ;
#1000;
sys_rst_n = 1'b1 ;
end
//------data_gen(随机数通过$random产生)
always@(posedge sys_clk)begin
if(data_gen_en == 1'b1)
data_gen =$random ;
end
assign ft_data = (ft_rxf_n == 1'b1)? 8'hz : data_gen;</code></pre>
<p> </p>
<p>//------重复收发10次(通过repeat实现)</p>
<pre>
<code class="language-cpp">repeat(10) begin
#100;//usb-> fpga
ft_rxf_n = 1'b0 ;
ft_txe_n = 1'b1 ;
data_gen_en = 1'b1 ;
#100;
ft_rxf_n = 1'b1 ;
ft_txe_n = 1'b1 ;
data_gen_en = 1'b0 ;
#100;//fpga -> usb
ft_rxf_n = 1'b1 ;
ft_txe_n = 1'b0 ;
data_gen_en = 1'b0 ;
#100;
ft_rxf_n = 1'b1 ;
ft_txe_n = 1'b1 ;
data_gen_en = 1'b0 ;
end</code></pre>
<p> </p>
<p>//------内部信号监视(通过monitor实现)</p>
<pre>
<code class="language-cpp">//------Monitor
initial begin
//---
#100;
$display("**********************************\n");
$display("//------Dump / Monitor all data.\n");
$display("**********************************\n");
//---
while(1)begin
//forever begin //forever will cause dead-lock.
@(posedge sys_clk)
if(u_top.ft232h_m0.buf_wr)begin
$display("Data usb2fpga is %x.",u_top.ft232h_m0.buf_data);
end
if(u_top.ft232h_m0.buf_rd)begin
$display("Data fpga2usb is %x.",u_top.ft232h_m0.ft_data_out);
end
end
end</code></pre>
<p> </p>
<h2 cid="n826" mdtype="heading">3.2 仿真Log</h2>
<p cid="n828" mdtype="paragraph">MOdelsim仿真Log如下:主要打印十次收发的数据(随机数),经比对收发数据一致,即<span style="background-color:#f39c12;">验证了FPGA代码功能OK</span>。</p>
<p cid="n828" mdtype="paragraph"> </p>
<pre>
<code class="language-cpp">//------Modelsim仿真Log
VSIM(paused)> run -all
# **********************************
#
# //------Dump / Monitor all data.
#
# **********************************
#
# Data usb2fpga is 81.
# Data usb2fpga is 09.
# Data usb2fpga is 63.
# Data usb2fpga is 0d.
# Data usb2fpga is 8d.
# Data usb2fpga is 65.
# Data usb2fpga is 12.
# Data usb2fpga is 01.
# Data fpga2usb is 81.
# Data fpga2usb is 09.
# Data fpga2usb is 63.
# Data fpga2usb is 0d.
# Data fpga2usb is 8d.
# Data fpga2usb is 65.
# Data fpga2usb is 12.
# Data fpga2usb is 01.
# Data usb2fpga is 3d.
# Data usb2fpga is ed.
# Data usb2fpga is 8c.
# Data usb2fpga is f9.
# Data usb2fpga is c6.
# Data usb2fpga is c5.
# Data usb2fpga is aa.
# Data usb2fpga is e5.
# Data fpga2usb is 3d.
# Data fpga2usb is ed.
# Data fpga2usb is 8c.
# Data fpga2usb is f9.
# Data fpga2usb is c6.
# Data fpga2usb is c5.
# Data fpga2usb is aa.
# Data fpga2usb is e5.
# Data usb2fpga is 8f.
# Data usb2fpga is f2.
# Data usb2fpga is ce.
# Data usb2fpga is e8.
# Data usb2fpga is c5.
# Data usb2fpga is 5c.
# Data usb2fpga is bd.
# Data usb2fpga is 2d.
# Data fpga2usb is 8f.
# Data fpga2usb is f2.
# Data fpga2usb is ce.
# Data fpga2usb is e8.
# Data fpga2usb is c5.
# Data fpga2usb is 5c.
# Data fpga2usb is bd.
# Data fpga2usb is 2d.
# Data usb2fpga is 0a.
# Data usb2fpga is 80.
# Data usb2fpga is 20.
# Data usb2fpga is aa.
# Data usb2fpga is 9d.
# Data usb2fpga is 96.
# Data usb2fpga is 13.
# Data usb2fpga is 0d.
# Data fpga2usb is 0a.
# Data fpga2usb is 80.
# Data fpga2usb is 20.
# Data fpga2usb is aa.
# Data fpga2usb is 9d.
# Data fpga2usb is 96.
# Data fpga2usb is 13.
# Data fpga2usb is 0d.
# Data usb2fpga is d5.
# Data usb2fpga is 02.
# Data usb2fpga is ae.
# Data usb2fpga is 1d.
# Data usb2fpga is cf.
# Data usb2fpga is 23.
# Data usb2fpga is 0a.
# Data usb2fpga is ca.
# Data fpga2usb is d5.
# Data fpga2usb is 02.
# Data fpga2usb is ae.
# Data fpga2usb is 1d.
# Data fpga2usb is cf.
# Data fpga2usb is 23.
# Data fpga2usb is 0a.
# Data fpga2usb is ca.
# Data usb2fpga is 8a.
# Data usb2fpga is 41.
# Data usb2fpga is d8.
# Data usb2fpga is 78.
# Data usb2fpga is 89.
# Data usb2fpga is eb.
# Data usb2fpga is b6.
# Data usb2fpga is c6.
# Data fpga2usb is 8a.
# Data fpga2usb is 41.
# Data fpga2usb is d8.
# Data fpga2usb is 78.
# Data fpga2usb is 89.
# Data fpga2usb is eb.
# Data fpga2usb is b6.
# Data fpga2usb is c6.
# Data usb2fpga is 2a.
# Data usb2fpga is 0b.
# Data usb2fpga is 71.
# Data usb2fpga is 85.
# Data usb2fpga is 4f.
# Data usb2fpga is 3b.
# Data usb2fpga is 3a.
# Data usb2fpga is 7e.
# Data fpga2usb is 2a.
# Data fpga2usb is 0b.
# Data fpga2usb is 71.
# Data fpga2usb is 85.
# Data fpga2usb is 4f.
# Data fpga2usb is 3b.
# Data fpga2usb is 3a.
# Data fpga2usb is 7e.
# Data usb2fpga is d9.
# Data usb2fpga is 62.
# Data usb2fpga is 4c.
# Data usb2fpga is 9f.
# Data usb2fpga is 8f.
# Data usb2fpga is f8.
# Data usb2fpga is b7.
# Data usb2fpga is 9f.
# Data fpga2usb is d9.
# Data fpga2usb is 62.
# Data fpga2usb is 4c.
# Data fpga2usb is 9f.
# Data fpga2usb is 8f.
# Data fpga2usb is f8.
# Data fpga2usb is b7.
# Data fpga2usb is 9f.
# Data usb2fpga is 89.
# Data usb2fpga is 49.
# Data usb2fpga is d0.
# Data usb2fpga is d7.
# Data usb2fpga is 51.
# Data usb2fpga is 96.
# Data usb2fpga is 0c.
# Data usb2fpga is c2.
# Data fpga2usb is 89.
# Data fpga2usb is 49.
# Data fpga2usb is d0.
# Data fpga2usb is d7.
# Data fpga2usb is 51.
# Data fpga2usb is 96.
# Data fpga2usb is 0c.
# Data fpga2usb is c2.
# Data usb2fpga is 3d.
# Data usb2fpga is 12.
# Data usb2fpga is 7e.
# Data usb2fpga is 6d.
# Data usb2fpga is 39.
# Data usb2fpga is 1f.
# Data usb2fpga is d3.
# Data usb2fpga is 85.
# Data fpga2usb is 3d.
# Data fpga2usb is 12.
# Data fpga2usb is 7e.
# Data fpga2usb is 6d.
# Data fpga2usb is 39.
# Data fpga2usb is 1f.
# Data fpga2usb is d3.
# Data fpga2usb is 85.
# **********************************
#
# //------Simulation_Stop.
#
# //------Stop @ 6000 ns.
#
# **********************************
#
# Break in Module usb_sim_top at D:/tronlong/eHighWay/prj/7_usb_loopback_top/usb_loopback_top.srcs/sim_1/new/usb_sim_top.v line 112
VSIM(paused)></code></pre>
<p> </p>
<h2 cid="n829" mdtype="heading">3.3 仿真波形</h2>
<p cid="n831" mdtype="paragraph">通过观察仿真波形wave,可以看到FPGA实现了数据收发,且数据收发正确。</p>
<pre style="background:#555; padding:10px; color:#ddd !important;">
//------
随机写入数据(十六进制):81 09 63 0d 8d 65 12 01 //第一组,共十组。buf_wr/buf_data
最终读取数据(十六进制):81 09 63 0d 8d 65 12 01 //第一组,共十组。buf_rd/ft_data_out</pre>
<p> </p>
<p></p>
<p></p>
<p></p>
<h1 cid="n880" mdtype="heading">附. USB仿真代码usb_sim_top.v</h1>
<p cid="n882" mdtype="paragraph">//------usb_sim_top.v</p>
<pre>
<code class="language-cpp">`timescale 1 ns/ 1 ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 11-16-2022 16:19:00
// Design Name:
// Module Name: usb_sim_top
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module usb_sim_top( );
//------------------------------------------------------------------
//------parameter
parameter PERIOD_100MHz = 10;//100MHz = 10.0ns
parameter PERIOD_60MHz= 16.7;// 60MHz = 16.7ns
//------
reg sys_rst_n ;
reg sys_clk ;//Work@60MHz Sim@100mhz //------FT232H_Interfaces
wire ft_clk ;//Work@60MHz: usb-clock output to fpga.
//---RD: usb-> fpga //Data available
reg ft_rxf_n ;//When high, do not read data from the FIFO.
//When low, there is data available in the FIFO which can be read by driving RD# low.
//When in synchronous mode, data is transferred on every clock that RXF# and RD# are both low.
//Note that the OE# pin must be driven low at least 1 clock period before asserting RD# low.
wire ft_oe_n ;//Output enable when low to drive data onto D0-7.
//This should be driven low at least 1 clock period
//before driving RD# low to allow for data buffer turn-around.
wire ft_rd_n ;//Enables the current FIFO data byte to be driven onto D0...D7 when RD# goes low.
//The next FIFO data byte (if available) is fetched from the receive FIFO buffer each CLKOUT cycle until RD# goes high.
//---WR: fpga -> usb //Space available
reg ft_txe_n ;//When high, do not write data into the FIFO.
//When low, data can be written into the FIFO by driving WR# low.
//When in synchronous mode, data is transferred on every clock that TXE# and WR# are both low.
wire ft_wr_n ;//Enables the data byte on the D0...D7 pins to be written into the transmit FIFO buffer when WR# is low.
//The next FIFO data byte is written to the transmit FIFO buffer each CLKOUT cycle until WR# goes high.
//---
wire ft_siwu_n ;//Send Immediate / WakeUp signal combines two functions.
//Tied to "1'b1" if not used.
//---DATA: inout
wire ft_data ;//D7 to D0 bidirectional FIFO data.
//This bus is normally input unless OE# is low.
//------
reg data_gen ;
reg data_gen_en ;
//------------------------------------------------------------------clock_reset
//------clock
initial begin
sys_clk = 0 ;
end
always #(PERIOD_100MHz / 2) sys_clk = ~sys_clk ;
/*
initial begin
sys_clk = 0 ;
forever #(PERIOD_100MHz / 2) sys_clk = !sys_clk ;
end
*/
assign ft_clk = sys_clk ;
//------reset
initial begin
sys_rst_n = 1'b0 ;
#1000;
sys_rst_n = 1'b1 ;
end
//------------------------------------------------------------------work
//------
initial begin
//---
ft_rxf_n = 1'b1 ;
ft_txe_n = 1'b1 ;
data_gen_en = 1'b0 ;
#1200;
repeat(10) begin
#100;//usb-> fpga
ft_rxf_n = 1'b0 ;
ft_txe_n = 1'b1 ;
data_gen_en = 1'b1 ;
#100;
ft_rxf_n = 1'b1 ;
ft_txe_n = 1'b1 ;
data_gen_en = 1'b0 ;
#100;//fpga -> usb
ft_rxf_n = 1'b1 ;
ft_txe_n = 1'b0 ;
data_gen_en = 1'b0 ;
#100;
ft_rxf_n = 1'b1 ;
ft_txe_n = 1'b1 ;
data_gen_en = 1'b0 ;
end
//---
#1000 ;
$display("**********************************\n");
$display("//------Simulation_Stop.\n");
$display("//------Stop @ %t ns.\n",$time/1000);
$display("**********************************\n");
$stop();
#1000 ;
$display("**********************************\n");
$display("//------Simulation_Stop.\n");
$display("//------Finish @ %t ns.\n",$time/1000);
$display("**********************************\n");
$finish();
end
//------Monitor
initial begin
//---
#100;
$display("**********************************\n");
$display("//------Dump / Monitor all data.\n");
$display("**********************************\n");
//---
while(1)begin
//forever begin //forever will cause dead-lock.
@(posedge sys_clk)
if(u_top.ft232h_m0.buf_wr)begin
$display("Data usb2fpga is %x.",u_top.ft232h_m0.buf_data);
end
if(u_top.ft232h_m0.buf_rd)begin
$display("Data fpga2usb is %x.",u_top.ft232h_m0.ft_data_out);
end
end
end
//------data_gen
always@(posedge sys_clk)begin
if(data_gen_en == 1'b1)
data_gen =$random ;
end
assign ft_data = (ft_rxf_n == 1'b1)? 8'hz : data_gen;
//------------------------------------------------------------------
top u_top(
.sys_clk ( ),//input 50MHz NC
.rst_n (sys_rst_n ),//input
.ft_clk (ft_clk ),//input 60MHz
.ft_rxf_n (ft_rxf_n ),//input Data available
.ft_txe_n (ft_txe_n ),//input Space available
.ft_oe_n (ft_oe_n ),//output
.ft_rd_n (ft_rd_n ),//output
.ft_wr_n (ft_wr_n ),//output
.ft_siwu_n (ft_siwu_n ),//output
.ft_data (ft_data ) //inout
);
//------------------------------------------------------------------
endmodule
</code></pre>
<p>//------工程文件</p>
<div></div>
<p> </p>
<p>//------end</p>
<p> </p>
<p>USB固件与FPGA接口程序不匹配导致误码可以确认是这样么</p>
火辣西米秀 发表于 2022-11-18 07:40
USB固件与FPGA接口程序不匹配导致误码可以确认是这样么
<p>初步推测是USB固件与FPGA接口程序不匹配。</p>
<p>开发板资料里说USB2.0接口模式是“FT245的同步FIFO模式”,仿真确实没问题,但是实测有误码。</p>
<p>固件在芯片FT232H的外部EEPROM里,开发板并没有对用户开放访问接口,所以固件暂时无法更改。</p>
<p>硬件原理图设计与芯片FT232H的datasheet基本一致,可以排除硬件设计问题。</p>
页:
[1]