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/] [RxModule.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, reduce the resource consumed
 
//version 0.5, defined many parameter to configure the IP core, making it easier to use.
//vertion 0.4, add the function for TxModule to get start in a configurable ff_clk time after 
//				RxModule receiving the first frame. To modify the delay time just to 
//				change the value of the macro-variable delay_cnt_config.
//version 0.3, changed the changes made by version 0.2 back
//version 0.2, set empty when ff_data_buf_index's less significant bits is 3'b111 or 3'b000
 
`include "common.v"
 
`define IDXlen			3		//2^IDXlen should be the number of cyclic queue
`define queue_len		(1<<3)	//define the length of the cyclic queue
 
`define rx_crc_offset	(`data_offset+(`uframelen*`num_uframe/4))	//index of first bit of crc
`define rx_total_len	(`rx_crc_offset + (4<<1))
`define rxdata_len		(`uframelen*`num_uframe/4)
 
`define delay_cnt_config	8	//the initiation value for the delay_cnt
 
module RxModule(phy_rxd, phy_rxen, phy_rxclk, phy_rxer,
				ff_clk, ff_data, ff_en, 
 
				`ifdef frameIDfromRx
					frameid, 
				`endif
 
				start,
				test1, test2, test3, test4
				);
	input phy_rxen, phy_rxclk, phy_rxer;	//MII interface
	input [3:0] phy_rxd;
 
	input ff_clk;			//270.8333KHz
	output ff_data, ff_en;
 
	`ifdef frameIDfromRx
		output[`frameidlen-1:0] frameid;
		reg[`frameidlen-1:0] frameid;
	`endif
 
	output start;			//to tell TxModule that buf in RxModule needs data
	output test1, test2, test3, test4;
	reg test1, test2;
 
	parameter delay_cnt_len =   (`delay_cnt_config <    2) ? 1 : (`delay_cnt_config <    4) ? 2 :
								(`delay_cnt_config <    8) ? 3 : (`delay_cnt_config <   16) ? 4 :
								(`delay_cnt_config <   32) ? 5 : (`delay_cnt_config <   64) ? 6 :
								(`delay_cnt_config <  128) ? 7 : 8;
	parameter nibble_idx_len = 	(`rx_total_len<=   2)?  1 : (`rx_total_len<=   4)?  2 :
								(`rx_total_len<=   8)?  3 : (`rx_total_len<=  16)?  4 :
								(`rx_total_len<=  32)?  5 : (`rx_total_len<=  64)?  6 :
								(`rx_total_len<= 128)?  7 : (`rx_total_len<= 256)?  8 :
								(`rx_total_len<= 512)?  9 : (`rx_total_len<=1024)? 10 : 
								(`rx_total_len<=2048)? 11 : 12;
	parameter ff_idx_len = 	(`rxdata_len<=   2)? 1 : (`rxdata_len<=   4)? 2 :
							(`rxdata_len<=   8)? 3 : (`rxdata_len<=  16)? 4 :
							(`rxdata_len<=  32)? 5 : (`rxdata_len<=  64)? 6 :
							(`rxdata_len<= 128)? 7 : (`rxdata_len<= 256)? 8 :
							(`rxdata_len<= 512)? 9 : (`rxdata_len<=1024)?10 :
							(`rxdata_len<=2048)?11 : 12;							
	parameter frameid_idx_len = ((`frameidlen>>2)<=  2)? 1 : ((`frameidlen>>2)<=  4)? 2 :
								((`frameidlen>>2)<=  8)? 3 : ((`frameidlen>>2)<= 16)? 4 :
								((`frameidlen>>2)<= 32)? 5 : ((`frameidlen>>2)<= 64)? 6 : 
								((`frameidlen>>2)<= 64)? 7 : 8;
	parameter ff_cnt_len  =	(`uframelen <    2) ? 1 : (`uframelen <    4) ? 2 :
							(`uframelen <    8) ? 3 : (`uframelen <   16) ? 4 :
							(`uframelen <   32) ? 5 : (`uframelen <   64) ? 6 :
							(`uframelen <  128) ? 7 : (`uframelen <  256) ? 8 :
							(`uframelen <  512) ? 9 : (`uframelen < 1024) ? 10:
							(`uframelen < 2048) ? 11: (`uframelen < 4096) ? 12:
							(`uframelen < 8192) ? 13: 14;
 
	reg ff_data;
	reg ff_en;
 
	reg[ff_cnt_len-1:0] ff_cnt;
	reg[2:0] ff_d;
 
	reg start=1'b0;
	reg start_intra=1'b0;
	reg[delay_cnt_len-1:0] delay_cnt;
 
	reg[3:0] gap_cnt;
	reg[1:0] gap_len_ctl;
	reg[1:0] cycle;
 
	reg[3:0] rxdata_buf [0:(`rxdata_len*`queue_len+1)];	//more ram for special usage
	wire[ff_idx_len+`IDXlen-1:0] rxdata_buf_writer_address;
	reg[ff_idx_len+`IDXlen-1:0] rxdata_buf_reader_address;
 
	reg[`frameidlen-1:0] frameid_buf[0:(`queue_len-1)];
 
	reg[nibble_idx_len-1:0] nibble_idx;
	reg[ff_idx_len-1:0] ff_idx;
 
	reg[`IDXlen-1:0] rxIDX, ffIDX;
 
	reg bad_da;
	reg queue_empty;
 
	reg[2:0] rxState = 0;
	parameter s_preamble = 0, s_address = 1, s_typelen = 2, 
				s_frameid = 3, s_data = 4, s_crc = 5;
	reg[1:0] ff_state = 0;
	parameter ffs_idle = 0, ffs_transfer = 1, ffs_gap = 2;
 
	wire[47:0] mac_add;
	wire[3:0] da[0:11];
	assign mac_add = `MAC_ADD;
	assign da[ 0] = mac_add[ 3: 0];
	assign da[ 1] = mac_add[ 7: 4];
	assign da[ 2] = mac_add[11: 8];
	assign da[ 3] = mac_add[15:12];
	assign da[ 4] = mac_add[19:16];
	assign da[ 5] = mac_add[23:20];
	assign da[ 6] = mac_add[27:24];
	assign da[ 7] = mac_add[31:28];
	assign da[ 8] = mac_add[35:32];
	assign da[ 9] = mac_add[39:36];
	assign da[10] = mac_add[43:40];
	assign da[11] = mac_add[47:44];
 
	assign test4 = start_intra;
	assign test3 = start;
 
	always@(posedge phy_rxclk)begin			//control the increasing of nibble_idx;
		if(phy_rxen & ~phy_rxer)			//data is valid and no error
			nibble_idx <= nibble_idx + 1;
		else
			nibble_idx <= 0;
	end
 
	always@(posedge phy_rxclk)begin
		if(phy_rxen & ~phy_rxer)
			case (rxState)
				s_preamble:
					if(nibble_idx == `da_offset-1)		rxState <= s_address;
					else 								rxState <= s_preamble;
 
				s_address: 
					if(nibble_idx == `typelen_offset-1)	rxState <= s_typelen;
					else								rxState <= s_address;
 
				s_typelen:
					if(nibble_idx == `frameid_offset-1)	rxState <= s_frameid;
					else								rxState <= s_typelen;
 
				s_frameid:
					if(nibble_idx == `data_offset-1)	rxState <= s_data;
					else								rxState <= s_frameid;
 
				s_data:
					if(nibble_idx == `rx_crc_offset-1)		rxState <= s_crc;
					else								rxState <= s_data;
 
				s_crc:
					if(nibble_idx == `rx_total_len-1)		rxState <= s_preamble;
					else								rxState <= s_crc;
 
				default: 								rxState <= rxState;
			endcase
		else
			rxState <= s_preamble;
	end
 
	assign rxdata_buf_writer_address = rxIDX*`rxdata_len + nibble_idx - `data_offset;
 
	always@(posedge phy_rxclk)begin			//receive data from Ethernet including the preamble, SFD and CRC
		if(phy_rxen & ~phy_rxer) begin		//data is valid and no error
			case (rxState)
				s_preamble: test1 <= ~test1;
				s_address:
					if((phy_rxd!=da[nibble_idx-`da_offset])&(nibble_idx < `sa_offset))
						bad_da <= 1;
 
				s_frameid: begin
					if(nibble_idx==`frameid_offset) begin 
						rxIDX <= phy_rxd[2:0];
						frameid_buf[phy_rxd[2:0]][(`frameidlen-1):(`frameidlen-4)]  <= phy_rxd;
					end else
						frameid_buf[rxIDX] <= {phy_rxd, frameid_buf[rxIDX][(`frameidlen-1):4]};
				end
 
				s_data: begin
					//test2 <= ~test2;
					rxdata_buf[rxdata_buf_writer_address] <= phy_rxd;
				end
			endcase
		end	else if ((nibble_idx == `rx_total_len ) & (!bad_da)) begin
		//one frame has been transfered over, the destinate address is right and then been put into the buffer
			start_intra <= 1;
		end	else
			bad_da <= 0;
	end
 
	always@(negedge ff_clk) begin
		case(ff_state)
			ffs_idle: begin			//wait the first frame to come
				gap_len_ctl <= 0;
				if(start_intra)	ff_state <= ffs_transfer;
				else ff_state <= ffs_idle;
			end
 
			ffs_transfer: begin
				if(ff_cnt == `uframelen-1)begin	//every `uframelen bit need a gap
					ff_state <= ffs_gap;
					gap_len_ctl <= gap_len_ctl + 1;
				end	
				else ff_state <= ffs_transfer;
			end
			ffs_gap: begin
				if(((gap_len_ctl == 0)&(gap_cnt == 8)) | ((gap_len_ctl != 0)&(gap_cnt == 7)))
					ff_state <=ffs_transfer;
				else ff_state <= ffs_gap;
			end
		endcase
	end
 
	always@(negedge ff_clk) begin				//flow the data out of the buffer
		case(ff_state)
			ffs_idle: begin
				ff_cnt <= 0;
				delay_cnt <= 0;
				cycle <= 0;
				ff_en <= 0;
				ff_idx <= 0;
				ffIDX <= rxIDX + 1;
				start <= 0;
				rxdata_buf_reader_address <= ffIDX*`rxdata_len+ff_idx;
			end
 
			ffs_transfer: begin
				`ifdef frameIDfromRx
					frameid <= frameid_buf[ffIDX];
				`endif
				if(delay_cnt == `delay_cnt_config) start <= 1;
				delay_cnt <= delay_cnt + 1;
				gap_cnt <= 0;
				ff_cnt <= ff_cnt + 1;
				cycle <= cycle + 1;
				ff_en <= 1;
 
				if(cycle==0) begin
					{ff_d[2:0],ff_data} <= rxdata_buf[rxdata_buf_reader_address];
					if(ff_idx == `rxdata_len-1)begin
						if(ffIDX!=rxIDX) begin
							queue_empty <= 0;
							if(queue_empty) begin
								ffIDX <= rxIDX + ((`delay_cnt_config==0)? 1:2) ;
								rxdata_buf_reader_address <= (rxIDX + ((`delay_cnt_config==0)? 1:2))*`rxdata_len;
							end
							else begin
								ffIDX <= ffIDX + 1;
								rxdata_buf_reader_address <= (ffIDX+1)*`rxdata_len;
							end
						end else begin
							rxdata_buf_reader_address <= ffIDX*`rxdata_len;
							queue_empty <= 1;
						end
						ff_idx <= 0;
					end
					else begin
						ff_idx <= ff_idx + 1;	
						rxdata_buf_reader_address <= ffIDX*`rxdata_len+ff_idx+1;
					end
				end else
					{ff_d[1:0],ff_data} <= ff_d;
			end
 
			ffs_gap: begin		//the 8.25 bit gap is implement by (3*8+9)/4
				ff_en <= 0;
				ff_data <= 0;
				ff_cnt <= 0;
				gap_cnt <= gap_cnt + 1;
			end
		endcase
	end
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.