OpenCores
URL https://opencores.org/ocsvn/10_100m_ethernet-fifo_convertor/10_100m_ethernet-fifo_convertor/trunk

Subversion Repositories 10_100m_ethernet-fifo_convertor

[/] [10_100m_ethernet-fifo_convertor/] [verilog/] [TxModule.v] - Rev 10

Compare with Previous | Blame | View Log

//author :Renliang Gu
//Email: gurenliang@gmail.com
//note: if there are some errors, please feel free to contact me. Thank you very much!
 
 
//Next step, add ff_data control to show the IP is busy
 
//version 0.3, declared a new variable data_av, and use it to start sending frame.
//version 0.3, delete the usage of pre_buf, and rename the pre to preaddlt
//version 0.3, add the option of frameID mode, by include common.v and judge the macro-varible frameIDfromRx
//This module is used to receive data from the demodulate module and send the data to the Ethernet PHY chip
 
`include "common.v"
 
`define tx_crc_offset	(`data_offset+((`uframelen+8)*`num_uframe/4)+2)	//index of first bit of crc
`define tx_total_len	(`tx_crc_offset + (4<<1))
 
`define txdata_len		   (((`uframelen+8)*`num_uframe/4)+2)
`define less_than_a_nibble 1	//0.25*8=2
`define last_cycle_val	2		//0.25*8=2
 
`define preaddlt_len	(`data_offset<<2)
 
module TxModule(reset, phy_txd, phy_txen, phy_txclk, phy_txer,
				ff_clk, ff_en, ff_data,
 
				`ifdef frameIDfromRx
					frameid, 
				`endif
 
				start,
				test1, test2, test3, test4);
	parameter nibble_idx_len = 	(`tx_total_len<=  2)? 1 : (`tx_total_len<=  4)? 2 :
								(`tx_total_len<=  8)? 3 : (`tx_total_len<= 16)? 4 :
								(`tx_total_len<= 32)? 5 : (`tx_total_len<= 64)? 6 :
								(`tx_total_len<=128)? 7 : (`tx_total_len<=256)? 8 :
								(`tx_total_len<=512)? 9 : (`tx_total_len<=1024)? 10 :
								(`tx_total_len<=2048)? 11 : 12;
	parameter ff_idx_len = 	(`txdata_len<=  2)? 1 : (`txdata_len<=  4)? 2 :
							(`txdata_len<=  8)? 3 : (`txdata_len<= 16)? 4 :
							(`txdata_len<= 32)? 5 : (`txdata_len<= 64)? 6 :
							(`txdata_len<=128)? 7 : (`txdata_len<=256)? 8 :
							(`txdata_len<=512)? 9 : (`txdata_len<=1024)? 10 : 11;
 
	input phy_txclk, reset;
	input ff_clk, ff_en, ff_data;	//ff_clk should be 207.83333KHz
 
	`ifdef frameIDfromRx
		input[`frameidlen-1:0] frameid;			//get the frameid information from RxModule
		reg[`frameidlen-1:0] frameid_buf[0:1];
	`endif
	`ifdef frameIDcount
		reg[`frameidlen-1:0] frameid=0;
	`endif
	reg[`frameidlen-1:0] frameid_reg;
 
	input  start;					//decide whether should give out the "need-data" ethernet package
	output [3:0] phy_txd;			//MII
	output phy_txen, phy_txer;
 
	output test1, test2, test3, test4;
	reg test1;//, test2, test3, test4;
 
	reg[3:0] phy_txd;
	reg phy_txen;
 
	reg[`preaddlt_len-1:0] preaddlt;
 
	reg[3:0] txdata_buf[0:`txdata_len*2-1];	//two buffer helps to step over different frame seamlessly
	reg[ff_idx_len:0] txdata_buf_reader_address;
 
	reg[nibble_idx_len-1:0] nibble_idx;
	wire data_av;
 
	reg Enable_Crc, Initialize_Crc;		//declare the variables for the CRC module
	wire [3:0] Data_Crc;
	wire CrcError;
	wire [31:0] Crc;
 
	wire txIDX;
	reg[1:0] cycle;
	reg ffIDX, ffIDX1, ffIDX2;
	reg[ff_idx_len-1:0] ff_idx;
	reg[2:0] ff_d;
 
	// Declare state register
	reg	[2:0]txState;
	parameter s_idle = 3'h0, s_preamble = 3'h1, s_address = 3'h2, s_data = 3'h3, s_crc =3'h4;
 
	assign test2 = txState[2];
	assign test3 = txState[1];
	assign test4 = txState[0];
 
	always @ (posedge ff_clk) begin		//receive data from demodulate module every bit one by one
		if(ff_en & start) begin
			`ifdef frameIDfromRx
				if((ff_idx==0)&&(cycle==0)) frameid_buf[ffIDX] <= frameid;
			`endif
 
			cycle <= cycle + 1;			 
			if((cycle==3)||
				((cycle == `last_cycle_val-1)&&(ff_idx==(`txdata_len-1-`less_than_a_nibble)))) begin
 
				txdata_buf[ffIDX*`txdata_len+ff_idx] <= ({ff_data,ff_d}>>(3-cycle));
				if (ff_idx == (`txdata_len-1-`less_than_a_nibble)) begin
					ffIDX <= ~ffIDX;
					ff_idx <= 0;
					cycle <= 0;
					//every time a frame being sent, frameID increases one
					`ifdef frameIDcount
						frameid <= frameid + 1;
					`endif
				end
				else begin
					ff_idx <= ff_idx + 1;
				end
 
			end else begin
				ff_d <= {ff_data, ff_d[2:1]};
			end
		end
		else begin
			ff_idx <= 0;
			cycle <= 0;
		end
	end
 
	assign phy_txer = 1'b0;
	assign data_av = ffIDX1 ^ ffIDX2;
	assign txIDX = ~ffIDX;
 
	always @ (negedge phy_txclk) begin 	//state machine run to send out the MAC frame
		ffIDX2 <= ffIDX1;
		ffIDX1 <= ffIDX;
	end
 
	// Determine the next state
	always @ (negedge phy_txclk) begin	//state machine run to send out the MAC frame
		if (reset)
			txState <= s_idle;
		else begin
			case (txState)
				s_idle: begin		//wait to be trigged
					test1 <= ~test1;
					if(data_av) begin	//once be trigged, prepare the data to send
						txState <= s_preamble;
					end
					else txState <= s_idle;
				end
 
				s_preamble:			//send the preambles
					if(nibble_idx == `da_offset-1)
						txState <= s_address;
					else
						txState <= s_preamble;
 
				s_address: begin		//send the destination address, source address and type
					if(nibble_idx== `data_offset-1)
						txState <= s_data;
					else
						txState <= s_address;
				end
				s_data:					//send data to PHY, every time four bits, lower bits go first
					//test2 <= ~test2;
					if (nibble_idx == `tx_crc_offset-1)
						txState <= s_crc;
					else txState <= s_data;
 
				s_crc:
					if (nibble_idx == `tx_total_len-1)
						txState <= s_idle;
					else txState <= s_crc;
 
				default: 
					txState <= s_idle;
			endcase
		end
	end
 
	always @ (negedge phy_txclk) begin 	//state machine run to send out the MAC frame
		if (reset)
			nibble_idx <= 0;
		else if(txState==s_idle)
			nibble_idx <= 0;
		else
			nibble_idx <= nibble_idx + 1;
	end
 
	always @ (negedge phy_txclk) begin 	//state machine run to send out the MAC frame
		if (reset)
			phy_txd <= 4'h0;
		else 
			case (txState)
				s_idle: begin
					//already stored MAC preamble, dest address and source address from right to left. 
					//decide whether should ask PC for new frame
					/*if(empty) preaddlt <= {16'h0008, `MAC_ADD, `PC_MAC_ADD, `Preamble};	
					else*/
					`ifdef frameIDfromRx
						preaddlt <= {frameid_buf[txIDX], 16'h0000, `MAC_ADD, `PC_MAC_ADD, `Preamble};
					`endif
					`ifdef frameIDcount
						preaddlt <= {frameid, 16'h0000, `MAC_ADD, `PC_MAC_ADD, `Preamble};
					`endif
				end
				s_preamble:
					{preaddlt[`preaddlt_len-5:0], phy_txd} <= preaddlt;
				s_address: begin
					{preaddlt[`preaddlt_len-5:0], phy_txd} <= preaddlt;
					txdata_buf_reader_address <= (txIDX*(`txdata_len));
				end
				s_data: begin
					txdata_buf_reader_address <= (txIDX*(`txdata_len))+nibble_idx-`data_offset+1;
					phy_txd <= txdata_buf[txdata_buf_reader_address];
				end
				s_crc: begin
					phy_txd[3] <= ~Crc[28];	//Special, the usage of the CRC_Module
					phy_txd[2] <= ~Crc[29];
					phy_txd[1] <= ~Crc[30];
					phy_txd[0] <= ~Crc[31];
				end
				default:
					phy_txd <= 4'h0;
			endcase
	end
 
	always @ (negedge phy_txclk) begin 	//state machine run to send out the MAC frame
		if (reset)
			phy_txen <= 1'b0;
		else if((txState==s_preamble)||(txState==s_address)||(txState==s_data)||(txState==s_crc))
			phy_txen <= 1'b1;
		else
			phy_txen <= 1'b0;
	end
 
	always @ (negedge phy_txclk) begin 	//state machine run to send out the MAC frame
		if (reset)
			Initialize_Crc <= 1'b0;
		else if(txState==s_preamble)
			Initialize_Crc <= 1'b1;		//prepare the CRC_Module for the following addresses
		else
			Initialize_Crc <= 1'b0;
	end
 
	always @ (negedge phy_txclk) begin 	//state machine run to send out the MAC frame
		if (reset)
			Enable_Crc <= 1'b0;
		else if((txState==s_address)||(txState==s_data))
			Enable_Crc <= 1'b1;		//enable the CRC_Module
		else
			Enable_Crc <= 1'b0;
	end
 
	assign Data_Crc[0] = phy_txd[3];	//input prepare for CRC_Module
	assign Data_Crc[1] = phy_txd[2];
	assign Data_Crc[2] = phy_txd[1];
	assign Data_Crc[3] = phy_txd[0];
 
	// Connecting module Crc
	CRC_Module txcrc (.Clk(phy_txclk), .Reset(reset), .Data(Data_Crc), .Enable(Enable_Crc), .Initialize(Initialize_Crc), 
               .Crc(Crc), .CrcError(CrcError));
 
endmodule

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.