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