From 61f2f0214c5999ea42a368a4fc99f03d8eb28d1e Mon Sep 17 00:00:00 2001 From: jcorgan Date: Mon, 8 Sep 2008 01:00:12 +0000 Subject: Merged r9433:9527 from features/gr-usrp2 into trunk. Adds usrp2 and gr-usrp2 top-level components. Trunk passes distcheck with mb-gcc installed, but currently not without them. The key issue is that when mb-gcc is not installed, the build system skips over the usrp2/firmware directory, and the firmware include files don't get put into the dist tarball. But we can't do the usual DIST_SUBDIRS method as the firmware is a subpackage. git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@9528 221aa14e-8319-0410-a670-987f0aec2ac5 --- eth/bench/verilog/100m.scr | 38 + eth/bench/verilog/Phy_sim.v | 113 ++ eth/bench/verilog/User_int_sim.v | 230 +++ eth/bench/verilog/error.scr | 146 ++ eth/bench/verilog/files.lst | 42 + eth/bench/verilog/host_sim.v | 82 + eth/bench/verilog/icomp.bat | 1 + eth/bench/verilog/isim.bat | 1 + eth/bench/verilog/jumbo_err.scr | 40 + eth/bench/verilog/jumbos.scr | 27 + eth/bench/verilog/mdio.scr | 52 + eth/bench/verilog/miim_model.v | 14 + eth/bench/verilog/misc.scr | 92 + eth/bench/verilog/pause.scr | 45 + eth/bench/verilog/tb_top.v | 1057 +++++++++++ eth/bench/verilog/test.scr | 23 + eth/bench/verilog/txmac.scr | 93 + eth/bench/verilog/xlnx_glbl.v | 29 + eth/demo/verilog/RAMB16_S1_S2.v | 1535 +++++++++++++++ eth/demo/verilog/demo.ucf | 52 + eth/demo/verilog/demo.v | 378 ++++ eth/demo/verilog/demo_packet_descriptor_memory.v | 384 ++++ eth/demo/verilog/demo_packet_generator.v | 274 +++ eth/demo/verilog/demo_uart.v | 235 +++ eth/demo/verilog/demo_wishbone_master.v | 376 ++++ eth/demo/verilog/tb_demo.v | 348 ++++ eth/header_ram.v | 24 + eth/mac_rxfifo_int.v | 80 + eth/mac_txfifo_int.v | 77 + eth/rtl/verilog/Clk_ctrl.v | 133 ++ eth/rtl/verilog/MAC_rx.v | 242 +++ eth/rtl/verilog/MAC_rx/Broadcast_filter.v | 107 ++ eth/rtl/verilog/MAC_rx/CRC_chk.v | 128 ++ eth/rtl/verilog/MAC_rx/MAC_rx_FF.v | 167 ++ eth/rtl/verilog/MAC_rx/MAC_rx_add_chk.v | 158 ++ eth/rtl/verilog/MAC_rx/MAC_rx_ctrl.v | 664 +++++++ eth/rtl/verilog/MAC_top.v | 516 +++++ eth/rtl/verilog/MAC_tx.v | 245 +++ eth/rtl/verilog/MAC_tx/CRC_gen.v | 169 ++ eth/rtl/verilog/MAC_tx/MAC_tx_FF.v | 722 +++++++ eth/rtl/verilog/MAC_tx/MAC_tx_addr_add.v | 128 ++ eth/rtl/verilog/MAC_tx/MAC_tx_ctrl.v | 648 +++++++ eth/rtl/verilog/MAC_tx/Random_gen.v | 109 ++ eth/rtl/verilog/Phy_int.v | 205 ++ eth/rtl/verilog/RMON.v | 163 ++ eth/rtl/verilog/RMON/RMON_addr_gen.v | 295 +++ eth/rtl/verilog/RMON/RMON_ctrl.v | 283 +++ eth/rtl/verilog/Reg_int.v | 270 +++ eth/rtl/verilog/TECH/eth_clk_div2.v | 71 + eth/rtl/verilog/TECH/eth_clk_switch.v | 81 + eth/rtl/verilog/TECH/xilinx/BUFGMUX.v | 64 + eth/rtl/verilog/TECH/xilinx/RAMB16_S36_S36.v | 2204 ++++++++++++++++++++++ eth/rtl/verilog/elastic_buffer.v | 93 + eth/rtl/verilog/elastic_buffer_tb.v | 66 + eth/rtl/verilog/eth_miim.v | 470 +++++ eth/rtl/verilog/flow_ctrl_rx.v | 85 + eth/rtl/verilog/flow_ctrl_tx.v | 36 + eth/rtl/verilog/header.vh | 7 + eth/rtl/verilog/miim/eth_clockgen.v | 141 ++ eth/rtl/verilog/miim/eth_outputcontrol.v | 158 ++ eth/rtl/verilog/miim/eth_shiftreg.v | 159 ++ eth/rx_prot_engine.v | 156 ++ eth/tx_prot_engine.v | 144 ++ 63 files changed, 15175 insertions(+) create mode 100644 eth/bench/verilog/100m.scr create mode 100644 eth/bench/verilog/Phy_sim.v create mode 100644 eth/bench/verilog/User_int_sim.v create mode 100644 eth/bench/verilog/error.scr create mode 100644 eth/bench/verilog/files.lst create mode 100644 eth/bench/verilog/host_sim.v create mode 100644 eth/bench/verilog/icomp.bat create mode 100644 eth/bench/verilog/isim.bat create mode 100644 eth/bench/verilog/jumbo_err.scr create mode 100644 eth/bench/verilog/jumbos.scr create mode 100644 eth/bench/verilog/mdio.scr create mode 100644 eth/bench/verilog/miim_model.v create mode 100644 eth/bench/verilog/misc.scr create mode 100644 eth/bench/verilog/pause.scr create mode 100644 eth/bench/verilog/tb_top.v create mode 100644 eth/bench/verilog/test.scr create mode 100644 eth/bench/verilog/txmac.scr create mode 100644 eth/bench/verilog/xlnx_glbl.v create mode 100644 eth/demo/verilog/RAMB16_S1_S2.v create mode 100644 eth/demo/verilog/demo.ucf create mode 100644 eth/demo/verilog/demo.v create mode 100644 eth/demo/verilog/demo_packet_descriptor_memory.v create mode 100644 eth/demo/verilog/demo_packet_generator.v create mode 100644 eth/demo/verilog/demo_uart.v create mode 100644 eth/demo/verilog/demo_wishbone_master.v create mode 100644 eth/demo/verilog/tb_demo.v create mode 100644 eth/header_ram.v create mode 100644 eth/mac_rxfifo_int.v create mode 100644 eth/mac_txfifo_int.v create mode 100644 eth/rtl/verilog/Clk_ctrl.v create mode 100644 eth/rtl/verilog/MAC_rx.v create mode 100644 eth/rtl/verilog/MAC_rx/Broadcast_filter.v create mode 100644 eth/rtl/verilog/MAC_rx/CRC_chk.v create mode 100644 eth/rtl/verilog/MAC_rx/MAC_rx_FF.v create mode 100644 eth/rtl/verilog/MAC_rx/MAC_rx_add_chk.v create mode 100644 eth/rtl/verilog/MAC_rx/MAC_rx_ctrl.v create mode 100644 eth/rtl/verilog/MAC_top.v create mode 100644 eth/rtl/verilog/MAC_tx.v create mode 100644 eth/rtl/verilog/MAC_tx/CRC_gen.v create mode 100644 eth/rtl/verilog/MAC_tx/MAC_tx_FF.v create mode 100644 eth/rtl/verilog/MAC_tx/MAC_tx_addr_add.v create mode 100644 eth/rtl/verilog/MAC_tx/MAC_tx_ctrl.v create mode 100644 eth/rtl/verilog/MAC_tx/Random_gen.v create mode 100644 eth/rtl/verilog/Phy_int.v create mode 100644 eth/rtl/verilog/RMON.v create mode 100644 eth/rtl/verilog/RMON/RMON_addr_gen.v create mode 100644 eth/rtl/verilog/RMON/RMON_ctrl.v create mode 100644 eth/rtl/verilog/Reg_int.v create mode 100644 eth/rtl/verilog/TECH/eth_clk_div2.v create mode 100644 eth/rtl/verilog/TECH/eth_clk_switch.v create mode 100644 eth/rtl/verilog/TECH/xilinx/BUFGMUX.v create mode 100644 eth/rtl/verilog/TECH/xilinx/RAMB16_S36_S36.v create mode 100644 eth/rtl/verilog/elastic_buffer.v create mode 100644 eth/rtl/verilog/elastic_buffer_tb.v create mode 100644 eth/rtl/verilog/eth_miim.v create mode 100644 eth/rtl/verilog/flow_ctrl_rx.v create mode 100644 eth/rtl/verilog/flow_ctrl_tx.v create mode 100644 eth/rtl/verilog/header.vh create mode 100644 eth/rtl/verilog/miim/eth_clockgen.v create mode 100644 eth/rtl/verilog/miim/eth_outputcontrol.v create mode 100644 eth/rtl/verilog/miim/eth_shiftreg.v create mode 100644 eth/rx_prot_engine.v create mode 100644 eth/tx_prot_engine.v (limited to 'eth') diff --git a/eth/bench/verilog/100m.scr b/eth/bench/verilog/100m.scr new file mode 100644 index 000000000..0dd59b894 --- /dev/null +++ b/eth/bench/verilog/100m.scr @@ -0,0 +1,38 @@ +// This tests just runs a few packets at 10/100 Mbps and 1 Gbps instead of only the usual 1 Gbps + +// Read from register 24 to confirm that Rx CRC check is enabled +03 00 18 00 01 ff ff + +// Set speed to 1000 Mbps for a starter +01 00 22 00 04 + +// Setup Tx and Rx MAC addresses and type field to "IP" +// Set Tx Data at offset 0, length 14 to 123456789ABC CBA987654321 0800 +10 00 00 00 0E 12 34 56 78 9A BC CB A9 87 65 43 21 08 00 + +// Transmit a 1000-byte frame 1 time - and expect it to be received again! +20 03 E8 00 01 + +// Wait (indefinitely) for missing Rx packets +22 00 00 + +// Set speed to 100 Mbps - this is 10x slower! +01 00 22 00 02 + +// Transmit a 1000-byte frame 1 time - and expect it to be received again! +20 03 E8 00 01 + +// Wait (indefinitely) for missing Rx packets +22 00 00 + +// Set speed to 10 Mbps - this is yet another 10x slower! +01 00 22 00 01 + +// Transmit a 1000-byte frame 1 time - and expect it to be received again! +20 03 E8 00 01 + +// Wait (indefinitely) for missing Rx packets +22 00 00 + +// Halt +FF diff --git a/eth/bench/verilog/Phy_sim.v b/eth/bench/verilog/Phy_sim.v new file mode 100644 index 000000000..f51ddbd82 --- /dev/null +++ b/eth/bench/verilog/Phy_sim.v @@ -0,0 +1,113 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// Phy_sim.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source 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 Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: Phy_sim.v,v $ +// Revision 1.3 2006/11/17 17:53:07 maverickist +// no message +// +// Revision 1.2 2006/01/19 14:07:50 maverickist +// verification is complete. +// +// Revision 1.1.1.1 2005/12/13 01:51:44 Administrator +// no message +// + +`timescale 1ns/100ps + +module Phy_sim( + input Gtx_clk, // Used only in GMII mode + output Rx_clk, + output Tx_clk, // Used only in MII mode + input Tx_er, + input Tx_en, + input [7:0] Txd, + output Rx_er, + output Rx_dv, + output [7:0] Rxd, + output Crs, + output Col, + input [2:0] Speed, + input Done +); + +////////////////////////////////////////////////////////////////////// +// this file used to simulate Phy. +// generate clk and loop the Tx data to Rx data +// full duplex mode can be verified on loop mode. +////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////// +// internal signals +////////////////////////////////////////////////////////////////////// +reg Clk_25m; // Used for 100 Mbps mode +reg Clk_2_5m; // Used for 10 Mbps mode + +//wire Rx_clk; +//wire Tx_clk; // Used only in MII mode + + initial + begin + #10; + while ( !Done ) + begin + #20 Clk_25m = 0; + #20 Clk_25m = 1; + end + end + + initial + begin + #10; + while ( !Done ) + begin + #200 Clk_2_5m = 0; + #200 Clk_2_5m = 1; + end + end + + assign Rx_clk = Speed[2] ? Gtx_clk : Speed[1] ? Clk_25m : Speed[0] ? Clk_2_5m : 0; + assign Tx_clk = Speed[2] ? Gtx_clk : Speed[1] ? Clk_25m : Speed[0] ? Clk_2_5m : 0; + + assign Rx_dv = Tx_en; + assign Rxd = Txd; + assign Rx_er = Tx_er; + assign Crs = Tx_en; + assign Col = 0; + +endmodule diff --git a/eth/bench/verilog/User_int_sim.v b/eth/bench/verilog/User_int_sim.v new file mode 100644 index 000000000..3f4aa249b --- /dev/null +++ b/eth/bench/verilog/User_int_sim.v @@ -0,0 +1,230 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// User_input_sim.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source 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 Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: User_int_sim.v,v $ +// Revision 1.3 2006/11/17 17:53:07 maverickist +// no message +// +// Revision 1.2 2006/01/19 14:07:50 maverickist +// verification is complete. +// +// Revision 1.2 2005/12/13 12:15:35 Administrator +// no message +// +// Revision 1.1.1.1 2005/12/13 01:51:44 Administrator +// no message +// +module User_int_sim ( + Reset, + Clk_user, + CPU_init_end, + + Rx_mac_ra, + Rx_mac_rd, + Rx_mac_data, + Rx_mac_BE, + Rx_mac_pa, + Rx_mac_sop, + Rx_mac_eop, + + Tx_mac_wa, + Tx_mac_wr, + Tx_mac_data, + Tx_mac_BE, + Tx_mac_sop, + Tx_mac_eop +); + + input Reset; + input Clk_user; + input CPU_init_end; + + input Rx_mac_ra; + output Rx_mac_rd; + input [31:0] Rx_mac_data; + input [1:0] Rx_mac_BE; + input Rx_mac_pa; + input Rx_mac_sop; + input Rx_mac_eop; + + input Tx_mac_wa; + output reg Tx_mac_wr; + output reg [31:0] Tx_mac_data; + output reg [1:0] Tx_mac_BE; // Big endian + output reg Tx_mac_sop; + output reg Tx_mac_eop; + +////////////////////////////////////////////////////////////////////// +// Internal signals +////////////////////////////////////////////////////////////////////// + + reg [4:0] operation; + reg [31:0] data; + reg Rx_mac_rd; + reg Start_tran; + +////////////////////////////////////////////////////////////////////// +//generate Tx user data +////////////////////////////////////////////////////////////////////// + + initial + begin + operation = 0; + data = 0; + end + + task SendPacket; + input [15:0] Length; + input [7:0] StartByte; + + reg [15:0] Counter; + reg [7:0] TxData; + + begin + Counter=Length; + TxData = StartByte; + Tx_mac_sop = 1; // First time + while ( Counter>0 ) + begin + while ( !Tx_mac_wa ) + begin + Tx_mac_wr = 0; + @( posedge Clk_user ); + end + + Tx_mac_data[31:24] = TxData; + Tx_mac_data[23:16] = TxData+1; + Tx_mac_data[15:8] = TxData+2; + Tx_mac_data[ 7:0] = TxData+3; + TxData = TxData+4; + if ( Counter<=4 ) + begin + // Indicate how many bytes are valid + if ( Counter==4 ) + Tx_mac_BE = 2'b00; + else + Tx_mac_BE = Counter; + Tx_mac_eop = 1; + end + Tx_mac_wr = 1; + + if ( Counter >= 4 ) + Counter = Counter - 4; + else + Counter = 0; + @( posedge Clk_user ); + Tx_mac_sop = 0; + end + + Tx_mac_eop = 0; + Tx_mac_wr = 0; + Tx_mac_data = 32'h0; + Tx_mac_BE = 2'b00; + end + endtask + + always @( posedge Clk_user or posedge Reset ) + if (Reset) + Start_tran <= 0; + else if (Tx_mac_eop && !Tx_mac_wa) + Start_tran <= 0; + else if (Tx_mac_wa) + Start_tran <= 1; + + always @(posedge Clk_user) + if (Tx_mac_wa && CPU_init_end) + /* $ip_32W_gen("../data/config.ini",operation,data); */ + ; + else + begin + operation <= 0; + data <= 0; + end + + initial + begin + Tx_mac_sop = 0; + Tx_mac_eop = 0; + Tx_mac_wr = 0; + Tx_mac_data = 32'h0; + Tx_mac_BE = 2'b00; + + #100; + while ( Reset ) + @( posedge Clk_user ); + + @( posedge Clk_user ); + + while ( !CPU_init_end ) + @( posedge Clk_user ); + + SendPacket( 64, 8'h11 ); + repeat( 20 ) + @( posedge Clk_user ); + SendPacket( 1500, 8'h12 ); + + end + +// assign Tx_mac_data = data; +// assign Tx_mac_wr = operation[4]; +// assign Tx_mac_sop = operation[3]; +// assign Tx_mac_eop = operation[2]; +// assign Tx_mac_BE = operation[1:0]; + +////////////////////////////////////////////////////////////////////// +//verify Rx user data +////////////////////////////////////////////////////////////////////// + + always @ (posedge Clk_user or posedge Reset) + if (Reset) + Rx_mac_rd <= 0; + else if (Rx_mac_ra) + Rx_mac_rd <= 1; + else + Rx_mac_rd <= 0; + + always @ (posedge Clk_user ) + if (Rx_mac_pa) + /* $ip_32W_check( Rx_mac_data, + {Rx_mac_sop,Rx_mac_eop,Rx_mac_eop?Rx_mac_BE:2'b0}); + */ + ; + +endmodule diff --git a/eth/bench/verilog/error.scr b/eth/bench/verilog/error.scr new file mode 100644 index 000000000..af42634a8 --- /dev/null +++ b/eth/bench/verilog/error.scr @@ -0,0 +1,146 @@ +// This tests sends 5 packets, injecting a bit error in two of them +// to verify the Rx CRC check works. The corresponding RMON statistics +// counter is finally checked to verify that the error was registered + +// Read from register 24 to confirm that Rx CRC check is enabled +03 00 18 00 01 ff ff + +// Set speed to 1000 Mbps +01 00 22 00 04 + +// Setup Tx and Rx MAC addresses and type field to "IP" +// Set Tx Data at offset 0, length 14 to 123456789ABC CBA987654321 0800 +10 00 00 00 0E 12 34 56 78 9A BC CB A9 87 65 43 21 08 00 + +//--- Packets #0 & 1 -------------------------------------------------------- + +// Transmit a 200-byte frame 1 time - and expect it to be received again! +20 00 C8 00 01 + +// Wait (indefinitely) for missing Rx packets +22 00 00 + +// Transmit a 200-byte frame 1 time - but expect to receive it with error! +25 00 C8 00 01 + +// Inject a single bit error in the packet (data bit 0) - this will cause a CRC error +23 00 01 + +// Wait (indefinitely) for missing Rx packets +22 00 00 + +//--- Packets #2 & 3 -------------------------------------------------------- + +// Transmit a 200-byte frame 1 time - and expect it to be received again! +20 00 C8 00 01 + +// Wait (indefinitely) for missing Rx packets +22 00 00 + +// Transmit a 200-byte frame 1 time - but expect to receive it with error! +25 00 C8 00 01 + +// Inject a single bit error in the packet (data bit 7) - this will cause a CRC error +23 00 80 + +// Wait (indefinitely) for missing Rx packets +22 00 00 + +//--- Packets #4 & 5 -------------------------------------------------------- + +// Transmit a 200-byte frame 1 time - and expect it to be received again! +20 00 C8 00 01 + +// Wait (indefinitely) for missing Rx packets +22 00 00 + +// Transmit a 200-byte frame 1 time - but don't expect it to be received again! +21 00 C8 00 01 + +// Inject a single bit error in the packet (RxEn) - this will cause a packet discard! +// (because it happens early in the packet) +23 01 00 + +// Wait (indefinitely) for missing Rx packets +22 00 00 + +//--- Packets #6 & 7 -------------------------------------------------------- + +// Transmit a 200-byte frame 1 time - and expect it to be received again! +20 00 C8 00 01 + +// Wait (indefinitely) for missing Rx packets +22 00 00 + +// Transmit a 200-byte frame 1 time - but don't expect it to be received again! +21 00 C8 00 01 + +// Inject a single bit error in the packet (RxEr) +23 02 00 + +// Wait (indefinitely) for missing Rx packets +22 00 00 + +//--- Packet #8 ------------------------------------------------------------- + +// Transmit a 200-byte frame 1 time - and expect it to be received again! +20 00 C8 00 01 + +// Wait (indefinitely) for missing Rx packets +22 00 00 + +//--------------------------------------------------------------------------- + +// Set CPU_rd_addr to address RxCRCErrCounter +01 00 1C 00 05 + +// Assert CPU_rd_apply +01 00 1D 00 01 + +// Kill a little time while waiting for CPU_rd_grant to assert... +02 00 1E +02 00 1E +02 00 1E +02 00 1E + +// Confirm that CPU_rd_grant is asserted +03 00 1E 00 01 ff ff + +// Read & check low part of RxCRCErrCounter (0x0002) +03 00 1F 00 02 ff ff + +// Read & check high part of RxCRCErrCounter (0x0000) +03 00 20 00 00 ff ff + +// Negate CPU_rd_apply +01 00 1D 00 00 + +//--------------------------------------------------------------------------- + +// Set CPU_rd_addr to address RxTooShortTooLongCounter +01 00 1C 00 07 + +// Assert CPU_rd_apply +01 00 1D 00 01 + +// Kill a little time while waiting for CPU_rd_grant to assert... +02 00 1E +02 00 1E +02 00 1E +02 00 1E + +// Confirm that CPU_rd_grant is asserted +03 00 1E 00 01 ff ff + +// Read & check low part of RxTooShortTooLongCounter (0x0002) +03 00 1F 00 02 ff ff + +// Read & check high part of RxTooShortTooLongCounter (0x0000) +03 00 20 00 00 ff ff + +// Negate CPU_rd_apply +01 00 1D 00 00 + + +// Halt +FF diff --git a/eth/bench/verilog/files.lst b/eth/bench/verilog/files.lst new file mode 100644 index 000000000..6175a4d43 --- /dev/null +++ b/eth/bench/verilog/files.lst @@ -0,0 +1,42 @@ +../../rtl/verilog/MAC_rx/Broadcast_filter.v +../../rtl/verilog/MAC_rx/CRC_chk.v +../../rtl/verilog/MAC_rx/MAC_rx_add_chk.v +../../rtl/verilog/MAC_rx/MAC_rx_ctrl.v +../../rtl/verilog/MAC_rx/MAC_rx_FF.v + +../../rtl/verilog/MAC_tx/CRC_gen.v +../../rtl/verilog/MAC_tx/flow_ctrl.v +../../rtl/verilog/MAC_tx/MAC_tx_addr_add.v +../../rtl/verilog/MAC_tx/MAC_tx_ctrl.v +../../rtl/verilog/MAC_tx/MAC_tx_FF.v +../../rtl/verilog/MAC_tx/Ramdon_gen.v + +../../rtl/verilog/miim/eth_clockgen.v +../../rtl/verilog/miim/eth_outputcontrol.v +../../rtl/verilog/miim/eth_shiftreg.v + +../../rtl/verilog/RMON/RMON_addr_gen.v +../../rtl/verilog/RMON/RMON_ctrl.v +../../rtl/verilog/RMON/RMON_dpram.v + +../../rtl/verilog/TECH/duram.v +../../rtl/verilog/TECH/eth_clk_div2.v +../../rtl/verilog/TECH/eth_clk_switch.v + +../../rtl/verilog/TECH/xilinx/BUFGMUX.v +../../rtl/verilog/TECH/xilinx/RAMB16_S36_S36.v + +../../rtl/verilog/Clk_ctrl.v +../../rtl/verilog/eth_miim.v +../../rtl/verilog/MAC_rx.v +../../rtl/verilog/MAC_top.v +../../rtl/verilog/MAC_tx.v +../../rtl/verilog/Phy_int.v +../../rtl/verilog/Reg_int.v +../../rtl/verilog/RMON.v + +../../bench/verilog/Phy_sim.v +../../bench/verilog/User_int_sim.v +../../bench/verilog/host_sim.v +../../bench/verilog/xlnx_glbl.v +../../bench/verilog/tb_top.v diff --git a/eth/bench/verilog/host_sim.v b/eth/bench/verilog/host_sim.v new file mode 100644 index 000000000..55abb8508 --- /dev/null +++ b/eth/bench/verilog/host_sim.v @@ -0,0 +1,82 @@ +module host_sim( + input Reset, + input Clk_reg, + output reg CSB, + output reg WRB, + output reg CPU_init_end, + output reg [15:0] CD_in, + input [15:0] CD_out, + output reg [7:0] CA +); + +//////////////////////////////////////// + +task CPU_init; + begin + CA = 0; + CD_in = 0; + WRB = 1; + CSB = 1; + end +endtask + +//////////////////////////////////////// + +task CPU_wr; + input [6:0] Addr; + input [15:0] Data; + begin + CA = {Addr,1'b0}; + CD_in = Data; + WRB = 0; + CSB = 0; + #20; + CA = 0; + CD_in = 0; + WRB = 1; + CSB = 1; + #20; + end +endtask + +///////////////////////////////////////// + +task CPU_rd; + input [6:0] Addr; + begin + CA = {Addr,1'b0}; + WRB = 1; + CSB = 0; + #20; + CA = 0; + WRB = 1; + CSB = 1; + #20; + end +endtask + +///////////////////////////////////////// + +integer i; + +reg [31:0] CPU_data [255:0]; +reg [7:0] write_times; +reg [7:0] write_add; +reg [15:0] write_data; + +initial + begin + CPU_init; + CPU_init_end=0; + //$readmemh("../data/CPU.vec",CPU_data); + //{write_times,write_add,write_data}=CPU_data[0]; + {write_times,write_add,write_data}='b0; + #90; + for (i=0;i (7+6)); + assign Tx_er_Modified = Tx_er ^ ( TxError[9] & TxInPayload ); + assign Tx_en_Modified = Tx_en ^ ( TxError[8] & TxInPayload ); + assign Txd_Modified = Txd ^ ( TxError[7:0] & {8{TxInPayload}} ); + + always @( posedge Reset or posedge Tx_clk ) + if ( Reset ) + begin + InjectError <= 0; + InjectErrorDone <= 0; + TxError <= 'b0; + end + else + if ( InjectError ) + begin + TxError <= InjectError; + InjectError <= 0; + InjectErrorDone <= TxInPayload; + end + else if ( TxInPayload || InjectErrorDone ) + begin + TxError <= 8'h00; + InjectErrorDone <= 0; + end + + //------------------------------------------------------------------------- + // Track pause on Tx interface + + reg TxEnSeenOnce; + integer TxTrackPause; + + always @( posedge Reset or posedge Tx_clk ) + if ( Reset ) + begin + TxEnSeenOnce <= 0; + TxTrackPause <= 0; + end + else + if ( Tx_en ) + begin + if ( TxEnSeenOnce && (TxTrackPause >= 64) ) // 512 bits + $display( "IDLE period on Tx interface ended after %0d Tx clocks (%0d bits, tick ~ %0d)", + TxTrackPause, + (Speed == 4) ? TxTrackPause*8 : TxTrackPause*4, + (Speed == 4) ? TxTrackPause*8/512 : TxTrackPause*4/512 ); + TxEnSeenOnce <= 1; + TxTrackPause <= 0; + end + else + TxTrackPause <= TxTrackPause + 1; + + //------------------------------------------------------------------------- + // Host access routines (register read & write) + //------------------------------------------------------------------------- + + task HostInit; + begin + RST_I <= 1; + + STB_I <= 0; + CYC_I <= 0; + ADR_I <= 'b0; + WE_I <= 0; + DAT_I <= 'b0; + + #100 RST_I <= 0; + + // Wait a couple of clock edges before continuing to allow + // internal logic to get out of reset + repeat( 2 ) + @( posedge CLK_I ); + end + endtask + + task HostWriteReg; + input [6:0] Addr; + input [15:0] Data; + begin + @( posedge CLK_I ); + ADR_I <= Addr; + DAT_I <= Data; + WE_I <= 1; + STB_I <= 1; + CYC_I <= 1; + + @( posedge CLK_I ); + + while ( ~ACK_O ) + @( posedge CLK_I ); + + STB_I <= 0; + CYC_I <= 0; + end + endtask + + task HostReadReg; + input [6:0] Addr; + output [15:0] Data; + begin + @( posedge CLK_I ); + ADR_I <= Addr; + WE_I <= 0; + STB_I <= 1; + CYC_I <= 1; + + @( posedge CLK_I ); + + while ( ~ACK_O ) + @( posedge CLK_I ); + + Data = DAT_O; + STB_I <= 0; + CYC_I <= 0; + end + endtask + + //------------------------------------------------------------------------- + // User interface access routines (packet Tx and Rx) + //------------------------------------------------------------------------- + + `define FIFOSIZE 10000 + + integer FIFO_WrPtr = 0; + integer FIFO_RdPtr = 0; + integer FIFO_ElementCount = 0; + reg [35:0] FIFO_Data[0:`FIFOSIZE]; + + function FIFO_Empty; + input Dummy; + begin + if ( FIFO_ElementCount > 0 ) + FIFO_Empty = 0; + else + FIFO_Empty = 1; + end + endfunction + + function FIFO_Full; + input Dummy; + begin + if ( FIFO_ElementCount < `FIFOSIZE ) + FIFO_Full = 0; + else + FIFO_Full = 1; + end + endfunction + + task FIFO_Wr; + input [35:0] Data; + + begin + if ( !FIFO_Full(0) ) + begin + FIFO_Data[ FIFO_WrPtr ] = Data; + FIFO_WrPtr = (FIFO_WrPtr + 1) % `FIFOSIZE; + FIFO_ElementCount = FIFO_ElementCount + 1; + end + else + begin + $display( "ERROR: FIFO_Wr() - FIFO overflow!" ); + Error = 1; + $finish; + end + end + endtask + + task FIFO_Rd; + output [35:0] Data; + + begin + if ( !FIFO_Empty(0) ) + begin + Data = FIFO_Data[ FIFO_RdPtr ]; + FIFO_RdPtr = (FIFO_RdPtr + 1) % `FIFOSIZE; + FIFO_ElementCount = FIFO_ElementCount - 1; + end + else + begin + $display( "ERROR: FIFO_Rd() - Reading from empty FIFO!" ); + Error = 1; + $finish; + end + end + endtask + + //------------------------------------------------------------------------- + + `define TXDATALEN 8000 + reg [7:0] TxData[0:`TXDATALEN-1]; + reg [7:0] TxAltData[0:`TXDATALEN-1]; + + // By default change payload after Ethernet Header + reg [15:0] TxHeaderLength = 14; + + real TxStartTime; + integer TxPacketCount = 0; + integer TxByteCount; + + task SendPacket; + input [15:0] Length; + // 0: Don't write to FIFO, 1: Write to FIFO, 2: Write Alternate to FIFO, 3: Write IGNORE to FIFO + input [1:0] Wr2FIFO; + + reg [15:0] Counter; + integer TxIndex; + integer i; + + reg [31:0] Tx_fifo_data; + + begin + @( posedge Clk_user ); #1; + + TxPacketCount = TxPacketCount + 1; + TxByteCount = TxByteCount + Length; + + Counter=Length; + TxIndex = 0; + Tx_mac_sop = 1; // First time + + if ( TxStartTime == 0 ) + TxStartTime = $realtime; + + while ( Counter>0 ) + begin + while ( !Tx_mac_wa ) + begin + Tx_mac_wr = 0; + @( posedge Clk_user ); #1; + end + + Tx_mac_data[31:24] = TxData[ TxIndex ]; + Tx_mac_data[23:16] = TxData[ TxIndex+1 ]; + Tx_mac_data[15:8] = TxData[ TxIndex+2 ]; + Tx_mac_data[ 7:0] = TxData[ TxIndex+3 ]; + + // Default take data from regular tx buffer + Tx_fifo_data = Tx_mac_data; + if ( Wr2FIFO==2 ) + begin + // Put content of Alternate Tx buffer on Rx expectancy queue + if ( (TxIndex+0)= TxHeaderLength ) + TxData[ TxIndex ] = TxData[ TxIndex ] + 1; + TxIndex = TxIndex+1; + end + + if ( Counter<=4 ) + begin + // Indicate how many bytes are valid + if ( Counter==4 ) + Tx_mac_BE = 2'b00; + else + Tx_mac_BE = Counter; + Tx_mac_eop = 1; + end + else + begin + Tx_mac_BE = 2'b00; + Tx_mac_eop = 0; + end + + casez ( Wr2FIFO ) + 1, + 2: FIFO_Wr( { Tx_mac_sop, Tx_mac_eop, Tx_mac_BE, Tx_fifo_data } ); + 3: // Ignore + begin + FIFO_Wr( { 2'b11, 2'b00, 32'h00000000 } ); + Wr2FIFO = 0; + end + endcase + + Tx_mac_wr = 1; + + if ( Counter >= 4 ) + Counter = Counter - 4; + else + Counter = 0; + @( posedge Clk_user ); #1; + Tx_mac_sop = 0; + end + + Tx_mac_sop = 1'bx; + Tx_mac_eop = 1'bx; + Tx_mac_wr = 0; + Tx_mac_data = 32'bx; + Tx_mac_BE = 2'bx; + end + endtask + + //------------------------------------------------------------------------- + + reg Negate_Rx_mac_rd; + + always @( posedge Clk_user or posedge Reset ) + if ( Reset ) + Rx_mac_rd <= 0; + else if ( Rx_mac_ra & ~Negate_Rx_mac_rd ) + Rx_mac_rd <= 1; + else + Rx_mac_rd <= 0; + + real RxStartTime; + integer RxPacketCount; + integer RxByteCount; + + reg InPacket; + integer RxPacketLength; + reg IgnoreUntilNextERR; + + always @( posedge Clk_user or posedge Reset ) + if ( Reset ) + begin + InPacket = 0; + RxPacketCount = 0; + Negate_Rx_mac_rd <= 0; + IgnoreUntilNextERR = 0; + end + else + begin + Negate_Rx_mac_rd <= 0; + + if ( Rx_mac_pa ) + begin : RxWord + reg [35:0] RxData; + reg [35:0] Expected; + reg [35:0] Mask; + + RxData = { Rx_mac_sop, Rx_mac_eop, Rx_mac_BE, Rx_mac_data }; + casez ( Rx_mac_BE ) + 2'b01: Mask = 36'hfff000000; + 2'b10: Mask = 36'hfffff0000; + 2'b11: Mask = 36'hfffffff00; + default: Mask = 36'hfffffffff; + endcase + + // Retrieve expected packet data + + if ( !IgnoreUntilNextERR ) + begin + FIFO_Rd( Expected ); + if ( Expected[35] & Expected[34] ) + begin + // Both SOP & EOP are asserted in expectancy data + // - this means that we should ignore all data received until next EOP + $display( "The payload of this packet will be IGNORED - and an ERROR must be signalled!" ); + IgnoreUntilNextERR = 1; + end + end + if ( IgnoreUntilNextERR ) + Mask = 36'h000000000; + + //$display( "DEBUG: RxData=0x%0x, Expected=0x%0x", RxData, Expected ); + + if ( (RxData & Mask) !== (Expected & Mask) ) + begin + $display( "ERROR: Receiving unexpected packet data: Got 0x%0x, expected 0x%0x (Mask=0x%0x)", + RxData, Expected, Mask ); + Error = 1; + end + + if ( InPacket ) + begin + if ( Rx_mac_eop ) + begin + // Ensure Rx_mac_rd is negated for one clock + Negate_Rx_mac_rd <= 1; + if ( Rx_mac_BE==2'b00 ) + RxPacketLength = RxPacketLength + 4; + else + RxPacketLength = RxPacketLength + Rx_mac_BE; + $display( "Rx packet #%0d of length %0d ends", + RxPacketCount, + RxPacketLength ); + RxPacketCount = RxPacketCount + 1; + RxByteCount = RxByteCount + RxPacketLength; + InPacket = 0; + end + else + RxPacketLength = RxPacketLength + 4; + end + else + begin + if ( Rx_mac_sop ) + begin + RxPacketLength = 4; + $display( "Rx packet #%0d begins: 0x%08x", RxPacketCount, Rx_mac_data ); + InPacket = 1; + if ( RxStartTime == 0 ) + RxStartTime = $realtime; + end + else + begin + $display( "ERROR: Unexpectedly reading from Rx FIFO while not receiving a packet!" ); + Error = 1; + end + end + + if ( Rx_mac_err ) + begin + if ( !Rx_mac_eop ) + begin + $display( "ERROR: Rx_mac_err was asserted without Rx_mac_eop also being asserted!" ); + Error = 1; + end + if ( IgnoreUntilNextERR ) + $display( "Info: Rx_mac_err was asserted as expected!" ); + else + begin + $display( "ERROR: Rx_mac_err was unexpectedly asserted!" ); + Error = 1; + end + IgnoreUntilNextERR = 0; + end + end + end + + //------------------------------------------------------------------------- + // Script handling + //------------------------------------------------------------------------- + + integer PC; + + task ScriptWriteReg; + input [15:0] Addr; + input [15:0] Data; + + begin + $display( "WriteReg( 0x%04x, 0x%04x )", Addr, Data ); + HostWriteReg( Addr, Data ); + end + endtask + + task ScriptReadReg; + input [15:0] Addr; + + reg [15:0] Data; + + begin + $write( "ReadReg( 0x%04x ): ", Addr ); + HostReadReg( Addr, Data ); + $display( "0x%04x", Data ); + end + endtask + + task ScriptReadRegAndMatch; + input [15:0] Addr; + input [15:0] Data; + input [15:0] Mask; + + reg [15:0] Read; + + begin + $write( "ReadRegAndMatch( 0x%04x, 0x%04x, 0x%04x ): ", Addr, Data, Mask ); + + HostReadReg( Addr, Read ); + $display( "0x%04x, masked=0x%04x", Read, Read & Mask ); + + if ( Data !== (Read & Mask) ) + begin + $display( "Error: Unexpected data read" ); + Error = 1; + end + end + endtask + + integer RxExpectPacketCount = 0; + + task ScriptSendPacket; + input [15:0] Length; + // 0: Don't receive, 1: Receive & match, 2: Receive & match alternate, 3: Receive & ignore + input [1:0] ExpectToRx; + + begin + $display( "ScriptSendPacket( 0x%04x, %0d )", Length, ExpectToRx ); + SendPacket( Length, ExpectToRx ); + if ( ExpectToRx != 0 ) + RxExpectPacketCount = RxExpectPacketCount + 1; + end + endtask + + `define SCRIPTLEN 10000 + integer i; + reg [7:0] Script[0:`SCRIPTLEN-1]; + + function [15:0] Get16bit; + input Dummy; + + reg [15:0] Data; + + begin + Data[15:8] = Script[PC]; + Data[7:0] = Script[PC+1]; + PC = PC+2; + + Get16bit = Data; + end + endfunction + + task ExecuteScript; + + reg [7:0] OpCode; + reg [15:0] Addr; + reg [15:0] Data; + reg [15:0] Length; + reg [15:0] Count; + reg [15:0] Mask; + + reg ScriptDone; + + begin + ScriptDone = 0; + Error = 0; + PC = 0; + + while ( !ScriptDone ) + begin + OpCode = Script[PC]; + //$write( "PC=%0d, OpCode=%02x: ", PC, OpCode ); + PC = PC+1; + + casez ( OpCode ) + 8'h00: // NOP + begin +// $display( "NOP" ); + #10; + end + 8'h01: // Write + begin + Addr = Get16bit(i); + Data = Get16bit(i); + ScriptWriteReg( Addr, Data ); + end + 8'h02: // Read + begin + Addr = Get16bit(i); + ScriptReadReg( Addr ); + end + 8'h03: // Read & match + begin + Addr = Get16bit(i); + Data = Get16bit(i); + Mask = Get16bit(i); + ScriptReadRegAndMatch( Addr, Data, Mask ); + end + + 8'h0f: // Delay + begin + Count = Get16bit(i); + $display( "Delay %0d", Count ); + while ( Count > 0 ) + begin + #10; + Count = Count - 1; + end + end + + 8'h10: // Setup Tx Data + begin + Addr = Get16bit(i); + Length = Get16bit(i); + $write( "TxData( 0x%04x ), length=%0d: ", Addr, Length ); + while ( Length != 0 ) + begin + TxData[Addr] = Script[PC]; + $write( " 0x%02x", Script[PC] ); + PC = PC + 1; + Addr = Addr + 1; + Length = Length - 1; + end + $display( "" ); + end + + 8'h11: // Setup Alternative Tx Data + begin + Addr = Get16bit(i); + Length = Get16bit(i); + $write( "TxAltData( 0x%04x ), length=%0d: ", Addr, Length ); + while ( Length != 0 ) + begin + TxAltData[Addr] = Script[PC]; + $write( " 0x%02x", Script[PC] ); + PC = PC + 1; + Addr = Addr + 1; + Length = Length - 1; + end + $display( "" ); + end + + 8'h20: // Transmit packet - and put it on Rx expectancy queue + begin + Length = Get16bit(i); // Length in bytes + Count = Get16bit(i); // Number of times + while ( Count != 0 ) + begin + ScriptSendPacket( Length, 1 ); + Count = Count - 1; + end + end + + 8'h21: // Transmit packet - but DON'T put it on Rx expectancy queue + begin + Length = Get16bit(i); // Length in bytes + Count = Get16bit(i); // Number of times + while ( Count != 0 ) + begin + ScriptSendPacket( Length, 0 ); + Count = Count - 1; + end + end + + 8'h22: // Wait + begin : OpCode22 + reg NoTimeOut; + Count = Get16bit(i); // Timeout in ns + if ( Count==0 ) + NoTimeOut = 1; + else + NoTimeOut = 0; + + $display( "Waiting for # of Rx packets = # of Tx packets..." ); + $display( "Timeout = %0d ns - Current # Rx =%0d, Expected=%0d", + Count, RxPacketCount, RxExpectPacketCount ); + + while( (NoTimeOut || (Count != 0)) && ( RxExpectPacketCount != RxPacketCount ) && !Error ) + begin + #1; + if ( !NoTimeOut ) + Count = Count - 1; + //$display( "NoTimeOut=%0d, Count=%0d", NoTimeOut, Count ); + end + + if ( !Error ) + if ( RxExpectPacketCount != RxPacketCount ) + begin + $display( "ERROR: Timeout waiting for Rx packet(s)!" ); + ScriptDone = 1; + Error = 1; + end + else + $display( "...Done waiting (time remaining = %0d ns)!", Count ); + end + + 8'h23: // Inject bit error in Tx packet + begin + InjectError = Get16bit(i); // Get bit error pattern + $display( "Injecting a single bit-error in Tx packet: TxEr=%0d, TxEn=%0d, TxD=0x%02h (0x%03h)", + InjectError[9], InjectError[8], InjectError[7:0], InjectError ); + end + + 8'h24: // Store internally generated PAUSE frame in Rx expect queue + begin + Count = Get16bit(i); // Timeout in ns + $display( "Generating PAUSE frame (tick=%0d) on Rx expect queue", Count ); + RxExpectPacketCount = RxExpectPacketCount + 1; + FIFO_Wr( { 1'b1, 1'b0, 2'b00, 32'h0180c200 } ); + FIFO_Wr( { 1'b0, 1'b0, 2'b00, 16'h0001, 16'h0000 } ); + FIFO_Wr( { 1'b0, 1'b0, 2'b00, 32'h00000000 } ); + FIFO_Wr( { 1'b0, 1'b0, 2'b00, 32'h88080001 } ); + FIFO_Wr( { 1'b0, 1'b0, 2'b00, Count, 16'h0000 } ); + FIFO_Wr( { 1'b0, 1'b0, 2'b00, 32'h00000000 } ); + FIFO_Wr( { 1'b0, 1'b0, 2'b00, 32'h00000000 } ); + FIFO_Wr( { 1'b0, 1'b0, 2'b00, 32'h00000000 } ); + FIFO_Wr( { 1'b0, 1'b0, 2'b00, 32'h00000000 } ); + FIFO_Wr( { 1'b0, 1'b0, 2'b00, 32'h00000000 } ); + FIFO_Wr( { 1'b0, 1'b0, 2'b00, 32'h00000000 } ); + FIFO_Wr( { 1'b0, 1'b0, 2'b00, 32'h00000000 } ); + FIFO_Wr( { 1'b0, 1'b0, 2'b00, 32'h00000000 } ); + FIFO_Wr( { 1'b0, 1'b0, 2'b00, 32'h00000000 } ); + FIFO_Wr( { 1'b0, 1'b1, 2'b00, 32'h00000000 } ); + end + + 8'h25: // Transmit packet - and indicate that it must be IGNORED upon reception + begin + Length = Get16bit(i); // Length in bytes + Count = Get16bit(i); // Number of times + while ( Count != 0 ) + begin + ScriptSendPacket( Length, 3 ); + Count = Count - 1; + end + end + + 8'h26: // Transmit packet - and put it on expectancy queue with Alternate header! + begin + Length = Get16bit(i); // Length in bytes + Count = Get16bit(i); // Number of times + while ( Count != 0 ) + begin + ScriptSendPacket( Length, 2 ); + Count = Count - 1; + end + end + + 8'hff: // Halt + begin + $display( "HALT" ); + ScriptDone = 1; + Done = 1; + end + + default: // Unknown opcode + begin + $display( "Unknown instruction encountered @ PC=%0d: OpCode=0x%02x", PC-1, OpCode ); + Error = 1; + end + + endcase + + if ( Error ) + begin + ScriptDone = 1; + Done = 1; + end + end + + if ( Error ) + $display( "ERROR: Test failed!"); + else + begin : ScriptSuccess + real TxTimeElapsed; + real RxTimeElapsed; + real ReferenceTime; + + ReferenceTime = $realtime; + #1; + ReferenceTime = $realtime - ReferenceTime; + + TxTimeElapsed = $realtime - TxStartTime; + RxTimeElapsed = $realtime - RxStartTime; + + $display( "TxStartTime=%0e, Now=%0e", TxStartTime, $realtime ); + $display( "RxStartTime=%0e, Now=%0e", RxStartTime, $realtime ); + + $display( "Tx stats: %0d packet(s) send, total of %0d bytes in %0e ns ~ %1.2f Mbps", + TxPacketCount, TxByteCount, TxTimeElapsed, TxByteCount*8*1e3/TxTimeElapsed ); + $display( "Rx stats: %0d packet(s) received, total of %0d bytes in %0e ns ~ %1.2f Mbps", + RxPacketCount, RxByteCount, RxTimeElapsed, RxByteCount*8*1e3/RxTimeElapsed ); + $display( "Test succeeded!"); + end + + end + endtask + + //------------------------------------------------------------------------- + // Generate all clocks + //------------------------------------------------------------------------- + + // GMII master clock (125 MHz) + initial + begin + #10; + while ( !Done ) + begin + #4 Clk_125M = 0; + #4 Clk_125M = 1; + end + end + + // User (packet) interface clock (100 MHz) + initial + begin + #10; + while ( !Done ) + begin + #5 Clk_user = 0; + #5 Clk_user = 1; + end + end + + // Wishbone host interface clock (50 MHz) + initial + begin + #10; + while ( !Done ) + begin + #10 CLK_I = 0; + #10 CLK_I = 1; + end + end + + //------------------------------------------------------------------------- + + initial + begin + if ( $test$plusargs( "vcd" ) ) + begin + $display( "Turning VCD data dump on" ); + $dumpfile(); + $dumpvars( 0 ); // Dump all signals in entire design + end + end + + //------------------------------------------------------------------------- + + reg [1023:0] ScriptFile; + + initial + begin + HostInit; + + TxStartTime = 0; + RxStartTime = 0; + TxByteCount = 0; + RxByteCount = 0; + + for ( i=0; i<`TXDATALEN; i=i+1 ) + TxData[i] = (i & 8'hff); + + // Fill script memory with HALTs + for ( i=0; i<`SCRIPTLEN; i=i+1 ) + Script[i] = 8'hff; + + if ( !$value$plusargs( "script=%s", ScriptFile ) ) + begin + $display( "Using default script file" ); + ScriptFile = "test.scr"; + end + + $readmemh( ScriptFile, Script ); + +// for ( i=0; i<40; i=i+1 ) +// $display( "Script[%0d]=0x%02x", i, Script[i] ); + + #10; + + ExecuteScript; + end + +endmodule diff --git a/eth/bench/verilog/test.scr b/eth/bench/verilog/test.scr new file mode 100644 index 000000000..2ad127d31 --- /dev/null +++ b/eth/bench/verilog/test.scr @@ -0,0 +1,23 @@ +// This tests just runs trough a couple of different packet lengths + +// Read from register 24 to confirm that Rx CRC check is enabled +03 00 18 00 01 ff ff + +// Set speed to 1000 Mbps +01 00 22 00 04 + +// Setup Tx and Rx MAC addresses and type field to "IP" +// Set Tx Data at offset 0, length 14 to 123456789ABC CBA987654321 0800 +10 00 00 00 0E 12 34 56 78 9A BC CB A9 87 65 43 21 08 00 + +// Transmit a 320-byte frame 1 time - and expect it to be received again! +20 01 40 00 01 + +// Transmit a 80-byte frame 1 time - and expect it to be received again! +20 00 50 00 01 + +// Wait (indefinitely) for missing Rx packets +22 00 00 + +// Halt +FF diff --git a/eth/bench/verilog/txmac.scr b/eth/bench/verilog/txmac.scr new file mode 100644 index 000000000..caa7db594 --- /dev/null +++ b/eth/bench/verilog/txmac.scr @@ -0,0 +1,93 @@ +// Read from register 24 to confirm that Rx CRC check is enabled +03 00 18 00 01 ff ff + +// Set speed to 1000 Mbps +01 00 22 00 04 + +// Write MAC address 12 35 56 78 9A BC to Rx Address buffer +01 00 10 00 00 +01 00 0f 00 12 +01 00 11 00 01 +01 00 11 00 00 +01 00 10 00 01 +01 00 0f 00 34 +01 00 11 00 01 +01 00 11 00 00 +01 00 10 00 02 +01 00 0f 00 56 +01 00 11 00 01 +01 00 11 00 00 +01 00 10 00 03 +01 00 0f 00 78 +01 00 11 00 01 +01 00 11 00 00 +01 00 10 00 04 +01 00 0f 00 9A +01 00 11 00 01 +01 00 11 00 00 +01 00 10 00 05 +01 00 0f 00 BC +01 00 11 00 01 +01 00 11 00 00 + +// Write 1 to register 14, MAC_rx_add_chk_en +// This turns on the Rx Destination MAC address filter +01 00 0e 00 01 + +// Setup Tx and Rx MAC addresses and type field to "IP" +// Set Tx Data at offset 0, length 14 to 123456789ABC CBA987654321 0800 +// (i.e. Destination MAC address is 123456789ABC matching the above) +10 00 00 00 0E 12 34 56 78 9A BC CB A9 87 65 43 21 08 00 + +// Setup Alternate Tx and Rx MAC addresses and type field to "IP" +// Set Tx Data at offset 0, length 14 to 123456789ABC 112233445566 0800 +// (i.e. Destination MAC address is 123456789ABC matching the above) +11 00 00 00 0E 12 34 56 78 9A BC 11 22 33 44 55 66 08 00 + +// Transmit a 60-byte frame 3 times - and expect them to be received again! +20 00 3C 00 03 + +// Wait (indefinitely) for missing Rx packets +22 00 00 + +// Write MAC address 11 22 33 44 55 66 to Tx MAC Source Address buffer +01 00 09 00 00 +01 00 08 00 11 +01 00 0a 00 01 +01 00 0a 00 00 +01 00 09 00 01 +01 00 08 00 22 +01 00 0a 00 01 +01 00 0a 00 00 +01 00 09 00 02 +01 00 08 00 33 +01 00 0a 00 01 +01 00 0a 00 00 +01 00 09 00 03 +01 00 08 00 44 +01 00 0a 00 01 +01 00 0a 00 00 +01 00 09 00 04 +01 00 08 00 55 +01 00 0a 00 01 +01 00 0a 00 00 +01 00 09 00 05 +01 00 08 00 66 +01 00 0a 00 01 +01 00 0a 00 00 + +// Transmit a 60 byte frame 3 times - and expect them to be received again! +20 00 3C 00 03 + +// Wait (indefinitely) for missing Rx packets +22 00 00 + +// Write 1 to register 7, MAC_tx_add_en +// This turns on the Tx Source MAC address replacement mechanism +01 00 07 00 01 + +// Transmit a 60 byte frame 3 times - and expect them to be received again with Alternate header! +26 00 3C 00 03 + +// Wait (indefinitely) for missing Rx packets +22 00 00 diff --git a/eth/bench/verilog/xlnx_glbl.v b/eth/bench/verilog/xlnx_glbl.v new file mode 100644 index 000000000..662a60e35 --- /dev/null +++ b/eth/bench/verilog/xlnx_glbl.v @@ -0,0 +1,29 @@ +module xlnx_glbl +( + GSR, + GTS +); + + //-------------------------------------------------------------------------- + // Parameters + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + // IO declarations + //-------------------------------------------------------------------------- + + output GSR; + output GTS; + + //-------------------------------------------------------------------------- + // Local declarations + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + // Internal declarations + //-------------------------------------------------------------------------- + + assign GSR = 0; + assign GTS = 0; + +endmodule diff --git a/eth/demo/verilog/RAMB16_S1_S2.v b/eth/demo/verilog/RAMB16_S1_S2.v new file mode 100644 index 000000000..758760b95 --- /dev/null +++ b/eth/demo/verilog/RAMB16_S1_S2.v @@ -0,0 +1,1535 @@ +// $Header: /devl/xcs/repo/env/Databases/CAEInterfaces/verunilibs/data/unisims/RAMB16_S1_S2.v,v 1.10 2005/03/14 22:54:41 wloo Exp $ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 1995/2005 Xilinx, Inc. +// All Right Reserved. +/////////////////////////////////////////////////////////////////////////////// +// ____ ____ +// / /\/ / +// /___/ \ / Vendor : Xilinx +// \ \ \/ Version : 8.1i (I.13) +// \ \ Description : Xilinx Functional Simulation Library Component +// / / 16K-Bit Data and 2K-Bit Parity Dual Port Block RAM +// /___/ /\ Filename : RAMB16_S1_S2.v +// \ \ / \ Timestamp : Thu Mar 10 16:43:35 PST 2005 +// \___\/\___\ +// +// Revision: +// 03/23/04 - Initial version. +// End Revision + +`ifdef legacy_model + +`timescale 1 ps / 1 ps + +module RAMB16_S1_S2 (DOA, DOB, ADDRA, ADDRB, CLKA, CLKB, DIA, DIB, ENA, ENB, SSRA, SSRB, WEA, WEB); + + parameter INIT_A = 1'h0; + parameter INIT_B = 2'h0; + parameter SRVAL_A = 1'h0; + parameter SRVAL_B = 2'h0; + parameter WRITE_MODE_A = "WRITE_FIRST"; + parameter WRITE_MODE_B = "WRITE_FIRST"; + parameter SIM_COLLISION_CHECK = "ALL"; + localparam SETUP_ALL = 1000; + localparam SETUP_READ_FIRST = 3000; + + parameter INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_10 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_11 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_12 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_13 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_14 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_15 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_16 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_17 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_18 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_19 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1A = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1B = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1C = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1D = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1E = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_20 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_21 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_22 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_23 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_24 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_25 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_26 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_27 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_28 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_29 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2A = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2B = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2C = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2D = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2E = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_30 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_31 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_32 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_33 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_34 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_35 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_36 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_37 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_38 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_39 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3A = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3B = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3C = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3D = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3E = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + + output [0:0] DOA; + reg [0:0] doa_out; + wire doa_out0; + + input [13:0] ADDRA; + input [0:0] DIA; + input ENA, CLKA, WEA, SSRA; + + output [1:0] DOB; + reg [1:0] dob_out; + wire dob_out0, dob_out1; + + input [12:0] ADDRB; + input [1:0] DIB; + input ENB, CLKB, WEB, SSRB; + + reg [18431:0] mem; + reg [8:0] count; + reg [1:0] wr_mode_a, wr_mode_b; + + reg [5:0] dmi, dbi; + reg [5:0] pmi, pbi; + + wire [13:0] addra_int; + reg [13:0] addra_reg; + wire [0:0] dia_int; + wire ena_int, clka_int, wea_int, ssra_int; + reg ena_reg, wea_reg, ssra_reg; + wire [12:0] addrb_int; + reg [12:0] addrb_reg; + wire [1:0] dib_int; + wire enb_int, clkb_int, web_int, ssrb_int; + reg display_flag; + reg enb_reg, web_reg, ssrb_reg; + + time time_clka, time_clkb; + time time_clka_clkb; + time time_clkb_clka; + + reg setup_all_a_b; + reg setup_all_b_a; + reg setup_zero; + reg setup_rf_a_b; + reg setup_rf_b_a; + reg [1:0] data_collision, data_collision_a_b, data_collision_b_a; + reg memory_collision, memory_collision_a_b, memory_collision_b_a; + reg address_collision, address_collision_a_b, address_collision_b_a; + reg change_clka; + reg change_clkb; + + wire [14:0] data_addra_int; + wire [14:0] data_addra_reg; + wire [14:0] data_addrb_int; + wire [14:0] data_addrb_reg; + wire [15:0] parity_addra_int; + wire [15:0] parity_addra_reg; + wire [15:0] parity_addrb_int; + wire [15:0] parity_addrb_reg; + + tri0 GSR = glbl.GSR; + + always @(GSR) + if (GSR) begin + assign doa_out = INIT_A[0:0]; + assign dob_out = INIT_B[1:0]; + end + else begin + deassign doa_out; + deassign dob_out; + end + + buf b_doa_out0 (doa_out0, doa_out[0]); + buf b_dob_out0 (dob_out0, dob_out[0]); + buf b_dob_out1 (dob_out1, dob_out[1]); + + buf b_doa0 (DOA[0], doa_out0); + buf b_dob0 (DOB[0], dob_out0); + buf b_dob1 (DOB[1], dob_out1); + + buf b_addra_0 (addra_int[0], ADDRA[0]); + buf b_addra_1 (addra_int[1], ADDRA[1]); + buf b_addra_2 (addra_int[2], ADDRA[2]); + buf b_addra_3 (addra_int[3], ADDRA[3]); + buf b_addra_4 (addra_int[4], ADDRA[4]); + buf b_addra_5 (addra_int[5], ADDRA[5]); + buf b_addra_6 (addra_int[6], ADDRA[6]); + buf b_addra_7 (addra_int[7], ADDRA[7]); + buf b_addra_8 (addra_int[8], ADDRA[8]); + buf b_addra_9 (addra_int[9], ADDRA[9]); + buf b_addra_10 (addra_int[10], ADDRA[10]); + buf b_addra_11 (addra_int[11], ADDRA[11]); + buf b_addra_12 (addra_int[12], ADDRA[12]); + buf b_addra_13 (addra_int[13], ADDRA[13]); + buf b_dia_0 (dia_int[0], DIA[0]); + buf b_ena (ena_int, ENA); + buf b_clka (clka_int, CLKA); + buf b_ssra (ssra_int, SSRA); + buf b_wea (wea_int, WEA); + buf b_addrb_0 (addrb_int[0], ADDRB[0]); + buf b_addrb_1 (addrb_int[1], ADDRB[1]); + buf b_addrb_2 (addrb_int[2], ADDRB[2]); + buf b_addrb_3 (addrb_int[3], ADDRB[3]); + buf b_addrb_4 (addrb_int[4], ADDRB[4]); + buf b_addrb_5 (addrb_int[5], ADDRB[5]); + buf b_addrb_6 (addrb_int[6], ADDRB[6]); + buf b_addrb_7 (addrb_int[7], ADDRB[7]); + buf b_addrb_8 (addrb_int[8], ADDRB[8]); + buf b_addrb_9 (addrb_int[9], ADDRB[9]); + buf b_addrb_10 (addrb_int[10], ADDRB[10]); + buf b_addrb_11 (addrb_int[11], ADDRB[11]); + buf b_addrb_12 (addrb_int[12], ADDRB[12]); + buf b_dib_0 (dib_int[0], DIB[0]); + buf b_dib_1 (dib_int[1], DIB[1]); + buf b_enb (enb_int, ENB); + buf b_clkb (clkb_int, CLKB); + buf b_ssrb (ssrb_int, SSRB); + buf b_web (web_int, WEB); + + initial begin + for (count = 0; count < 256; count = count + 1) begin + mem[count] <= INIT_00[count]; + mem[256 * 1 + count] <= INIT_01[count]; + mem[256 * 2 + count] <= INIT_02[count]; + mem[256 * 3 + count] <= INIT_03[count]; + mem[256 * 4 + count] <= INIT_04[count]; + mem[256 * 5 + count] <= INIT_05[count]; + mem[256 * 6 + count] <= INIT_06[count]; + mem[256 * 7 + count] <= INIT_07[count]; + mem[256 * 8 + count] <= INIT_08[count]; + mem[256 * 9 + count] <= INIT_09[count]; + mem[256 * 10 + count] <= INIT_0A[count]; + mem[256 * 11 + count] <= INIT_0B[count]; + mem[256 * 12 + count] <= INIT_0C[count]; + mem[256 * 13 + count] <= INIT_0D[count]; + mem[256 * 14 + count] <= INIT_0E[count]; + mem[256 * 15 + count] <= INIT_0F[count]; + mem[256 * 16 + count] <= INIT_10[count]; + mem[256 * 17 + count] <= INIT_11[count]; + mem[256 * 18 + count] <= INIT_12[count]; + mem[256 * 19 + count] <= INIT_13[count]; + mem[256 * 20 + count] <= INIT_14[count]; + mem[256 * 21 + count] <= INIT_15[count]; + mem[256 * 22 + count] <= INIT_16[count]; + mem[256 * 23 + count] <= INIT_17[count]; + mem[256 * 24 + count] <= INIT_18[count]; + mem[256 * 25 + count] <= INIT_19[count]; + mem[256 * 26 + count] <= INIT_1A[count]; + mem[256 * 27 + count] <= INIT_1B[count]; + mem[256 * 28 + count] <= INIT_1C[count]; + mem[256 * 29 + count] <= INIT_1D[count]; + mem[256 * 30 + count] <= INIT_1E[count]; + mem[256 * 31 + count] <= INIT_1F[count]; + mem[256 * 32 + count] <= INIT_20[count]; + mem[256 * 33 + count] <= INIT_21[count]; + mem[256 * 34 + count] <= INIT_22[count]; + mem[256 * 35 + count] <= INIT_23[count]; + mem[256 * 36 + count] <= INIT_24[count]; + mem[256 * 37 + count] <= INIT_25[count]; + mem[256 * 38 + count] <= INIT_26[count]; + mem[256 * 39 + count] <= INIT_27[count]; + mem[256 * 40 + count] <= INIT_28[count]; + mem[256 * 41 + count] <= INIT_29[count]; + mem[256 * 42 + count] <= INIT_2A[count]; + mem[256 * 43 + count] <= INIT_2B[count]; + mem[256 * 44 + count] <= INIT_2C[count]; + mem[256 * 45 + count] <= INIT_2D[count]; + mem[256 * 46 + count] <= INIT_2E[count]; + mem[256 * 47 + count] <= INIT_2F[count]; + mem[256 * 48 + count] <= INIT_30[count]; + mem[256 * 49 + count] <= INIT_31[count]; + mem[256 * 50 + count] <= INIT_32[count]; + mem[256 * 51 + count] <= INIT_33[count]; + mem[256 * 52 + count] <= INIT_34[count]; + mem[256 * 53 + count] <= INIT_35[count]; + mem[256 * 54 + count] <= INIT_36[count]; + mem[256 * 55 + count] <= INIT_37[count]; + mem[256 * 56 + count] <= INIT_38[count]; + mem[256 * 57 + count] <= INIT_39[count]; + mem[256 * 58 + count] <= INIT_3A[count]; + mem[256 * 59 + count] <= INIT_3B[count]; + mem[256 * 60 + count] <= INIT_3C[count]; + mem[256 * 61 + count] <= INIT_3D[count]; + mem[256 * 62 + count] <= INIT_3E[count]; + mem[256 * 63 + count] <= INIT_3F[count]; + end + address_collision <= 0; + address_collision_a_b <= 0; + address_collision_b_a <= 0; + change_clka <= 0; + change_clkb <= 0; + data_collision <= 0; + data_collision_a_b <= 0; + data_collision_b_a <= 0; + memory_collision <= 0; + memory_collision_a_b <= 0; + memory_collision_b_a <= 0; + setup_all_a_b <= 0; + setup_all_b_a <= 0; + setup_zero <= 0; + setup_rf_a_b <= 0; + setup_rf_b_a <= 0; + end + + assign data_addra_int = addra_int * 1; + assign data_addra_reg = addra_reg * 1; + assign data_addrb_int = addrb_int * 2; + assign data_addrb_reg = addrb_reg * 2; + + + initial begin + + display_flag = 1; + + case (SIM_COLLISION_CHECK) + + "NONE" : begin + assign setup_all_a_b = 1'b0; + assign setup_all_b_a = 1'b0; + assign setup_zero = 1'b0; + assign setup_rf_a_b = 1'b0; + assign setup_rf_b_a = 1'b0; + assign display_flag = 0; + end + "WARNING_ONLY" : begin + assign data_collision = 2'b00; + assign data_collision_a_b = 2'b00; + assign data_collision_b_a = 2'b00; + assign memory_collision = 1'b0; + assign memory_collision_a_b = 1'b0; + assign memory_collision_b_a = 1'b0; + end + "GENERATE_X_ONLY" : begin + assign display_flag = 0; + end + "ALL" : ; + default : begin + $display("Attribute Syntax Error : The Attribute SIM_COLLISION_CHECK on RAMB16_S1_S2 instance %m is set to %s. Legal values for this attribute are ALL, NONE, WARNING_ONLY or GENERATE_X_ONLY.", SIM_COLLISION_CHECK); + $finish; + end + + endcase // case(SIM_COLLISION_CHECK) + + end // initial begin + + + always @(posedge clka_int) begin + time_clka = $time; + #0 time_clkb_clka = time_clka - time_clkb; + change_clka = ~change_clka; + end + + always @(posedge clkb_int) begin + time_clkb = $time; + #0 time_clka_clkb = time_clkb - time_clka; + change_clkb = ~change_clkb; + end + + always @(change_clkb) begin + if ((0 < time_clka_clkb) && (time_clka_clkb < SETUP_ALL)) + setup_all_a_b = 1; + if ((0 < time_clka_clkb) && (time_clka_clkb < SETUP_READ_FIRST)) + setup_rf_a_b = 1; + end + + always @(change_clka) begin + if ((0 < time_clkb_clka) && (time_clkb_clka < SETUP_ALL)) + setup_all_b_a = 1; + if ((0 < time_clkb_clka) && (time_clkb_clka < SETUP_READ_FIRST)) + setup_rf_b_a = 1; + end + + always @(change_clkb or change_clka) begin + if ((time_clkb_clka == 0) && (time_clka_clkb == 0)) + setup_zero = 1; + end + + always @(posedge setup_zero) begin + if ((ena_int == 1) && (wea_int == 1) && + (enb_int == 1) && (web_int == 1) && + (data_addra_int[14:1] == data_addrb_int[14:1])) + memory_collision <= 1; + end + + always @(posedge setup_all_a_b or posedge setup_rf_a_b) begin + if ((ena_reg == 1) && (wea_reg == 1) && + (enb_int == 1) && (web_int == 1) && + (data_addra_reg[14:1] == data_addrb_int[14:1])) + memory_collision_a_b <= 1; + end + + always @(posedge setup_all_b_a or posedge setup_rf_b_a) begin + if ((ena_int == 1) && (wea_int == 1) && + (enb_reg == 1) && (web_reg == 1) && + (data_addra_int[14:1] == data_addrb_reg[14:1])) + memory_collision_b_a <= 1; + end + + always @(posedge setup_all_a_b) begin + if (data_addra_reg[14:1] == data_addrb_int[14:1]) begin + if ((ena_reg == 1) && (enb_int == 1)) begin + case ({wr_mode_a, wr_mode_b, wea_reg, web_int}) + 6'b000011 : begin data_collision_a_b <= 2'b11; display_wa_wb; end + 6'b000111 : begin data_collision_a_b <= 2'b11; display_wa_wb; end + 6'b001011 : begin data_collision_a_b <= 2'b10; display_wa_wb; end +// 6'b010011 : begin data_collision_a_b <= 2'b00; display_wa_wb; end +// 6'b010111 : begin data_collision_a_b <= 2'b00; display_wa_wb; end +// 6'b011011 : begin data_collision_a_b <= 2'b00; display_wa_wb; end + 6'b100011 : begin data_collision_a_b <= 2'b01; display_wa_wb; end + 6'b100111 : begin data_collision_a_b <= 2'b01; display_wa_wb; end + 6'b101011 : begin display_wa_wb; end + 6'b000001 : begin data_collision_a_b <= 2'b10; display_ra_wb; end +// 6'b000101 : begin data_collision_a_b <= 2'b00; display_ra_wb; end + 6'b001001 : begin data_collision_a_b <= 2'b10; display_ra_wb; end + 6'b010001 : begin data_collision_a_b <= 2'b10; display_ra_wb; end +// 6'b010101 : begin data_collision_a_b <= 2'b00; display_ra_wb; end + 6'b011001 : begin data_collision_a_b <= 2'b10; display_ra_wb; end + 6'b100001 : begin data_collision_a_b <= 2'b10; display_ra_wb; end +// 6'b100101 : begin data_collision_a_b <= 2'b00; display_ra_wb; end + 6'b101001 : begin data_collision_a_b <= 2'b10; display_ra_wb; end + 6'b000010 : begin data_collision_a_b <= 2'b01; display_wa_rb; end + 6'b000110 : begin data_collision_a_b <= 2'b01; display_wa_rb; end + 6'b001010 : begin data_collision_a_b <= 2'b01; display_wa_rb; end +// 6'b010010 : begin data_collision_a_b <= 2'b00; display_wa_rb; end +// 6'b010110 : begin data_collision_a_b <= 2'b00; display_wa_rb; end +// 6'b011010 : begin data_collision_a_b <= 2'b00; display_wa_rb; end + 6'b100010 : begin data_collision_a_b <= 2'b01; display_wa_rb; end + 6'b100110 : begin data_collision_a_b <= 2'b01; display_wa_rb; end + 6'b101010 : begin data_collision_a_b <= 2'b01; display_wa_rb; end + endcase + end + end + setup_all_a_b <= 0; + end + + + always @(posedge setup_all_b_a) begin + if (data_addra_int[14:1] == data_addrb_reg[14:1]) begin + if ((ena_int == 1) && (enb_reg == 1)) begin + case ({wr_mode_a, wr_mode_b, wea_int, web_reg}) + 6'b000011 : begin data_collision_b_a <= 2'b11; display_wa_wb; end +// 6'b000111 : begin data_collision_b_a <= 2'b00; display_wa_wb; end + 6'b001011 : begin data_collision_b_a <= 2'b10; display_wa_wb; end + 6'b010011 : begin data_collision_b_a <= 2'b11; display_wa_wb; end +// 6'b010111 : begin data_collision_b_a <= 2'b00; display_wa_wb; end + 6'b011011 : begin data_collision_b_a <= 2'b10; display_wa_wb; end + 6'b100011 : begin data_collision_b_a <= 2'b01; display_wa_wb; end + 6'b100111 : begin data_collision_b_a <= 2'b01; display_wa_wb; end + 6'b101011 : begin display_wa_wb; end + 6'b000001 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b000101 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b001001 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b010001 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b010101 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b011001 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b100001 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b100101 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b101001 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b000010 : begin data_collision_b_a <= 2'b01; display_wa_rb; end + 6'b000110 : begin data_collision_b_a <= 2'b01; display_wa_rb; end + 6'b001010 : begin data_collision_b_a <= 2'b01; display_wa_rb; end +// 6'b010010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b010110 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b011010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end + 6'b100010 : begin data_collision_b_a <= 2'b01; display_wa_rb; end + 6'b100110 : begin data_collision_b_a <= 2'b01; display_wa_rb; end + 6'b101010 : begin data_collision_b_a <= 2'b01; display_wa_rb; end + endcase + end + end + setup_all_b_a <= 0; + end + + + always @(posedge setup_zero) begin + if (data_addra_int[14:1] == data_addrb_int[14:1]) begin + if ((ena_int == 1) && (enb_int == 1)) begin + case ({wr_mode_a, wr_mode_b, wea_int, web_int}) + 6'b000011 : begin data_collision <= 2'b11; display_wa_wb; end + 6'b000111 : begin data_collision <= 2'b11; display_wa_wb; end + 6'b001011 : begin data_collision <= 2'b10; display_wa_wb; end + 6'b010011 : begin data_collision <= 2'b11; display_wa_wb; end + 6'b010111 : begin data_collision <= 2'b11; display_wa_wb; end + 6'b011011 : begin data_collision <= 2'b10; display_wa_wb; end + 6'b100011 : begin data_collision <= 2'b01; display_wa_wb; end + 6'b100111 : begin data_collision <= 2'b01; display_wa_wb; end + 6'b101011 : begin display_wa_wb; end + 6'b000001 : begin data_collision <= 2'b10; display_ra_wb; end +// 6'b000101 : begin data_collision <= 2'b00; display_ra_wb; end + 6'b001001 : begin data_collision <= 2'b10; display_ra_wb; end + 6'b010001 : begin data_collision <= 2'b10; display_ra_wb; end +// 6'b010101 : begin data_collision <= 2'b00; display_ra_wb; end + 6'b011001 : begin data_collision <= 2'b10; display_ra_wb; end + 6'b100001 : begin data_collision <= 2'b10; display_ra_wb; end +// 6'b100101 : begin data_collision <= 2'b00; display_ra_wb; end + 6'b101001 : begin data_collision <= 2'b10; display_ra_wb; end + 6'b000010 : begin data_collision <= 2'b01; display_wa_rb; end + 6'b000110 : begin data_collision <= 2'b01; display_wa_rb; end + 6'b001010 : begin data_collision <= 2'b01; display_wa_rb; end +// 6'b010010 : begin data_collision <= 2'b00; display_wa_rb; end +// 6'b010110 : begin data_collision <= 2'b00; display_wa_rb; end +// 6'b011010 : begin data_collision <= 2'b00; display_wa_rb; end + 6'b100010 : begin data_collision <= 2'b01; display_wa_rb; end + 6'b100110 : begin data_collision <= 2'b01; display_wa_rb; end + 6'b101010 : begin data_collision <= 2'b01; display_wa_rb; end + endcase + end + end + setup_zero <= 0; + end + + task display_ra_wb; + begin + if (display_flag) + $display("Memory Collision Error on RAMB16_S1_S2:%m at simulation time %.3f ns\nA read was performed on address %h (hex) of Port A while a write was requested to the same address on Port B. The write will be successful however the read value on Port A is unknown until the next CLKA cycle.", $time/1000.0, addra_int); + end + endtask + + task display_wa_rb; + begin + if (display_flag) + $display("Memory Collision Error on RAMB16_S1_S2:%m at simulation time %.3f ns\nA read was performed on address %h (hex) of Port B while a write was requested to the same address on Port A. The write will be successful however the read value on Port B is unknown until the next CLKB cycle.", $time/1000.0, addrb_int); + end + endtask + + task display_wa_wb; + begin + if (display_flag) + $display("Memory Collision Error on RAMB16_S1_S2:%m at simulation time %.3f ns\nA write was requested to the same address simultaneously at both Port A and Port B of the RAM. The contents written to the RAM at address location %h (hex) of Port A and address location %h (hex) of Port B are unknown.", $time/1000.0, addra_int, addrb_int); + end + endtask + + + always @(posedge setup_rf_a_b) begin + if (data_addra_reg[14:1] == data_addrb_int[14:1]) begin + if ((ena_reg == 1) && (enb_int == 1)) begin + case ({wr_mode_a, wr_mode_b, wea_reg, web_int}) +// 6'b000011 : begin data_collision_a_b <= 2'b00; display_wa_wb; end +// 6'b000111 : begin data_collision_a_b <= 2'b00; display_wa_wb; end +// 6'b001011 : begin data_collision_a_b <= 2'b00; display_wa_wb; end + 6'b010011 : begin data_collision_a_b <= 2'b11; display_wa_wb; end + 6'b010111 : begin data_collision_a_b <= 2'b11; display_wa_wb; end + 6'b011011 : begin data_collision_a_b <= 2'b10; display_wa_wb; end +// 6'b100011 : begin data_collision_a_b <= 2'b00; display_wa_wb; end +// 6'b100111 : begin data_collision_a_b <= 2'b00; display_wa_wb; end +// 6'b101011 : begin data_collision_a_b <= 2'b00; display_wa_wb; end +// 6'b000001 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b000101 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b001001 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b010001 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b010101 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b011001 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b100001 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b100101 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b101001 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b000010 : begin data_collision_a_b <= 2'b00; display_wa_rb; end +// 6'b000110 : begin data_collision_a_b <= 2'b00; display_wa_rb; end +// 6'b001010 : begin data_collision_a_b <= 2'b00; display_wa_rb; end + 6'b010010 : begin data_collision_a_b <= 2'b01; display_wa_rb; end + 6'b010110 : begin data_collision_a_b <= 2'b01; display_wa_rb; end + 6'b011010 : begin data_collision_a_b <= 2'b01; display_wa_rb; end +// 6'b100010 : begin data_collision_a_b <= 2'b00; display_wa_rb; end +// 6'b100110 : begin data_collision_a_b <= 2'b00; display_wa_rb; end +// 6'b101010 : begin data_collision_a_b <= 2'b00; display_wa_rb; end + endcase + end + end + setup_rf_a_b <= 0; + end + + + always @(posedge setup_rf_b_a) begin + if (data_addra_int[14:1] == data_addrb_reg[14:1]) begin + if ((ena_int == 1) && (enb_reg == 1)) begin + case ({wr_mode_a, wr_mode_b, wea_int, web_reg}) +// 6'b000011 : begin data_collision_b_a <= 2'b00; display_wa_wb; end + 6'b000111 : begin data_collision_b_a <= 2'b11; display_wa_wb; end +// 6'b001011 : begin data_collision_b_a <= 2'b00; display_wa_wb; end +// 6'b010011 : begin data_collision_b_a <= 2'b00; display_wa_wb; end + 6'b010111 : begin data_collision_b_a <= 2'b11; display_wa_wb; end +// 6'b011011 : begin data_collision_b_a <= 2'b00; display_wa_wb; end +// 6'b100011 : begin data_collision_b_a <= 2'b00; display_wa_wb; end + 6'b100111 : begin data_collision_b_a <= 2'b01; display_wa_wb; end +// 6'b101011 : begin data_collision_b_a <= 2'b00; display_wa_wb; end +// 6'b000001 : begin data_collision_b_a <= 2'b00; display_ra_wb; end + 6'b000101 : begin data_collision_b_a <= 2'b10; display_ra_wb; end +// 6'b001001 : begin data_collision_b_a <= 2'b00; display_ra_wb; end +// 6'b010001 : begin data_collision_b_a <= 2'b00; display_ra_wb; end + 6'b010101 : begin data_collision_b_a <= 2'b10; display_ra_wb; end +// 6'b011001 : begin data_collision_b_a <= 2'b00; display_ra_wb; end +// 6'b100001 : begin data_collision_b_a <= 2'b00; display_ra_wb; end + 6'b100101 : begin data_collision_b_a <= 2'b10; display_ra_wb; end +// 6'b101001 : begin data_collision_b_a <= 2'b00; display_ra_wb; end +// 6'b000010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b000110 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b001010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b010010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b010110 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b011010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b100010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b100110 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b101010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end + endcase + end + end + setup_rf_b_a <= 0; + end + + + always @(posedge clka_int) begin + addra_reg <= addra_int; + ena_reg <= ena_int; + ssra_reg <= ssra_int; + wea_reg <= wea_int; + end + + always @(posedge clkb_int) begin + addrb_reg <= addrb_int; + enb_reg <= enb_int; + ssrb_reg <= ssrb_int; + web_reg <= web_int; + end + + // Data + always @(posedge memory_collision) begin + for (dmi = 0; dmi < 1; dmi = dmi + 1) begin + mem[data_addra_int + dmi] <= 1'bX; + end + memory_collision <= 0; + end + + always @(posedge memory_collision_a_b) begin + for (dmi = 0; dmi < 1; dmi = dmi + 1) begin + mem[data_addra_reg + dmi] <= 1'bX; + end + memory_collision_a_b <= 0; + end + + always @(posedge memory_collision_b_a) begin + for (dmi = 0; dmi < 1; dmi = dmi + 1) begin + mem[data_addra_int + dmi] <= 1'bX; + end + memory_collision_b_a <= 0; + end + + always @(posedge data_collision[1]) begin + if (ssra_int == 0) begin + doa_out <= 1'bX; + end + data_collision[1] <= 0; + end + + always @(posedge data_collision[0]) begin + if (ssrb_int == 0) begin + for (dbi = 0; dbi < 1; dbi = dbi + 1) begin + dob_out[data_addra_int[0 : 0] + dbi] <= 1'bX; + end + end + data_collision[0] <= 0; + end + + always @(posedge data_collision_a_b[1]) begin + if (ssra_reg == 0) begin + doa_out <= 1'bX; + end + data_collision_a_b[1] <= 0; + end + + always @(posedge data_collision_a_b[0]) begin + if (ssrb_int == 0) begin + for (dbi = 0; dbi < 1; dbi = dbi + 1) begin + dob_out[data_addra_reg[0 : 0] + dbi] <= 1'bX; + end + end + data_collision_a_b[0] <= 0; + end + + always @(posedge data_collision_b_a[1]) begin + if (ssra_int == 0) begin + doa_out <= 1'bX; + end + data_collision_b_a[1] <= 0; + end + + always @(posedge data_collision_b_a[0]) begin + if (ssrb_reg == 0) begin + for (dbi = 0; dbi < 1; dbi = dbi + 1) begin + dob_out[data_addra_int[0 : 0] + dbi] <= 1'bX; + end + end + data_collision_b_a[0] <= 0; + end + + + initial begin + case (WRITE_MODE_A) + "WRITE_FIRST" : wr_mode_a <= 2'b00; + "READ_FIRST" : wr_mode_a <= 2'b01; + "NO_CHANGE" : wr_mode_a <= 2'b10; + default : begin + $display("Attribute Syntax Error : The Attribute WRITE_MODE_A on RAMB16_S1_S2 instance %m is set to %s. Legal values for this attribute are WRITE_FIRST, READ_FIRST or NO_CHANGE.", WRITE_MODE_A); + $finish; + end + endcase + end + + initial begin + case (WRITE_MODE_B) + "WRITE_FIRST" : wr_mode_b <= 2'b00; + "READ_FIRST" : wr_mode_b <= 2'b01; + "NO_CHANGE" : wr_mode_b <= 2'b10; + default : begin + $display("Attribute Syntax Error : The Attribute WRITE_MODE_B on RAMB16_S1_S2 instance %m is set to %s. Legal values for this attribute are WRITE_FIRST, READ_FIRST or NO_CHANGE.", WRITE_MODE_B); + $finish; + end + endcase + end + + // Port A + always @(posedge clka_int) begin + if (ena_int == 1'b1) begin + if (ssra_int == 1'b1) begin + doa_out[0] <= SRVAL_A[0]; + end + else begin + if (wea_int == 1'b1) begin + if (wr_mode_a == 2'b00) begin + doa_out <= dia_int; + end + else if (wr_mode_a == 2'b01) begin + doa_out[0] <= mem[data_addra_int + 0]; + end + end + else begin + doa_out[0] <= mem[data_addra_int + 0]; + end + end + end + end + + always @(posedge clka_int) begin + if (ena_int == 1'b1 && wea_int == 1'b1) begin + mem[data_addra_int + 0] <= dia_int[0]; + end + end + + // Port B + always @(posedge clkb_int) begin + if (enb_int == 1'b1) begin + if (ssrb_int == 1'b1) begin + dob_out[0] <= SRVAL_B[0]; + dob_out[1] <= SRVAL_B[1]; + end + else begin + if (web_int == 1'b1) begin + if (wr_mode_b == 2'b00) begin + dob_out <= dib_int; + end + else if (wr_mode_b == 2'b01) begin + dob_out[0] <= mem[data_addrb_int + 0]; + dob_out[1] <= mem[data_addrb_int + 1]; + end + end + else begin + dob_out[0] <= mem[data_addrb_int + 0]; + dob_out[1] <= mem[data_addrb_int + 1]; + end + end + end + end + + always @(posedge clkb_int) begin + if (enb_int == 1'b1 && web_int == 1'b1) begin + mem[data_addrb_int + 0] <= dib_int[0]; + mem[data_addrb_int + 1] <= dib_int[1]; + end + end + + specify + (CLKA *> DOA) = (100, 100); + (CLKB *> DOB) = (100, 100); + endspecify + +endmodule + +`else + +// $Header: /devl/xcs/repo/env/Databases/CAEInterfaces/verunilibs/data/unisims/RAMB16_S1_S2.v,v 1.10 2005/03/14 22:54:41 wloo Exp $ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 1995/2005 Xilinx, Inc. +// All Right Reserved. +/////////////////////////////////////////////////////////////////////////////// +// ____ ____ +// / /\/ / +// /___/ \ / Vendor : Xilinx +// \ \ \/ Version : 8.1i (I.13) +// \ \ Description : Xilinx Timing Simulation Library Component +// / / 16K-Bit Data and 2K-Bit Parity Dual Port Block RAM +// /___/ /\ Filename : RAMB16_S1_S2.v +// \ \ / \ Timestamp : Thu Mar 10 16:44:01 PST 2005 +// \___\/\___\ +// +// Revision: +// 03/23/04 - Initial version. +// 03/10/05 - Initialized outputs. +// End Revision + +`timescale 1 ps/1 ps + +module RAMB16_S1_S2 (DOA, DOB, ADDRA, ADDRB, CLKA, CLKB, DIA, DIB, ENA, ENB, SSRA, SSRB, WEA, WEB); + + parameter INIT_A = 1'h0; + parameter INIT_B = 2'h0; + parameter SRVAL_A = 1'h0; + parameter SRVAL_B = 2'h0; + parameter WRITE_MODE_A = "WRITE_FIRST"; + parameter WRITE_MODE_B = "WRITE_FIRST"; + parameter SIM_COLLISION_CHECK = "ALL"; + localparam SETUP_ALL = 1000; + localparam SETUP_READ_FIRST = 3000; + + parameter INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_10 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_11 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_12 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_13 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_14 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_15 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_16 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_17 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_18 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_19 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1A = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1B = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1C = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1D = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1E = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_20 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_21 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_22 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_23 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_24 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_25 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_26 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_27 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_28 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_29 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2A = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2B = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2C = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2D = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2E = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_30 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_31 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_32 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_33 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_34 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_35 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_36 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_37 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_38 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_39 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3A = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3B = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3C = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3D = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3E = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + + output [0:0] DOA; + output [1:0] DOB; + + input [13:0] ADDRA; + input [0:0] DIA; + input ENA, CLKA, WEA, SSRA; + input [12:0] ADDRB; + input [1:0] DIB; + input ENB, CLKB, WEB, SSRB; + + reg [0:0] doa_out = INIT_A[0:0]; + reg [1:0] dob_out = INIT_B[1:0]; + + reg [1:0] mem [8191:0]; + + reg [8:0] count, countp; + reg [1:0] wr_mode_a, wr_mode_b; + + reg [5:0] dmi, dbi; + reg [5:0] pmi, pbi; + + wire [13:0] addra_int; + reg [13:0] addra_reg; + wire [0:0] dia_int; + wire ena_int, clka_int, wea_int, ssra_int; + reg ena_reg, wea_reg, ssra_reg; + wire [12:0] addrb_int; + reg [12:0] addrb_reg; + wire [1:0] dib_int; + wire enb_int, clkb_int, web_int, ssrb_int; + reg display_flag, output_flag; + reg enb_reg, web_reg, ssrb_reg; + + time time_clka, time_clkb; + time time_clka_clkb; + time time_clkb_clka; + + reg setup_all_a_b; + reg setup_all_b_a; + reg setup_zero; + reg setup_rf_a_b; + reg setup_rf_b_a; + reg [1:0] data_collision, data_collision_a_b, data_collision_b_a; + reg memory_collision, memory_collision_a_b, memory_collision_b_a; + reg change_clka; + reg change_clkb; + + wire [14:0] data_addra_int; + wire [14:0] data_addra_reg; + wire [14:0] data_addrb_int; + wire [14:0] data_addrb_reg; + + wire dia_enable = ena_int && wea_int; + wire dib_enable = enb_int && web_int; + + tri0 GSR = glbl.GSR; + wire gsr_int; + + buf b_gsr (gsr_int, GSR); + + buf b_doa [0:0] (DOA, doa_out); + buf b_addra [13:0] (addra_int, ADDRA); + buf b_dia [0:0] (dia_int, DIA); + buf b_ena (ena_int, ENA); + buf b_clka (clka_int, CLKA); + buf b_ssra (ssra_int, SSRA); + buf b_wea (wea_int, WEA); + + buf b_dob [1:0] (DOB, dob_out); + buf b_addrb [12:0] (addrb_int, ADDRB); + buf b_dib [1:0] (dib_int, DIB); + buf b_enb (enb_int, ENB); + buf b_clkb (clkb_int, CLKB); + buf b_ssrb (ssrb_int, SSRB); + buf b_web (web_int, WEB); + + + always @(gsr_int) + if (gsr_int) begin + assign {doa_out} = INIT_A; + assign {dob_out} = INIT_B; + end + else begin + deassign doa_out; + deassign dob_out; + end + + + initial begin + + for (count = 0; count < 128; count = count + 1) begin + mem[count] = INIT_00[(count * 2) +: 2]; + mem[128 * 1 + count] = INIT_01[(count * 2) +: 2]; + mem[128 * 2 + count] = INIT_02[(count * 2) +: 2]; + mem[128 * 3 + count] = INIT_03[(count * 2) +: 2]; + mem[128 * 4 + count] = INIT_04[(count * 2) +: 2]; + mem[128 * 5 + count] = INIT_05[(count * 2) +: 2]; + mem[128 * 6 + count] = INIT_06[(count * 2) +: 2]; + mem[128 * 7 + count] = INIT_07[(count * 2) +: 2]; + mem[128 * 8 + count] = INIT_08[(count * 2) +: 2]; + mem[128 * 9 + count] = INIT_09[(count * 2) +: 2]; + mem[128 * 10 + count] = INIT_0A[(count * 2) +: 2]; + mem[128 * 11 + count] = INIT_0B[(count * 2) +: 2]; + mem[128 * 12 + count] = INIT_0C[(count * 2) +: 2]; + mem[128 * 13 + count] = INIT_0D[(count * 2) +: 2]; + mem[128 * 14 + count] = INIT_0E[(count * 2) +: 2]; + mem[128 * 15 + count] = INIT_0F[(count * 2) +: 2]; + mem[128 * 16 + count] = INIT_10[(count * 2) +: 2]; + mem[128 * 17 + count] = INIT_11[(count * 2) +: 2]; + mem[128 * 18 + count] = INIT_12[(count * 2) +: 2]; + mem[128 * 19 + count] = INIT_13[(count * 2) +: 2]; + mem[128 * 20 + count] = INIT_14[(count * 2) +: 2]; + mem[128 * 21 + count] = INIT_15[(count * 2) +: 2]; + mem[128 * 22 + count] = INIT_16[(count * 2) +: 2]; + mem[128 * 23 + count] = INIT_17[(count * 2) +: 2]; + mem[128 * 24 + count] = INIT_18[(count * 2) +: 2]; + mem[128 * 25 + count] = INIT_19[(count * 2) +: 2]; + mem[128 * 26 + count] = INIT_1A[(count * 2) +: 2]; + mem[128 * 27 + count] = INIT_1B[(count * 2) +: 2]; + mem[128 * 28 + count] = INIT_1C[(count * 2) +: 2]; + mem[128 * 29 + count] = INIT_1D[(count * 2) +: 2]; + mem[128 * 30 + count] = INIT_1E[(count * 2) +: 2]; + mem[128 * 31 + count] = INIT_1F[(count * 2) +: 2]; + mem[128 * 32 + count] = INIT_20[(count * 2) +: 2]; + mem[128 * 33 + count] = INIT_21[(count * 2) +: 2]; + mem[128 * 34 + count] = INIT_22[(count * 2) +: 2]; + mem[128 * 35 + count] = INIT_23[(count * 2) +: 2]; + mem[128 * 36 + count] = INIT_24[(count * 2) +: 2]; + mem[128 * 37 + count] = INIT_25[(count * 2) +: 2]; + mem[128 * 38 + count] = INIT_26[(count * 2) +: 2]; + mem[128 * 39 + count] = INIT_27[(count * 2) +: 2]; + mem[128 * 40 + count] = INIT_28[(count * 2) +: 2]; + mem[128 * 41 + count] = INIT_29[(count * 2) +: 2]; + mem[128 * 42 + count] = INIT_2A[(count * 2) +: 2]; + mem[128 * 43 + count] = INIT_2B[(count * 2) +: 2]; + mem[128 * 44 + count] = INIT_2C[(count * 2) +: 2]; + mem[128 * 45 + count] = INIT_2D[(count * 2) +: 2]; + mem[128 * 46 + count] = INIT_2E[(count * 2) +: 2]; + mem[128 * 47 + count] = INIT_2F[(count * 2) +: 2]; + mem[128 * 48 + count] = INIT_30[(count * 2) +: 2]; + mem[128 * 49 + count] = INIT_31[(count * 2) +: 2]; + mem[128 * 50 + count] = INIT_32[(count * 2) +: 2]; + mem[128 * 51 + count] = INIT_33[(count * 2) +: 2]; + mem[128 * 52 + count] = INIT_34[(count * 2) +: 2]; + mem[128 * 53 + count] = INIT_35[(count * 2) +: 2]; + mem[128 * 54 + count] = INIT_36[(count * 2) +: 2]; + mem[128 * 55 + count] = INIT_37[(count * 2) +: 2]; + mem[128 * 56 + count] = INIT_38[(count * 2) +: 2]; + mem[128 * 57 + count] = INIT_39[(count * 2) +: 2]; + mem[128 * 58 + count] = INIT_3A[(count * 2) +: 2]; + mem[128 * 59 + count] = INIT_3B[(count * 2) +: 2]; + mem[128 * 60 + count] = INIT_3C[(count * 2) +: 2]; + mem[128 * 61 + count] = INIT_3D[(count * 2) +: 2]; + mem[128 * 62 + count] = INIT_3E[(count * 2) +: 2]; + mem[128 * 63 + count] = INIT_3F[(count * 2) +: 2]; + end + + + change_clka <= 0; + change_clkb <= 0; + data_collision <= 0; + data_collision_a_b <= 0; + data_collision_b_a <= 0; + memory_collision <= 0; + memory_collision_a_b <= 0; + memory_collision_b_a <= 0; + setup_all_a_b <= 0; + setup_all_b_a <= 0; + setup_zero <= 0; + setup_rf_a_b <= 0; + setup_rf_b_a <= 0; + end + + assign data_addra_int = addra_int * 1; + assign data_addra_reg = addra_reg * 1; + assign data_addrb_int = addrb_int * 2; + assign data_addrb_reg = addrb_reg * 2; + + + initial begin + + display_flag = 1; + output_flag = 1; + + case (SIM_COLLISION_CHECK) + + "NONE" : begin + output_flag = 0; + display_flag = 0; + end + "WARNING_ONLY" : output_flag = 0; + "GENERATE_ONLY" : display_flag = 0; + "ALL" : ; + + default : begin + $display("Attribute Syntax Error : The Attribute SIM_COLLISION_CHECK on RAMB16_S1_S2 instance %m is set to %s. Legal values for this attribute are ALL, NONE, WARNING_ONLY or GENERATE_ONLY.", SIM_COLLISION_CHECK); + $finish; + end + + endcase // case(SIM_COLLISION_CHECK) + + end // initial begin + + + always @(posedge clka_int) begin + if ((output_flag || display_flag)) begin + time_clka = $time; + #0 time_clkb_clka = time_clka - time_clkb; + change_clka = ~change_clka; + end + end + + always @(posedge clkb_int) begin + if ((output_flag || display_flag)) begin + time_clkb = $time; + #0 time_clka_clkb = time_clkb - time_clka; + change_clkb = ~change_clkb; + end + end + + always @(change_clkb) begin + if ((0 < time_clka_clkb) && (time_clka_clkb < SETUP_ALL)) + setup_all_a_b = 1; + if ((0 < time_clka_clkb) && (time_clka_clkb < SETUP_READ_FIRST)) + setup_rf_a_b = 1; + end + + always @(change_clka) begin + if ((0 < time_clkb_clka) && (time_clkb_clka < SETUP_ALL)) + setup_all_b_a = 1; + if ((0 < time_clkb_clka) && (time_clkb_clka < SETUP_READ_FIRST)) + setup_rf_b_a = 1; + end + + always @(change_clkb or change_clka) begin + if ((time_clkb_clka == 0) && (time_clka_clkb == 0)) + setup_zero = 1; + end + + always @(posedge setup_zero) begin + if ((ena_int == 1) && (wea_int == 1) && + (enb_int == 1) && (web_int == 1) && + (data_addra_int[14:1] == data_addrb_int[14:1])) + memory_collision <= 1; + end + + always @(posedge setup_all_a_b or posedge setup_rf_a_b) begin + if ((ena_reg == 1) && (wea_reg == 1) && + (enb_int == 1) && (web_int == 1) && + (data_addra_reg[14:1] == data_addrb_int[14:1])) + memory_collision_a_b <= 1; + end + + always @(posedge setup_all_b_a or posedge setup_rf_b_a) begin + if ((ena_int == 1) && (wea_int == 1) && + (enb_reg == 1) && (web_reg == 1) && + (data_addra_int[14:1] == data_addrb_reg[14:1])) + memory_collision_b_a <= 1; + end + + always @(posedge setup_all_a_b) begin + if (data_addra_reg[14:1] == data_addrb_int[14:1]) begin + if ((ena_reg == 1) && (enb_int == 1)) begin + case ({wr_mode_a, wr_mode_b, wea_reg, web_int}) + 6'b000011 : begin data_collision_a_b <= 2'b11; display_wa_wb; end + 6'b000111 : begin data_collision_a_b <= 2'b11; display_wa_wb; end + 6'b001011 : begin data_collision_a_b <= 2'b10; display_wa_wb; end +// 6'b010011 : begin data_collision_a_b <= 2'b00; display_wa_wb; end +// 6'b010111 : begin data_collision_a_b <= 2'b00; display_wa_wb; end +// 6'b011011 : begin data_collision_a_b <= 2'b00; display_wa_wb; end + 6'b100011 : begin data_collision_a_b <= 2'b01; display_wa_wb; end + 6'b100111 : begin data_collision_a_b <= 2'b01; display_wa_wb; end + 6'b101011 : begin display_wa_wb; end + 6'b000001 : begin data_collision_a_b <= 2'b10; display_ra_wb; end +// 6'b000101 : begin data_collision_a_b <= 2'b00; display_ra_wb; end + 6'b001001 : begin data_collision_a_b <= 2'b10; display_ra_wb; end + 6'b010001 : begin data_collision_a_b <= 2'b10; display_ra_wb; end +// 6'b010101 : begin data_collision_a_b <= 2'b00; display_ra_wb; end + 6'b011001 : begin data_collision_a_b <= 2'b10; display_ra_wb; end + 6'b100001 : begin data_collision_a_b <= 2'b10; display_ra_wb; end +// 6'b100101 : begin data_collision_a_b <= 2'b00; display_ra_wb; end + 6'b101001 : begin data_collision_a_b <= 2'b10; display_ra_wb; end + 6'b000010 : begin data_collision_a_b <= 2'b01; display_wa_rb; end + 6'b000110 : begin data_collision_a_b <= 2'b01; display_wa_rb; end + 6'b001010 : begin data_collision_a_b <= 2'b01; display_wa_rb; end +// 6'b010010 : begin data_collision_a_b <= 2'b00; display_wa_rb; end +// 6'b010110 : begin data_collision_a_b <= 2'b00; display_wa_rb; end +// 6'b011010 : begin data_collision_a_b <= 2'b00; display_wa_rb; end + 6'b100010 : begin data_collision_a_b <= 2'b01; display_wa_rb; end + 6'b100110 : begin data_collision_a_b <= 2'b01; display_wa_rb; end + 6'b101010 : begin data_collision_a_b <= 2'b01; display_wa_rb; end + endcase + end + end + setup_all_a_b <= 0; + end + + + always @(posedge setup_all_b_a) begin + if (data_addra_int[14:1] == data_addrb_reg[14:1]) begin + if ((ena_int == 1) && (enb_reg == 1)) begin + case ({wr_mode_a, wr_mode_b, wea_int, web_reg}) + 6'b000011 : begin data_collision_b_a <= 2'b11; display_wa_wb; end +// 6'b000111 : begin data_collision_b_a <= 2'b00; display_wa_wb; end + 6'b001011 : begin data_collision_b_a <= 2'b10; display_wa_wb; end + 6'b010011 : begin data_collision_b_a <= 2'b11; display_wa_wb; end +// 6'b010111 : begin data_collision_b_a <= 2'b00; display_wa_wb; end + 6'b011011 : begin data_collision_b_a <= 2'b10; display_wa_wb; end + 6'b100011 : begin data_collision_b_a <= 2'b01; display_wa_wb; end + 6'b100111 : begin data_collision_b_a <= 2'b01; display_wa_wb; end + 6'b101011 : begin display_wa_wb; end + 6'b000001 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b000101 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b001001 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b010001 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b010101 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b011001 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b100001 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b100101 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b101001 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b000010 : begin data_collision_b_a <= 2'b01; display_wa_rb; end + 6'b000110 : begin data_collision_b_a <= 2'b01; display_wa_rb; end + 6'b001010 : begin data_collision_b_a <= 2'b01; display_wa_rb; end +// 6'b010010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b010110 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b011010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end + 6'b100010 : begin data_collision_b_a <= 2'b01; display_wa_rb; end + 6'b100110 : begin data_collision_b_a <= 2'b01; display_wa_rb; end + 6'b101010 : begin data_collision_b_a <= 2'b01; display_wa_rb; end + endcase + end + end + setup_all_b_a <= 0; + end + + + always @(posedge setup_zero) begin + if (data_addra_int[14:1] == data_addrb_int[14:1]) begin + if ((ena_int == 1) && (enb_int == 1)) begin + case ({wr_mode_a, wr_mode_b, wea_int, web_int}) + 6'b000011 : begin data_collision <= 2'b11; display_wa_wb; end + 6'b000111 : begin data_collision <= 2'b11; display_wa_wb; end + 6'b001011 : begin data_collision <= 2'b10; display_wa_wb; end + 6'b010011 : begin data_collision <= 2'b11; display_wa_wb; end + 6'b010111 : begin data_collision <= 2'b11; display_wa_wb; end + 6'b011011 : begin data_collision <= 2'b10; display_wa_wb; end + 6'b100011 : begin data_collision <= 2'b01; display_wa_wb; end + 6'b100111 : begin data_collision <= 2'b01; display_wa_wb; end + 6'b101011 : begin display_wa_wb; end + 6'b000001 : begin data_collision <= 2'b10; display_ra_wb; end +// 6'b000101 : begin data_collision <= 2'b00; display_ra_wb; end + 6'b001001 : begin data_collision <= 2'b10; display_ra_wb; end + 6'b010001 : begin data_collision <= 2'b10; display_ra_wb; end +// 6'b010101 : begin data_collision <= 2'b00; display_ra_wb; end + 6'b011001 : begin data_collision <= 2'b10; display_ra_wb; end + 6'b100001 : begin data_collision <= 2'b10; display_ra_wb; end +// 6'b100101 : begin data_collision <= 2'b00; display_ra_wb; end + 6'b101001 : begin data_collision <= 2'b10; display_ra_wb; end + 6'b000010 : begin data_collision <= 2'b01; display_wa_rb; end + 6'b000110 : begin data_collision <= 2'b01; display_wa_rb; end + 6'b001010 : begin data_collision <= 2'b01; display_wa_rb; end +// 6'b010010 : begin data_collision <= 2'b00; display_wa_rb; end +// 6'b010110 : begin data_collision <= 2'b00; display_wa_rb; end +// 6'b011010 : begin data_collision <= 2'b00; display_wa_rb; end + 6'b100010 : begin data_collision <= 2'b01; display_wa_rb; end + 6'b100110 : begin data_collision <= 2'b01; display_wa_rb; end + 6'b101010 : begin data_collision <= 2'b01; display_wa_rb; end + endcase + end + end + setup_zero <= 0; + end + + task display_ra_wb; + begin + if (display_flag) + $display("Memory Collision Error on RAMB16_S1_S2:%m at simulation time %.3f ns\nA read was performed on address %h (hex) of Port A while a write was requested to the same address on Port B. The write will be successful however the read value on Port A is unknown until the next CLKA cycle.", $time/1000.0, addra_int); + end + endtask + + task display_wa_rb; + begin + if (display_flag) + $display("Memory Collision Error on RAMB16_S1_S2:%m at simulation time %.3f ns\nA read was performed on address %h (hex) of Port B while a write was requested to the same address on Port A. The write will be successful however the read value on Port B is unknown until the next CLKB cycle.", $time/1000.0, addrb_int); + end + endtask + + task display_wa_wb; + begin + if (display_flag) + $display("Memory Collision Error on RAMB16_S1_S2:%m at simulation time %.3f ns\nA write was requested to the same address simultaneously at both Port A and Port B of the RAM. The contents written to the RAM at address location %h (hex) of Port A and address location %h (hex) of Port B are unknown.", $time/1000.0, addra_int, addrb_int); + end + endtask + + + always @(posedge setup_rf_a_b) begin + if (data_addra_reg[14:1] == data_addrb_int[14:1]) begin + if ((ena_reg == 1) && (enb_int == 1)) begin + case ({wr_mode_a, wr_mode_b, wea_reg, web_int}) +// 6'b000011 : begin data_collision_a_b <= 2'b00; display_wa_wb; end +// 6'b000111 : begin data_collision_a_b <= 2'b00; display_wa_wb; end +// 6'b001011 : begin data_collision_a_b <= 2'b00; display_wa_wb; end + 6'b010011 : begin data_collision_a_b <= 2'b11; display_wa_wb; end + 6'b010111 : begin data_collision_a_b <= 2'b11; display_wa_wb; end + 6'b011011 : begin data_collision_a_b <= 2'b10; display_wa_wb; end +// 6'b100011 : begin data_collision_a_b <= 2'b00; display_wa_wb; end +// 6'b100111 : begin data_collision_a_b <= 2'b00; display_wa_wb; end +// 6'b101011 : begin data_collision_a_b <= 2'b00; display_wa_wb; end +// 6'b000001 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b000101 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b001001 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b010001 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b010101 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b011001 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b100001 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b100101 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b101001 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b000010 : begin data_collision_a_b <= 2'b00; display_wa_rb; end +// 6'b000110 : begin data_collision_a_b <= 2'b00; display_wa_rb; end +// 6'b001010 : begin data_collision_a_b <= 2'b00; display_wa_rb; end + 6'b010010 : begin data_collision_a_b <= 2'b01; display_wa_rb; end + 6'b010110 : begin data_collision_a_b <= 2'b01; display_wa_rb; end + 6'b011010 : begin data_collision_a_b <= 2'b01; display_wa_rb; end +// 6'b100010 : begin data_collision_a_b <= 2'b00; display_wa_rb; end +// 6'b100110 : begin data_collision_a_b <= 2'b00; display_wa_rb; end +// 6'b101010 : begin data_collision_a_b <= 2'b00; display_wa_rb; end + endcase + end + end + setup_rf_a_b <= 0; + end + + + always @(posedge setup_rf_b_a) begin + if (data_addra_int[14:1] == data_addrb_reg[14:1]) begin + if ((ena_int == 1) && (enb_reg == 1)) begin + case ({wr_mode_a, wr_mode_b, wea_int, web_reg}) +// 6'b000011 : begin data_collision_b_a <= 2'b00; display_wa_wb; end + 6'b000111 : begin data_collision_b_a <= 2'b11; display_wa_wb; end +// 6'b001011 : begin data_collision_b_a <= 2'b00; display_wa_wb; end +// 6'b010011 : begin data_collision_b_a <= 2'b00; display_wa_wb; end + 6'b010111 : begin data_collision_b_a <= 2'b11; display_wa_wb; end +// 6'b011011 : begin data_collision_b_a <= 2'b00; display_wa_wb; end +// 6'b100011 : begin data_collision_b_a <= 2'b00; display_wa_wb; end + 6'b100111 : begin data_collision_b_a <= 2'b01; display_wa_wb; end +// 6'b101011 : begin data_collision_b_a <= 2'b00; display_wa_wb; end +// 6'b000001 : begin data_collision_b_a <= 2'b00; display_ra_wb; end + 6'b000101 : begin data_collision_b_a <= 2'b10; display_ra_wb; end +// 6'b001001 : begin data_collision_b_a <= 2'b00; display_ra_wb; end +// 6'b010001 : begin data_collision_b_a <= 2'b00; display_ra_wb; end + 6'b010101 : begin data_collision_b_a <= 2'b10; display_ra_wb; end +// 6'b011001 : begin data_collision_b_a <= 2'b00; display_ra_wb; end +// 6'b100001 : begin data_collision_b_a <= 2'b00; display_ra_wb; end + 6'b100101 : begin data_collision_b_a <= 2'b10; display_ra_wb; end +// 6'b101001 : begin data_collision_b_a <= 2'b00; display_ra_wb; end +// 6'b000010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b000110 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b001010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b010010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b010110 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b011010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b100010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b100110 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b101010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end + endcase + end + end + setup_rf_b_a <= 0; + end + + + always @(posedge clka_int) begin + if ((output_flag || display_flag)) begin + addra_reg <= addra_int; + ena_reg <= ena_int; + ssra_reg <= ssra_int; + wea_reg <= wea_int; + end + end + + always @(posedge clkb_int) begin + if ((output_flag || display_flag)) begin + addrb_reg <= addrb_int; + enb_reg <= enb_int; + ssrb_reg <= ssrb_int; + web_reg <= web_int; + end + end + + + // Data + always @(posedge memory_collision) begin + if ((output_flag || display_flag)) begin + mem[addra_int[13:1]][addra_int[0:0] * 1 +: 1] <= 1'bx; + memory_collision <= 0; + end + + end + + always @(posedge memory_collision_a_b) begin + if ((output_flag || display_flag)) begin + mem[addra_reg[13:1]][addra_reg[0:0] * 1 +: 1] <= 1'bx; + memory_collision_a_b <= 0; + end + end + + always @(posedge memory_collision_b_a) begin + if ((output_flag || display_flag)) begin + mem[addra_int[13:1]][addra_int[0:0] * 1 +: 1] <= 1'bx; + memory_collision_b_a <= 0; + end + end + + always @(posedge data_collision[1]) begin + if (ssra_int == 0 && output_flag) begin + doa_out <= #100 1'bX; + end + data_collision[1] <= 0; + end + + always @(posedge data_collision[0]) begin + if (ssrb_int == 0 && output_flag) begin + dob_out[addra_int[0:0] * 1 +: 1] <= #100 1'bX; + end + data_collision[0] <= 0; + end + + always @(posedge data_collision_a_b[1]) begin + if (ssra_reg == 0 && output_flag) begin + doa_out <= #100 1'bX; + end + data_collision_a_b[1] <= 0; + end + + always @(posedge data_collision_a_b[0]) begin + if (ssrb_int == 0 && output_flag) begin + dob_out[addra_reg[0:0] * 1 +: 1] <= #100 1'bX; + end + data_collision_a_b[0] <= 0; + end + + always @(posedge data_collision_b_a[1]) begin + if (ssra_int == 0 && output_flag) begin + doa_out <= #100 1'bX; + end + data_collision_b_a[1] <= 0; + end + + always @(posedge data_collision_b_a[0]) begin + if (ssrb_reg == 0 && output_flag) begin + dob_out[addra_int[0:0] * 1 +: 1] <= #100 1'bX; + end + data_collision_b_a[0] <= 0; + end + + + initial begin + case (WRITE_MODE_A) + "WRITE_FIRST" : wr_mode_a <= 2'b00; + "READ_FIRST" : wr_mode_a <= 2'b01; + "NO_CHANGE" : wr_mode_a <= 2'b10; + default : begin + $display("Attribute Syntax Error : The Attribute WRITE_MODE_A on RAMB16_S1_S2 instance %m is set to %s. Legal values for this attribute are WRITE_FIRST, READ_FIRST or NO_CHANGE.", WRITE_MODE_A); + $finish; + end + endcase + end + + initial begin + case (WRITE_MODE_B) + "WRITE_FIRST" : wr_mode_b <= 2'b00; + "READ_FIRST" : wr_mode_b <= 2'b01; + "NO_CHANGE" : wr_mode_b <= 2'b10; + default : begin + $display("Attribute Syntax Error : The Attribute WRITE_MODE_B on RAMB16_S1_S2 instance %m is set to %s. Legal values for this attribute are WRITE_FIRST, READ_FIRST or NO_CHANGE.", WRITE_MODE_B); + $finish; + end + endcase + end + + + // Port A + always @(posedge clka_int) begin + + if (ena_int == 1'b1) begin + + if (ssra_int == 1'b1) begin + {doa_out} <= #100 SRVAL_A; + end + else begin + if (wea_int == 1'b1) begin + if (wr_mode_a == 2'b00) begin + doa_out <= #100 dia_int; + end + else if (wr_mode_a == 2'b01) begin + + doa_out <= #100 mem[addra_int[13:1]][addra_int[0:0] * 1 +: 1]; + + end + end + else begin + + doa_out <= #100 mem[addra_int[13:1]][addra_int[0:0] * 1 +: 1]; + + end + end + + // memory + if (wea_int == 1'b1) begin + mem[addra_int[13:1]][addra_int[0:0] * 1 +: 1] <= dia_int; + end + + end + end + + + // Port B + always @(posedge clkb_int) begin + + if (enb_int == 1'b1) begin + + if (ssrb_int == 1'b1) begin + {dob_out} <= #100 SRVAL_B; + end + else begin + if (web_int == 1'b1) begin + if (wr_mode_b == 2'b00) begin + dob_out <= #100 dib_int; + end + else if (wr_mode_b == 2'b01) begin + dob_out <= #100 mem[addrb_int]; + end + end + else begin + dob_out <= #100 mem[addrb_int]; + end + end + + // memory + if (web_int == 1'b1) begin + mem[addrb_int] <= dib_int; + end + + end + end + + +endmodule + +`endif diff --git a/eth/demo/verilog/demo.ucf b/eth/demo/verilog/demo.ucf new file mode 100644 index 000000000..f3562b46b --- /dev/null +++ b/eth/demo/verilog/demo.ucf @@ -0,0 +1,52 @@ +NET "Reset_n" LOC = "C15"; // PushButton #4 +NET "Clk_100M" LOC = "B15"; +NET "Clk_125M" LOC = "A16"; // GMII only + +NET "RS232_TXD" LOC = "A9"; +NET "RS232_RXD" LOC = "F1"; + +NET "USB_TXD" LOC = "D1"; +NET "USB_RXD" LOC = "A8"; + +NET "PHY_RESET_n" LOC = "E25"; + +NET "PHY_RXC" LOC = "B13"; +NET "PHY_RXD<0>" LOC = "D16"; +NET "PHY_RXD<1>" LOC = "C16"; +NET "PHY_RXD<2>" LOC = "D15"; +NET "PHY_RXD<3>" LOC = "D14"; +NET "PHY_RXD<4>" LOC = "E14"; +NET "PHY_RXD<5>" LOC = "F14"; +NET "PHY_RXD<6>" LOC = "F11"; +NET "PHY_RXD<7>" LOC = "F12"; +NET "PHY_RXDV" LOC = "F13"; +NET "PHY_RXER" LOC = "E13"; + +NET "PHY_GTX_CLK" LOC = "C26"; // GMII only +NET "PHY_TXC" LOC = "A10"; +NET "PHY_TXD<0>" LOC = "H26"; +NET "PHY_TXD<1>" LOC = "H24"; +NET "PHY_TXD<2>" LOC = "G26"; +NET "PHY_TXD<3>" LOC = "G24"; +NET "PHY_TXD<4>" LOC = "F26"; +NET "PHY_TXD<5>" LOC = "F24"; +NET "PHY_TXD<6>" LOC = "E26"; +NET "PHY_TXD<7>" LOC = "E24"; +NET "PHY_TXEN" LOC = "D26"; +NET "PHY_TXER" LOC = "D24"; + +NET "PHY_COL" LOC = "B24"; +NET "PHY_CRS" LOC = "D25"; + +NET "PHY_MDC" LOC = "G25"; +NET "PHY_MDIO" LOC = "H25"; + +NET "LED<1>" LOC = "D13"; // LED #1-4 +NET "LED<2>" LOC = "D12"; +NET "LED<3>" LOC = "C11"; +NET "LED<4>" LOC = "D11"; + +NET "Clk_100M" PERIOD = 10.000 ; # 100 MHz +NET "Clk_125M" PERIOD = 8.000 ; # 125 MHz +NET "PHY_RXC" PERIOD = 8.000 ; # 125 MHz +NET "PHY_TXC" PERIOD = 8.000 ; # 125 MHz diff --git a/eth/demo/verilog/demo.v b/eth/demo/verilog/demo.v new file mode 100644 index 000000000..649903c9a --- /dev/null +++ b/eth/demo/verilog/demo.v @@ -0,0 +1,378 @@ +module demo( + Reset_n, + Clk_100M, + Clk_125M, // GMII only + + RS232_TXD, + RS232_RXD, + + USB_TXD, + USB_RXD, + + //--- 10/100/1000BASE-T Ethernet PHY (MII/GMII) + PHY_RESET_n, + + PHY_RXC, + PHY_RXD, + PHY_RXDV, + PHY_RXER, + + PHY_GTX_CLK, // GMII only + PHY_TXC, + PHY_TXD, + PHY_TXEN, + PHY_TXER, + + PHY_COL, + PHY_CRS, + + PHY_MDC, + PHY_MDIO, + + // Misc. I/Os + LED, + Button +); + + input Reset_n; + input Clk_100M; + input Clk_125M; // GMII + + output RS232_TXD; + input RS232_RXD; + + output USB_TXD; + input USB_RXD; + + //--- 10/100/1000BASE-T Ethernet PHY (MII/GMII) + output PHY_RESET_n; + + input PHY_RXC; + input [7:0] PHY_RXD; + input PHY_RXDV; + input PHY_RXER; + + output PHY_GTX_CLK; // GMII only + input PHY_TXC; + output [7:0] PHY_TXD; + output PHY_TXEN; + output PHY_TXER; + + input PHY_COL; + input PHY_CRS; + + output PHY_MDC; + inout PHY_MDIO; + + // Misc. I/Os + output [1:4] LED; + + input [1:4] Button; + + //------------------------------------------------------------------------- + // Local declarations + //------------------------------------------------------------------------- + + // Rename to "standard" core clock name + wire Clk = Clk_100M; + + reg [27:0] Counter; + always @( negedge Reset_n or posedge Clk ) + if ( ~Reset_n ) + Counter <= 0; + else + Counter <= Counter + 1; + + assign LED[1:4] = Counter[27:24]; + + //------------------------------------------------------------------------- + // Instantiation of sub-modules + //------------------------------------------------------------------------- + + //--- UART ---------------------------------------------------------------- + + wire UART_RXD; + wire UART_TXD; + wire UART_RxValid; + wire [7:0] UART_RxData; + wire UART_TxReady; + wire UART_TxValid; + wire [7:0] UART_TxData; + + demo_uart demo_uart( + .Reset_n( Reset_n ), + .Clk ( Clk ), + + // Interface to UART PHY + .RXD_i( UART_RXD ), + .TXD_o( UART_TXD ), + + // Clk is divided by (Prescaler+1) to generate 16x the bitrate +`ifdef EHDL_SIMULATION + .Prescaler_i( 16'd3 ), // Corresponds to VERY FAST - for simulation only! +`else + .Prescaler_i( 16'd650 ), // Corresponds to 9600 baud (assuming 100 MHz clock) +`endif + + // Pulsed when RxData is valid + .RxValid_o( UART_RxValid ), + .RxData_o ( UART_RxData ), + + // Asserted when ready for a new Tx byte + .TxReady_o( UART_TxReady ), + + // Pulsed when TxData is valid + .TxValid_i( UART_TxValid ), + .TxData_i ( UART_TxData ) + ); + + // Transmit & receive in parallel on either RS232 or USB/RS232 interface +// assign UART_RXD = RS232_RXD & USB_RXD; // RS232 signals are high when inactive + assign UART_RXD = RS232_RXD; + + assign RS232_TXD = UART_TXD; + assign USB_TXD = UART_TXD; + + //--- UART-to-Wishbone Master --------------------------------------------- + + wire WB_STB_ETH; + wire WB_STB_PDM; + wire WB_STB_PG; + wire WB_CYC; + wire [14:0] WB_ADR; + wire WB_WE; + wire [15:0] WB_DAT_Wr; + wire [15:0] WB_DAT_Rd; + wire WB_ACK; + + demo_wishbone_master demo_wishbone_master( + .Reset_n( Reset_n ), + .Clk ( Clk ), + + //--- UART interface + + // Pulsed when RxData_i is valid + .RxValid_i( UART_RxValid ), + .RxData_i ( UART_RxData ), + + // Asserted when ready for a new Tx byte + .TxReady_i( UART_TxReady ), + + // Pulsed when TxData_o is valid + .TxValid_o( UART_TxValid ), + .TxData_o ( UART_TxData ), + + //--- Wishbone interface + .STB_ETH_O( WB_STB_ETH ), + .STB_PDM_O( WB_STB_PDM ), + .STB_PG_O ( WB_STB_PG ), + .CYC_O ( WB_CYC ), + .ADR_O ( WB_ADR ), + .WE_O ( WB_WE ), + .DAT_O ( WB_DAT_Wr ), + .DAT_I ( WB_DAT_Rd ), + .ACK_I ( WB_ACK ) + ); + + //--- Wishbone clients ---------------------------------------------------- + + //--- Packet Descriptor Memory -------------------------------------------- + + wire [15:0] WB_DAT_Rd_PDM; + wire WB_ACK_PDM; + + wire PDM_Rd; + wire [13:0] PDM_Addr; + wire [31:0] PDM_RdData; + + demo_packet_descriptor_memory demo_packet_descriptor_memory( + .Reset_n( Reset_n ), + .Clk ( Clk ), + + //--- Wishbone interface + .STB_I( WB_STB_PDM ), + .CYC_I( WB_CYC ), + .ADR_I( WB_ADR ), + .WE_I ( WB_WE ), + .DAT_I( WB_DAT_Wr ), + .DAT_O( WB_DAT_Rd_PDM ), + .ACK_O( WB_ACK_PDM ), + + //--- Packet Generator interface + // RdData_o is always valid exactly one clock after Addr_i changes + // and Rd_i is asserted + .Rd_i ( PDM_Rd ), + .Addr_i ( PDM_Addr ), + .RdData_o( PDM_RdData ) + ); + + //--- Packet Generator ---------------------------------------------------- + + wire [15:0] WB_DAT_Rd_PG; + wire WB_ACK_PG; + + wire Rx_mac_ra; + wire Rx_mac_rd; + wire [31:0] Rx_mac_data; + wire [1:0] Rx_mac_BE; + wire Rx_mac_pa; + wire Rx_mac_sop; + wire Rx_mac_err; + wire Rx_mac_eop; + + wire Tx_mac_wa; + wire Tx_mac_wr; + wire [31:0] Tx_mac_data; + wire [1:0] Tx_mac_BE; + wire Tx_mac_sop; + wire Tx_mac_eop; + + demo_packet_generator demo_packet_generator( + .Reset_n( Reset_n ), + .Clk ( Clk ), + + //--- Wishbone interface + .STB_I( WB_STB_PG ), + .CYC_I( WB_CYC ), + .ADR_I( WB_ADR[1:0] ), + .WE_I ( WB_WE ), + .DAT_I( WB_DAT_Wr ), + .DAT_O( WB_DAT_Rd_PG ), + .ACK_O( WB_ACK_PG ), + + //--- Packet Descriptor Memory interface + // RdData_i is always valid exactly one clock after Addr_o changes + // and Rd_o is asserted + .Rd_o ( PDM_Rd ), + .Addr_o ( PDM_Addr ), + .RdData_i( PDM_RdData ), + + //--- User (packet) interface + .Rx_mac_ra ( Rx_mac_ra ), + .Rx_mac_rd ( Rx_mac_rd ), + .Rx_mac_data( Rx_mac_data ), + .Rx_mac_BE ( Rx_mac_BE ), + .Rx_mac_pa ( Rx_mac_pa ), + .Rx_mac_sop ( Rx_mac_sop ), + .Rx_mac_err ( Rx_mac_err ), + .Rx_mac_eop ( Rx_mac_eop ), + + .Tx_mac_wa ( Tx_mac_wa ), + .Tx_mac_wr ( Tx_mac_wr ), + .Tx_mac_data( Tx_mac_data ), + .Tx_mac_BE ( Tx_mac_BE ), + .Tx_mac_sop ( Tx_mac_sop ), + .Tx_mac_eop ( Tx_mac_eop ) + ); + + //--- Simple Wishbone client ---------------------------------------------- + + reg [15:0] Reg1; + reg [15:0] Reg2; + + reg WB_ACK_Reg; + reg [15:0] WB_DAT_Reg; + + always @( negedge Reset_n or posedge Clk ) + if ( ~Reset_n ) + begin + WB_ACK_Reg <= 0; + WB_DAT_Reg <= 'b0; + + Reg1 <= 16'h1234; + Reg2 <= 16'hABCD; + end + else + begin + WB_ACK_Reg <= 0; + if ( WB_CYC & ~( WB_STB_ETH | WB_STB_PG | WB_STB_PDM ) ) + begin + WB_ACK_Reg <= 1; + if ( WB_WE ) + begin + if ( WB_ADR[0] ) + Reg2 <= WB_DAT_Wr; + else + Reg1 <= WB_DAT_Wr; + end + else + begin + if ( WB_ADR[0] ) + WB_DAT_Reg <= Reg2; + else + WB_DAT_Reg <= Reg1; + end + end + end + + //--- DUT - Ethernet Core ------------------------------------------------- + + wire [15:0] WB_DAT_Rd_ETH; + wire WB_ACK_ETH; + + wire [2:0] Speed; + + MAC_top dut( + // System signals + .Clk_125M( Clk_125M ), + .Clk_user( Clk ), + .Speed ( Speed ), + + // Wishbone compliant core host interface + .RST_I( ~Reset_n ), + .CLK_I( Clk ), + .STB_I( WB_STB_ETH ), + .CYC_I( WB_CYC ), + .ADR_I( WB_ADR[6:0] ), + .WE_I ( WB_WE ), + .DAT_I( WB_DAT_Wr ), + .DAT_O( WB_DAT_Rd_ETH ), + .ACK_O( WB_ACK_ETH ), + + // User (packet) interface + .Rx_mac_ra ( Rx_mac_ra ), + .Rx_mac_rd ( Rx_mac_rd ), + .Rx_mac_data( Rx_mac_data ), + .Rx_mac_BE ( Rx_mac_BE ), + .Rx_mac_pa ( Rx_mac_pa ), + .Rx_mac_sop ( Rx_mac_sop ), + .Rx_mac_err ( Rx_mac_err ), + .Rx_mac_eop ( Rx_mac_eop ), + + .Tx_mac_wa ( Tx_mac_wa ), + .Tx_mac_wr ( Tx_mac_wr ), + .Tx_mac_data( Tx_mac_data ), + .Tx_mac_BE ( Tx_mac_BE ), + .Tx_mac_sop ( Tx_mac_sop ), + .Tx_mac_eop ( Tx_mac_eop ), + + // PHY interface (GMII/MII) + .Gtx_clk( PHY_GTX_CLK ), // Used only in GMII mode + .Rx_clk ( PHY_RXC ), + .Tx_clk ( PHY_TXC ), // Used only in MII mode + .Tx_er ( PHY_TXER ), + .Tx_en ( PHY_TXEN ), + .Txd ( PHY_TXD ), + .Rx_er ( PHY_RXER ), + .Rx_dv ( PHY_RXDV ), + .Rxd ( PHY_RXD ), + .Crs ( PHY_CRS ), + .Col ( PHY_COL ), + + // MDIO interface (to PHY) + .Mdio( PHY_MDIO ), + .Mdc ( PHY_MDC ) + ); + + //--- Combination of Wishbone read data and acknowledge ------------------- + + assign WB_DAT_Rd = ({16{WB_ACK_Reg}} & WB_DAT_Reg ) | + ({16{WB_ACK_PDM}} & WB_DAT_Rd_PDM) | + ({16{WB_ACK_PG }} & WB_DAT_Rd_PG ) | + ({16{WB_ACK_ETH}} & WB_DAT_Rd_ETH); + + assign WB_ACK = WB_ACK_Reg | WB_ACK_PDM | WB_ACK_PG | WB_ACK_ETH; + + assign PHY_RESET_n = Reset_n; + +endmodule diff --git a/eth/demo/verilog/demo_packet_descriptor_memory.v b/eth/demo/verilog/demo_packet_descriptor_memory.v new file mode 100644 index 000000000..a5588a7d1 --- /dev/null +++ b/eth/demo/verilog/demo_packet_descriptor_memory.v @@ -0,0 +1,384 @@ +module demo_packet_descriptor_memory( + Reset_n, + Clk, + + //--- Wishbone interface + STB_I, + CYC_I, + ADR_I, + WE_I, + DAT_I, + DAT_O, + ACK_O, + + //--- Packet Generator interface + // RdData_o is always valid exactly one clock after Addr_i changes + // and Rd_i is asserted + Rd_i, + Addr_i, + RdData_o +); + + input Reset_n; + input Clk; + + //--- Wishbone interface + input STB_I; + input CYC_I; + input [14:0] ADR_I; + input WE_I; + input [15:0] DAT_I; + output [15:0] DAT_O; + output ACK_O; + + //--- Packet Generator interface + // RdData_o is always valid exactly one clock after Addr_i changes + // and Rd_i is asserted + input Rd_i; + input [13:0] Addr_i; + output [31:0] RdData_o; + + //------------------------------------------------------------------------- + // Local declarations + //------------------------------------------------------------------------- + + reg ACK_O; + + //------------------------------------------------------------------------- + + wire [15:0] WrDataA = DAT_I; + wire [15:0] RdDataA; + wire [31:0] RdDataB; + + assign DAT_O = RdDataA; + assign RdData_o = RdDataB; + + wire WB_Access = STB_I & CYC_I; + wire WB_AccessClock1; + reg WB_AccessClock2; + + assign WB_AccessClock1 = WB_Access & ~WB_AccessClock2; + + always @( negedge Reset_n or posedge Clk ) + if ( ~Reset_n ) + begin + WB_AccessClock2 <= 0; + ACK_O <= 0; + end + else + begin + WB_AccessClock2 <= WB_Access; + ACK_O <= WB_AccessClock1; + end + + //------------------------------------------------------------------------- + // Instantiation of sub-modules + //------------------------------------------------------------------------- + + //--- Instantiation of Xilinx 16 Kbit Dual Port Memory -------------------- + + RAMB16_S1_S2 RAMB16_S1_S2_bit0 ( + .DOA( RdDataA[0] ), + .DOB( { RdDataB[0], RdDataB[16+0] } ), + + .ADDRA( ADR_I[13:0] ), + .DIA ( WrDataA[0] ), + .ENA ( WB_AccessClock1 ), + .CLKA ( Clk ), + .WEA ( WE_I ), + .SSRA ( 1'b0 ), + + .ADDRB( Addr_i[12:0] ), + .DIB ( 2'b00 ), + .ENB ( Rd_i ), + .CLKB ( Clk ), + .WEB ( 1'b0 ), + .SSRB ( 1'b0 ) + ); + + RAMB16_S1_S2 RAMB16_S1_S2_bit1 ( + .DOA( RdDataA[1] ), + .DOB( { RdDataB[1], RdDataB[16+1] } ), + + .ADDRA( ADR_I[13:0] ), + .DIA ( WrDataA[1] ), + .ENA ( WB_AccessClock1 ), + .CLKA ( Clk ), + .WEA ( WE_I ), + .SSRA ( 1'b0 ), + + .ADDRB( Addr_i[12:0] ), + .DIB ( 2'b00 ), + .ENB ( Rd_i ), + .CLKB ( Clk ), + .WEB ( 1'b0 ), + .SSRB ( 1'b0 ) + ); + + RAMB16_S1_S2 RAMB16_S1_S2_bit2 ( + .DOA( RdDataA[2] ), + .DOB( { RdDataB[2], RdDataB[16+2] } ), + + .ADDRA( ADR_I[13:0] ), + .DIA ( WrDataA[2] ), + .ENA ( WB_AccessClock1 ), + .CLKA ( Clk ), + .WEA ( WE_I ), + .SSRA ( 1'b0 ), + + .ADDRB( Addr_i[12:0] ), + .DIB ( 2'b00 ), + .ENB ( Rd_i ), + .CLKB ( Clk ), + .WEB ( 1'b0 ), + .SSRB ( 1'b0 ) + ); + + RAMB16_S1_S2 RAMB16_S1_S2_bit3 ( + .DOA( RdDataA[3] ), + .DOB( { RdDataB[3], RdDataB[16+3] } ), + + .ADDRA( ADR_I[13:0] ), + .DIA ( WrDataA[3] ), + .ENA ( WB_AccessClock1 ), + .CLKA ( Clk ), + .WEA ( WE_I ), + .SSRA ( 1'b0 ), + + .ADDRB( Addr_i[12:0] ), + .DIB ( 2'b00 ), + .ENB ( Rd_i ), + .CLKB ( Clk ), + .WEB ( 1'b0 ), + .SSRB ( 1'b0 ) + ); + + RAMB16_S1_S2 RAMB16_S1_S2_bit4 ( + .DOA( RdDataA[4] ), + .DOB( { RdDataB[4], RdDataB[16+4] } ), + + .ADDRA( ADR_I[13:0] ), + .DIA ( WrDataA[4] ), + .ENA ( WB_AccessClock1 ), + .CLKA ( Clk ), + .WEA ( WE_I ), + .SSRA ( 1'b0 ), + + .ADDRB( Addr_i[12:0] ), + .DIB ( 2'b00 ), + .ENB ( Rd_i ), + .CLKB ( Clk ), + .WEB ( 1'b0 ), + .SSRB ( 1'b0 ) + ); + + RAMB16_S1_S2 RAMB16_S1_S2_bit5 ( + .DOA( RdDataA[5] ), + .DOB( { RdDataB[5], RdDataB[16+5] } ), + + .ADDRA( ADR_I[13:0] ), + .DIA ( WrDataA[5] ), + .ENA ( WB_AccessClock1 ), + .CLKA ( Clk ), + .WEA ( WE_I ), + .SSRA ( 1'b0 ), + + .ADDRB( Addr_i[12:0] ), + .DIB ( 2'b00 ), + .ENB ( Rd_i ), + .CLKB ( Clk ), + .WEB ( 1'b0 ), + .SSRB ( 1'b0 ) + ); + + RAMB16_S1_S2 RAMB16_S1_S2_bit6 ( + .DOA( RdDataA[6] ), + .DOB( { RdDataB[6], RdDataB[16+6] } ), + + .ADDRA( ADR_I[13:0] ), + .DIA ( WrDataA[6] ), + .ENA ( WB_AccessClock1 ), + .CLKA ( Clk ), + .WEA ( WE_I ), + .SSRA ( 1'b0 ), + + .ADDRB( Addr_i[12:0] ), + .DIB ( 2'b00 ), + .ENB ( Rd_i ), + .CLKB ( Clk ), + .WEB ( 1'b0 ), + .SSRB ( 1'b0 ) + ); + + RAMB16_S1_S2 RAMB16_S1_S2_bit7 ( + .DOA( RdDataA[7] ), + .DOB( { RdDataB[7], RdDataB[16+7] } ), + + .ADDRA( ADR_I[13:0] ), + .DIA ( WrDataA[7] ), + .ENA ( WB_AccessClock1 ), + .CLKA ( Clk ), + .WEA ( WE_I ), + .SSRA ( 1'b0 ), + + .ADDRB( Addr_i[12:0] ), + .DIB ( 2'b00 ), + .ENB ( Rd_i ), + .CLKB ( Clk ), + .WEB ( 1'b0 ), + .SSRB ( 1'b0 ) + ); + + RAMB16_S1_S2 RAMB16_S1_S2_bit8 ( + .DOA( RdDataA[8] ), + .DOB( { RdDataB[8], RdDataB[16+8] } ), + + .ADDRA( ADR_I[13:0] ), + .DIA ( WrDataA[8] ), + .ENA ( WB_AccessClock1 ), + .CLKA ( Clk ), + .WEA ( WE_I ), + .SSRA ( 1'b0 ), + + .ADDRB( Addr_i[12:0] ), + .DIB ( 2'b00 ), + .ENB ( Rd_i ), + .CLKB ( Clk ), + .WEB ( 1'b0 ), + .SSRB ( 1'b0 ) + ); + + RAMB16_S1_S2 RAMB16_S1_S2_bit9 ( + .DOA( RdDataA[9] ), + .DOB( { RdDataB[9], RdDataB[16+9] } ), + + .ADDRA( ADR_I[13:0] ), + .DIA ( WrDataA[9] ), + .ENA ( WB_AccessClock1 ), + .CLKA ( Clk ), + .WEA ( WE_I ), + .SSRA ( 1'b0 ), + + .ADDRB( Addr_i[12:0] ), + .DIB ( 2'b00 ), + .ENB ( Rd_i ), + .CLKB ( Clk ), + .WEB ( 1'b0 ), + .SSRB ( 1'b0 ) + ); + + RAMB16_S1_S2 RAMB16_S1_S2_bit10 ( + .DOA( RdDataA[10] ), + .DOB( { RdDataB[10], RdDataB[16+10] } ), + + .ADDRA( ADR_I[13:0] ), + .DIA ( WrDataA[10] ), + .ENA ( WB_AccessClock1 ), + .CLKA ( Clk ), + .WEA ( WE_I ), + .SSRA ( 1'b0 ), + + .ADDRB( Addr_i[12:0] ), + .DIB ( 2'b00 ), + .ENB ( Rd_i ), + .CLKB ( Clk ), + .WEB ( 1'b0 ), + .SSRB ( 1'b0 ) + ); + + RAMB16_S1_S2 RAMB16_S1_S2_bit11 ( + .DOA( RdDataA[11] ), + .DOB( { RdDataB[11], RdDataB[16+11] } ), + + .ADDRA( ADR_I[13:0] ), + .DIA ( WrDataA[11] ), + .ENA ( WB_AccessClock1 ), + .CLKA ( Clk ), + .WEA ( WE_I ), + .SSRA ( 1'b0 ), + + .ADDRB( Addr_i[12:0] ), + .DIB ( 2'b00 ), + .ENB ( Rd_i ), + .CLKB ( Clk ), + .WEB ( 1'b0 ), + .SSRB ( 1'b0 ) + ); + + RAMB16_S1_S2 RAMB16_S1_S2_bit12 ( + .DOA( RdDataA[12] ), + .DOB( { RdDataB[12], RdDataB[16+12] } ), + + .ADDRA( ADR_I[13:0] ), + .DIA ( WrDataA[12] ), + .ENA ( WB_AccessClock1 ), + .CLKA ( Clk ), + .WEA ( WE_I ), + .SSRA ( 1'b0 ), + + .ADDRB( Addr_i[12:0] ), + .DIB ( 2'b00 ), + .ENB ( Rd_i ), + .CLKB ( Clk ), + .WEB ( 1'b0 ), + .SSRB ( 1'b0 ) + ); + + RAMB16_S1_S2 RAMB16_S1_S2_bit13 ( + .DOA( RdDataA[13] ), + .DOB( { RdDataB[13], RdDataB[16+13] } ), + + .ADDRA( ADR_I[13:0] ), + .DIA ( WrDataA[13] ), + .ENA ( WB_AccessClock1 ), + .CLKA ( Clk ), + .WEA ( WE_I ), + .SSRA ( 1'b0 ), + + .ADDRB( Addr_i[12:0] ), + .DIB ( 2'b00 ), + .ENB ( Rd_i ), + .CLKB ( Clk ), + .WEB ( 1'b0 ), + .SSRB ( 1'b0 ) + ); + + RAMB16_S1_S2 RAMB16_S1_S2_bit14 ( + .DOA( RdDataA[14] ), + .DOB( { RdDataB[14], RdDataB[16+14] } ), + + .ADDRA( ADR_I[13:0] ), + .DIA ( WrDataA[14] ), + .ENA ( WB_AccessClock1 ), + .CLKA ( Clk ), + .WEA ( WE_I ), + .SSRA ( 1'b0 ), + + .ADDRB( Addr_i[12:0] ), + .DIB ( 2'b00 ), + .ENB ( Rd_i ), + .CLKB ( Clk ), + .WEB ( 1'b0 ), + .SSRB ( 1'b0 ) + ); + + RAMB16_S1_S2 RAMB16_S1_S2_bit15 ( + .DOA( RdDataA[15] ), + .DOB( { RdDataB[15], RdDataB[16+15] } ), + + .ADDRA( ADR_I[13:0] ), + .DIA ( WrDataA[15] ), + .ENA ( WB_AccessClock1 ), + .CLKA ( Clk ), + .WEA ( WE_I ), + .SSRA ( 1'b0 ), + + .ADDRB( Addr_i[12:0] ), + .DIB ( 2'b00 ), + .ENB ( Rd_i ), + .CLKB ( Clk ), + .WEB ( 1'b0 ), + .SSRB ( 1'b0 ) + ); + +endmodule diff --git a/eth/demo/verilog/demo_packet_generator.v b/eth/demo/verilog/demo_packet_generator.v new file mode 100644 index 000000000..22ad52b4c --- /dev/null +++ b/eth/demo/verilog/demo_packet_generator.v @@ -0,0 +1,274 @@ +module demo_packet_generator( + Reset_n, + Clk, + + //--- Wishbone interface + STB_I, + CYC_I, + ADR_I, + WE_I, + DAT_I, + DAT_O, + ACK_O, + + //--- Packet Descriptor Memory interface + // RdData_i is always valid exactly one clock after Addr_o changes + // and Rd_o is asserted + Rd_o, + Addr_o, + RdData_i, + + //--- User (packet) interface + Rx_mac_ra, + Rx_mac_rd, + Rx_mac_data, + Rx_mac_BE, + Rx_mac_pa, + Rx_mac_sop, + Rx_mac_err, + Rx_mac_eop, + + Tx_mac_wa, + Tx_mac_wr, + Tx_mac_data, + Tx_mac_BE, + Tx_mac_sop, + Tx_mac_eop +); + + input Reset_n; + input Clk; + + //--- Wishbone interface + input STB_I; + input CYC_I; + input [1:0] ADR_I; + input WE_I; + input [15:0] DAT_I; + output [15:0] DAT_O; + output ACK_O; + + //--- Packet Generator interface + // RdData_o is always valid exactly one clock after Addr_o changes + // and Rd_o is asserted + output Rd_o; + output [13:0] Addr_o; + input [31:0] RdData_i; + + //--- User (packet) interface + input Rx_mac_ra; + output Rx_mac_rd; + input [31:0] Rx_mac_data; + input [1:0] Rx_mac_BE; + input Rx_mac_pa; + input Rx_mac_sop; + input Rx_mac_err; + input Rx_mac_eop; + + input Tx_mac_wa; + output Tx_mac_wr; + output [31:0] Tx_mac_data; + output [1:0] Tx_mac_BE; + output Tx_mac_sop; + output Tx_mac_eop; + + //------------------------------------------------------------------------- + // Local declarations + //------------------------------------------------------------------------- + + reg ACK_O; + reg [15:0] DAT_O; + + reg Rd_o; + reg Tx_mac_wr; + reg [1:0] Tx_mac_BE; + reg Tx_mac_sop; + reg Tx_mac_eop; + + //--- Wishbone interface -------------------------------------------------- + + reg [1:0] PG_CFG; + wire PG_Enable = PG_CFG[0]; + + always @( negedge Reset_n or posedge Clk ) + if ( ~Reset_n ) + begin + ACK_O <= 0; + DAT_O <= 'b0; + + PG_CFG <= 2'h0; + end + else + begin + ACK_O <= 0; + if ( CYC_I & STB_I ) + begin + ACK_O <= ~ACK_O; // Generate single cycle pulse! + if ( WE_I ) + begin + PG_CFG <= DAT_I; + end + else + begin + DAT_O[1:0] <= PG_CFG; + end + end + end + + //--- Packet Generator FSM ------------------------------------------------ + + parameter PG_FSM_STATE_IDLE = 3'h0; + parameter PG_FSM_STATE_LD_DESC_1 = 3'h1; + parameter PG_FSM_STATE_LD_DESC_2 = 3'h2; + parameter PG_FSM_STATE_RD_HEADER = 3'h3; + parameter PG_FSM_STATE_PAYLOAD_SEQ_NUMBER = 3'h4; + parameter PG_FSM_STATE_PAYLOAD = 3'h5; + parameter PG_FSM_STATE_DONE = 3'h6; + reg [2:0] PG_FSM_State; + + reg [9:0] DescHigh; // Selects currente descriptor + reg [3:0] DescLow; // Index into a single descriptor (16 entries) + + reg PDM_CFG1_LAST; + reg [3:0] PDM_CFG1_REPEAT; + reg [3:0] PDM_CFG1_HDRLEN; + reg [15:0] PDM_CFG2_PAYLDLEN; + + reg [31:0] Tx_mac_data_reg; + reg WriteHeader; + reg [15:0] PayloadRemaining; + reg [31:0] PacketSequenceNumber; + reg [31:0] Payload; + + always @( negedge Reset_n or posedge Clk ) + if ( ~Reset_n ) + begin + PG_FSM_State <= PG_FSM_STATE_IDLE; + + Rd_o <= 0; + + DescHigh <= 10'b0; + DescLow <= 4'b0; + + Tx_mac_wr <= 0; + Tx_mac_sop <= 0; + Tx_mac_eop <= 0; + Tx_mac_BE <= 2'b00; + + Tx_mac_data_reg <= 32'b0; + WriteHeader <= 0; + PayloadRemaining <= 16'd0; + + PacketSequenceNumber <= 32'd0; + Payload <= 32'h0; + + { PDM_CFG1_HDRLEN, PDM_CFG1_REPEAT, PDM_CFG1_LAST, PDM_CFG2_PAYLDLEN } <= 'b0; + end + else + begin + casez ( PG_FSM_State ) + PG_FSM_STATE_IDLE: + if ( PG_Enable ) + begin + PG_FSM_State <= PG_FSM_STATE_LD_DESC_1; + Rd_o <= 1; + end + else + begin + DescHigh <= 10'b0; + DescLow <= 4'b0; + end + + PG_FSM_STATE_LD_DESC_1: + begin + PG_FSM_State <= PG_FSM_STATE_LD_DESC_2; + + DescLow <= DescLow + 1; + end + + PG_FSM_STATE_LD_DESC_2: + begin + PG_FSM_State <= PG_FSM_STATE_RD_HEADER; + + { PDM_CFG1_LAST, PDM_CFG1_REPEAT, PDM_CFG1_HDRLEN, PDM_CFG2_PAYLDLEN } <= + { RdData_i[31], RdData_i[23:20], RdData_i[19:16], RdData_i[15:0] }; + end + + PG_FSM_STATE_RD_HEADER: + begin + Tx_mac_wr <= 0; + if ( Tx_mac_wa ) + begin + // Space in Tx FIFO - write next header word + DescLow <= DescLow + 1; + Tx_mac_wr <= 1; + Tx_mac_sop <= ( DescLow == 1 ); // Assert SOP on first header word + WriteHeader <= 1; + if ( DescLow == PDM_CFG1_HDRLEN ) + begin + // The requested number of header words has been read + // - proceed to generate packet payload + PG_FSM_State <= PG_FSM_STATE_PAYLOAD_SEQ_NUMBER; + PayloadRemaining <= PDM_CFG2_PAYLDLEN; + end + end + end + + PG_FSM_STATE_PAYLOAD_SEQ_NUMBER: + begin + WriteHeader <= 0; + Tx_mac_data_reg <= PacketSequenceNumber; + Tx_mac_wr <= 0; + Tx_mac_sop <= 0; + if ( Tx_mac_wa ) + begin + Tx_mac_wr <= 1; + PG_FSM_State <= PG_FSM_STATE_PAYLOAD; + Payload <= 32'h01020304; + PayloadRemaining <= PayloadRemaining - 4; + end + end + + PG_FSM_STATE_PAYLOAD: + begin + Tx_mac_data_reg <= Payload; + Tx_mac_wr <= 0; + if ( Tx_mac_wa ) + begin + Tx_mac_wr <= 1; + Tx_mac_data_reg <= Payload; + Payload[31:24] <= Payload[31:24] + 8'h04; + Payload[23:16] <= Payload[23:16] + 8'h04; + Payload[15: 8] <= Payload[15: 8] + 8'h04; + Payload[ 7: 0] <= Payload[ 7: 0] + 8'h04; + PayloadRemaining <= PayloadRemaining - 4; + if ( PayloadRemaining <= 4 ) + begin + PG_FSM_State <= PG_FSM_STATE_DONE; + + Tx_mac_eop <= 1; + // Indicate how many bytes are valid in this last transfer + Tx_mac_BE <= PayloadRemaining[1:0]; + end + end + end + + PG_FSM_STATE_DONE: + begin + // TBD: Add support for REPEAT, NEXT & LAST! + Tx_mac_wr <= 0; + Tx_mac_eop <= 0; + end + endcase + end + + //------------------------------------------------------------------------- + + assign Tx_mac_data = WriteHeader ? + RdData_i : Tx_mac_data_reg; + + assign Addr_o = { DescHigh, DescLow }; + + assign Rx_mac_rd = 0; + +endmodule diff --git a/eth/demo/verilog/demo_uart.v b/eth/demo/verilog/demo_uart.v new file mode 100644 index 000000000..ba4a3c35c --- /dev/null +++ b/eth/demo/verilog/demo_uart.v @@ -0,0 +1,235 @@ +module demo_uart( + Reset_n, + Clk, + + // Interface to UART PHY (RS232 level converter) + RXD_i, + TXD_o, + + // Clk is divided by (Prescaler+1) to generate 16x the bitrate + Prescaler_i, + + // Pulsed when RxData is valid + RxValid_o, + RxData_o, + + // Asserted when ready for a new Tx byte + TxReady_o, + + // Pulsed when TxData is valid + TxValid_i, + TxData_i +); + + input Reset_n; + input Clk; + + // Interface to UART PHY (RS232 level converter) + input RXD_i; + output TXD_o; + + // Clk is divided by (Prescaler+1) to generate 16x the bitrate + input [15:0] Prescaler_i; + + // Pulsed when RxData is valid + output RxValid_o; + output [7:0] RxData_o; + + // Asserted when ready for a new Tx byte + output TxReady_o; + + // Pulsed when TxData is valid + input TxValid_i; + input [7:0] TxData_i; + + //------------------------------------------------------------------------- + // Local declarations + //------------------------------------------------------------------------- + + reg TXD_o; + reg RxValid_o; + reg [7:0] RxData_o; + reg TxReady_o; + + //------------------------------------------------------------------------- + // Instantiation of sub-modules + //------------------------------------------------------------------------- + + //--- Prescaler generating 16x bitrate clock ------------------------------ + + reg Clk_16x; + reg [15:0] Prescaler; + + always @( negedge Reset_n or posedge Clk ) + if ( ~Reset_n ) + begin + Prescaler <= 0; + Clk_16x <= 0; + end + else + begin + if ( Prescaler == Prescaler_i ) + begin + Prescaler <= 0; + Clk_16x <= 1; + end + else + begin + Prescaler <= Prescaler + 1; + Clk_16x <= 0; + end + end + + //--- Transmitter logic --------------------------------------------------- + + reg [3:0] TxCounter; + reg TxSendBit; + + always @( negedge Reset_n or posedge Clk ) + if ( ~Reset_n ) + begin + TxCounter <= 0; + TxSendBit <= 0; + end + else + begin + TxSendBit <= 0; + if ( Clk_16x ) + begin + if ( TxCounter == 15 ) + begin + TxCounter <= 0; + TxSendBit <= 1; + end + else + TxCounter <= TxCounter + 1; + end + end + + reg [7:0] TxData_reg; + reg [3:0] TxBitCnt; + always @( negedge Reset_n or posedge Clk ) + if ( ~Reset_n ) + begin + TXD_o <= 1; + TxReady_o <= 1; + TxData_reg <= 0; + TxBitCnt <= 0; + end + else + begin + if ( TxReady_o ) + begin + if ( TxValid_i ) + begin + TxReady_o <= 0; + TxData_reg <= TxData_i; + TxBitCnt <= 0; + end + end + else + begin + if ( TxSendBit ) + begin + // Only do anything on bit boundaries + casez ( TxBitCnt ) + 0: // Tx START bit + TXD_o <= 0; + 10: // Tx second STOP bit + // Now we're done + TxReady_o <= 1; + default: // Tx data bit + first stop bit + begin + TXD_o <= TxData_reg[0]; + TxData_reg <= { 1'b1, TxData_reg[7:1] }; + end + endcase + + TxBitCnt <= TxBitCnt+1; + end + end + end + + //--- Receiver logic ------------------------------------------------------ + + reg RxHunt; + reg [3:0] RxCounter; + reg RxSampleBit; + reg RxDone; + + always @( negedge Reset_n or posedge Clk ) + if ( ~Reset_n ) + begin + RxCounter <= 0; + RxSampleBit <= 0; + + RxHunt <= 1; + end + else + begin + RxSampleBit <= 0; + + if ( RxDone ) + RxHunt <= 1; + + if ( Clk_16x ) + begin + if ( RxHunt ) + begin + if ( RXD_i == 0 ) + begin + // Receiving start bit! + RxHunt <= 0; + // Reset 16x bit counter + RxCounter <= 0; + end + end + else + begin + RxCounter <= RxCounter + 1; + if ( RxCounter == 7 ) + // In middle of Rx bit in next cycle + RxSampleBit <= 1; + end + end + end + + reg [3:0] RxBitCount; + + always @( negedge Reset_n or posedge Clk ) + if ( ~Reset_n ) + begin + RxValid_o <= 0; + RxData_o <= 'b0; + RxBitCount <= 0; + RxDone <= 0; + end + else + begin + RxValid_o <= 0; + RxDone <= 0; + + if ( RxSampleBit ) + begin + RxBitCount <= RxBitCount + 1; + + casez ( RxBitCount ) + 0: // START bit - just ignore it + ; + 9: // STOP bit - indicate we're ready again + begin + RxDone <= 1; + RxBitCount <= 0; + end + default: // Rx Data bits + begin + RxData_o <= { RXD_i, RxData_o[7:1] }; + if ( RxBitCount == 8 ) + // Last data bit just received + RxValid_o <= 1; + end + endcase + end + end + +endmodule diff --git a/eth/demo/verilog/demo_wishbone_master.v b/eth/demo/verilog/demo_wishbone_master.v new file mode 100644 index 000000000..b3c64fbcf --- /dev/null +++ b/eth/demo/verilog/demo_wishbone_master.v @@ -0,0 +1,376 @@ +module demo_wishbone_master( + Reset_n, + Clk, + + //--- UART interface + + // Pulsed when RxData_i is valid + RxValid_i, + RxData_i, + + // Asserted when ready for a new Tx byte + TxReady_i, + + // Pulsed when TxData_o is valid + TxValid_o, + TxData_o, + + //--- Wishbone interface + STB_ETH_O, + STB_PDM_O, + STB_PG_O, + CYC_O, + ADR_O, + WE_O, + DAT_O, + DAT_I, + ACK_I +); + + input Reset_n; + input Clk; + + //--- UART interface + + // Pulsed when RxData_i is valid + input RxValid_i; + input [7:0] RxData_i; + + // Asserted when ready for a new Tx byte + input TxReady_i; + + // Pulsed when TxData_o is valid + output TxValid_o; + output [7:0] TxData_o; + + output STB_ETH_O; + output STB_PDM_O; + output STB_PG_O; + output CYC_O; + output [14:0] ADR_O; + output WE_O; + output [15:0] DAT_O; + input [15:0] DAT_I; + input ACK_I; + + //------------------------------------------------------------------------- + // Local declarations + //------------------------------------------------------------------------- + + reg TxValid_o; + reg [7:0] TxData_o; + reg STB_ETH_O; + reg STB_PDM_O; + reg STB_PG_O; + reg CYC_O; + reg [14:0] ADR_O; + reg WE_O; + reg [15:0] DAT_O; + + //------------------------------------------------------------------------- + // Instantiation of sub-modules + //------------------------------------------------------------------------- + + //--- Transmit FSM -------------------------------------------------------- + + parameter TX_STATE_IDLE = 0; + parameter TX_STATE_INIT = 1; + parameter TX_STATE_OK = 2; + parameter TX_STATE_ERROR = 3; + parameter TX_STATE_VALUE = 4; + parameter TX_STATE_LF = 5; + + reg [2:0] TxState; + reg [3:0] TxIndex; + reg TxLast; + + wire [15:0] TxValue16; + wire [3:0] TxHexDigit; + wire [7:0] TxHexChar; + reg TxOK; + reg TxERROR; + reg TxValue; + + always @( negedge Reset_n or posedge Clk ) + if ( ~Reset_n ) + begin + TxState <= TX_STATE_INIT; + TxIndex <= 0; + TxLast <= 0; + + TxValid_o <= 0; + TxData_o <= 'b0; + end + else + begin + TxValid_o <= 0; + + // Don't do anything in cycle following TxValid_o being pulsed + if ( ~TxValid_o ) + begin + casez ( TxState ) + TX_STATE_INIT: + casez ( TxIndex ) + 0: TxData_o <= "R"; + 1: TxData_o <= "E"; + 2: TxData_o <= "A"; + 3: TxData_o <= "D"; + 4: TxData_o <= "Y"; + default: TxLast <= 1; + endcase + + TX_STATE_OK: + casez ( TxIndex ) + 0: TxData_o <= "O"; + 1: TxData_o <= "K"; + default: TxLast <= 1; + endcase + + TX_STATE_ERROR: + casez ( TxIndex ) + 0: TxData_o <= "E"; + 1: TxData_o <= "R"; + 2: TxData_o <= "R"; + 3: TxData_o <= "O"; + 4: TxData_o <= "R"; + default: TxLast <= 1; + endcase + + TX_STATE_VALUE: + casez ( TxIndex ) + 0,1,2,3: TxData_o <= TxHexChar; + default: TxLast <= 1; + endcase + + TX_STATE_LF: + ; + + default: + begin + if ( TxOK ) + TxState <= TX_STATE_OK; + else if ( TxERROR ) + TxState <= TX_STATE_ERROR; + else if ( TxValue ) + begin + TxState <= TX_STATE_VALUE; + TxIndex <= 0; + end + end + endcase + + if ( (TxState != TX_STATE_IDLE) & TxReady_i ) + begin + TxValid_o <= 1; + + if ( TxLast ) + begin + if ( TxState == TX_STATE_LF ) + begin + TxData_o <= 10; // LF + TxState <= TX_STATE_IDLE; + TxIndex <= 0; + TxLast <= 0; + end + else + begin + TxData_o <= 13; // CR + TxState <= TX_STATE_LF; + end + end + else + TxIndex <= TxIndex + 1; + end + end + end + + assign TxHexDigit = (TxIndex==0) ? TxValue16[15:12] : + (TxIndex==1) ? TxValue16[11: 8] : + (TxIndex==2) ? TxValue16[ 7: 4] : + TxValue16[ 3: 0]; + + assign TxHexChar = (TxHexDigit <= 9) ? (TxHexDigit + "0") : + (TxHexDigit + "A"-'hA); + + //--- Receive FSM --------------------------------------------------------- + + parameter RX_STATE_IDLE = 0; + parameter RX_STATE_VALUE16_FIRST = 1; + parameter RX_STATE_VALUE16 = 2; + parameter RX_STATE_COMMENT = 3; + parameter RX_STATE_CMD = 4; + + reg [2:0] RxState; + + wire IsWhiteSpace = ( RxData_i==" " ) | + ( RxData_i=="\t" ) | + ( RxData_i=="," ) | + ( RxData_i==10 ) | + ( RxData_i==13 ); + wire IsHexDigit = (( RxData_i >= "0" ) & ( RxData_i <= "9" )) | + (( RxData_i >= "a" ) & ( RxData_i <= "f" )) | + (( RxData_i >= "A" ) & ( RxData_i <= "F" )); + wire [3:0] RxHexValue = + (( RxData_i >= "0" ) & ( RxData_i <= "9" )) ? RxData_i[3:0] : + (( RxData_i >= "a" ) & ( RxData_i <= "f" )) ? (RxData_i-"a"+'hA) : + (( RxData_i >= "A" ) & ( RxData_i <= "F" )) ? (RxData_i-"A"+'hA) : 0; + + reg [15:0] RxValue16; + reg RxWrite; + reg RxWrData; + + reg [15:0] RegAddr; + reg [15:0] RegRdData; + + assign TxValue16 = RegRdData; + + always @( negedge Reset_n or posedge Clk ) + if ( ~Reset_n ) + begin + RxState <= RX_STATE_IDLE; + + RxValue16 <= 16'h0; + RxWrite <= 0; + RxWrData <= 0; + + RegAddr <= 'b0; + RegRdData <= 'b0; + + STB_ETH_O <= 0; + STB_PDM_O <= 0; + STB_PG_O <= 0; + CYC_O <= 0; + ADR_O <= 0; + WE_O <= 0; + DAT_O <= 0; + + TxOK <= 0; + TxERROR <= 0; + TxValue <= 0; + end + else + begin + TxOK <= 0; + TxERROR <= 0; + TxValue <= 0; + + if ( RxState == RX_STATE_CMD ) + begin + STB_ETH_O <= ( RegAddr[15:12] == 4'h0 ); + STB_PG_O <= ( RegAddr[15:12] == 4'h1 ); + STB_PDM_O <= ( RegAddr[15] == 1'b1 ); + + CYC_O <= 1; + ADR_O <= RegAddr[14:0]; + WE_O <= RxWrite; + + if ( ACK_I ) + begin + // Register transaction is completing! + CYC_O <= 0; + STB_ETH_O <= 0; + STB_PDM_O <= 0; + STB_PG_O <= 0; + + // Latch data read in case of a read + RegRdData <= DAT_I; + + if ( RxWrite ) + // Transaction was a register write + TxOK <= 1; + else + TxValue <= 1; + + RxState <= RX_STATE_IDLE; + end + end + else if ( (TxState == TX_STATE_IDLE) & RxValid_i ) + begin + // A byte has been received! + + casez ( RxState ) + RX_STATE_IDLE: + if ( (RxData_i == "w") | (RxData_i == "W") ) + begin + // Write Register Command: W rrrr dddd + RxState <= RX_STATE_VALUE16_FIRST; + RxWrite <= 1; + RxWrData <= 0; + end + else if ( (RxData_i == "r") | (RxData_i == "R") ) + begin + // Read Register Command: R rrrr + RxState <= RX_STATE_VALUE16_FIRST; + RxWrite <= 0; + end + else if ( RxData_i == "/" ) + begin + // Comment! + RxState <= RX_STATE_COMMENT; + end + else if ( ~IsWhiteSpace ) + // Unknown command! + TxERROR <= 1; + + RX_STATE_COMMENT: + if ( (RxData_i == 13) | (RxData_i == 10) ) + // CR or LF - end of comment + RxState <= RX_STATE_IDLE; + + RX_STATE_VALUE16_FIRST: + if ( IsHexDigit ) + begin + RxValue16 <= { 12'b0, RxHexValue }; + RxState <= RX_STATE_VALUE16; + end + else if ( ~IsWhiteSpace ) + begin + // Unexpected character! + TxERROR <= 1; + RxState <= RX_STATE_IDLE; + end + + RX_STATE_VALUE16: + if ( IsHexDigit ) + RxValue16 <= { RxValue16[11:0], RxHexValue }; + else if ( IsWhiteSpace ) + begin + // Done collecting 16-bit value + if ( RxWrite ) + begin + // This is a register write + if ( RxWrData ) + begin + // Second time around - just received write data + DAT_O <= RxValue16; + RxState <= RX_STATE_CMD; + end + else + begin + // Just received register address - expecting second argument + RegAddr <= RxValue16; + RxState <= RX_STATE_VALUE16_FIRST; + RxWrData <= 1; // Now receive the write data + end + end + else + begin + // This is a register read + RegAddr <= RxValue16; + RxState <= RX_STATE_CMD; + end + end + else + begin + // Unexpected character! + TxERROR <= 1; + RxState <= RX_STATE_IDLE; + end + + default: + TxERROR <= 1; + endcase + end + end + +endmodule diff --git a/eth/demo/verilog/tb_demo.v b/eth/demo/verilog/tb_demo.v new file mode 100644 index 000000000..c5a8a3f41 --- /dev/null +++ b/eth/demo/verilog/tb_demo.v @@ -0,0 +1,348 @@ +`timescale 1ns / 1ns + +module tb_demo; + + //-------------------- Instantiate Xilinx glbl module ---------------------- + // - this is needed to get ModelSim to work because e.g. I/O buffer models + // refer directly to glbl.GTS and similar signals + + wire GSR; + wire GTS; + xlnx_glbl glbl( .GSR( GSR ), .GTS( GTS ) ); + + reg VLOG_ExitSignal = 0; + reg Done = 0; + reg Error = 0; + + //------------------------------------------------------------------------- + + reg Reset_n; + reg Clk_100M; + reg Clk_125M; + + wire RS232_TXD; + wire RS232_RXD; + + wire USB_TXD; + wire USB_RXD; + + //--- 10/100/1000BASE-T Ethernet PHY (MII/GMII) + wire PHY_RESET_n; + + wire PHY_RXC; + wire [7:0] PHY_RXD; + wire PHY_RXDV; + wire PHY_RXER; + + wire PHY_GTX_CLK; // GMII only + wire PHY_TXC; + wire [7:0] PHY_TXD; + wire PHY_TXEN; + wire PHY_TXER; + + wire PHY_COL = 0; + wire PHY_CRS = 0; + + wire PHY_MDC; + wire PHY_MDIO; + + wire [1:4] LED; + + reg [1:4] Button = 4'b0000; + + //------------------------------------------------------------------------- + // Local declarations + //------------------------------------------------------------------------- + + //------------------------------------------------------------------------- + // Instantiation of sub-modules + //------------------------------------------------------------------------- + + //--- DUT + + demo demo( + .Reset_n ( Reset_n ), + .Clk_100M( Clk_100M ), + .Clk_125M( Clk_125M ), + + .RS232_TXD( RS232_TXD ), + .RS232_RXD( RS232_RXD ), + + .USB_TXD( USB_TXD ), + .USB_RXD( USB_RXD ), + + //--- 10/100/1000BASE-T Ethernet PHY (MII/GMII) + .PHY_RESET_n( PHY_RESET_n ), + + .PHY_RXC ( PHY_RXC ), + .PHY_RXD ( PHY_RXD ), + .PHY_RXDV( PHY_RXDV ), + .PHY_RXER( PHY_RXER ), + + .PHY_GTX_CLK( PHY_GTX_CLK ), // GMII only + .PHY_TXC ( PHY_TXC ), + .PHY_TXD ( PHY_TXD ), + .PHY_TXEN ( PHY_TXEN ), + .PHY_TXER ( PHY_TXER ), + + .PHY_COL( PHY_COL ), + .PHY_CRS( PHY_CRS ), + + .PHY_MDC ( PHY_MDC ), + .PHY_MDIO( PHY_MDIO ), + + // Misc. I/Os + .LED ( LED ), + .Button( Button ) + ); + + //------------------------------------------------------------------------- + // MII/GMII Ethernet PHY model + + reg [2:0] Speed = 3'b000; + + Phy_sim U_Phy_sim( + .Gtx_clk( PHY_GTX_CLK ), + .Rx_clk ( PHY_RXC ), + .Tx_clk ( PHY_TXC ), + .Tx_er ( PHY_TXER ), + .Tx_en ( PHY_TXEN ), + .Txd ( PHY_TXD ), + .Rx_er ( PHY_RXER ), + .Rx_dv ( PHY_RXDV ), + .Rxd ( PHY_RXD ), + .Crs ( PHY_CRS ), + .Col ( PHY_COL ), + .Speed ( Speed ), + .Done ( Done ) + ); + + //------------------------------------------------------------------------- + // Generate all clocks & reset + //------------------------------------------------------------------------- + + // Core master clock (100 MHz) + initial + begin + #10; + while ( !Done ) + begin + #5 Clk_100M = 0; + #5 Clk_100M = 1; + end + end + + // GMII master clock (125 MHz) + initial + begin + #10; + while ( !Done ) + begin + #4 Clk_125M = 0; + #4 Clk_125M = 1; + end + end + + initial + begin + Reset_n = 0; + + #103; + Reset_n = 1; + end + + //--- Emulate UART Transmitter -------------------------------------------- + + parameter PRESCALER_16X = 3; + integer Prescaler; + integer TxLen = 0; + reg [2:0] TxState; + integer TxBit; + reg [1023:0] TxMsg; + reg TXD; + reg TxDone; + + always @( negedge Reset_n or posedge Clk_100M ) + if ( ~Reset_n ) + begin + Prescaler <= 0; + TxState = 0; + TXD = 1; + TxBit = 0; + TxDone <= 0; + end + else + begin + TxDone <= 0; + + if ( Prescaler == ((PRESCALER_16X + 1)*16 -1) ) + Prescaler <= 0; + else + Prescaler <= Prescaler + 1; + + if ( Prescaler==0 ) + begin + casez ( TxState ) + 0: // IDLE + begin + if ( TxLen != 0 ) + begin // Send start bit! + TxBit = (TxLen-1)*8; + TxLen = TxLen - 1; + TXD = 0; + TxState = 1; + end + end + + 1: // Send next data bit + begin + // Send next data bit + TXD = TxMsg[ TxBit ]; + TxBit = TxBit + 1; + if ( (TxBit % 8)==0 ) + // Next send two stop bits + TxState = 2; + end + + 2: // First of two stop bits + begin + TXD = 1; + TxState = 3; + end + + 3: // Second of two stop bits + begin + TXD = 1; + TxState = 0; + if ( TxLen == 0 ) + // Done with transmission! + TxDone <= 1; + end + endcase + end + end + + assign RS232_RXD = TXD; + assign USB_RXD = 1; + + //--- Send commands to the DUT -------------------------------------------- + + initial + begin + #10; + while ( ~Reset_n ) #10; + + // Wait a couple of clock edges before continuing to allow + // internal logic to get out of reset + repeat ( 5 ) + @( posedge Clk_100M ); + + // Wait for the "READY" message to complete transmission + #60000; + + // Select 100 Mbps + Speed = 3'b010; + TxMsg = "W 0022 0002 "; + TxLen = 12; + while ( ~TxDone ) + @( posedge Clk_100M ); + + #50000; + + TxMsg = "W 8000 8003 "; + TxLen = 12; + while ( ~TxDone ) + @( posedge Clk_100M ); + + #50000; + + TxMsg = "W 8001 0011 "; + TxLen = 12; + while ( ~TxDone ) + @( posedge Clk_100M ); + + #50000; + + TxMsg = "W 8002 1234 "; + TxLen = 12; + while ( ~TxDone ) + @( posedge Clk_100M ); + + #50000; + + TxMsg = "W 8003 5678 "; + TxLen = 12; + while ( ~TxDone ) + @( posedge Clk_100M ); + + #50000; + + TxMsg = "W 8004 9ABC "; + TxLen = 12; + while ( ~TxDone ) + @( posedge Clk_100M ); + + #50000; + + TxMsg = "W 8005 DEF0 "; + TxLen = 12; + while ( ~TxDone ) + @( posedge Clk_100M ); + + #50000; + + TxMsg = "W 8006 C5C0 "; + TxLen = 12; + while ( ~TxDone ) + @( posedge Clk_100M ); + + #50000; + + TxMsg = "W 8007 BABE "; + TxLen = 12; + while ( ~TxDone ) + @( posedge Clk_100M ); + + #50000; + + TxMsg = "R 8006 "; + TxLen = 7; + while ( ~TxDone ) + @( posedge Clk_100M ); + + #50000; + + // Enable PG! + TxMsg = "W 1000 0001 "; + TxLen = 12; + while ( ~TxDone ) + @( posedge Clk_100M ); + + #50000; + + // Read back that PG has been enabled! + TxMsg = "R 1000 "; + TxLen = 7; + while ( ~TxDone ) + @( posedge Clk_100M ); + + #50000; + + #50000; + + Done = 1; #10; + + $stop; + end + + //--- Directly accesses a register on the internal Wishbone bus, bypassing the UART interface + + task WrReg; + input [15:0] Reg; + input [15:0] Data; + + begin + end + endtask + +endmodule diff --git a/eth/header_ram.v b/eth/header_ram.v new file mode 100644 index 000000000..699f16a4f --- /dev/null +++ b/eth/header_ram.v @@ -0,0 +1,24 @@ + +module header_ram + #(parameter REGNUM=0, + parameter WIDTH=32) + (input clk, + input set_stb, + input [7:0] set_addr, + input [31:0] set_data, + + input [3:0] addr, + output [31:0] q + ); + + reg [WIDTH-1:0] mini_ram[0:15]; + wire write_to_ram = (set_stb & (set_addr[7:4]==REGNUM[7:4])); + wire [3:0] ram_addr = write_to_ram ? set_addr[3:0] : addr; + + always @(posedge clk) + if(write_to_ram) + mini_ram[ram_addr] <= set_data; + + assign q = mini_ram[ram_addr]; + +endmodule // header_ram diff --git a/eth/mac_rxfifo_int.v b/eth/mac_rxfifo_int.v new file mode 100644 index 000000000..9393cbd12 --- /dev/null +++ b/eth/mac_rxfifo_int.v @@ -0,0 +1,80 @@ + +module mac_rxfifo_int + (input clk, input rst, + + input Rx_mac_empty, + output Rx_mac_rd, + input [31:0] Rx_mac_data, + input [1:0] Rx_mac_BE, + input Rx_mac_sop, + input Rx_mac_eop, + input Rx_mac_err, + + output [31:0] wr_dat_o, + output wr_write_o, + output wr_done_o, + output wr_error_o, + input wr_ready_i, + input wr_full_i, + + // FIFO Status + output [15:0] fifo_occupied, + output fifo_full, + output fifo_empty + ); + + // Write side of short FIFO + // Inputs: full, Rx_mac_empty, Rx_mac_sop, Rx_mac_eop, Rx_mac_err, Rx_mac_data/BE + // Controls: write, datain, Rx_mac_rd + + wire write, full, read, empty, sop_o, eop_o, error_o; + + // Write side of short FIFO + assign write = ~full & ~Rx_mac_empty; + assign Rx_mac_rd = write; + + shortfifo #(.WIDTH(35)) mac_rx_sfifo + (.clk(clk),.rst(rst),.clear(0), + .datain({Rx_mac_sop,Rx_mac_eop,Rx_mac_err,Rx_mac_data}),.write(write),.full(full), + .dataout({sop_o,eop_o,error_o,wr_dat_o}),.read(read),.empty(empty), + .space(), .occupied(fifo_occupied[4:0]) ); + assign fifo_occupied[15:5] = 0; + assign fifo_full = full; + assign fifo_empty = empty; + + // Read side of short FIFO + // Inputs: empty, dataout, wr_ready_i, wr_full_i + // Controls: read, wr_dat_o, wr_write_o, wr_done_o, wr_error_o + + reg [1:0] rd_state; + localparam RD_IDLE = 0; + localparam RD_HAVEPKT = 1; + localparam RD_XFER = 2; + localparam RD_ERROR = 3; + + always @(posedge clk) + if(rst) + rd_state <= RD_IDLE; + else + case(rd_state) + RD_IDLE : + if(sop_o & ~empty) + rd_state <= RD_HAVEPKT; + RD_HAVEPKT : + if(wr_ready_i) + rd_state <= RD_XFER; + RD_XFER : + if(eop_o & ~empty) + rd_state <= RD_IDLE; + else if(wr_full_i) + rd_state <= RD_HAVEPKT; + RD_ERROR : + rd_state <= RD_IDLE; + endcase // case(rd_state) + + assign read = ~empty & ((rd_state == RD_XFER) | ((rd_state==RD_IDLE)&~sop_o)); + assign wr_write_o = ~empty & (rd_state == RD_XFER); + assign wr_done_o = ~empty & (rd_state == RD_XFER) & eop_o; + assign wr_error_o = ~empty & (rd_state == RD_XFER) & error_o; + +endmodule // mac_rxfifo_int diff --git a/eth/mac_txfifo_int.v b/eth/mac_txfifo_int.v new file mode 100644 index 000000000..38d8d38fc --- /dev/null +++ b/eth/mac_txfifo_int.v @@ -0,0 +1,77 @@ + +module mac_txfifo_int + (input clk, input rst, input mac_clk, + + // To MAC + input Tx_mac_wa, + output Tx_mac_wr, + output [31:0] Tx_mac_data, + output [1:0] Tx_mac_BE, + output Tx_mac_sop, + output Tx_mac_eop, + + // To buffer interface + input [31:0] rd_dat_i, + output rd_read_o, + output rd_done_o, + output rd_error_o, + input rd_sop_i, + input rd_eop_i, + + // FIFO Status + output [15:0] fifo_occupied, + output fifo_full, + output fifo_empty ); + + wire empty, full, sfifo_write, sfifo_read; + wire [33:0] sfifo_in, sfifo_out; + + /* + shortfifo #(.WIDTH(34)) txmac_sfifo + (.clk(clk),.rst(rst),.clear(0), + .datain(sfifo_in),.write(sfifo_write),.full(full), + .dataout(sfifo_out),.read(sfifo_read),.empty(empty)); + */ + fifo_xlnx_512x36_2clk mac_tx_fifo_2clk + (.rst(rst), + .wr_clk(clk),.din({2'b0,sfifo_in}),.full(full),.wr_en(sfifo_write),.wr_data_count(fifo_occupied[8:0]), + .rd_clk(mac_clk),.dout(sfifo_out),.empty(empty),.rd_en(sfifo_read),.rd_data_count() ); + assign fifo_occupied[15:9] = 0; + assign fifo_full = full; + assign fifo_empty = empty; // Note empty is in wrong clock domain + + // MAC side signals + // We are allowed to do one more write after we are told the FIFO is full + // This allows us to register the _wa signal and speed up timing. + + reg tx_mac_wa_d1; + always @(posedge clk) + tx_mac_wa_d1 <= Tx_mac_wa; + + assign sfifo_read = ~empty & tx_mac_wa_d1; + + assign Tx_mac_wr = sfifo_read; + assign Tx_mac_data = sfifo_out[31:0]; + assign Tx_mac_BE = 0; // Since we only deal with packets that are multiples of 32 bits long + assign Tx_mac_sop = sfifo_out[33]; + assign Tx_mac_eop = sfifo_out[32]; + + + // BUFFER side signals + reg xfer_active; + always @(posedge clk) + if(rst) + xfer_active <= 0; + else if(rd_eop_i & ~full) + xfer_active <= 0; + else if(rd_sop_i) + xfer_active <= 1; + + assign sfifo_in = {rd_sop_i, rd_eop_i, rd_dat_i}; + assign sfifo_write = xfer_active & ~full; + + assign rd_read_o = sfifo_write; + assign rd_done_o = 0; // Always send everything we're given? + assign rd_error_o = 0; // No possible error situations? + +endmodule // mac_txfifo_int diff --git a/eth/rtl/verilog/Clk_ctrl.v b/eth/rtl/verilog/Clk_ctrl.v new file mode 100644 index 000000000..917082644 --- /dev/null +++ b/eth/rtl/verilog/Clk_ctrl.v @@ -0,0 +1,133 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// Clk_ctrl.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source 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 Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: Clk_ctrl.v,v $ +// Revision 1.3 2006/01/19 14:07:52 maverickist +// verification is complete. +// +// Revision 1.2 2005/12/16 06:44:13 Administrator +// replaced tab with space. +// passed 9.6k length frame test. +// +// Revision 1.1.1.1 2005/12/13 01:51:44 Administrator +// no message +// + +module Clk_ctrl( +Reset , +Clk_125M , +//host interface, +Speed , +//Phy interface , +Gtx_clk , +Rx_clk , +Tx_clk , +//interface clk , +MAC_tx_clk , +MAC_rx_clk , +MAC_tx_clk_div , +MAC_rx_clk_div +); +input Reset ; +input Clk_125M ; + //host interface +input [2:0] Speed ; + //Phy interface +output Gtx_clk ;//used only in GMII mode +input Rx_clk ; +input Tx_clk ;//used only in MII mode + //interface clk signals +output MAC_tx_clk ; +output MAC_rx_clk ; +output MAC_tx_clk_div ; +output MAC_rx_clk_div ; + + +// ****************************************************************************** +// internal signals +// ****************************************************************************** +wire Rx_clk_div2 ; +wire Tx_clk_div2 ; +// ****************************************************************************** +// +// ****************************************************************************** + assign Gtx_clk = Clk_125M ; + assign MAC_rx_clk = Rx_clk ; + assign MAC_rx_clk_div = Rx_clk ; + assign MAC_tx_clk = Clk_125M; + assign MAC_tx_clk_div = Clk_125M; + + + /* +eth_clk_div2 U_0_CLK_DIV2( +.Reset (Reset ), +.IN (Rx_clk ), +.OUT (Rx_clk_div2 ) +); + +eth_clk_div2 U_1_CLK_DIV2( +.Reset (Reset ), +.IN (Tx_clk ), +.OUT (Tx_clk_div2 ) +); + +eth_clk_switch U_0_CLK_SWITCH( +.IN_0 (Rx_clk_div2 ), +.IN_1 (Rx_clk ), +.SW (Speed[2] ), +.OUT (MAC_rx_clk_div ) +); + +eth_clk_switch U_1_CLK_SWITCH( +.IN_0 (Tx_clk ), +.IN_1 (Clk_125M ), +.SW (Speed[2] ), +.OUT (MAC_tx_clk ) +); + +eth_clk_switch U_2_CLK_SWITCH( +.IN_0 (Tx_clk_div2 ), +.IN_1 (Clk_125M ), +.SW (Speed[2] ), +.OUT (MAC_tx_clk_div ) +); + + */ +endmodule diff --git a/eth/rtl/verilog/MAC_rx.v b/eth/rtl/verilog/MAC_rx.v new file mode 100644 index 000000000..0e02e8fcc --- /dev/null +++ b/eth/rtl/verilog/MAC_rx.v @@ -0,0 +1,242 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// MAC_rx.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source 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 Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: MAC_rx.v,v $ +// Revision 1.4 2006/11/17 17:53:07 maverickist +// no message +// +// Revision 1.3 2006/01/19 14:07:52 maverickist +// verification is complete. +// +// Revision 1.2 2005/12/16 06:44:13 Administrator +// replaced tab with space. +// passed 9.6k length frame test. +// +// Revision 1.1.1.1 2005/12/13 01:51:44 Administrator +// no message +// + +module MAC_rx + #(parameter RX_FF_DEPTH = 9) + ( +input Reset , +input Clk_user, +input Clk , + //RMII interface +input MCrs_dv , +input [7:0] MRxD , +input MRxErr , + //flow_control signals +output [15:0] pause_quanta, +output pause_quanta_val, +output [15:0] rx_fifo_space, + //user interface +output Rx_mac_empty, +input Rx_mac_rd , +output [31:0] Rx_mac_data , +output [1:0] Rx_mac_BE , +output Rx_mac_sop , +output Rx_mac_eop , +output Rx_mac_err , + //CPU +input MAC_rx_add_chk_en , +input [7:0] MAC_add_prom_data , +input [2:0] MAC_add_prom_add , +input MAC_add_prom_wr , +input broadcast_filter_en , +input [15:0] broadcast_bucket_depth , +input [15:0] broadcast_bucket_interval , +input RX_APPEND_CRC, +input [4:0] Rx_Hwmark , +input [4:0] Rx_Lwmark , +input CRC_chk_en , +input [5:0] RX_IFG_SET , +input [15:0] RX_MAX_LENGTH ,// 1518 +input [6:0] RX_MIN_LENGTH ,// 64 + //RMON interface +output [15:0] Rx_pkt_length_rmon , +output Rx_apply_rmon , +output [2:0] Rx_pkt_err_type_rmon , +output [2:0] Rx_pkt_type_rmon , + + output [15:0] rx_fifo_occupied, + output rx_fifo_full, + output rx_fifo_empty, + output [31:0] debug +); +//****************************************************************************** +//internal signals +//****************************************************************************** + //CRC_chk interface +wire CRC_en ; +wire [7:0] CRC_data; +wire CRC_init; +wire CRC_err ; + //MAC_rx_add_chk interface +wire MAC_add_en ; +wire [7:0] MAC_add_data; +wire MAC_rx_add_chk_err ; + //broadcast_filter +wire broadcast_ptr ; +wire broadcast_drop ; + //MAC_rx_ctrl interface +wire [7:0] Fifo_data ; +wire Fifo_data_en ; +wire Fifo_full ; +wire Fifo_data_err ; +wire Fifo_data_drop ; +wire Fifo_data_end ; + + +//****************************************************************************** +//instantiation +//****************************************************************************** + + +MAC_rx_ctrl U_MAC_rx_ctrl( +.Reset (Reset ), +.Clk (Clk ), + //RMII interface ( //RMII interface ), +.MCrs_dv (MCrs_dv ), +.MRxD (MRxD ), +.MRxErr (MRxErr ), + //CRC_chk interface (//CRC_chk interface ), +.CRC_en (CRC_en ), +.CRC_data (CRC_data ), +.CRC_init (CRC_init ), +.CRC_err (CRC_err ), + //MAC_rx_add_chk interface (//MAC_rx_add_chk interface), +.MAC_add_en (MAC_add_en ), +.MAC_add_data (MAC_add_data ), +.MAC_rx_add_chk_err (MAC_rx_add_chk_err ), + //broadcast_filter (//broadcast_filter ), +.broadcast_ptr (broadcast_ptr ), +.broadcast_drop (broadcast_drop ), + //flow_control signals (//flow_control signals ), +.pause_quanta (pause_quanta ), +.pause_quanta_val (pause_quanta_val ), + //MAC_rx_FF interface (//MAC_rx_FF interface ), +.Fifo_data (Fifo_data ), +.Fifo_data_en (Fifo_data_en ), +.Fifo_data_err (Fifo_data_err ), +.Fifo_data_drop (Fifo_data_drop ), +.Fifo_data_end (Fifo_data_end ), +.Fifo_full (Fifo_full ), + //RMON interface (//RMON interface ), +.Rx_pkt_type_rmon (Rx_pkt_type_rmon ), +.Rx_pkt_length_rmon (Rx_pkt_length_rmon ), +.Rx_apply_rmon (Rx_apply_rmon ), +.Rx_pkt_err_type_rmon (Rx_pkt_err_type_rmon ), + //CPU (//CPU ), +.RX_IFG_SET (RX_IFG_SET ), +.RX_MAX_LENGTH (RX_MAX_LENGTH ), +.RX_MIN_LENGTH (RX_MIN_LENGTH ) +); + + assign debug = {28'd0, Fifo_data_en, Fifo_data_err, Fifo_data_end,Fifo_full}; + +MAC_rx_FF #(.RX_FF_DEPTH(RX_FF_DEPTH)) U_MAC_rx_FF ( +.Reset (Reset ), +.Clk_MAC (Clk ), +.Clk_SYS (Clk_user ), + //MAC_rx_ctrl interface (//MAC_rx_ctrl interface ), +.Fifo_data (Fifo_data ), +.Fifo_data_en (Fifo_data_en ), +.Fifo_full (Fifo_full ), +.Fifo_data_err (Fifo_data_err ), +//.Fifo_data_drop (Fifo_data_drop ), +.Fifo_data_end (Fifo_data_end ), +.Fifo_space (rx_fifo_space ), + //CPU (//CPU ), +.Rx_Hwmark (Rx_Hwmark ), +.Rx_Lwmark (Rx_Lwmark ), +.RX_APPEND_CRC (RX_APPEND_CRC ), + //user interface (//user interface ), +.Rx_mac_empty (Rx_mac_empty ), +.Rx_mac_rd (Rx_mac_rd ), +.Rx_mac_data (Rx_mac_data ), +.Rx_mac_BE (Rx_mac_BE ), +.Rx_mac_sop (Rx_mac_sop ), +.Rx_mac_eop (Rx_mac_eop ), +.Rx_mac_err (Rx_mac_err ), + +.fifo_occupied(rx_fifo_occupied), +.fifo_full_dbg(rx_fifo_full), +.fifo_empty(rx_fifo_empty) +); + + Broadcast_filter U_Broadcast_filter + (.Reset (Reset ), + .Clk (Clk ), + //MAC_rx_ctrl (//MAC_rx_ctrl ), + .broadcast_ptr (broadcast_ptr ), + .broadcast_drop (broadcast_drop ), + //FromCPU (//FromCPU ), + .broadcast_filter_en (broadcast_filter_en ), + .broadcast_bucket_depth (broadcast_bucket_depth ), + .broadcast_bucket_interval (broadcast_bucket_interval ) + ); + +CRC_chk U_CRC_chk( +.Reset (Reset ), +.Clk (Clk ), +.CRC_data (CRC_data ), +.CRC_init (CRC_init ), +.CRC_en (CRC_en ), + //From CPU (//From CPU ), +.CRC_chk_en (CRC_chk_en ), +.CRC_err (CRC_err ) +); + + MAC_rx_add_chk U_MAC_rx_add_chk + (.Reset (Reset ), + .Clk (Clk ), + .Init (CRC_init ), + .data (MAC_add_data ), + .MAC_add_en (MAC_add_en ), + .MAC_rx_add_chk_err (MAC_rx_add_chk_err ), + //From CPU (//From CPU ), + .MAC_rx_add_chk_en (MAC_rx_add_chk_en ), + .MAC_add_prom_data (MAC_add_prom_data ), + .MAC_add_prom_add (MAC_add_prom_add ), + .MAC_add_prom_wr (MAC_add_prom_wr ) + ); + +endmodule // MAC_rx diff --git a/eth/rtl/verilog/MAC_rx/Broadcast_filter.v b/eth/rtl/verilog/MAC_rx/Broadcast_filter.v new file mode 100644 index 000000000..bc95e31d7 --- /dev/null +++ b/eth/rtl/verilog/MAC_rx/Broadcast_filter.v @@ -0,0 +1,107 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// Broadcast_filter.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source 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 Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: Broadcast_filter.v,v $ +// Revision 1.3 2006/01/19 14:07:54 maverickist +// verification is complete. +// +// Revision 1.2 2005/12/16 06:44:16 Administrator +// replaced tab with space. +// passed 9.6k length frame test. +// +// Revision 1.1.1.1 2005/12/13 01:51:45 Administrator +// no message +// + +module Broadcast_filter ( +Reset , +Clk , +//MAC_rx_ctrl , +broadcast_ptr , +broadcast_drop , +//FromCPU , +broadcast_filter_en , +broadcast_bucket_depth , +broadcast_bucket_interval +); +input Reset ; +input Clk ; + //MAC_rx_ctrl +input broadcast_ptr ; +output broadcast_drop ; + //FromCPU ; +input broadcast_filter_en ; +input [15:0] broadcast_bucket_depth ; +input [15:0] broadcast_bucket_interval ; + +//****************************************************************************** +//internal signals +//****************************************************************************** +reg [15:0] time_counter ; +reg [15:0] broadcast_counter ; +reg broadcast_drop ; +//****************************************************************************** +// +//****************************************************************************** +always @ (posedge Clk or posedge Reset) + if (Reset) + time_counter <=0; + else if (time_counter==broadcast_bucket_interval) + time_counter <=0; + else + time_counter <=time_counter+1; + +always @ (posedge Clk or posedge Reset) + if (Reset) + broadcast_counter <=0; + else if (time_counter==broadcast_bucket_interval) + broadcast_counter <=0; + else if (broadcast_ptr&&broadcast_counter!=broadcast_bucket_depth) + broadcast_counter <=broadcast_counter+1; + +always @ (posedge Clk or posedge Reset) + if (Reset) + broadcast_drop <=0; + else if(broadcast_filter_en&&broadcast_counter==broadcast_bucket_depth) + broadcast_drop <=1; + else + broadcast_drop <=0; + +endmodule \ No newline at end of file diff --git a/eth/rtl/verilog/MAC_rx/CRC_chk.v b/eth/rtl/verilog/MAC_rx/CRC_chk.v new file mode 100644 index 000000000..d6bb22b51 --- /dev/null +++ b/eth/rtl/verilog/MAC_rx/CRC_chk.v @@ -0,0 +1,128 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// CRC_chk.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source 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 Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: CRC_chk.v,v $ +// Revision 1.3 2006/01/19 14:07:54 maverickist +// verification is complete. +// +// Revision 1.2 2005/12/16 06:44:16 Administrator +// replaced tab with space. +// passed 9.6k length frame test. +// +// Revision 1.1.1.1 2005/12/13 01:51:45 Administrator +// no message +// + +module CRC_chk( +Reset , +Clk , +CRC_data , +CRC_init , +CRC_en , +//From CPU +CRC_chk_en , +CRC_err +); +input Reset ; +input Clk ; +input[7:0] CRC_data ; +input CRC_init ; +input CRC_en ; + //From CPU +input CRC_chk_en ; +output CRC_err ; +//****************************************************************************** +//internal signals +//****************************************************************************** +reg [31:0] CRC_reg; +//****************************************************************************** +//input data width is 8bit, and the first bit is bit[0] +function[31:0] NextCRC; + input[7:0] D; + input[31:0] C; + reg[31:0] NewCRC; + begin + NewCRC[0]=C[24]^C[30]^D[1]^D[7]; + NewCRC[1]=C[25]^C[31]^D[0]^D[6]^C[24]^C[30]^D[1]^D[7]; + NewCRC[2]=C[26]^D[5]^C[25]^C[31]^D[0]^D[6]^C[24]^C[30]^D[1]^D[7]; + NewCRC[3]=C[27]^D[4]^C[26]^D[5]^C[25]^C[31]^D[0]^D[6]; + NewCRC[4]=C[28]^D[3]^C[27]^D[4]^C[26]^D[5]^C[24]^C[30]^D[1]^D[7]; + NewCRC[5]=C[29]^D[2]^C[28]^D[3]^C[27]^D[4]^C[25]^C[31]^D[0]^D[6]^C[24]^C[30]^D[1]^D[7]; + NewCRC[6]=C[30]^D[1]^C[29]^D[2]^C[28]^D[3]^C[26]^D[5]^C[25]^C[31]^D[0]^D[6]; + NewCRC[7]=C[31]^D[0]^C[29]^D[2]^C[27]^D[4]^C[26]^D[5]^C[24]^D[7]; + NewCRC[8]=C[0]^C[28]^D[3]^C[27]^D[4]^C[25]^D[6]^C[24]^D[7]; + NewCRC[9]=C[1]^C[29]^D[2]^C[28]^D[3]^C[26]^D[5]^C[25]^D[6]; + NewCRC[10]=C[2]^C[29]^D[2]^C[27]^D[4]^C[26]^D[5]^C[24]^D[7]; + NewCRC[11]=C[3]^C[28]^D[3]^C[27]^D[4]^C[25]^D[6]^C[24]^D[7]; + NewCRC[12]=C[4]^C[29]^D[2]^C[28]^D[3]^C[26]^D[5]^C[25]^D[6]^C[24]^C[30]^D[1]^D[7]; + NewCRC[13]=C[5]^C[30]^D[1]^C[29]^D[2]^C[27]^D[4]^C[26]^D[5]^C[25]^C[31]^D[0]^D[6]; + NewCRC[14]=C[6]^C[31]^D[0]^C[30]^D[1]^C[28]^D[3]^C[27]^D[4]^C[26]^D[5]; + NewCRC[15]=C[7]^C[31]^D[0]^C[29]^D[2]^C[28]^D[3]^C[27]^D[4]; + NewCRC[16]=C[8]^C[29]^D[2]^C[28]^D[3]^C[24]^D[7]; + NewCRC[17]=C[9]^C[30]^D[1]^C[29]^D[2]^C[25]^D[6]; + NewCRC[18]=C[10]^C[31]^D[0]^C[30]^D[1]^C[26]^D[5]; + NewCRC[19]=C[11]^C[31]^D[0]^C[27]^D[4]; + NewCRC[20]=C[12]^C[28]^D[3]; + NewCRC[21]=C[13]^C[29]^D[2]; + NewCRC[22]=C[14]^C[24]^D[7]; + NewCRC[23]=C[15]^C[25]^D[6]^C[24]^C[30]^D[1]^D[7]; + NewCRC[24]=C[16]^C[26]^D[5]^C[25]^C[31]^D[0]^D[6]; + NewCRC[25]=C[17]^C[27]^D[4]^C[26]^D[5]; + NewCRC[26]=C[18]^C[28]^D[3]^C[27]^D[4]^C[24]^C[30]^D[1]^D[7]; + NewCRC[27]=C[19]^C[29]^D[2]^C[28]^D[3]^C[25]^C[31]^D[0]^D[6]; + NewCRC[28]=C[20]^C[30]^D[1]^C[29]^D[2]^C[26]^D[5]; + NewCRC[29]=C[21]^C[31]^D[0]^C[30]^D[1]^C[27]^D[4]; + NewCRC[30]=C[22]^C[31]^D[0]^C[28]^D[3]; + NewCRC[31]=C[23]^C[29]^D[2]; + NextCRC=NewCRC; + end + endfunction + +always @ (posedge Clk or posedge Reset) + if (Reset) + CRC_reg <=32'hffffffff; + else if (CRC_init) + CRC_reg <=32'hffffffff; + else if (CRC_en) + CRC_reg <=NextCRC(CRC_data,CRC_reg); + +assign CRC_err = CRC_chk_en&(CRC_reg[31:0] != 32'hc704dd7b); + +endmodule diff --git a/eth/rtl/verilog/MAC_rx/MAC_rx_FF.v b/eth/rtl/verilog/MAC_rx/MAC_rx_FF.v new file mode 100644 index 000000000..e212b8986 --- /dev/null +++ b/eth/rtl/verilog/MAC_rx/MAC_rx_FF.v @@ -0,0 +1,167 @@ + +// //////////////////////////////////////////////////////////////////// +// Completely Rewritten by M. Ettus, no John Gao code left +// //////////////////////////////////////////////////////////////////// + +module MAC_rx_FF + #(parameter RX_FF_DEPTH = 9) + (input Reset, + input Clk_MAC, + input Clk_SYS, + + // MAC_rx_ctrl interface + input [7:0] Fifo_data, + input Fifo_data_en, + output Fifo_full, + input Fifo_data_err, + input Fifo_data_end, + output [15:0] Fifo_space, + + // CPU + input RX_APPEND_CRC, + input [4:0] Rx_Hwmark, + input [4:0] Rx_Lwmark, + + // User interface + output Rx_mac_empty, + input Rx_mac_rd, + output [31:0] Rx_mac_data, + output [1:0] Rx_mac_BE, + output Rx_mac_sop, + output Rx_mac_eop, + output Rx_mac_err, + + // FIFO Levels + output [15:0] fifo_occupied, + output fifo_full_dbg, + output fifo_empty + ); + + reg [1:0] FF_state; + reg [2:0] PKT_state; + reg [31:0] staging; + reg [35:0] staging2; + reg line_ready, line_ready_d1; + wire sop_i, eop_i; + reg [1:0] be; + + always @(posedge Clk_MAC or posedge Reset) + if(Reset) + FF_state <= 0; + else + if(Fifo_data_err | Fifo_data_end) + FF_state <= 0; + else if(Fifo_data_en) + FF_state <= FF_state + 1; + + always @(posedge Clk_MAC or posedge Reset) + if(Reset) + staging[31:0] <= 0; + else if(Fifo_data_en) + case(FF_state) + 0 : staging[31:24] <= Fifo_data; + 1 : staging[23:16] <= Fifo_data; + 2 : staging[15:8] <= Fifo_data; + 3 : staging[7:0] <= Fifo_data; + endcase // case(FF_state) + + localparam PKT_idle = 0; + localparam PKT_sop = 1; + localparam PKT_pkt = 2; + localparam PKT_end = 3; + localparam PKT_err = 4; + + always @(posedge Clk_MAC or posedge Reset) + if(Reset) + PKT_state <= 0; + else + case(PKT_state) + PKT_idle : + if(Fifo_data_en) + PKT_state <= PKT_sop; + PKT_sop, PKT_pkt : + if(Fifo_data_err | (line_ready & Fifo_full)) + PKT_state <= PKT_err; + else if(Fifo_data_end) + PKT_state <= PKT_end; + else if(line_ready & ~Fifo_full) + PKT_state <= PKT_pkt; + PKT_end : + PKT_state <= PKT_idle; + PKT_err : + if(~Fifo_full) + PKT_state <= PKT_idle; + endcase // case(PKT_state) + + assign sop_i = (PKT_state == PKT_sop); + assign eop_i = (PKT_state == PKT_end); + + always @(posedge Clk_MAC) + if(line_ready) + staging2 <= {sop_i, eop_i, be[1:0], staging}; + + always @(posedge Clk_MAC) + if(Reset) + line_ready <= 0; + else if((Fifo_data_en & (FF_state==2'd3)) | Fifo_data_end | Fifo_data_err) + line_ready <= 1; + else + line_ready <= 0; + + always @(posedge Clk_MAC) + line_ready_d1 <= line_ready; + + always @(posedge Clk_MAC) + if(Fifo_data_end | Fifo_data_err) + be <= FF_state; + else + be <= 0; + + wire sop_o, eop_o, empty; + wire [1:0] be_o; + wire [RX_FF_DEPTH-1:0] occupied, occupied_sysclk; + wire [31:0] dataout; + +/* + fifo_2clock #(.DWIDTH(36),.AWIDTH(RX_FF_DEPTH)) mac_rx_fifo + (.wclk(Clk_MAC),.datain((PKT_state==PKT_err) ? 36'hF_FFFF_FFFF : staging2),.write(~Fifo_full & (line_ready_d1|(PKT_state==PKT_err))), + .full(Fifo_full),.level_wclk(occupied), + .rclk(Clk_SYS),.dataout({sop_o,eop_o,be_o[1:0],dataout}),.read(Rx_mac_rd), + .empty(empty),.level_rclk(), + .arst(Reset) ); + */ + + fifo_xlnx_2Kx36_2clk mac_rx_ff_core + ( + .din((PKT_state==PKT_err) ? 36'hF_FFFF_FFFF : staging2), // Bus [35 : 0] + .rd_clk(Clk_SYS), + .rd_en(Rx_mac_rd), + .rst(Reset), + .wr_clk(Clk_MAC), + .wr_en(~Fifo_full & (line_ready_d1|(PKT_state==PKT_err))), + .dout({sop_o,eop_o,be_o[1:0],dataout}), // Bus [35 : 0] + .empty(empty), + .full(Fifo_full), + .rd_data_count(occupied_sysclk), // Bus [11 : 0] + .wr_data_count(occupied)); // Bus [11 : 0] + + assign Fifo_space[15:RX_FF_DEPTH] = 0; + assign Fifo_space[RX_FF_DEPTH-1:0] = ~occupied; + assign fifo_occupied = occupied_sysclk; + assign fifo_full_dbg = Fifo_full; // FIXME -- in wrong clock domain + assign fifo_empty = empty; + + // mac side fifo interface + // Input - Rx_mac_rd + // Output - Rx_mac_empty, Rx_mac_sop, Rx_mac_eop, Rx_mac_err, Rx_mac_data, Rx_mac_BE + + assign Rx_mac_BE = be_o; + assign Rx_mac_sop = sop_o & ~eop_o; + assign Rx_mac_eop = eop_o; + assign Rx_mac_err = sop_o & eop_o; + assign Rx_mac_empty = empty; + assign Rx_mac_data = dataout; + +endmodule // MAC_rx_FF + +// FIXME Should we send out an "almost full" signal instead of full? diff --git a/eth/rtl/verilog/MAC_rx/MAC_rx_add_chk.v b/eth/rtl/verilog/MAC_rx/MAC_rx_add_chk.v new file mode 100644 index 000000000..0c8d6bd4e --- /dev/null +++ b/eth/rtl/verilog/MAC_rx/MAC_rx_add_chk.v @@ -0,0 +1,158 @@ +// //////////////////////////////////////////////////////////////////// +// // //// +// // MAC_rx_add_chk.v //// +// // //// +// // This file is part of the Ethernet IP core project //// +// // http://www.opencores.org/projects.cgi/wr_en/ethernet_tri_mode///// +// // //// +// // Author(s): //// +// // - Jon Gao (gaojon@yahoo.com) //// +// // //// +// // //// +// //////////////////////////////////////////////////////////////////// +// // //// +// // Copyright (C) 2001 Authors //// +// // //// +// // This source file may be used and distributed without //// +// // restriction provided that this copyright statement is not //// +// // removed from the file and that any derivative work contains //// +// // the original copyright notice and the associated disclaimer. //// +// // //// +// // This source file is free software; you can redistribute it //// +// // and/or modify it under the terms of the GNU Lesser General //// +// // Public License as published by the Free Software Foundation; //// +// // either version 2.1 of the License, or (at your option) any //// +// // later version. //// +// // //// +// // This source 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 Lesser General Public License for more //// +// // details. //// +// // //// +// // You should have received a copy of the GNU Lesser General //// +// // Public License along with this source; if not, download it //// +// // from http://www.opencores.org/lgpl.shtml //// +// // //// +// //////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: MAC_rx_add_chk.v,v $ +// Revision 1.3 2006/01/19 14:07:54 maverickist +// verification is complete. +// +// Revision 1.2 2005/12/16 06:44:17 Administrator +// replaced tab with space. +// passed 9.6k length frame test. +// +// Revision 1.1.1.1 2005/12/13 01:51:45 Administrator +// no message +// + +module MAC_rx_add_chk + (Reset , + Clk , + Init , + data , + MAC_add_en , + MAC_rx_add_chk_err , + //From CPU + MAC_rx_add_chk_en , + MAC_add_prom_data , + MAC_add_prom_add , + MAC_add_prom_wr + ); + + input Reset ; + input Clk ; + input Init ; + input [7:0] data ; + input MAC_add_en ; + output MAC_rx_add_chk_err ; + //From CPU + input MAC_rx_add_chk_en ; + input [7:0] MAC_add_prom_data ; + input [2:0] MAC_add_prom_add ; + input MAC_add_prom_wr ; + + // ****************************************************************************** + // internal signals + // ****************************************************************************** + reg [2:0] addr_rd; + wire [2:0] addr_wr; + wire [7:0] din; + //wire [7:0] dout; + reg [7:0] dout; + wire wr_en; + + reg MAC_rx_add_chk_err; + reg MAC_add_prom_wr_dl1; + reg MAC_add_prom_wr_dl2; + reg [7:0] data_dl1 ; + reg MAC_add_en_dl1 ; + + // ****************************************************************************** + // write data from cpu to prom + // ****************************************************************************** + always @ (posedge Clk or posedge Reset) + if (Reset) + begin + data_dl1 <=0; + MAC_add_en_dl1 <=0; + end + else + begin + data_dl1 <=data; + MAC_add_en_dl1 <=MAC_add_en; + end + + always @ (posedge Clk or posedge Reset) + if (Reset) + begin + MAC_add_prom_wr_dl1 <=0; + MAC_add_prom_wr_dl2 <=0; + end + else + begin + MAC_add_prom_wr_dl1 <=MAC_add_prom_wr; + MAC_add_prom_wr_dl2 <=MAC_add_prom_wr_dl1; + end + + assign wr_en =MAC_add_prom_wr_dl1&!MAC_add_prom_wr_dl2; + assign addr_wr =MAC_add_prom_add; + assign din =MAC_add_prom_data; + + // ****************************************************************************** + // mac add verify + // ****************************************************************************** + always @ (posedge Clk or posedge Reset) + if (Reset) + addr_rd <=0; + else if (Init) + addr_rd <=0; + else if (MAC_add_en) + addr_rd <=addr_rd + 1; + + always @ (posedge Clk or posedge Reset) + if (Reset) + MAC_rx_add_chk_err <=0; + else if (Init) + MAC_rx_add_chk_err <=0; + else if (MAC_rx_add_chk_en && MAC_add_en_dl1 && (dout!=data_dl1) ) + MAC_rx_add_chk_err <=1; + + + // ****************************************************************************** + // a port for read ,b port for write . + // ****************************************************************************** + + reg [7:0] address_ram [0:7]; + always @(posedge Clk) + if(wr_en) + address_ram[addr_wr] <= din; + + always @(posedge Clk) + dout <= address_ram[addr_rd]; + +endmodule // MAC_rx_add_chk diff --git a/eth/rtl/verilog/MAC_rx/MAC_rx_ctrl.v b/eth/rtl/verilog/MAC_rx/MAC_rx_ctrl.v new file mode 100644 index 000000000..5ab795801 --- /dev/null +++ b/eth/rtl/verilog/MAC_rx/MAC_rx_ctrl.v @@ -0,0 +1,664 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// MAC_rx_ctrl.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source 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 Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: MAC_rx_ctrl.v,v $ +// Revision 1.4 2006/06/25 04:58:56 maverickist +// no message +// +// Revision 1.3 2006/01/19 14:07:54 maverickist +// verification is complete. +// +// Revision 1.3 2005/12/16 06:44:17 Administrator +// replaced tab with space. +// passed 9.6k length frame test. +// +// Revision 1.2 2005/12/13 12:15:37 Administrator +// no message +// +// Revision 1.1.1.1 2005/12/13 01:51:45 Administrator +// no message +// + +module MAC_rx_ctrl ( +Reset , +Clk , +//RMII interface +MCrs_dv , // +MRxD , // +MRxErr , // +//CRC_chk interface +CRC_en , +CRC_data, +CRC_init , +CRC_err , +//MAC_rx_add_chk interface +MAC_add_en , +MAC_add_data, +MAC_rx_add_chk_err , +//broadcast_filter +broadcast_ptr , +broadcast_drop , +//flow_control signals +pause_quanta , +pause_quanta_val , +//MAC_rx_FF interface +Fifo_data , +Fifo_data_en , +Fifo_data_err , +Fifo_data_drop , +Fifo_data_end , +Fifo_full , +//RMON interface +Rx_pkt_type_rmon , +Rx_pkt_length_rmon , +Rx_apply_rmon , +Rx_pkt_err_type_rmon , +//CPU +RX_IFG_SET , +RX_MAX_LENGTH, +RX_MIN_LENGTH +); + +input Reset ; +input Clk ; + //RMII interface +input MCrs_dv ; +input [7:0] MRxD ; +input MRxErr ; + //CRC_chk interface +output CRC_en ; +output CRC_init; +output [7:0] CRC_data; +input CRC_err ; + //MAC_rx_add_chk interface +output MAC_add_en ; +output [7:0] MAC_add_data; +input MAC_rx_add_chk_err ; + //broadcast_filter +output broadcast_ptr ; +input broadcast_drop ; + //flow_control signals +output [15:0] pause_quanta ; +output pause_quanta_val ; + //MAC_rx_FF interface +output [7:0] Fifo_data ; +output Fifo_data_en ; +output Fifo_data_err ; +output Fifo_data_drop ; +output Fifo_data_end ; +input Fifo_full; + //RMON interface +output [15:0] Rx_pkt_length_rmon ; +output Rx_apply_rmon ; +output [2:0] Rx_pkt_err_type_rmon ; +output [2:0] Rx_pkt_type_rmon ; + //CPU +input [5:0] RX_IFG_SET ; +input [15:0] RX_MAX_LENGTH ;// 1518 +input [6:0] RX_MIN_LENGTH ;// 64 + +//****************************************************************************** +//internal signals +//****************************************************************************** +parameter State_idle =4'd00; +parameter State_preamble =4'd01; +parameter State_SFD =4'd02; +parameter State_data =4'd03; +parameter State_checkCRC =4'd04; +parameter State_OkEnd =4'd07; +parameter State_DropEnd =4'd08; +parameter State_ErrEnd =4'd09; +parameter State_CRCErrEnd =4'd10; +parameter State_FFFullDrop =4'd11; +parameter State_FFFullErrEnd =4'd12; +parameter State_IFG =4'd13; +parameter State_Drop2End =4'd14; + +parameter Pause_idle =4'd0; +parameter Pause_pre_syn =4'd1; +parameter Pause_quanta_hi =4'd2; +parameter Pause_quanta_lo =4'd3; +parameter Pause_syn =4'd4; + +reg [3:0] Current_state /* synthesis syn_keep=1 */; +reg [3:0] Next_state; +reg [3:0] Pause_current /* synthesis syn_keep=1 */; +reg [3:0] Pause_next; +reg [5:0] IFG_counter; +reg Crs_dv ; +reg [7:0] RxD ; +reg [7:0] RxD_dl1 ; +reg RxErr ; +reg [15:0] Frame_length_counter; +reg Too_long; +reg Too_short; +reg ProcessingHeader; +//reg Fifo_data_en; +//reg Fifo_data_err; +//reg Fifo_data_drop; +//reg Fifo_data_end; +reg CRC_en; +reg CRC_init; +reg Rx_apply_rmon; +reg [2:0] Rx_pkt_err_type_rmon; +reg MAC_add_en; +reg [2:0] Rx_pkt_type_rmon; +reg [7:0] pause_quanta_h ; +reg [15:0] pause_quanta ; +reg pause_quanta_val ; +reg pause_quanta_val_tmp; +reg pause_frame_ptr ; +reg broadcast_ptr ; +//****************************************************************************** +//delay signals +//****************************************************************************** + +always @ (posedge Reset or posedge Clk) + if (Reset) + begin + Crs_dv <=0; + RxD <=0; + RxErr <=0; + end + else + begin + Crs_dv <=MCrs_dv ; + RxD <=MRxD ; + RxErr <=MRxErr ; + end + +always @ (posedge Reset or posedge Clk) + if (Reset) + RxD_dl1 <=0; + else + RxD_dl1 <=RxD; + +//--------------------------------------------------------------------------- +// Small pre-FIFO (acutally a synchronously clearable shift-register) for +// storing the first part of a packet before writing it to the "real" FIFO +// in MAC_rx_FF. This allows a packet to be dropped safely if an error +// happens in the beginning of a packet (or if the MAC address doesn't pass +// the receive filter!) +//--------------------------------------------------------------------------- + + reg pre_fifo_data_drop; + reg pre_fifo_data_en; + reg pre_fifo_data_err; + reg pre_fifo_data_end; + wire [7:0] pre_fifo_wrdata; + + reg [8+3-1:0] pre_fifo_element_0; + reg [8+3-1:0] pre_fifo_element_1; + reg [8+3-1:0] pre_fifo_element_2; + reg [8+3-1:0] pre_fifo_element_3; + reg [8+3-1:0] pre_fifo_element_4; + reg [8+3-1:0] pre_fifo_element_5; + reg [8+3-1:0] pre_fifo_element_6; + reg [8+3-1:0] pre_fifo_element_7; + reg [8+3-1:0] pre_fifo_element_8; + reg [8+3-1:0] pre_fifo_element_9; + + always @( posedge Reset or posedge Clk ) + if ( Reset ) + begin + pre_fifo_element_0 <= 'b0; + pre_fifo_element_1 <= 'b0; + pre_fifo_element_2 <= 'b0; + pre_fifo_element_3 <= 'b0; + pre_fifo_element_4 <= 'b0; + pre_fifo_element_5 <= 'b0; + pre_fifo_element_6 <= 'b0; + pre_fifo_element_7 <= 'b0; + pre_fifo_element_8 <= 'b0; + pre_fifo_element_9 <= 'b0; + end + else + begin + if ( pre_fifo_data_drop ) + begin + pre_fifo_element_0 <= 'b0; + pre_fifo_element_1 <= 'b0; + pre_fifo_element_2 <= 'b0; + pre_fifo_element_3 <= 'b0; + pre_fifo_element_4 <= 'b0; + pre_fifo_element_5 <= 'b0; + pre_fifo_element_6 <= 'b0; + pre_fifo_element_7 <= 'b0; + pre_fifo_element_8 <= 'b0; + pre_fifo_element_9 <= 'b0; + end + else + begin + pre_fifo_element_0 <= pre_fifo_element_1; + pre_fifo_element_1 <= pre_fifo_element_2; + pre_fifo_element_2 <= pre_fifo_element_3; + pre_fifo_element_3 <= pre_fifo_element_4; + pre_fifo_element_4 <= pre_fifo_element_5; + pre_fifo_element_5 <= pre_fifo_element_6; + pre_fifo_element_6 <= pre_fifo_element_7; + pre_fifo_element_7 <= pre_fifo_element_8; + pre_fifo_element_8 <= pre_fifo_element_9; + pre_fifo_element_9 <= { pre_fifo_data_en, + pre_fifo_data_err, + pre_fifo_data_end, + pre_fifo_wrdata }; + end + end + + assign Fifo_data = pre_fifo_element_0[7:0]; + assign Fifo_data_end = pre_fifo_element_0[8]; + assign Fifo_data_err = pre_fifo_element_0[9]; + assign Fifo_data_en = pre_fifo_element_0[10]; + + assign CRC_data = pre_fifo_wrdata; + assign MAC_add_data = pre_fifo_wrdata; + +//****************************************************************************** +//State_machine +//****************************************************************************** + +always @( posedge Reset or posedge Clk ) + if ( Reset ) + Current_state <= State_idle; + else + Current_state <= Next_state; + +always @ (*) + case (Current_state) + State_idle: + if ( Crs_dv&&RxD==8'h55 ) + Next_state = State_preamble; + else + Next_state = Current_state; + + State_preamble: + if ( !Crs_dv ) + Next_state = State_DropEnd; + else if ( RxErr ) + Next_state = State_DropEnd; + else if ( RxD==8'hd5 ) + Next_state = State_SFD; + else if ( RxD==8'h55 ) + Next_state =Current_state; + else + Next_state = State_DropEnd; + + State_SFD: + if ( !Crs_dv ) + Next_state = State_DropEnd; + else if ( RxErr ) + Next_state = State_DropEnd; + else + Next_state = State_data; + + State_data: + if ( !Crs_dv && !ProcessingHeader && !Too_short && !Too_long ) + Next_state = State_checkCRC; + else if ( !Crs_dv && ProcessingHeader ) + Next_state = State_Drop2End; + else if ( !Crs_dv && (Too_short | Too_long) ) + Next_state = State_ErrEnd; + else if ( Fifo_full ) + Next_state = State_FFFullErrEnd; + else if ( RxErr && ProcessingHeader ) + Next_state = State_Drop2End; + else if ( RxErr || Too_long ) + Next_state = State_ErrEnd; + else if ( MAC_rx_add_chk_err || broadcast_drop ) + Next_state = State_DropEnd; + else + Next_state = State_data; + + State_checkCRC: + if ( CRC_err ) + Next_state = State_CRCErrEnd; + else + Next_state = State_OkEnd; + + State_OkEnd: + Next_state = State_IFG; + + State_ErrEnd: + Next_state = State_IFG; + + State_DropEnd: + Next_state = State_IFG; + + State_Drop2End: + Next_state = State_IFG; + + State_CRCErrEnd: + Next_state = State_IFG; + + State_FFFullErrEnd: + Next_state = State_FFFullDrop; + + State_FFFullDrop: + if ( !Crs_dv ) + Next_state =State_IFG; + else + Next_state =Current_state; + + State_IFG: + if ( IFG_counter==RX_IFG_SET-4 ) // Remove some additional time? + Next_state = State_idle; + else + Next_state = Current_state; + + default: + Next_state = State_idle; + endcase + +always @( posedge Reset or posedge Clk ) + if ( Reset ) + IFG_counter <= 0; + else if ( Current_state!=State_IFG ) + IFG_counter <= 0; + else + IFG_counter <= IFG_counter + 1; + +//****************************************************************************** +//gen fifo interface signals +//****************************************************************************** + +assign pre_fifo_wrdata = RxD_dl1; + +always @( Current_state ) + if ( Current_state==State_data ) + pre_fifo_data_en = 1; + else + pre_fifo_data_en = 0; + +always @( Current_state ) + if ( (Current_state==State_ErrEnd ) || + (Current_state==State_OkEnd ) || + (Current_state==State_CRCErrEnd ) || + (Current_state==State_FFFullErrEnd) || + (Current_state==State_DropEnd ) || + (Current_state==State_Drop2End ) ) + pre_fifo_data_end = 1; + else + pre_fifo_data_end = 0; + +always @( Current_state ) + if ( (Current_state==State_ErrEnd ) || + (Current_state==State_CRCErrEnd ) || + (Current_state==State_FFFullErrEnd) || + (Current_state==State_DropEnd ) || + (Current_state==State_Drop2End ) ) + pre_fifo_data_err = 1; + else + pre_fifo_data_err = 0; + +always @( Current_state ) + if ( (Current_state==State_DropEnd ) || + (Current_state==State_Drop2End) ) + pre_fifo_data_drop = 1; + else + pre_fifo_data_drop = 0; + + // Drop in main Rx FIFO is no longer supported! + assign Fifo_data_drop = 0; + +//****************************************************************************** +//CRC_chk interface +//****************************************************************************** + +always @(Current_state) + if (Current_state==State_data) + CRC_en =1; + else + CRC_en =0; + +always @(Current_state) + if (Current_state==State_SFD) + CRC_init =1; + else + CRC_init =0; + +//****************************************************************************** +//gen rmon signals +//****************************************************************************** +always @ (posedge Clk or posedge Reset) + if (Reset) + Frame_length_counter <=0; + else if (Current_state==State_SFD) + Frame_length_counter <=1; + else if (Current_state==State_data) + Frame_length_counter <=Frame_length_counter+ 1'b1; + +always @( Frame_length_counter ) + if ( Frame_length_counter < 8 ) + ProcessingHeader = 1; + else + ProcessingHeader = 0; + +always @ (Frame_length_counter or RX_MIN_LENGTH) + if (Frame_length_counterRX_MAX_LENGTH) + Too_long =1; + else + Too_long =0; + +assign Rx_pkt_length_rmon = Frame_length_counter-1'b1; + +reg [2:0] Rx_apply_rmon_reg; + +always @( posedge Clk or posedge Reset ) + if ( Reset ) + begin + Rx_apply_rmon <= 0; + Rx_apply_rmon_reg <= 'b0; + end + else + begin + if ( (Current_state==State_OkEnd ) || + (Current_state==State_ErrEnd ) || + (Current_state==State_CRCErrEnd ) || + (Current_state==State_Drop2End ) || + (Current_state==State_FFFullErrEnd) ) + Rx_apply_rmon <= 1; + else + if ( Rx_apply_rmon_reg[2] ) + Rx_apply_rmon <= 0; + + Rx_apply_rmon_reg <= { Rx_apply_rmon_reg[1:0], Rx_apply_rmon }; + end + +always @ (posedge Clk or posedge Reset) + if (Reset) + Rx_pkt_err_type_rmon <=0; + else if (Current_state==State_CRCErrEnd) + Rx_pkt_err_type_rmon <=3'b001 ;// + else if (Current_state==State_FFFullErrEnd) + Rx_pkt_err_type_rmon <=3'b010 ;// + else if ( (Current_state==State_ErrEnd) || (Current_state==State_Drop2End) ) + Rx_pkt_err_type_rmon <=3'b011 ;// + else if(Current_state==State_OkEnd) + Rx_pkt_err_type_rmon <=3'b100 ; + + + +always @ (posedge Clk or posedge Reset) + if (Reset) + Rx_pkt_type_rmon <=0; + else if (Current_state==State_OkEnd&&pause_frame_ptr) + Rx_pkt_type_rmon <=3'b100 ;// + else if(Current_state==State_SFD&&Next_state==State_data) + Rx_pkt_type_rmon <={1'b0,MRxD[7:6]}; + +always @ (posedge Clk or posedge Reset) + if (Reset) + broadcast_ptr <=0; + else if(Current_state==State_IFG) + broadcast_ptr <=0; + else if(Current_state==State_SFD&&Next_state==State_data&&MRxD[7:6]==2'b11) + broadcast_ptr <=1; + + + +//****************************************************************************** +//MAC add checker signals +//****************************************************************************** +always @ (Frame_length_counter or pre_fifo_data_en) + if(Frame_length_counter>=1&&Frame_length_counter<=6) + MAC_add_en <=pre_fifo_data_en; + else + MAC_add_en <=0; + +//****************************************************************************** +//flow control signals +//****************************************************************************** +always @ (posedge Clk or posedge Reset) + if (Reset) + Pause_current <=Pause_idle; + else + Pause_current <=Pause_next; + +always @ (*) + case (Pause_current) + Pause_idle : + if(Current_state==State_SFD) + Pause_next =Pause_pre_syn; + else + Pause_next =Pause_current; + Pause_pre_syn: + case (Frame_length_counter) + 16'd1: if (RxD_dl1==8'h01) + Pause_next =Pause_current; + else + Pause_next =Pause_idle; + 16'd2: if (RxD_dl1==8'h80) + Pause_next =Pause_current; + else + Pause_next =Pause_idle; + 16'd3: if (RxD_dl1==8'hc2) + Pause_next =Pause_current; + else + Pause_next =Pause_idle; + 16'd4: if (RxD_dl1==8'h00) + Pause_next =Pause_current; + else + Pause_next =Pause_idle; + 16'd5: if (RxD_dl1==8'h00) + Pause_next =Pause_current; + else + Pause_next =Pause_idle; + 16'd6: if (RxD_dl1==8'h01) + Pause_next =Pause_current; + else + Pause_next =Pause_idle; + 16'd13: if (RxD_dl1==8'h88) + Pause_next =Pause_current; + else + Pause_next =Pause_idle; + 16'd14: if (RxD_dl1==8'h08) + Pause_next =Pause_current; + else + Pause_next =Pause_idle; + 16'd15: if (RxD_dl1==8'h00) + Pause_next =Pause_current; + else + Pause_next =Pause_idle; + 16'd16: if (RxD_dl1==8'h01) + Pause_next =Pause_quanta_hi; + else + Pause_next =Pause_idle; + default: Pause_next =Pause_current; + endcase + Pause_quanta_hi : + Pause_next =Pause_quanta_lo; + Pause_quanta_lo : + Pause_next =Pause_syn; + Pause_syn : + if (Current_state==State_IFG) + Pause_next =Pause_idle; + else + Pause_next =Pause_current; + default + Pause_next =Pause_idle; + endcase + +always @ (posedge Clk or posedge Reset) + if (Reset) + pause_quanta_h <=0; + else if(Pause_current==Pause_quanta_hi) + pause_quanta_h <=RxD_dl1; + +always @ (posedge Clk or posedge Reset) + if (Reset) + pause_quanta <=0; + else if(Pause_current==Pause_quanta_lo) + pause_quanta <={pause_quanta_h,RxD_dl1}; + + // The following 2 always blocks are a strange way of holding + // pause_quanta_val high for 2 cycles +always @ (posedge Clk or posedge Reset) + if (Reset) + pause_quanta_val_tmp <=0; + else if(Current_state==State_OkEnd&&Pause_current==Pause_syn) + pause_quanta_val_tmp <=1; + else + pause_quanta_val_tmp <=0; + +always @ (posedge Clk or posedge Reset) + if (Reset) + pause_quanta_val <=0; + else if(Current_state==State_OkEnd&&Pause_current==Pause_syn||pause_quanta_val_tmp) + pause_quanta_val <=1; + else + pause_quanta_val <=0; + +always @ (posedge Clk or posedge Reset) + if (Reset) + pause_frame_ptr <=0; + else if(Pause_current==Pause_syn) + pause_frame_ptr <=1; + else + pause_frame_ptr <=0; + +endmodule + + diff --git a/eth/rtl/verilog/MAC_top.v b/eth/rtl/verilog/MAC_top.v new file mode 100644 index 000000000..d93b287ce --- /dev/null +++ b/eth/rtl/verilog/MAC_top.v @@ -0,0 +1,516 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// MAC_top.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source 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 Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// + +module MAC_top + #(parameter TX_FF_DEPTH = 9, + parameter RX_FF_DEPTH = 9) + ( + // System signals + input Clk_125M, + input Clk_user, + + input rst_mac, + input rst_user, + + // Wishbone compliant core host interface + input RST_I, // Active high (async) reset of the Wishbone interface + input CLK_I, // Wishbone interface clock (nominally 50 MHz) + input STB_I, // Active high module-select + input CYC_I, // Active high cycle-enable + input [6:0] ADR_I, // Module register address + input WE_I, // Active high for writes, low for reads + input [31:0] DAT_I, // Write data + output [31:0] DAT_O, // Read data + output ACK_O, // Acknowledge output – single high pulse + + // User (packet) interface + output Rx_mac_empty, + input Rx_mac_rd, + output [31:0] Rx_mac_data, + output [1:0] Rx_mac_BE, + output Rx_mac_sop, + output Rx_mac_eop, + output Rx_mac_err, + + output Tx_mac_wa, + input Tx_mac_wr, + input [31:0] Tx_mac_data, + input [1:0] Tx_mac_BE, + input Tx_mac_sop, + input Tx_mac_eop, + + // PHY interface (GMII/MII) + output Gtx_clk, // Used only in GMII mode + input Rx_clk, + input Tx_clk, // Used only in MII mode + output Tx_er, + output Tx_en, + output [7:0] Txd, + input Rx_er, + input Rx_dv, + input [7:0] Rxd, + input Crs, + input Col, + + // MDIO interface (to PHY) + inout Mdio, + output Mdc, + + // FIFO levels + output [15:0] rx_fifo_occupied, + output rx_fifo_full, + output rx_fifo_empty, + output [15:0] tx_fifo_occupied, + output tx_fifo_full, + output tx_fifo_empty, + + // Debug Interface + output [31:0] debug0, + output [31:0] debug1 +); + + wire rst_mac_rx = rst_mac; + wire rst_mac_tx = rst_mac; + wire [2:0] Speed; + + wire [31:0] debug_rx; + wire [31:0] debug_tx0; + wire [31:0] debug_tx1; + + //------------------------------------------------------------------------- + // Local declarations + //------------------------------------------------------------------------- + + // RMON interface + wire [15:0] Rx_pkt_length_rmon; + wire Rx_apply_rmon; + wire [2:0] Rx_pkt_err_type_rmon; + wire [2:0] Rx_pkt_type_rmon; + wire [2:0] Tx_pkt_type_rmon; + wire [15:0] Tx_pkt_length_rmon; + wire Tx_apply_rmon; + wire [2:0] Tx_pkt_err_type_rmon; + + // PHY interface + wire MCrs_dv; + wire [7:0] MRxD; + wire MRxErr; + + // Flow-control signals + wire [15:0] pause_quanta; + wire pause_quanta_val; + wire [15:0] rx_fifo_space; + wire pause_apply, pause_quanta_sub; + wire xon_gen, xoff_gen, xon_gen_complete, xoff_gen_complete; + wire [15:0] fc_hwmark, fc_lwmark; + + //PHY interface + wire [7:0] MTxD; + wire MTxEn; + wire MCRS; + + // Interface clk signals + wire MAC_tx_clk; + wire MAC_rx_clk; + wire MAC_tx_clk_div; + wire MAC_rx_clk_div; + + // Reg signals + wire [4:0] Tx_Hwmark; + wire [4:0] Tx_Lwmark; + wire pause_frame_send_en; + wire [15:0] pause_quanta_set; + wire MAC_tx_add_en; + wire FullDuplex; + wire [3:0] MaxRetry; + wire [5:0] IFGset; + wire [7:0] MAC_tx_add_prom_data; + wire [2:0] MAC_tx_add_prom_add; + wire MAC_tx_add_prom_wr; + wire tx_pause_en; + + // Rx host interface + wire MAC_rx_add_chk_en; + wire [7:0] MAC_rx_add_prom_data; + wire [2:0] MAC_rx_add_prom_add; + wire MAC_rx_add_prom_wr; + wire broadcast_filter_en; + wire RX_APPEND_CRC; + wire [4:0] Rx_Hwmark; + wire [4:0] Rx_Lwmark; + wire CRC_chk_en; + wire [5:0] RX_IFG_SET; + wire [15:0] RX_MAX_LENGTH; + wire [6:0] RX_MIN_LENGTH; + + // RMON host interface + wire [5:0] CPU_rd_addr; + wire CPU_rd_apply; + wire CPU_rd_grant; + wire [31:0] CPU_rd_dout; + + // PHY int host interface + wire Line_loop_en; + + // MII to CPU + wire [7:0] Divider; + wire [15:0] CtrlData; + wire [4:0] Rgad; + wire [4:0] Fiad; + wire NoPre; + wire WCtrlData; + wire RStat; + wire ScanStat; + wire Busy; + wire LinkFail; + wire Nvalid; + wire [15:0] Prsd; + wire WCtrlDataStart; + wire RStatStart; + wire UpdateMIIRX_DATAReg; + wire [15:0] broadcast_bucket_depth; + wire [15:0] broadcast_bucket_interval; + + //------------------------------------------------------------------------- + // Instantiation of sub-modules + //------------------------------------------------------------------------- + + MAC_rx #(.RX_FF_DEPTH(RX_FF_DEPTH)) + U_MAC_rx( + .Reset ( rst_mac_rx ), + .Clk_user ( Clk_user ), + .Clk ( MAC_rx_clk_div ), + + // RMII interface + .MCrs_dv ( MCrs_dv ), + .MRxD ( MRxD ), + .MRxErr ( MRxErr ), + + // Flow-control signals + .pause_quanta ( pause_quanta ), + .pause_quanta_val ( pause_quanta_val ), + .rx_fifo_space ( rx_fifo_space ), + + // User interface + .Rx_mac_empty ( Rx_mac_empty ), + .Rx_mac_rd ( Rx_mac_rd ), + .Rx_mac_data ( Rx_mac_data ), + .Rx_mac_BE ( Rx_mac_BE ), + .Rx_mac_sop ( Rx_mac_sop ), + .Rx_mac_eop ( Rx_mac_eop ), + .Rx_mac_err ( Rx_mac_err ), + + // CPU + .MAC_rx_add_chk_en ( MAC_rx_add_chk_en ), + .MAC_add_prom_data ( MAC_rx_add_prom_data ), + .MAC_add_prom_add ( MAC_rx_add_prom_add ), + .MAC_add_prom_wr ( MAC_rx_add_prom_wr ), + .broadcast_filter_en ( broadcast_filter_en ), + .broadcast_bucket_depth ( broadcast_bucket_depth ), + .broadcast_bucket_interval( broadcast_bucket_interval ), + .RX_APPEND_CRC ( RX_APPEND_CRC ), + .Rx_Hwmark ( Rx_Hwmark ), + .Rx_Lwmark ( Rx_Lwmark ), + .CRC_chk_en ( CRC_chk_en ), + .RX_IFG_SET ( RX_IFG_SET ), + .RX_MAX_LENGTH ( RX_MAX_LENGTH ), + .RX_MIN_LENGTH ( RX_MIN_LENGTH ), + + // RMON interface + .Rx_pkt_length_rmon ( Rx_pkt_length_rmon ), + .Rx_apply_rmon ( Rx_apply_rmon ), + .Rx_pkt_err_type_rmon ( Rx_pkt_err_type_rmon ), + .Rx_pkt_type_rmon ( Rx_pkt_type_rmon ), + + .rx_fifo_occupied(rx_fifo_occupied), + .rx_fifo_full(rx_fifo_full), + .rx_fifo_empty(rx_fifo_empty), + .debug(debug_rx) + ); + + MAC_tx #(.TX_FF_DEPTH(TX_FF_DEPTH)) + U_MAC_tx( + .Reset ( rst_mac_tx ), + .Clk ( MAC_tx_clk_div ), + //.Clk_user ( Clk_user ), + .Clk_user ( MAC_tx_clk_div ), + + // PHY interface + .TxD ( MTxD ), + .TxEn ( MTxEn ), + .CRS ( MCRS ), + + // RMON + .Tx_pkt_type_rmon ( Tx_pkt_type_rmon ), + .Tx_pkt_length_rmon ( Tx_pkt_length_rmon ), + .Tx_apply_rmon ( Tx_apply_rmon ), + .Tx_pkt_err_type_rmon( Tx_pkt_err_type_rmon ), + + // User interface + .Tx_mac_wa ( Tx_mac_wa ), + .Tx_mac_wr ( Tx_mac_wr ), + .Tx_mac_data ( Tx_mac_data ), + .Tx_mac_BE ( Tx_mac_BE ), + .Tx_mac_sop ( Tx_mac_sop ), + .Tx_mac_eop ( Tx_mac_eop ), + + // Host interface + .Tx_Hwmark ( Tx_Hwmark ), + .Tx_Lwmark ( Tx_Lwmark ), + .MAC_tx_add_en ( MAC_tx_add_en ), + .FullDuplex ( FullDuplex ), + .MaxRetry ( MaxRetry ), + .IFGset ( IFGset ), + .MAC_add_prom_data ( MAC_tx_add_prom_data ), + .MAC_add_prom_add ( MAC_tx_add_prom_add ), + .MAC_add_prom_wr ( MAC_tx_add_prom_wr ), + + .pause_apply ( pause_apply ), + .pause_quanta_sub ( pause_quanta_sub ), + .pause_quanta_set ( pause_quanta_set ), + .xoff_gen ( xoff_gen ), + .xon_gen ( xon_gen ), + .xoff_gen_complete ( xoff_gen_complete ), + .xon_gen_complete ( xon_gen_complete ), + .debug0(debug_tx0), + .debug1(debug_tx1) + ); + + // Flow control outbound -- when other side sends PAUSE, we wait + flow_ctrl_tx flow_ctrl_tx + (.rst(rst_mac_tx), + .tx_clk(MAC_tx_clk_div), + // Setting + .tx_pause_en ( tx_pause_en ), + // From RX side + .pause_quanta (pause_quanta), + .pause_quanta_val(pause_quanta_val), // Other guy sent a PAUSE + // To TX side + .pause_apply (pause_apply), // To TX, stop sending new frames + .pause_quanta_sub (pause_quanta_sub) // From TX, indicates we have used up 1 quanta + ); + + flow_ctrl_rx flow_ctrl_rx // When we are running out of RX space, send a PAUSE + (.rst(rst_mac_rx), // FIXME + // Settings + .pause_frame_send_en ( pause_frame_send_en ), + .pause_quanta_set ( pause_quanta_set ), + .fc_hwmark (fc_hwmark), + .fc_lwmark (fc_lwmark), + // From RX side + .rx_clk(MAC_rx_clk_div), + .rx_fifo_space (rx_fifo_space), // Decide if we need to send a PAUSE + // To TX side + .tx_clk(MAC_tx_clk_div), + .xoff_gen (xoff_gen), + .xon_gen(xon_gen), // Tell our TX to send PAUSE frames + .xoff_gen_complete (xoff_gen_complete), + .xon_gen_complete(xon_gen_complete) + ); + + RMON U_RMON( + .Clk ( CLK_I ), + .Reset ( RST_I ), + + // Tx RMON + .Tx_pkt_type_rmon ( Tx_pkt_type_rmon ), + .Tx_pkt_length_rmon ( Tx_pkt_length_rmon ), + .Tx_apply_rmon ( Tx_apply_rmon ), + .Tx_pkt_err_type_rmon( Tx_pkt_err_type_rmon ), + + // Rx RMON + .Rx_pkt_type_rmon ( Rx_pkt_type_rmon ), + .Rx_pkt_length_rmon ( Rx_pkt_length_rmon ), + .Rx_apply_rmon ( Rx_apply_rmon ), + .Rx_pkt_err_type_rmon( Rx_pkt_err_type_rmon ), + + // CPU + .CPU_rd_addr ( CPU_rd_addr ), + .CPU_rd_apply ( CPU_rd_apply ), + .CPU_rd_grant ( CPU_rd_grant ), + .CPU_rd_dout ( CPU_rd_dout ) + ); + + Phy_int U_Phy_int( + .rst_mac_rx ( rst_mac_rx ), + .rst_mac_tx ( rst_mac_tx ), + .MAC_rx_clk ( MAC_rx_clk ), + .MAC_tx_clk ( MAC_tx_clk ), + // Rx interface + .MCrs_dv ( MCrs_dv ), + .MRxD ( MRxD ), + .MRxErr ( MRxErr ), + // Tx interface + .MTxD ( MTxD ), + .MTxEn ( MTxEn ), + .MCRS ( MCRS ), + // PHY interface + .Tx_er ( Tx_er ), + .Tx_en ( Tx_en ), + .Txd ( Txd ), + .Rx_er ( Rx_er ), + .Rx_dv ( Rx_dv ), + .Rxd ( Rxd ), + .Crs ( Crs ), + .Col ( Col ), + // Host interface + .Line_loop_en( Line_loop_en ), + .Speed ( Speed ) ); + + Clk_ctrl U_Clk_ctrl( + .Reset ( rst_mac ), + .Clk_125M ( Clk_125M ), + + // Host interface + .Speed ( Speed ), + + // Phy interface + .Gtx_clk ( Gtx_clk ), + .Rx_clk ( Rx_clk ), + .Tx_clk ( Tx_clk ), + + // Interface clocks + .MAC_tx_clk ( MAC_tx_clk ), + .MAC_rx_clk ( MAC_rx_clk ), + .MAC_tx_clk_div( MAC_tx_clk_div ), + .MAC_rx_clk_div( MAC_rx_clk_div ) + ); + + eth_miim U_eth_miim( + .Clk ( CLK_I ), + .Reset ( RST_I ), + .Divider ( Divider ), + .NoPre ( NoPre ), + .CtrlData ( CtrlData ), + .Rgad ( Rgad ), + .Fiad ( Fiad ), + .WCtrlData ( WCtrlData ), + .RStat ( RStat ), + .ScanStat ( ScanStat ), + .Mdio ( Mdio ), + .Mdc ( Mdc ), + .Busy ( Busy ), + .Prsd ( Prsd ), + .LinkFail ( LinkFail ), + .Nvalid ( Nvalid ), + .WCtrlDataStart ( WCtrlDataStart ), + .RStatStart ( RStatStart ), + .UpdateMIIRX_DATAReg( UpdateMIIRX_DATAReg ) + ); + + Reg_int U_Reg_int( + // Wishbone compliant core host interface + .CLK_I( CLK_I ), + .RST_I( RST_I ), + .STB_I( STB_I ), + .CYC_I( CYC_I ), + .ADR_I( ADR_I ), + .WE_I ( WE_I ), + .DAT_I( DAT_I ), + .DAT_O( DAT_O ), + .ACK_O( ACK_O ), + + // Tx host interface + .Tx_Hwmark ( Tx_Hwmark ), + .Tx_Lwmark ( Tx_Lwmark ), + .MAC_tx_add_en ( MAC_tx_add_en ), + .FullDuplex ( FullDuplex ), + .MaxRetry ( MaxRetry ), + .IFGset ( IFGset ), + .MAC_tx_add_prom_data ( MAC_tx_add_prom_data ), + .MAC_tx_add_prom_add ( MAC_tx_add_prom_add ), + .MAC_tx_add_prom_wr ( MAC_tx_add_prom_wr ), + + // Rx host interface + .MAC_rx_add_chk_en ( MAC_rx_add_chk_en ), + .MAC_rx_add_prom_data ( MAC_rx_add_prom_data ), + .MAC_rx_add_prom_add ( MAC_rx_add_prom_add ), + .MAC_rx_add_prom_wr ( MAC_rx_add_prom_wr ), + .broadcast_filter_en ( broadcast_filter_en ), + .broadcast_bucket_depth ( broadcast_bucket_depth ), + .broadcast_bucket_interval( broadcast_bucket_interval ), + .RX_APPEND_CRC ( RX_APPEND_CRC ), + .Rx_Hwmark ( Rx_Hwmark ), + .Rx_Lwmark ( Rx_Lwmark ), + .CRC_chk_en ( CRC_chk_en ), + .RX_IFG_SET ( RX_IFG_SET ), + .RX_MAX_LENGTH ( RX_MAX_LENGTH ), + .RX_MIN_LENGTH ( RX_MIN_LENGTH ), + + // Flow Control settings + .pause_frame_send_en ( pause_frame_send_en ), + .pause_quanta_set ( pause_quanta_set ), + .tx_pause_en ( tx_pause_en ), + .fc_hwmark ( fc_hwmark ), + .fc_lwmark ( fc_lwmark ), + + // RMON host interface + .CPU_rd_addr ( CPU_rd_addr ), + .CPU_rd_apply ( CPU_rd_apply ), + .CPU_rd_grant ( CPU_rd_grant ), + .CPU_rd_dout ( CPU_rd_dout ), + + // PHY int host interface + .Line_loop_en ( Line_loop_en ), + .Speed ( Speed ), + + // MII to CPU + .Divider ( Divider ), + .CtrlData ( CtrlData ), + .Rgad ( Rgad ), + .Fiad ( Fiad ), + .NoPre ( NoPre ), + .WCtrlData ( WCtrlData ), + .RStat ( RStat ), + .ScanStat ( ScanStat ), + .Busy ( Busy ), + .LinkFail ( LinkFail ), + .Nvalid ( Nvalid ), + .Prsd ( Prsd ), + .WCtrlDataStart ( WCtrlDataStart ), + .RStatStart ( RStatStart ), + .UpdateMIIRX_DATAReg ( UpdateMIIRX_DATAReg ) + ); + + assign debug0 = {xon_gen, xoff_gen, Tx_en, Rx_dv}; + //assign debug0 = {{debug_rx[3:0], xon_gen, xon_gen_complete, xoff_gen, xoff_gen_complete}, + // {1'b0,Rx_mac_err,Rx_mac_empty,Rx_mac_rd,Rx_mac_sop,Rx_mac_eop,Rx_mac_BE[1:0]}, + // {rx_fifo_space}}; + //assign debug0 = debug_tx0; + //assign debug1 = debug_tx1; +endmodule diff --git a/eth/rtl/verilog/MAC_tx.v b/eth/rtl/verilog/MAC_tx.v new file mode 100644 index 000000000..50b08dffb --- /dev/null +++ b/eth/rtl/verilog/MAC_tx.v @@ -0,0 +1,245 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// MAC_tx.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source 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 Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: MAC_tx.v,v $ +// Revision 1.4 2006/11/17 17:53:07 maverickist +// no message +// +// Revision 1.3 2006/01/19 14:07:53 maverickist +// verification is complete. +// +// Revision 1.2 2005/12/16 06:44:14 Administrator +// replaced tab with space. +// passed 9.6k length frame test. +// +// Revision 1.1.1.1 2005/12/13 01:51:44 Administrator +// no message +// + +module MAC_tx + #(parameter TX_FF_DEPTH = 9) + ( +input Reset , +input Clk , +input Clk_user , + //PHY interface +output [7:0] TxD , +output TxEn , +input CRS , + //RMON +output [2:0] Tx_pkt_type_rmon , +output [15:0] Tx_pkt_length_rmon , +output Tx_apply_rmon , +output [2:0] Tx_pkt_err_type_rmon, + //user interface +output Tx_mac_wa , +input Tx_mac_wr , +input [31:0] Tx_mac_data , +input [1:0] Tx_mac_BE ,//big endian +input Tx_mac_sop , +input Tx_mac_eop , + //host interface +input [4:0] Tx_Hwmark , +input [4:0] Tx_Lwmark , +input MAC_tx_add_en , +input FullDuplex , +input [3:0] MaxRetry , +input [5:0] IFGset , +input [7:0] MAC_add_prom_data , +input [2:0] MAC_add_prom_add , +input MAC_add_prom_wr , + // Flow control stuff +input pause_apply , +output pause_quanta_sub, +input [15:0] pause_quanta_set , +input xoff_gen, +input xon_gen, +output xoff_gen_complete, +output xon_gen_complete, + output [31:0] debug0, + output [31:0] debug1 +); + + // ****************************************************************************** + // internal signals + // ****************************************************************************** + //CRC_gen Interface +wire CRC_init ; +wire[7:0] Frame_data ; +wire Data_en ; +wire CRC_rd ; +wire CRC_end ; +wire[7:0] CRC_out ; + //Random_gen interface +wire Random_init ; +wire[3:0] RetryCnt ; +wire Random_time_meet ;//levle hight indicate random time passed away + //flow control + //MAC_rx_FF +wire[7:0] Fifo_data ; +wire Fifo_rd ; +wire Fifo_eop ; +wire Fifo_da ; +wire Fifo_rd_finish ; +wire Fifo_rd_retry ; +wire Fifo_ra ; +wire Fifo_data_err_empty ; +wire Fifo_data_err_full ; + //MAC_tx_addr_add +wire MAC_tx_addr_init ; +wire MAC_tx_addr_rd ; +wire[7:0] MAC_tx_addr_data ; + +//****************************************************************************** +//instantiation +//****************************************************************************** +MAC_tx_ctrl U_MAC_tx_ctrl( +.Reset (Reset ), +.Clk (Clk ), + //CRC_gen Interface (//CRC_gen Interface ), +.CRC_init (CRC_init ), +.Frame_data (Frame_data ), +.Data_en (Data_en ), +.CRC_rd (CRC_rd ), +.CRC_end (CRC_end ), +.CRC_out (CRC_out ), + //Random_gen interfac (//Random_gen interfac ), +.Random_init (Random_init ), +.RetryCnt (RetryCnt ), +.Random_time_meet (Random_time_meet ), + //flow control (//flow control ), +.pause_apply (pause_apply ), +.pause_quanta_sub (pause_quanta_sub ), +.xoff_gen (xoff_gen ), +.xoff_gen_complete (xoff_gen_complete ), +.xon_gen (xon_gen ), +.xon_gen_complete (xon_gen_complete ), + //MAC_tx_FF (//MAC_tx_FF ), +.Fifo_data (Fifo_data ), +.Fifo_rd (Fifo_rd ), +.Fifo_eop (Fifo_eop ), +.Fifo_da (Fifo_da ), +.Fifo_rd_finish (Fifo_rd_finish ), +.Fifo_rd_retry (Fifo_rd_retry ), +.Fifo_ra (Fifo_ra ), +.Fifo_data_err_empty (Fifo_data_err_empty ), +.Fifo_data_err_full (Fifo_data_err_full ), + //RMII (//RMII ), +.TxD (TxD ), +.TxEn (TxEn ), +.CRS (CRS ), + //MAC_tx_addr_add (//MAC_tx_addr_add ), +.MAC_tx_addr_rd (MAC_tx_addr_rd ), +.MAC_tx_addr_data (MAC_tx_addr_data ), +.MAC_tx_addr_init (MAC_tx_addr_init ), + //RMON (//RMON ), +.Tx_pkt_type_rmon (Tx_pkt_type_rmon ), +.Tx_pkt_length_rmon (Tx_pkt_length_rmon ), +.Tx_apply_rmon (Tx_apply_rmon ), +.Tx_pkt_err_type_rmon (Tx_pkt_err_type_rmon ), + //CPU (//CPU ), +.pause_quanta_set (pause_quanta_set ), +.MAC_tx_add_en (MAC_tx_add_en ), +.FullDuplex (FullDuplex ), +.MaxRetry (MaxRetry ), +.IFGset (IFGset ) +); + +CRC_gen U_CRC_gen( +.Reset (Reset ), +.Clk (Clk ), +.Init (CRC_init ), +.Frame_data (Frame_data ), +.Data_en (Data_en ), +.CRC_rd (CRC_rd ), +.CRC_out (CRC_out ), +.CRC_end (CRC_end ) +); + + MAC_tx_addr_add U_MAC_tx_addr_add + (.Reset (Reset ), + .Clk (Clk ), + .MAC_tx_addr_rd (MAC_tx_addr_rd ), + .MAC_tx_addr_init (MAC_tx_addr_init ), + .MAC_tx_addr_data (MAC_tx_addr_data ), + //CPU + .MAC_add_prom_data (MAC_add_prom_data ), + .MAC_add_prom_add (MAC_add_prom_add ), + .MAC_add_prom_wr (MAC_add_prom_wr ) + ); + +MAC_tx_FF #(.TX_FF_DEPTH(TX_FF_DEPTH)) U_MAC_tx_FF( +.Reset (Reset ), +.Clk_MAC (Clk ), +.Clk_SYS (Clk_user ), + //MAC_rx_ctrl interf (//MAC_rx_ctrl interf ), +.Fifo_data (Fifo_data ), +.Fifo_rd (Fifo_rd ), +.Fifo_rd_finish (Fifo_rd_finish ), +.Fifo_rd_retry (Fifo_rd_retry ), +.Fifo_eop (Fifo_eop ), +.Fifo_da (Fifo_da ), +.Fifo_ra (Fifo_ra ), +.Fifo_data_err_empty (Fifo_data_err_empty ), +.Fifo_data_err_full (Fifo_data_err_full ), + //user interface (//user interface ), +.Tx_mac_wa (Tx_mac_wa ), +.Tx_mac_wr (Tx_mac_wr ), +.Tx_mac_data (Tx_mac_data ), +.Tx_mac_BE (Tx_mac_BE ), +.Tx_mac_sop (Tx_mac_sop ), +.Tx_mac_eop (Tx_mac_eop ), + //host interface (//host interface ), +.FullDuplex (FullDuplex ), +.Tx_Hwmark (Tx_Hwmark ), +.Tx_Lwmark (Tx_Lwmark ), +.debug0(debug0), +.debug1(debug1) +); + +Random_gen U_Random_gen( +.Reset (Reset ), +.Clk (Clk ), +.Init (Random_init ), +.RetryCnt (RetryCnt ), +.Random_time_meet (Random_time_meet ) +); + +endmodule diff --git a/eth/rtl/verilog/MAC_tx/CRC_gen.v b/eth/rtl/verilog/MAC_tx/CRC_gen.v new file mode 100644 index 000000000..4a16e7c36 --- /dev/null +++ b/eth/rtl/verilog/MAC_tx/CRC_gen.v @@ -0,0 +1,169 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// CRC_gen.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source 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 Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: CRC_gen.v,v $ +// Revision 1.3 2006/01/19 14:07:54 maverickist +// verification is complete. +// +// Revision 1.2 2005/12/16 06:44:17 Administrator +// replaced tab with space. +// passed 9.6k length frame test. +// +// Revision 1.1.1.1 2005/12/13 01:51:45 Administrator +// no message +// + +module CRC_gen ( +Reset , +Clk , +Init , +Frame_data , +Data_en , +CRC_rd , +CRC_end , +CRC_out + +); +input Reset ; +input Clk ; +input Init ; +input [7:0] Frame_data ; +input Data_en ; +input CRC_rd ; +output [7:0] CRC_out ; +output CRC_end ; + +//****************************************************************************** +//internal signals +//****************************************************************************** +reg [7:0] CRC_out ; +reg [31:0] CRC_reg; +reg CRC_end; +reg [3:0] Counter; +//****************************************************************************** +//****************************************************************************** +//input data width is 8bit, and the first bit is bit[0] +function[31:0] NextCRC; + input[7:0] D; + input[31:0] C; + reg[31:0] NewCRC; + begin + NewCRC[0]=C[24]^C[30]^D[1]^D[7]; + NewCRC[1]=C[25]^C[31]^D[0]^D[6]^C[24]^C[30]^D[1]^D[7]; + NewCRC[2]=C[26]^D[5]^C[25]^C[31]^D[0]^D[6]^C[24]^C[30]^D[1]^D[7]; + NewCRC[3]=C[27]^D[4]^C[26]^D[5]^C[25]^C[31]^D[0]^D[6]; + NewCRC[4]=C[28]^D[3]^C[27]^D[4]^C[26]^D[5]^C[24]^C[30]^D[1]^D[7]; + NewCRC[5]=C[29]^D[2]^C[28]^D[3]^C[27]^D[4]^C[25]^C[31]^D[0]^D[6]^C[24]^C[30]^D[1]^D[7]; + NewCRC[6]=C[30]^D[1]^C[29]^D[2]^C[28]^D[3]^C[26]^D[5]^C[25]^C[31]^D[0]^D[6]; + NewCRC[7]=C[31]^D[0]^C[29]^D[2]^C[27]^D[4]^C[26]^D[5]^C[24]^D[7]; + NewCRC[8]=C[0]^C[28]^D[3]^C[27]^D[4]^C[25]^D[6]^C[24]^D[7]; + NewCRC[9]=C[1]^C[29]^D[2]^C[28]^D[3]^C[26]^D[5]^C[25]^D[6]; + NewCRC[10]=C[2]^C[29]^D[2]^C[27]^D[4]^C[26]^D[5]^C[24]^D[7]; + NewCRC[11]=C[3]^C[28]^D[3]^C[27]^D[4]^C[25]^D[6]^C[24]^D[7]; + NewCRC[12]=C[4]^C[29]^D[2]^C[28]^D[3]^C[26]^D[5]^C[25]^D[6]^C[24]^C[30]^D[1]^D[7]; + NewCRC[13]=C[5]^C[30]^D[1]^C[29]^D[2]^C[27]^D[4]^C[26]^D[5]^C[25]^C[31]^D[0]^D[6]; + NewCRC[14]=C[6]^C[31]^D[0]^C[30]^D[1]^C[28]^D[3]^C[27]^D[4]^C[26]^D[5]; + NewCRC[15]=C[7]^C[31]^D[0]^C[29]^D[2]^C[28]^D[3]^C[27]^D[4]; + NewCRC[16]=C[8]^C[29]^D[2]^C[28]^D[3]^C[24]^D[7]; + NewCRC[17]=C[9]^C[30]^D[1]^C[29]^D[2]^C[25]^D[6]; + NewCRC[18]=C[10]^C[31]^D[0]^C[30]^D[1]^C[26]^D[5]; + NewCRC[19]=C[11]^C[31]^D[0]^C[27]^D[4]; + NewCRC[20]=C[12]^C[28]^D[3]; + NewCRC[21]=C[13]^C[29]^D[2]; + NewCRC[22]=C[14]^C[24]^D[7]; + NewCRC[23]=C[15]^C[25]^D[6]^C[24]^C[30]^D[1]^D[7]; + NewCRC[24]=C[16]^C[26]^D[5]^C[25]^C[31]^D[0]^D[6]; + NewCRC[25]=C[17]^C[27]^D[4]^C[26]^D[5]; + NewCRC[26]=C[18]^C[28]^D[3]^C[27]^D[4]^C[24]^C[30]^D[1]^D[7]; + NewCRC[27]=C[19]^C[29]^D[2]^C[28]^D[3]^C[25]^C[31]^D[0]^D[6]; + NewCRC[28]=C[20]^C[30]^D[1]^C[29]^D[2]^C[26]^D[5]; + NewCRC[29]=C[21]^C[31]^D[0]^C[30]^D[1]^C[27]^D[4]; + NewCRC[30]=C[22]^C[31]^D[0]^C[28]^D[3]; + NewCRC[31]=C[23]^C[29]^D[2]; + NextCRC=NewCRC; + end + endfunction +//****************************************************************************** + +always @ (posedge Clk) // or posedge Reset) +// if (Reset) +// CRC_reg <=32'hffffffff; +// else + if (Init) + CRC_reg <=32'hffffffff; + else if (Data_en) + CRC_reg <=NextCRC(Frame_data,CRC_reg); + else if (CRC_rd) + CRC_reg <={CRC_reg[23:0],8'hff}; + +always @ (CRC_rd or CRC_reg) +// if (CRC_rd) + CRC_out <=~{ + CRC_reg[24], + CRC_reg[25], + CRC_reg[26], + CRC_reg[27], + CRC_reg[28], + CRC_reg[29], + CRC_reg[30], + CRC_reg[31] + }; +// else +// CRC_out <=0; + +//caculate CRC out length ,4 cycles +//CRC_end aligned to last CRC checksum data +always @(posedge Clk or posedge Reset) + if (Reset) + Counter <=0; + else if (!CRC_rd) + Counter <=0; + else + Counter <=Counter + 1; + +always @ (Counter) + if (Counter==3) + CRC_end=1; + else + CRC_end=0; + +endmodule + + diff --git a/eth/rtl/verilog/MAC_tx/MAC_tx_FF.v b/eth/rtl/verilog/MAC_tx/MAC_tx_FF.v new file mode 100644 index 000000000..e62346fb7 --- /dev/null +++ b/eth/rtl/verilog/MAC_tx/MAC_tx_FF.v @@ -0,0 +1,722 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// MAC_tx_FF.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source 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 Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// + +module MAC_tx_FF + #(parameter TX_FF_DEPTH = 9) + (input Reset , + input Clk_MAC , + input Clk_SYS , + //MAC_tx_ctrl + output reg [7:0]Fifo_data , + input Fifo_rd , + input Fifo_rd_finish , + input Fifo_rd_retry , + output reg Fifo_eop , + output reg Fifo_da , + output reg Fifo_ra , + output reg Fifo_data_err_empty , + output Fifo_data_err_full , + //user interface + output reg Tx_mac_wa , + input Tx_mac_wr , + input [31:0] Tx_mac_data , + input [1:0] Tx_mac_BE ,//big endian + input Tx_mac_sop , + input Tx_mac_eop , + //host interface + input FullDuplex , + input [4:0] Tx_Hwmark , + input [4:0] Tx_Lwmark , + output [31:0] debug0, + output [31:0] debug1 + ); + +//****************************************************************************** +//internal signals +//****************************************************************************** +localparam MAC_byte3 =4'd00; +localparam MAC_byte2 =4'd01; +localparam MAC_byte1 =4'd02; +localparam MAC_byte0 =4'd03; +localparam MAC_wait_finish =4'd04; +localparam MAC_retry =4'd08; +localparam MAC_idle =4'd09; +localparam MAC_FFEmpty =4'd10; +localparam MAC_FFEmpty_drop =4'd11; +localparam MAC_pkt_sub =4'd12; +localparam MAC_FF_Err =4'd13; + + +reg [3:0] Next_state_MAC ; + + +localparam SYS_idle =4'd0; +localparam SYS_WaitSop =4'd1; +localparam SYS_SOP =4'd2; +localparam SYS_MOP =4'd3; +localparam SYS_DROP =4'd4; +localparam SYS_EOP_ok =4'd5; +localparam SYS_FFEmpty =4'd6; +localparam SYS_EOP_err =4'd7; +localparam SYS_SOP_err =4'd8; + +reg [3:0] Next_state_SYS; + +reg [TX_FF_DEPTH-1:0] Add_wr ; +reg [TX_FF_DEPTH-1:0] Add_wr_ungray ; +reg [TX_FF_DEPTH-1:0] Add_wr_gray ; +reg [TX_FF_DEPTH-1:0] Add_wr_gray_dl1 ; +reg [TX_FF_DEPTH-1:0] Add_wr_gray_dl2 ; + +reg [TX_FF_DEPTH-1:0] Add_rd ; +reg [TX_FF_DEPTH-1:0] Add_rd_reg ; +reg [TX_FF_DEPTH-1:0] Add_rd_gray ; +reg [TX_FF_DEPTH-1:0] Add_rd_gray_dl1 ; +reg [TX_FF_DEPTH-1:0] Add_rd_gray_dl2 ; +reg [TX_FF_DEPTH-1:0] Add_rd_ungray ; +wire[35:0] Din ; +wire[35:0] Dout ; +reg Wr_en ; +wire[TX_FF_DEPTH-1:0] Add_wr_pluse; +wire[TX_FF_DEPTH-1:0] Add_wr_pluse_pluse; +reg [TX_FF_DEPTH-1:TX_FF_DEPTH-5] Add_rd_reg_dl1; + +reg [3:0] Current_state_MAC; +reg [3:0] Current_state_MAC_reg; +reg [3:0] Current_state_SYS; +reg Full; +reg AlmostFull; +reg Empty; +reg [35:0] Dout_reg; +reg Packet_number_sub_edge; +reg Packet_number_add; +reg [5:0] Packet_number_inFF; +reg [5:0] Packet_number_inFF_reg; +reg Dout_reg_en; +reg Add_rd_add; + + +reg Tx_mac_wr_dl1 ; +reg [31:0] Tx_mac_data_dl1 ; +reg [1:0] Tx_mac_BE_dl1 ; +reg FF_FullErr ; +wire[1:0] Dout_BE ; +wire Dout_eop ; +wire Dout_err ; +wire[31:0] Dout_data ; +reg Packet_number_sub_dl1 ; +reg Packet_number_sub_dl2 ; +reg [4:0] Fifo_data_count ; +reg Fifo_ra_tmp ; +reg Pkt_sub_apply_tmp ; +reg Pkt_sub_apply ; +reg Add_rd_reg_rdy_tmp ; +reg Add_rd_reg_rdy ; +reg Add_rd_reg_rdy_dl1 ; +reg Add_rd_reg_rdy_dl2 ; +reg [4:0] Tx_Hwmark_pl ; +reg [4:0] Tx_Lwmark_pl ; +reg Add_rd_jump_tmp ; +reg Add_rd_jump_tmp_pl1 ; +reg Add_rd_jump ; +reg Add_rd_jump_wr_pl1 ; + +//****************************************************************************** +//write data to from FF . +//domain Clk_SYS +//****************************************************************************** +always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + Current_state_SYS <=SYS_idle; + else + Current_state_SYS <=Next_state_SYS; + +always @ (Current_state_SYS or Tx_mac_wr or Tx_mac_sop or Full or AlmostFull + or Tx_mac_eop ) + case (Current_state_SYS) + SYS_idle: + if (Tx_mac_wr&&Tx_mac_sop&&!Full) + Next_state_SYS =SYS_SOP; + else + Next_state_SYS =Current_state_SYS ; + SYS_SOP: + Next_state_SYS =SYS_MOP; + SYS_MOP: + if (AlmostFull) + Next_state_SYS =SYS_DROP; + else if (Tx_mac_wr&&Tx_mac_sop) + Next_state_SYS =SYS_SOP_err; + else if (Tx_mac_wr&&Tx_mac_eop) + Next_state_SYS =SYS_EOP_ok; + else + Next_state_SYS =Current_state_SYS ; + SYS_EOP_ok: + if (Tx_mac_wr&&Tx_mac_sop) + Next_state_SYS =SYS_SOP; + else + Next_state_SYS =SYS_idle; + SYS_EOP_err: + if (Tx_mac_wr&&Tx_mac_sop) + Next_state_SYS =SYS_SOP; + else + Next_state_SYS =SYS_idle; + SYS_SOP_err: + Next_state_SYS =SYS_DROP; + SYS_DROP: //FIFO overflow + if (Tx_mac_wr&&Tx_mac_eop) + Next_state_SYS =SYS_EOP_err; + else + Next_state_SYS =Current_state_SYS ; + default: + Next_state_SYS =SYS_idle; + endcase + +//delay signals +always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + begin + Tx_mac_wr_dl1 <=0; + Tx_mac_data_dl1 <=0; + Tx_mac_BE_dl1 <=0; + end + else + begin + Tx_mac_wr_dl1 <=Tx_mac_wr ; + Tx_mac_data_dl1 <=Tx_mac_data ; + Tx_mac_BE_dl1 <=Tx_mac_BE ; + end + +always @(Current_state_SYS) + if (Current_state_SYS==SYS_EOP_err) + FF_FullErr =1; + else + FF_FullErr =0; + +reg Tx_mac_eop_gen; + +always @(Current_state_SYS) + if (Current_state_SYS==SYS_EOP_err||Current_state_SYS==SYS_EOP_ok) + Tx_mac_eop_gen =1; + else + Tx_mac_eop_gen =0; + +assign Din={Tx_mac_eop_gen,FF_FullErr,Tx_mac_BE_dl1,Tx_mac_data_dl1}; + +always @(Current_state_SYS or Tx_mac_wr_dl1) + if ((Current_state_SYS==SYS_SOP||Current_state_SYS==SYS_EOP_ok|| + Current_state_SYS==SYS_MOP||Current_state_SYS==SYS_EOP_err)&&Tx_mac_wr_dl1) + Wr_en = 1; + else + Wr_en = 0; + + +// + + +always @ (posedge Reset or posedge Clk_SYS) + if (Reset) + Add_wr_gray <=0; + else + begin : Add_wr_gray_loop + integer i; + Add_wr_gray[TX_FF_DEPTH-1] <=Add_wr[TX_FF_DEPTH-1]; + for (i=TX_FF_DEPTH-2;i>=0;i=i-1) + Add_wr_gray[i] <=Add_wr[i+1]^Add_wr[i]; + end + +always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + Add_rd_gray_dl1 <=0; + else + Add_rd_gray_dl1 <=Add_rd_gray; + + always @(posedge Clk_SYS or posedge Reset) + if (Reset) + Add_rd_gray_dl2 <= 0; + else + Add_rd_gray_dl2 <= Add_rd_gray_dl1; + +always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + Add_rd_jump_wr_pl1 <=0; + else + Add_rd_jump_wr_pl1 <=Add_rd_jump; + +always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + Add_rd_ungray =0; + else if (!Add_rd_jump_wr_pl1) + begin : Add_rd_ungray_loop + integer i; + Add_rd_ungray[TX_FF_DEPTH-1] = Add_rd_gray_dl2[TX_FF_DEPTH-1]; + for (i=TX_FF_DEPTH-2;i>=0;i=i-1) + Add_rd_ungray[i] = Add_rd_ungray[i+1]^Add_rd_gray_dl2[i]; + end + +assign Add_wr_pluse =Add_wr+1; +assign Add_wr_pluse_pluse =Add_wr+4; + +always @ (Add_wr_pluse or Add_rd_ungray) + if (Add_wr_pluse==Add_rd_ungray) + Full =1; + else + Full =0; + +always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + AlmostFull <=0; + else if (Add_wr_pluse_pluse==Add_rd_ungray) + AlmostFull <=1; + else + AlmostFull <=0; + +always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + Add_wr <= 0; + else if (Wr_en&&!Full) + Add_wr <= Add_wr +1; + +always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + begin + Packet_number_sub_dl1 <=0; + Packet_number_sub_dl2 <=0; + end + else + begin + Packet_number_sub_dl1 <=Pkt_sub_apply; + Packet_number_sub_dl2 <=Packet_number_sub_dl1; + end + +always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + Packet_number_sub_edge <=0; + else if (Packet_number_sub_dl1&!Packet_number_sub_dl2) + Packet_number_sub_edge <=1; + else + Packet_number_sub_edge <=0; + +always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + Packet_number_add <=0; + else if (Current_state_SYS==SYS_EOP_ok||Current_state_SYS==SYS_EOP_err) + Packet_number_add <=1; + else + Packet_number_add <=0; + + +always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + Packet_number_inFF <=0; + else if (Packet_number_add&&!Packet_number_sub_edge) + Packet_number_inFF <=Packet_number_inFF + 1'b1; + else if (!Packet_number_add&&Packet_number_sub_edge) + Packet_number_inFF <=Packet_number_inFF - 1'b1; + + +always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + Packet_number_inFF_reg <=0; + else + Packet_number_inFF_reg <=Packet_number_inFF; + +always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + begin + Add_rd_reg_rdy_dl1 <=0; + Add_rd_reg_rdy_dl2 <=0; + end + else + begin + Add_rd_reg_rdy_dl1 <=Add_rd_reg_rdy; + Add_rd_reg_rdy_dl2 <=Add_rd_reg_rdy_dl1; + end + +always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + Add_rd_reg_dl1 <=0; + else if (Add_rd_reg_rdy_dl1&!Add_rd_reg_rdy_dl2) + Add_rd_reg_dl1 <=Add_rd_reg[TX_FF_DEPTH-1:TX_FF_DEPTH-5]; + + + +always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + Fifo_data_count <=0; + else if (FullDuplex) + Fifo_data_count <=Add_wr[TX_FF_DEPTH-1:TX_FF_DEPTH-5]-Add_rd_ungray[TX_FF_DEPTH-1:TX_FF_DEPTH-5]; + else + Fifo_data_count <=Add_wr[TX_FF_DEPTH-1:TX_FF_DEPTH-5]-Add_rd_reg_dl1[TX_FF_DEPTH-1:TX_FF_DEPTH-5]; //for half duplex backoff requirement + + +always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + Fifo_ra_tmp <=0; + else if (Packet_number_inFF_reg>=1||Fifo_data_count>=Tx_Lwmark) + Fifo_ra_tmp <=1; + else + Fifo_ra_tmp <=0; + +always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + begin + Tx_Hwmark_pl <=0; + Tx_Lwmark_pl <=0; + end + else + begin + Tx_Hwmark_pl <=Tx_Hwmark; + Tx_Lwmark_pl <=Tx_Lwmark; + end + +always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + Tx_mac_wa <=0; + else if (Fifo_data_count>=Tx_Hwmark_pl) + Tx_mac_wa <=0; + else if (Fifo_data_count=0;i=i-1) + Add_rd_gray[i] <= Add_rd[i+1]^Add_rd[i]; + end +// + +always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Add_wr_gray_dl1 <=0; + else + Add_wr_gray_dl1 <=Add_wr_gray; + +always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Add_wr_gray_dl2 <=0; + else + Add_wr_gray_dl2 <=Add_wr_gray_dl1; + +always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Add_wr_ungray =0; + else + begin : Add_wr_ungray_loop + integer i; + Add_wr_ungray[TX_FF_DEPTH-1] = Add_wr_gray_dl2[TX_FF_DEPTH-1]; + for (i=TX_FF_DEPTH-2;i>=0;i=i-1) + Add_wr_ungray[i] = Add_wr_ungray[i+1]^Add_wr_gray_dl2[i]; + end + +//empty +always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Empty <=1; + else if (Add_rd==Add_wr_ungray) + Empty <=1; + else + Empty <=0; + +//ra +always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Fifo_ra <=0; + else + Fifo_ra <=Fifo_ra_tmp; + + + +always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Pkt_sub_apply_tmp <=0; + else if (Current_state_MAC==MAC_pkt_sub) + Pkt_sub_apply_tmp <=1; + else + Pkt_sub_apply_tmp <=0; + +always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Pkt_sub_apply <=0; + else if ((Current_state_MAC==MAC_pkt_sub)||Pkt_sub_apply_tmp) + Pkt_sub_apply <=1; + else + Pkt_sub_apply <=0; + +//reg Add_rd for collison retry +always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Add_rd_reg <=0; + else if (Fifo_rd_finish) + Add_rd_reg <=Add_rd; + +always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Add_rd_reg_rdy_tmp <=0; + else if (Fifo_rd_finish) + Add_rd_reg_rdy_tmp <=1; + else + Add_rd_reg_rdy_tmp <=0; + +always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Add_rd_reg_rdy <=0; + else if (Fifo_rd_finish||Add_rd_reg_rdy_tmp) + Add_rd_reg_rdy <=1; + else + Add_rd_reg_rdy <=0; + + +always @ (Current_state_MAC or Next_state_MAC) + if ((Current_state_MAC==MAC_idle||Current_state_MAC==MAC_byte0)&&Next_state_MAC==MAC_byte3) + Add_rd_add =1; + else + Add_rd_add =0; + + +always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Add_rd <=0; + else if (Current_state_MAC==MAC_retry) + Add_rd <= Add_rd_reg; + else if (Add_rd_add) + Add_rd <= Add_rd + 1; + +always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Add_rd_jump_tmp <=0; + else if (Current_state_MAC==MAC_retry) + Add_rd_jump_tmp <=1; + else + Add_rd_jump_tmp <=0; + +always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Add_rd_jump_tmp_pl1 <=0; + else + Add_rd_jump_tmp_pl1 <=Add_rd_jump_tmp; + +always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Add_rd_jump <=0; + else if (Current_state_MAC==MAC_retry) + Add_rd_jump <=1; + else if (Add_rd_jump_tmp_pl1) + Add_rd_jump <=0; + +//gen Fifo_data + + +always @ (Dout_data or Current_state_MAC) + case (Current_state_MAC) + MAC_byte3: + Fifo_data =Dout_data[31:24]; + MAC_byte2: + Fifo_data =Dout_data[23:16]; + MAC_byte1: + Fifo_data =Dout_data[15:8]; + MAC_byte0: + Fifo_data =Dout_data[7:0]; + default: + Fifo_data =0; + endcase + +always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Fifo_da <=0; + else if ((Current_state_MAC==MAC_byte0||Current_state_MAC==MAC_byte1|| + Current_state_MAC==MAC_byte2||Current_state_MAC==MAC_byte3)&&Fifo_rd&&!Fifo_eop) + Fifo_da <=1; + else + Fifo_da <=0; + +//gen Fifo_data_err_empty +assign Fifo_data_err_full=Dout_err; +//gen Fifo_data_err_empty +always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Current_state_MAC_reg <=0; + else + Current_state_MAC_reg <=Current_state_MAC; + +always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Fifo_data_err_empty <=0; + else if (Current_state_MAC_reg==MAC_FFEmpty) + Fifo_data_err_empty <=1; + else + Fifo_data_err_empty <=0; + +//always @ (posedge Clk_MAC) +// if (Current_state_MAC_reg==MAC_FF_Err) +// begin +// $finish(2); +// $display("mac_tx_FF meet error status at time :%t",$time); +// end + +//gen Fifo_eop aligned to last valid data byte +always @ ( Current_state_MAC or Dout_eop or Dout_BE ) + if ( ( ( Current_state_MAC==MAC_byte0 && Dout_BE==2'b00 ) || + ( Current_state_MAC==MAC_byte1 && Dout_BE==2'b11 ) || + ( Current_state_MAC==MAC_byte2 && Dout_BE==2'b10 ) || + ( Current_state_MAC==MAC_byte3 && Dout_BE==2'b01 ) ) && Dout_eop ) + Fifo_eop = 1; + else + Fifo_eop = 0; + + // Dual port RAM for FIFO + ram_2port #(.DWIDTH(36),.AWIDTH(TX_FF_DEPTH)) mac_tx_ff_ram + (.clka(Clk_SYS),.ena(1'b1),.wea(Wr_en),.addra(Add_wr),.dia(Din),.doa(), + .clkb(Clk_MAC),.enb(1'b1),.web(1'b0),.addrb(Add_rd),.dib(36'b0),.dob(Dout) ); + + assign debug0 = + { { 5'd0, Empty, Full, AlmostFull }, + { Current_state_SYS, Current_state_MAC }, + { Fifo_rd, Fifo_rd_finish, Fifo_rd_retry, Fifo_eop, Fifo_da, Fifo_ra, Fifo_data_err_empty, Fifo_data_err_full }, + { 2'b0, Dout_BE, Tx_mac_wa, Tx_mac_wr, Tx_mac_sop, Tx_mac_eop} }; + + assign debug1 = + { { 8'd0 }, + { 8'd0 }, + { 8'd0 }, + { 8'd0 } }; + +endmodule // MAC_tx_FF diff --git a/eth/rtl/verilog/MAC_tx/MAC_tx_addr_add.v b/eth/rtl/verilog/MAC_tx/MAC_tx_addr_add.v new file mode 100644 index 000000000..76026ce06 --- /dev/null +++ b/eth/rtl/verilog/MAC_tx/MAC_tx_addr_add.v @@ -0,0 +1,128 @@ +// //////////////////////////////////////////////////////////////////// +// // //// +// // MAC_tx_addr_add.v //// +// // //// +// // This file is part of the Ethernet IP core project //// +// // http://www.opencores.org/projects.cgi/wr_en/ethernet_tri_mode///// +// // //// +// // Author(s): //// +// // - Jon Gao (gaojon@yahoo.com) //// +// // //// +// // //// +// //////////////////////////////////////////////////////////////////// +// // //// +// // Copyright (C) 2001 Authors //// +// // //// +// // This source file may be used and distributed without //// +// // restriction provided that this copyright statement is not //// +// // removed from the file and that any derivative work contains //// +// // the original copyright notice and the associated disclaimer. //// +// // //// +// // This source file is free software; you can redistribute it //// +// // and/or modify it under the terms of the GNU Lesser General //// +// // Public License as published by the Free Software Foundation; //// +// // either version 2.1 of the License, or (at your option) any //// +// // later version. //// +// // //// +// // This source 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 Lesser General Public License for more //// +// // details. //// +// // //// +// // You should have received a copy of the GNU Lesser General //// +// // Public License along with this source; if not, download it //// +// // from http://www.opencores.org/lgpl.shtml //// +// // //// +// //////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: MAC_tx_addr_add.v,v $ +// Revision 1.3 2006/01/19 14:07:54 maverickist +// verification is complete. +// +// Revision 1.2 2005/12/16 06:44:18 Administrator +// replaced tab with space. +// passed 9.6k length frame test. +// +// Revision 1.1.1.1 2005/12/13 01:51:45 Administrator +// no message +// + +module MAC_tx_addr_add + (Reset , + Clk , + MAC_tx_addr_init , + MAC_tx_addr_rd , + MAC_tx_addr_data , + //CPU , + MAC_add_prom_data , + MAC_add_prom_add , + MAC_add_prom_wr + ); + + input Reset ; + input Clk ; + input MAC_tx_addr_rd ; + input MAC_tx_addr_init ; + output [7:0] MAC_tx_addr_data ; + //CPU ; + input [7:0] MAC_add_prom_data ; + input [2:0] MAC_add_prom_add ; + input MAC_add_prom_wr ; + + // ****************************************************************************** + // internal signals + // ****************************************************************************** + reg [2:0] add_rd; + wire [2:0] add_wr; + wire [7:0] din; + //wire [7:0] dout; + reg [7:0] dout; + wire wr_en; + reg MAC_add_prom_wr_dl1; + reg MAC_add_prom_wr_dl2; + // ****************************************************************************** + // write data from cpu to prom + // ****************************************************************************** + always @ (posedge Clk or posedge Reset) + if (Reset) + begin + MAC_add_prom_wr_dl1 <=0; + MAC_add_prom_wr_dl2 <=0; + end + else + begin + MAC_add_prom_wr_dl1 <=MAC_add_prom_wr; + MAC_add_prom_wr_dl2 <=MAC_add_prom_wr_dl1; + end + + assign wr_en =MAC_add_prom_wr_dl1&!MAC_add_prom_wr_dl2; + assign add_wr =MAC_add_prom_add; + assign din =MAC_add_prom_data; + + // ****************************************************************************** + // read data from cpu to prom + // ****************************************************************************** + always @ (posedge Clk or posedge Reset) + if (Reset) + add_rd <=0; + else if (MAC_tx_addr_init) + add_rd <=0; + else if (MAC_tx_addr_rd) + add_rd <=add_rd + 1; + assign MAC_tx_addr_data=dout; + // ****************************************************************************** + // b port for read ,a port for write . + // ****************************************************************************** + + reg [7:0] address_ram [0:7]; + always @(posedge Clk) + if(wr_en) + address_ram[add_wr] <= din; + + always @(posedge Clk) + dout <= address_ram[add_rd]; + +endmodule // MAC_tx_addr_add diff --git a/eth/rtl/verilog/MAC_tx/MAC_tx_ctrl.v b/eth/rtl/verilog/MAC_tx/MAC_tx_ctrl.v new file mode 100644 index 000000000..0fd7c603e --- /dev/null +++ b/eth/rtl/verilog/MAC_tx/MAC_tx_ctrl.v @@ -0,0 +1,648 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// MAC_tx_ctrl.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source 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 Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: MAC_tx_Ctrl.v,v $ +// Revision 1.4 2006/06/25 04:58:56 maverickist +// no message +// +// Revision 1.3 2006/01/19 14:07:54 maverickist +// verification is complete. +// +// Revision 1.3 2005/12/16 06:44:17 Administrator +// replaced tab with space. +// passed 9.6k length frame test. +// +// Revision 1.2 2005/12/13 12:15:38 Administrator +// no message +// +// Revision 1.1.1.1 2005/12/13 01:51:45 Administrator +// no message +// + +module MAC_tx_ctrl ( +Reset , +Clk , +//CRC_gen Interface +CRC_init , +Frame_data , +Data_en , +CRC_rd , +CRC_end , +CRC_out , +//Ramdon_gen interfac +Random_init , +RetryCnt , +Random_time_meet , +//flow control +pause_apply , +pause_quanta_sub , +xoff_gen , +xoff_gen_complete , +xon_gen , +xon_gen_complete , +//MAC_tx_FF +Fifo_data , +Fifo_rd , +Fifo_eop , +Fifo_da , +Fifo_rd_finish , +Fifo_rd_retry , +Fifo_ra , +Fifo_data_err_empty , +Fifo_data_err_full , +//RMII +TxD , +TxEn , +CRS , +//MAC_tx_addr_add +MAC_tx_addr_rd , +MAC_tx_addr_data , +MAC_tx_addr_init , +//RMON +Tx_pkt_type_rmon , +Tx_pkt_length_rmon , +Tx_apply_rmon , +Tx_pkt_err_type_rmon, +//CPU +pause_quanta_set , +MAC_tx_add_en , +FullDuplex , +MaxRetry , +IFGset +); + +input Reset ; +input Clk ; + //CRC_gen Interface +output CRC_init ; +output [7:0] Frame_data ; +output Data_en ; +output CRC_rd ; +input CRC_end ; +input [7:0] CRC_out ; + //Ramdon_gen interface +output Random_init ; +output [3:0] RetryCnt ; +input Random_time_meet ;//levle hight indicate random time passed away + //flow control +input pause_apply ; +output pause_quanta_sub ; +input xoff_gen ; +output xoff_gen_complete ; +input xon_gen ; +output xon_gen_complete ; + //MAC_rx_FF +input [7:0] Fifo_data ; +output Fifo_rd ; +input Fifo_eop ; +input Fifo_da ; +output Fifo_rd_finish ; +output Fifo_rd_retry ; +input Fifo_ra ; +input Fifo_data_err_empty ; +input Fifo_data_err_full ; + //RMII +output [7:0] TxD ; +output TxEn ; +input CRS ; + //MAC_tx_addr_add +output MAC_tx_addr_init ; +output MAC_tx_addr_rd ; +input [7:0] MAC_tx_addr_data ; + //RMON +output [2:0] Tx_pkt_type_rmon ; +output [15:0] Tx_pkt_length_rmon ; +output Tx_apply_rmon ; +output [2:0] Tx_pkt_err_type_rmon; + //CPU +input [15:0] pause_quanta_set ; +input MAC_tx_add_en ; +input FullDuplex ; +input [3:0] MaxRetry ; +input [5:0] IFGset ; +//****************************************************************************** +//internal signals +//****************************************************************************** +parameter StateIdle =4'd00; +parameter StatePreamble =4'd01; +parameter StateSFD =4'd02; +parameter StateData =4'd03; +parameter StatePause =4'd04; +parameter StatePAD =4'd05; +parameter StateFCS =4'd06; +parameter StateIFG =4'd07; +parameter StateJam =4'd08; +parameter StateBackOff =4'd09; +parameter StateJamDrop =4'd10; +parameter StateFFEmptyDrop =4'd11; +parameter StateSwitchNext =4'd12; +parameter StateDefer =4'd13; +parameter StateSendPauseFrame =4'd14; + +reg [3:0] Current_state; +reg [3:0] Next_state; +reg [5:0] IFG_counter; +reg [4:0] Preamble_counter;// +reg [7:0] TxD_tmp ; +reg TxEn_tmp ; +reg [15:0] Tx_pkt_length_rmon ; +reg Tx_apply_rmon ; +reg [2:0] Tx_pkt_err_type_rmon; +reg [3:0] RetryCnt ; +reg Random_init ; +reg Fifo_rd_finish ; +reg Fifo_rd_retry ; +reg [7:0] TxD ; +reg TxEn ; +reg CRC_init ; +reg Data_en ; +reg CRC_rd ; +reg Fifo_rd ; +reg MAC_tx_addr_rd ; +reg MAC_header_slot ; +reg MAC_header_slot_tmp ; +reg [2:0] Tx_pkt_type_rmon ; +wire Collision ; +reg MAC_tx_addr_init ; +reg Src_MAC_ptr ; +reg [7:0] IPLengthCounter ;//for pad append +reg [1:0] PADCounter ; +reg [7:0] JamCounter ; +reg PktDrpEvenPtr ; +reg [7:0] pause_counter ; +reg pause_quanta_sub ; +reg [15:0] pause_quanta_set_dl1 ; +reg xoff_gen_complete ; +reg xon_gen_complete ; +//****************************************************************************** +//boundery signal processing +//****************************************************************************** +always @(posedge Clk or posedge Reset) + if (Reset) + begin + pause_quanta_set_dl1 <=0; + end + else + begin + pause_quanta_set_dl1 <=pause_quanta_set ; + end +//****************************************************************************** +//state machine +//****************************************************************************** +assign Collision=TxEn&CRS; + +always @(posedge Clk or posedge Reset) + if (Reset) + IPLengthCounter <=0; + else if (Current_state==StateDefer) + IPLengthCounter <=0; + else if (IPLengthCounter!=8'hff&&(Current_state==StateData||Current_state==StateSendPauseFrame||Current_state==StatePAD)) + IPLengthCounter <=IPLengthCounter+1; + +always @(posedge Clk or posedge Reset) + if (Reset) + PADCounter <=0; + else if (Current_state!=StatePAD) + PADCounter <=0; + else + PADCounter <=PADCounter+1; + +always @(posedge Clk or posedge Reset) + if (Reset) + Current_state <=StateDefer; + else + Current_state <=Next_state; + +always @ (*) + case (Current_state) + StateDefer: + if ((FullDuplex)||(!FullDuplex&&!CRS)) + Next_state=StateIFG; + else + Next_state=Current_state; + StateIFG: + if (!FullDuplex&&CRS) + Next_state=StateDefer; + else if ((FullDuplex&&IFG_counter==IFGset-4)||(!FullDuplex&&!CRS&&IFG_counter==IFGset-4))//remove some additional time + Next_state=StateIdle; + else + Next_state=Current_state; + StateIdle: + if (!FullDuplex&&CRS) + Next_state=StateDefer; + else if (xoff_gen||xon_gen) + Next_state=StatePreamble; + else if (pause_apply) + Next_state=StatePause; + else if ((FullDuplex||~CRS)&&Fifo_ra) + Next_state=StatePreamble; + else + Next_state=Current_state; + StatePause: + if (pause_counter==512/8) + Next_state=StateDefer; + else if (xoff_gen||xon_gen) + Next_state=StateIdle; + else + Next_state=Current_state; + StatePreamble: + if (!FullDuplex&&Collision) + Next_state=StateJam; + else if ((FullDuplex&&Preamble_counter==6)||(!FullDuplex&&!Collision&&Preamble_counter==6)) + Next_state=StateSFD; + else + Next_state=Current_state; + StateSFD: + if (!FullDuplex&&Collision) + Next_state=StateJam; + else if (xoff_gen||xon_gen) + Next_state=StateSendPauseFrame; + else + Next_state=StateData; + StateSendPauseFrame: + if (IPLengthCounter==17) + Next_state=StatePAD; + else + Next_state=Current_state; + StateData: + if (!FullDuplex&&Collision) + Next_state=StateJam; + else if (Fifo_data_err_empty) + Next_state=StateFFEmptyDrop; + else if (Fifo_eop&&IPLengthCounter>=59)//IP+MAC+TYPE=60 ,start from 0 + Next_state=StateFCS; + else if (Fifo_eop) + Next_state=StatePAD; + else + Next_state=StateData; + StatePAD: + if (!FullDuplex&&Collision) + Next_state=StateJam; + else if (IPLengthCounter>=59) + Next_state=StateFCS; + else + Next_state=Current_state; + StateJam: + if (RetryCnt<=MaxRetry&&JamCounter==16) + Next_state=StateBackOff; + else if (RetryCnt>MaxRetry) + Next_state=StateJamDrop; + else + Next_state=Current_state; + StateBackOff: + if (Random_time_meet) + Next_state =StateDefer; + else + Next_state =Current_state; + StateFCS: + if (!FullDuplex&&Collision) + Next_state =StateJam; + else if (CRC_end) + Next_state =StateSwitchNext; + else + Next_state =Current_state; + StateFFEmptyDrop: + if (Fifo_eop) + Next_state =StateSwitchNext; + else + Next_state =Current_state; + StateJamDrop: + if (Fifo_eop) + Next_state =StateSwitchNext; + else + Next_state =Current_state; + StateSwitchNext: + Next_state =StateDefer; + default: + Next_state =StateDefer; + endcase + + + +always @ (posedge Clk or posedge Reset) + if (Reset) + JamCounter <=0; + else if (Current_state!=StateJam) + JamCounter <=0; + else if (Current_state==StateJam) + JamCounter <=JamCounter+1; + + +always @ (posedge Clk or posedge Reset) + if (Reset) + RetryCnt <=0; + else if (Current_state==StateSwitchNext) + RetryCnt <=0; + else if (Current_state==StateJam&&Next_state==StateBackOff) + RetryCnt <=RetryCnt + 1; + +always @ (posedge Clk or posedge Reset) + if (Reset) + IFG_counter <=0; + else if (Current_state!=StateIFG) + IFG_counter <=0; + else + IFG_counter <=IFG_counter + 1; + +always @ (posedge Clk or posedge Reset) + if (Reset) + Preamble_counter <=0; + else if (Current_state!=StatePreamble) + Preamble_counter <=0; + else + Preamble_counter <=Preamble_counter+ 1; + +always @ (posedge Clk or posedge Reset) + if (Reset) + PktDrpEvenPtr <=0; + else if(Current_state==StateJamDrop||Current_state==StateFFEmptyDrop) + PktDrpEvenPtr <=~PktDrpEvenPtr; +//****************************************************************************** +//generate output signals +//****************************************************************************** +//CRC related +always @(Current_state) + if (Current_state==StateSFD) + CRC_init =1; + else + CRC_init =0; + +assign Frame_data=TxD_tmp; + +always @(Current_state) + if (Current_state==StateData||Current_state==StateSendPauseFrame||Current_state==StatePAD) + Data_en =1; + else + Data_en =0; + +always @(Current_state) + if (Current_state==StateFCS) + CRC_rd =1; + else + CRC_rd =0; + +//Ramdon_gen interface +always @(Current_state or Next_state) + if (Current_state==StateJam&&Next_state==StateBackOff) + Random_init =1; + else + Random_init =0; + +//MAC_rx_FF +//data have one cycle delay after fifo read signals +always @ (*) + if (Current_state==StateData || + Current_state==StateSFD&&!(xoff_gen||xon_gen) || + Current_state==StateJamDrop&&PktDrpEvenPtr|| + Current_state==StateFFEmptyDrop&&PktDrpEvenPtr ) + Fifo_rd =1; + else + Fifo_rd =0; + +always @ (Current_state) + if (Current_state==StateSwitchNext) + Fifo_rd_finish =1; + else + Fifo_rd_finish =0; + +always @ (Current_state) + if (Current_state==StateJam) + Fifo_rd_retry =1; + else + Fifo_rd_retry =0; +//RMII +always @(Current_state) + if (Current_state==StatePreamble||Current_state==StateSFD|| + Current_state==StateData||Current_state==StateSendPauseFrame|| + Current_state==StateFCS||Current_state==StatePAD||Current_state==StateJam) + TxEn_tmp =1; + else + TxEn_tmp =0; + +//gen txd data +always @(*) + case (Current_state) + StatePreamble: + TxD_tmp =8'h55; + StateSFD: + TxD_tmp =8'hd5; + StateData: + if (Src_MAC_ptr&&MAC_tx_add_en) + TxD_tmp =MAC_tx_addr_data; + else + TxD_tmp =Fifo_data; + StateSendPauseFrame: + if (Src_MAC_ptr&&MAC_tx_add_en) + TxD_tmp =MAC_tx_addr_data; + else + case (IPLengthCounter) + 8'd0: TxD_tmp =8'h01; + 8'd1: TxD_tmp =8'h80; + 8'd2: TxD_tmp =8'hc2; + 8'd3: TxD_tmp =8'h00; + 8'd4: TxD_tmp =8'h00; + 8'd5: TxD_tmp =8'h01; + 8'd12: TxD_tmp =8'h88;//type + 8'd13: TxD_tmp =8'h08;// + 8'd14: TxD_tmp =8'h00;//opcode + 8'd15: TxD_tmp =8'h01; + 8'd16: TxD_tmp =xon_gen?8'b0:pause_quanta_set_dl1[15:8]; + 8'd17: TxD_tmp =xon_gen?8'b0:pause_quanta_set_dl1[7:0]; +// 8'd60: TxD_tmp =8'h26; +// 8'd61: TxD_tmp =8'h6b; +// 8'd62: TxD_tmp =8'hae; +// 8'd63: TxD_tmp =8'h0a; + default:TxD_tmp =0; + endcase + + StatePAD: + TxD_tmp =8'h00; + StateJam: + TxD_tmp =8'h01; //jam sequence + StateFCS: + TxD_tmp =CRC_out; + default: + TxD_tmp =2'b0; + endcase +always @ (posedge Clk or posedge Reset) + if (Reset) + begin + TxD <=0; + TxEn <=0; + end + else + begin + TxD <=TxD_tmp; + TxEn <=TxEn_tmp; + end +//RMON + + +always @ (posedge Clk or posedge Reset) + if (Reset) + Tx_pkt_length_rmon <=0; + else if (Current_state==StateSFD) + Tx_pkt_length_rmon <=0; + else if (Current_state==StateData||Current_state==StateSendPauseFrame||Current_state==StatePAD||Current_state==StateFCS) + Tx_pkt_length_rmon <=Tx_pkt_length_rmon+1; + + +reg [2:0] Tx_apply_rmon_reg; + +always @( posedge Clk or posedge Reset ) + if ( Reset ) + begin + Tx_apply_rmon <= 0; + Tx_apply_rmon_reg <= 'b0; + end + else + begin + if ( (Fifo_eop&&Current_state==StateJamDrop) || + (Fifo_eop&&Current_state==StateFFEmptyDrop) || + CRC_end ) + Tx_apply_rmon <= 1; + else + if ( Tx_apply_rmon_reg[2] ) + Tx_apply_rmon <= 0; + + Tx_apply_rmon_reg <= { Tx_apply_rmon_reg[1:0], Tx_apply_rmon }; + end + +always @ (posedge Clk or posedge Reset) + if (Reset) + Tx_pkt_err_type_rmon <=0; + else if(Fifo_eop&&Current_state==StateJamDrop) + Tx_pkt_err_type_rmon <=3'b001;// + else if(Fifo_eop&&Current_state==StateFFEmptyDrop) + Tx_pkt_err_type_rmon <=3'b010;//underflow + else if(Fifo_eop&&Fifo_data_err_full) + Tx_pkt_err_type_rmon <=3'b011;//overflow + else if(CRC_end) + Tx_pkt_err_type_rmon <=3'b100;//normal + +always @ (posedge Clk or posedge Reset) + if (Reset) + MAC_header_slot_tmp <=0; + else if(Current_state==StateSFD&&Next_state==StateData) + MAC_header_slot_tmp <=1; + else + MAC_header_slot_tmp <=0; + +always @ (posedge Clk or posedge Reset) + if (Reset) + MAC_header_slot <=0; + else + MAC_header_slot <=MAC_header_slot_tmp; + +always @ (posedge Clk or posedge Reset) + if (Reset) + Tx_pkt_type_rmon <=0; + else if (Current_state==StateSendPauseFrame) + Tx_pkt_type_rmon <=3'b100; + else if(MAC_header_slot) + Tx_pkt_type_rmon <={1'b0,TxD[7:6]}; + + +always @(Tx_pkt_length_rmon) + if (Tx_pkt_length_rmon>=6&&Tx_pkt_length_rmon<=11) + Src_MAC_ptr =1; + else + Src_MAC_ptr =0; + +//MAC_tx_addr_add +always @ (posedge Clk or posedge Reset) + if (Reset) + MAC_tx_addr_rd <=0; + else if ((Tx_pkt_length_rmon>=4&&Tx_pkt_length_rmon<=9)&&(MAC_tx_add_en||Current_state==StateSendPauseFrame)) + MAC_tx_addr_rd <=1; + else + MAC_tx_addr_rd <=0; + + always @* + //if ((Tx_pkt_length_rmon==3)&&Fifo_rd) + if (Current_state==StatePreamble) + MAC_tx_addr_init=1; + else + MAC_tx_addr_init=0; + +//************************************************************************************************************** +// CFH: this implementation delays the time it sends an entire Ethernet frame with 512 bits for every pause +// request of 512 bits. Actually, it should only delay the time it takes to transmit 512 bits, not counting +// Ethernet header, CRC, Interframe Gap etc. +// Hence the current implementation waits longer than the pause frame actually requests (~20% more) +//************************************************************************************************************** + +//flow control +always @(posedge Clk or posedge Reset) + if (Reset) + pause_counter <=0; + else if (Current_state!=StatePause) + pause_counter <=0; + else + pause_counter <=pause_counter+1; + +always @ (posedge Clk or posedge Reset) + if (Reset) + pause_quanta_sub <=0; + else if(pause_counter==512/8) + pause_quanta_sub <=1; + else + pause_quanta_sub <=0; + +// FIXME The below probably won't work if the pause request comes when we are in the wrong state + wire clear_xonxoff = (Current_state==StateSendPauseFrame) & (IPLengthCounter==17); +always @ (posedge Clk or posedge Reset) + if (Reset) + xoff_gen_complete <=0; + else if(clear_xonxoff & xoff_gen) + xoff_gen_complete <=1; + else + xoff_gen_complete <=0; + + +always @ (posedge Clk or posedge Reset) + if (Reset) + xon_gen_complete <=0; + else if(clear_xonxoff & xon_gen) + xon_gen_complete <=1; + else + xon_gen_complete <=0; + +endmodule diff --git a/eth/rtl/verilog/MAC_tx/Random_gen.v b/eth/rtl/verilog/MAC_tx/Random_gen.v new file mode 100644 index 000000000..fd57008b1 --- /dev/null +++ b/eth/rtl/verilog/MAC_tx/Random_gen.v @@ -0,0 +1,109 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// Random_gen.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source 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 Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// + +module Random_gen( +Reset , +Clk , +Init , +RetryCnt , +Random_time_meet +); +input Reset ; +input Clk ; +input Init ; +input [3:0] RetryCnt ; +output Random_time_meet; + +//****************************************************************************** +//internal signals +//****************************************************************************** +reg [9:0] Random_sequence ; +reg [9:0] Random ; +reg [9:0] Random_counter ; +reg [7:0] Slot_time_counter; //256*2=512bit=1 slot time +reg Random_time_meet; + +//****************************************************************************** +always @ (posedge Clk or posedge Reset) + if (Reset) + Random_sequence <=0; + else + Random_sequence <={Random_sequence[8:0],~(Random_sequence[2]^Random_sequence[9])}; + +always @ (RetryCnt or Random_sequence) + case (RetryCnt) + 4'h0 : Random={9'b0,Random_sequence[0]}; + 4'h1 : Random={8'b0,Random_sequence[1:0]}; + 4'h2 : Random={7'b0,Random_sequence[2:0]}; + 4'h3 : Random={6'b0,Random_sequence[3:0]}; + 4'h4 : Random={5'b0,Random_sequence[4:0]}; + 4'h5 : Random={4'b0,Random_sequence[5:0]}; + 4'h6 : Random={3'b0,Random_sequence[6:0]}; + 4'h7 : Random={2'b0,Random_sequence[7:0]}; + 4'h8 : Random={1'b0,Random_sequence[8:0]}; + 4'h9 : Random={ Random_sequence[9:0]}; + default : Random={ Random_sequence[9:0]}; + endcase + +always @ (posedge Clk or posedge Reset) + if (Reset) + Slot_time_counter <=0; + else if(Init) + Slot_time_counter <=0; + else if(!Random_time_meet) + Slot_time_counter <=Slot_time_counter+1; + +always @ (posedge Clk or posedge Reset) + if (Reset) + Random_counter <=0; + else if (Init) + Random_counter <=Random; + else if (Random_counter!=0&&Slot_time_counter==255) + Random_counter <=Random_counter -1 ; + +always @ (posedge Clk or posedge Reset) + if (Reset) + Random_time_meet <=1; + else if (Init) + Random_time_meet <=0; + else if (Random_counter==0) + Random_time_meet <=1; + +endmodule + + diff --git a/eth/rtl/verilog/Phy_int.v b/eth/rtl/verilog/Phy_int.v new file mode 100644 index 000000000..c85d4f64b --- /dev/null +++ b/eth/rtl/verilog/Phy_int.v @@ -0,0 +1,205 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// Phy_int.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source 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 Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: Phy_int.v,v $ +// Revision 1.3 2006/01/19 14:07:53 maverickist +// verification is complete. +// +// Revision 1.3 2005/12/16 06:44:14 Administrator +// replaced tab with space. +// passed 9.6k length frame test. +// +// Revision 1.2 2005/12/13 12:15:36 Administrator +// no message +// +// Revision 1.1.1.1 2005/12/13 01:51:44 Administrator +// no message +// + +module Phy_int + (input rst_mac_rx, + input rst_mac_tx, + input MAC_rx_clk, + input MAC_tx_clk, + + // Rx interface + output reg MCrs_dv, + output reg [7:0] MRxD, + output MRxErr, + + // Tx interface + input [7:0] MTxD, + input MTxEn, + output MCRS, + + // PHY interface + output Tx_er, + output reg Tx_en, + output reg [7:0] Txd, + input Rx_er, + input Rx_dv, + input [7:0] Rxd, + input Crs, + input Col, + + // Host interface + input Line_loop_en, + input [2:0] Speed ); + + //------------------------------------------------------------------------- + // Local declarations + //------------------------------------------------------------------------- + + reg [7:0] MTxD_dl1; + reg MTxEn_dl1; + reg Tx_odd_data_ptr; + reg Rx_odd_data_ptr; + reg Rx_er_dl1; + reg Rx_dv_dl1; + reg Rx_dv_dl2; + reg [7:0] Rxd_dl1; + reg [7:0] Rxd_dl2; + reg Crs_dl1; + + //------------------------------------------------------------------------- + // Tx control + //------------------------------------------------------------------------- + + // Reg boundary signals + always @( posedge MAC_tx_clk or posedge rst_mac_tx ) + if ( rst_mac_tx ) + begin + MTxD_dl1 <= 0; + MTxEn_dl1 <= 0; + end + else + begin + MTxD_dl1 <= MTxD; + MTxEn_dl1 <= MTxEn; + end + + always @( posedge MAC_tx_clk or posedge rst_mac_tx ) + if ( rst_mac_tx ) + Tx_odd_data_ptr <= 0; + else if ( !MTxD_dl1 ) + Tx_odd_data_ptr <= 0; + else + Tx_odd_data_ptr <= !Tx_odd_data_ptr; + + + always @( posedge MAC_tx_clk or posedge rst_mac_tx ) + if ( rst_mac_tx ) + Txd <= 0; + else if ( Speed[2] && MTxEn_dl1 ) + Txd <= MTxD_dl1; + else if ( MTxEn_dl1 && !Tx_odd_data_ptr ) + Txd <= { 4'b0, MTxD_dl1[3:0] }; + else if ( MTxEn_dl1 && Tx_odd_data_ptr ) + Txd <= { 4'b0, MTxD_dl1[7:4] }; + else + Txd <=0; + + always @( posedge MAC_tx_clk or posedge rst_mac_tx ) + if ( rst_mac_tx ) + Tx_en <= 0; + else if ( MTxEn_dl1 ) + Tx_en <= 1; + else + Tx_en <= 0; + + assign Tx_er = 0; + + //------------------------------------------------------------------------- + // Rx control + //------------------------------------------------------------------------- + + // Reg boundery signals + always @( posedge MAC_rx_clk or posedge rst_mac_rx ) + if ( rst_mac_rx ) + begin + Rx_er_dl1 <= 0; + Rx_dv_dl1 <= 0; + Rx_dv_dl2 <= 0; + Rxd_dl1 <= 0; + Rxd_dl2 <= 0; + Crs_dl1 <= 0; + end + else + begin + Rx_er_dl1 <= Rx_er; + Rx_dv_dl1 <= Rx_dv; + Rx_dv_dl2 <= Rx_dv_dl1; + Rxd_dl1 <= Rxd; + Rxd_dl2 <= Rxd_dl1; + Crs_dl1 <= Crs; + end + + assign MRxErr = Rx_er_dl1; + assign MCRS = Crs_dl1; + + always @( posedge MAC_rx_clk or posedge rst_mac_rx ) + if ( rst_mac_rx ) + MCrs_dv <= 0; + else if ( Line_loop_en ) + MCrs_dv <= Tx_en; + else if( Rx_dv_dl2 ) + MCrs_dv <= 1; + else + MCrs_dv <= 0; + + always @ ( posedge MAC_rx_clk or posedge rst_mac_rx ) + if ( rst_mac_rx ) + Rx_odd_data_ptr <= 0; + else if ( !Rx_dv_dl1 ) + Rx_odd_data_ptr <= 0; + else + Rx_odd_data_ptr <= !Rx_odd_data_ptr; + + always @ ( posedge MAC_rx_clk or posedge rst_mac_rx ) + if ( rst_mac_rx ) + MRxD <= 0; + else if( Line_loop_en ) + MRxD <= Txd; + else if( Speed[2] && Rx_dv_dl2 ) + MRxD <= Rxd_dl2; + else if( Rx_dv_dl1 && Rx_odd_data_ptr ) + MRxD <={ Rxd_dl1[3:0], Rxd_dl2[3:0] }; + +endmodule diff --git a/eth/rtl/verilog/RMON.v b/eth/rtl/verilog/RMON.v new file mode 100644 index 000000000..18a84beb5 --- /dev/null +++ b/eth/rtl/verilog/RMON.v @@ -0,0 +1,163 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// RMON.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source 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 Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: RMON.v,v $ +// Revision 1.4 2006/06/25 04:58:56 maverickist +// no message +// +// Revision 1.3 2006/01/19 14:07:53 maverickist +// verification is complete. +// +// Revision 1.2 2005/12/16 06:44:16 Administrator +// replaced tab with space. +// passed 9.6k length frame test. +// +// Revision 1.1.1.1 2005/12/13 01:51:44 Administrator +// no message +// + +module RMON + (input Clk , + input Reset , + //Tx_RMON + input [2:0] Tx_pkt_type_rmon , + input [15:0] Tx_pkt_length_rmon , + input Tx_apply_rmon , + input [2:0] Tx_pkt_err_type_rmon, + //Tx_RMON + input [2:0] Rx_pkt_type_rmon , + input [15:0] Rx_pkt_length_rmon , + input Rx_apply_rmon , + input [2:0] Rx_pkt_err_type_rmon, + //CPU + input [5:0] CPU_rd_addr , + input CPU_rd_apply , + output CPU_rd_grant , + output [31:0] CPU_rd_dout + ); + + // ****************************************************************************** + // interface signals + // ****************************************************************************** + wire Reg_apply_0 ; + wire [4:0] Reg_addr_0 ; + wire [15:0] Reg_data_0 ; + wire Reg_next_0 ; + wire Reg_apply_1 ; + wire [4:0] Reg_addr_1 ; + wire [15:0] Reg_data_1 ; + wire Reg_next_1 ; + wire [5:0] Addra ; + wire [31:0] Dina ; + reg [31:0] Douta ; + wire Wea ; + + // ****************************************************************************** + + RMON_addr_gen U_0_Rx_RMON_addr_gen + (.Clk (Clk ), + .Reset (Reset ), + //RMON + .Pkt_type_rmon (Rx_pkt_type_rmon ), + .Pkt_length_rmon (Rx_pkt_length_rmon ), + .Apply_rmon (Rx_apply_rmon ), + .Pkt_err_type_rmon (Rx_pkt_err_type_rmon ), + //Rmon_ctrl + .Reg_apply (Reg_apply_0 ), + .Reg_addr (Reg_addr_0 ), + .Reg_data (Reg_data_0 ), + .Reg_next (Reg_next_0 ), + //CPU + .Reg_drop_apply ( ) ); + + RMON_addr_gen U_0_Tx_RMON_addr_gen + (.Clk (Clk ), + .Reset (Reset ), + //RMON + .Pkt_type_rmon (Tx_pkt_type_rmon ), + .Pkt_length_rmon (Tx_pkt_length_rmon ), + .Apply_rmon (Tx_apply_rmon ), + .Pkt_err_type_rmon (Tx_pkt_err_type_rmon ), + //Rmon_ctrl + .Reg_apply (Reg_apply_1 ), + .Reg_addr (Reg_addr_1 ), + .Reg_data (Reg_data_1 ), + .Reg_next (Reg_next_1 ), + //CPU + .Reg_drop_apply ( ) ); + + RMON_ctrl U_RMON_ctrl + (.Clk (Clk ), + .Reset (Reset ), + //RMON_ctrl + .Reg_apply_0 (Reg_apply_0 ), + .Reg_addr_0 (Reg_addr_0 ), + .Reg_data_0 (Reg_data_0 ), + .Reg_next_0 (Reg_next_0 ), + .Reg_apply_1 (Reg_apply_1 ), + .Reg_addr_1 (Reg_addr_1 ), + .Reg_data_1 (Reg_data_1 ), + .Reg_next_1 (Reg_next_1 ), + //dual-port ram + .Addra (Addra ), + .Dina (Dina ), + .Douta (Douta ), + .Wea (Wea ), + //CPU + .CPU_rd_addr (CPU_rd_addr ), + .CPU_rd_apply (CPU_rd_apply ), + .CPU_rd_grant (CPU_rd_grant ), + .CPU_rd_dout (CPU_rd_dout ) ); + + reg [31:0] RMON_ram [0:63]; + wire [31:0] Douta_imm = RMON_ram[Addra]; + integer i; + initial + for(i=0;i<64;i=i+1) + RMON_ram[i] = 32'd0; + + always @(posedge Clk) + if(Wea) + RMON_ram[Addra] <= Dina; + + always @(posedge Clk) + Douta <= Douta_imm; + +endmodule // RMON diff --git a/eth/rtl/verilog/RMON/RMON_addr_gen.v b/eth/rtl/verilog/RMON/RMON_addr_gen.v new file mode 100644 index 000000000..9da8d1f80 --- /dev/null +++ b/eth/rtl/verilog/RMON/RMON_addr_gen.v @@ -0,0 +1,295 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// RMON_addr_gen.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source 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 Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: RMON_addr_gen.v,v $ +// Revision 1.4 2006/06/25 04:58:57 maverickist +// no message +// +// Revision 1.3 2006/01/19 14:07:55 maverickist +// verification is complete. +// +// Revision 1.2 2005/12/16 06:44:19 Administrator +// replaced tab with space. +// passed 9.6k length frame test. +// +// Revision 1.1.1.1 2005/12/13 01:51:45 Administrator +// no message +// +module RMON_addr_gen( +Clk , +Reset , +//RMON +Pkt_type_rmon , +Pkt_length_rmon , +Apply_rmon ,//pluse signal looks like eop +Pkt_err_type_rmon , +// +Reg_apply , +Reg_addr , +Reg_data , +Reg_next , +//CPU +Reg_drop_apply +); +input Clk ; +input Reset ; + //RMON +input [2:0] Pkt_type_rmon ; +input [15:0] Pkt_length_rmon ; +input Apply_rmon ;//pluse signal looks like eop +input [2:0] Pkt_err_type_rmon ; + //RMON_ctrl +output Reg_apply ; +output [4:0] Reg_addr ; +output [15:0] Reg_data ; +input Reg_next ; + //CPU +output Reg_drop_apply ; + +//****************************************************************************** +//internal signals +//****************************************************************************** +parameter StateIdle =4'd0; +parameter StatePktLength =4'd1; +parameter StatePktNumber =4'd2; +parameter StatePktType =4'd3; +parameter StatePktRange =4'd4; + +reg [3:0] CurrentState /* synthesys syn_keep=1 */; +reg [3:0] NextState; + +reg [2:0] PktTypeReg ; +reg [15:0] PktLengthReg ; +reg [2:0] PktErrTypeReg ; + +reg Reg_apply ; +reg [4:0] Reg_addr ; +reg [15:0] Reg_data ; +reg Reg_drop_apply ; +//****************************************************************************** +//register boundery signals + +//****************************************************************************** +reg Apply_rmon_dl1; +reg Apply_rmon_dl2; +reg Apply_rmon_pulse; +reg [2:0] Pkt_type_rmon_dl1 ; +reg [15:0] Pkt_length_rmon_dl1 ; +reg [2:0] Pkt_err_type_rmon_dl1 ; + +always @(posedge Clk or posedge Reset) + if (Reset) + begin + Pkt_type_rmon_dl1 <=0; + Pkt_length_rmon_dl1 <=0; + Pkt_err_type_rmon_dl1 <=0; + end + else + begin + Pkt_type_rmon_dl1 <=Pkt_type_rmon ; + Pkt_length_rmon_dl1 <=Pkt_length_rmon ; + Pkt_err_type_rmon_dl1 <=Pkt_err_type_rmon ; + end + +always @(posedge Clk or posedge Reset) + if (Reset) + begin + Apply_rmon_dl1 <=0; + Apply_rmon_dl2 <=0; + end + else + begin + Apply_rmon_dl1 <=Apply_rmon; + Apply_rmon_dl2 <=Apply_rmon_dl1; + end + +always @(Apply_rmon_dl1 or Apply_rmon_dl2) + if (Apply_rmon_dl1&!Apply_rmon_dl2) + Apply_rmon_pulse =1; + else + Apply_rmon_pulse =0; + + + +always @(posedge Clk or posedge Reset) + if (Reset) + begin + PktTypeReg <=0; + PktLengthReg <=0; + PktErrTypeReg <=0; + end + else if (Apply_rmon_pulse&&CurrentState==StateIdle) + begin + PktTypeReg <=Pkt_type_rmon_dl1 ; + PktLengthReg <=Pkt_length_rmon_dl1 ; + PktErrTypeReg <=Pkt_err_type_rmon_dl1 ; + end + + +//****************************************************************************** +//State Machine +//****************************************************************************** +always @(posedge Clk or posedge Reset) + if (Reset) + CurrentState <=StateIdle; + else + CurrentState <=NextState; + +always @(CurrentState or Apply_rmon_pulse or Reg_next) + case (CurrentState) + StateIdle: + if (Apply_rmon_pulse) + NextState =StatePktLength; + else + NextState =StateIdle; + StatePktLength: + if (Reg_next) + NextState =StatePktNumber; + else + NextState =CurrentState; + StatePktNumber: + if (Reg_next) + NextState =StatePktType; + else + NextState =CurrentState; + StatePktType: + if (Reg_next) + NextState =StatePktRange; + else + NextState =CurrentState; + StatePktRange: + if (Reg_next) + NextState =StateIdle; + else + NextState =CurrentState; + default: + NextState =StateIdle; + endcase + +//****************************************************************************** +//gen output signals +//****************************************************************************** +//Reg_apply +always @ (CurrentState) + if (CurrentState==StatePktLength||CurrentState==StatePktNumber|| + CurrentState==StatePktType||CurrentState==StatePktRange) + Reg_apply =1; + else + Reg_apply =0; + +//Reg_addr +always @ (posedge Clk or posedge Reset) + if (Reset) + Reg_addr <=0; + else case (CurrentState) + StatePktLength: + Reg_addr <=5'd00; + StatePktNumber: + Reg_addr <=5'd01; + StatePktType: + case(PktTypeReg) + 3'b011: + Reg_addr <=5'd02; //broadcast + 3'b001: + Reg_addr <=5'd03; //multicast + 3'b100: + Reg_addr <=5'd16; //pause frame + default: + Reg_addr <=5'd04; //unicast + endcase + StatePktRange: + case(PktErrTypeReg) + 3'b001: + Reg_addr <=5'd05; + 3'b010: + Reg_addr <=5'd06; + 3'b011: + Reg_addr <=5'd07; + 3'b100: + if (PktLengthReg<64) + Reg_addr <=5'd08; + else if (PktLengthReg==64) + Reg_addr <=5'd09; + else if (PktLengthReg<128) + Reg_addr <=5'd10; + else if (PktLengthReg<256) + Reg_addr <=5'd11; + else if (PktLengthReg<512) + Reg_addr <=5'd12; + else if (PktLengthReg<1024) + Reg_addr <=5'd13; + else if (PktLengthReg<1519) + Reg_addr <=5'd14; + else + Reg_addr <=5'd15; + default: + Reg_addr <=5'd05; + endcase + default: + Reg_addr <=5'd05; + endcase + +//Reg_data +always @ (CurrentState or PktLengthReg) + case (CurrentState) + StatePktLength: + Reg_data =PktLengthReg; + StatePktNumber: + Reg_data =1; + StatePktType: + Reg_data =1; + StatePktRange: + Reg_data =1; + default: + Reg_data =0; + endcase + +//Reg_drop_apply +always @ (posedge Clk or posedge Reset) + if (Reset) + Reg_drop_apply <=0; + else if (CurrentState!=StateIdle&&Apply_rmon_pulse) + Reg_drop_apply <=1; + else + Reg_drop_apply <=0; + + +endmodule + diff --git a/eth/rtl/verilog/RMON/RMON_ctrl.v b/eth/rtl/verilog/RMON/RMON_ctrl.v new file mode 100644 index 000000000..4fc038dc8 --- /dev/null +++ b/eth/rtl/verilog/RMON/RMON_ctrl.v @@ -0,0 +1,283 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// RMON_ctrl.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source 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 Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: RMON_ctrl.v,v $ +// Revision 1.4 2006/06/25 04:58:57 maverickist +// no message +// +// Revision 1.3 2006/01/19 14:07:55 maverickist +// verification is complete. +// +// Revision 1.2 2005/12/16 06:44:19 Administrator +// replaced tab with space. +// passed 9.6k length frame test. +// +// Revision 1.1.1.1 2005/12/13 01:51:45 Administrator +// no message +// +module RMON_ctrl ( +Clk , +Reset , +//RMON_ctrl +Reg_apply_0 , +Reg_addr_0 , +Reg_data_0 , +Reg_next_0 , +Reg_apply_1 , +Reg_addr_1 , +Reg_data_1 , +Reg_next_1 , +//dual-port ram +Addra , +Dina , +Douta , +Wea , +//CPU +CPU_rd_addr , +CPU_rd_apply , +CPU_rd_grant , +CPU_rd_dout + +); +input Clk ; +input Reset ; + //RMON_ctrl +input Reg_apply_0 ; +input [4:0] Reg_addr_0 ; +input [15:0] Reg_data_0 ; +output Reg_next_0 ; +input Reg_apply_1 ; +input [4:0] Reg_addr_1 ; +input [15:0] Reg_data_1 ; +output Reg_next_1 ; + //dual-port ram + //port-a for Rmon +output [5:0] Addra ; +output [31:0] Dina ; +input [31:0] Douta ; +output Wea ; + //CPU +input [5:0] CPU_rd_addr ; +input CPU_rd_apply ; +output CPU_rd_grant ; +output [31:0] CPU_rd_dout ; + + + + +//****************************************************************************** +//internal signals +//****************************************************************************** + +parameter StateCPU =4'd00; +parameter StateMAC0 =4'd01; +parameter StateMAC1 =4'd02; + + +reg [3:0] CurrentState /* synthesys syn_keep=1 */; +reg [3:0] NextState; +reg [3:0] CurrentState_reg; + +reg [4:0] StepCounter; +reg [5:0] Addra ; +reg [31:0] Dina; +reg Reg_next_0 ; +reg Reg_next_1 ; +reg Write; +reg Read; +reg Pipeline; +reg [31:0] CPU_rd_dout ; +reg CPU_rd_apply_reg ; +//****************************************************************************** +//State Machine +//****************************************************************************** + +always @(posedge Clk or posedge Reset) + if (Reset) + CurrentState <=StateMAC0; + else + CurrentState <=NextState; + +always @(posedge Clk or posedge Reset) + if (Reset) + CurrentState_reg <=StateMAC0; + else if(CurrentState!=StateCPU) + CurrentState_reg <=CurrentState; + +always @(CurrentState or CPU_rd_apply_reg or Reg_apply_0 or CurrentState_reg + or Reg_apply_1 + or StepCounter + ) + case(CurrentState) + StateMAC0: + if(!Reg_apply_0&&CPU_rd_apply_reg) + NextState =StateCPU; + else if(!Reg_apply_0) + NextState =StateMAC1; + else + NextState =CurrentState; + StateMAC1: + if(!Reg_apply_1&&CPU_rd_apply_reg) + NextState =StateCPU; + else if(!Reg_apply_1) + NextState =StateMAC0; + else + NextState =CurrentState; + StateCPU: + if (StepCounter==3) + case (CurrentState_reg) + StateMAC0 :NextState =StateMAC0 ; + StateMAC1 :NextState =StateMAC1 ; + default :NextState =StateMAC0; + endcase + else + NextState =CurrentState; + + default: + NextState =StateMAC0; + endcase + + + +always @(posedge Clk or posedge Reset) + if (Reset) + StepCounter <=0; + else if(NextState!=CurrentState) + StepCounter <=0; + else if (StepCounter!=4'hf) + StepCounter <=StepCounter + 1; + +//****************************************************************************** +//temp signals +//****************************************************************************** +always @(StepCounter) + if( StepCounter==1||StepCounter==4|| + StepCounter==7||StepCounter==10) + Read =1; + else + Read =0; + +always @(StepCounter or CurrentState) + if( StepCounter==2||StepCounter==5|| + StepCounter==8||StepCounter==11) + Pipeline =1; + else + Pipeline =0; + +always @(StepCounter or CurrentState) + if( StepCounter==3||StepCounter==6|| + StepCounter==9||StepCounter==12) + Write =1; + else + Write =0; + + +//****************************************************************************** +//gen output signals +//****************************************************************************** +//Addra +always @(*) + case(CurrentState) + StateMAC0 : Addra={1'd0 ,Reg_addr_0 }; + StateMAC1 : Addra={1'd1 ,Reg_addr_1 }; + StateCPU: Addra=CPU_rd_addr; + default: Addra=0; + endcase + +//Dina +always @(posedge Clk or posedge Reset) + if (Reset) + Dina <=0; + else + case(CurrentState) + StateMAC0 : Dina<=Douta+Reg_data_0 ; + StateMAC1 : Dina<=Douta+Reg_data_1 ; + StateCPU: Dina<=0; + default: Dina<=0; + endcase + +assign Wea =Write; +//Reg_next +always @(CurrentState or Pipeline) + if(CurrentState==StateMAC0) + Reg_next_0 =Pipeline; + else + Reg_next_0 =0; + +always @(CurrentState or Pipeline) + if(CurrentState==StateMAC1) + Reg_next_1 =Pipeline; + else + Reg_next_1 =0; + + +//CPU_rd_grant +reg CPU_rd_apply_dl1; +reg CPU_rd_apply_dl2; +//rising edge +always @ (posedge Clk or posedge Reset) + if (Reset) + begin + CPU_rd_apply_dl1 <=0; + CPU_rd_apply_dl2 <=0; + end + else + begin + CPU_rd_apply_dl1 <=CPU_rd_apply; + CPU_rd_apply_dl2 <=CPU_rd_apply_dl1; + end + +always @ (posedge Clk or posedge Reset) + if (Reset) + CPU_rd_apply_reg <=0; + else if (CPU_rd_apply_dl1&!CPU_rd_apply_dl2) + CPU_rd_apply_reg <=1; + else if (CurrentState==StateCPU&&Write) + CPU_rd_apply_reg <=0; + +assign CPU_rd_grant = CPU_rd_apply & CPU_rd_apply_dl1 & CPU_rd_apply_dl2 & !CPU_rd_apply_reg; + +always @ (posedge Clk or posedge Reset) + if (Reset) + CPU_rd_dout <=0; + else if (Pipeline&&CurrentState==StateCPU) + CPU_rd_dout <=Douta; + +endmodule diff --git a/eth/rtl/verilog/Reg_int.v b/eth/rtl/verilog/Reg_int.v new file mode 100644 index 000000000..f1bea2316 --- /dev/null +++ b/eth/rtl/verilog/Reg_int.v @@ -0,0 +1,270 @@ +module Reg_int ( + // Wishbone compliant core host interface + input CLK_I, // Wishbone interface clock (nominally 50 MHz) + input RST_I, // Active high (async) reset of the Wishbone interface + input STB_I, // Active high module-select + input CYC_I, // Active high cycle-enable + input [6:0] ADR_I, // Module register address + input WE_I, // Active high for writes, low for reads + input [31:0] DAT_I, // Write data + output reg [31:0] DAT_O, // Read data + output reg ACK_O, // Acknowledge output – single high pulse + + // Tx host interface + output [4:0] Tx_Hwmark, + output [4:0] Tx_Lwmark, + output MAC_tx_add_en, + output FullDuplex, + output [3:0] MaxRetry, + output [5:0] IFGset, + output [7:0] MAC_tx_add_prom_data, + output [2:0] MAC_tx_add_prom_add, + output MAC_tx_add_prom_wr, + + // Rx host interface + output MAC_rx_add_chk_en, + output [7:0] MAC_rx_add_prom_data, + output [2:0] MAC_rx_add_prom_add, + output MAC_rx_add_prom_wr, + output broadcast_filter_en, + output [15:0] broadcast_bucket_depth, + output [15:0] broadcast_bucket_interval, + output RX_APPEND_CRC, + output [4:0] Rx_Hwmark, + output [4:0] Rx_Lwmark, + output CRC_chk_en, + output [5:0] RX_IFG_SET, + output [15:0] RX_MAX_LENGTH, // Default 1518 + output [6:0] RX_MIN_LENGTH, // Default 64 + + // Flow control settings + output pause_frame_send_en, + output [15:0] pause_quanta_set, + output tx_pause_en, + output [15:0] fc_hwmark, + output [15:0] fc_lwmark, + + // RMON host interface + output [5:0] CPU_rd_addr, + output CPU_rd_apply, + input CPU_rd_grant, + input [31:0] CPU_rd_dout, + + //Phy int host interface + output Line_loop_en, + output [2:0] Speed, + + //MII to CPU + output [7:0] Divider, // Divider for the host clock + output [15:0] CtrlData, // Control Data (to be written to the PHY reg.) + output [4:0] Rgad, // Register Address (within the PHY) + output [4:0] Fiad, // PHY Address + output NoPre, // No Preamble (no 32-bit preamble) + output WCtrlData, // Write Control Data operation + output RStat, // Read Status operation + output ScanStat, // Scan Status operation + input Busy, // Busy Signal + input LinkFail, // Link Integrity Signal + input Nvalid, // Invalid Status (qualifier for the valid scan result) + input [15:0] Prsd, // Read Status Data (data read from the PHY) + input WCtrlDataStart, // This signals resets the WCTRLDATA bit in the MIIM Command register + input RStatStart, // This signal resets the RSTAT BIT in the MIIM Command register + input UpdateMIIRX_DATAReg // Updates MII RX_DATA register with read data +); + + // New registers for controlling the MII interface + wire [8:0] MIIMODER; + reg [2:0] MIICOMMAND; + wire [12:0] MIIADDRESS; + wire [15:0] MIITX_DATA; + reg [15:0] MIIRX_DATA; + wire [2:0] MIISTATUS; + + // New registers for controlling the MII interface + + // MIIMODER + assign NoPre = MIIMODER[8]; + assign Divider = MIIMODER[7:0]; + // MIICOMMAND + assign WCtrlData = MIICOMMAND[2]; + assign RStat = MIICOMMAND[1]; + assign ScanStat = MIICOMMAND[0]; + // MIIADDRESS + assign Rgad = MIIADDRESS[12:8]; + assign Fiad = MIIADDRESS[4:0]; + // MIITX_DATA + assign CtrlData = MIITX_DATA[15:0]; + // MIISTATUS + assign MIISTATUS[2:0] = { 13'b0, Nvalid, Busy, LinkFail }; + + wire Wr; + + RegCPUData #( 5 ) U_0_000( Tx_Hwmark , 7'd000, 5'h09, RST_I, CLK_I, Wr, ADR_I, DAT_I[4:0] ); + RegCPUData #( 5 ) U_0_001( Tx_Lwmark , 7'd001, 5'h08, RST_I, CLK_I, Wr, ADR_I, DAT_I[4:0] ); + RegCPUData #( 1 ) U_0_002( pause_frame_send_en , 7'd002, 1'h0, RST_I, CLK_I, Wr, ADR_I, DAT_I[0:0] ); + RegCPUData #( 16 ) U_0_003( pause_quanta_set , 7'd003, 16'h01af, RST_I, CLK_I, Wr, ADR_I, DAT_I[15:0] ); + RegCPUData #( 6 ) U_0_004( IFGset , 7'd004, 6'h0c, RST_I, CLK_I, Wr, ADR_I, DAT_I[5:0] ); + RegCPUData #( 1 ) U_0_005( FullDuplex , 7'd005, 1'h1, RST_I, CLK_I, Wr, ADR_I, DAT_I[0:0] ); + RegCPUData #( 4 ) U_0_006( MaxRetry , 7'd006, 4'h2, RST_I, CLK_I, Wr, ADR_I, DAT_I[3:0] ); + RegCPUData #( 1 ) U_0_007( MAC_tx_add_en , 7'd007, 1'h0, RST_I, CLK_I, Wr, ADR_I, DAT_I[0:0] ); + RegCPUData #( 8 ) U_0_008( MAC_tx_add_prom_data , 7'd008, 8'h00, RST_I, CLK_I, Wr, ADR_I, DAT_I[7:0] ); + RegCPUData #( 3 ) U_0_009( MAC_tx_add_prom_add , 7'd009, 3'h0, RST_I, CLK_I, Wr, ADR_I, DAT_I[2:0] ); + RegCPUData #( 1 ) U_0_010( MAC_tx_add_prom_wr , 7'd010, 1'h0, RST_I, CLK_I, Wr, ADR_I, DAT_I[0:0] ); + RegCPUData #( 1 ) U_0_011( tx_pause_en , 7'd011, 1'h1, RST_I, CLK_I, Wr, ADR_I, DAT_I[0:0] ); + RegCPUData #( 16 ) U_0_012( fc_hwmark , 7'd012, 1'h0, RST_I, CLK_I, Wr, ADR_I, DAT_I[15:0] ); + RegCPUData #( 16 ) U_0_013( fc_lwmark , 7'd013, 1'h0, RST_I, CLK_I, Wr, ADR_I, DAT_I[15:0] ); + RegCPUData #( 1 ) U_0_014( MAC_rx_add_chk_en , 7'd014, 1'h0, RST_I, CLK_I, Wr, ADR_I, DAT_I[0:0] ); + RegCPUData #( 8 ) U_0_015( MAC_rx_add_prom_data , 7'd015, 8'h00, RST_I, CLK_I, Wr, ADR_I, DAT_I[7:0] ); + RegCPUData #( 3 ) U_0_016( MAC_rx_add_prom_add , 7'd016, 3'h0, RST_I, CLK_I, Wr, ADR_I, DAT_I[2:0] ); + RegCPUData #( 1 ) U_0_017( MAC_rx_add_prom_wr , 7'd017, 1'h0, RST_I, CLK_I, Wr, ADR_I, DAT_I[0:0] ); + RegCPUData #( 1 ) U_0_018( broadcast_filter_en , 7'd018, 1'h0, RST_I, CLK_I, Wr, ADR_I, DAT_I[0:0] ); + RegCPUData #( 16 ) U_0_019( broadcast_bucket_depth , 7'd019, 16'h0000, RST_I, CLK_I, Wr, ADR_I, DAT_I[15:0] ); + RegCPUData #( 16 ) U_0_020( broadcast_bucket_interval , 7'd020, 16'h0000, RST_I, CLK_I, Wr, ADR_I, DAT_I[15:0] ); + RegCPUData #( 1 ) U_0_021( RX_APPEND_CRC , 7'd021, 1'h0, RST_I, CLK_I, Wr, ADR_I, DAT_I[0:0] ); + RegCPUData #( 5 ) U_0_022( Rx_Hwmark , 7'd022, 5'h1a, RST_I, CLK_I, Wr, ADR_I, DAT_I[4:0] ); + RegCPUData #( 5 ) U_0_023( Rx_Lwmark , 7'd023, 5'h10, RST_I, CLK_I, Wr, ADR_I, DAT_I[4:0] ); + RegCPUData #( 1 ) U_0_024( CRC_chk_en , 7'd024, 1'h1, RST_I, CLK_I, Wr, ADR_I, DAT_I[0:0] ); + RegCPUData #( 6 ) U_0_025( RX_IFG_SET , 7'd025, 6'h0c, RST_I, CLK_I, Wr, ADR_I, DAT_I[5:0] ); + RegCPUData #( 16 ) U_0_026( RX_MAX_LENGTH , 7'd026, 16'h2710, RST_I, CLK_I, Wr, ADR_I, DAT_I[15:0] ); + RegCPUData #( 7 ) U_0_027( RX_MIN_LENGTH , 7'd027, 7'h40, RST_I, CLK_I, Wr, ADR_I, DAT_I[6:0] ); + RegCPUData #( 6 ) U_0_028( CPU_rd_addr , 7'd028, 6'h00, RST_I, CLK_I, Wr, ADR_I, DAT_I[5:0] ); + RegCPUData #( 1 ) U_0_029( CPU_rd_apply , 7'd029, 1'h0, RST_I, CLK_I, Wr, ADR_I, DAT_I[0:0] ); +//RegCPUData #( 1 ) U_0_030( CPU_rd_grant , 7'd030, 1'h0, RST_I, CLK_I, Wr, ADR_I, DAT_I[0:0] ); +//RegCPUData #( 16 ) U_0_031( CPU_rd_dout_l , 7'd031, 16'h0000, RST_I, CLK_I, Wr, ADR_I, DAT_I[15:0] ); +//RegCPUData #( 16 ) U_0_032( CPU_rd_dout_h , 7'd032, 16'h0000, RST_I, CLK_I, Wr, ADR_I, DAT_I[15:0] ); + RegCPUData #( 1 ) U_0_033( Line_loop_en , 7'd033, 1'h0, RST_I, CLK_I, Wr, ADR_I, DAT_I[0:0] ); + RegCPUData #( 3 ) U_0_034( Speed , 7'd034, 3'h0, RST_I, CLK_I, Wr, ADR_I, DAT_I[2:0] ); + + // New registers for controlling the MDIO interface + RegCPUData #( 9 ) U_0_035( MIIMODER , 7'd035, 9'h064, RST_I, CLK_I, Wr, ADR_I, DAT_I[8:0] ); + // Reg #36 is MIICOMMAND - implemented separately below + RegCPUData #( 13 ) U_0_037( MIIADDRESS , 7'd037, 13'h0000, RST_I, CLK_I, Wr, ADR_I, DAT_I[12:0] ); + RegCPUData #( 16 ) U_0_038( MIITX_DATA , 7'd038, 16'h0000, RST_I, CLK_I, Wr, ADR_I, DAT_I[15:0] ); + + // Asserted in first clock of 2-cycle access, negated otherwise + wire Access = ~ACK_O & STB_I & CYC_I; + + // Asserted in first clock of 2-cycle write access, negated otherwise + assign Wr = Access & WE_I; + + // MIICOMMAND register - needs special treatment because of auto-resetting bits + always @ ( posedge RST_I or posedge CLK_I ) + if ( RST_I ) + MIICOMMAND <= 0; + else + begin + if ( Wr & ( ADR_I == 7'd036 ) ) + // Write access + MIICOMMAND <= DAT_I; + else + begin + if ( WCtrlDataStart ) + MIICOMMAND[2] <= 0; + if ( RStatStart ) + MIICOMMAND[1] <= 0; + end + end + + // MIIRX_DATA register + always @ ( posedge RST_I or posedge CLK_I ) + if ( RST_I ) + MIIRX_DATA <= 0; + else + if ( UpdateMIIRX_DATAReg ) + MIIRX_DATA <= Prsd; + + // ACK_O is asserted in second clock of 2-cycle access, negated otherwise + always @ ( posedge RST_I or posedge CLK_I ) + if ( RST_I ) + ACK_O <= 0; + else + ACK_O <= Access; + + always @ ( posedge RST_I or posedge CLK_I ) + if(RST_I) + DAT_O <= 0; + else + begin + DAT_O <=0; + if ( Access & ~WE_I ) + casez ( ADR_I ) + 7'd00: DAT_O <= Tx_Hwmark; + 7'd01: DAT_O <= Tx_Lwmark; + 7'd02: DAT_O <= pause_frame_send_en; + 7'd03: DAT_O <= pause_quanta_set; + 7'd04: DAT_O <= IFGset; + 7'd05: DAT_O <= FullDuplex; + 7'd06: DAT_O <= MaxRetry; + 7'd07: DAT_O <= MAC_tx_add_en; + 7'd08: DAT_O <= MAC_tx_add_prom_data; + 7'd09: DAT_O <= MAC_tx_add_prom_add; + 7'd10: DAT_O <= MAC_tx_add_prom_wr; + 7'd11: DAT_O <= tx_pause_en; + 7'd12: DAT_O <= fc_hwmark; + 7'd13: DAT_O <= fc_lwmark; + 7'd14: DAT_O <= MAC_rx_add_chk_en; + 7'd15: DAT_O <= MAC_rx_add_prom_data; + 7'd16: DAT_O <= MAC_rx_add_prom_add; + 7'd17: DAT_O <= MAC_rx_add_prom_wr; + 7'd18: DAT_O <= broadcast_filter_en; + 7'd19: DAT_O <= broadcast_bucket_depth; + 7'd20: DAT_O <= broadcast_bucket_interval; + 7'd21: DAT_O <= RX_APPEND_CRC; + 7'd22: DAT_O <= Rx_Hwmark; + 7'd23: DAT_O <= Rx_Lwmark; + 7'd24: DAT_O <= CRC_chk_en; + 7'd25: DAT_O <= RX_IFG_SET; + 7'd26: DAT_O <= RX_MAX_LENGTH; + 7'd27: DAT_O <= RX_MIN_LENGTH; + 7'd28: DAT_O <= CPU_rd_addr; + 7'd29: DAT_O <= CPU_rd_apply; + 7'd30: DAT_O <= CPU_rd_grant; + 7'd31: DAT_O <= CPU_rd_dout; + //7'd32: DAT_O <= CPU_rd_dout[31:16]; + 7'd33: DAT_O <= Line_loop_en; + 7'd34: DAT_O <= Speed; + + // New registers for controlling MII interface + 7'd35: DAT_O <= MIIMODER; + 7'd36: DAT_O <= MIICOMMAND; + 7'd37: DAT_O <= MIIADDRESS; + 7'd38: DAT_O <= MIITX_DATA; + 7'd39: DAT_O <= MIIRX_DATA; + 7'd40: DAT_O <= MIISTATUS; + endcase + end + +endmodule + +module RegCPUData( + RegOut, + RegAddr, + RegInit, + + Reset, + Clk, + Wr, + Addr, + WrData +); + + parameter WIDTH = 16; + + output reg [WIDTH-1:0] RegOut; + input [6:0] RegAddr; + input [WIDTH-1:0] RegInit; + + input Reset; + input Clk; + input Wr; + input [6:0] Addr; + input [WIDTH-1:0] WrData; + + always @( posedge Reset or posedge Clk ) + if ( Reset ) + RegOut <= RegInit; + else + if ( Wr && ( Addr == RegAddr ) ) + RegOut <= WrData; + +endmodule diff --git a/eth/rtl/verilog/TECH/eth_clk_div2.v b/eth/rtl/verilog/TECH/eth_clk_div2.v new file mode 100644 index 000000000..994907d44 --- /dev/null +++ b/eth/rtl/verilog/TECH/eth_clk_div2.v @@ -0,0 +1,71 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// eth_clk_div2.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source 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 Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: CLK_DIV2.v,v $ +// Revision 1.3 2006/01/19 14:07:56 maverickist +// verification is complete. +// +// Revision 1.2 2005/12/16 06:44:20 Administrator +// replaced tab with space. +// passed 9.6k length frame test. +// +// Revision 1.1.1.1 2005/12/13 01:51:44 Administrator +// no message +// + + +////////////////////////////////////////////////////////////////////// +// This file can only used for simulation . +// You need to replace it with your own element according to technology +////////////////////////////////////////////////////////////////////// + +module eth_clk_div2 ( + input Reset, + input IN, + output reg OUT +); + +always @ (posedge IN or posedge Reset) + if (Reset) + OUT <= 0; + else + OUT <= ~OUT; + +endmodule diff --git a/eth/rtl/verilog/TECH/eth_clk_switch.v b/eth/rtl/verilog/TECH/eth_clk_switch.v new file mode 100644 index 000000000..c5375743f --- /dev/null +++ b/eth/rtl/verilog/TECH/eth_clk_switch.v @@ -0,0 +1,81 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// eth_clk_switch.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source 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 Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: CLK_SWITCH.v,v $ +// Revision 1.3 2006/01/19 14:07:56 maverickist +// verification is complete. +// +// Revision 1.2 2005/12/16 06:44:20 Administrator +// replaced tab with space. +// passed 9.6k length frame test. +// +// Revision 1.1.1.1 2005/12/13 01:51:44 Administrator +// no message +// + +`include "header.vh" + +////////////////////////////////////////////////////////////////////// +// This file can only used for simulation . +// You need to replace it with your own element according to technology +////////////////////////////////////////////////////////////////////// +module eth_clk_switch ( + input IN_0, + input IN_1, + input SW, + output OUT +); + +`ifdef MAC_TARGET_XILINX + + BUFGMUX U_BUFGMUX ( + .O ( OUT ), + .I0( IN_0 ), + .I1( IN_1 ), + .S ( SW ) + ); + +`else + + assign OUT = SW ? IN_1 : IN_0; + +`endif + +endmodule diff --git a/eth/rtl/verilog/TECH/xilinx/BUFGMUX.v b/eth/rtl/verilog/TECH/xilinx/BUFGMUX.v new file mode 100644 index 000000000..f5bb4a74a --- /dev/null +++ b/eth/rtl/verilog/TECH/xilinx/BUFGMUX.v @@ -0,0 +1,64 @@ +// $Header: /devl/xcs/repo/env/Databases/CAEInterfaces/verunilibs/data/unisims/BUFGMUX.v,v 1.9.34.2 2005/10/21 20:45:30 wloo Exp $ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 1995/2004 Xilinx, Inc. +// All Right Reserved. +/////////////////////////////////////////////////////////////////////////////// +// ____ ____ +// / /\/ / +// /___/ \ / Vendor : Xilinx +// \ \ \/ Version : 7.1i (H.19) +// \ \ Description : Xilinx Functional Simulation Library Component +// / / Global Clock Mux Buffer with Output State 0 +// /___/ /\ Filename : BUFGMUX.v +// \ \ / \ Timestamp : Thu Mar 25 16:42:14 PST 2004 +// \___\/\___\ +// +// Revision: +// 03/23/04 - Initial version. + +`timescale 100 ps / 10 ps + +module BUFGMUX (O, I0, I1, S); + + output O; + + input I0, I1, S; + + reg q0, q1; + reg q0_enable, q1_enable; + + tri0 GSR = glbl.GSR; + + bufif1 B0 (O, I0, q0); + bufif1 B1 (O, I1, q1); + pulldown P1 (O); + + always @(GSR or I0 or S or q0_enable) + if (GSR) + q0 <= 1; + else if (!I0) + q0 <= !S && q0_enable; + + always @(GSR or I1 or S or q1_enable) + if (GSR) + q1 <= 0; + else if (!I1) + q1 <= S && q1_enable; + + always @(GSR or q1 or I0) + if (GSR) + q0_enable <= 1; + else if (q1) + q0_enable <= 0; + else if (I0) + q0_enable <= !q1; + + always @(GSR or q0 or I1) + if (GSR) + q1_enable <= 0; + else if (q0) + q1_enable <= 0; + else if (I1) + q1_enable <= !q0; + +endmodule diff --git a/eth/rtl/verilog/TECH/xilinx/RAMB16_S36_S36.v b/eth/rtl/verilog/TECH/xilinx/RAMB16_S36_S36.v new file mode 100644 index 000000000..80545a9b8 --- /dev/null +++ b/eth/rtl/verilog/TECH/xilinx/RAMB16_S36_S36.v @@ -0,0 +1,2204 @@ +// $Header: /devl/xcs/repo/env/Databases/CAEInterfaces/verunilibs/data/unisims/RAMB16_S36_S36.v,v 1.9 2005/03/14 22:54:41 wloo Exp $ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 1995/2005 Xilinx, Inc. +// All Right Reserved. +/////////////////////////////////////////////////////////////////////////////// +// ____ ____ +// / /\/ / +// /___/ \ / Vendor : Xilinx +// \ \ \/ Version : 8.1i (I.13) +// \ \ Description : Xilinx Functional Simulation Library Component +// / / 16K-Bit Data and 2K-Bit Parity Dual Port Block RAM +// /___/ /\ Filename : RAMB16_S36_S36.v +// \ \ / \ Timestamp : Thu Mar 10 16:43:36 PST 2005 +// \___\/\___\ +// +// Revision: +// 03/23/04 - Initial version. +// End Revision + +`ifdef legacy_model + +`timescale 1 ps / 1 ps + +module RAMB16_S36_S36 (DOA, DOB, DOPA, DOPB, ADDRA, ADDRB, CLKA, CLKB, DIA, DIB, DIPA, DIPB, ENA, ENB, SSRA, SSRB, WEA, WEB); + + parameter INIT_A = 36'h0; + parameter INIT_B = 36'h0; + parameter SRVAL_A = 36'h0; + parameter SRVAL_B = 36'h0; + parameter WRITE_MODE_A = "WRITE_FIRST"; + parameter WRITE_MODE_B = "WRITE_FIRST"; + parameter SIM_COLLISION_CHECK = "ALL"; + localparam SETUP_ALL = 1000; + localparam SETUP_READ_FIRST = 3000; + + parameter INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_10 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_11 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_12 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_13 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_14 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_15 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_16 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_17 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_18 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_19 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1A = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1B = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1C = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1D = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1E = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_20 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_21 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_22 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_23 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_24 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_25 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_26 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_27 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_28 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_29 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2A = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2B = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2C = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2D = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2E = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_30 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_31 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_32 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_33 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_34 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_35 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_36 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_37 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_38 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_39 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3A = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3B = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3C = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3D = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3E = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + + output [31:0] DOA; + output [3:0] DOPA; + reg [31:0] doa_out; + reg [3:0] dopa_out; + wire doa_out0, doa_out1, doa_out2, doa_out3, doa_out4, doa_out5, doa_out6, doa_out7, doa_out8, doa_out9, doa_out10, doa_out11, doa_out12, doa_out13, doa_out14, doa_out15, doa_out16, doa_out17, doa_out18, doa_out19, doa_out20, doa_out21, doa_out22, doa_out23, doa_out24, doa_out25, doa_out26, doa_out27, doa_out28, doa_out29, doa_out30, doa_out31; + wire dopa0_out, dopa1_out, dopa2_out, dopa3_out; + + input [8:0] ADDRA; + input [31:0] DIA; + input [3:0] DIPA; + input ENA, CLKA, WEA, SSRA; + + output [31:0] DOB; + output [3:0] DOPB; + reg [31:0] dob_out; + reg [3:0] dopb_out; + wire dob_out0, dob_out1, dob_out2, dob_out3, dob_out4, dob_out5, dob_out6, dob_out7, dob_out8, dob_out9, dob_out10, dob_out11, dob_out12, dob_out13, dob_out14, dob_out15, dob_out16, dob_out17, dob_out18, dob_out19, dob_out20, dob_out21, dob_out22, dob_out23, dob_out24, dob_out25, dob_out26, dob_out27, dob_out28, dob_out29, dob_out30, dob_out31; + wire dopb0_out, dopb1_out, dopb2_out, dopb3_out; + + input [8:0] ADDRB; + input [31:0] DIB; + input [3:0] DIPB; + input ENB, CLKB, WEB, SSRB; + + reg [18431:0] mem; + reg [8:0] count; + reg [1:0] wr_mode_a, wr_mode_b; + + reg [5:0] dmi, dbi; + reg [5:0] pmi, pbi; + + wire [8:0] addra_int; + reg [8:0] addra_reg; + wire [31:0] dia_int; + wire [3:0] dipa_int; + wire ena_int, clka_int, wea_int, ssra_int; + reg ena_reg, wea_reg, ssra_reg; + wire [8:0] addrb_int; + reg [8:0] addrb_reg; + wire [31:0] dib_int; + wire [3:0] dipb_int; + wire enb_int, clkb_int, web_int, ssrb_int; + reg display_flag; + reg enb_reg, web_reg, ssrb_reg; + + time time_clka, time_clkb; + time time_clka_clkb; + time time_clkb_clka; + + reg setup_all_a_b; + reg setup_all_b_a; + reg setup_zero; + reg setup_rf_a_b; + reg setup_rf_b_a; + reg [1:0] data_collision, data_collision_a_b, data_collision_b_a; + reg memory_collision, memory_collision_a_b, memory_collision_b_a; + reg address_collision, address_collision_a_b, address_collision_b_a; + reg change_clka; + reg change_clkb; + + wire [14:0] data_addra_int; + wire [14:0] data_addra_reg; + wire [14:0] data_addrb_int; + wire [14:0] data_addrb_reg; + wire [15:0] parity_addra_int; + wire [15:0] parity_addra_reg; + wire [15:0] parity_addrb_int; + wire [15:0] parity_addrb_reg; + + tri0 GSR = glbl.GSR; + + always @(GSR) + if (GSR) begin + assign doa_out = INIT_A[31:0]; + assign dopa_out = INIT_A[35:32]; + assign dob_out = INIT_B[31:0]; + assign dopb_out = INIT_B[35:32]; + end + else begin + deassign doa_out; + deassign dopa_out; + deassign dob_out; + deassign dopb_out; + end + + buf b_doa_out0 (doa_out0, doa_out[0]); + buf b_doa_out1 (doa_out1, doa_out[1]); + buf b_doa_out2 (doa_out2, doa_out[2]); + buf b_doa_out3 (doa_out3, doa_out[3]); + buf b_doa_out4 (doa_out4, doa_out[4]); + buf b_doa_out5 (doa_out5, doa_out[5]); + buf b_doa_out6 (doa_out6, doa_out[6]); + buf b_doa_out7 (doa_out7, doa_out[7]); + buf b_doa_out8 (doa_out8, doa_out[8]); + buf b_doa_out9 (doa_out9, doa_out[9]); + buf b_doa_out10 (doa_out10, doa_out[10]); + buf b_doa_out11 (doa_out11, doa_out[11]); + buf b_doa_out12 (doa_out12, doa_out[12]); + buf b_doa_out13 (doa_out13, doa_out[13]); + buf b_doa_out14 (doa_out14, doa_out[14]); + buf b_doa_out15 (doa_out15, doa_out[15]); + buf b_doa_out16 (doa_out16, doa_out[16]); + buf b_doa_out17 (doa_out17, doa_out[17]); + buf b_doa_out18 (doa_out18, doa_out[18]); + buf b_doa_out19 (doa_out19, doa_out[19]); + buf b_doa_out20 (doa_out20, doa_out[20]); + buf b_doa_out21 (doa_out21, doa_out[21]); + buf b_doa_out22 (doa_out22, doa_out[22]); + buf b_doa_out23 (doa_out23, doa_out[23]); + buf b_doa_out24 (doa_out24, doa_out[24]); + buf b_doa_out25 (doa_out25, doa_out[25]); + buf b_doa_out26 (doa_out26, doa_out[26]); + buf b_doa_out27 (doa_out27, doa_out[27]); + buf b_doa_out28 (doa_out28, doa_out[28]); + buf b_doa_out29 (doa_out29, doa_out[29]); + buf b_doa_out30 (doa_out30, doa_out[30]); + buf b_doa_out31 (doa_out31, doa_out[31]); + buf b_dopa_out0 (dopa_out0, dopa_out[0]); + buf b_dopa_out1 (dopa_out1, dopa_out[1]); + buf b_dopa_out2 (dopa_out2, dopa_out[2]); + buf b_dopa_out3 (dopa_out3, dopa_out[3]); + buf b_dob_out0 (dob_out0, dob_out[0]); + buf b_dob_out1 (dob_out1, dob_out[1]); + buf b_dob_out2 (dob_out2, dob_out[2]); + buf b_dob_out3 (dob_out3, dob_out[3]); + buf b_dob_out4 (dob_out4, dob_out[4]); + buf b_dob_out5 (dob_out5, dob_out[5]); + buf b_dob_out6 (dob_out6, dob_out[6]); + buf b_dob_out7 (dob_out7, dob_out[7]); + buf b_dob_out8 (dob_out8, dob_out[8]); + buf b_dob_out9 (dob_out9, dob_out[9]); + buf b_dob_out10 (dob_out10, dob_out[10]); + buf b_dob_out11 (dob_out11, dob_out[11]); + buf b_dob_out12 (dob_out12, dob_out[12]); + buf b_dob_out13 (dob_out13, dob_out[13]); + buf b_dob_out14 (dob_out14, dob_out[14]); + buf b_dob_out15 (dob_out15, dob_out[15]); + buf b_dob_out16 (dob_out16, dob_out[16]); + buf b_dob_out17 (dob_out17, dob_out[17]); + buf b_dob_out18 (dob_out18, dob_out[18]); + buf b_dob_out19 (dob_out19, dob_out[19]); + buf b_dob_out20 (dob_out20, dob_out[20]); + buf b_dob_out21 (dob_out21, dob_out[21]); + buf b_dob_out22 (dob_out22, dob_out[22]); + buf b_dob_out23 (dob_out23, dob_out[23]); + buf b_dob_out24 (dob_out24, dob_out[24]); + buf b_dob_out25 (dob_out25, dob_out[25]); + buf b_dob_out26 (dob_out26, dob_out[26]); + buf b_dob_out27 (dob_out27, dob_out[27]); + buf b_dob_out28 (dob_out28, dob_out[28]); + buf b_dob_out29 (dob_out29, dob_out[29]); + buf b_dob_out30 (dob_out30, dob_out[30]); + buf b_dob_out31 (dob_out31, dob_out[31]); + buf b_dopb_out0 (dopb_out0, dopb_out[0]); + buf b_dopb_out1 (dopb_out1, dopb_out[1]); + buf b_dopb_out2 (dopb_out2, dopb_out[2]); + buf b_dopb_out3 (dopb_out3, dopb_out[3]); + + buf b_doa0 (DOA[0], doa_out0); + buf b_doa1 (DOA[1], doa_out1); + buf b_doa2 (DOA[2], doa_out2); + buf b_doa3 (DOA[3], doa_out3); + buf b_doa4 (DOA[4], doa_out4); + buf b_doa5 (DOA[5], doa_out5); + buf b_doa6 (DOA[6], doa_out6); + buf b_doa7 (DOA[7], doa_out7); + buf b_doa8 (DOA[8], doa_out8); + buf b_doa9 (DOA[9], doa_out9); + buf b_doa10 (DOA[10], doa_out10); + buf b_doa11 (DOA[11], doa_out11); + buf b_doa12 (DOA[12], doa_out12); + buf b_doa13 (DOA[13], doa_out13); + buf b_doa14 (DOA[14], doa_out14); + buf b_doa15 (DOA[15], doa_out15); + buf b_doa16 (DOA[16], doa_out16); + buf b_doa17 (DOA[17], doa_out17); + buf b_doa18 (DOA[18], doa_out18); + buf b_doa19 (DOA[19], doa_out19); + buf b_doa20 (DOA[20], doa_out20); + buf b_doa21 (DOA[21], doa_out21); + buf b_doa22 (DOA[22], doa_out22); + buf b_doa23 (DOA[23], doa_out23); + buf b_doa24 (DOA[24], doa_out24); + buf b_doa25 (DOA[25], doa_out25); + buf b_doa26 (DOA[26], doa_out26); + buf b_doa27 (DOA[27], doa_out27); + buf b_doa28 (DOA[28], doa_out28); + buf b_doa29 (DOA[29], doa_out29); + buf b_doa30 (DOA[30], doa_out30); + buf b_doa31 (DOA[31], doa_out31); + buf b_dopa0 (DOPA[0], dopa_out0); + buf b_dopa1 (DOPA[1], dopa_out1); + buf b_dopa2 (DOPA[2], dopa_out2); + buf b_dopa3 (DOPA[3], dopa_out3); + buf b_dob0 (DOB[0], dob_out0); + buf b_dob1 (DOB[1], dob_out1); + buf b_dob2 (DOB[2], dob_out2); + buf b_dob3 (DOB[3], dob_out3); + buf b_dob4 (DOB[4], dob_out4); + buf b_dob5 (DOB[5], dob_out5); + buf b_dob6 (DOB[6], dob_out6); + buf b_dob7 (DOB[7], dob_out7); + buf b_dob8 (DOB[8], dob_out8); + buf b_dob9 (DOB[9], dob_out9); + buf b_dob10 (DOB[10], dob_out10); + buf b_dob11 (DOB[11], dob_out11); + buf b_dob12 (DOB[12], dob_out12); + buf b_dob13 (DOB[13], dob_out13); + buf b_dob14 (DOB[14], dob_out14); + buf b_dob15 (DOB[15], dob_out15); + buf b_dob16 (DOB[16], dob_out16); + buf b_dob17 (DOB[17], dob_out17); + buf b_dob18 (DOB[18], dob_out18); + buf b_dob19 (DOB[19], dob_out19); + buf b_dob20 (DOB[20], dob_out20); + buf b_dob21 (DOB[21], dob_out21); + buf b_dob22 (DOB[22], dob_out22); + buf b_dob23 (DOB[23], dob_out23); + buf b_dob24 (DOB[24], dob_out24); + buf b_dob25 (DOB[25], dob_out25); + buf b_dob26 (DOB[26], dob_out26); + buf b_dob27 (DOB[27], dob_out27); + buf b_dob28 (DOB[28], dob_out28); + buf b_dob29 (DOB[29], dob_out29); + buf b_dob30 (DOB[30], dob_out30); + buf b_dob31 (DOB[31], dob_out31); + buf b_dopb0 (DOPB[0], dopb_out0); + buf b_dopb1 (DOPB[1], dopb_out1); + buf b_dopb2 (DOPB[2], dopb_out2); + buf b_dopb3 (DOPB[3], dopb_out3); + + buf b_addra_0 (addra_int[0], ADDRA[0]); + buf b_addra_1 (addra_int[1], ADDRA[1]); + buf b_addra_2 (addra_int[2], ADDRA[2]); + buf b_addra_3 (addra_int[3], ADDRA[3]); + buf b_addra_4 (addra_int[4], ADDRA[4]); + buf b_addra_5 (addra_int[5], ADDRA[5]); + buf b_addra_6 (addra_int[6], ADDRA[6]); + buf b_addra_7 (addra_int[7], ADDRA[7]); + buf b_addra_8 (addra_int[8], ADDRA[8]); + buf b_dia_0 (dia_int[0], DIA[0]); + buf b_dia_1 (dia_int[1], DIA[1]); + buf b_dia_2 (dia_int[2], DIA[2]); + buf b_dia_3 (dia_int[3], DIA[3]); + buf b_dia_4 (dia_int[4], DIA[4]); + buf b_dia_5 (dia_int[5], DIA[5]); + buf b_dia_6 (dia_int[6], DIA[6]); + buf b_dia_7 (dia_int[7], DIA[7]); + buf b_dia_8 (dia_int[8], DIA[8]); + buf b_dia_9 (dia_int[9], DIA[9]); + buf b_dia_10 (dia_int[10], DIA[10]); + buf b_dia_11 (dia_int[11], DIA[11]); + buf b_dia_12 (dia_int[12], DIA[12]); + buf b_dia_13 (dia_int[13], DIA[13]); + buf b_dia_14 (dia_int[14], DIA[14]); + buf b_dia_15 (dia_int[15], DIA[15]); + buf b_dia_16 (dia_int[16], DIA[16]); + buf b_dia_17 (dia_int[17], DIA[17]); + buf b_dia_18 (dia_int[18], DIA[18]); + buf b_dia_19 (dia_int[19], DIA[19]); + buf b_dia_20 (dia_int[20], DIA[20]); + buf b_dia_21 (dia_int[21], DIA[21]); + buf b_dia_22 (dia_int[22], DIA[22]); + buf b_dia_23 (dia_int[23], DIA[23]); + buf b_dia_24 (dia_int[24], DIA[24]); + buf b_dia_25 (dia_int[25], DIA[25]); + buf b_dia_26 (dia_int[26], DIA[26]); + buf b_dia_27 (dia_int[27], DIA[27]); + buf b_dia_28 (dia_int[28], DIA[28]); + buf b_dia_29 (dia_int[29], DIA[29]); + buf b_dia_30 (dia_int[30], DIA[30]); + buf b_dia_31 (dia_int[31], DIA[31]); + buf b_dipa_0 (dipa_int[0], DIPA[0]); + buf b_dipa_1 (dipa_int[1], DIPA[1]); + buf b_dipa_2 (dipa_int[2], DIPA[2]); + buf b_dipa_3 (dipa_int[3], DIPA[3]); + buf b_ena (ena_int, ENA); + buf b_clka (clka_int, CLKA); + buf b_ssra (ssra_int, SSRA); + buf b_wea (wea_int, WEA); + buf b_addrb_0 (addrb_int[0], ADDRB[0]); + buf b_addrb_1 (addrb_int[1], ADDRB[1]); + buf b_addrb_2 (addrb_int[2], ADDRB[2]); + buf b_addrb_3 (addrb_int[3], ADDRB[3]); + buf b_addrb_4 (addrb_int[4], ADDRB[4]); + buf b_addrb_5 (addrb_int[5], ADDRB[5]); + buf b_addrb_6 (addrb_int[6], ADDRB[6]); + buf b_addrb_7 (addrb_int[7], ADDRB[7]); + buf b_addrb_8 (addrb_int[8], ADDRB[8]); + buf b_dib_0 (dib_int[0], DIB[0]); + buf b_dib_1 (dib_int[1], DIB[1]); + buf b_dib_2 (dib_int[2], DIB[2]); + buf b_dib_3 (dib_int[3], DIB[3]); + buf b_dib_4 (dib_int[4], DIB[4]); + buf b_dib_5 (dib_int[5], DIB[5]); + buf b_dib_6 (dib_int[6], DIB[6]); + buf b_dib_7 (dib_int[7], DIB[7]); + buf b_dib_8 (dib_int[8], DIB[8]); + buf b_dib_9 (dib_int[9], DIB[9]); + buf b_dib_10 (dib_int[10], DIB[10]); + buf b_dib_11 (dib_int[11], DIB[11]); + buf b_dib_12 (dib_int[12], DIB[12]); + buf b_dib_13 (dib_int[13], DIB[13]); + buf b_dib_14 (dib_int[14], DIB[14]); + buf b_dib_15 (dib_int[15], DIB[15]); + buf b_dib_16 (dib_int[16], DIB[16]); + buf b_dib_17 (dib_int[17], DIB[17]); + buf b_dib_18 (dib_int[18], DIB[18]); + buf b_dib_19 (dib_int[19], DIB[19]); + buf b_dib_20 (dib_int[20], DIB[20]); + buf b_dib_21 (dib_int[21], DIB[21]); + buf b_dib_22 (dib_int[22], DIB[22]); + buf b_dib_23 (dib_int[23], DIB[23]); + buf b_dib_24 (dib_int[24], DIB[24]); + buf b_dib_25 (dib_int[25], DIB[25]); + buf b_dib_26 (dib_int[26], DIB[26]); + buf b_dib_27 (dib_int[27], DIB[27]); + buf b_dib_28 (dib_int[28], DIB[28]); + buf b_dib_29 (dib_int[29], DIB[29]); + buf b_dib_30 (dib_int[30], DIB[30]); + buf b_dib_31 (dib_int[31], DIB[31]); + buf b_dipb_0 (dipb_int[0], DIPB[0]); + buf b_dipb_1 (dipb_int[1], DIPB[1]); + buf b_dipb_2 (dipb_int[2], DIPB[2]); + buf b_dipb_3 (dipb_int[3], DIPB[3]); + buf b_enb (enb_int, ENB); + buf b_clkb (clkb_int, CLKB); + buf b_ssrb (ssrb_int, SSRB); + buf b_web (web_int, WEB); + + initial begin + for (count = 0; count < 256; count = count + 1) begin + mem[count] <= INIT_00[count]; + mem[256 * 1 + count] <= INIT_01[count]; + mem[256 * 2 + count] <= INIT_02[count]; + mem[256 * 3 + count] <= INIT_03[count]; + mem[256 * 4 + count] <= INIT_04[count]; + mem[256 * 5 + count] <= INIT_05[count]; + mem[256 * 6 + count] <= INIT_06[count]; + mem[256 * 7 + count] <= INIT_07[count]; + mem[256 * 8 + count] <= INIT_08[count]; + mem[256 * 9 + count] <= INIT_09[count]; + mem[256 * 10 + count] <= INIT_0A[count]; + mem[256 * 11 + count] <= INIT_0B[count]; + mem[256 * 12 + count] <= INIT_0C[count]; + mem[256 * 13 + count] <= INIT_0D[count]; + mem[256 * 14 + count] <= INIT_0E[count]; + mem[256 * 15 + count] <= INIT_0F[count]; + mem[256 * 16 + count] <= INIT_10[count]; + mem[256 * 17 + count] <= INIT_11[count]; + mem[256 * 18 + count] <= INIT_12[count]; + mem[256 * 19 + count] <= INIT_13[count]; + mem[256 * 20 + count] <= INIT_14[count]; + mem[256 * 21 + count] <= INIT_15[count]; + mem[256 * 22 + count] <= INIT_16[count]; + mem[256 * 23 + count] <= INIT_17[count]; + mem[256 * 24 + count] <= INIT_18[count]; + mem[256 * 25 + count] <= INIT_19[count]; + mem[256 * 26 + count] <= INIT_1A[count]; + mem[256 * 27 + count] <= INIT_1B[count]; + mem[256 * 28 + count] <= INIT_1C[count]; + mem[256 * 29 + count] <= INIT_1D[count]; + mem[256 * 30 + count] <= INIT_1E[count]; + mem[256 * 31 + count] <= INIT_1F[count]; + mem[256 * 32 + count] <= INIT_20[count]; + mem[256 * 33 + count] <= INIT_21[count]; + mem[256 * 34 + count] <= INIT_22[count]; + mem[256 * 35 + count] <= INIT_23[count]; + mem[256 * 36 + count] <= INIT_24[count]; + mem[256 * 37 + count] <= INIT_25[count]; + mem[256 * 38 + count] <= INIT_26[count]; + mem[256 * 39 + count] <= INIT_27[count]; + mem[256 * 40 + count] <= INIT_28[count]; + mem[256 * 41 + count] <= INIT_29[count]; + mem[256 * 42 + count] <= INIT_2A[count]; + mem[256 * 43 + count] <= INIT_2B[count]; + mem[256 * 44 + count] <= INIT_2C[count]; + mem[256 * 45 + count] <= INIT_2D[count]; + mem[256 * 46 + count] <= INIT_2E[count]; + mem[256 * 47 + count] <= INIT_2F[count]; + mem[256 * 48 + count] <= INIT_30[count]; + mem[256 * 49 + count] <= INIT_31[count]; + mem[256 * 50 + count] <= INIT_32[count]; + mem[256 * 51 + count] <= INIT_33[count]; + mem[256 * 52 + count] <= INIT_34[count]; + mem[256 * 53 + count] <= INIT_35[count]; + mem[256 * 54 + count] <= INIT_36[count]; + mem[256 * 55 + count] <= INIT_37[count]; + mem[256 * 56 + count] <= INIT_38[count]; + mem[256 * 57 + count] <= INIT_39[count]; + mem[256 * 58 + count] <= INIT_3A[count]; + mem[256 * 59 + count] <= INIT_3B[count]; + mem[256 * 60 + count] <= INIT_3C[count]; + mem[256 * 61 + count] <= INIT_3D[count]; + mem[256 * 62 + count] <= INIT_3E[count]; + mem[256 * 63 + count] <= INIT_3F[count]; + mem[256 * 64 + count] <= INITP_00[count]; + mem[256 * 65 + count] <= INITP_01[count]; + mem[256 * 66 + count] <= INITP_02[count]; + mem[256 * 67 + count] <= INITP_03[count]; + mem[256 * 68 + count] <= INITP_04[count]; + mem[256 * 69 + count] <= INITP_05[count]; + mem[256 * 70 + count] <= INITP_06[count]; + mem[256 * 71 + count] <= INITP_07[count]; + end + address_collision <= 0; + address_collision_a_b <= 0; + address_collision_b_a <= 0; + change_clka <= 0; + change_clkb <= 0; + data_collision <= 0; + data_collision_a_b <= 0; + data_collision_b_a <= 0; + memory_collision <= 0; + memory_collision_a_b <= 0; + memory_collision_b_a <= 0; + setup_all_a_b <= 0; + setup_all_b_a <= 0; + setup_zero <= 0; + setup_rf_a_b <= 0; + setup_rf_b_a <= 0; + end + + assign data_addra_int = addra_int * 32; + assign data_addra_reg = addra_reg * 32; + assign data_addrb_int = addrb_int * 32; + assign data_addrb_reg = addrb_reg * 32; + assign parity_addra_int = 16384 + addra_int * 4; + assign parity_addra_reg = 16384 + addra_reg * 4; + assign parity_addrb_int = 16384 + addrb_int * 4; + assign parity_addrb_reg = 16384 + addrb_reg * 4; + + + initial begin + + display_flag = 1; + + case (SIM_COLLISION_CHECK) + + "NONE" : begin + assign setup_all_a_b = 1'b0; + assign setup_all_b_a = 1'b0; + assign setup_zero = 1'b0; + assign setup_rf_a_b = 1'b0; + assign setup_rf_b_a = 1'b0; + assign display_flag = 0; + end + "WARNING_ONLY" : begin + assign data_collision = 2'b00; + assign data_collision_a_b = 2'b00; + assign data_collision_b_a = 2'b00; + assign memory_collision = 1'b0; + assign memory_collision_a_b = 1'b0; + assign memory_collision_b_a = 1'b0; + end + "GENERATE_X_ONLY" : begin + assign display_flag = 0; + end + "ALL" : ; + default : begin + $display("Attribute Syntax Error : The Attribute SIM_COLLISION_CHECK on RAMB16_S36_S36 instance %m is set to %s. Legal values for this attribute are ALL, NONE, WARNING_ONLY or GENERATE_X_ONLY.", SIM_COLLISION_CHECK); + $finish; + end + + endcase // case(SIM_COLLISION_CHECK) + + end // initial begin + + + always @(posedge clka_int) begin + time_clka = $time; + #0 time_clkb_clka = time_clka - time_clkb; + change_clka = ~change_clka; + end + + always @(posedge clkb_int) begin + time_clkb = $time; + #0 time_clka_clkb = time_clkb - time_clka; + change_clkb = ~change_clkb; + end + + always @(change_clkb) begin + if ((0 < time_clka_clkb) && (time_clka_clkb < SETUP_ALL)) + setup_all_a_b = 1; + if ((0 < time_clka_clkb) && (time_clka_clkb < SETUP_READ_FIRST)) + setup_rf_a_b = 1; + end + + always @(change_clka) begin + if ((0 < time_clkb_clka) && (time_clkb_clka < SETUP_ALL)) + setup_all_b_a = 1; + if ((0 < time_clkb_clka) && (time_clkb_clka < SETUP_READ_FIRST)) + setup_rf_b_a = 1; + end + + always @(change_clkb or change_clka) begin + if ((time_clkb_clka == 0) && (time_clka_clkb == 0)) + setup_zero = 1; + end + + always @(posedge setup_zero) begin + if ((ena_int == 1) && (wea_int == 1) && + (enb_int == 1) && (web_int == 1) && + (data_addra_int[14:5] == data_addrb_int[14:5])) + memory_collision <= 1; + end + + always @(posedge setup_all_a_b or posedge setup_rf_a_b) begin + if ((ena_reg == 1) && (wea_reg == 1) && + (enb_int == 1) && (web_int == 1) && + (data_addra_reg[14:5] == data_addrb_int[14:5])) + memory_collision_a_b <= 1; + end + + always @(posedge setup_all_b_a or posedge setup_rf_b_a) begin + if ((ena_int == 1) && (wea_int == 1) && + (enb_reg == 1) && (web_reg == 1) && + (data_addra_int[14:5] == data_addrb_reg[14:5])) + memory_collision_b_a <= 1; + end + + always @(posedge setup_all_a_b) begin + if (data_addra_reg[14:5] == data_addrb_int[14:5]) begin + if ((ena_reg == 1) && (enb_int == 1)) begin + case ({wr_mode_a, wr_mode_b, wea_reg, web_int}) + 6'b000011 : begin data_collision_a_b <= 2'b11; display_wa_wb; end + 6'b000111 : begin data_collision_a_b <= 2'b11; display_wa_wb; end + 6'b001011 : begin data_collision_a_b <= 2'b10; display_wa_wb; end +// 6'b010011 : begin data_collision_a_b <= 2'b00; display_wa_wb; end +// 6'b010111 : begin data_collision_a_b <= 2'b00; display_wa_wb; end +// 6'b011011 : begin data_collision_a_b <= 2'b00; display_wa_wb; end + 6'b100011 : begin data_collision_a_b <= 2'b01; display_wa_wb; end + 6'b100111 : begin data_collision_a_b <= 2'b01; display_wa_wb; end + 6'b101011 : begin display_wa_wb; end + 6'b000001 : begin data_collision_a_b <= 2'b10; display_ra_wb; end +// 6'b000101 : begin data_collision_a_b <= 2'b00; display_ra_wb; end + 6'b001001 : begin data_collision_a_b <= 2'b10; display_ra_wb; end + 6'b010001 : begin data_collision_a_b <= 2'b10; display_ra_wb; end +// 6'b010101 : begin data_collision_a_b <= 2'b00; display_ra_wb; end + 6'b011001 : begin data_collision_a_b <= 2'b10; display_ra_wb; end + 6'b100001 : begin data_collision_a_b <= 2'b10; display_ra_wb; end +// 6'b100101 : begin data_collision_a_b <= 2'b00; display_ra_wb; end + 6'b101001 : begin data_collision_a_b <= 2'b10; display_ra_wb; end + 6'b000010 : begin data_collision_a_b <= 2'b01; display_wa_rb; end + 6'b000110 : begin data_collision_a_b <= 2'b01; display_wa_rb; end + 6'b001010 : begin data_collision_a_b <= 2'b01; display_wa_rb; end +// 6'b010010 : begin data_collision_a_b <= 2'b00; display_wa_rb; end +// 6'b010110 : begin data_collision_a_b <= 2'b00; display_wa_rb; end +// 6'b011010 : begin data_collision_a_b <= 2'b00; display_wa_rb; end + 6'b100010 : begin data_collision_a_b <= 2'b01; display_wa_rb; end + 6'b100110 : begin data_collision_a_b <= 2'b01; display_wa_rb; end + 6'b101010 : begin data_collision_a_b <= 2'b01; display_wa_rb; end + endcase + end + end + setup_all_a_b <= 0; + end + + + always @(posedge setup_all_b_a) begin + if (data_addra_int[14:5] == data_addrb_reg[14:5]) begin + if ((ena_int == 1) && (enb_reg == 1)) begin + case ({wr_mode_a, wr_mode_b, wea_int, web_reg}) + 6'b000011 : begin data_collision_b_a <= 2'b11; display_wa_wb; end +// 6'b000111 : begin data_collision_b_a <= 2'b00; display_wa_wb; end + 6'b001011 : begin data_collision_b_a <= 2'b10; display_wa_wb; end + 6'b010011 : begin data_collision_b_a <= 2'b11; display_wa_wb; end +// 6'b010111 : begin data_collision_b_a <= 2'b00; display_wa_wb; end + 6'b011011 : begin data_collision_b_a <= 2'b10; display_wa_wb; end + 6'b100011 : begin data_collision_b_a <= 2'b01; display_wa_wb; end + 6'b100111 : begin data_collision_b_a <= 2'b01; display_wa_wb; end + 6'b101011 : begin display_wa_wb; end + 6'b000001 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b000101 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b001001 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b010001 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b010101 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b011001 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b100001 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b100101 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b101001 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b000010 : begin data_collision_b_a <= 2'b01; display_wa_rb; end + 6'b000110 : begin data_collision_b_a <= 2'b01; display_wa_rb; end + 6'b001010 : begin data_collision_b_a <= 2'b01; display_wa_rb; end +// 6'b010010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b010110 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b011010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end + 6'b100010 : begin data_collision_b_a <= 2'b01; display_wa_rb; end + 6'b100110 : begin data_collision_b_a <= 2'b01; display_wa_rb; end + 6'b101010 : begin data_collision_b_a <= 2'b01; display_wa_rb; end + endcase + end + end + setup_all_b_a <= 0; + end + + + always @(posedge setup_zero) begin + if (data_addra_int[14:5] == data_addrb_int[14:5]) begin + if ((ena_int == 1) && (enb_int == 1)) begin + case ({wr_mode_a, wr_mode_b, wea_int, web_int}) + 6'b000011 : begin data_collision <= 2'b11; display_wa_wb; end + 6'b000111 : begin data_collision <= 2'b11; display_wa_wb; end + 6'b001011 : begin data_collision <= 2'b10; display_wa_wb; end + 6'b010011 : begin data_collision <= 2'b11; display_wa_wb; end + 6'b010111 : begin data_collision <= 2'b11; display_wa_wb; end + 6'b011011 : begin data_collision <= 2'b10; display_wa_wb; end + 6'b100011 : begin data_collision <= 2'b01; display_wa_wb; end + 6'b100111 : begin data_collision <= 2'b01; display_wa_wb; end + 6'b101011 : begin display_wa_wb; end + 6'b000001 : begin data_collision <= 2'b10; display_ra_wb; end +// 6'b000101 : begin data_collision <= 2'b00; display_ra_wb; end + 6'b001001 : begin data_collision <= 2'b10; display_ra_wb; end + 6'b010001 : begin data_collision <= 2'b10; display_ra_wb; end +// 6'b010101 : begin data_collision <= 2'b00; display_ra_wb; end + 6'b011001 : begin data_collision <= 2'b10; display_ra_wb; end + 6'b100001 : begin data_collision <= 2'b10; display_ra_wb; end +// 6'b100101 : begin data_collision <= 2'b00; display_ra_wb; end + 6'b101001 : begin data_collision <= 2'b10; display_ra_wb; end + 6'b000010 : begin data_collision <= 2'b01; display_wa_rb; end + 6'b000110 : begin data_collision <= 2'b01; display_wa_rb; end + 6'b001010 : begin data_collision <= 2'b01; display_wa_rb; end +// 6'b010010 : begin data_collision <= 2'b00; display_wa_rb; end +// 6'b010110 : begin data_collision <= 2'b00; display_wa_rb; end +// 6'b011010 : begin data_collision <= 2'b00; display_wa_rb; end + 6'b100010 : begin data_collision <= 2'b01; display_wa_rb; end + 6'b100110 : begin data_collision <= 2'b01; display_wa_rb; end + 6'b101010 : begin data_collision <= 2'b01; display_wa_rb; end + endcase + end + end + setup_zero <= 0; + end + + task display_ra_wb; + begin + if (display_flag) + $display("Memory Collision Error on RAMB16_S36_S36:%m at simulation time %.3f ns\nA read was performed on address %h (hex) of Port A while a write was requested to the same address on Port B. The write will be successful however the read value on Port A is unknown until the next CLKA cycle.", $time/1000.0, addra_int); + end + endtask + + task display_wa_rb; + begin + if (display_flag) + $display("Memory Collision Error on RAMB16_S36_S36:%m at simulation time %.3f ns\nA read was performed on address %h (hex) of Port B while a write was requested to the same address on Port A. The write will be successful however the read value on Port B is unknown until the next CLKB cycle.", $time/1000.0, addrb_int); + end + endtask + + task display_wa_wb; + begin + if (display_flag) + $display("Memory Collision Error on RAMB16_S36_S36:%m at simulation time %.3f ns\nA write was requested to the same address simultaneously at both Port A and Port B of the RAM. The contents written to the RAM at address location %h (hex) of Port A and address location %h (hex) of Port B are unknown.", $time/1000.0, addra_int, addrb_int); + end + endtask + + + always @(posedge setup_rf_a_b) begin + if (data_addra_reg[14:5] == data_addrb_int[14:5]) begin + if ((ena_reg == 1) && (enb_int == 1)) begin + case ({wr_mode_a, wr_mode_b, wea_reg, web_int}) +// 6'b000011 : begin data_collision_a_b <= 2'b00; display_wa_wb; end +// 6'b000111 : begin data_collision_a_b <= 2'b00; display_wa_wb; end +// 6'b001011 : begin data_collision_a_b <= 2'b00; display_wa_wb; end + 6'b010011 : begin data_collision_a_b <= 2'b11; display_wa_wb; end + 6'b010111 : begin data_collision_a_b <= 2'b11; display_wa_wb; end + 6'b011011 : begin data_collision_a_b <= 2'b10; display_wa_wb; end +// 6'b100011 : begin data_collision_a_b <= 2'b00; display_wa_wb; end +// 6'b100111 : begin data_collision_a_b <= 2'b00; display_wa_wb; end +// 6'b101011 : begin data_collision_a_b <= 2'b00; display_wa_wb; end +// 6'b000001 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b000101 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b001001 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b010001 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b010101 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b011001 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b100001 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b100101 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b101001 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b000010 : begin data_collision_a_b <= 2'b00; display_wa_rb; end +// 6'b000110 : begin data_collision_a_b <= 2'b00; display_wa_rb; end +// 6'b001010 : begin data_collision_a_b <= 2'b00; display_wa_rb; end + 6'b010010 : begin data_collision_a_b <= 2'b01; display_wa_rb; end + 6'b010110 : begin data_collision_a_b <= 2'b01; display_wa_rb; end + 6'b011010 : begin data_collision_a_b <= 2'b01; display_wa_rb; end +// 6'b100010 : begin data_collision_a_b <= 2'b00; display_wa_rb; end +// 6'b100110 : begin data_collision_a_b <= 2'b00; display_wa_rb; end +// 6'b101010 : begin data_collision_a_b <= 2'b00; display_wa_rb; end + endcase + end + end + setup_rf_a_b <= 0; + end + + + always @(posedge setup_rf_b_a) begin + if (data_addra_int[14:5] == data_addrb_reg[14:5]) begin + if ((ena_int == 1) && (enb_reg == 1)) begin + case ({wr_mode_a, wr_mode_b, wea_int, web_reg}) +// 6'b000011 : begin data_collision_b_a <= 2'b00; display_wa_wb; end + 6'b000111 : begin data_collision_b_a <= 2'b11; display_wa_wb; end +// 6'b001011 : begin data_collision_b_a <= 2'b00; display_wa_wb; end +// 6'b010011 : begin data_collision_b_a <= 2'b00; display_wa_wb; end + 6'b010111 : begin data_collision_b_a <= 2'b11; display_wa_wb; end +// 6'b011011 : begin data_collision_b_a <= 2'b00; display_wa_wb; end +// 6'b100011 : begin data_collision_b_a <= 2'b00; display_wa_wb; end + 6'b100111 : begin data_collision_b_a <= 2'b01; display_wa_wb; end +// 6'b101011 : begin data_collision_b_a <= 2'b00; display_wa_wb; end +// 6'b000001 : begin data_collision_b_a <= 2'b00; display_ra_wb; end + 6'b000101 : begin data_collision_b_a <= 2'b10; display_ra_wb; end +// 6'b001001 : begin data_collision_b_a <= 2'b00; display_ra_wb; end +// 6'b010001 : begin data_collision_b_a <= 2'b00; display_ra_wb; end + 6'b010101 : begin data_collision_b_a <= 2'b10; display_ra_wb; end +// 6'b011001 : begin data_collision_b_a <= 2'b00; display_ra_wb; end +// 6'b100001 : begin data_collision_b_a <= 2'b00; display_ra_wb; end + 6'b100101 : begin data_collision_b_a <= 2'b10; display_ra_wb; end +// 6'b101001 : begin data_collision_b_a <= 2'b00; display_ra_wb; end +// 6'b000010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b000110 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b001010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b010010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b010110 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b011010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b100010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b100110 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b101010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end + endcase + end + end + setup_rf_b_a <= 0; + end + + + always @(posedge clka_int) begin + addra_reg <= addra_int; + ena_reg <= ena_int; + ssra_reg <= ssra_int; + wea_reg <= wea_int; + end + + always @(posedge clkb_int) begin + addrb_reg <= addrb_int; + enb_reg <= enb_int; + ssrb_reg <= ssrb_int; + web_reg <= web_int; + end + + // Data + always @(posedge memory_collision) begin + for (dmi = 0; dmi < 32; dmi = dmi + 1) begin + mem[data_addra_int + dmi] <= 1'bX; + end + memory_collision <= 0; + end + + always @(posedge memory_collision_a_b) begin + for (dmi = 0; dmi < 32; dmi = dmi + 1) begin + mem[data_addra_reg + dmi] <= 1'bX; + end + memory_collision_a_b <= 0; + end + + always @(posedge memory_collision_b_a) begin + for (dmi = 0; dmi < 32; dmi = dmi + 1) begin + mem[data_addra_int + dmi] <= 1'bX; + end + memory_collision_b_a <= 0; + end + + always @(posedge data_collision[1]) begin + if (ssra_int == 0) begin + doa_out <= 32'bX; + end + data_collision[1] <= 0; + end + + always @(posedge data_collision[0]) begin + if (ssrb_int == 0) begin + dob_out <= 32'bX; + end + data_collision[0] <= 0; + end + + always @(posedge data_collision_a_b[1]) begin + if (ssra_reg == 0) begin + doa_out <= 32'bX; + end + data_collision_a_b[1] <= 0; + end + + always @(posedge data_collision_a_b[0]) begin + if (ssrb_int == 0) begin + dob_out <= 32'bX; + end + data_collision_a_b[0] <= 0; + end + + always @(posedge data_collision_b_a[1]) begin + if (ssra_int == 0) begin + doa_out <= 32'bX; + end + data_collision_b_a[1] <= 0; + end + + always @(posedge data_collision_b_a[0]) begin + if (ssrb_reg == 0) begin + dob_out <= 32'bX; + end + data_collision_b_a[0] <= 0; + end + + + // Parity + always @(posedge memory_collision) begin + for (pmi = 0; pmi < 4; pmi = pmi + 1) begin + mem[parity_addra_int + pmi] <= 1'bX; + end + end + + always @(posedge memory_collision_a_b) begin + for (pmi = 0; pmi < 4; pmi = pmi + 1) begin + mem[parity_addra_reg + pmi] <= 1'bX; + end + end + + always @(posedge memory_collision_b_a) begin + for (pmi = 0; pmi < 4; pmi = pmi + 1) begin + mem[parity_addra_int + pmi] <= 1'bX; + end + end + + always @(posedge data_collision[1]) begin + if (ssra_int == 0) begin + dopa_out <= 4'bX; + end + end + + always @(posedge data_collision[0]) begin + if (ssrb_int == 0) begin + dopb_out <= 4'bX; + end + end + + always @(posedge data_collision_a_b[1]) begin + if (ssra_reg == 0) begin + dopa_out <= 4'bX; + end + end + + always @(posedge data_collision_a_b[0]) begin + if (ssrb_int == 0) begin + dopb_out <= 4'bX; + end + end + + always @(posedge data_collision_b_a[1]) begin + if (ssra_int == 0) begin + dopa_out <= 4'bX; + end + end + + always @(posedge data_collision_b_a[0]) begin + if (ssrb_reg == 0) begin + dopb_out <= 4'bX; + end + end + + + initial begin + case (WRITE_MODE_A) + "WRITE_FIRST" : wr_mode_a <= 2'b00; + "READ_FIRST" : wr_mode_a <= 2'b01; + "NO_CHANGE" : wr_mode_a <= 2'b10; + default : begin + $display("Attribute Syntax Error : The Attribute WRITE_MODE_A on RAMB16_S36_S36 instance %m is set to %s. Legal values for this attribute are WRITE_FIRST, READ_FIRST or NO_CHANGE.", WRITE_MODE_A); + $finish; + end + endcase + end + + initial begin + case (WRITE_MODE_B) + "WRITE_FIRST" : wr_mode_b <= 2'b00; + "READ_FIRST" : wr_mode_b <= 2'b01; + "NO_CHANGE" : wr_mode_b <= 2'b10; + default : begin + $display("Attribute Syntax Error : The Attribute WRITE_MODE_B on RAMB16_S36_S36 instance %m is set to %s. Legal values for this attribute are WRITE_FIRST, READ_FIRST or NO_CHANGE.", WRITE_MODE_B); + $finish; + end + endcase + end + + // Port A + always @(posedge clka_int) begin + if (ena_int == 1'b1) begin + if (ssra_int == 1'b1) begin + doa_out[0] <= SRVAL_A[0]; + doa_out[1] <= SRVAL_A[1]; + doa_out[2] <= SRVAL_A[2]; + doa_out[3] <= SRVAL_A[3]; + doa_out[4] <= SRVAL_A[4]; + doa_out[5] <= SRVAL_A[5]; + doa_out[6] <= SRVAL_A[6]; + doa_out[7] <= SRVAL_A[7]; + doa_out[8] <= SRVAL_A[8]; + doa_out[9] <= SRVAL_A[9]; + doa_out[10] <= SRVAL_A[10]; + doa_out[11] <= SRVAL_A[11]; + doa_out[12] <= SRVAL_A[12]; + doa_out[13] <= SRVAL_A[13]; + doa_out[14] <= SRVAL_A[14]; + doa_out[15] <= SRVAL_A[15]; + doa_out[16] <= SRVAL_A[16]; + doa_out[17] <= SRVAL_A[17]; + doa_out[18] <= SRVAL_A[18]; + doa_out[19] <= SRVAL_A[19]; + doa_out[20] <= SRVAL_A[20]; + doa_out[21] <= SRVAL_A[21]; + doa_out[22] <= SRVAL_A[22]; + doa_out[23] <= SRVAL_A[23]; + doa_out[24] <= SRVAL_A[24]; + doa_out[25] <= SRVAL_A[25]; + doa_out[26] <= SRVAL_A[26]; + doa_out[27] <= SRVAL_A[27]; + doa_out[28] <= SRVAL_A[28]; + doa_out[29] <= SRVAL_A[29]; + doa_out[30] <= SRVAL_A[30]; + doa_out[31] <= SRVAL_A[31]; + dopa_out[0] <= SRVAL_A[32]; + dopa_out[1] <= SRVAL_A[33]; + dopa_out[2] <= SRVAL_A[34]; + dopa_out[3] <= SRVAL_A[35]; + end + else begin + if (wea_int == 1'b1) begin + if (wr_mode_a == 2'b00) begin + doa_out <= dia_int; + dopa_out <= dipa_int; + end + else if (wr_mode_a == 2'b01) begin + doa_out[0] <= mem[data_addra_int + 0]; + doa_out[1] <= mem[data_addra_int + 1]; + doa_out[2] <= mem[data_addra_int + 2]; + doa_out[3] <= mem[data_addra_int + 3]; + doa_out[4] <= mem[data_addra_int + 4]; + doa_out[5] <= mem[data_addra_int + 5]; + doa_out[6] <= mem[data_addra_int + 6]; + doa_out[7] <= mem[data_addra_int + 7]; + doa_out[8] <= mem[data_addra_int + 8]; + doa_out[9] <= mem[data_addra_int + 9]; + doa_out[10] <= mem[data_addra_int + 10]; + doa_out[11] <= mem[data_addra_int + 11]; + doa_out[12] <= mem[data_addra_int + 12]; + doa_out[13] <= mem[data_addra_int + 13]; + doa_out[14] <= mem[data_addra_int + 14]; + doa_out[15] <= mem[data_addra_int + 15]; + doa_out[16] <= mem[data_addra_int + 16]; + doa_out[17] <= mem[data_addra_int + 17]; + doa_out[18] <= mem[data_addra_int + 18]; + doa_out[19] <= mem[data_addra_int + 19]; + doa_out[20] <= mem[data_addra_int + 20]; + doa_out[21] <= mem[data_addra_int + 21]; + doa_out[22] <= mem[data_addra_int + 22]; + doa_out[23] <= mem[data_addra_int + 23]; + doa_out[24] <= mem[data_addra_int + 24]; + doa_out[25] <= mem[data_addra_int + 25]; + doa_out[26] <= mem[data_addra_int + 26]; + doa_out[27] <= mem[data_addra_int + 27]; + doa_out[28] <= mem[data_addra_int + 28]; + doa_out[29] <= mem[data_addra_int + 29]; + doa_out[30] <= mem[data_addra_int + 30]; + doa_out[31] <= mem[data_addra_int + 31]; + dopa_out[0] <= mem[parity_addra_int + 0]; + dopa_out[1] <= mem[parity_addra_int + 1]; + dopa_out[2] <= mem[parity_addra_int + 2]; + dopa_out[3] <= mem[parity_addra_int + 3]; + end + end + else begin + doa_out[0] <= mem[data_addra_int + 0]; + doa_out[1] <= mem[data_addra_int + 1]; + doa_out[2] <= mem[data_addra_int + 2]; + doa_out[3] <= mem[data_addra_int + 3]; + doa_out[4] <= mem[data_addra_int + 4]; + doa_out[5] <= mem[data_addra_int + 5]; + doa_out[6] <= mem[data_addra_int + 6]; + doa_out[7] <= mem[data_addra_int + 7]; + doa_out[8] <= mem[data_addra_int + 8]; + doa_out[9] <= mem[data_addra_int + 9]; + doa_out[10] <= mem[data_addra_int + 10]; + doa_out[11] <= mem[data_addra_int + 11]; + doa_out[12] <= mem[data_addra_int + 12]; + doa_out[13] <= mem[data_addra_int + 13]; + doa_out[14] <= mem[data_addra_int + 14]; + doa_out[15] <= mem[data_addra_int + 15]; + doa_out[16] <= mem[data_addra_int + 16]; + doa_out[17] <= mem[data_addra_int + 17]; + doa_out[18] <= mem[data_addra_int + 18]; + doa_out[19] <= mem[data_addra_int + 19]; + doa_out[20] <= mem[data_addra_int + 20]; + doa_out[21] <= mem[data_addra_int + 21]; + doa_out[22] <= mem[data_addra_int + 22]; + doa_out[23] <= mem[data_addra_int + 23]; + doa_out[24] <= mem[data_addra_int + 24]; + doa_out[25] <= mem[data_addra_int + 25]; + doa_out[26] <= mem[data_addra_int + 26]; + doa_out[27] <= mem[data_addra_int + 27]; + doa_out[28] <= mem[data_addra_int + 28]; + doa_out[29] <= mem[data_addra_int + 29]; + doa_out[30] <= mem[data_addra_int + 30]; + doa_out[31] <= mem[data_addra_int + 31]; + dopa_out[0] <= mem[parity_addra_int + 0]; + dopa_out[1] <= mem[parity_addra_int + 1]; + dopa_out[2] <= mem[parity_addra_int + 2]; + dopa_out[3] <= mem[parity_addra_int + 3]; + end + end + end + end + + always @(posedge clka_int) begin + if (ena_int == 1'b1 && wea_int == 1'b1) begin + mem[data_addra_int + 0] <= dia_int[0]; + mem[data_addra_int + 1] <= dia_int[1]; + mem[data_addra_int + 2] <= dia_int[2]; + mem[data_addra_int + 3] <= dia_int[3]; + mem[data_addra_int + 4] <= dia_int[4]; + mem[data_addra_int + 5] <= dia_int[5]; + mem[data_addra_int + 6] <= dia_int[6]; + mem[data_addra_int + 7] <= dia_int[7]; + mem[data_addra_int + 8] <= dia_int[8]; + mem[data_addra_int + 9] <= dia_int[9]; + mem[data_addra_int + 10] <= dia_int[10]; + mem[data_addra_int + 11] <= dia_int[11]; + mem[data_addra_int + 12] <= dia_int[12]; + mem[data_addra_int + 13] <= dia_int[13]; + mem[data_addra_int + 14] <= dia_int[14]; + mem[data_addra_int + 15] <= dia_int[15]; + mem[data_addra_int + 16] <= dia_int[16]; + mem[data_addra_int + 17] <= dia_int[17]; + mem[data_addra_int + 18] <= dia_int[18]; + mem[data_addra_int + 19] <= dia_int[19]; + mem[data_addra_int + 20] <= dia_int[20]; + mem[data_addra_int + 21] <= dia_int[21]; + mem[data_addra_int + 22] <= dia_int[22]; + mem[data_addra_int + 23] <= dia_int[23]; + mem[data_addra_int + 24] <= dia_int[24]; + mem[data_addra_int + 25] <= dia_int[25]; + mem[data_addra_int + 26] <= dia_int[26]; + mem[data_addra_int + 27] <= dia_int[27]; + mem[data_addra_int + 28] <= dia_int[28]; + mem[data_addra_int + 29] <= dia_int[29]; + mem[data_addra_int + 30] <= dia_int[30]; + mem[data_addra_int + 31] <= dia_int[31]; + mem[parity_addra_int + 0] <= dipa_int[0]; + mem[parity_addra_int + 1] <= dipa_int[1]; + mem[parity_addra_int + 2] <= dipa_int[2]; + mem[parity_addra_int + 3] <= dipa_int[3]; + end + end + + // Port B + always @(posedge clkb_int) begin + if (enb_int == 1'b1) begin + if (ssrb_int == 1'b1) begin + dob_out[0] <= SRVAL_B[0]; + dob_out[1] <= SRVAL_B[1]; + dob_out[2] <= SRVAL_B[2]; + dob_out[3] <= SRVAL_B[3]; + dob_out[4] <= SRVAL_B[4]; + dob_out[5] <= SRVAL_B[5]; + dob_out[6] <= SRVAL_B[6]; + dob_out[7] <= SRVAL_B[7]; + dob_out[8] <= SRVAL_B[8]; + dob_out[9] <= SRVAL_B[9]; + dob_out[10] <= SRVAL_B[10]; + dob_out[11] <= SRVAL_B[11]; + dob_out[12] <= SRVAL_B[12]; + dob_out[13] <= SRVAL_B[13]; + dob_out[14] <= SRVAL_B[14]; + dob_out[15] <= SRVAL_B[15]; + dob_out[16] <= SRVAL_B[16]; + dob_out[17] <= SRVAL_B[17]; + dob_out[18] <= SRVAL_B[18]; + dob_out[19] <= SRVAL_B[19]; + dob_out[20] <= SRVAL_B[20]; + dob_out[21] <= SRVAL_B[21]; + dob_out[22] <= SRVAL_B[22]; + dob_out[23] <= SRVAL_B[23]; + dob_out[24] <= SRVAL_B[24]; + dob_out[25] <= SRVAL_B[25]; + dob_out[26] <= SRVAL_B[26]; + dob_out[27] <= SRVAL_B[27]; + dob_out[28] <= SRVAL_B[28]; + dob_out[29] <= SRVAL_B[29]; + dob_out[30] <= SRVAL_B[30]; + dob_out[31] <= SRVAL_B[31]; + dopb_out[0] <= SRVAL_B[32]; + dopb_out[1] <= SRVAL_B[33]; + dopb_out[2] <= SRVAL_B[34]; + dopb_out[3] <= SRVAL_B[35]; + end + else begin + if (web_int == 1'b1) begin + if (wr_mode_b == 2'b00) begin + dob_out <= dib_int; + dopb_out <= dipb_int; + end + else if (wr_mode_b == 2'b01) begin + dob_out[0] <= mem[data_addrb_int + 0]; + dob_out[1] <= mem[data_addrb_int + 1]; + dob_out[2] <= mem[data_addrb_int + 2]; + dob_out[3] <= mem[data_addrb_int + 3]; + dob_out[4] <= mem[data_addrb_int + 4]; + dob_out[5] <= mem[data_addrb_int + 5]; + dob_out[6] <= mem[data_addrb_int + 6]; + dob_out[7] <= mem[data_addrb_int + 7]; + dob_out[8] <= mem[data_addrb_int + 8]; + dob_out[9] <= mem[data_addrb_int + 9]; + dob_out[10] <= mem[data_addrb_int + 10]; + dob_out[11] <= mem[data_addrb_int + 11]; + dob_out[12] <= mem[data_addrb_int + 12]; + dob_out[13] <= mem[data_addrb_int + 13]; + dob_out[14] <= mem[data_addrb_int + 14]; + dob_out[15] <= mem[data_addrb_int + 15]; + dob_out[16] <= mem[data_addrb_int + 16]; + dob_out[17] <= mem[data_addrb_int + 17]; + dob_out[18] <= mem[data_addrb_int + 18]; + dob_out[19] <= mem[data_addrb_int + 19]; + dob_out[20] <= mem[data_addrb_int + 20]; + dob_out[21] <= mem[data_addrb_int + 21]; + dob_out[22] <= mem[data_addrb_int + 22]; + dob_out[23] <= mem[data_addrb_int + 23]; + dob_out[24] <= mem[data_addrb_int + 24]; + dob_out[25] <= mem[data_addrb_int + 25]; + dob_out[26] <= mem[data_addrb_int + 26]; + dob_out[27] <= mem[data_addrb_int + 27]; + dob_out[28] <= mem[data_addrb_int + 28]; + dob_out[29] <= mem[data_addrb_int + 29]; + dob_out[30] <= mem[data_addrb_int + 30]; + dob_out[31] <= mem[data_addrb_int + 31]; + dopb_out[0] <= mem[parity_addrb_int + 0]; + dopb_out[1] <= mem[parity_addrb_int + 1]; + dopb_out[2] <= mem[parity_addrb_int + 2]; + dopb_out[3] <= mem[parity_addrb_int + 3]; + end + end + else begin + dob_out[0] <= mem[data_addrb_int + 0]; + dob_out[1] <= mem[data_addrb_int + 1]; + dob_out[2] <= mem[data_addrb_int + 2]; + dob_out[3] <= mem[data_addrb_int + 3]; + dob_out[4] <= mem[data_addrb_int + 4]; + dob_out[5] <= mem[data_addrb_int + 5]; + dob_out[6] <= mem[data_addrb_int + 6]; + dob_out[7] <= mem[data_addrb_int + 7]; + dob_out[8] <= mem[data_addrb_int + 8]; + dob_out[9] <= mem[data_addrb_int + 9]; + dob_out[10] <= mem[data_addrb_int + 10]; + dob_out[11] <= mem[data_addrb_int + 11]; + dob_out[12] <= mem[data_addrb_int + 12]; + dob_out[13] <= mem[data_addrb_int + 13]; + dob_out[14] <= mem[data_addrb_int + 14]; + dob_out[15] <= mem[data_addrb_int + 15]; + dob_out[16] <= mem[data_addrb_int + 16]; + dob_out[17] <= mem[data_addrb_int + 17]; + dob_out[18] <= mem[data_addrb_int + 18]; + dob_out[19] <= mem[data_addrb_int + 19]; + dob_out[20] <= mem[data_addrb_int + 20]; + dob_out[21] <= mem[data_addrb_int + 21]; + dob_out[22] <= mem[data_addrb_int + 22]; + dob_out[23] <= mem[data_addrb_int + 23]; + dob_out[24] <= mem[data_addrb_int + 24]; + dob_out[25] <= mem[data_addrb_int + 25]; + dob_out[26] <= mem[data_addrb_int + 26]; + dob_out[27] <= mem[data_addrb_int + 27]; + dob_out[28] <= mem[data_addrb_int + 28]; + dob_out[29] <= mem[data_addrb_int + 29]; + dob_out[30] <= mem[data_addrb_int + 30]; + dob_out[31] <= mem[data_addrb_int + 31]; + dopb_out[0] <= mem[parity_addrb_int + 0]; + dopb_out[1] <= mem[parity_addrb_int + 1]; + dopb_out[2] <= mem[parity_addrb_int + 2]; + dopb_out[3] <= mem[parity_addrb_int + 3]; + end + end + end + end + + always @(posedge clkb_int) begin + if (enb_int == 1'b1 && web_int == 1'b1) begin + mem[data_addrb_int + 0] <= dib_int[0]; + mem[data_addrb_int + 1] <= dib_int[1]; + mem[data_addrb_int + 2] <= dib_int[2]; + mem[data_addrb_int + 3] <= dib_int[3]; + mem[data_addrb_int + 4] <= dib_int[4]; + mem[data_addrb_int + 5] <= dib_int[5]; + mem[data_addrb_int + 6] <= dib_int[6]; + mem[data_addrb_int + 7] <= dib_int[7]; + mem[data_addrb_int + 8] <= dib_int[8]; + mem[data_addrb_int + 9] <= dib_int[9]; + mem[data_addrb_int + 10] <= dib_int[10]; + mem[data_addrb_int + 11] <= dib_int[11]; + mem[data_addrb_int + 12] <= dib_int[12]; + mem[data_addrb_int + 13] <= dib_int[13]; + mem[data_addrb_int + 14] <= dib_int[14]; + mem[data_addrb_int + 15] <= dib_int[15]; + mem[data_addrb_int + 16] <= dib_int[16]; + mem[data_addrb_int + 17] <= dib_int[17]; + mem[data_addrb_int + 18] <= dib_int[18]; + mem[data_addrb_int + 19] <= dib_int[19]; + mem[data_addrb_int + 20] <= dib_int[20]; + mem[data_addrb_int + 21] <= dib_int[21]; + mem[data_addrb_int + 22] <= dib_int[22]; + mem[data_addrb_int + 23] <= dib_int[23]; + mem[data_addrb_int + 24] <= dib_int[24]; + mem[data_addrb_int + 25] <= dib_int[25]; + mem[data_addrb_int + 26] <= dib_int[26]; + mem[data_addrb_int + 27] <= dib_int[27]; + mem[data_addrb_int + 28] <= dib_int[28]; + mem[data_addrb_int + 29] <= dib_int[29]; + mem[data_addrb_int + 30] <= dib_int[30]; + mem[data_addrb_int + 31] <= dib_int[31]; + mem[parity_addrb_int + 0] <= dipb_int[0]; + mem[parity_addrb_int + 1] <= dipb_int[1]; + mem[parity_addrb_int + 2] <= dipb_int[2]; + mem[parity_addrb_int + 3] <= dipb_int[3]; + end + end + + specify + (CLKA *> DOA) = (100, 100); + (CLKA *> DOPA) = (100, 100); + (CLKB *> DOB) = (100, 100); + (CLKB *> DOPB) = (100, 100); + endspecify + +endmodule + +`else + +// $Header: /devl/xcs/repo/env/Databases/CAEInterfaces/verunilibs/data/unisims/RAMB16_S36_S36.v,v 1.9 2005/03/14 22:54:41 wloo Exp $ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 1995/2005 Xilinx, Inc. +// All Right Reserved. +/////////////////////////////////////////////////////////////////////////////// +// ____ ____ +// / /\/ / +// /___/ \ / Vendor : Xilinx +// \ \ \/ Version : 8.1i (I.13) +// \ \ Description : Xilinx Timing Simulation Library Component +// / / 16K-Bit Data and 2K-Bit Parity Dual Port Block RAM +// /___/ /\ Filename : RAMB16_S36_S36.v +// \ \ / \ Timestamp : Thu Mar 10 16:44:01 PST 2005 +// \___\/\___\ +// +// Revision: +// 03/23/04 - Initial version. +// 03/10/05 - Initialized outputs. +// End Revision + +`timescale 1 ps/1 ps + +module RAMB16_S36_S36 (DOA, DOB, DOPA, DOPB, ADDRA, ADDRB, CLKA, CLKB, DIA, DIB, DIPA, DIPB, ENA, ENB, SSRA, SSRB, WEA, WEB); + + parameter INIT_A = 36'h0; + parameter INIT_B = 36'h0; + parameter SRVAL_A = 36'h0; + parameter SRVAL_B = 36'h0; + parameter WRITE_MODE_A = "WRITE_FIRST"; + parameter WRITE_MODE_B = "WRITE_FIRST"; + parameter SIM_COLLISION_CHECK = "ALL"; + localparam SETUP_ALL = 1000; + localparam SETUP_READ_FIRST = 3000; + + parameter INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_10 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_11 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_12 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_13 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_14 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_15 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_16 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_17 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_18 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_19 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1A = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1B = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1C = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1D = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1E = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_20 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_21 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_22 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_23 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_24 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_25 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_26 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_27 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_28 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_29 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2A = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2B = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2C = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2D = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2E = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_30 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_31 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_32 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_33 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_34 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_35 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_36 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_37 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_38 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_39 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3A = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3B = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3C = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3D = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3E = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + + output [31:0] DOA; + output [3:0] DOPA; + output [31:0] DOB; + output [3:0] DOPB; + + input [8:0] ADDRA; + input [31:0] DIA; + input [3:0] DIPA; + input ENA, CLKA, WEA, SSRA; + input [8:0] ADDRB; + input [31:0] DIB; + input [3:0] DIPB; + input ENB, CLKB, WEB, SSRB; + + reg [31:0] doa_out = INIT_A[31:0]; + reg [3:0] dopa_out = INIT_A[35:32]; + reg [31:0] dob_out = INIT_B[31:0]; + reg [3:0] dopb_out = INIT_B[35:32]; + + reg [31:0] mem [511:0]; + reg [3:0] memp [511:0]; + + reg [8:0] count, countp; + reg [1:0] wr_mode_a, wr_mode_b; + + reg [5:0] dmi, dbi; + reg [5:0] pmi, pbi; + + wire [8:0] addra_int; + reg [8:0] addra_reg; + wire [31:0] dia_int; + wire [3:0] dipa_int; + wire ena_int, clka_int, wea_int, ssra_int; + reg ena_reg, wea_reg, ssra_reg; + wire [8:0] addrb_int; + reg [8:0] addrb_reg; + wire [31:0] dib_int; + wire [3:0] dipb_int; + wire enb_int, clkb_int, web_int, ssrb_int; + reg display_flag, output_flag; + reg enb_reg, web_reg, ssrb_reg; + + time time_clka, time_clkb; + time time_clka_clkb; + time time_clkb_clka; + + reg setup_all_a_b; + reg setup_all_b_a; + reg setup_zero; + reg setup_rf_a_b; + reg setup_rf_b_a; + reg [1:0] data_collision, data_collision_a_b, data_collision_b_a; + reg memory_collision, memory_collision_a_b, memory_collision_b_a; + reg change_clka; + reg change_clkb; + + wire [14:0] data_addra_int; + wire [14:0] data_addra_reg; + wire [14:0] data_addrb_int; + wire [14:0] data_addrb_reg; + + wire dia_enable = ena_int && wea_int; + wire dib_enable = enb_int && web_int; + + tri0 GSR = glbl.GSR; + wire gsr_int; + + buf b_gsr (gsr_int, GSR); + + buf b_doa [31:0] (DOA, doa_out); + buf b_dopa [3:0] (DOPA, dopa_out); + buf b_addra [8:0] (addra_int, ADDRA); + buf b_dia [31:0] (dia_int, DIA); + buf b_dipa [3:0] (dipa_int, DIPA); + buf b_ena (ena_int, ENA); + buf b_clka (clka_int, CLKA); + buf b_ssra (ssra_int, SSRA); + buf b_wea (wea_int, WEA); + + buf b_dob [31:0] (DOB, dob_out); + buf b_dopb [3:0] (DOPB, dopb_out); + buf b_addrb [8:0] (addrb_int, ADDRB); + buf b_dib [31:0] (dib_int, DIB); + buf b_dipb [3:0] (dipb_int, DIPB); + buf b_enb (enb_int, ENB); + buf b_clkb (clkb_int, CLKB); + buf b_ssrb (ssrb_int, SSRB); + buf b_web (web_int, WEB); + + + always @(gsr_int) + if (gsr_int) begin + assign {dopa_out, doa_out} = INIT_A; + assign {dopb_out, dob_out} = INIT_B; + end + else begin + deassign doa_out; + deassign dopa_out; + deassign dob_out; + deassign dopb_out; + end + + initial begin : initialize_mems + +`ifdef UNDEFINED + for (count = 0; count < 8; count = count + 1) begin + mem[count] = INIT_00[(count * 32) +: 32]; + mem[8 * 1 + count] = INIT_01[(count * 32) +: 32]; + mem[8 * 2 + count] = INIT_02[(count * 32) +: 32]; + mem[8 * 3 + count] = INIT_03[(count * 32) +: 32]; + mem[8 * 4 + count] = INIT_04[(count * 32) +: 32]; + mem[8 * 5 + count] = INIT_05[(count * 32) +: 32]; + mem[8 * 6 + count] = INIT_06[(count * 32) +: 32]; + mem[8 * 7 + count] = INIT_07[(count * 32) +: 32]; + mem[8 * 8 + count] = INIT_08[(count * 32) +: 32]; + mem[8 * 9 + count] = INIT_09[(count * 32) +: 32]; + mem[8 * 10 + count] = INIT_0A[(count * 32) +: 32]; + mem[8 * 11 + count] = INIT_0B[(count * 32) +: 32]; + mem[8 * 12 + count] = INIT_0C[(count * 32) +: 32]; + mem[8 * 13 + count] = INIT_0D[(count * 32) +: 32]; + mem[8 * 14 + count] = INIT_0E[(count * 32) +: 32]; + mem[8 * 15 + count] = INIT_0F[(count * 32) +: 32]; + mem[8 * 16 + count] = INIT_10[(count * 32) +: 32]; + mem[8 * 17 + count] = INIT_11[(count * 32) +: 32]; + mem[8 * 18 + count] = INIT_12[(count * 32) +: 32]; + mem[8 * 19 + count] = INIT_13[(count * 32) +: 32]; + mem[8 * 20 + count] = INIT_14[(count * 32) +: 32]; + mem[8 * 21 + count] = INIT_15[(count * 32) +: 32]; + mem[8 * 22 + count] = INIT_16[(count * 32) +: 32]; + mem[8 * 23 + count] = INIT_17[(count * 32) +: 32]; + mem[8 * 24 + count] = INIT_18[(count * 32) +: 32]; + mem[8 * 25 + count] = INIT_19[(count * 32) +: 32]; + mem[8 * 26 + count] = INIT_1A[(count * 32) +: 32]; + mem[8 * 27 + count] = INIT_1B[(count * 32) +: 32]; + mem[8 * 28 + count] = INIT_1C[(count * 32) +: 32]; + mem[8 * 29 + count] = INIT_1D[(count * 32) +: 32]; + mem[8 * 30 + count] = INIT_1E[(count * 32) +: 32]; + mem[8 * 31 + count] = INIT_1F[(count * 32) +: 32]; + mem[8 * 32 + count] = INIT_20[(count * 32) +: 32]; + mem[8 * 33 + count] = INIT_21[(count * 32) +: 32]; + mem[8 * 34 + count] = INIT_22[(count * 32) +: 32]; + mem[8 * 35 + count] = INIT_23[(count * 32) +: 32]; + mem[8 * 36 + count] = INIT_24[(count * 32) +: 32]; + mem[8 * 37 + count] = INIT_25[(count * 32) +: 32]; + mem[8 * 38 + count] = INIT_26[(count * 32) +: 32]; + mem[8 * 39 + count] = INIT_27[(count * 32) +: 32]; + mem[8 * 40 + count] = INIT_28[(count * 32) +: 32]; + mem[8 * 41 + count] = INIT_29[(count * 32) +: 32]; + mem[8 * 42 + count] = INIT_2A[(count * 32) +: 32]; + mem[8 * 43 + count] = INIT_2B[(count * 32) +: 32]; + mem[8 * 44 + count] = INIT_2C[(count * 32) +: 32]; + mem[8 * 45 + count] = INIT_2D[(count * 32) +: 32]; + mem[8 * 46 + count] = INIT_2E[(count * 32) +: 32]; + mem[8 * 47 + count] = INIT_2F[(count * 32) +: 32]; + mem[8 * 48 + count] = INIT_30[(count * 32) +: 32]; + mem[8 * 49 + count] = INIT_31[(count * 32) +: 32]; + mem[8 * 50 + count] = INIT_32[(count * 32) +: 32]; + mem[8 * 51 + count] = INIT_33[(count * 32) +: 32]; + mem[8 * 52 + count] = INIT_34[(count * 32) +: 32]; + mem[8 * 53 + count] = INIT_35[(count * 32) +: 32]; + mem[8 * 54 + count] = INIT_36[(count * 32) +: 32]; + mem[8 * 55 + count] = INIT_37[(count * 32) +: 32]; + mem[8 * 56 + count] = INIT_38[(count * 32) +: 32]; + mem[8 * 57 + count] = INIT_39[(count * 32) +: 32]; + mem[8 * 58 + count] = INIT_3A[(count * 32) +: 32]; + mem[8 * 59 + count] = INIT_3B[(count * 32) +: 32]; + mem[8 * 60 + count] = INIT_3C[(count * 32) +: 32]; + mem[8 * 61 + count] = INIT_3D[(count * 32) +: 32]; + mem[8 * 62 + count] = INIT_3E[(count * 32) +: 32]; + mem[8 * 63 + count] = INIT_3F[(count * 32) +: 32]; + end +`else + integer i; + for (i = 0; i < 512; i = i + 1) + begin + mem[i] = 0; + memp[i] = 0; + end + +`endif + +// initiate parity start +`ifdef UNDEFINED + for (countp = 0; countp < 64; countp = countp + 1) begin + memp[countp] = INITP_00[(countp * 4) +: 4]; + memp[64 * 1 + countp] = INITP_01[(countp * 4) +: 4]; + memp[64 * 2 + countp] = INITP_02[(countp * 4) +: 4]; + memp[64 * 3 + countp] = INITP_03[(countp * 4) +: 4]; + memp[64 * 4 + countp] = INITP_04[(countp * 4) +: 4]; + memp[64 * 5 + countp] = INITP_05[(countp * 4) +: 4]; + memp[64 * 6 + countp] = INITP_06[(countp * 4) +: 4]; + memp[64 * 7 + countp] = INITP_07[(countp * 4) +: 4]; + end +`endif +// initiate parity end + + change_clka <= 0; + change_clkb <= 0; + data_collision <= 0; + data_collision_a_b <= 0; + data_collision_b_a <= 0; + memory_collision <= 0; + memory_collision_a_b <= 0; + memory_collision_b_a <= 0; + setup_all_a_b <= 0; + setup_all_b_a <= 0; + setup_zero <= 0; + setup_rf_a_b <= 0; + setup_rf_b_a <= 0; + end + + assign data_addra_int = addra_int * 32; + assign data_addra_reg = addra_reg * 32; + assign data_addrb_int = addrb_int * 32; + assign data_addrb_reg = addrb_reg * 32; + + + initial begin + + display_flag = 1; + output_flag = 1; + + case (SIM_COLLISION_CHECK) + + "NONE" : begin + output_flag = 0; + display_flag = 0; + end + "WARNING_ONLY" : output_flag = 0; + "GENERATE_ONLY" : display_flag = 0; + "ALL" : ; + + default : begin + $display("Attribute Syntax Error : The Attribute SIM_COLLISION_CHECK on RAMB16_S36_S36 instance %m is set to %s. Legal values for this attribute are ALL, NONE, WARNING_ONLY or GENERATE_ONLY.", SIM_COLLISION_CHECK); + $finish; + end + + endcase // case(SIM_COLLISION_CHECK) + + end // initial begin + + + always @(posedge clka_int) begin + if ((output_flag || display_flag)) begin + time_clka = $time; + #0 time_clkb_clka = time_clka - time_clkb; + change_clka = ~change_clka; + end + end + + always @(posedge clkb_int) begin + if ((output_flag || display_flag)) begin + time_clkb = $time; + #0 time_clka_clkb = time_clkb - time_clka; + change_clkb = ~change_clkb; + end + end + + always @(change_clkb) begin + if ((0 < time_clka_clkb) && (time_clka_clkb < SETUP_ALL)) + setup_all_a_b = 1; + if ((0 < time_clka_clkb) && (time_clka_clkb < SETUP_READ_FIRST)) + setup_rf_a_b = 1; + end + + always @(change_clka) begin + if ((0 < time_clkb_clka) && (time_clkb_clka < SETUP_ALL)) + setup_all_b_a = 1; + if ((0 < time_clkb_clka) && (time_clkb_clka < SETUP_READ_FIRST)) + setup_rf_b_a = 1; + end + + always @(change_clkb or change_clka) begin + if ((time_clkb_clka == 0) && (time_clka_clkb == 0)) + setup_zero = 1; + end + + always @(posedge setup_zero) begin + if ((ena_int == 1) && (wea_int == 1) && + (enb_int == 1) && (web_int == 1) && + (data_addra_int[14:5] == data_addrb_int[14:5])) + memory_collision <= 1; + end + + always @(posedge setup_all_a_b or posedge setup_rf_a_b) begin + if ((ena_reg == 1) && (wea_reg == 1) && + (enb_int == 1) && (web_int == 1) && + (data_addra_reg[14:5] == data_addrb_int[14:5])) + memory_collision_a_b <= 1; + end + + always @(posedge setup_all_b_a or posedge setup_rf_b_a) begin + if ((ena_int == 1) && (wea_int == 1) && + (enb_reg == 1) && (web_reg == 1) && + (data_addra_int[14:5] == data_addrb_reg[14:5])) + memory_collision_b_a <= 1; + end + + always @(posedge setup_all_a_b) begin + if (data_addra_reg[14:5] == data_addrb_int[14:5]) begin + if ((ena_reg == 1) && (enb_int == 1)) begin + case ({wr_mode_a, wr_mode_b, wea_reg, web_int}) + 6'b000011 : begin data_collision_a_b <= 2'b11; display_wa_wb; end + 6'b000111 : begin data_collision_a_b <= 2'b11; display_wa_wb; end + 6'b001011 : begin data_collision_a_b <= 2'b10; display_wa_wb; end +// 6'b010011 : begin data_collision_a_b <= 2'b00; display_wa_wb; end +// 6'b010111 : begin data_collision_a_b <= 2'b00; display_wa_wb; end +// 6'b011011 : begin data_collision_a_b <= 2'b00; display_wa_wb; end + 6'b100011 : begin data_collision_a_b <= 2'b01; display_wa_wb; end + 6'b100111 : begin data_collision_a_b <= 2'b01; display_wa_wb; end + 6'b101011 : begin display_wa_wb; end + 6'b000001 : begin data_collision_a_b <= 2'b10; display_ra_wb; end +// 6'b000101 : begin data_collision_a_b <= 2'b00; display_ra_wb; end + 6'b001001 : begin data_collision_a_b <= 2'b10; display_ra_wb; end + 6'b010001 : begin data_collision_a_b <= 2'b10; display_ra_wb; end +// 6'b010101 : begin data_collision_a_b <= 2'b00; display_ra_wb; end + 6'b011001 : begin data_collision_a_b <= 2'b10; display_ra_wb; end + 6'b100001 : begin data_collision_a_b <= 2'b10; display_ra_wb; end +// 6'b100101 : begin data_collision_a_b <= 2'b00; display_ra_wb; end + 6'b101001 : begin data_collision_a_b <= 2'b10; display_ra_wb; end + 6'b000010 : begin data_collision_a_b <= 2'b01; display_wa_rb; end + 6'b000110 : begin data_collision_a_b <= 2'b01; display_wa_rb; end + 6'b001010 : begin data_collision_a_b <= 2'b01; display_wa_rb; end +// 6'b010010 : begin data_collision_a_b <= 2'b00; display_wa_rb; end +// 6'b010110 : begin data_collision_a_b <= 2'b00; display_wa_rb; end +// 6'b011010 : begin data_collision_a_b <= 2'b00; display_wa_rb; end + 6'b100010 : begin data_collision_a_b <= 2'b01; display_wa_rb; end + 6'b100110 : begin data_collision_a_b <= 2'b01; display_wa_rb; end + 6'b101010 : begin data_collision_a_b <= 2'b01; display_wa_rb; end + endcase + end + end + setup_all_a_b <= 0; + end + + + always @(posedge setup_all_b_a) begin + if (data_addra_int[14:5] == data_addrb_reg[14:5]) begin + if ((ena_int == 1) && (enb_reg == 1)) begin + case ({wr_mode_a, wr_mode_b, wea_int, web_reg}) + 6'b000011 : begin data_collision_b_a <= 2'b11; display_wa_wb; end +// 6'b000111 : begin data_collision_b_a <= 2'b00; display_wa_wb; end + 6'b001011 : begin data_collision_b_a <= 2'b10; display_wa_wb; end + 6'b010011 : begin data_collision_b_a <= 2'b11; display_wa_wb; end +// 6'b010111 : begin data_collision_b_a <= 2'b00; display_wa_wb; end + 6'b011011 : begin data_collision_b_a <= 2'b10; display_wa_wb; end + 6'b100011 : begin data_collision_b_a <= 2'b01; display_wa_wb; end + 6'b100111 : begin data_collision_b_a <= 2'b01; display_wa_wb; end + 6'b101011 : begin display_wa_wb; end + 6'b000001 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b000101 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b001001 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b010001 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b010101 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b011001 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b100001 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b100101 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b101001 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b000010 : begin data_collision_b_a <= 2'b01; display_wa_rb; end + 6'b000110 : begin data_collision_b_a <= 2'b01; display_wa_rb; end + 6'b001010 : begin data_collision_b_a <= 2'b01; display_wa_rb; end +// 6'b010010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b010110 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b011010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end + 6'b100010 : begin data_collision_b_a <= 2'b01; display_wa_rb; end + 6'b100110 : begin data_collision_b_a <= 2'b01; display_wa_rb; end + 6'b101010 : begin data_collision_b_a <= 2'b01; display_wa_rb; end + endcase + end + end + setup_all_b_a <= 0; + end + + + always @(posedge setup_zero) begin + if (data_addra_int[14:5] == data_addrb_int[14:5]) begin + if ((ena_int == 1) && (enb_int == 1)) begin + case ({wr_mode_a, wr_mode_b, wea_int, web_int}) + 6'b000011 : begin data_collision <= 2'b11; display_wa_wb; end + 6'b000111 : begin data_collision <= 2'b11; display_wa_wb; end + 6'b001011 : begin data_collision <= 2'b10; display_wa_wb; end + 6'b010011 : begin data_collision <= 2'b11; display_wa_wb; end + 6'b010111 : begin data_collision <= 2'b11; display_wa_wb; end + 6'b011011 : begin data_collision <= 2'b10; display_wa_wb; end + 6'b100011 : begin data_collision <= 2'b01; display_wa_wb; end + 6'b100111 : begin data_collision <= 2'b01; display_wa_wb; end + 6'b101011 : begin display_wa_wb; end + 6'b000001 : begin data_collision <= 2'b10; display_ra_wb; end +// 6'b000101 : begin data_collision <= 2'b00; display_ra_wb; end + 6'b001001 : begin data_collision <= 2'b10; display_ra_wb; end + 6'b010001 : begin data_collision <= 2'b10; display_ra_wb; end +// 6'b010101 : begin data_collision <= 2'b00; display_ra_wb; end + 6'b011001 : begin data_collision <= 2'b10; display_ra_wb; end + 6'b100001 : begin data_collision <= 2'b10; display_ra_wb; end +// 6'b100101 : begin data_collision <= 2'b00; display_ra_wb; end + 6'b101001 : begin data_collision <= 2'b10; display_ra_wb; end + 6'b000010 : begin data_collision <= 2'b01; display_wa_rb; end + 6'b000110 : begin data_collision <= 2'b01; display_wa_rb; end + 6'b001010 : begin data_collision <= 2'b01; display_wa_rb; end +// 6'b010010 : begin data_collision <= 2'b00; display_wa_rb; end +// 6'b010110 : begin data_collision <= 2'b00; display_wa_rb; end +// 6'b011010 : begin data_collision <= 2'b00; display_wa_rb; end + 6'b100010 : begin data_collision <= 2'b01; display_wa_rb; end + 6'b100110 : begin data_collision <= 2'b01; display_wa_rb; end + 6'b101010 : begin data_collision <= 2'b01; display_wa_rb; end + endcase + end + end + setup_zero <= 0; + end + + task display_ra_wb; + begin + if (display_flag) + $display("Memory Collision Error on RAMB16_S36_S36:%m at simulation time %.3f ns\nA read was performed on address %h (hex) of Port A while a write was requested to the same address on Port B. The write will be successful however the read value on Port A is unknown until the next CLKA cycle.", $time/1000.0, addra_int); + end + endtask + + task display_wa_rb; + begin + if (display_flag) + $display("Memory Collision Error on RAMB16_S36_S36:%m at simulation time %.3f ns\nA read was performed on address %h (hex) of Port B while a write was requested to the same address on Port A. The write will be successful however the read value on Port B is unknown until the next CLKB cycle.", $time/1000.0, addrb_int); + end + endtask + + task display_wa_wb; + begin + if (display_flag) + $display("Memory Collision Error on RAMB16_S36_S36:%m at simulation time %.3f ns\nA write was requested to the same address simultaneously at both Port A and Port B of the RAM. The contents written to the RAM at address location %h (hex) of Port A and address location %h (hex) of Port B are unknown.", $time/1000.0, addra_int, addrb_int); + end + endtask + + + always @(posedge setup_rf_a_b) begin + if (data_addra_reg[14:5] == data_addrb_int[14:5]) begin + if ((ena_reg == 1) && (enb_int == 1)) begin + case ({wr_mode_a, wr_mode_b, wea_reg, web_int}) +// 6'b000011 : begin data_collision_a_b <= 2'b00; display_wa_wb; end +// 6'b000111 : begin data_collision_a_b <= 2'b00; display_wa_wb; end +// 6'b001011 : begin data_collision_a_b <= 2'b00; display_wa_wb; end + 6'b010011 : begin data_collision_a_b <= 2'b11; display_wa_wb; end + 6'b010111 : begin data_collision_a_b <= 2'b11; display_wa_wb; end + 6'b011011 : begin data_collision_a_b <= 2'b10; display_wa_wb; end +// 6'b100011 : begin data_collision_a_b <= 2'b00; display_wa_wb; end +// 6'b100111 : begin data_collision_a_b <= 2'b00; display_wa_wb; end +// 6'b101011 : begin data_collision_a_b <= 2'b00; display_wa_wb; end +// 6'b000001 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b000101 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b001001 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b010001 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b010101 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b011001 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b100001 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b100101 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b101001 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b000010 : begin data_collision_a_b <= 2'b00; display_wa_rb; end +// 6'b000110 : begin data_collision_a_b <= 2'b00; display_wa_rb; end +// 6'b001010 : begin data_collision_a_b <= 2'b00; display_wa_rb; end + 6'b010010 : begin data_collision_a_b <= 2'b01; display_wa_rb; end + 6'b010110 : begin data_collision_a_b <= 2'b01; display_wa_rb; end + 6'b011010 : begin data_collision_a_b <= 2'b01; display_wa_rb; end +// 6'b100010 : begin data_collision_a_b <= 2'b00; display_wa_rb; end +// 6'b100110 : begin data_collision_a_b <= 2'b00; display_wa_rb; end +// 6'b101010 : begin data_collision_a_b <= 2'b00; display_wa_rb; end + endcase + end + end + setup_rf_a_b <= 0; + end + + + always @(posedge setup_rf_b_a) begin + if (data_addra_int[14:5] == data_addrb_reg[14:5]) begin + if ((ena_int == 1) && (enb_reg == 1)) begin + case ({wr_mode_a, wr_mode_b, wea_int, web_reg}) +// 6'b000011 : begin data_collision_b_a <= 2'b00; display_wa_wb; end + 6'b000111 : begin data_collision_b_a <= 2'b11; display_wa_wb; end +// 6'b001011 : begin data_collision_b_a <= 2'b00; display_wa_wb; end +// 6'b010011 : begin data_collision_b_a <= 2'b00; display_wa_wb; end + 6'b010111 : begin data_collision_b_a <= 2'b11; display_wa_wb; end +// 6'b011011 : begin data_collision_b_a <= 2'b00; display_wa_wb; end +// 6'b100011 : begin data_collision_b_a <= 2'b00; display_wa_wb; end + 6'b100111 : begin data_collision_b_a <= 2'b01; display_wa_wb; end +// 6'b101011 : begin data_collision_b_a <= 2'b00; display_wa_wb; end +// 6'b000001 : begin data_collision_b_a <= 2'b00; display_ra_wb; end + 6'b000101 : begin data_collision_b_a <= 2'b10; display_ra_wb; end +// 6'b001001 : begin data_collision_b_a <= 2'b00; display_ra_wb; end +// 6'b010001 : begin data_collision_b_a <= 2'b00; display_ra_wb; end + 6'b010101 : begin data_collision_b_a <= 2'b10; display_ra_wb; end +// 6'b011001 : begin data_collision_b_a <= 2'b00; display_ra_wb; end +// 6'b100001 : begin data_collision_b_a <= 2'b00; display_ra_wb; end + 6'b100101 : begin data_collision_b_a <= 2'b10; display_ra_wb; end +// 6'b101001 : begin data_collision_b_a <= 2'b00; display_ra_wb; end +// 6'b000010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b000110 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b001010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b010010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b010110 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b011010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b100010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b100110 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b101010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end + endcase + end + end + setup_rf_b_a <= 0; + end + + + always @(posedge clka_int) begin + if ((output_flag || display_flag)) begin + addra_reg <= addra_int; + ena_reg <= ena_int; + ssra_reg <= ssra_int; + wea_reg <= wea_int; + end + end + + always @(posedge clkb_int) begin + if ((output_flag || display_flag)) begin + addrb_reg <= addrb_int; + enb_reg <= enb_int; + ssrb_reg <= ssrb_int; + web_reg <= web_int; + end + end + + + // Data + always @(posedge memory_collision) begin + if ((output_flag || display_flag)) begin + mem[addra_int] <= 32'bx; + memory_collision <= 0; + end + + end + + always @(posedge memory_collision_a_b) begin + if ((output_flag || display_flag)) begin + mem[addra_reg] <= 32'bx; + memory_collision_a_b <= 0; + end + end + + always @(posedge memory_collision_b_a) begin + if ((output_flag || display_flag)) begin + mem[addra_int] <= 32'bx; + memory_collision_b_a <= 0; + end + end + + always @(posedge data_collision[1]) begin + if (ssra_int == 0 && output_flag) begin + doa_out <= #100 32'bX; + end + data_collision[1] <= 0; + end + + always @(posedge data_collision[0]) begin + if (ssrb_int == 0 && output_flag) begin + dob_out <= #100 32'bX; + end + data_collision[0] <= 0; + end + + always @(posedge data_collision_a_b[1]) begin + if (ssra_reg == 0 && output_flag) begin + doa_out <= #100 32'bX; + end + data_collision_a_b[1] <= 0; + end + + always @(posedge data_collision_a_b[0]) begin + if (ssrb_int == 0 && output_flag) begin + dob_out <= #100 32'bX; + end + data_collision_a_b[0] <= 0; + end + + always @(posedge data_collision_b_a[1]) begin + if (ssra_int == 0 && output_flag) begin + doa_out <= #100 32'bX; + end + data_collision_b_a[1] <= 0; + end + + always @(posedge data_collision_b_a[0]) begin + if (ssrb_reg == 0 && output_flag) begin + dob_out <= #100 32'bX; + end + data_collision_b_a[0] <= 0; + end + +// x parity start + always @(posedge memory_collision) begin + if ((output_flag || display_flag)) + memp[addra_int] <= 4'bx; + end + + always @(posedge memory_collision_a_b) begin + if ((output_flag || display_flag)) + memp[addra_reg] <= 4'bx; + end + + always @(posedge memory_collision_b_a) begin + if ((output_flag || display_flag)) + memp[addra_int] <= 4'bx; + end + + always @(posedge data_collision[1]) begin + if (ssra_int == 0 && output_flag) begin + dopa_out <= #100 4'bX; + end + end + + always @(posedge data_collision_a_b[1]) begin + if (ssra_reg == 0 && output_flag) begin + dopa_out <= #100 4'bX; + end + end + + + always @(posedge data_collision_b_a[1]) begin + if (ssra_int == 0 && output_flag) begin + dopa_out <= #100 4'bX; + end + end + + always @(posedge data_collision[0]) begin + if (ssrb_int == 0 && output_flag) begin + dopb_out <= #100 4'bx; + end + end + + always @(posedge data_collision_a_b[0]) begin + if (ssrb_int == 0 && output_flag) begin + dopb_out <= #100 4'bx; + end + end + + always @(posedge data_collision_b_a[0]) begin + if (ssrb_reg == 0 && output_flag) begin + dopb_out <= #100 4'bx; + end + end +// x parity end + + initial begin + case (WRITE_MODE_A) + "WRITE_FIRST" : wr_mode_a <= 2'b00; + "READ_FIRST" : wr_mode_a <= 2'b01; + "NO_CHANGE" : wr_mode_a <= 2'b10; + default : begin + $display("Attribute Syntax Error : The Attribute WRITE_MODE_A on RAMB16_S36_S36 instance %m is set to %s. Legal values for this attribute are WRITE_FIRST, READ_FIRST or NO_CHANGE.", WRITE_MODE_A); + $finish; + end + endcase + end + + initial begin + case (WRITE_MODE_B) + "WRITE_FIRST" : wr_mode_b <= 2'b00; + "READ_FIRST" : wr_mode_b <= 2'b01; + "NO_CHANGE" : wr_mode_b <= 2'b10; + default : begin + $display("Attribute Syntax Error : The Attribute WRITE_MODE_B on RAMB16_S36_S36 instance %m is set to %s. Legal values for this attribute are WRITE_FIRST, READ_FIRST or NO_CHANGE.", WRITE_MODE_B); + $finish; + end + endcase + end + + + // Port A + always @(posedge clka_int) begin + + if (ena_int == 1'b1) begin + + if (ssra_int == 1'b1) begin + {dopa_out, doa_out} <= #100 SRVAL_A; + end + else begin + if (wea_int == 1'b1) begin + if (wr_mode_a == 2'b00) begin + doa_out <= #100 dia_int; + dopa_out <= #100 dipa_int; + end + else if (wr_mode_a == 2'b01) begin + + doa_out <= #100 mem[addra_int]; + dopa_out <= #100 memp[addra_int]; + + end + end + else begin + + doa_out <= #100 mem[addra_int]; + dopa_out <= #100 memp[addra_int]; + + end + end + + // memory + if (wea_int == 1'b1) begin + mem[addra_int] <= dia_int; + memp[addra_int] <= dipa_int; + end + + end + end + + + // Port B + always @(posedge clkb_int) begin + + if (enb_int == 1'b1) begin + + if (ssrb_int == 1'b1) begin + {dopb_out, dob_out} <= #100 SRVAL_B; + end + else begin + if (web_int == 1'b1) begin + if (wr_mode_b == 2'b00) begin + dob_out <= #100 dib_int; + dopb_out <= #100 dipb_int; + end + else if (wr_mode_b == 2'b01) begin + dob_out <= #100 mem[addrb_int]; + dopb_out <= #100 memp[addrb_int]; + end + end + else begin + dob_out <= #100 mem[addrb_int]; + dopb_out <= #100 memp[addrb_int]; + end + end + + // memory + if (web_int == 1'b1) begin + mem[addrb_int] <= dib_int; + memp[addrb_int] <= dipb_int; + end + + end + end + + +endmodule + +`endif diff --git a/eth/rtl/verilog/elastic_buffer.v b/eth/rtl/verilog/elastic_buffer.v new file mode 100644 index 000000000..56c821b7e --- /dev/null +++ b/eth/rtl/verilog/elastic_buffer.v @@ -0,0 +1,93 @@ + + +module elastic_buffer + ( input rx_clk, + input tx_clk, + input rst, + + input [7:0] rxd, + input rx_dv, + input rx_er, + input crs, + input col, + + output [7:0] rxd_ret, + output rx_dv_ret, + output rx_er_ret, + output crs_ret, + output col_ret ); + + reg [3:0] addr_wr,addr_wr_gray,awg_d1,awg_d2,addr_wr_gray_ret,awgr_d1,addr_wr_ungray,addr_rd; + + reg [11:0] buffer [0:15]; + integer i; + initial + for(i=0;i<16;i=i+1) + buffer[i] <= 0; + + reg [7:0] rxd_d1, rxd_d2; + reg rx_dv_d1,rx_er_d1,crs_d1,col_d1, rx_dv_d2,rx_er_d2,crs_d2,col_d2; + wire rx_dv_ret_adv; + reg rx_dv_ontime; + + always @(posedge rx_clk) + {col_d1,crs_d1,rx_er_d1,rx_dv_d1,rxd_d1} <= {col,crs,rx_er,rx_dv,rxd}; + + always @(posedge rx_clk) + {col_d2,crs_d2,rx_er_d2,rx_dv_d2,rxd_d2} <= {col_d1,crs_d1,rx_er_d1,rx_dv_d1,rxd_d1}; + + always @(posedge rx_clk) + buffer[addr_wr] <= {col_d2,crs_d2,rx_er_d2,rx_dv_d1,rxd_d2}; + + always @(posedge rx_clk or posedge rst) + if(rst) addr_wr <= 0; + else addr_wr <= addr_wr + 1; + + always @(posedge rx_clk) + begin + addr_wr_gray <= {addr_wr[3],^addr_wr[3:2],^addr_wr[2:1],^addr_wr[1:0]}; + awg_d1 <= addr_wr_gray; + awg_d2 <= awg_d1; + end + + always @(posedge tx_clk) + begin + addr_wr_gray_ret <= awg_d2; + awgr_d1 <= addr_wr_gray_ret; + addr_wr_ungray <= {awgr_d1[3],^awgr_d1[3:2],^awgr_d1[3:1],^awgr_d1[3:0]}; + end + + wire [3:0] addr_delta = addr_rd-addr_wr_ungray; + reg [1:0] direction; + localparam retard = 2'd0; + localparam good = 2'd1; + localparam advance = 2'd2; + localparam wayoff = 2'd3; + + always @* + case(addr_delta) + 4'd1, 4'd2, 4'd3, 4'd4, 4'd5 : direction <= retard; + 4'd15, 4'd14, 4'd13, 4'd12, 4'd11 : direction <= advance; + 4'd0 : direction <= good; + default : direction <= wayoff; + endcase // case(addr_delta) + + always @(posedge tx_clk or posedge rst) + if(rst) + addr_rd <= 0; + else if(rx_dv_ret_adv | rx_dv_ontime) + addr_rd <= addr_rd + 1; + else + case(direction) + retard : addr_rd <= addr_rd; + advance : addr_rd <= addr_rd + 2; + good : addr_rd <= addr_rd + 1; + wayoff : addr_rd <= addr_wr_ungray; + endcase // case(direction) + + assign {col_ret,crs_ret,rx_er_ret,rx_dv_ret_adv,rxd_ret} = buffer[addr_rd]; + always @(posedge tx_clk) + rx_dv_ontime <= rx_dv_ret_adv; + + assign rx_dv_ret = rx_dv_ontime; +endmodule // elastic_buffer diff --git a/eth/rtl/verilog/elastic_buffer_tb.v b/eth/rtl/verilog/elastic_buffer_tb.v new file mode 100644 index 000000000..757049ec4 --- /dev/null +++ b/eth/rtl/verilog/elastic_buffer_tb.v @@ -0,0 +1,66 @@ + +module elastic_buffer_tb; + + reg rx_clk = 0, tx_clk = 0, rst = 1; + + reg [7:0] rxd; + wire [7:0] rxd_ret; + reg rx_dv, rx_er, crs, col; + wire rx_dv_ret, rx_er_ret, crs_ret, col_ret; + + elastic_buffer elastic_buffer + (.rx_clk(rx_clk),.tx_clk(tx_clk),.rst(rst), + .rxd(rxd),.rx_dv(rx_dv),.rx_er(rx_er),.crs(crs),.col(col), + .rxd_ret(rxd_ret),.rx_dv_ret(rx_dv_ret),.rx_er_ret(rx_er_ret), + .crs_ret(crs_ret),.col_ret(col_ret) ); + + always #100 rx_clk = ~rx_clk; + always #101 tx_clk = ~tx_clk; + initial #950 rst = 0; + + initial + begin + {col,crs,rx_er,rx_dv,rxd} <= 0; + @(negedge rst); + @(posedge rx_clk); + + repeat (13) + begin + repeat (284) + @(posedge rx_clk); + SendPKT; + end + repeat (100) + @(posedge rx_clk); + $finish; + end // initial begin + + reg [7:0] rxd_ret_d1; + always @(posedge tx_clk) + rxd_ret_d1 <= rxd_ret; + + wire [7:0] diff = rxd_ret_d1 - rxd_ret; + + wire error = rx_dv_ret && (diff != 8'hFF); + + task SendPKT; + begin + {col,crs,rx_er,rx_dv,rxd} <= 0; + @(posedge rx_clk); + {col,crs,rx_er,rx_dv,rxd} <= {4'hF,8'd1}; + @(posedge rx_clk); + repeat (250) + begin + rxd <= rxd + 1; + @(posedge rx_clk); + end + {col,crs,rx_er,rx_dv,rxd} <= 0; + @(posedge rx_clk); + end + endtask // SendPKT + + initial begin + $dumpfile("elastic_buffer_tb.vcd"); + $dumpvars(0,elastic_buffer_tb); + end +endmodule // elastic_buffer_tb diff --git a/eth/rtl/verilog/eth_miim.v b/eth/rtl/verilog/eth_miim.v new file mode 100644 index 000000000..a15c94205 --- /dev/null +++ b/eth/rtl/verilog/eth_miim.v @@ -0,0 +1,470 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// eth_miim.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects/ethmac/ //// +//// //// +//// Author(s): //// +//// - Igor Mohor (igorM@opencores.org) //// +//// //// +//// All additional information is avaliable in the Readme.txt //// +//// file. //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source 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 Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: eth_miim.v,v $ +// Revision 1.3 2006/01/19 14:07:53 maverickist +// verification is complete. +// +// Revision 1.1.1.1 2005/12/13 01:51:44 Administrator +// no message +// +// Revision 1.4 2005/08/16 12:07:57 Administrator +// no message +// +// Revision 1.3 2005/05/19 07:04:29 Administrator +// no message +// +// Revision 1.2 2005/04/27 15:58:46 Administrator +// no message +// +// Revision 1.1.1.1 2004/12/15 06:38:54 Administrator +// no message +// +// Revision 1.5 2003/05/16 10:08:27 mohor +// Busy was set 2 cycles too late. Reported by Dennis Scott. +// +// Revision 1.4 2002/08/14 18:32:10 mohor +// - Busy signal was not set on time when scan status operation was performed +// and clock was divided with more than 2. +// - Nvalid remains valid two more clocks (was previously cleared too soon). +// +// Revision 1.3 2002/01/23 10:28:16 mohor +// Link in the header changed. +// +// Revision 1.2 2001/10/19 08:43:51 mohor +// eth_timescale.v changed to timescale.v This is done because of the +// simulation of the few cores in a one joined project. +// +// Revision 1.1 2001/08/06 14:44:29 mohor +// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex). +// Include files fixed to contain no path. +// File names and module names changed ta have a eth_ prologue in the name. +// File eth_timescale.v is used to define timescale +// All pin names on the top module are changed to contain _I, _O or _OE at the end. +// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O +// and Mdo_OE. The bidirectional signal must be created on the top level. This +// is done due to the ASIC tools. +// +// Revision 1.2 2001/08/02 09:25:31 mohor +// Unconnected signals are now connected. +// +// Revision 1.1 2001/07/30 21:23:42 mohor +// Directory structure changed. Files checked and joind together. +// +// Revision 1.3 2001/06/01 22:28:56 mohor +// This files (MIIM) are fully working. They were thoroughly tested. The testbench is not updated. +// +// + +module eth_miim +( + Clk, + Reset, + Divider, + NoPre, + CtrlData, + Rgad, + Fiad, + WCtrlData, + RStat, + ScanStat, + Mdio, + Mdc, + Busy, + Prsd, + LinkFail, + Nvalid, + WCtrlDataStart, + RStatStart, + UpdateMIIRX_DATAReg +); + +input Clk; // Host Clock +input Reset; // General Reset +input [7:0] Divider; // Divider for the host clock +input [15:0] CtrlData; // Control Data (to be written to the PHY reg.) +input [4:0] Rgad; // Register Address (within the PHY) +input [4:0] Fiad; // PHY Address +input NoPre; // No Preamble (no 32-bit preamble) +input WCtrlData; // Write Control Data operation +input RStat; // Read Status operation +input ScanStat; // Scan Status operation +inout Mdio; // MII Management Data In + +output Mdc; // MII Management Data Clock + +output Busy; // Busy Signal +output LinkFail; // Link Integrity Signal +output Nvalid; // Invalid Status (qualifier for the valid scan result) + +output [15:0] Prsd; // Read Status Data (data read from the PHY) + +output WCtrlDataStart; // This signals resets the WCTRLDATA bit in the MIIM Command register +output RStatStart; // This signal resets the RSTAT BIT in the MIIM Command register +output UpdateMIIRX_DATAReg;// Updates MII RX_DATA register with read data + +//parameter Tp = 1; + + +reg Nvalid; +reg EndBusy_d; // Pre-end Busy signal +reg EndBusy; // End Busy signal (stops the operation in progress) + +reg WCtrlData_q1; // Write Control Data operation delayed 1 Clk cycle +reg WCtrlData_q2; // Write Control Data operation delayed 2 Clk cycles +reg WCtrlData_q3; // Write Control Data operation delayed 3 Clk cycles +reg WCtrlDataStart; // Start Write Control Data Command (positive edge detected) +reg WCtrlDataStart_q; +reg WCtrlDataStart_q1; // Start Write Control Data Command delayed 1 Mdc cycle +reg WCtrlDataStart_q2; // Start Write Control Data Command delayed 2 Mdc cycles + +reg RStat_q1; // Read Status operation delayed 1 Clk cycle +reg RStat_q2; // Read Status operation delayed 2 Clk cycles +reg RStat_q3; // Read Status operation delayed 3 Clk cycles +reg RStatStart; // Start Read Status Command (positive edge detected) +reg RStatStart_q1; // Start Read Status Command delayed 1 Mdc cycle +reg RStatStart_q2; // Start Read Status Command delayed 2 Mdc cycles + +reg ScanStat_q1; // Scan Status operation delayed 1 cycle +reg ScanStat_q2; // Scan Status operation delayed 2 cycles +reg SyncStatMdcEn; // Scan Status operation delayed at least cycles and synchronized to MdcEn + +wire WriteDataOp; // Write Data Operation (positive edge detected) +wire ReadStatusOp; // Read Status Operation (positive edge detected) +wire ScanStatusOp; // Scan Status Operation (positive edge detected) +wire StartOp; // Start Operation (start of any of the preceding operations) +wire EndOp; // End of Operation + +reg InProgress; // Operation in progress +reg InProgress_q1; // Operation in progress delayed 1 Mdc cycle +reg InProgress_q2; // Operation in progress delayed 2 Mdc cycles +reg InProgress_q3; // Operation in progress delayed 3 Mdc cycles + +reg WriteOp; // Write Operation Latch (When asserted, write operation is in progress) +reg [6:0] BitCounter; // Bit Counter + + +wire [3:0] ByteSelect; // Byte Select defines which byte (preamble, data, operation, etc.) is loaded and shifted through the shift register. +wire MdcEn; // MII Management Data Clock Enable signal is asserted for one Clk period before Mdc rises. +wire ShiftedBit; // This bit is output of the shift register and is connected to the Mdo signal + + +wire LatchByte1_d2; +wire LatchByte0_d2; +reg LatchByte1_d; +reg LatchByte0_d; +reg [1:0] LatchByte; // Latch Byte selects which part of Read Status Data is updated from the shift register + +reg UpdateMIIRX_DATAReg;// Updates MII RX_DATA register with read data + +wire Mdo; // MII Management Data Output +wire MdoEn; // MII Management Data Output Enable +wire Mdi; + +assign Mdi=Mdio; +assign Mdio=MdoEn?Mdo:1'bz; + + + +// Generation of the EndBusy signal. It is used for ending the MII Management operation. +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + begin + EndBusy_d <= 1'b0; + EndBusy <= 1'b0; + end + else + begin + EndBusy_d <= ~InProgress_q2 & InProgress_q3; + EndBusy <= EndBusy_d; + end +end + + +// Update MII RX_DATA register +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + UpdateMIIRX_DATAReg <= 0; + else + if(EndBusy & ~WCtrlDataStart_q) + UpdateMIIRX_DATAReg <= 1; + else + UpdateMIIRX_DATAReg <= 0; +end + + + +// Generation of the delayed signals used for positive edge triggering. +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + begin + WCtrlData_q1 <= 1'b0; + WCtrlData_q2 <= 1'b0; + WCtrlData_q3 <= 1'b0; + + RStat_q1 <= 1'b0; + RStat_q2 <= 1'b0; + RStat_q3 <= 1'b0; + + ScanStat_q1 <= 1'b0; + ScanStat_q2 <= 1'b0; + SyncStatMdcEn <= 1'b0; + end + else + begin + WCtrlData_q1 <= WCtrlData; + WCtrlData_q2 <= WCtrlData_q1; + WCtrlData_q3 <= WCtrlData_q2; + + RStat_q1 <= RStat; + RStat_q2 <= RStat_q1; + RStat_q3 <= RStat_q2; + + ScanStat_q1 <= ScanStat; + ScanStat_q2 <= ScanStat_q1; + if(MdcEn) + SyncStatMdcEn <= ScanStat_q2; + end +end + + +// Generation of the Start Commands (Write Control Data or Read Status) +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + begin + WCtrlDataStart <= 1'b0; + WCtrlDataStart_q <= 1'b0; + RStatStart <= 1'b0; + end + else + begin + if(EndBusy) + begin + WCtrlDataStart <= 1'b0; + RStatStart <= 1'b0; + end + else + begin + if(WCtrlData_q2 & ~WCtrlData_q3) + WCtrlDataStart <= 1'b1; + if(RStat_q2 & ~RStat_q3) + RStatStart <= 1'b1; + WCtrlDataStart_q <= WCtrlDataStart; + end + end +end + + +// Generation of the Nvalid signal (indicates when the status is invalid) +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + Nvalid <= 1'b0; + else + begin + if(~InProgress_q2 & InProgress_q3) + begin + Nvalid <= 1'b0; + end + else + begin + if(ScanStat_q2 & ~SyncStatMdcEn) + Nvalid <= 1'b1; + end + end +end + +// Signals used for the generation of the Operation signals (positive edge) +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + begin + WCtrlDataStart_q1 <= 1'b0; + WCtrlDataStart_q2 <= 1'b0; + + RStatStart_q1 <= 1'b0; + RStatStart_q2 <= 1'b0; + + InProgress_q1 <= 1'b0; + InProgress_q2 <= 1'b0; + InProgress_q3 <= 1'b0; + + LatchByte0_d <= 1'b0; + LatchByte1_d <= 1'b0; + + LatchByte <= 2'b00; + end + else + begin + if(MdcEn) + begin + WCtrlDataStart_q1 <= WCtrlDataStart; + WCtrlDataStart_q2 <= WCtrlDataStart_q1; + + RStatStart_q1 <= RStatStart; + RStatStart_q2 <= RStatStart_q1; + + LatchByte[0] <= LatchByte0_d; + LatchByte[1] <= LatchByte1_d; + + LatchByte0_d <= LatchByte0_d2; + LatchByte1_d <= LatchByte1_d2; + + InProgress_q1 <= InProgress; + InProgress_q2 <= InProgress_q1; + InProgress_q3 <= InProgress_q2; + end + end +end + + +// Generation of the Operation signals +assign WriteDataOp = WCtrlDataStart_q1 & ~WCtrlDataStart_q2; +assign ReadStatusOp = RStatStart_q1 & ~RStatStart_q2; +assign ScanStatusOp = SyncStatMdcEn & ~InProgress & ~InProgress_q1 & ~InProgress_q2; +assign StartOp = WriteDataOp | ReadStatusOp | ScanStatusOp; + +// Busy +reg Busy; +always @ (posedge Clk or posedge Reset) + if (Reset) + Busy <=0; + else if(WCtrlData | WCtrlDataStart | RStat | RStatStart | SyncStatMdcEn | EndBusy | InProgress | InProgress_q3 | Nvalid) + Busy <=1; + else + Busy <=0; + +//assign Busy = WCtrlData | WCtrlDataStart | RStat | RStatStart | SyncStatMdcEn | EndBusy | InProgress | InProgress_q3 | Nvalid; + + +// Generation of the InProgress signal (indicates when an operation is in progress) +// Generation of the WriteOp signal (indicates when a write is in progress) +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + begin + InProgress <= 1'b0; + WriteOp <= 1'b0; + end + else + begin + if(MdcEn) + begin + if(StartOp) + begin + if(~InProgress) + WriteOp <= WriteDataOp; + InProgress <= 1'b1; + end + else + begin + if(EndOp) + begin + InProgress <= 1'b0; + WriteOp <= 1'b0; + end + end + end + end +end + + + +// Bit Counter counts from 0 to 63 (from 32 to 63 when NoPre is asserted) +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + BitCounter[6:0] <= 7'h0; + else + begin + if(MdcEn) + begin + if(InProgress) + begin + if(NoPre & ( BitCounter == 7'h0 )) + BitCounter[6:0] <= 7'h21; + else + BitCounter[6:0] <= BitCounter[6:0] + 1'b1; + end + else + BitCounter[6:0] <= 7'h0; + end + end +end + + +// Operation ends when the Bit Counter reaches 63 +assign EndOp = BitCounter==63; + +assign ByteSelect[0] = InProgress & ((NoPre & (BitCounter == 7'h0)) | (~NoPre & (BitCounter == 7'h20))); +assign ByteSelect[1] = InProgress & (BitCounter == 7'h28); +assign ByteSelect[2] = InProgress & WriteOp & (BitCounter == 7'h30); +assign ByteSelect[3] = InProgress & WriteOp & (BitCounter == 7'h38); + + +// Latch Byte selects which part of Read Status Data is updated from the shift register +assign LatchByte1_d2 = InProgress & ~WriteOp & BitCounter == 7'h37; +assign LatchByte0_d2 = InProgress & ~WriteOp & BitCounter == 7'h3F; + +wire MdcEn_n; + +// Connecting the Clock Generator Module +eth_clockgen clkgen(.Clk(Clk), .Reset(Reset), .Divider(Divider[7:0]), .MdcEn(MdcEn), .MdcEn_n(MdcEn_n), .Mdc(Mdc) + ); + +// Connecting the Shift Register Module +eth_shiftreg shftrg(.Clk(Clk), .Reset(Reset), .MdcEn_n(MdcEn_n), .Mdi(Mdi), .Fiad(Fiad), .Rgad(Rgad), + .CtrlData(CtrlData), .WriteOp(WriteOp), .ByteSelect(ByteSelect), .LatchByte(LatchByte), + .ShiftedBit(ShiftedBit), .Prsd(Prsd), .LinkFail(LinkFail) + ); + +// Connecting the Output Control Module +eth_outputcontrol outctrl(.Clk(Clk), .Reset(Reset), .MdcEn_n(MdcEn_n), .InProgress(InProgress), + .ShiftedBit(ShiftedBit), .BitCounter(BitCounter), .WriteOp(WriteOp), .NoPre(NoPre), + .Mdo(Mdo), .MdoEn(MdoEn) + ); + +endmodule diff --git a/eth/rtl/verilog/flow_ctrl_rx.v b/eth/rtl/verilog/flow_ctrl_rx.v new file mode 100644 index 000000000..7ded9e08b --- /dev/null +++ b/eth/rtl/verilog/flow_ctrl_rx.v @@ -0,0 +1,85 @@ + +// RX side of flow control -- when we are running out of RX space, send a PAUSE + +module flow_ctrl_rx + (input rst, + //host processor + input pause_frame_send_en, + input [15:0] pause_quanta_set, + input [15:0] fc_hwmark, + input [15:0] fc_lwmark, + // From MAC_rx_ctrl + input rx_clk, + input [15:0] rx_fifo_space, + // MAC_tx_ctrl + input tx_clk, + output reg xoff_gen, + output reg xon_gen, + input xoff_gen_complete, + input xon_gen_complete + ); + + // ****************************************************************************** + // Force our TX to send a PAUSE frame because our RX is nearly full + // ****************************************************************************** + + reg xon_int, xoff_int; + reg [21:0] countdown; + + always @(posedge rx_clk or posedge rst) + if(rst) + begin + xon_int <= 0; + xoff_int <= 0; + end + else + begin + xon_int <= 0; + xoff_int <= 0; + if(pause_frame_send_en) + if(countdown == 0) + if(rx_fifo_space < fc_lwmark) + xoff_int <= 1; + else + ; + else + if(rx_fifo_space > fc_hwmark) + xon_int <= 1; + end // else: !if(rst) + + reg xoff_int_d1, xon_int_d1; + + always @(posedge rx_clk) + xon_int_d1 <= xon_int; + always @(posedge rx_clk) + xoff_int_d1 <= xoff_int; + + always @ (posedge tx_clk or posedge rst) + if (rst) + xoff_gen <=0; + else if (xoff_gen_complete) + xoff_gen <=0; + else if (xoff_int | xoff_int_d1) + xoff_gen <=1; + + always @ (posedge tx_clk or posedge rst) + if (rst) + xon_gen <=0; + else if (xon_gen_complete) + xon_gen <=0; + else if (xon_int | xon_int_d1) + xon_gen <=1; + + wire [15:0] pq_reduced = pause_quanta_set - 2; + + always @(posedge tx_clk or posedge rst) + if(rst) + countdown <= 0; + else if(xoff_gen) + countdown <= {pq_reduced,6'd0}; + else if(xon_gen) + countdown <= 0; + else if(countdown != 0) + countdown <= countdown - 1; + +endmodule // flow_ctrl diff --git a/eth/rtl/verilog/flow_ctrl_tx.v b/eth/rtl/verilog/flow_ctrl_tx.v new file mode 100644 index 000000000..9f7556de4 --- /dev/null +++ b/eth/rtl/verilog/flow_ctrl_tx.v @@ -0,0 +1,36 @@ + +// TX side of flow control -- when other side sends PAUSE, we wait + +module flow_ctrl_tx + (input rst, + input tx_clk, + //host processor + input tx_pause_en, + // From MAC_rx_ctrl + input [15:0] pause_quanta, + input pause_quanta_val, + // MAC_tx_ctrl + output pause_apply, + input pause_quanta_sub); + + // ****************************************************************************** + // Inhibit our TX from transmitting because they sent us a PAUSE frame + // ****************************************************************************** + + reg [15:0] pause_quanta_counter; + reg pqval_d1, pqval_d2; + + always @(posedge tx_clk) pqval_d1 <= pause_quanta_val; + always @(posedge tx_clk) pqval_d2 <= pqval_d1; + + always @ (posedge tx_clk or posedge rst) + if (rst) + pause_quanta_counter <= 0; + else if (pqval_d1 & ~pqval_d2) + pause_quanta_counter <= pause_quanta; + else if((pause_quanta_counter!=0) & pause_quanta_sub) + pause_quanta_counter <= pause_quanta_counter - 1; + + assign pause_apply = tx_pause_en & (pause_quanta_counter != 0); + +endmodule // flow_ctrl diff --git a/eth/rtl/verilog/header.vh b/eth/rtl/verilog/header.vh new file mode 100644 index 000000000..ca0b580e4 --- /dev/null +++ b/eth/rtl/verilog/header.vh @@ -0,0 +1,7 @@ +`define MAC_SOURCE_REPLACE_EN 1 +`define MAC_TARGET_CHECK_EN 1 +`define MAC_BROADCAST_FILTER_EN 1 +`define MAC_TX_FF_DEPTH 9 +`define MAC_RX_FF_DEPTH 9 +`define MAC_TARGET_XILINX 1 +// `define MAC_TARGET_ALTERA 1 diff --git a/eth/rtl/verilog/miim/eth_clockgen.v b/eth/rtl/verilog/miim/eth_clockgen.v new file mode 100644 index 000000000..9da732f7f --- /dev/null +++ b/eth/rtl/verilog/miim/eth_clockgen.v @@ -0,0 +1,141 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// eth_clockgen.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects/ethmac/ //// +//// //// +//// Author(s): //// +//// - Igor Mohor (igorM@opencores.org) //// +//// //// +//// All additional information is avaliable in the Readme.txt //// +//// file. //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source 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 Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: eth_clockgen.v,v $ +// Revision 1.2 2005/12/13 12:54:49 maverickist +// first simulation passed +// +// Revision 1.1.1.1 2005/12/13 01:51:45 Administrator +// no message +// +// Revision 1.2 2005/04/27 15:58:45 Administrator +// no message +// +// Revision 1.1.1.1 2004/12/15 06:38:54 Administrator +// no message +// +// Revision 1.3 2002/01/23 10:28:16 mohor +// Link in the header changed. +// +// Revision 1.2 2001/10/19 08:43:51 mohor +// eth_timescale.v changed to timescale.v This is done because of the +// simulation of the few cores in a one joined project. +// +// Revision 1.1 2001/08/06 14:44:29 mohor +// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex). +// Include files fixed to contain no path. +// File names and module names changed ta have a eth_ prologue in the name. +// File eth_timescale.v is used to define timescale +// All pin names on the top module are changed to contain _I, _O or _OE at the end. +// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O +// and Mdo_OE. The bidirectional signal must be created on the top level. This +// is done due to the ASIC tools. +// +// Revision 1.1 2001/07/30 21:23:42 mohor +// Directory structure changed. Files checked and joind together. +// +// Revision 1.3 2001/06/01 22:28:55 mohor +// This files (MIIM) are fully working. They were thoroughly tested. The testbench is not updated. +// +// + +module eth_clockgen(Clk, Reset, Divider, MdcEn, MdcEn_n, Mdc); + +//parameter Tp=1; + +input Clk; // Input clock (Host clock) +input Reset; // Reset signal +input [7:0] Divider; // Divider (input clock will be divided by the Divider[7:0]) + +output Mdc; // Output clock +output MdcEn; // Enable signal is asserted for one Clk period before Mdc rises. +output MdcEn_n; // Enable signal is asserted for one Clk period before Mdc falls. + +reg Mdc; +reg [7:0] Counter; + +wire CountEq0; +wire [7:0] CounterPreset; +wire [7:0] TempDivider; + + +assign TempDivider[7:0] = (Divider[7:0]<2)? 8'h02 : Divider[7:0]; // If smaller than 2 +assign CounterPreset[7:0] = (TempDivider[7:0]>>1) -1; // We are counting half of period + + +// Counter counts half period +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + Counter[7:0] <= 8'h1; + else + begin + if(CountEq0) + begin + Counter[7:0] <= CounterPreset[7:0]; + end + else + Counter[7:0] <= Counter - 8'h1; + end +end + + +// Mdc is asserted every other half period +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + Mdc <= 1'b0; + else + begin + if(CountEq0) + Mdc <= ~Mdc; + end +end + + +assign CountEq0 = Counter == 8'h0; +assign MdcEn = CountEq0 & ~Mdc; +assign MdcEn_n = CountEq0 & Mdc; + +endmodule + + diff --git a/eth/rtl/verilog/miim/eth_outputcontrol.v b/eth/rtl/verilog/miim/eth_outputcontrol.v new file mode 100644 index 000000000..3df6c560a --- /dev/null +++ b/eth/rtl/verilog/miim/eth_outputcontrol.v @@ -0,0 +1,158 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// eth_outputcontrol.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects/ethmac/ //// +//// //// +//// Author(s): //// +//// - Igor Mohor (igorM@opencores.org) //// +//// //// +//// All additional information is avaliable in the Readme.txt //// +//// file. //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source 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 Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: eth_outputcontrol.v,v $ +// Revision 1.2 2005/12/13 12:54:49 maverickist +// first simulation passed +// +// Revision 1.1.1.1 2005/12/13 01:51:45 Administrator +// no message +// +// Revision 1.2 2005/04/27 15:58:46 Administrator +// no message +// +// Revision 1.1.1.1 2004/12/15 06:38:54 Administrator +// no message +// +// Revision 1.4 2002/07/09 20:11:59 mohor +// Comment removed. +// +// Revision 1.3 2002/01/23 10:28:16 mohor +// Link in the header changed. +// +// Revision 1.2 2001/10/19 08:43:51 mohor +// eth_timescale.v changed to timescale.v This is done because of the +// simulation of the few cores in a one joined project. +// +// Revision 1.1 2001/08/06 14:44:29 mohor +// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex). +// Include files fixed to contain no path. +// File names and module names changed ta have a eth_ prologue in the name. +// File eth_timescale.v is used to define timescale +// All pin names on the top module are changed to contain _I, _O or _OE at the end. +// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O +// and Mdo_OE. The bidirectional signal must be created on the top level. This +// is done due to the ASIC tools. +// +// Revision 1.1 2001/07/30 21:23:42 mohor +// Directory structure changed. Files checked and joind together. +// +// Revision 1.3 2001/06/01 22:28:56 mohor +// This files (MIIM) are fully working. They were thoroughly tested. The testbench is not updated. +// +// + +module eth_outputcontrol(Clk, Reset, InProgress, ShiftedBit, BitCounter, WriteOp, NoPre, MdcEn_n, Mdo, MdoEn); + +input Clk; // Host Clock +input Reset; // General Reset +input WriteOp; // Write Operation Latch (When asserted, write operation is in progress) +input NoPre; // No Preamble (no 32-bit preamble) +input InProgress; // Operation in progress +input ShiftedBit; // This bit is output of the shift register and is connected to the Mdo signal +input [6:0] BitCounter; // Bit Counter +input MdcEn_n; // MII Management Data Clock Enable signal is asserted for one Clk period before Mdc falls. + +output Mdo; // MII Management Data Output +output MdoEn; // MII Management Data Output Enable + +wire SerialEn; + +reg MdoEn_2d; +reg MdoEn_d; +reg MdoEn; + +reg Mdo_2d; +reg Mdo_d; +reg Mdo; // MII Management Data Output + + + +// Generation of the Serial Enable signal (enables the serialization of the data) +assign SerialEn = WriteOp & InProgress & ( BitCounter>31 | ( ( BitCounter == 0 ) & NoPre ) ) + | ~WriteOp & InProgress & (( BitCounter>31 & BitCounter<46 ) | ( ( BitCounter == 0 ) & NoPre )); + + +// Generation of the MdoEn signal +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + begin + MdoEn_2d <= 1'b0; + MdoEn_d <= 1'b0; + MdoEn <= 1'b0; + end + else + begin + if(MdcEn_n) + begin + MdoEn_2d <= SerialEn | InProgress & BitCounter<32; + MdoEn_d <= MdoEn_2d; + MdoEn <= MdoEn_d; + end + end +end + + +// Generation of the Mdo signal. +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + begin + Mdo_2d <= 1'b0; + Mdo_d <= 1'b0; + Mdo <= 1'b0; + end + else + begin + if(MdcEn_n) + begin + Mdo_2d <= ~SerialEn & BitCounter<32; + Mdo_d <= ShiftedBit | Mdo_2d; + Mdo <= Mdo_d; + end + end +end + + + +endmodule diff --git a/eth/rtl/verilog/miim/eth_shiftreg.v b/eth/rtl/verilog/miim/eth_shiftreg.v new file mode 100644 index 000000000..0b97bb7bc --- /dev/null +++ b/eth/rtl/verilog/miim/eth_shiftreg.v @@ -0,0 +1,159 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// eth_shiftreg.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects/ethmac/ //// +//// //// +//// Author(s): //// +//// - Igor Mohor (igorM@opencores.org) //// +//// //// +//// All additional information is avaliable in the Readme.txt //// +//// file. //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source 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 Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: eth_shiftreg.v,v $ +// Revision 1.2 2005/12/13 12:54:49 maverickist +// first simulation passed +// +// Revision 1.1.1.1 2005/12/13 01:51:45 Administrator +// no message +// +// Revision 1.2 2005/04/27 15:58:47 Administrator +// no message +// +// Revision 1.1.1.1 2004/12/15 06:38:54 Administrator +// no message +// +// Revision 1.5 2002/08/14 18:16:59 mohor +// LinkFail signal was not latching appropriate bit. +// +// Revision 1.4 2002/03/02 21:06:01 mohor +// LinkFail signal was not latching appropriate bit. +// +// Revision 1.3 2002/01/23 10:28:16 mohor +// Link in the header changed. +// +// Revision 1.2 2001/10/19 08:43:51 mohor +// eth_timescale.v changed to timescale.v This is done because of the +// simulation of the few cores in a one joined project. +// +// Revision 1.1 2001/08/06 14:44:29 mohor +// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex). +// Include files fixed to contain no path. +// File names and module names changed ta have a eth_ prologue in the name. +// File eth_timescale.v is used to define timescale +// All pin names on the top module are changed to contain _I, _O or _OE at the end. +// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O +// and Mdo_OE. The bidirectional signal must be created on the top level. This +// is done due to the ASIC tools. +// +// Revision 1.1 2001/07/30 21:23:42 mohor +// Directory structure changed. Files checked and joind together. +// +// Revision 1.3 2001/06/01 22:28:56 mohor +// This files (MIIM) are fully working. They were thoroughly tested. The testbench is not updated. +// +// + +module eth_shiftreg(Clk, Reset, MdcEn_n, Mdi, Fiad, Rgad, CtrlData, WriteOp, ByteSelect, + LatchByte, ShiftedBit, Prsd, LinkFail); + + +input Clk; // Input clock (Host clock) +input Reset; // Reset signal +input MdcEn_n; // Enable signal is asserted for one Clk period before Mdc falls. +input Mdi; // MII input data +input [4:0] Fiad; // PHY address +input [4:0] Rgad; // Register address (within the selected PHY) +input [15:0]CtrlData; // Control data (data to be written to the PHY) +input WriteOp; // The current operation is a PHY register write operation +input [3:0] ByteSelect; // Byte select +input [1:0] LatchByte; // Byte select for latching (read operation) + +output ShiftedBit; // Bit shifted out of the shift register +output[15:0]Prsd; // Read Status Data (data read from the PHY) +output LinkFail; // Link Integrity Signal + +reg [7:0] ShiftReg; // Shift register for shifting the data in and out +reg [15:0]Prsd; +reg LinkFail; + + + + +// ShiftReg[7:0] :: Shift Register Data +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + begin + ShiftReg[7:0] <= 8'h0; + Prsd[15:0] <= 16'h0; + LinkFail <= 1'b0; + end + else + begin + if(MdcEn_n) + begin + if(|ByteSelect) + begin + case (ByteSelect[3:0]) + 4'h1 : ShiftReg[7:0] <= {2'b01, ~WriteOp, WriteOp, Fiad[4:1]}; + 4'h2 : ShiftReg[7:0] <= {Fiad[0], Rgad[4:0], 2'b10}; + 4'h4 : ShiftReg[7:0] <= CtrlData[15:8]; + 4'h8 : ShiftReg[7:0] <= CtrlData[7:0]; + default : ShiftReg[7:0] <= 8'h0; + endcase + end + else + begin + ShiftReg[7:0] <= {ShiftReg[6:0], Mdi}; + if(LatchByte[0]) + begin + Prsd[7:0] <= {ShiftReg[6:0], Mdi}; + if(Rgad == 5'h01) + LinkFail <= ~ShiftReg[1]; // this is bit [2], because it is not shifted yet + end + else + begin + if(LatchByte[1]) + Prsd[15:8] <= {ShiftReg[6:0], Mdi}; + end + end + end + end +end + + +assign ShiftedBit = ShiftReg[7]; + + +endmodule diff --git a/eth/rx_prot_engine.v b/eth/rx_prot_engine.v new file mode 100644 index 000000000..d34f168d7 --- /dev/null +++ b/eth/rx_prot_engine.v @@ -0,0 +1,156 @@ + +module rx_prot_engine + #(parameter FIFO_SIZE=11) + (input clk, input rst, + + input Rx_mac_ra, + output Rx_mac_rd, + input [31:0] Rx_mac_data, + input [1:0] Rx_mac_BE, + input Rx_mac_pa, + input Rx_mac_sop, + input Rx_mac_eop, + input Rx_mac_err, + + output [31:0] wr_dat_o, + output wr_write_o, + output wr_done_o, + output wr_error_o, + input wr_ready_i, + input wr_full_i, + output wr_flag_o, + + input set_stb, + input [7:0] set_addr, + input [31:0] set_data, + + output [15:0] rx_fifo_status, + output reg [7:0] rx_seqnum, + output reg [7:0] rx_channel, + output [7:0] rx_flags + ); + + wire read, write, full, empty; + wire eop_i, err_i, eop_o, err_o, flag_i, sop_i, flag_o, sop_o; + wire [31:0] dat_i, dat_o; + reg xfer_active; + + wire [3:0] hdr_adr; + wire [31:0] hdr_dat; + + header_ram #(.REGNUM(48),.WIDTH(32)) rx_header_ram + (.clk(clk),.set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), + .addr(hdr_adr),.q(hdr_dat)); + + // Buffer interface side + always @(posedge clk) + if(rst) + xfer_active <= 0; + else if(wr_ready_i & ~empty) + xfer_active <= 1; + else if(eop_o | err_o | wr_full_i) + xfer_active <= 0; + + assign wr_done_o = eop_o & wr_write_o; + assign wr_error_o = err_o & wr_write_o; + assign wr_dat_o = dat_o; + assign wr_write_o = xfer_active & ~empty; + assign read = wr_write_o; + + // FIFO in the middle + cascadefifo2 #(.WIDTH(36),.SIZE(11)) rx_prot_fifo + (.clk(clk),.rst(rst), + .datain({flag_i,sop_i,eop_i,err_i,dat_i}),.write(write),.full(full), + .dataout({flag_o,sop_o,eop_o,err_o,dat_o}),.read(read),.empty(empty), + .clear(0),.fifo_space(rx_fifo_status)); + + // MAC side + localparam ETH_TYPE = 16'hBEEF; + + reg [2:0] prot_state; + localparam PROT_IDLE = 0; + localparam PROT_HDR1 = 1; + localparam PROT_HDR2 = 2; + localparam PROT_HDR3 = 3; + localparam PROT_HDR4 = 4; + localparam PROT_HDR5 = 5; + localparam PROT_PKT = 6; + + // Things to control: flag_i, sop_i, eop_i, err_i, dat_i, write, Rx_mac_rd + // Inputs to SM: Rx_mac_sop, Rx_mac_eop, Rx_mac_ra, Rx_mac_pa, + // Rx_mac_BE, Rx_mac_err, full + + reg flag; + assign dat_i = Rx_mac_data; + assign sop_i = Rx_mac_sop; + assign eop_i = Rx_mac_eop; + assign err_i = Rx_mac_err; + assign flag_i = flag; + assign wr_flag_o = flag_o; + assign Rx_mac_rd = (prot_state != PROT_IDLE) && (~full|~Rx_mac_pa); + assign write = (prot_state != PROT_IDLE) && ~full && Rx_mac_pa; + + assign hdr_adr = {1'b0,prot_state[2:0]}; + + wire [7:0] rx_seqnum_p1 = rx_seqnum + 1; + + always @(posedge clk) + if(rst) + begin + prot_state <= PROT_IDLE; + flag <= 0; + end + else if(prot_state == PROT_IDLE) + begin + flag <= 0; + if(Rx_mac_ra) + prot_state <= PROT_HDR1; + end + else if(write) + case(prot_state) + PROT_HDR1 : + begin + prot_state <= PROT_HDR2; + if(hdr_dat != Rx_mac_data) + flag <= 1; + end + PROT_HDR2 : + begin + prot_state <= PROT_HDR3; + if(hdr_dat != Rx_mac_data) + flag <= 1; + end + PROT_HDR3 : + begin + prot_state <= PROT_HDR4; + if(hdr_dat != Rx_mac_data) + flag <= 1; + end + PROT_HDR4 : + begin + prot_state <= PROT_HDR5; + if(hdr_dat[31:16] != Rx_mac_data[31:16]) + flag <= 1; + rx_channel <= hdr_dat[15:8]; + end + PROT_HDR5 : + begin + prot_state <= PROT_PKT; + if((rx_seqnum_p1) != Rx_mac_data[15:8]) + flag <= 1; + end + PROT_PKT : + if(Rx_mac_eop | Rx_mac_err) + prot_state <= PROT_IDLE; + endcase // case(prot_state) + + always @(posedge clk) + if(rst) + rx_seqnum <= 8'hFF; + else if(set_stb & (set_addr == 54)) + rx_seqnum <= set_data[7:0]; + else if(write & (prot_state == PROT_HDR5) & ((rx_seqnum_p1) == Rx_mac_data[15:8]) & ~flag) + rx_seqnum <= rx_seqnum + 1; + + // Error cases -- Rx_mac_error, BE != 0 +endmodule // rx_prot_engine diff --git a/eth/tx_prot_engine.v b/eth/tx_prot_engine.v new file mode 100644 index 000000000..894d74a11 --- /dev/null +++ b/eth/tx_prot_engine.v @@ -0,0 +1,144 @@ + +module tx_prot_engine + (input clk, input rst, + + // To MAC + input Tx_mac_wa, + output Tx_mac_wr, + output [31:0] Tx_mac_data, + output [1:0] Tx_mac_BE, + output Tx_mac_sop, + output Tx_mac_eop, + + // To buffer interface + input [31:0] rd_dat_i, + output rd_read_o, + output rd_done_o, + output rd_error_o, + input rd_sop_i, + input rd_eop_i, + + // To control + input set_stb, + input [7:0] set_addr, + input [31:0] set_data, + + // Protocol Stuff + input [15:0] rx_fifo_status, + input [7:0] rx_seqnum + //input [7:0] tx_channel, + //input [7:0] tx_flags + ); + + wire [3:0] hdr_adr; + wire [31:0] hdr_dat; + wire [7:0] tx_channel; + + header_ram #(.REGNUM(32),.WIDTH(32)) tx_header_ram + (.clk(clk),.set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), + .addr(hdr_adr),.q(hdr_dat)); + + setting_reg #(.my_addr(32)) sr_channel + (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),.in(set_data), + .out(tx_channel),.changed()); + + // Might as well use a shortfifo here since they are basically free + wire empty, full, sfifo_write, sfifo_read; + wire [33:0] sfifo_in, sfifo_out; + + shortfifo #(.WIDTH(34)) txmac_sfifo + (.clk(clk),.rst(rst),.clear(0), + .datain(sfifo_in),.write(sfifo_write),.full(full), + .dataout(sfifo_out),.read(sfifo_read),.empty(empty)); + + // MAC side signals + // Inputs -- Tx_mac_wa, sfifo_out, empty + // outputs -- sfifo_read, Tx_mac_data, Tx_mac_wr, Tx_mac_BE, Tx_mac_sop, Tx_mac_eop + + // We are allowed to do one more write after we are told the FIFO is full + // This allows us to register the _wa signal and speed up timing. + reg tx_mac_wa_d1; + always @(posedge clk) + tx_mac_wa_d1 <= Tx_mac_wa; + + reg [2:0] prot_state; + localparam PROT_IDLE = 0; + localparam PROT_HDR1 = 1; + localparam PROT_HDR2 = 2; + localparam PROT_HDR3 = 3; + localparam PROT_HDR4 = 4; + localparam PROT_HDR5 = 5; + localparam PROT_PKT = 6; + + reg [7:0] tx_seqnum; + reg all_match; + always @(posedge clk) + if(rst) + tx_seqnum <= 0; + else if(set_stb & (set_addr == 36)) + tx_seqnum <= set_data[7:0]; + else if(tx_mac_wa_d1 & all_match & (prot_state == PROT_HDR5)) + tx_seqnum <= tx_seqnum + 1; + + always @(posedge clk) + if(rst) + prot_state <= PROT_IDLE; + else + if(tx_mac_wa_d1 & ~empty) + case(prot_state) + PROT_IDLE : + prot_state <= PROT_HDR1; + PROT_HDR1 : + prot_state <= PROT_HDR2; + PROT_HDR2 : + prot_state <= PROT_HDR3; + PROT_HDR3 : + prot_state <= PROT_HDR4; + PROT_HDR4 : + prot_state <= PROT_HDR5; + PROT_HDR5 : + prot_state <= PROT_PKT; + PROT_PKT : + if(sfifo_out[32] & ~empty) + prot_state <= PROT_IDLE; + default : + prot_state <= PROT_IDLE; + endcase // case(prot_state) + + assign hdr_adr = {1'b0,prot_state}; + wire match = (hdr_dat == sfifo_out[31:0]); + always @(posedge clk) + if(prot_state == PROT_IDLE) + all_match <= 1; + else if(tx_mac_wa_d1 & ~empty & + ((prot_state==PROT_HDR1)|(prot_state==PROT_HDR2)|(prot_state==PROT_HDR3))) + all_match <= all_match & match; + + localparam ETH_TYPE = 16'hBEEF; + assign Tx_mac_data = + ((prot_state == PROT_HDR5) & all_match) ? {rx_fifo_status,tx_seqnum,rx_seqnum} : + sfifo_out[31:0]; + assign sfifo_read = (prot_state != PROT_IDLE) & ~empty & tx_mac_wa_d1; + assign Tx_mac_wr = sfifo_read; + assign Tx_mac_BE = 0; // Since we only deal with packets that are multiples of 32 bits long + assign Tx_mac_sop = sfifo_out[33]; + assign Tx_mac_eop = sfifo_out[32]; + + // BUFFER side signals + reg xfer_active; + always @(posedge clk) + if(rst) + xfer_active <= 0; + else if(rd_eop_i & ~full) + xfer_active <= 0; + else if(rd_sop_i) + xfer_active <= 1; + + assign sfifo_in = {rd_sop_i, rd_eop_i, rd_dat_i}; + assign sfifo_write = xfer_active & ~full; + + assign rd_read_o = sfifo_write; + assign rd_done_o = 0; // Always send everything we're given? + assign rd_error_o = 0; // No possible error situations? + +endmodule // tx_prot_engine -- cgit v1.2.3