diff --git a/examples/nexys_a7/ethernet_logic_analyzer/sim/comparison_tb.sv b/examples/nexys_a7/ethernet_logic_analyzer/sim/comparison_tb.sv new file mode 100644 index 0000000..3deb584 --- /dev/null +++ b/examples/nexys_a7/ethernet_logic_analyzer/sim/comparison_tb.sv @@ -0,0 +1,170 @@ +`default_nettype none +`timescale 1ns/1ps + +module comparison_tb(); + logic ethclk; + logic rst; + + always begin + #5; + ethclk = !ethclk; + end + + /* batteries... */ + logic eth_crsdv; + logic[1:0] eth_rxd; + + logic eth_refclk; + logic eth_rstn; + + /* ether -> { cksum, bitorder } */ + logic[1:0] ether_axiod; + logic ether_axiov; + + /* cksum -> top_level */ + logic cksum_done, cksum_kill; + + /* bitorder -> firewall */ + logic[1:0] bitorder_axiod; + logic bitorder_axiov; + + /* firewall -> aggregate */ + logic[1:0] firewall_axiod; + logic firewall_axiov; + + /* aggregate output */ + logic[31:0] aggregate_axiod; + logic aggregate_axiov; + + /* and here's the pipeline... */ + + logic enable; + logic eth_crsdv_playback; + logic [1:0] eth_rxd_playback; + + logic eth_crsdv_pb9k; + logic [1:0] eth_rxd_pb9k; + + logic eth_crsdv_mtx; + logic [1:0] eth_rxd_mtx; + + logic eth_crsdv_debug; + logic [1:0] eth_rxd_debug; + + // assign eth_crsdv_debug = eth_crsdv_playback; + // assign eth_rxd_debug = eth_rxd_playback; + + // assign eth_crsdv_debug = eth_crsdv_pb9k; + // assign eth_rxd_debug = eth_rxd_pb9k; + + assign eth_crsdv_debug = eth_crsdv_mtx; + assign eth_rxd_debug = eth_rxd_mtx; + + ether_la_playback #(.MEM_FILE("capture.mem")) ether_la_playback_inst ( + .clk(ethclk), + .enable(enable), + .done(), + + .eth_crsdv(eth_crsdv_playback), + .eth_rxd(eth_rxd_playback), + .eth_txen(), + .eth_txd()); + + logic pb9k_start; + packet_blaster_9k pb9k ( + .clk(ethclk), + .rst(rst), + + //.src_mac(48'h69_2C_08_30_75_FD), + .src_mac(48'h00_00_00_00_00_00), + .dst_mac(48'hFF_FF_FF_FF_FF_FF), + + .data(16'h5678), + + .start(pb9k_start), + + .txen(eth_crsdv_pb9k), + .txd(eth_rxd_pb9k)); + + logic mtx_start; + mac_tx mtx ( + .clk(ethclk), + + .data(16'h5678), + + .start(mtx_start), + + .txen(eth_crsdv_mtx), + .txd(eth_rxd_mtx)); + + + + ether e( + .clk(ethclk), + .rst(rst), + .rxd(eth_rxd_debug), + .crsdv(eth_crsdv_debug), + .axiov(ether_axiov), + .axiod(ether_axiod)); + + bitorder b( + .clk(ethclk), + .rst(rst), + .axiiv(ether_axiov), + .axiid(ether_axiod), + .axiov(bitorder_axiov), + .axiod(bitorder_axiod)); + + firewall f( + .clk(ethclk), + .rst(rst), + .axiiv(bitorder_axiov), + .axiid(bitorder_axiod), + .axiov(firewall_axiov), + .axiod(firewall_axiod)); + + aggregate a( + .clk(ethclk), + .rst(rst), + .axiiv(firewall_axiov), + .axiid(firewall_axiod), + .axiov(aggregate_axiov), + .axiod(aggregate_axiod)); + + cksum c( + .clk(ethclk), + .rst(rst), + .axiiv(ether_axiov), + .axiid(ether_axiod), + .done(cksum_done), + .kill(cksum_kill)); + + initial begin + ethclk = 0; + $dumpfile("comparison_tb.vcd"); + $dumpvars(0, comparison_tb); + rst = 0; + pb9k_start = 0; + mtx_start = 0; + #10; + rst = 1; + #10; + rst = 0; + #10; + enable = 1; + #430; + pb9k_start = 1; + #10; + pb9k_start = 0; + #60; + mtx_start = 1 ; + #10; + mtx_start = 0; + + #5000; + + $finish(); + end + +endmodule +`default_nettype wire \ No newline at end of file diff --git a/examples/nexys_a7/ethernet_logic_analyzer/sim/mac_tx_tb.sv b/examples/nexys_a7/ethernet_logic_analyzer/sim/mac_tx_tb.sv new file mode 100644 index 0000000..9d9ffc2 --- /dev/null +++ b/examples/nexys_a7/ethernet_logic_analyzer/sim/mac_tx_tb.sv @@ -0,0 +1,128 @@ +`default_nettype none +`timescale 1ns/1ps + +module mac_tx_tb(); + logic ethclk; + logic rst; + + always begin + #5; + ethclk = !ethclk; + end + + /* batteries... */ + logic eth_crsdv; + logic[1:0] eth_rxd; + + logic eth_refclk; + logic eth_rstn; + + /* ether -> { cksum, bitorder } */ + logic[1:0] ether_axiod; + logic ether_axiov; + + /* cksum -> top_level */ + logic cksum_done, cksum_kill; + + /* bitorder -> firewall */ + logic[1:0] bitorder_axiod; + logic bitorder_axiov; + + /* firewall -> aggregate */ + logic[1:0] firewall_axiod; + logic firewall_axiov; + + /* aggregate output */ + logic[31:0] aggregate_axiod; + logic aggregate_axiov; + + /* and here's the pipeline... */ + + logic enable; + logic eth_crsdv_ref; + logic [1:0] eth_rxd_ref; + ether_la_playback #(.MEM_FILE("capture.mem")) ether_la_playback_inst ( + .clk(ethclk), + .enable(enable), + .done(), + + .eth_crsdv(eth_crsdv_ref), + .eth_rxd(eth_rxd_ref), + .eth_txen(), + .eth_txd()); + + logic start; + mac_tx mtx ( + .clk(ethclk), + + .data(16'h5678), + + .start(start), + + .txen(eth_crsdv), + .txd(eth_rxd)); + + ether e( + .clk(ethclk), + .rst(rst), + .rxd(eth_rxd), + .crsdv(eth_crsdv_ref), + .axiov(ether_axiov), + .axiod(ether_axiod)); + + bitorder b( + .clk(ethclk), + .rst(rst), + .axiiv(ether_axiov), + .axiid(ether_axiod), + .axiov(bitorder_axiov), + .axiod(bitorder_axiod)); + + firewall f( + .clk(ethclk), + .rst(rst), + .axiiv(bitorder_axiov), + .axiid(bitorder_axiod), + .axiov(firewall_axiov), + .axiod(firewall_axiod)); + + aggregate a( + .clk(ethclk), + .rst(rst), + .axiiv(firewall_axiov), + .axiid(firewall_axiod), + .axiov(aggregate_axiov), + .axiod(aggregate_axiod)); + + cksum c( + .clk(ethclk), + .rst(rst), + .axiiv(ether_axiov), + .axiid(ether_axiod), + .done(cksum_done), + .kill(cksum_kill)); + + initial begin + ethclk = 0; + $dumpfile("mac_tx_tb.vcd"); + $dumpvars(0, mac_tx_tb); + rst = 0; + start = 0; + #10; + rst = 1; + #10; + rst = 0; + #10; + enable = 1; + #500; + start = 1; + #10; + start = 0; + + #5000; + + $finish(); + end + +endmodule +`default_nettype wire \ No newline at end of file diff --git a/examples/nexys_a7/ethernet_logic_analyzer/src/mac_tx.v b/examples/nexys_a7/ethernet_logic_analyzer/src/mac_tx.v new file mode 100644 index 0000000..8ef8edd --- /dev/null +++ b/examples/nexys_a7/ethernet_logic_analyzer/src/mac_tx.v @@ -0,0 +1,161 @@ +`default_nettype none +`timescale 1ns/1ps + +module mac_tx( + input wire clk, + + input wire [15:0] data, + input wire start, + + output reg txen, + output reg [1:0] txd + ); + + /* + ok so how's this going to work: + what goes on the line is either the fcs, or everything else after being routed through bitorder + + we keep the counter, once it gets to some value then we'll flip the switch and talk to the FCS + + so then we mux between: + - the fixed portion ahead of the payload (prepayload) + - the payload, which is some register + - the zero padding, which is of some length that's parameterized + - the FCS, which DOES NOT GO THROUGH BITORDER + + */ + + + localparam PREAMBLE = {7{8'b01010101}}; + localparam SFD = 8'b11010101; + parameter SRC_MAC = 48'h00_00_00_00_00_00; + parameter DST_MAC = 48'hFF_FF_FF_FF_FF_FF; + parameter LENGTH = 16'h1234; + localparam FCS_DATA = 32'b01001110_00010000_01011001_10011010; + + localparam PREPAYLOAD_DATA = {PREAMBLE, SFD, DST_MAC, SRC_MAC, LENGTH}; + + // all lengths are in units of dibits, hence all the mulitplies by four + localparam PREPAYLOAD_LEN = (7 + 1 + 6 + 6 + 2) * 4; // in dibits + // localparam PAYLOAD_LEN = LENGTH * 4; + localparam PAYLOAD_LEN = 2 * 4; + localparam ZERO_PAD_LEN = (46 * 4) - PAYLOAD_LEN ; // minimum payload size is 46 bytes + localparam FCS_LEN = 4*4; + localparam IPG_LEN = 96/2; + + // state machine + reg [8:0] counter = 0; + reg [2:0] state = 0; + localparam IDLE = 0; + localparam PREPAYLOAD = 1; + localparam PAYLOAD = 2; + localparam ZERO_PAD = 3; + localparam FCS = 4; + localparam IPG = 5; + + reg prev_start; + always @(posedge clk) prev_start <= start; + + reg rst = 1; + always @(posedge clk) rst <= 0; + + + reg bitorder_axiiv; + reg [1:0] bitorder_axiid; + + bitorder b( + .clk(clk), + .rst(rst), + .axiiv(bitorder_axiiv), + .axiid(bitorder_axiid), + .axiov(txen), + .axiod(txd)); + + reg crc_axiiv = 0; + reg crc_axiov; + reg [31:0] crc_axiod; + crc32 crc( + .clk(clk), + .rst(rst), + + .axiiv(crc_axiiv), + .axiid(txd), + + .axiov(crc_axiov), + .axiod(crc_axiod)); + + always @(posedge clk) begin + + // idle state + if (state == IDLE) begin + bitorder_axiiv <= 0; + bitorder_axiid <= 0; + + if(start && ~prev_start) state <= PREPAYLOAD; + counter <= 0; + end + + // everything before the payload (preamble, sfd, dst mac, src mac, length) + else if (state == PREPAYLOAD) begin + bitorder_axiiv <= 1; + bitorder_axiid <= PREPAYLOAD_DATA[2*(PREPAYLOAD_LEN-counter)-1-:2]; + + if(counter == 36) crc_axiiv <= 1; + + counter <= counter + 1; + if(counter == PREPAYLOAD_LEN - 1) begin + counter <= 0; + state <= PAYLOAD; + end + end + + // the payload itself + else if (state == PAYLOAD) begin + $display(2*(PAYLOAD_LEN-counter)-2); + bitorder_axiid <= data[2*(PAYLOAD_LEN-counter)-1-:2]; + + counter <= counter + 1; + if(counter == PAYLOAD_LEN - 1) begin + counter <= 0; + state <= ZERO_PAD; + end + end + + // zero padding + else if (state == ZERO_PAD) begin + bitorder_axiid <= 2'b00; + + counter <= counter + 1; + if(counter == ZERO_PAD_LEN - 1) begin + counter <= 0; + state <= FCS; + end + end + + + // readout fcs from the checksum module + else if (state == FCS) begin + bitorder_axiiv <= 1; + bitorder_axiid <= FCS_DATA[2*(FCS_LEN-counter)-1-:2]; + + counter <= counter + 1; + if(counter == FCS_LEN - 1) begin + counter <= 0; + state <= IPG; + end + end + + // interpacket gap + else if (state == IPG) begin + bitorder_axiiv <= 0; + bitorder_axiid <= 2'b00; + + counter <= counter + 1; + if (counter == IPG_LEN - 1) begin + counter <= 0; + state <= IDLE; + end + end + end +endmodule +`default_nettype wire \ No newline at end of file