为验证一款UTMI接口的PHY芯片数据通路是否正常,功能实现是否满足需求,特搭建此工程进行测试。
FPGA芯片:Xilinx XCVU440
PHY芯片:CY7C68000
平台:Vivado 2019.2
下文是我写的几篇技术背景:
CY7C68000介绍
开源项目UTMI介绍
USB2.0介绍
PHY 芯片接口:
接口稍微有点不同,这个芯片支持高低八位分别使用的模式,具体可以看一下第一篇博客。
打算使用开源项目中的一下模块来实现
此模块可以将 UTMI接口转内部数据接口。
如何对内部数据接口进行数据的读写呢?
我发现这个内部数据总线接口可以较好的和AXI4-S总线进行连接,就是数据位宽对不上,稍微处理一下就好。
添加一个MicroBlaze,用MicroBlaze对接口访问,代码编写起来更加方便。
MicroBlaze部分这么搭建:
添加了一个AXI4-S 转 AXI4-Full的FIFO,就能对数据进行读写了。
该IP的介绍。使用memory mapped的形式访问AXI4-S接口,看来这样使用是没错的可以使用的。
最终架构:
加了个时钟模块和一个vio模块
UTMI走60MHz,MicroBlaze走100MHz;
vio用来提供外部时钟复位。
顶层代码:
module usb_utmi_top(
(* mark_debug="true" *)input PHY_CLK,
(* mark_debug="true" *)output RESET,
(* mark_debug="true" *)inout [15:0] DATA,
(* mark_debug="true" *)output XCVR_SEL,
(* mark_debug="true" *)output TERM_SEL,
(* mark_debug="true" *)output SUSPEND,
(* mark_debug="true" *)input [1:0] LINESTATE,
(* mark_debug="true" *)output [1:0] OP_MODE,
(* mark_debug="true" *)output TX_VALID,
(* mark_debug="true" *)input TX_READY,
(* mark_debug="true" *)input RX_ACTIVE,
(* mark_debug="true" *)input RX_ERROR,
(* mark_debug="true" *)input RX_VALID,
(* mark_debug="true" *)inout VALIDH,
(* mark_debug="true" *)output DATA16_8,
(* mark_debug="true" *)output UNI_BIDI
);
//SYS
(* mark_debug="true" *)wire reset;
wire locked;
wire clk_100m;
wire clk_60m;
// UTMI Interface
(* mark_debug="true" *)wire[7:0] rx_data;
(* mark_debug="true" *)wire rx_valid, rx_active, rx_err;
(* mark_debug="true" *)wire[7:0] tx_data;
(* mark_debug="true" *)wire tx_valid,tx_ready,tx_first,tx_valid_last;
wire[31:0] AXI_STR_TXD_0_tdata;
wire mode_hs; // High Speed Mode
wire usb_reset; // USB Reset
wire usb_suspend; // USB Suspend
wire usb_attached; // Attached to USB
// input clk_in1_0;
// input dcm_locked_0;
// input reset_rtl_0;
(* mark_debug="true" *)wire[15:0] data_out_w;
(* mark_debug="true" *)wire[15:0] data_in_w;
assign UNI_BIDI =1'b1; //将高低八分别定义为收发
assign DATA16_8 =1'b0; //八位模式
assign RESET =reset;
assign data_in_w = DATA;
assign DATA = TX_READY ? data_out_w : 16'hzzzz;
assign tx_data = AXI_STR_TXD_0_tdata[7:0];
clk_wiz_0 u0
(
// Clock out ports
.clk_out1(clk_100m), // output clk_out1
.clk_out2(clk_60m), // output clk_out2
// Status and control signals
.reset(1'b0), // input reset
.locked(locked), // output locked
// Clock in ports
.clk_in1(PHY_CLK)); // input clk_in1
vio_0 u1 (
.clk(clk_100m), // input wire clk
.probe_out0(reset) // output wire [0 : 0] probe_out0
);
design_1_wrapper u2(
.AXI_STR_RXD_0_tdata( {4{rx_data}} ),
.AXI_STR_RXD_0_tlast(),
.AXI_STR_RXD_0_tready(),
.AXI_STR_RXD_0_tvalid(rx_valid),
.AXI_STR_TXD_0_tdata(AXI_STR_TXD_0_tdata ),
.AXI_STR_TXD_0_tlast(tx_valid_last),
.AXI_STR_TXD_0_tready(tx_ready),
.AXI_STR_TXD_0_tvalid(tx_valid),
.clk_in1_0(clk_100m),
.dcm_locked_0(locked),
.reset_rtl_0(1'b1));
// UTMI Interface
usbf_utmi_if u3(
.phy_clk( PHY_CLK ),
.rst( reset ),
.DataOut( data_out_w[15:8]),
.TxValid( TX_VALID ),
.TxReady( TX_READY ),
.RxValid( RX_VALID ),
.RxActive( RX_ACTIVE ),
.RxError( RX_ERROR ),
.DataIn( data_in_w[7:0] ),
.XcvSelect( XCVR_SEL ),
.TermSel( TERM_SEL ),
.SuspendM( SUSPEND ),
.LineState( LINESTATE ),
.OpMode( OP_MODE ),
.usb_vbus( ),
.rx_data( rx_data ),
.rx_valid( rx_valid ),
.rx_active( rx_active ),
.rx_err( rx_err ),
.tx_data( tx_data ),
.tx_valid( tx_valid ),
.tx_valid_last( tx_valid_last ),
.tx_ready( tx_ready ),
.tx_first( tx_first ),
.mode_hs( mode_hs ),
.usb_reset( usb_reset ),
.usb_suspend( usb_suspend ),
.usb_attached( usb_attached ),
.resume_req( )
);
搭建完成后编译,会遇到组合逻辑环的问题,是开源项目自带的,我加了一条约束暂时解决了。
组合逻辑环解决
MicroBlaze代码用C写,现场编辑,看看效果。
待测试,测试完成再写总结。提供一种思路