zynq-sandbox

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

eth_rmii_tx.sv (2935B)


      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 // 1. Asserting packet starts tx cycle.
     18 // 2. Deasserting packet will cause tx cycle to complete after current byte
     19 //    has completed transmission.
     20 // 3. busy is asserted while a packet is in flight (and will remain asserted after
     21 //    packet deasserts, until after inter-packet-gap (IPG) has completed).
     22 // 4. advance is asserted when txdata is consumed
     23 
     24 module eth_rmii_tx(
     25 	input clk50,
     26 
     27 	output reg [1:0]tx = 0,
     28 	output reg txen = 0,
     29 
     30 	input [7:0]data,
     31 	input packet,
     32 	output reg busy = 0,
     33 	output reg advance = 0
     34 	);
     35 
     36 typedef enum {
     37 	IDLE, PRE, DAT0, DAT1, DAT2, DAT3, EOP
     38 } state_t;
     39 
     40 state_t state = IDLE;
     41 state_t next_state;
     42 
     43 reg [7:0] txdata = 0;
     44 reg [7:0] next_txdata;
     45 
     46 wire [7:0]txshift = { 2'b0, txdata[7:2] };
     47 
     48 
     49 reg [5:0] count = 0;
     50 reg [5:0] next_count;
     51 
     52 wire count_is_zero = (count == 0);
     53 
     54 wire [5:0]count_minus_one = (count - 1);
     55 
     56 reg next_txen;
     57 reg [1:0]next_tx;
     58 reg next_advance;
     59 reg next_busy;
     60 
     61 always_comb begin
     62 	next_state = state;
     63 	next_count = count;
     64 	next_txdata = txdata;
     65 	next_busy = busy;
     66 	next_tx = tx;
     67 	next_txen = 1;
     68 	next_advance = 0;
     69 
     70 	case (state)
     71 	IDLE: begin
     72 		next_txen = 0;
     73 		next_tx = 0;
     74 		if (packet) begin
     75 			next_state = PRE;
     76 			next_count = 31;
     77 			next_busy = 1;
     78 		end
     79 	end
     80 	PRE: begin
     81 		if (count_is_zero) begin
     82 			next_state = DAT0;
     83 			next_txdata = data;
     84 			next_advance = 1;
     85 			next_tx = 2'b11;
     86 		end else begin
     87 			next_tx = 2'b01;
     88 			next_count = count_minus_one;
     89 		end
     90 	end
     91 	DAT0: begin
     92 		next_state = DAT1;
     93 		next_txdata = txshift;
     94 		next_tx = txdata[1:0];
     95 	end
     96 	DAT1: begin
     97 		next_state = DAT2;
     98 		next_txdata = txshift;
     99 		next_tx = txdata[1:0];
    100 	end
    101 	DAT2: begin
    102 		next_state = DAT3;
    103 		next_txdata = txshift;
    104 		next_tx = txdata[1:0];
    105 	end
    106 	DAT3: begin
    107 		next_tx = txdata[1:0];
    108 		if (~packet) begin
    109 			// no more data, wrap it up
    110 			next_state = EOP;
    111 			next_count = 48;
    112 		end else begin
    113 			next_state = DAT0;
    114 			next_txdata = data;
    115 			next_advance = 1;
    116 		end
    117 	end
    118 	EOP: begin
    119 		next_tx = 0;
    120 		next_txen = 0;
    121 		if (count_is_zero) begin
    122 			next_state = IDLE;
    123 			next_busy = 0;
    124 		end else begin
    125 			next_count = count_minus_one;
    126 		end
    127 	end
    128 	endcase
    129 end
    130 
    131 always_ff @(posedge clk50) begin
    132 	state <= next_state;
    133 	count <= next_count;
    134 	txdata <= next_txdata;
    135 	txen <= next_txen;
    136 	tx <= next_tx;
    137 	advance <= next_advance;
    138 	busy <= next_busy;
    139 end
    140 
    141 endmodule