OpenCores
URL https://opencores.org/ocsvn/minimac/minimac/trunk

Subversion Repositories minimac

[/] [minimac/] [trunk/] [minimac.tar] - Diff between revs 2 and 3

Only display areas with differences | Details | Blame | View Log

Rev 2 Rev 3
minimac/0000755000175000017500000000000011411201677012657 5ustar  lekernellekernelminimac/rtl/0000755000175000017500000000000011411201677013460 5ustar  lekernellekernelminimac/rtl/minimac_txfifo.v0000644000175000017500000000461511422254233016647 0ustar  lekernellekernel/*
minimac/0000755000175000017500000000000011411201677012657 5ustar  lekernellekernelminimac/rtl/0000755000175000017500000000000011411201677013460 5ustar  lekernellekernelminimac/rtl/minimac_txfifo.v0000644000175000017500000000461511422254233016647 0ustar  lekernellekernel/*
 * Milkymist VJ SoC
 * Milkymist VJ SoC
 * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
 * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
 *
 *
 * This program is free software: you can redistribute it and/or modify
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, version 3 of the License.
 * the Free Software Foundation, version 3 of the License.
 *
 *
 * This program is distributed in the hope that it will be useful,
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * GNU General Public License for more details.
 *
 *
 * You should have received a copy of the GNU General Public License
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see .
 * along with this program.  If not, see .
 */
 */
module minimac_txfifo(
module minimac_txfifo(
        input sys_clk,
        input sys_clk,
        input tx_rst,
        input tx_rst,
        input stb,
        input stb,
        input [7:0] data,
        input [7:0] data,
        output full,
        output full,
        input can_tx,
        input can_tx,
        output reg empty,
        output reg empty,
        input phy_tx_clk,
        input phy_tx_clk,
        output reg phy_tx_en,
        output reg phy_tx_en,
        output reg [3:0] phy_tx_data
        output reg [3:0] phy_tx_data
);
);
wire [7:0] fifo_out;
wire [7:0] fifo_out;
wire fifo_empty;
wire fifo_empty;
reg fifo_read;
reg fifo_read;
reg empty2;
reg empty2;
always @(posedge sys_clk) begin
always @(posedge sys_clk) begin
        empty2 <= fifo_empty;
        empty2 <= fifo_empty;
        empty <= empty2;
        empty <= empty2;
end
end
asfifo #(
asfifo #(
        .data_width(8),
        .data_width(8),
        .address_width(7)
        .address_width(7)
) fifo (
) fifo (
        .data_out(fifo_out),
        .data_out(fifo_out),
        .empty(fifo_empty),
        .empty(fifo_empty),
        .read_en(fifo_read),
        .read_en(fifo_read),
        .clk_read(phy_tx_clk),
        .clk_read(phy_tx_clk),
        .data_in(data),
        .data_in(data),
        .full(full),
        .full(full),
        .write_en(stb),
        .write_en(stb),
        .clk_write(sys_clk),
        .clk_write(sys_clk),
        .rst(tx_rst)
        .rst(tx_rst)
);
);
reg can_tx1;
reg can_tx1;
reg can_tx2;
reg can_tx2;
always @(posedge phy_tx_clk) begin
always @(posedge phy_tx_clk) begin
        can_tx1 <= can_tx;
        can_tx1 <= can_tx;
        can_tx2 <= can_tx1;
        can_tx2 <= can_tx1;
end
end
reg tx_rst1;
reg tx_rst1;
reg tx_rst2;
reg tx_rst2;
always @(posedge phy_tx_clk) begin
always @(posedge phy_tx_clk) begin
        tx_rst1 <= tx_rst;
        tx_rst1 <= tx_rst;
        tx_rst2 <= tx_rst1;
        tx_rst2 <= tx_rst1;
end
end
wire interframe_gap;
wire interframe_gap;
wire transmitting = can_tx2 & ~fifo_empty & ~interframe_gap;
wire transmitting = can_tx2 & ~fifo_empty & ~interframe_gap;
reg transmitting_r;
reg transmitting_r;
always @(posedge phy_tx_clk)
always @(posedge phy_tx_clk)
        transmitting_r <= transmitting;
        transmitting_r <= transmitting;
