⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tests_lib.v

📁 usb1.1 ip核
💻 V
字号:
/////////////////////////////////////////////////////////////////////////                                                             ////////  Test Bench Library                                         ////////                                                             ////////                                                             ////////  Author: Rudolf Usselmann                                   ////////          rudi@asics.ws                                      ////////                                                             ////////                                                             ////////  Downloaded from: http://www.opencores.org/cores/usb1_funct/////////                                                             /////////////////////////////////////////////////////////////////////////////                                                             //////// Copyright (C) 2000-2002 Rudolf Usselmann                    ////////                         www.asics.ws                        ////////                         rudi@asics.ws                       ////////                                                             //////// This source file may be used and distributed without        //////// restriction provided that this copyright statement is not   //////// removed from the file and that any derivative work contains //////// the original copyright notice and the associated disclaimer.////////                                                             ////////     THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY     //////// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   //////// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS   //////// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR      //////// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,         //////// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    //////// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE   //////// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR        //////// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  //////// LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT  //////// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT  //////// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE         //////// POSSIBILITY OF SUCH DAMAGE.                                 ////////                                                             ///////////////////////////////////////////////////////////////////////////  CVS Log////  $Id: tests_lib.v,v 1.1 2002/09/25 06:10:10 rudi Exp $////  $Date: 2002/09/25 06:10:10 $//  $Revision: 1.1 $//  $Author: rudi $//  $Locker:  $//  $State: Exp $//// Change History://               $Log: tests_lib.v,v $//               Revision 1.1  2002/09/25 06:10:10  rudi//               Added Test Bench//////////////task show_errors;//这是任务begin$display("\n");$display("     +--------------------+");$display("     |  Total ERRORS: %0d   |", error_cnt);$display("     +--------------------+");endendtasktask recv_packet;//主机收到数据包output	[3:0]	pid;//应该仅是数据包的标识符output		size;//有效数据载荷,即除去pid和crc16后的东西integer		del, size,n;//del没有用????reg	[15:0]	crc16r;reg	[7:0]	x,y;begincrc16r = 16'hffff;//全一,算是初始化吧utmi_recv_pack(size);//两个作用:将主机接收到的数据存在txmen中,二,将接收到的总字节数存在size中for(n=1;n<size-2;n=n+1)//n从1到size-3,不包含0,和size-2,size-1,因为0是pid,最后两个是crc16   begin	y = txmem[n];//注意x的存放顺序,是为了计算crc16而设定的顺序	x[7] = y[0];	x[6] = y[1];	x[5] = y[2];	x[4] = y[3];	x[3] = y[4];	x[2] = y[5];	x[1] = y[6];	x[0] = y[7];	crc16r = crc16(crc16r, x);//crc16(crc_in,din),这里的crc16是一个函数   end//到这里时,针对payload部分的crc16校验已经计算完毕,存在crc16r中y = crc16r[15:8];x[7] = y[0];x[6] = y[1];x[5] = y[2];x[4] = y[3];x[3] = y[4];x[2] = y[5];x[1] = y[6];x[0] = y[7];crc16r[15:8] = ~x;//实际上是将crc16的高8位重新排了个序y = crc16r[7:0];x[7] = y[0];x[6] = y[1];x[5] = y[2];x[4] = y[3];x[3] = y[4];x[2] = y[5];x[1] = y[6];x[0] = y[7];crc16r[7:0] = ~x;//实际上是将crc16的低8位重新排了个序//到这里时,按照标准顺序排列的crc16已经存在crc16r中了if(crc16r !== {txmem[n], txmem[n+1]})//注意位对位的匹配,我这里已看不清了,因为它的crc16算法不明$display("ERROR: CRC Mismatch: Expected: %h, Got: %h%h (%t)",		crc16r, txmem[n], txmem[n+1], $time);for(n=0;n<size-3;n=n+1)//把数据存到缓冲区去了,二级缓冲的样子,存到buffer1中了	buffer1[buffer1_last+n] = txmem[n+1];buffer1_last = buffer1_last+n;//修改buffer1的指针使它指向空白区// Check PIDx = txmem[0];if(x[7:4] !== ~x[3:0])//注意!==为不全等运算符$display("ERROR: Pid Checksum mismatch: Top: %h Bottom: %h (%t)",		x[7:4], x[3:0], $time);pid = x[3:0];size=size-3;//减掉了pid和crc16endendtasktask send_token;//主机发送令牌包input	[6:0]	fa;input	[3:0]	ep;input	[3:0]	pid;reg	[15:0]	tmp_data;reg	[10:0]	x,y;//11位integer		len;begintmp_data = {fa, ep, 5'h0};//被凑成16位了if(pid == `USBF_T_PID_ACK)	len = 1;//看到这里我可以确定是主机发送的令牌包了,因为主机只有一种握手包就是ackelse				len = 3;y = {fa, ep};//11位x[10] = y[4];//它这么变换的目的是什么????x[9] = y[5]; //是不是为了适应crc5输入的需要????不明白,crc5是按发送先后顺序计算的,我认为一点都不直观,不好x[8] = y[6];x[7] = y[7];x[6] = y[8];x[5] = y[9];x[4] = y[10];x[3] = y[0];x[2] = y[1];x[1] = y[2];x[0] = y[3];y[4:0]  = crc5( 5'h1f, x );//算出来crc5了,注意到全1输入!!!为什么?还不是初始化吗,傻瓜!tmp_data[4:0]  = ~y[4:0];tmp_data[15:5] = x;txmem[0] = {~pid, pid};	// PID,注意了,tmp_data中的数据是按位发送的先后顺序排列的,即倒序txmem[1] = {	tmp_data[8],tmp_data[9],tmp_data[10],tmp_data[11],		tmp_data[12],tmp_data[13],tmp_data[14],tmp_data[15]};txmem[2] = {	tmp_data[0],tmp_data[1],tmp_data[2],tmp_data[3],		tmp_data[4],tmp_data[5],tmp_data[6],tmp_data[7]};utmi_send_pack(len);//把要发送的令牌或握手包送出去了,要发送的数据存在txmem中endendtasktask send_sof;//传送帧开始包input	[10:0]	frmn;//给定要传送的帧号reg	[15:0]	tmp_data;reg	[10:0]	x,y;beginy = frmn;x[10] = y[0];x[9] = y[1];x[8] = y[2];x[7] = y[3];x[6] = y[4];x[5] = y[5];x[4] = y[6];x[3] = y[7];x[2] = y[8];x[1] = y[9];x[0] = y[10];tmp_data[15:5] = x;//注意,tmp_data是按发送的位先后顺序排列的y[4:0]  = crc5( 5'h1f, x );tmp_data[4:0]  = ~y[4:0];txmem[0] = {~`USBF_T_PID_SOF, `USBF_T_PID_SOF};	// PIDtxmem[1] = {	tmp_data[8],tmp_data[9],tmp_data[10],tmp_data[11],		tmp_data[12],tmp_data[13],tmp_data[14],tmp_data[15]};txmem[2] = {	tmp_data[0],tmp_data[1],tmp_data[2],tmp_data[3],		tmp_data[4],tmp_data[5],tmp_data[6],tmp_data[7]};txmem[1] = 	frmn[7:0];//这里展示了另一种装载txmem的算法,一样的txmem[2] = {	tmp_data[0],tmp_data[1],tmp_data[2],tmp_data[3],		tmp_data[4], frmn[10:8] };utmi_send_pack(3);endendtaskfunction [4:0] crc5;//搞清楚为什么送入的crc5是全一,见204行,傻猫还问,不是说了吗,那是初始化input	[4:0]	crc_in;input	[10:0]	din;reg	[4:0]	crc_out;//这个好象根本没用到begincrc5[0] =	din[10] ^ din[9] ^ din[6] ^ din[5] ^ din[3] ^		din[0] ^ crc_in[0] ^ crc_in[3] ^ crc_in[4];crc5[1] =	din[10] ^ din[7] ^ din[6] ^ din[4] ^ din[1] ^		crc_in[0] ^ crc_in[1] ^ crc_in[4];crc5[2] =	din[10] ^ din[9] ^ din[8] ^ din[7] ^ din[6] ^		din[3] ^ din[2] ^ din[0] ^ crc_in[0] ^ crc_in[1] ^		crc_in[2] ^ crc_in[3] ^ crc_in[4];crc5[3] =	din[10] ^ din[9] ^ din[8] ^ din[7] ^ din[4] ^ din[3] ^		din[1] ^ crc_in[1] ^ crc_in[2] ^ crc_in[3] ^ crc_in[4];crc5[4] =	din[10] ^ din[9] ^ din[8] ^ din[5] ^ din[4] ^ din[2] ^		crc_in[2] ^ crc_in[3] ^ crc_in[4];endendfunctiontask send_data;//主机发送数据包input	[3:0]	pid;//给定包标识符input		len;//给定数据包的payload长度input		mode;//这个是什么?在协议中可找不到这么野蛮的东西!!测着玩的,别当真integer		n, len, mode, delay;reg	[15:0]	crc16r;reg	[7:0]	x,y;begintxmem[0] = {~pid, pid};	// PIDcrc16r = 16'hffff;//初始化for(n=0;n<len;n=n+1)   begin	if(mode==1)	y = buffer1[buffer1_last+n];//和主机接收时一样,都用的是buffer1	else		y = n;//想不通它在传什么,0到len-1	x[7] = y[0];	x[6] = y[1];	x[5] = y[2];	x[4] = y[3];	x[3] = y[4];	x[2] = y[5];	x[1] = y[6];	x[0] = y[7];	txmem[n+1] = y;//要发送的数据送到发送接收仓:txmen,感觉象是码头	crc16r = crc16(crc16r, x);//一直在累积计算   endbuffer1_last = buffer1_last + n;//修改buffer1_last指针,使它指向下一片数据y = crc16r[15:8];x[7] = y[0];x[6] = y[1];x[5] = y[2];x[4] = y[3];x[3] = y[4];x[2] = y[5];x[1] = y[6];x[0] = y[7];txmem[n+1] = ~x;//整理成某种规定的格式再发送y = crc16r[7:0];x[7] = y[0];x[6] = y[1];x[5] = y[2];x[4] = y[3];x[3] = y[4];x[2] = y[5];x[1] = y[6];x[0] = y[7];txmem[n+2] = ~x;//注意这里变为n+2,因为没有for语句给的n=n+1了utmi_send_pack(len+3);//加3是因为有pid和crc16endendtaskfunction [15:0] crc16;//一个函数input	[15:0]	crc_in;input	[7:0]	din;reg	[15:0]	crc_out;begincrc_out[0] =	din[7] ^ din[6] ^ din[5] ^ din[4] ^ din[3] ^		din[2] ^ din[1] ^ din[0] ^ crc_in[8] ^ crc_in[9] ^		crc_in[10] ^ crc_in[11] ^ crc_in[12] ^ crc_in[13] ^		crc_in[14] ^ crc_in[15];crc_out[1] =	din[7] ^ din[6] ^ din[5] ^ din[4] ^ din[3] ^ din[2] ^		din[1] ^ crc_in[9] ^ crc_in[10] ^ crc_in[11] ^		crc_in[12] ^ crc_in[13] ^ crc_in[14] ^ crc_in[15];crc_out[2] =	din[1] ^ din[0] ^ crc_in[8] ^ crc_in[9];crc_out[3] =	din[2] ^ din[1] ^ crc_in[9] ^ crc_in[10];crc_out[4] =	din[3] ^ din[2] ^ crc_in[10] ^ crc_in[11];crc_out[5] =	din[4] ^ din[3] ^ crc_in[11] ^ crc_in[12];crc_out[6] =	din[5] ^ din[4] ^ crc_in[12] ^ crc_in[13];crc_out[7] =	din[6] ^ din[5] ^ crc_in[13] ^ crc_in[14];crc_out[8] =	din[7] ^ din[6] ^ crc_in[0] ^ crc_in[14] ^ crc_in[15];crc_out[9] =	din[7] ^ crc_in[1] ^ crc_in[15];crc_out[10] =	crc_in[2];crc_out[11] =	crc_in[3];crc_out[12] =	crc_in[4];crc_out[13] =	crc_in[5];crc_out[14] =	crc_in[6];crc_out[15] =	din[7] ^ din[6] ^ din[5] ^ din[4] ^ din[3] ^ din[2] ^		din[1] ^ din[0] ^ crc_in[7] ^ crc_in[8] ^ crc_in[9] ^		crc_in[10] ^ crc_in[11] ^ crc_in[12] ^ crc_in[13] ^		crc_in[14] ^ crc_in[15];crc16 = crc_out;//必不可少endendfunction/////////////////////////////////////////////////////////////////////// UTMI Low level Tasks//task utmi_send_pack;//这也是指主机发送input	size;integer n,size;begin@(posedge clk);//等到一个时钟上升沿#1;tb_tx_valid = 1'b1;//先让待发送的数据有效for(n=0;n<size;n=n+1)//n从0到size-1,全部发送   begin	tb_txdata = txmem[n];//送上前线	@(posedge clk);//等到下一个时钟上升沿	#2;	while(!tb_tx_ready)	@(posedge clk);//如果phy没有准备好传输,就等到下一个时钟上升沿,一直到发出去为止	#1;   endtb_tx_valid = 1'b0;//发送完毕,通知phy,线上的数据无效@(posedge clk);//等一个时钟上升沿endendtasktask utmi_recv_pack;//这是指主机接收output	size;integer	size;beginsize = 0;while(!tb_rx_active)	@(posedge clk);//如果没有检测到同步头,就等到下一个时钟上升沿来。while(tb_rx_active)   begin	#1;	while(!tb_rx_valid & tb_rx_active)	@(posedge clk);//当检测到同步头但是数据还是无效时,等下一个时钟上升沿来		if(tb_rx_valid & tb_rx_active)	   begin		txmem[size] = tb_rxdata;//搞清楚txmen是什么缓冲区!存传来的数据		size = size + 1;//传送的字节数	   end	@(posedge clk);//无条件等到下一个时钟上升沿来   endendendtask

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -