diff --git a/src/eth/eth_mac.v b/src/eth/eth_mac.v index d4caba8..4740077 100644 --- a/src/eth/eth_mac.v +++ b/src/eth/eth_mac.v @@ -44,6 +44,7 @@ rmii_clock_generator #( wire tx_wrt; wire tx_not_full; wire transmitter_busy; +wire [MEM_DATA_WIDTH-1:0] tx_data_in; rmii_transmit_controller #( .STORAGE_WIDTH(MEM_DATA_WIDTH) @@ -53,7 +54,7 @@ rmii_transmit_controller #( .clear(clear), .REF_pulse(REF_pulse), - .data_in(mem_data), + .data_in(tx_data_in), .wrt(tx_wrt), .not_full(tx_not_full), .busy(transmitter_busy), @@ -85,7 +86,7 @@ mac_memory_access_controller #( .frame_len(frame_len), .busy(mem_acc_busy), - .tx_data_in(), + .tx_data_in(tx_data_in), .tx_not_full(tx_not_full), .tx_wrt(tx_wrt) ); diff --git a/src/eth/mac_memory_access_controller.v b/src/eth/mac_memory_access_controller.v index a1c177c..73ff806 100644 --- a/src/eth/mac_memory_access_controller.v +++ b/src/eth/mac_memory_access_controller.v @@ -1,5 +1,7 @@ `timescale 1ns / 1ps +`include "src/eth/crc32.v" + module mac_memory_access_controller #( parameter DATA_WIDTH = 8, parameter ADDR_WIDTH = 12, @@ -21,24 +23,50 @@ module mac_memory_access_controller #( output busy, // a frame is currently being processed and transmitted - output [DATA_MSB:0] tx_data_in, // data input for the transmitter block + output reg [DATA_MSB:0] tx_data_in, // data input for the transmitter block input tx_not_full, // transmitter block supports storing new blocks of data output tx_wrt // issue a write onto the transmitter block ); +// -------------- + +wire clear_crc = (state != FETCH_FRAME); +wire crc_en; +wire [31:0] crc_out; + +crc32 crc32_engine ( + .clk(clk), + .rst(rst), + .clear(clear_crc | clear), + + .data_in(mem_data), + .crc_en(crc_en), + .crc_out(crc_out) +); + +// -------------- + wire rstclr = rst | clear; // state machine states localparam IDLE = 0; -localparam FETCH_FRAME = 1; -localparam WAIT_TX_COMPL = 2; +localparam INSERT_PREAMBLE = 1; +localparam FETCH_FRAME = 2; +localparam APPEND_CRC = 3; +localparam WAIT_TX_COMPL = 4; // main state machine -reg [1:0] state; +reg [2:0] state; wire frame_params_valid = frame_len != 0; // frame setup and transmission -reg [LEN_MSB:0] len_left; +localparam PREAMBLE_PATTERN = 8'h55; // Ethernet preamble pattern +localparam SOF_PATTERN = 8'h56; // Ethernet Start-of-Frame pattern +localparam PREAMBLE_LEN = 8; // length of the frame preamble +reg [2:0] preamble_idx; // index of the preamble byte being sent +reg [1:0] crc_idx; // index of the CRC bytes + +reg [LEN_MSB:0] len_left; // remaining bytes to be transmitted always @(posedge clk) begin @@ -48,6 +76,8 @@ begin //tx_wrt <= 0; mem_addr <= 0; len_left <= 0; + preamble_idx <= 0; + crc_idx <= 0; end else begin @@ -56,23 +86,35 @@ begin begin mem_addr <= frame_addr; len_left <= frame_len - 1; + preamble_idx <= 0; + crc_idx <= 0; + end + + INSERT_PREAMBLE: + begin + if (tx_not_full) + begin + preamble_idx <= preamble_idx + 1; + end end FETCH_FRAME: begin if (len_left != 0) - begin - //tx_wrt <= 1; - + begin if (tx_not_full) begin mem_addr <= mem_addr + 1; len_left <= len_left - 1; end end - else + end + + APPEND_CRC: + begin + if (tx_not_full) begin - //tx_wrt <= 0; + crc_idx <= cdc_idx + 1; end end @@ -82,8 +124,10 @@ begin // next state logic case (state) - IDLE: if (start && frame_params_valid) state <= FETCH_FRAME; - FETCH_FRAME: if ((len_left == 0) && tx_not_full) state <= WAIT_TX_COMPL; + IDLE: if (start && frame_params_valid) state <= INSERT_PREAMBLE; + INSERT_PREAMBLE: if (preamble_idx == (PREAMBLE_LEN - 1)) state <= FETCH_FRAME; + FETCH_FRAME: if ((len_left == 0) && tx_not_full) state <= APPEND_CRC; + APPEND_CRC: if (crc_idx == (3)) state <= WAIT_TX_COMPL; WAIT_TX_COMPL: if (!transmitter_busy) state <= IDLE; default: state <= IDLE; endcase @@ -92,7 +136,23 @@ end // combinatorial outputs assign busy = (state != IDLE); -assign tx_data_in = mem_data; -assign tx_wrt = (state == FETCH_FRAME); +//assign tx_data_in = mem_data; +assign tx_wrt = (state == FETCH_FRAME) || (state == INSERT_PREAMBLE); + +// assign data output +always @(*) +begin + case (state) + INSERT_PREAMBLE: tx_data_in <= (preamble_idx == (PREAMBLE_LEN - 1)) ? SOF_PATTERN : PREAMBLE_PATTERN; + APPEND_CRC: + case (crc_idx) + 2'd0: tx_data_in <= crc_out[31:24]; + 2'd1: tx_data_in <= crc_out[23:16]; + 2'd2: tx_data_in <= crc_out[15:8]; + default: tx_data_in <= crc_out[7:0]; + endcase + default: tx_data_in <= mem_data; + endcase +end endmodule