reg [4:0] interframe_counter;
reg [4:0] interframe_counter;
always @(posedge phy_tx_clk) begin
always @(posedge phy_tx_clk) begin
        if(tx_rst2)
        if(tx_rst2)
                interframe_counter <= 5'd0;
                interframe_counter <= 5'd0;
        else begin
        else begin
                if(transmitting_r & ~transmitting)
                if(transmitting_r & ~transmitting)
                        interframe_counter <= 5'd24;
                        interframe_counter <= 5'd24;
                else if(interframe_counter != 5'd0)
                else if(interframe_counter != 5'd0)
                        interframe_counter <= interframe_counter - 5'd1;
                        interframe_counter <= interframe_counter - 5'd1;
        end
        end
end
end
assign interframe_gap = |interframe_counter;
assign interframe_gap = |interframe_counter;
reg hi_nibble;
reg hi_nibble;
always @(posedge phy_tx_clk) begin
always @(posedge phy_tx_clk) begin
        if(tx_rst2) begin
        if(tx_rst2) begin
                hi_nibble <= 1'b0;
                hi_nibble <= 1'b0;
                phy_tx_en <= 1'b0;
                phy_tx_en <= 1'b0;
        end else begin
        end else begin
                hi_nibble <= 1'b0;
                hi_nibble <= 1'b0;
                phy_tx_en <= 1'b0;
                phy_tx_en <= 1'b0;
                fifo_read <= 1'b0;
                fifo_read <= 1'b0;
                if(transmitting) begin
                if(transmitting) begin
                        phy_tx_en <= 1'b1;
                        phy_tx_en <= 1'b1;
                        if(~hi_nibble) begin
                        if(~hi_nibble) begin
                                phy_tx_data <= fifo_out[3:0];
                                phy_tx_data <= fifo_out[3:0];
                                fifo_read <= 1'b1;
                                fifo_read <= 1'b1;
                                hi_nibble <= 1'b1;
                                hi_nibble <= 1'b1;
                        end else begin
                        end else begin
                                phy_tx_data <= fifo_out[7:4];
                                phy_tx_data <= fifo_out[7:4];
                                hi_nibble <= 1'b0;
                                hi_nibble <= 1'b0;
                        end
                        end
                end
                end
        end
        end
end
end
endmodule
endmodule
minimac/rtl/minimac_tx.v0000644000175000017500000000747111422254272016011 0ustar  lekernellekernel/*
minimac/rtl/minimac_tx.v0000644000175000017500000000747111422254272016011 0ustar  lekernellekernel/*
 * Milkymist VJ SoC
 * Milkymist VJ SoC
 * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
 * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
 *
 *
 * This program is free software: you can redistribute it and/or modify
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, version 3 of the License.
 * the Free Software Foundation, version 3 of the License.
 *
 *
 * This program is distributed in the hope that it will be useful,
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * GNU General Public License for more details.
 *
 *
 * You should have received a copy of the GNU General Public License
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see .
 * along with this program.  If not, see .
 */
 */
module minimac_tx(
module minimac_tx(
        input sys_clk,
        input sys_clk,
        input sys_rst,
        input sys_rst,
        input tx_rst,
        input tx_rst,
        input tx_valid,
        input tx_valid,
        input [29:0] tx_adr,
        input [29:0] tx_adr,
        input [1:0] tx_bytecount,
        input [1:0] tx_bytecount,
        output reg tx_next,
        output reg tx_next,
        output [31:0] wbtx_adr_o,
        output [31:0] wbtx_adr_o,
        output wbtx_cyc_o,
        output wbtx_cyc_o,
        output wbtx_stb_o,
        output wbtx_stb_o,
        input wbtx_ack_i,
        input wbtx_ack_i,
        input [31:0] wbtx_dat_i,
        input [31:0] wbtx_dat_i,
        input phy_tx_clk,
        input phy_tx_clk,
        output phy_tx_en,
        output phy_tx_en,
        output [3:0] phy_tx_data
        output [3:0] phy_tx_data
);
);
reg bus_stb;
reg bus_stb;
assign wbtx_cyc_o = bus_stb;
assign wbtx_cyc_o = bus_stb;
assign wbtx_stb_o = bus_stb;
assign wbtx_stb_o = bus_stb;
assign wbtx_adr_o = {tx_adr, 2'd0};
assign wbtx_adr_o = {tx_adr, 2'd0};
reg stb;
reg stb;
reg [7:0] data;
reg [7:0] data;
wire full;
wire full;
reg can_tx;
reg can_tx;
wire empty;
wire empty;
minimac_txfifo txfifo(
minimac_txfifo txfifo(
        .sys_clk(sys_clk),
        .sys_clk(sys_clk),
        .tx_rst(tx_rst),
        .tx_rst(tx_rst),
        .stb(stb),
        .stb(stb),
        .data(data),
        .data(data),
        .full(full),
        .full(full),
        .can_tx(can_tx),
        .can_tx(can_tx),
        .empty(empty),
        .empty(empty),
        .phy_tx_clk(phy_tx_clk),
        .phy_tx_clk(phy_tx_clk),
        .phy_tx_en(phy_tx_en),
        .phy_tx_en(phy_tx_en),
        .phy_tx_data(phy_tx_data)
        .phy_tx_data(phy_tx_data)
);
);
reg load_input;
reg load_input;
reg [31:0] input_reg;
reg [31:0] input_reg;
always @(posedge sys_clk)
always @(posedge sys_clk)
        if(load_input)
        if(load_input)
                input_reg <= wbtx_dat_i;
                input_reg <= wbtx_dat_i;
always @(*) begin
always @(*) begin
        case(tx_bytecount)
        case(tx_bytecount)
                2'd0: data = input_reg[31:24];
                2'd0: data = input_reg[31:24];
                2'd1: data = input_reg[23:16];
                2'd1: data = input_reg[23:16];
                2'd2: data = input_reg[16: 8];
                2'd2: data = input_reg[16: 8];
                2'd3: data = input_reg[ 7: 0];
                2'd3: data = input_reg[ 7: 0];
        endcase
        endcase
end
end
wire firstbyte = tx_bytecount == 2'd0;
wire firstbyte = tx_bytecount == 2'd0;
reg purge;
reg purge;
/* fetch FSM */
/* fetch FSM */
reg [1:0] state;
reg [1:0] state;
reg [1:0] next_state;
reg [1:0] next_state;
parameter IDLE  = 2'd0;
parameter IDLE  = 2'd0;
parameter FETCH = 2'd1;
parameter FETCH = 2'd1;
parameter WRITE1 = 2'd2;
parameter WRITE1 = 2'd2;
always @(posedge sys_clk) begin
always @(posedge sys_clk) begin
        if(sys_rst)
        if(sys_rst)
                state <= IDLE;
                state <= IDLE;
        else
        else
                state <= next_state;
                state <= next_state;
end
end
always @(*) begin
always @(*) begin
        next_state = state;
        next_state = state;
        load_input = 1'b0;
        load_input = 1'b0;
        tx_next = 1'b0;
        tx_next = 1'b0;
        stb = 1'b0;
        stb = 1'b0;
        bus_stb = 1'b0;
        bus_stb = 1'b0;
        case(state)
        case(state)
                IDLE: begin
                IDLE: begin
                        if(tx_valid & ~full & ~purge) begin
                        if(tx_valid & ~full & ~purge) begin
                                if(firstbyte)
                                if(firstbyte)
                                        next_state = FETCH;
                                        next_state = FETCH;
                                else begin
                                else begin
                                        stb = 1'b1;
                                        stb = 1'b1;
                                        tx_next = 1'b1;
                                        tx_next = 1'b1;
                                end
                                end
                        end
                        end
                end
                end
                FETCH: begin
                FETCH: begin
                        bus_stb = 1'b1;
                        bus_stb = 1'b1;
                        load_input = 1'b1;
                        load_input = 1'b1;
                        if(wbtx_ack_i)
                        if(wbtx_ack_i)
                                next_state = WRITE1;
                                next_state = WRITE1;
                end
                end
                WRITE1: begin
                WRITE1: begin
                        stb = 1'b1;
                        stb = 1'b1;
                        tx_next = 1'b1;
                        tx_next = 1'b1;
                        next_state = IDLE;
                        next_state = IDLE;
                end
                end
        endcase
        endcase
end
end
/* Byte counter */
/* Byte counter */
reg reset_byte_counter;
reg reset_byte_counter;
reg [6:0] byte_counter;
reg [6:0] byte_counter;
always @(posedge sys_clk) begin
always @(posedge sys_clk) begin
        if(sys_rst)
        if(sys_rst)
                byte_counter <= 7'd0;
                byte_counter <= 7'd0;
        else begin
        else begin
                if(reset_byte_counter)
                if(reset_byte_counter)
                        byte_counter <= 7'd0;
                        byte_counter <= 7'd0;
                else if(stb)
                else if(stb)
                        byte_counter <= byte_counter + 7'd1;
                        byte_counter <= byte_counter + 7'd1;
        end
        end
end
end
wire tx_level_reached = byte_counter[6];
wire tx_level_reached = byte_counter[6];
/* FIFO control FSM */
/* FIFO control FSM */
reg [1:0] fstate;
reg [1:0] fstate;
reg [1:0] next_fstate;
reg [1:0] next_fstate;
parameter FIDLE         = 2'd0;
parameter FIDLE         = 2'd0;
parameter FWAITFULL     = 2'd1;
parameter FWAITFULL     = 2'd1;
parameter FTX           = 2'd2;
parameter FTX           = 2'd2;
parameter FPURGE        = 2'd3;
parameter FPURGE        = 2'd3;
always @(posedge sys_clk) begin
always @(posedge sys_clk) begin
        if(sys_rst)
        if(sys_rst)
                fstate <= FIDLE;
                fstate <= FIDLE;
        else
        else
                fstate <= next_fstate;
                fstate <= next_fstate;
end
end
always @(*) begin
always @(*) begin
        next_fstate = fstate;
        next_fstate = fstate;
        can_tx = 1'b0;
        can_tx = 1'b0;
        purge = 1'b0;
        purge = 1'b0;
        reset_byte_counter = 1'b1;
        reset_byte_counter = 1'b1;
        case(fstate)
        case(fstate)
                FIDLE: begin
                FIDLE: begin
                        if(tx_valid)
                        if(tx_valid)
                                next_fstate = FWAITFULL;
                                next_fstate = FWAITFULL;
                end
                end
                /* Wait for the FIFO to fill to 64 bytes (< ethernet minimum of 72)
                /* Wait for the FIFO to fill to 64 bytes (< ethernet minimum of 72)
                 * before starting transmission. */
                 * before starting transmission. */
                FWAITFULL: begin
                FWAITFULL: begin
                        reset_byte_counter = 1'b0;
                        reset_byte_counter = 1'b0;
                        if(tx_level_reached)
                        if(tx_level_reached)
                                next_fstate = FTX;
                                next_fstate = FTX;
                end
                end
                FTX: begin
                FTX: begin
                        can_tx = 1'b1;
                        can_tx = 1'b1;
                        if(~tx_valid) begin
                        if(~tx_valid) begin
                                purge = 1'b1;
                                purge = 1'b1;
                                next_fstate = FPURGE;
                                next_fstate = FPURGE;
                        end
                        end
                end
                end
                FPURGE: begin
                FPURGE: begin
                        can_tx = 1'b1;
                        can_tx = 1'b1;
                        purge = 1'b1;
                        purge = 1'b1;
                        if(empty)
                        if(empty)
                                next_fstate = FIDLE;
                                next_fstate = FIDLE;
                        /* NB! there is a potential bug because of the latency
                        /* NB! there is a potential bug because of the latency
                         * introducted by the synchronizer on can_tx in txfifo.
                         * introducted by the synchronizer on can_tx in txfifo.
                         * However, the interframe gap prevents it to happen
                         * However, the interframe gap prevents it to happen
                         * unless f(sys_clk) >> f(phy_tx_clk).
                         * unless f(sys_clk) >> f(phy_tx_clk).
                         */
                         */
                end
                end
        endcase
        endcase
end
end
endmodule
endmodule
minimac/rtl/minimac_rxfifo.v0000644000175000017500000000522111422254230016634 0ustar  lekernellekernel/*
minimac/rtl/minimac_rxfifo.v0000644000175000017500000000522111422254230016634 0ustar  lekernellekernel/*
 * Milkymist VJ SoC
 * Milkymist VJ SoC
 * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
 * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
 *
 *
 * This program is free software: you can redistribute it and/or modify
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, version 3 of the License.
 * the Free Software Foundation, version 3 of the License.
 *
 *
 * This program is distributed in the hope that it will be useful,
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * GNU General Public License for more details.
 *
 *
 * You should have received a copy of the GNU General Public License
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see .
 * along with this program.  If not, see .
 */
 */
module minimac_rxfifo(
module minimac_rxfifo(
        input sys_clk,
        input sys_clk,
        input rx_rst,
        input rx_rst,
        input phy_rx_clk,
        input phy_rx_clk,
        input [3:0] phy_rx_data,
        input [3:0] phy_rx_data,
        input phy_dv,
        input phy_dv,
        input phy_rx_er,
        input phy_rx_er,
        output empty,
        output empty,
        input ack,
        input ack,
        output eof,
        output eof,
        output [7:0] data,
        output [7:0] data,
        output reg fifo_full
        output reg fifo_full
);
);
/*
/*
 * EOF = 0              frame data
 * EOF = 0              frame data
 * EOF = 1, data[0] = 0 frame completed without errors
 * EOF = 1, data[0] = 0 frame completed without errors
 * EOF = 1, data[0] = 1 frame completed with errors
 * EOF = 1, data[0] = 1 frame completed with errors
 */
 */
wire [8:0] fifo_out;
wire [8:0] fifo_out;
assign eof = fifo_out[8];
assign eof = fifo_out[8];
assign data = fifo_out[7:0];
assign data = fifo_out[7:0];
reg fifo_eof;
reg fifo_eof;
reg [3:0] fifo_hi;
reg [3:0] fifo_hi;
reg [3:0] fifo_lo;
reg [3:0] fifo_lo;
wire [8:0] fifo_in = {fifo_eof, fifo_hi, fifo_lo};
wire [8:0] fifo_in = {fifo_eof, fifo_hi, fifo_lo};
reg fifo_we;
reg fifo_we;
wire full;
wire full;
asfifo #(
asfifo #(
        .data_width(9),
        .data_width(9),
        .address_width(7)
        .address_width(7)
) fifo (
) fifo (
        .data_out(fifo_out),
        .data_out(fifo_out),
        .empty(empty),
        .empty(empty),
        .read_en(ack),
        .read_en(ack),
        .clk_read(sys_clk),
        .clk_read(sys_clk),
        .data_in(fifo_in),
        .data_in(fifo_in),
        .full(full),
        .full(full),
        .write_en(fifo_we),
        .write_en(fifo_we),
        .clk_write(phy_rx_clk),
        .clk_write(phy_rx_clk),
        .rst(rx_rst)
        .rst(rx_rst)
);
);
/* we assume f(sys_clk) > f(phy_rx_clk) */
/* we assume f(sys_clk) > f(phy_rx_clk) */
reg fifo_full1;
reg fifo_full1;
always @(posedge sys_clk) begin
always @(posedge sys_clk) begin
        fifo_full1 <= full;
        fifo_full1 <= full;
        fifo_full <= fifo_full1;
        fifo_full <= fifo_full1;
end
end
reg rx_rst1;
reg rx_rst1;
reg rx_rst2;
reg rx_rst2;
always @(posedge phy_rx_clk) begin
always @(posedge phy_rx_clk) begin
        rx_rst1 <= rx_rst;
        rx_rst1 <= rx_rst;
        rx_rst2 <= rx_rst1;
        rx_rst2 <= rx_rst1;
end
end
reg hi_nibble;
reg hi_nibble;
reg abort;
reg abort;
reg phy_dv_r;
reg phy_dv_r;
always @(posedge phy_rx_clk) begin
always @(posedge phy_rx_clk) begin
        if(rx_rst2) begin
        if(rx_rst2) begin
                fifo_we <= 1'b0;
                fifo_we <= 1'b0;
                fifo_eof <= 1'b0;
                fifo_eof <= 1'b0;
                fifo_hi <= 4'd0;
                fifo_hi <= 4'd0;
                fifo_lo <= 4'd0;
                fifo_lo <= 4'd0;
                hi_nibble <= 1'b0;
                hi_nibble <= 1'b0;
                abort <= 1'b0;
                abort <= 1'b0;
                phy_dv_r <= 1'b0;
                phy_dv_r <= 1'b0;
        end else begin
        end else begin
                fifo_eof <= 1'b0;
                fifo_eof <= 1'b0;
                fifo_we <= 1'b0;
                fifo_we <= 1'b0;
                /* Transfer data */
                /* Transfer data */
                if(~abort) begin
                if(~abort) begin
                        if(~hi_nibble) begin
                        if(~hi_nibble) begin
                                fifo_lo <= phy_rx_data;
                                fifo_lo <= phy_rx_data;
                                if(phy_dv)
                                if(phy_dv)
                                        hi_nibble <= 1'b1;
                                        hi_nibble <= 1'b1;
                        end else begin
                        end else begin
                                fifo_hi <= phy_rx_data;
                                fifo_hi <= phy_rx_data;
                                fifo_we <= 1'b1;
                                fifo_we <= 1'b1;
                                hi_nibble <= 1'b0;
                                hi_nibble <= 1'b0;
                        end
                        end
                end
                end
                /* Detect error events */
                /* Detect error events */
                if(phy_dv & phy_rx_er) begin
                if(phy_dv & phy_rx_er) begin
                        fifo_eof <= 1'b1;
                        fifo_eof <= 1'b1;
                        fifo_hi <= 4'd0;
                        fifo_hi <= 4'd0;
                        fifo_lo <= 4'd1;
                        fifo_lo <= 4'd1;
                        fifo_we <= 1'b1;
                        fifo_we <= 1'b1;
                        abort <= 1'b1;
                        abort <= 1'b1;
                        hi_nibble <= 1'b0;
                        hi_nibble <= 1'b0;
                end
                end
                /* Detect end of frame */
                /* Detect end of frame */
                phy_dv_r <= phy_dv;
                phy_dv_r <= phy_dv;
                if(phy_dv_r & ~phy_dv) begin
                if(phy_dv_r & ~phy_dv) begin
                        if(~abort) begin
                        if(~abort) begin
                                fifo_eof <= 1'b1;
                                fifo_eof <= 1'b1;
                                fifo_hi <= 4'd0;
                                fifo_hi <= 4'd0;
                                fifo_lo <= 4'd0;
                                fifo_lo <= 4'd0;
                                fifo_we <= 1'b1;
                                fifo_we <= 1'b1;
                        end
                        end
                        abort <= 1'b0;
                        abort <= 1'b0;
                        hi_nibble <= 1'b0;
                        hi_nibble <= 1'b0;
                end
                end
        end
        end
end
end
endmodule
endmodule
minimac/rtl/minimac_ctlif.v0000644000175000017500000001347211422301322016442 0ustar  lekernellekernel/*
minimac/rtl/minimac_ctlif.v0000644000175000017500000001347211422301322016442 0ustar  lekernellekernel/*
 * Milkymist VJ SoC
 * Milkymist VJ SoC
 * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
 * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
 *
 *
 * This program is free software: you can redistribute it and/or modify
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, version 3 of the License.
 * the Free Software Foundation, version 3 of the License.
 *
 *
 * This program is distributed in the hope that it will be useful,
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * GNU General Public License for more details.
 *
 *
 * You should have received a copy of the GNU General Public License
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see .
 * along with this program.  If not, see .
 */
 */
module minimac_ctlif #(
module minimac_ctlif #(
        parameter csr_addr = 4'h0
        parameter csr_addr = 4'h0
) (
) (
        input sys_clk,
        input sys_clk,
        input sys_rst,
        input sys_rst,
        input [13:0] csr_a,
        input [13:0] csr_a,
        input csr_we,
        input csr_we,
        input [31:0] csr_di,
        input [31:0] csr_di,
        output reg [31:0] csr_do,
        output reg [31:0] csr_do,
        output reg irq_rx,
        output reg irq_rx,
        output reg irq_tx,
        output reg irq_tx,
        output reg rx_rst,
        output reg rx_rst,
        output reg tx_rst,
        output reg tx_rst,
        output rx_valid,
        output rx_valid,
        output [29:0] rx_adr,
        output [29:0] rx_adr,
        input rx_resetcount,
        input rx_resetcount,
        input rx_incrcount,
        input rx_incrcount,
        input rx_endframe,
        input rx_endframe,
        input fifo_full,
        input fifo_full,
        output tx_valid,
        output tx_valid,
        output reg [29:0] tx_adr,
        output reg [29:0] tx_adr,
        output reg [1:0] tx_bytecount,
        output reg [1:0] tx_bytecount,
        input tx_next,
        input tx_next,
        output reg phy_mii_clk,
        output reg phy_mii_clk,
        inout phy_mii_data
        inout phy_mii_data
);
);
reg mii_data_oe;
reg mii_data_oe;
reg mii_data_do;
reg mii_data_do;
assign phy_mii_data = mii_data_oe ? mii_data_do : 1'bz;
assign phy_mii_data = mii_data_oe ? mii_data_do : 1'bz;
/* Be paranoid about metastability */
/* Be paranoid about metastability */
reg mii_data_di1;
reg mii_data_di1;
reg mii_data_di;
reg mii_data_di;
always @(posedge sys_clk) begin
always @(posedge sys_clk) begin
        mii_data_di1 <= phy_mii_data;
        mii_data_di1 <= phy_mii_data;
        mii_data_di <= mii_data_di1;
        mii_data_di <= mii_data_di1;
end
end
/*
/*
 * RX Slots
 * RX Slots
 *
 *
 * State:
 * State:
 * 00 -> slot is not in use
 * 00 -> slot is not in use
 * 01 -> slot has been loaded with a buffer
 * 01 -> slot has been loaded with a buffer
 * 10 -> slot has received a packet
 * 10 -> slot has received a packet
 * 11 -> invalid
 * 11 -> invalid
 */
 */
reg [1:0] slot0_state;
reg [1:0] slot0_state;
reg [29:0] slot0_adr;
reg [29:0] slot0_adr;
reg [10:0] slot0_count;
reg [10:0] slot0_count;
reg [1:0] slot1_state;
reg [1:0] slot1_state;
reg [29:0] slot1_adr;
reg [29:0] slot1_adr;
reg [10:0] slot1_count;
reg [10:0] slot1_count;
reg [1:0] slot2_state;
reg [1:0] slot2_state;
reg [29:0] slot2_adr;
reg [29:0] slot2_adr;
reg [10:0] slot2_count;
reg [10:0] slot2_count;
reg [1:0] slot3_state;
reg [1:0] slot3_state;
reg [29:0] slot3_adr;
reg [29:0] slot3_adr;
reg [10:0] slot3_count;
reg [10:0] slot3_count;
wire select0 = slot0_state[0];
wire select0 = slot0_state[0];
wire select1 = slot1_state[0] & ~slot0_state[0];
wire select1 = slot1_state[0] & ~slot0_state[0];
wire select2 = slot2_state[0] & ~slot1_state[0] & ~slot0_state[0];
wire select2 = slot2_state[0] & ~slot1_state[0] & ~slot0_state[0];
wire select3 = slot3_state[0] & ~slot2_state[0] & ~slot1_state[0] & ~slot0_state[0];
wire select3 = slot3_state[0] & ~slot2_state[0] & ~slot1_state[0] & ~slot0_state[0];
assign rx_valid = slot0_state[0] | slot1_state[0] | slot2_state[0] | slot3_state[0];
assign rx_valid = slot0_state[0] | slot1_state[0] | slot2_state[0] | slot3_state[0];
assign rx_adr =  {30{select0}} & slot0_adr
assign rx_adr =  {30{select0}} & slot0_adr
                |{30{select1}} & slot1_adr
                |{30{select1}} & slot1_adr
                |{30{select2}} & slot2_adr
                |{30{select2}} & slot2_adr
                |{30{select3}} & slot3_adr;
                |{30{select3}} & slot3_adr;
/*
/*
 * TX
 * TX
 */
 */
reg [10:0] tx_remaining;
reg [10:0] tx_remaining;
assign tx_valid = |tx_remaining;
assign tx_valid = |tx_remaining;
wire csr_selected = csr_a[13:10] == csr_addr;
wire csr_selected = csr_a[13:10] == csr_addr;
always @(posedge sys_clk) begin
always @(posedge sys_clk) begin
        if(sys_rst) begin
        if(sys_rst) begin
                csr_do <= 32'd0;
                csr_do <= 32'd0;
                rx_rst <= 1'b1;
                rx_rst <= 1'b1;
                tx_rst <= 1'b1;
                tx_rst <= 1'b1;
                mii_data_oe <= 1'b0;
                mii_data_oe <= 1'b0;
                mii_data_do <= 1'b0;
                mii_data_do <= 1'b0;
                phy_mii_clk <= 1'b0;
                phy_mii_clk <= 1'b0;
                slot0_state <= 2'b00;
                slot0_state <= 2'b00;
                slot0_adr <= 30'd0;
                slot0_adr <= 30'd0;
                slot0_count <= 11'd0;
                slot0_count <= 11'd0;
                slot1_state <= 2'b00;
                slot1_state <= 2'b00;
                slot1_adr <= 30'd0;
                slot1_adr <= 30'd0;
                slot1_count <= 11'd0;
                slot1_count <= 11'd0;
                slot2_state <= 2'b00;
                slot2_state <= 2'b00;
                slot2_adr <= 30'd0;
                slot2_adr <= 30'd0;
                slot2_count <= 11'd0;
                slot2_count <= 11'd0;
                slot3_state <= 2'b00;
                slot3_state <= 2'b00;
                slot3_adr <= 30'd0;
                slot3_adr <= 30'd0;
                slot3_count <= 11'd0;
                slot3_count <= 11'd0;
                tx_remaining <= 11'd0;
                tx_remaining <= 11'd0;
                tx_adr <= 30'd0;
                tx_adr <= 30'd0;
                tx_bytecount <= 2'd0;
                tx_bytecount <= 2'd0;
        end else begin
        end else begin
                csr_do <= 32'd0;
                csr_do <= 32'd0;
                if(csr_selected) begin
                if(csr_selected) begin
                        if(csr_we) begin
                        if(csr_we) begin
                                case(csr_a[3:0])
                                case(csr_a[3:0])
                                        4'd0 : begin
                                        4'd0 : begin
                                                tx_rst <= csr_di[1];
                                                tx_rst <= csr_di[1];
                                                rx_rst <= csr_di[0];
                                                rx_rst <= csr_di[0];
                                        end
                                        end
                                        4'd1 : begin
                                        4'd1 : begin
                                                phy_mii_clk <= csr_di[3];
                                                phy_mii_clk <= csr_di[3];
                                                mii_data_oe <= csr_di[2];
                                                mii_data_oe <= csr_di[2];
                                                mii_data_do <= csr_di[0];
                                                mii_data_do <= csr_di[0];
                                        end
                                        end
                                        4'd2 : begin
                                        4'd2 : begin
                                                slot0_state <= csr_di[1:0];
                                                slot0_state <= csr_di[1:0];
                                                slot0_count <= 11'd0;
                                                slot0_count <= 11'd0;
                                        end
                                        end
                                        4'd3 : slot0_adr <= csr_di[31:2];
                                        4'd3 : slot0_adr <= csr_di[31:2];
                                        // slot0_count is read-only
                                        // slot0_count is read-only
                                        4'd5 : begin
                                        4'd5 : begin
                                                slot1_state <= csr_di[1:0];
                                                slot1_state <= csr_di[1:0];
                                                slot1_count <= 11'd0;
                                                slot1_count <= 11'd0;
                                        end
                                        end
                                        4'd6 : slot1_adr <= csr_di[31:2];
                                        4'd6 : slot1_adr <= csr_di[31:2];
                                        // slot1_count is read-only
                                        // slot1_count is read-only
                                        4'd8 : begin
                                        4'd8 : begin
                                                slot2_state <= csr_di[1:0];
                                                slot2_state <= csr_di[1:0];
                                                slot2_count <= 11'd0;
                                                slot2_count <= 11'd0;
                                        end
                                        end
                                        4'd9 : slot2_adr <= csr_di[31:2];
                                        4'd9 : slot2_adr <= csr_di[31:2];
                                        // slot2_count is read-only
                                        // slot2_count is read-only
                                        4'd11: begin
                                        4'd11: begin
                                                slot3_state <= csr_di[1:0];
                                                slot3_state <= csr_di[1:0];
                                                slot3_count <= 11'd0;
                                                slot3_count <= 11'd0;
                                        end
                                        end
                                        4'd12: slot3_adr <= csr_di[31:2];
                                        4'd12: slot3_adr <= csr_di[31:2];
                                        // slot3_count is read-only
                                        // slot3_count is read-only
                                        4'd14: tx_adr <= csr_di[31:2];
                                        4'd14: tx_adr <= csr_di[31:2];
                                        4'd15: begin
                                        4'd15: begin
                                                tx_remaining <= csr_di[10:0];
                                                tx_remaining <= csr_di[10:0];
                                                tx_bytecount <= 2'd0;
                                                tx_bytecount <= 2'd0;
                                        end
                                        end
                                endcase
                                endcase
                        end
                        end
                        case(csr_a[3:0])
                        case(csr_a[3:0])
                                4'd0 : csr_do <= {tx_rst, rx_rst};
                                4'd0 : csr_do <= {tx_rst, rx_rst};
                                4'd1 : csr_do <= {phy_mii_clk, mii_data_oe, mii_data_di, mii_data_do};
                                4'd1 : csr_do <= {phy_mii_clk, mii_data_oe, mii_data_di, mii_data_do};
                                4'd2 : csr_do <= slot0_state;
                                4'd2 : csr_do <= slot0_state;
                                4'd3 : csr_do <= {slot0_adr, 2'd0};
                                4'd3 : csr_do <= {slot0_adr, 2'd0};
                                4'd4 : csr_do <= slot0_count;
                                4'd4 : csr_do <= slot0_count;
                                4'd5 : csr_do <= slot1_state;
                                4'd5 : csr_do <= slot1_state;
                                4'd6 : csr_do <= {slot1_adr, 2'd0};
                                4'd6 : csr_do <= {slot1_adr, 2'd0};
                                4'd7 : csr_do <= slot1_count;
                                4'd7 : csr_do <= slot1_count;
                                4'd8 : csr_do <= slot2_state;
                                4'd8 : csr_do <= slot2_state;
                                4'd9 : csr_do <= {slot2_adr, 2'd0};
                                4'd9 : csr_do <= {slot2_adr, 2'd0};
                                4'd10: csr_do <= slot2_count;
                                4'd10: csr_do <= slot2_count;
                                4'd11: csr_do <= slot3_state;
                                4'd11: csr_do <= slot3_state;
                                4'd12: csr_do <= {slot3_adr, 2'd0};
                                4'd12: csr_do <= {slot3_adr, 2'd0};
                                4'd13: csr_do <= slot3_count;
                                4'd13: csr_do <= slot3_count;
                                4'd14: csr_do <= tx_adr;
                                4'd14: csr_do <= tx_adr;
                                4'd15: csr_do <= tx_remaining;
                                4'd15: csr_do <= tx_remaining;
                        endcase
                        endcase
                end
                end
                if(fifo_full)
                if(fifo_full)
                        rx_rst <= 1'b1;
                        rx_rst <= 1'b1;
                if(rx_resetcount) begin
                if(rx_resetcount) begin
                        if(select0)
                        if(select0)
                                slot0_count <= 11'd0;
                                slot0_count <= 11'd0;
                        if(select1)
                        if(select1)
                                slot1_count <= 11'd0;
                                slot1_count <= 11'd0;
                        if(select2)
                        if(select2)
                                slot2_count <= 11'd0;
                                slot2_count <= 11'd0;
                        if(select3)
                        if(select3)
                                slot3_count <= 11'd0;
                                slot3_count <= 11'd0;
                end
                end
                if(rx_incrcount) begin
                if(rx_incrcount) begin
                        if(select0)
                        if(select0)
                                slot0_count <= slot0_count + 11'd1;
                                slot0_count <= slot0_count + 11'd1;
                        if(select1)
                        if(select1)
                                slot1_count <= slot1_count + 11'd1;
                                slot1_count <= slot1_count + 11'd1;
                        if(select2)
                        if(select2)
                                slot2_count <= slot2_count + 11'd1;
                                slot2_count <= slot2_count + 11'd1;
                        if(select3)
                        if(select3)
                                slot3_count <= slot3_count + 11'd1;
                                slot3_count <= slot3_count + 11'd1;
                end
                end
                if(rx_endframe) begin
                if(rx_endframe) begin
                        if(select0)
                        if(select0)
                                slot0_state <= 2'b10;
                                slot0_state <= 2'b10;
                        if(select1)
                        if(select1)
                                slot1_state <= 2'b10;
                                slot1_state <= 2'b10;
                        if(select2)
                        if(select2)
                                slot2_state <= 2'b10;
                                slot2_state <= 2'b10;
                        if(select3)
                        if(select3)
                                slot3_state <= 2'b10;
                                slot3_state <= 2'b10;
                end
                end
                if(tx_next) begin
                if(tx_next) begin
                        tx_remaining <= tx_remaining - 11'd1;
                        tx_remaining <= tx_remaining - 11'd1;
                        tx_bytecount <= tx_bytecount + 2'd1;
                        tx_bytecount <= tx_bytecount + 2'd1;
                        if(tx_bytecount == 2'd3)
                        if(tx_bytecount == 2'd3)
                                tx_adr <= tx_adr + 30'd1;
                                tx_adr <= tx_adr + 30'd1;
                end
                end
        end
        end
end
end
/* Interrupt logic */
/* Interrupt logic */
reg tx_valid_r;
reg tx_valid_r;
always @(posedge sys_clk) begin
always @(posedge sys_clk) begin
        if(sys_rst) begin
        if(sys_rst) begin
                irq_rx <= 1'b0;
                irq_rx <= 1'b0;
                tx_valid_r <= 1'b0;
                tx_valid_r <= 1'b0;
                irq_tx <= 1'b0;
                irq_tx <= 1'b0;
        end else begin
        end else begin
                irq_rx <= slot0_state[1] | slot1_state[1] | slot2_state[1] | slot3_state[1] | rx_rst;
                irq_rx <= slot0_state[1] | slot1_state[1] | slot2_state[1] | slot3_state[1] | rx_rst;
                tx_valid_r <= tx_valid;
                tx_valid_r <= tx_valid;
                irq_tx <= tx_valid_r & ~tx_valid;
                irq_tx <= tx_valid_r & ~tx_valid;
        end
        end
end
end
endmodule
endmodule
minimac/rtl/minimac.v0000644000175000017500000000607711411201677015276 0ustar  lekernellekernel/*
minimac/rtl/minimac.v0000644000175000017500000000607711411201677015276 0ustar  lekernellekernel/*
 * Milkymist VJ SoC
 * Milkymist VJ SoC
 * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
 * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
 *
 *
 * This program is free software: you can redistribute it and/or modify
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, version 3 of the License.
 * the Free Software Foundation, version 3 of the License.
 *
 *
 * This program is distributed in the hope that it will be useful,
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * GNU General Public License for more details.
 *
 *
 * You should have received a copy of the GNU General Public License
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see .
 * along with this program.  If not, see .
 */
 */
module minimac #(
module minimac #(
        parameter csr_addr = 4'h0
        parameter csr_addr = 4'h0
) (
) (
        input sys_clk,
        input sys_clk,
        input sys_rst,
        input sys_rst,
        input [13:0] csr_a,
        input [13:0] csr_a,
        input csr_we,
        input csr_we,
        input [31:0] csr_di,
        input [31:0] csr_di,
        output [31:0] csr_do,
        output [31:0] csr_do,
        output irq_rx,
        output irq_rx,
        output irq_tx,
        output irq_tx,
        // WE=1 and SEL=1111 are assumed
        // WE=1 and SEL=1111 are assumed
        output [31:0] wbrx_adr_o,
        output [31:0] wbrx_adr_o,
        output [2:0] wbrx_cti_o,
        output [2:0] wbrx_cti_o,
        output wbrx_cyc_o,
        output wbrx_cyc_o,
        output wbrx_stb_o,
        output wbrx_stb_o,
        input wbrx_ack_i,
        input wbrx_ack_i,
        output [31:0] wbrx_dat_o,
        output [31:0] wbrx_dat_o,
        // WE=0 is assumed
        // WE=0 is assumed
        output [31:0] wbtx_adr_o,
        output [31:0] wbtx_adr_o,
        output [2:0] wbtx_cti_o,
        output [2:0] wbtx_cti_o,
        output wbtx_cyc_o,
        output wbtx_cyc_o,
        output wbtx_stb_o,
        output wbtx_stb_o,
        input wbtx_ack_i,
        input wbtx_ack_i,
        input [31:0] wbtx_dat_i,
        input [31:0] wbtx_dat_i,
        input phy_tx_clk,
        input phy_tx_clk,
        output [3:0] phy_tx_data,
        output [3:0] phy_tx_data,
        output phy_tx_en,
        output phy_tx_en,
        output phy_tx_er,
        output phy_tx_er,
        input phy_rx_clk,
        input phy_rx_clk,
        input [3:0] phy_rx_data,
        input [3:0] phy_rx_data,
        input phy_dv,
        input phy_dv,
        input phy_rx_er,
        input phy_rx_er,
        input phy_col,
        input phy_col,
        input phy_crs,
        input phy_crs,
        output phy_mii_clk,
        output phy_mii_clk,
        inout phy_mii_data
        inout phy_mii_data
);
);
assign wbrx_cti_o = 3'd0;
assign wbrx_cti_o = 3'd0;
assign wbtx_cti_o = 3'd0;
assign wbtx_cti_o = 3'd0;
wire rx_rst;
wire rx_rst;
wire tx_rst;
wire tx_rst;
wire rx_valid;
wire rx_valid;
wire [29:0] rx_adr;
wire [29:0] rx_adr;
wire rx_resetcount;
wire rx_resetcount;
wire rx_incrcount;
wire rx_incrcount;
wire rx_endframe;
wire rx_endframe;
wire fifo_full;
wire fifo_full;
wire tx_valid;
wire tx_valid;
wire [29:0] tx_adr;
wire [29:0] tx_adr;
wire [1:0] tx_bytecount;
wire [1:0] tx_bytecount;
wire tx_next;
wire tx_next;
minimac_ctlif #(
minimac_ctlif #(
        .csr_addr(csr_addr)
        .csr_addr(csr_addr)
) ctlif (
) ctlif (
        .sys_clk(sys_clk),
        .sys_clk(sys_clk),
        .sys_rst(sys_rst),
        .sys_rst(sys_rst),
        .csr_a(csr_a),
        .csr_a(csr_a),
        .csr_we(csr_we),
        .csr_we(csr_we),
        .csr_di(csr_di),
        .csr_di(csr_di),
        .csr_do(csr_do),
        .csr_do(csr_do),
        .irq_rx(irq_rx),
        .irq_rx(irq_rx),
        .irq_tx(irq_tx),
        .irq_tx(irq_tx),
        .rx_rst(rx_rst),
        .rx_rst(rx_rst),
        .tx_rst(tx_rst),
        .tx_rst(tx_rst),
        .rx_valid(rx_valid),
        .rx_valid(rx_valid),
        .rx_adr(rx_adr),
        .rx_adr(rx_adr),
        .rx_resetcount(rx_resetcount),
        .rx_resetcount(rx_resetcount),
        .rx_incrcount(rx_incrcount),
        .rx_incrcount(rx_incrcount),
        .rx_endframe(rx_endframe),
        .rx_endframe(rx_endframe),
        .fifo_full(fifo_full),
        .fifo_full(fifo_full),
        .tx_valid(tx_valid),
        .tx_valid(tx_valid),
        .tx_adr(tx_adr),
        .tx_adr(tx_adr),
        .tx_bytecount(tx_bytecount),
        .tx_bytecount(tx_bytecount),
        .tx_next(tx_next),
        .tx_next(tx_next),
        .phy_mii_clk(phy_mii_clk),
        .phy_mii_clk(phy_mii_clk),
        .phy_mii_data(phy_mii_data)
        .phy_mii_data(phy_mii_data)
);
);
minimac_rx rx(
minimac_rx rx(
        .sys_clk(sys_clk),
        .sys_clk(sys_clk),
        .sys_rst(sys_rst),
        .sys_rst(sys_rst),
        .rx_rst(rx_rst),
        .rx_rst(rx_rst),
        .wbm_adr_o(wbrx_adr_o),
        .wbm_adr_o(wbrx_adr_o),
        .wbm_cyc_o(wbrx_cyc_o),
        .wbm_cyc_o(wbrx_cyc_o),
        .wbm_stb_o(wbrx_stb_o),
        .wbm_stb_o(wbrx_stb_o),
        .wbm_ack_i(wbrx_ack_i),
        .wbm_ack_i(wbrx_ack_i),
        .wbm_dat_o(wbrx_dat_o),
        .wbm_dat_o(wbrx_dat_o),
        .rx_valid(rx_valid),
        .rx_valid(rx_valid),
        .rx_adr(rx_adr),
        .rx_adr(rx_adr),
        .rx_resetcount(rx_resetcount),
        .rx_resetcount(rx_resetcount),
        .rx_incrcount(rx_incrcount),
        .rx_incrcount(rx_incrcount),
        .rx_endframe(rx_endframe),
        .rx_endframe(rx_endframe),
        .fifo_full(fifo_full),
        .fifo_full(fifo_full),
        .phy_rx_clk(phy_rx_clk),
        .phy_rx_clk(phy_rx_clk),
        .phy_rx_data(phy_rx_data),
        .phy_rx_data(phy_rx_data),
        .phy_dv(phy_dv),
        .phy_dv(phy_dv),
        .phy_rx_er(phy_rx_er)
        .phy_rx_er(phy_rx_er)
);
);
minimac_tx tx(
minimac_tx tx(
        .sys_clk(sys_clk),
        .sys_clk(sys_clk),
        .sys_rst(sys_rst),
        .sys_rst(sys_rst),
        .tx_rst(tx_rst),
        .tx_rst(tx_rst),
        .tx_valid(tx_valid),
        .tx_valid(tx_valid),
        .tx_adr(tx_adr),
        .tx_adr(tx_adr),
        .tx_bytecount(tx_bytecount),
        .tx_bytecount(tx_bytecount),
        .tx_next(tx_next),
        .tx_next(tx_next),
        .wbtx_adr_o(wbtx_adr_o),
        .wbtx_adr_o(wbtx_adr_o),
        .wbtx_cyc_o(wbtx_cyc_o),
        .wbtx_cyc_o(wbtx_cyc_o),
        .wbtx_stb_o(wbtx_stb_o),
        .wbtx_stb_o(wbtx_stb_o),
        .wbtx_ack_i(wbtx_ack_i),
        .wbtx_ack_i(wbtx_ack_i),
        .wbtx_dat_i(wbtx_dat_i),
        .wbtx_dat_i(wbtx_dat_i),
        .phy_tx_clk(phy_tx_clk),
        .phy_tx_clk(phy_tx_clk),
        .phy_tx_en(phy_tx_en),
        .phy_tx_en(phy_tx_en),
        .phy_tx_data(phy_tx_data)
        .phy_tx_data(phy_tx_data)
);
);
assign phy_tx_er = 1'b0;
assign phy_tx_er = 1'b0;
endmodule
endmodule
minimac/rtl/minimac_rx.v0000644000175000017500000001070211411201677015775 0ustar  lekernellekernel/*
minimac/rtl/minimac_rx.v0000644000175000017500000001070211411201677015775 0ustar  lekernellekernel/*
 * Milkymist VJ SoC
 * Milkymist VJ SoC
 * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
 * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
 *
 *
 * This program is free software: you can redistribute it and/or modify
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, version 3 of the License.
 * the Free Software Foundation, version 3 of the License.
 *
 *
 * This program is distributed in the hope that it will be useful,
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * GNU General Public License for more details.
 *
 *
 * You should have received a copy of the GNU General Public License
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see .
 * along with this program.  If not, see .
 */
 */
module minimac_rx(
module minimac_rx(
        input sys_clk,
        input sys_clk,
        input sys_rst,
        input sys_rst,
        input rx_rst,
        input rx_rst,
        output [31:0] wbm_adr_o,
        output [31:0] wbm_adr_o,
        output wbm_cyc_o,
        output wbm_cyc_o,
        output wbm_stb_o,
        output wbm_stb_o,
        input wbm_ack_i,
        input wbm_ack_i,
        output reg [31:0] wbm_dat_o,
        output reg [31:0] wbm_dat_o,
        input rx_valid,
        input rx_valid,
        input [29:0] rx_adr,
        input [29:0] rx_adr,
        output rx_resetcount,
        output rx_resetcount,
        output rx_incrcount,
        output rx_incrcount,
        output rx_endframe,
        output rx_endframe,
        output fifo_full,
        output fifo_full,
        input phy_rx_clk,
        input phy_rx_clk,
        input [3:0] phy_rx_data,
        input [3:0] phy_rx_data,
        input phy_dv,
        input phy_dv,
        input phy_rx_er
        input phy_rx_er
);
);
reg rx_resetcount_r;
reg rx_resetcount_r;
reg rx_endframe_r;
reg rx_endframe_r;
assign rx_resetcount = rx_resetcount_r;
assign rx_resetcount = rx_resetcount_r;
assign rx_endframe = rx_endframe_r;
assign rx_endframe = rx_endframe_r;
reg bus_stb;
reg bus_stb;
assign wbm_cyc_o = bus_stb;
assign wbm_cyc_o = bus_stb;
assign wbm_stb_o = bus_stb;
assign wbm_stb_o = bus_stb;
wire fifo_empty;
wire fifo_empty;
reg fifo_ack;
reg fifo_ack;
wire fifo_eof;
wire fifo_eof;
wire [7:0] fifo_data;
wire [7:0] fifo_data;
minimac_rxfifo rxfifo(
minimac_rxfifo rxfifo(
        .sys_clk(sys_clk),
        .sys_clk(sys_clk),
        .rx_rst(rx_rst),
        .rx_rst(rx_rst),
        .phy_rx_clk(phy_rx_clk),
        .phy_rx_clk(phy_rx_clk),
        .phy_rx_data(phy_rx_data),
        .phy_rx_data(phy_rx_data),
        .phy_dv(phy_dv),
        .phy_dv(phy_dv),
        .phy_rx_er(phy_rx_er),
        .phy_rx_er(phy_rx_er),
        .empty(fifo_empty),
        .empty(fifo_empty),
        .ack(fifo_ack),
        .ack(fifo_ack),
        .eof(fifo_eof),
        .eof(fifo_eof),
        .data(fifo_data),
        .data(fifo_data),
        .fifo_full(fifo_full)
        .fifo_full(fifo_full)
);
);
reg start_of_frame;
reg start_of_frame;
reg end_of_frame;
reg end_of_frame;
reg in_frame;
reg in_frame;
always @(posedge sys_clk) begin
always @(posedge sys_clk) begin
        if(sys_rst|rx_rst)
        if(sys_rst|rx_rst)
                in_frame <= 1'b0;
                in_frame <= 1'b0;
        else begin
        else begin
                if(start_of_frame)
                if(start_of_frame)
                        in_frame <= 1'b1;
                        in_frame <= 1'b1;
                if(end_of_frame)
                if(end_of_frame)
                        in_frame <= 1'b0;
                        in_frame <= 1'b0;
        end
        end
end
end
reg loadbyte_en;
reg loadbyte_en;
reg [1:0] loadbyte_counter;
reg [1:0] loadbyte_counter;
always @(posedge sys_clk) begin
always @(posedge sys_clk) begin
        if(sys_rst|rx_rst)
        if(sys_rst|rx_rst)
                loadbyte_counter <= 1'b0;
                loadbyte_counter <= 1'b0;
        else begin
        else begin
                if(start_of_frame)
                if(start_of_frame)
                        loadbyte_counter <= 1'b0;
                        loadbyte_counter <= 1'b0;
                else if(loadbyte_en)
                else if(loadbyte_en)
                        loadbyte_counter <= loadbyte_counter + 2'd1;
                        loadbyte_counter <= loadbyte_counter + 2'd1;
                if(loadbyte_en) begin
                if(loadbyte_en) begin
                        case(loadbyte_counter)
                        case(loadbyte_counter)
                                2'd0: wbm_dat_o[31:24] <= fifo_data;
                                2'd0: wbm_dat_o[31:24] <= fifo_data;
                                2'd1: wbm_dat_o[23:16] <= fifo_data;
                                2'd1: wbm_dat_o[23:16] <= fifo_data;
                                2'd2: wbm_dat_o[15: 8] <= fifo_data;
                                2'd2: wbm_dat_o[15: 8] <= fifo_data;
                                2'd3: wbm_dat_o[ 7: 0] <= fifo_data;
                                2'd3: wbm_dat_o[ 7: 0] <= fifo_data;
                        endcase
                        endcase
                end
                end
        end
        end
end
end
wire full_word = &loadbyte_counter;
wire full_word = &loadbyte_counter;
wire empty_word = loadbyte_counter == 2'd0;
wire empty_word = loadbyte_counter == 2'd0;
parameter MTU = 11'd1530;
parameter MTU = 11'd1530;
reg [10:0] maxcount;
reg [10:0] maxcount;
always @(posedge sys_clk) begin
always @(posedge sys_clk) begin
        if(sys_rst|rx_rst)
        if(sys_rst|rx_rst)
                maxcount <= MTU;
                maxcount <= MTU;
        else begin
        else begin
                if(start_of_frame)
                if(start_of_frame)
                        maxcount <= MTU;
                        maxcount <= MTU;
                else if(loadbyte_en)
                else if(loadbyte_en)
                        maxcount <= maxcount - 11'd1;
                        maxcount <= maxcount - 11'd1;
        end
        end
end
end
wire still_place = |maxcount;
wire still_place = |maxcount;
assign rx_incrcount = loadbyte_en;
assign rx_incrcount = loadbyte_en;
reg next_wb_adr;
reg next_wb_adr;
reg [29:0] adr;
reg [29:0] adr;
always @(posedge sys_clk) begin
always @(posedge sys_clk) begin
        if(sys_rst)
        if(sys_rst)
                adr <= 30'd0;
                adr <= 30'd0;
        else begin
        else begin
                if(start_of_frame)
                if(start_of_frame)
                        adr <= rx_adr;
                        adr <= rx_adr;
                if(next_wb_adr)
                if(next_wb_adr)
                        adr <= adr + 30'd1;
                        adr <= adr + 30'd1;
        end
        end
