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

📄 usiepkt.v

📁 实现USB接口功能的VHDL和verilog完整源代码
💻 V
字号:
/******************************************
	Filename: 	siepkt.v 1.22
******************************************/

/*
This module creates and encodes outgoing data packets.
It takes requests from the device inteface to "senddata,
sendnak, sendack, sendstall" and generates sync,
pid, data bytes, and eop.  The bit serial data are sent to
the nrzo (bit stuffer and nrzi encoder) and the data bytes
come from the device interface.  The packet encoder sends
an "ack" after each packet is sent (acksent, etc.).
*/

module Usiepkt
	(
	// inputs from bus/dpll/nrzo/crc
                testmode,
                testreset,
		usbclock,
        syncreset,
		usbreset,
		nextxmitdata,
		oktoxmit,
		xmitcrcout,

	// inputs from device/function
		xmitlastbyte,
		xmitdatatogglebit,
		xmitdatabyte,
		senddata,
		sendnak,
		sendack,
		sendstall,

	// outputs to bus
		xmitactive,
		xmitdatabit,
		xmitidle,
		xmitsendse0,
		xmitcrc16data,
		xmitcrc16send,
		xmitdatavalid,

	// outputs to device/function
		nextxmitbyte,
		datasent,
		stallsent,
		acksent,
		naksent
	);

`include "Usiepktdef.v"
`include "Uusbdef.v"

// inputs from bus/dpll
  input         testmode;
  input         testreset;
  input	usbclock;
  input	syncreset;
  input	usbreset;	// synopsys sync_set_reset "usbreset"

  input	      nextxmitdata;
  input	      oktoxmit;
  input	      xmitcrcout;

// inputs from device/function
  input	      xmitlastbyte;
  input	      xmitdatatogglebit;
  input [7:0]   xmitdatabyte;
  input	      senddata;
  input	      sendnak;
  input	      sendack;
  input	      sendstall;

// outputs to bus
  output	      xmitactive;
  output	      xmitdatabit;
  output	      xmitidle;
  output	      xmitsendse0;
  output	      xmitcrc16data;
  output	      xmitcrc16send;
  output	      xmitdatavalid;

// outputs to device/function
  output	      nextxmitbyte;
  output	      datasent;
  output	      stallsent;
  output	      acksent;
  output	      naksent;

  reg [7:0]     outgoingdatabyte;
  reg	      xmitdatabit;
  reg	      xmitidle;
  reg	      xmitsendse0;
  reg	      xmitcrc16data;
  reg	      xmitcrc16send;
  reg	      xmitdatavalid;
  reg	      nextxmitbyte;
  reg	      datasent;
  reg	      stallsent;
  reg	      acksent;
  reg	      naksent;

  reg [3:0]     bitcount;
  reg	      resetbitcount;

reg	[9:0]	prevpktst, pktst, nextpktst;

reg	[3:0]	currentpid;

// used to register this, but don't need to
// wire	thisbyteislast = xmitlastbyte;

// special aysnc flop logic for usbclockout 
wire   rstn;
assign rstn = (testmode)? testreset : ~syncreset;
dffr asyncflop (
	.q (xmitactive),
	.d (nextpktst != PKTIDLE),
	.clk (usbclock),
	.rstn (rstn)
	);

