zynq-sandbox

old FPGA projects for ZYNQ
git clone http://frotz.net/git/zynq-sandbox.git
Log | Files | Refs | README

eth_rmii_rx.sv (3515B)


      1 // Copyright 2014 Brian Swetland <swetland@frotz.net>
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //     http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 `timescale 1ns / 1ps
     16 
     17 // CRS_DV -- multiplexed, CR on first di-bit, DV on second di-bit of each nibble
     18 //
     19 //           preamble | packet 
     20 // crs_dv ... 1 1 1 1 1 CR DV CR DV CR DV CR ...
     21 // rx0    ... 0 0 0 0 1 b0 b2 b4 b6 b0 b2 b4 ...
     22 // rx1    ... 1 1 1 1 1 b1 b3 b5 b7 b1 b3 b5 ...
     23 //
     24 // CR can go low when carrier lost, while DV remains asserted through end of frame.
     25 
     26 // valid is asserted on each clock where data contains a byte of the frame
     27 // eop is asserted for one clock after the last byte of the frame has arrived
     28 // and before the next frame's first byte arrives
     29 
     30 module eth_rmii_rx(
     31 	input clk50,
     32 
     33 	input [1:0]rx,
     34 	input crs_dv,
     35 
     36 	output reg [7:0]data = 0,
     37 	output reg valid = 0,
     38 	output reg eop = 0,
     39 
     40 	// transmit outputs which can drive
     41 	// an eth_rmii_tx to create a repeater
     42 	output reg [1:0]out_tx = 0,
     43 	output reg out_txen = 0,
     44 
     45 	// start of packet strobe (for timestamping, etc)
     46 	output reg sop = 0
     47 	);
     48 
     49 typedef enum {
     50 	IDLE, PRE1, PRE2, PRE3,
     51         DAT0, DAT1, DAT2, DAT3,
     52 	ERR0, ERR1, EOP
     53 } state_t;
     54 
     55 state_t state = IDLE;
     56 state_t next_state;
     57 
     58 reg [7:0]next_data;
     59 reg next_valid;
     60 reg next_eop;
     61 
     62 wire [7:0]rxshift = { rx, data[7:2] };
     63 
     64 reg [1:0]delay_tx = 0;
     65 reg delay_txen = 0;
     66 reg next_txen;
     67 reg next_sop;
     68 
     69 always_comb begin
     70 	next_state = state;
     71 	next_data = data;
     72 	next_valid = 0;
     73 	next_eop = 0;
     74 	next_sop = 0;
     75 	next_txen = delay_txen;
     76 
     77 	case (state)
     78 	IDLE: if ((rx == 2'b01) && (crs_dv == 1)) begin
     79 		// crs_dv may go high asynchronously
     80 		// only move to preamble on crs_dv AND a preamble di-bit
     81 		next_state = PRE1;
     82 		next_txen = 1;
     83 		next_sop = 1;
     84 	end
     85 	PRE1: if (rx == 2'b01) begin
     86 		next_state = PRE2;
     87 	end else begin
     88 		next_state = ERR0;
     89 	end
     90 	PRE2: if (rx == 2'b01) begin
     91 		next_state = PRE3;
     92 	end else begin
     93 		next_state = ERR0;
     94 	end
     95 	PRE3: if (rx == 2'b11) begin
     96 		next_state = DAT0;
     97 	end else if (rx == 2'b01) begin
     98 		next_state = PRE3;
     99 	end else begin
    100 		next_state = ERR0;
    101 	end
    102 	DAT0: begin
    103 		next_data = rxshift;
    104 		next_state = DAT1;
    105 	end
    106 	DAT1: begin
    107 		next_data = rxshift;
    108 		if (crs_dv) begin
    109 			next_state = DAT2;
    110 		end else begin
    111 			next_txen = 0;
    112 			next_state = EOP;
    113 		end
    114 	end
    115 	DAT2: begin
    116 		next_data = rxshift;
    117 		next_state = DAT3;
    118 	end
    119 	DAT3: begin
    120 		next_data = rxshift;
    121 		if (crs_dv) begin
    122 			next_state = DAT0;
    123 			next_valid = 1;
    124 		end else begin
    125 			next_txen = 0;
    126 			next_state = EOP;
    127 		end
    128 	end
    129 	EOP: begin
    130 		next_state = IDLE;
    131 		next_data = 0;
    132 		next_eop = 1;
    133 	end
    134 	ERR0: begin
    135 		next_txen = 0;
    136 		if (crs_dv == 0) begin
    137 			next_state = ERR1;
    138 		end
    139 	end
    140 	ERR1: begin
    141 		if (crs_dv == 0) begin
    142 			next_state = IDLE;
    143 		end else begin
    144 			next_state = ERR0;
    145 		end
    146 	end
    147 	endcase
    148 end
    149 
    150 always_ff @(posedge clk50) begin
    151 	state <= next_state;
    152 	valid <= next_valid;
    153 	data <= next_data;
    154 	eop <= next_eop;
    155 	sop <= next_sop;
    156 	delay_txen <= next_txen;
    157 	delay_tx <= rx;
    158 	out_txen <= next_txen ? delay_txen : 0;
    159 	out_tx <= next_txen ? delay_tx : 0;
    160 end
    161 
    162 endmodule