end
end
assign wbm_adr_o = {adr, 2'd0};
assign wbm_adr_o = {adr, 2'd0};
reg [2:0] state;
reg [2:0] state;
reg [2:0] next_state;
reg [2:0] next_state;
parameter IDLE          = 3'd0;
parameter IDLE          = 3'd0;
parameter LOADBYTE      = 3'd1;
parameter LOADBYTE      = 3'd1;
parameter WBSTROBE      = 3'd2;
parameter WBSTROBE      = 3'd2;
parameter SENDLAST      = 3'd3;
parameter SENDLAST      = 3'd3;
parameter NOMORE        = 3'd3;
parameter NOMORE        = 3'd3;
always @(posedge sys_clk) begin
always @(posedge sys_clk) begin
        if(sys_rst)
        if(sys_rst)
                state <= IDLE;
                state <= IDLE;
        else
        else
                state <= next_state;
                state <= next_state;
end
end
always @(*) begin
always @(*) begin
        next_state = state;
        next_state = state;
        fifo_ack = 1'b0;
        fifo_ack = 1'b0;
        rx_resetcount_r = 1'b0;
        rx_resetcount_r = 1'b0;
        rx_endframe_r = 1'b0;
        rx_endframe_r = 1'b0;
        start_of_frame = 1'b0;
        start_of_frame = 1'b0;
        end_of_frame = 1'b0;
        end_of_frame = 1'b0;
        loadbyte_en = 1'b0;
        loadbyte_en = 1'b0;
        bus_stb = 1'b0;
        bus_stb = 1'b0;
        next_wb_adr = 1'b0;
        next_wb_adr = 1'b0;
        case(state)
        case(state)
                IDLE: begin
                IDLE: begin
                        if(~fifo_empty & rx_valid) begin
                        if(~fifo_empty & rx_valid) begin
                                if(fifo_eof) begin
                                if(fifo_eof) begin
                                        fifo_ack = 1'b1;
                                        fifo_ack = 1'b1;
                                        if(in_frame) begin
                                        if(in_frame) begin
                                                if(fifo_data[0])
                                                if(fifo_data[0])
                                                        rx_resetcount_r = 1'b1;
                                                        rx_resetcount_r = 1'b1;
                                                else begin
                                                else begin
                                                        if(empty_word)
                                                        if(empty_word)
                                                                rx_endframe_r = 1'b1;
                                                                rx_endframe_r = 1'b1;
                                                        else
                                                        else
                                                                next_state = SENDLAST;
                                                                next_state = SENDLAST;
                                                end
                                                end
                                                end_of_frame = 1'b1;
                                                end_of_frame = 1'b1;
                                        end
                                        end
                                end else begin
                                end else begin
                                        if(~in_frame)
                                        if(~in_frame)
                                                start_of_frame = 1'b1;
                                                start_of_frame = 1'b1;
                                        next_state = LOADBYTE;
                                        next_state = LOADBYTE;
                                end
                                end
                        end
                        end
                end
                end
                LOADBYTE: begin
                LOADBYTE: begin
                        loadbyte_en = 1'b1;
                        loadbyte_en = 1'b1;
                        fifo_ack = 1'b1;
                        fifo_ack = 1'b1;
                        if(full_word & rx_valid)
                        if(full_word & rx_valid)
                                next_state = WBSTROBE;
                                next_state = WBSTROBE;
                        else
                        else
                                next_state = IDLE;
                                next_state = IDLE;
                end
                end
                WBSTROBE: begin
                WBSTROBE: begin
                        bus_stb = 1'b1;
                        bus_stb = 1'b1;
                        if(wbm_ack_i) begin
                        if(wbm_ack_i) begin
                                if(still_place)
                                if(still_place)
                                        next_state = IDLE;
                                        next_state = IDLE;
                                else
                                else
                                        next_state = NOMORE;
                                        next_state = NOMORE;
                                next_wb_adr = 1'b1;
                                next_wb_adr = 1'b1;
                        end
                        end
                end
                end
                SENDLAST: begin
                SENDLAST: begin
                        bus_stb = 1'b1;
                        bus_stb = 1'b1;
                        if(wbm_ack_i) begin
                        if(wbm_ack_i) begin
                                rx_endframe_r = 1'b1;
                                rx_endframe_r = 1'b1;
                                next_state = IDLE;
                                next_state = IDLE;
                        end
                        end
                end
                end
                NOMORE: begin
                NOMORE: begin
                        fifo_ack = 1'b1;
                        fifo_ack = 1'b1;
                        if(~fifo_empty & rx_valid) begin
                        if(~fifo_empty & rx_valid) begin
                                if(fifo_eof) begin
                                if(fifo_eof) begin
                                        rx_resetcount_r = 1'b1;
                                        rx_resetcount_r = 1'b1;
                                        end_of_frame = 1'b1;
                                        end_of_frame = 1'b1;
                                        next_state = IDLE;
                                        next_state = IDLE;
                                end
                                end
                        end
                        end
                end
                end
        endcase
        endcase
end
end
endmodule
endmodule
minimac/test/0000755000175000017500000000000011411201677013636 5ustar  lekernellekernelminimac/test/tb_minimac.v0000644000175000017500000000776011411201677016141 0ustar  lekernellekernel/*
minimac/test/0000755000175000017500000000000011411201677013636 5ustar  lekernellekernelminimac/test/tb_minimac.v0000644000175000017500000000776011411201677016141 0ustar  lekernellekernel/*
 * Milkymist VJ SoC
 * Milkymist VJ SoC
 * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
 * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
 *
 *
 * This program is free software: you can redistribute it and/or modify
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, version 3 of the License.
 * the Free Software Foundation, version 3 of the License.
 *
 *
 * This program is distributed in the hope that it will be useful,
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * GNU General Public License for more details.
 *
 *
 * You should have received a copy of the GNU General Public License
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see .
 * along with this program.  If not, see .
 */
 */
module tb_minimac();
module tb_minimac();
/* 100MHz system clock */
/* 100MHz system clock */
reg sys_clk;
reg sys_clk;
initial sys_clk = 1'b0;
initial sys_clk = 1'b0;
always #5 sys_clk = ~sys_clk;
always #5 sys_clk = ~sys_clk;
/* 25MHz RX clock */
/* 25MHz RX clock */
reg phy_rx_clk;
reg phy_rx_clk;
initial phy_rx_clk = 1'b0;
initial phy_rx_clk = 1'b0;
always #20 phy_rx_clk = ~phy_rx_clk;
always #20 phy_rx_clk = ~phy_rx_clk;
/* 25MHz TX clock */
/* 25MHz TX clock */
reg phy_tx_clk;
reg phy_tx_clk;
initial phy_tx_clk = 1'b0;
initial phy_tx_clk = 1'b0;
always #20 phy_tx_clk = ~phy_tx_clk;
always #20 phy_tx_clk = ~phy_tx_clk;
reg sys_rst;
reg sys_rst;
reg [13:0] csr_a;
reg [13:0] csr_a;
reg csr_we;
reg csr_we;
reg [31:0] csr_di;
reg [31:0] csr_di;
wire [31:0] csr_do;
wire [31:0] csr_do;
wire [31:0] wbrx_adr_o;
wire [31:0] wbrx_adr_o;
wire [2:0] wbrx_cti_o;
wire [2:0] wbrx_cti_o;
wire wbrx_cyc_o;
wire wbrx_cyc_o;
wire wbrx_stb_o;
wire wbrx_stb_o;
reg wbrx_ack_i;
reg wbrx_ack_i;
wire [31:0] wbrx_dat_o;
wire [31:0] wbrx_dat_o;
wire [31:0] wbtx_adr_o;
wire [31:0] wbtx_adr_o;
wire [2:0] wbtx_cti_o;
wire [2:0] wbtx_cti_o;
wire wbtx_cyc_o;
wire wbtx_cyc_o;
wire wbtx_stb_o;
wire wbtx_stb_o;
reg wbtx_ack_i;
reg wbtx_ack_i;
reg [31:0] wbtx_dat_i;
reg [31:0] wbtx_dat_i;
reg [3:0] phy_rx_data;
reg [3:0] phy_rx_data;
reg phy_dv;
reg phy_dv;
reg phy_rx_er;
reg phy_rx_er;
wire phy_tx_en;
wire phy_tx_en;
wire [3:0] phy_tx_data;
wire [3:0] phy_tx_data;
wire irq_rx;
wire irq_rx;
wire irq_tx;
wire irq_tx;
minimac #(
minimac #(
        .csr_addr(4'h0)
        .csr_addr(4'h0)
) ethernet (
) ethernet (
        .sys_clk(sys_clk),
        .sys_clk(sys_clk),
        .sys_rst(sys_rst),
        .sys_rst(sys_rst),
        .csr_a(csr_a),
        .csr_a(csr_a),
        .csr_we(csr_we),
        .csr_we(csr_we),
        .csr_di(csr_di),
        .csr_di(csr_di),
        .csr_do(csr_do),
        .csr_do(csr_do),
        .wbrx_adr_o(wbrx_adr_o),
        .wbrx_adr_o(wbrx_adr_o),
        .wbrx_cti_o(wbrx_cti_o),
        .wbrx_cti_o(wbrx_cti_o),
        .wbrx_cyc_o(wbrx_cyc_o),
        .wbrx_cyc_o(wbrx_cyc_o),
        .wbrx_stb_o(wbrx_stb_o),
        .wbrx_stb_o(wbrx_stb_o),
        .wbrx_ack_i(wbrx_ack_i),
        .wbrx_ack_i(wbrx_ack_i),
        .wbrx_dat_o(wbrx_dat_o),
        .wbrx_dat_o(wbrx_dat_o),
        .wbtx_adr_o(wbtx_adr_o),
        .wbtx_adr_o(wbtx_adr_o),
        .wbtx_cti_o(wbtx_cti_o),
        .wbtx_cti_o(wbtx_cti_o),
        .wbtx_cyc_o(wbtx_cyc_o),
        .wbtx_cyc_o(wbtx_cyc_o),
        .wbtx_stb_o(wbtx_stb_o),
        .wbtx_stb_o(wbtx_stb_o),
        .wbtx_ack_i(wbtx_ack_i),
        .wbtx_ack_i(wbtx_ack_i),
        .wbtx_dat_i(wbtx_dat_i),
        .wbtx_dat_i(wbtx_dat_i),
        .irq_rx(irq_rx),
        .irq_rx(irq_rx),
        .irq_tx(irq_tx),
        .irq_tx(irq_tx),
        .phy_tx_clk(phy_tx_clk),
        .phy_tx_clk(phy_tx_clk),
        .phy_tx_data(phy_tx_data),
        .phy_tx_data(phy_tx_data),
        .phy_tx_en(phy_tx_en),
        .phy_tx_en(phy_tx_en),
        .phy_tx_er(),
        .phy_tx_er(),
        .phy_rx_clk(phy_rx_clk),
        .phy_rx_clk(phy_rx_clk),
        .phy_rx_data(phy_rx_data),
        .phy_rx_data(phy_rx_data),
        .phy_dv(phy_dv),
        .phy_dv(phy_dv),
        .phy_rx_er(phy_rx_er),
        .phy_rx_er(phy_rx_er),
        .phy_col(),
        .phy_col(),
        .phy_crs(),
        .phy_crs(),
        .phy_mii_clk(),
        .phy_mii_clk(),
        .phy_mii_data()
        .phy_mii_data()
);
);
task waitclock;
task waitclock;
begin
begin
        @(posedge sys_clk);
        @(posedge sys_clk);
        #1;
        #1;
end
end
endtask
endtask
task csrwrite;
task csrwrite;
input [31:0] address;
input [31:0] address;
input [31:0] data;
input [31:0] data;
begin
begin
        csr_a = address[16:2];
        csr_a = address[16:2];
        csr_di = data;
        csr_di = data;
        csr_we = 1'b1;
        csr_we = 1'b1;
        waitclock;
        waitclock;
        $display("Configuration Write: %x=%x", address, data);
        $display("Configuration Write: %x=%x", address, data);
        csr_we = 1'b0;
        csr_we = 1'b0;
end
end
endtask
endtask
task csrread;
task csrread;
input [31:0] address;
input [31:0] address;
begin
begin
        csr_a = address[16:2];
        csr_a = address[16:2];
        waitclock;
        waitclock;
        $display("Configuration Read : %x=%x", address, csr_do);
        $display("Configuration Read : %x=%x", address, csr_do);
end
end
endtask
endtask
always @(posedge sys_clk) begin
always @(posedge sys_clk) begin
        if(wbrx_cyc_o & wbrx_stb_o & ~wbrx_ack_i & (($random % 5) == 0)) begin
        if(wbrx_cyc_o & wbrx_stb_o & ~wbrx_ack_i & (($random % 5) == 0)) begin
                $display("Write: %x <- %x", wbrx_adr_o, wbrx_dat_o);
                $display("Write: %x <- %x", wbrx_adr_o, wbrx_dat_o);
                wbrx_ack_i = 1'b1;
                wbrx_ack_i = 1'b1;
        end else
        end else
                wbrx_ack_i = 1'b0;
                wbrx_ack_i = 1'b0;
end
end
always @(posedge sys_clk) begin
always @(posedge sys_clk) begin
        if(wbtx_cyc_o & wbtx_stb_o & ~wbtx_ack_i & (($random % 5) == 0)) begin
        if(wbtx_cyc_o & wbtx_stb_o & ~wbtx_ack_i & (($random % 5) == 0)) begin
                wbtx_dat_i = $random;
                wbtx_dat_i = $random;
                $display("Read : %x -> %x", wbtx_adr_o, wbtx_dat_i);
                $display("Read : %x -> %x", wbtx_adr_o, wbtx_dat_i);
                wbtx_ack_i = 1'b1;
                wbtx_ack_i = 1'b1;
        end else
        end else
                wbtx_ack_i = 1'b0;
                wbtx_ack_i = 1'b0;
end
end
always @(posedge phy_rx_clk) begin
always @(posedge phy_rx_clk) begin
        phy_rx_er <= 1'b0;
        phy_rx_er <= 1'b0;
        phy_rx_data <= $random;
        phy_rx_data <= $random;
        if(phy_dv) begin
        if(phy_dv) begin
                //$display("rx: %x", phy_rx_data);
                //$display("rx: %x", phy_rx_data);
                if(($random % 125) == 0) begin
                if(($random % 125) == 0) begin
                        phy_dv <= 1'b0;
                        phy_dv <= 1'b0;
                        //$display("** stopping transmission");
                        //$display("** stopping transmission");
                end
                end
        end else begin
        end else begin
                if(($random % 12) == 0) begin
                if(($random % 12) == 0) begin
                        phy_dv <= 1'b1;
                        phy_dv <= 1'b1;
                        //$display("** starting transmission");
                        //$display("** starting transmission");
                end
                end
        end
        end
end
end
always @(posedge phy_tx_clk) begin
always @(posedge phy_tx_clk) begin
        if(phy_tx_en)
        if(phy_tx_en)
                $display("tx: %x", phy_tx_data);
                $display("tx: %x", phy_tx_data);
end
end
initial begin
initial begin
        /* Reset / Initialize our logic */
        /* Reset / Initialize our logic */
        sys_rst = 1'b1;
        sys_rst = 1'b1;
        csr_a = 14'd0;
        csr_a = 14'd0;
        csr_di = 32'd0;
        csr_di = 32'd0;
        csr_we = 1'b0;
        csr_we = 1'b0;
        phy_dv = 1'b0;
        phy_dv = 1'b0;
        waitclock;
        waitclock;
        sys_rst = 1'b0;
        sys_rst = 1'b0;
        waitclock;
        waitclock;
        /*csrwrite(32'h00, 0);
        /*csrwrite(32'h00, 0);
        csrwrite(32'h0C, 32'h10000000);
        csrwrite(32'h0C, 32'h10000000);
        csrwrite(32'h08, 1);
        csrwrite(32'h08, 1);
        #3000;
        #3000;
        csrread(32'h00);
        csrread(32'h00);
        csrread(32'h14);
        csrread(32'h14);
        csrread(32'h20);
        csrread(32'h20);
        csrread(32'h2C);
        csrread(32'h2C);
        csrread(32'h38);*/
        csrread(32'h38);*/
        waitclock;
        waitclock;
        waitclock;
        waitclock;
        waitclock;
        waitclock;
        waitclock;
        waitclock;
        csrwrite(32'h00, 1);
        csrwrite(32'h00, 1);
        csrwrite(32'h3C, 72);
        csrwrite(32'h3C, 72);
        csrread(32'h3C);
        csrread(32'h3C);
        @(posedge irq_tx);
        @(posedge irq_tx);
        #30000;
        #30000;
        $finish;
        $finish;
end
end
endmodule
endmodule
minimac/test/Makefile0000644000175000017500000000041011411201677015271 0ustar  lekernellekernelSOURCES=tb_minimac.v $(wildcard ../rtl/*.v)
minimac/test/Makefile0000644000175000017500000000041011411201677015271 0ustar  lekernellekernelSOURCES=tb_minimac.v $(wildcard ../rtl/*.v)
all: cversim
all: cversim
isim: tb_minimac
isim: tb_minimac
        ./tb_minimac
        ./tb_minimac
cversim: $(SOURCES)
cversim: $(SOURCES)
        cver $(SOURCES)
        cver $(SOURCES)
clean:
clean:
        rm -f tb_minimac verilog.log minimac.vcd
        rm -f tb_minimac verilog.log minimac.vcd
tb_minimac: $(SOURCES)
tb_minimac: $(SOURCES)
        iverilog -o tb_minimac $(SOURCES)
        iverilog -o tb_minimac $(SOURCES)
.PHONY: clean sim cversim
.PHONY: clean sim cversim
minimac/doc/0000755000175000017500000000000011422324710013420 5ustar  lekernellekernelminimac/doc/Makefile0000644000175000017500000000041411411201677015063 0ustar  lekernellekernelTEX=minimac.tex
minimac/doc/0000755000175000017500000000000011431543453013427 5ustar  lekernellekernelminimac/doc/Makefile0000644000175000017500000000041411411201677015063 0ustar  lekernellekernelTEX=minimac.tex
DVI=$(TEX:.tex=.dvi)
DVI=$(TEX:.tex=.dvi)
PS=$(TEX:.tex=.ps)
PS=$(TEX:.tex=.ps)
PDF=$(TEX:.tex=.pdf)
PDF=$(TEX:.tex=.pdf)
AUX=$(TEX:.tex=.aux)
AUX=$(TEX:.tex=.aux)
LOG=$(TEX:.tex=.log)
LOG=$(TEX:.tex=.log)
all: $(PDF)
all: $(PDF)
%.dvi: %.tex
%.dvi: %.tex
        latex $<
        latex $<
%.ps: %.dvi
%.ps: %.dvi
        dvips $<
        dvips $<
%.pdf: %.ps
%.pdf: %.ps
        ps2pdf $<
        ps2pdf $<
clean:
clean:
        rm -f $(DVI) $(PS) $(PDF) $(AUX) $(LOG)
        rm -f $(DVI) $(PS) $(PDF) $(AUX) $(LOG)
.PHONY: clean
.PHONY: clean
minimac/doc/minimac.tex0000644000175000017500000002170311422301534015561 0ustar  lekernellekernel\documentclass[a4paper,11pt]{article}
minimac/doc/minimac.tex0000644000175000017500000002170311422301534015561 0ustar  lekernellekernel\documentclass[a4paper,11pt]{article}
\usepackage{fullpage}
\usepackage{fullpage}
\usepackage[latin1]{inputenc}
\usepackage[latin1]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[T1]{fontenc}
\usepackage[normalem]{ulem}
\usepackage[normalem]{ulem}
\usepackage[english]{babel}
\usepackage[english]{babel}
\usepackage{listings,babel}
\usepackage{listings,babel}
\lstset{breaklines=true,basicstyle=\ttfamily}
\lstset{breaklines=true,basicstyle=\ttfamily}
\usepackage{graphicx}
\usepackage{graphicx}
\usepackage{moreverb}
\usepackage{moreverb}
\usepackage{url}
\usepackage{url}
\usepackage{amsmath}
\usepackage{amsmath}
\usepackage{float}
\usepackage{float}
\usepackage{tabularx}
\usepackage{tabularx}
\title{Minimac - the minimalist Ethernet MAC}
\title{Minimac - the minimalist Ethernet MAC}
\author{S\'ebastien Bourdeauducq}
\author{S\'ebastien Bourdeauducq}
\date{July 2010}
\date{July 2010}
\begin{document}
\begin{document}
\setlength{\parindent}{0pt}
\setlength{\parindent}{0pt}
\setlength{\parskip}{5pt}
\setlength{\parskip}{5pt}
\maketitle{}
\maketitle{}
\section{Overview}
\section{Overview}
Minimac is a 10/100 Ethernet MAC for MII PHYs, built with minimal hardware resource usage in mind. It is designed for resource-constrained system-on-chips where basic network connectivity is desired.
Minimac is a 10/100 Ethernet MAC for MII PHYs, built with minimal hardware resource usage in mind. It is designed for resource-constrained system-on-chips where basic network connectivity is desired.
It has the following features:
It has the following features:
\begin{itemize}
\begin{itemize}
\item CSR control interface efficiently connects the core to the Milkymist\texttrademark~architecture.
\item CSR control interface efficiently connects the core to the Milkymist\texttrademark~architecture.
\item WISHBONE master interfaces stream packets straight to and from system memory, minimizing on-chip data storage.
\item WISHBONE master interfaces stream packets straight to and from system memory, minimizing on-chip data storage.
\item Four hardware-controlled packet reception slots reduce the risk of lost data in case of high interrupt latency from the system CPU.
\item Four hardware-controlled packet reception slots reduce the risk of lost data in case of high interrupt latency from the system CPU.
\item Software generates and checks Ethernet CRCs and preambles.
\item Software generates and checks Ethernet CRCs and preambles.
\item Full duplex (switched) operation only, without collision detection, retransmission nor MAC filtering.
\item Full duplex (switched) operation only, without collision detection, retransmission nor MAC filtering.
\item Bit-banged MDIO interface.
\item Bit-banged MDIO interface.
\end{itemize}
\end{itemize}
\section{Setup register}
\section{Setup register}
\begin{tabularx}{450pt}{|l|l|X|}
\begin{tabularx}{450pt}{|l|l|X|}
\hline
\hline
\textbf{Register} & \textbf{Bits} & \textbf{Description} \\
\textbf{Register} & \textbf{Bits} & \textbf{Description} \\
\hline
\hline
0x00 & 0 & RX reset. When this bit is active (default at reset), the reception FIFO is cleared and kept empty, the reception logic is set to expect a new packet, and no new transfers are made through the RX DMA interface. If the bit is set while in the middle of a WISHBONE bus cycle, that cycle is allowed to finish. Setting the RX reset bit does not modify the state of the RX slots. \\
0x00 & 0 & RX reset. When this bit is active (default at reset), the reception FIFO is cleared and kept empty, the reception logic is set to expect a new packet, and no new transfers are made through the RX DMA interface. If the bit is set while in the middle of a WISHBONE bus cycle, that cycle is allowed to finish. Setting the RX reset bit does not modify the state of the RX slots. \\
\hline
\hline
-- & 1 & TX reset. When this bit is active (default at reset), the transmission FIFO is cleared and kept empty, the transmission logic is set to expect a new packet, and no new transfers are made through the TX DMA interface. If the bit is set while in the middle of a WISHBONE bus cycle, that cycle is allowed to finish. \\
-- & 1 & TX reset. When this bit is active (default at reset), the transmission FIFO is cleared and kept empty, the transmission logic is set to expect a new packet, and no new transfers are made through the TX DMA interface. If the bit is set while in the middle of a WISHBONE bus cycle, that cycle is allowed to finish. \\
\hline
\hline
-- & 31 -- 2 & Reserved. \\
-- & 31 -- 2 & Reserved. \\
\hline
\hline
\end{tabularx}
\end{tabularx}
\section{MDIO}
\section{MDIO}
The two MDIO pins (clock and bidirectional data) are controlled using a low-level, bit-banged interface on register 0x04.
The two MDIO pins (clock and bidirectional data) are controlled using a low-level, bit-banged interface on register 0x04.
\begin{tabularx}{450pt}{|l|l|X|}
\begin{tabularx}{450pt}{|l|l|X|}
\hline
\hline
\textbf{Register} & \textbf{Bits} & \textbf{Description} \\
\textbf{Register} & \textbf{Bits} & \textbf{Description} \\
\hline
\hline
0x04 & 0 & Logic level driven to the MDIO data pin (if OE=1). \\
0x04 & 0 & Logic level driven to the MDIO data pin (if OE=1). \\
\hline
\hline
-- & 1 & Logic level read from the MDIO data pin. \\
-- & 1 & Logic level read from the MDIO data pin. \\
\hline
\hline
-- & 2 & Output Enable (OE). When this bit is set, the SoC drives the bidirectional MDIO data pin. \\
-- & 2 & Output Enable (OE). When this bit is set, the SoC drives the bidirectional MDIO data pin. \\
\hline
\hline
-- & 3 & Logic level driven to the MDIO clock pin. \\
-- & 3 & Logic level driven to the MDIO clock pin. \\
\hline
\hline
-- & 31 -- 4 & Reserved. \\
-- & 31 -- 4 & Reserved. \\
\hline
\hline
\end{tabularx}
\end{tabularx}
\section{Packet reception}
\section{Packet reception}
There are four reception slots. When a packet arrives, the Minimac cores picks the loaded slot with the lowest number (first slot 0, then 1, etc.), DMA's the packet into the system memory at the address given by the slot, updates the slot's byte count according to the length of the packet, and updates the slot's state to ``pending''.
There are four reception slots. When a packet arrives, the Minimac cores picks the loaded slot with the lowest number (first slot 0, then 1, etc.), DMA's the packet into the system memory at the address given by the slot, updates the slot's byte count according to the length of the packet, and updates the slot's state to ``pending''.
If a reception error occurs, of if the packet exceeds the Ethernet MTU, the whole packet is discarded and the slot's state is unchanged. However, some of the packet's data may have been transferred to the system memory; so software should consider that the contents of a DMA buffer attached to a loaded slot are undefined. DMA buffers should be made large enough to include a maximum length Ethernet packet with preamble and CRC. Raw packets are received entirely, including preamble, trailer and CRC.
If a reception error occurs, of if the packet exceeds the Ethernet MTU, the whole packet is discarded and the slot's state is unchanged. However, some of the packet's data may have been transferred to the system memory; so software should consider that the contents of a DMA buffer attached to a loaded slot are undefined. DMA buffers should be made large enough to include a maximum length Ethernet packet with preamble and CRC. Raw packets are received entirely, including preamble, trailer and CRC.
Memory addresses must be aligned to a 32-bit boundary.
Memory addresses must be aligned to a 32-bit boundary.
\begin{tabularx}{450pt}{|l|X|}
\begin{tabularx}{450pt}{|l|X|}
\hline
\hline
\textbf{Register} & \textbf{Description} \\
\textbf{Register} & \textbf{Description} \\
\hline
\hline
0x08 & State of the slot 0 (see below). \\
0x08 & State of the slot 0 (see below). \\
\hline
\hline
0x0C & DMA address of the slot 0. This address is read-only for Minimac and may be re-used for another transfer without the need to reprogram it. \\
0x0C & DMA address of the slot 0. This address is read-only for Minimac and may be re-used for another transfer without the need to reprogram it. \\
\hline
\hline
0x10 & Reception byte count of the slot 0. \\
0x10 & Reception byte count of the slot 0. \\
\hline
\hline
0x14 & State of the slot 1. \\
0x14 & State of the slot 1. \\
\hline
\hline
0x18 & DMA address of the slot 1. \\
0x18 & DMA address of the slot 1. \\
\hline
\hline
0x1C & Reception byte count of the slot 1. \\
0x1C & Reception byte count of the slot 1. \\
\hline
\hline
0x20 & State of the slot 2. \\
0x20 & State of the slot 2. \\
\hline
\hline
0x24 & DMA address of the slot 2. \\
0x24 & DMA address of the slot 2. \\
\hline
\hline
0x28 & Reception byte count of the slot 2. \\
0x28 & Reception byte count of the slot 2. \\
\hline
\hline
0x2C & State of the slot 3. \\
0x2C & State of the slot 3. \\
\hline
\hline
0x30 & DMA address of the slot 3. \\
0x30 & DMA address of the slot 3. \\
\hline
\hline
0x34 & Reception byte count of the slot 3. \\
0x34 & Reception byte count of the slot 3. \\
\hline
\hline
\end{tabularx}
\end{tabularx}
\begin{tabularx}{450pt}{|l|X|}
\begin{tabularx}{450pt}{|l|X|}
\hline
\hline
\textbf{State} & \textbf{Description} \\
\textbf{State} & \textbf{Description} \\
\hline
\hline
0 (empty) & Slot is empty. No valid DMA address has been specified for this slot. Software may program a DMA address and, then, set the slot state to 1. This state is the default at reset. \\
0 (empty) & Slot is empty. No valid DMA address has been specified for this slot. Software may program a DMA address and, then, set the slot state to 1. This state is the default at reset. \\
\hline
\hline
1 (loaded) & Slot is loaded with a valid DMA address, and is awaiting a complete packet reception to switch to state 2. Software may cancel the potential transfer by setting the state to 0. In this case, no new DMA transfers will be made for this slot, but if the core was in a middle of a WISHBONE cycle, that cycle will be allowed to complete. \\
1 (loaded) & Slot is loaded with a valid DMA address, and is awaiting a complete packet reception to switch to state 2. Software may cancel the potential transfer by setting the state to 0. In this case, no new DMA transfers will be made for this slot, but if the core was in a middle of a WISHBONE cycle, that cycle will be allowed to complete. \\
\hline
\hline
2 (pending) & Slot has received a valid packet which has been fully transferred to the DMA buffer. The byte counter has been updated with the length of the packet. No further packet transfers will occur for this slot. The software can set the state to 0 to disable this slot, or to 1 to reload it for a new transmission. \\
2 (pending) & Slot has received a valid packet which has been fully transferred to the DMA buffer. The byte counter has been updated with the length of the packet. No further packet transfers will occur for this slot. The software can set the state to 0 to disable this slot, or to 1 to reload it for a new transmission. \\
\hline
\hline
* & All other state values are invalid and should not be used. \\
* & All other state values are invalid and should not be used. \\
\hline
\hline
\end{tabularx}
\end{tabularx}
If one or more slots is in state 2, the RX interrupt line is set and kept asserted.
If one or more slots is in state 2, the RX interrupt line is set and kept asserted.
\section{Packet emission}
\section{Packet emission}
Minimac supports only one outstanding packet emission request.
Minimac supports only one outstanding packet emission request.
When software writes a non-zero value the the remaining byte count register after having programmed the address of the DMA buffer, a packet is streamed from system memory and sent to the PHY. A full raw Ethernet packet must have been loaded in the memory, including preamble, trailer and CRC. The packet must be contiguous in memory, i.e. there is no support for scatter-gather techniques. The remaining byte count register will then decrement while the packet is being transferred. Once it reaches 0, transmission terminates and the TX interrupt line is pulsed. At the same time, the address register is incremented until it reaches the end of the packet. This implies that the software typically needs to re-load the address register to send a new packet.
When software writes a non-zero value the the remaining byte count register after having programmed the address of the DMA buffer, a packet is streamed from system memory and sent to the PHY. A full raw Ethernet packet must have been loaded in the memory, including preamble, trailer and CRC. The packet must be contiguous in memory, i.e. there is no support for scatter-gather techniques. The remaining byte count register will then decrement while the packet is being transferred. Once it reaches 0, transmission terminates and the TX interrupt line is pulsed. At the same time, the address register is incremented until it reaches the end of the packet. This implies that the software typically needs to re-load the address register to send a new packet.
Software can cancel the transmission of a packet by writing 0 to the remaining byte count register. No new WISHBONE DMA transfer will be started, but if the core was in a middle of a WISHBONE cycle, that cycle will be allowed to complete. Cancelling the transmission of a packet is discouraged as it is likely to cause an incomplete Ethernet frame to be sent over the network.
Software can cancel the transmission of a packet by writing 0 to the remaining byte count register. No new WISHBONE DMA transfer will be started, but if the core was in a middle of a WISHBONE cycle, that cycle will be allowed to complete. Cancelling the transmission of a packet is discouraged as it is likely to cause an incomplete Ethernet frame to be sent over the network.
The DMA buffer must be aligned to a 32-bit boundary.
The DMA buffer must be aligned to a 32-bit boundary.
\begin{tabularx}{450pt}{|l|X|}
\begin{tabularx}{450pt}{|l|X|}
\hline
\hline
\textbf{Register} & \textbf{Description} \\
\textbf{Register} & \textbf{Description} \\
\hline
\hline
0x38 & TX DMA address. \\
0x38 & TX DMA address. \\
\hline
\hline
0x3C & Remaining TX byte count. \\
0x3C & Remaining TX byte count. \\
\hline
\hline
\end{tabularx}
\end{tabularx}
\section{Memory system considerations}
\section{Memory system considerations}
In order to reduce costs, Minimac does not provide enough on-chip storage to hold complete Ethernet frames and instead streams them to and from the system memory while they are being transferred over the medium. However, to cope with the latency stemming from this technique, Minimac provides a limited form of data storage consisting of the TX and RX FIFO buffers, each being able to store a few dozen bytes (the exact amount is configurable at synthesis time).
In order to reduce costs, Minimac does not provide enough on-chip storage to hold complete Ethernet frames and instead streams them to and from the system memory while they are being transferred over the medium. However, to cope with the latency stemming from this technique, Minimac provides a limited form of data storage consisting of the TX and RX FIFO buffers, each being able to store a few dozen bytes (the exact amount is configurable at synthesis time).
This scheme obviously assumes that the system memory infrastructure can provide enough bandwidth and low levels of latency to the Minimac DMA interfaces. In case it fails to do so, FIFOs can overflow or underflow. This can happen transitionally, for example if the memory system is temporarily overloaded by transfers made by other cores in the system on chip.
This scheme obviously assumes that the system memory infrastructure can provide enough bandwidth and low levels of latency to the Minimac DMA interfaces. In case it fails to do so, FIFOs can overflow or underflow. This can happen transitionally, for example if the memory system is temporarily overloaded by transfers made by other cores in the system on chip.
\begin{itemize}
\begin{itemize}
\item if the RX FIFO overflows, reception is interrupted, the slot does not go into state 2 (the whole packet is dropped), the ``RX reset'' bit is set in the setup register (clearing the FIFO), and the RX interrupt line is asserted (and kept asserted until the ``RX reset'' bit is cleared). To recover from this state, software must clear the ``RX reset'' bit.
\item if the RX FIFO overflows, reception is interrupted, the slot does not go into state 2 (the whole packet is dropped), the ``RX reset'' bit is set in the setup register (clearing the FIFO), and the RX interrupt line is asserted (and kept asserted until the ``RX reset'' bit is cleared). To recover from this state, software must clear the ``RX reset'' bit.
\item if the TX FIFO underflows, invalid data will be sent on the Ethernet medium. The software is not notified and does not need to do anything to recover from this state, except retransmit the corrupted frame (higher level network protocols will typically do that).
\item if the TX FIFO underflows, invalid data will be sent on the Ethernet medium. The software is not notified and does not need to do anything to recover from this state, except retransmit the corrupted frame (higher level network protocols will typically do that).
\end{itemize}
\end{itemize}
\section*{Copyright notice}
\section*{Copyright notice}
Copyright \copyright 2007-2010 S\'ebastien Bourdeauducq. \\
Copyright \copyright 2007-2010 S\'ebastien Bourdeauducq. \\
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the LICENSE.FDL file at the root of the Milkymist source distribution.
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the LICENSE.FDL file at the root of the Milkymist source distribution.
\end{document}
\end{document}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.