always @(posedge usbclock)
begin
	datasent <= ((pktst == PKTCRC16) && bitcount == 4'h0);
	stallsent <= ((pktst == PKTSTALL) && bitcount == 4'h0);
	acksent <= ((pktst == PKTACK) && bitcount == 4'h0);
	naksent <= ((pktst == PKTNAK) && bitcount == 4'h0);

	xmitsendse0 <=  ((nextpktst == PKTEOP) && (bitcount != 4'h1));

	xmitidle <= ((nextpktst == PKTIDLE) || 
		((nextpktst == PKTEOP) && bitcount == 4'h1));

	xmitdatavalid <= nextxmitdata;	// gets qualified in crc with crc16data

	if (usbreset)
		xmitcrc16data <= 1'b0;
	else if (nextpktst == PKTDATA)
		xmitcrc16data <= 1'b1;
	else
		xmitcrc16data <= 1'b0;

	if (usbreset)
		xmitcrc16send <= 1'b0;
	else if (nextpktst == PKTCRC16)
		xmitcrc16send <= 1'b1;
	else
		xmitcrc16send <= 1'b0;

	if (usbreset)
		nextxmitbyte <= 1'b0;
		// ask for next byte if sending data and count is 0 and count is advancing (no double pumps)
	else if ((pktst == PKTDATA) && (bitcount == 4'h0) && nextxmitdata)
		nextxmitbyte <= 1'b1;
	else
		nextxmitbyte <= 1'b0;

	if (resetbitcount)
		bitcount <= 1'b0;
	else if (nextxmitdata)
		bitcount <= bitcount + 1'b1;


	case(nextpktst)	// synopsys full_case parallel_case
		PKTDPID  : currentpid <= (xmitdatatogglebit) ? PIDDATA1 : PIDDATA0;
		PKTACK	  : currentpid <= PIDACK;
		PKTSTALL : currentpid <= PIDSTALL;
		PKTNAK	  : currentpid <= PIDNAK;
	//	default   : currentpid <= currentpid;
	endcase

	if (nextpktst == PKTDATA && bitcount == 4'h7)	// works coming out of PID
		outgoingdatabyte <= xmitdatabyte;		// and within data!
end
 
// state machine for decoding data from the usb
always @(posedge usbclock)
begin
	if (usbreset)
		pktst <= PKTIDLE;
	else
		pktst <= nextpktst;
	prevpktst <= pktst;
end

//synopsys sync_set_reset_local infer_sync "usbreset"
always @(pktst or usbreset or sendack or sendnak or senddata or 
		xmitdatatogglebit or bitcount or 
                oktoxmit or xmitlastbyte or
		outgoingdatabyte or sendstall or currentpid or xmitcrcout or nextxmitdata)
begin : infer_sync
	if (usbreset)
	begin
		nextpktst = PKTIDLE;
		resetbitcount = 1'b1;
		xmitdatabit = 1'b1;
	end
	else
		case (pktst)	// synopsys parallel_case full_case
			PKTIDLE:
			begin
				xmitdatabit = 1'b1;
				resetbitcount = 1'b1;
				if ((sendack || sendnak || sendstall || senddata) && oktoxmit)	// need to do something!
				begin
					nextpktst = PKTSYNC;
				end
				else 
				begin
					nextpktst = PKTIDLE;
				end
			end
			PKTSYNC:
			begin
				if (bitcount != 4'h7)
				begin
					resetbitcount = 1'b0;
					xmitdatabit = 1'b0;
					nextpktst = PKTSYNC;
				end
				else if (sendstall)	// last bit of sync, prioritize for which packet to send
				begin
					resetbitcount = 1'b1;
					xmitdatabit = 1'b1;
					nextpktst = PKTSTALL;
				end
				else if (sendnak)	// last bit of sync, prioritize for which packet to send
				begin
					resetbitcount = 1'b1;
					xmitdatabit = 1'b1;
					nextpktst = PKTNAK;
				end
				else if (sendack)	// last bit of sync, prioritize for which packet to send
				begin
					resetbitcount = 1'b1;
					xmitdatabit = 1'b1;
					nextpktst = PKTACK;
				end
				else
				begin
					resetbitcount = 1'b1;
					xmitdatabit = 1'b1;
					nextpktst = PKTDPID;
				end
			end
			PKTDPID:
			begin
				if (bitcount[2] == 1'b0)	// less than 4
					xmitdatabit = currentpid[bitcount[1:0]];
				else
					xmitdatabit = ~currentpid[bitcount[1:0]];
				if ((bitcount == 4'h7) && nextxmitdata)
				begin
					resetbitcount = 1'b1;
					if (xmitlastbyte)	// support zero length data!
						nextpktst = PKTCRC16;
					else
						nextpktst = PKTDATA;
				end
				else
				begin
					resetbitcount = 1'b0;
					nextpktst = PKTDPID;
				end
			end
			PKTACK, PKTNAK, PKTSTALL:
			begin
				if (bitcount[2] == 1'b0)	// less than 4
					xmitdatabit = currentpid[bitcount[1:0]];
				else
					xmitdatabit = ~currentpid[bitcount[1:0]];
				if ((bitcount == 4'h7) && nextxmitdata)
				begin
					resetbitcount = 1'b1;
					nextpktst = PKTEOP;
				end
				else
				begin
					resetbitcount = 1'b0;
					nextpktst = pktst;
				end
			end
			PKTEOP:
			begin
				xmitdatabit = 1'b1;		// send 1, but really will be se0
				if (bitcount == 4'h2)		// 2 ticks of se0, then one idle
				begin
					resetbitcount = 1'b1;
					nextpktst = PKTIDLE;
				end
				else
				begin
					resetbitcount = 1'b0;
					nextpktst = PKTEOP;
				end
			end
			PKTDATA:
			begin
				xmitdatabit = outgoingdatabyte[bitcount];
				if ((bitcount == 4'h7) && nextxmitdata)	// last bit of byte
					resetbitcount = 1'b1;
				else
					resetbitcount = 1'b0;
				if (xmitlastbyte && (bitcount == 4'h7) && nextxmitdata)	// last bit of byte
				begin
					nextpktst = PKTCRC16;
				end
				else
				begin
					nextpktst = PKTDATA;
				end
			end
			PKTCRC16:
			begin
				xmitdatabit = xmitcrcout;		// crc (combinatorial) from generator
				if ((bitcount != 4'hf) || ~nextxmitdata)
				begin
					resetbitcount = 1'b0;
					nextpktst = PKTCRC16;
				end
				else
				begin
					resetbitcount = 1'b1;
					nextpktst = PKTEOP;
				end
			end
	endcase
end

// make the ascii version of the packet state
// synopsys translate_off
reg [8*10:1]	pktstate;
always @(pktst)
case (pktst)
	PKTIDLE : pktstate = "PKTIDLE";
	PKTSYNC : pktstate = "PKTSYNC";
	PKTDPID : pktstate = "PKTDPID";
	PKTDATA : pktstate = "PKTDATA";
	PKTCRC16 : pktstate = "PKTCRC16";
	PKTNAK : pktstate = "PKTNAK";
	PKTACK : pktstate = "PKTACK";
	PKTSTALL : pktstate = "PKTSTALL";
	PKTERROR : pktstate = "PKTERROR";
	PKTEOP : pktstate = "PKTEOP";
endcase
// synopsys translate_on

endmodule

⌨️ 快捷键说明

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