/******************************************************************************* * SPIDER - Verilog implementation of 10baseT to ronja interface * ******************************************************************************* * version 0.9.1 * ******************************************************************************* * It uses ideas from hardware design of TWISTER * * by Karel 'Clock' Kulhavy - Twibright Labs www.twibright.com * * Written by Jakub Ladman www.volny.cz/ladmanj/ * ******************************************************************************* * Target - Xilinx XC9572XL * ******************************************************************************* * * * Copyright (C) 2004 - 2005 Jakub Ladman * * * ******************************************************************************* * This hdl code is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License * * as published by the Free Software Foundation; either version 2 * * of the License, or (at your option) any later version. * * * * This hdl code is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * *******************************************************************************/ module spider(TP_TXP, TP_TXN, TP_RX, TX, RX, TX_LED, RX_LED, clk_main, test, LINK_LED, IDLE_LED, N_AUTONEG_OFF); output TP_TXP, TP_TXN, TX, TX_LED, RX_LED, test, LINK_LED, IDLE_LED; input TP_RX, RX, clk_main, N_AUTONEG_OFF; wire clk_half, clk_quarter, clk_eighth, link_pulses; wire TX_pac_det, RX_pac_det, idle_sig, tp_link; wire c_export; //test assign test = clk_quarter; assign LINK_LED = ~tp_link; assign IDLE_LED = ~N_AUTONEG_OFF; //test clock_divider clkdiv0 (clk_half, clk_quarter, clk_eighth, clk_main); // divides clk to multiple used frequencies (saves cpld capacity) packet_detector rx_det (RX_pac_det, RX, clk_main, clk_half); // outputs one if packet present on RX tx_packet_detector tx_det (TX_pac_det, TP_RX, clk_main, clk_half); // outputs one if packet present on TX linkdet ld (tp_link, TP_RX, clk_main, c_export); // tp_link is high, when any pulses comes from tp cable link_integrity_pulses lp0 (link_pulses, clk_eighth, clk_main, RX_pac_det, tp_link, c_export); // if packet not detected, generates TP media link integrity pulses idle_generator idl0 (idle_sig, clk_eighth, TX_pac_det); // if packet not detected, generates 1MHz idle signal assign TX = (TX_pac_det) ? TP_RX : idle_sig; // switches data or idle signal to the optic assign TP_TXP = (RX_pac_det) ? ~RX : link_pulses; assign TP_TXN = (RX_pac_det) ? RX : 1'b1; // switches data or lp to the TP media assign TX_LED = ~TX_pac_det; //drives tx indicator led between vcc and pin assign RX_LED = ~RX_pac_det; //drives rx indicator led between vcc and pin endmodule module clock_divider (clk_half, clk_quarter, clk_eighth, clk_main); // clk prescaler output clk_half, clk_quarter, clk_eighth; input clk_main; reg [2:0] cntr; initial cntr = 0; always @(posedge clk_main) cntr <= cntr + 1; assign clk_half = cntr[0]; assign clk_quarter = cntr[1]; assign clk_eighth = cntr[2]; endmodule module counter(out, clk, reset); // 16bit counter used as 16.384msec generator parameter WIDTH = 16; output [WIDTH - 1 : 0] out; input clk, reset; reg [WIDTH - 1 : 0] out; wire clk, reset; initial out = 0; always @(posedge clk or posedge reset) if (reset) out <= 0; else out <= out + 1; endmodule // counter module link_integrity_pulses (flp_out, clk_4, clk_32, reset, link, c_out); output flp_out, c_out; input clk_4, clk_32, reset, link; wire [15:0] c_bus; wire c_clk; wire flp_out; wire current_bit; reg [3:0] burst_cnt; reg [1:0] link_derivator; wire link_on, lp_start; initial begin burst_cnt = 4'b1111; link_derivator = 0; end always@(posedge clk_32) link_derivator = {link_derivator[0], link}; assign link_on = ~link_derivator[1] & link_derivator[0]; assign lp_start = c_bus[14] & c_bus[15]; always@(posedge link_on or posedge lp_start) if (link_on) burst_cnt = 0; else if(burst_cnt < 4'b1111) burst_cnt = burst_cnt + 1; assign c_clk = clk_4 & ~reset; counter c0(c_bus, c_clk, reset); // 16 bit counter assign c_out = c_bus[15]; assign current_bit = ((c_bus[13:8] == 6'd0)||(c_bus[13:8] == 6'd01)||(c_bus[13:8] == 6'd02)|| (c_bus[13:8] == 6'd04)||(c_bus[13:8] == 6'd06)||(c_bus[13:8] == 6'd08)|| (c_bus[13:8] == 6'd10)||(c_bus[13:8] == 6'd11)||(c_bus[13:8] == 6'd12)|| (c_bus[13:8] == 6'd13)||(c_bus[13:8] == 6'd14)||(c_bus[13:8] == 6'd16)|| (c_bus[13:8] == 6'd18)||(c_bus[13:8] == 6'd20)||(c_bus[13:8] == 6'd22)|| (c_bus[13:8] == 6'd24)||(c_bus[13:8] == 6'd26)||(c_bus[13:8] == 6'd28)|| (c_bus[13:8] == 6'd29)||(c_bus[13:8] == 6'd30)||(c_bus[13:8] == 6'd32)); reg [2:0] p_shorter; reg being_transmitted; initial begin p_shorter = 0; being_transmitted = 0; end always @ (posedge clk_32) begin if (c_bus[14] & c_bus[15] & c_bus[7] & ~being_transmitted & ((burst_cnt < 4'b1000)|(c_bus[13:8] == 6'd0))) begin being_transmitted = 1; p_shorter[2] = current_bit; p_shorter[1] = current_bit; p_shorter[0] = current_bit; end else p_shorter = {p_shorter[1:0], 1'b0 }; if (~c_bus[7]) being_transmitted = 0; end assign flp_out = ~(p_shorter[2] & link); endmodule module idle_generator (out, clk_4, reset); // resetable divider output 1MHz output out; input clk_4, reset; reg [1:0] cntr; initial cntr = 0; always @(posedge clk_4 or posedge reset) if (reset) cntr <= 0; else cntr <= cntr + 1; assign out = cntr[1]; endmodule module packet_detector (out, in, clk_32, clk_16); output out; input in, clk_32, clk_16; pacdet first(out, in, clk_32, clk_16); endmodule module tx_packet_detector (out, in, clk_32, clk_16); output out; input in, clk_32, clk_16; reg [1:0] delay; initial delay = 0; wire interconnect; pacdet second(interconnect, in, clk_32, clk_16); always@(posedge interconnect or posedge clk_16) if (interconnect) delay <= 2'b11; else delay <= {delay[0], 1'b0}; assign out = delay[1]; endmodule module pacdet (out, in, clk_f, clk_h); output out; input in, clk_f, clk_h; reg [1:0] shift0; reg [4:0] shift1; reg [7:0] shift2; initial begin shift0 = 0; shift1 = 0; shift2 = 0; end always@(posedge clk_f) shift0 = {shift0[0], in}; wire edge_det; assign edge_det = (shift0[0] & ~shift0[1]); always@(posedge clk_h or posedge edge_det) if(edge_det) shift1 = 0; else shift1 = {shift1[3:0], 1'b1}; always@(posedge clk_h or posedge (shift1[4])) if(shift1[4]) shift2 = 0; else shift2 = {shift2[6:0], 1'b1}; assign out = shift2[7]; endmodule module linkdet (out, in, clk_32, clk); //detects any activity on TP input output out; input in, clk_32, clk; reg [1:0] derivator; always@(posedge clk_32) derivator = {derivator[0], in}; wire derout = derivator[1] & ~derivator[0]; reg [1:0] window; always@(posedge derout or posedge clk) if (derout) window = 0; else if(window < 2'b11) window = window + 1; assign out = ~window[1]; endmodule