diff options
| -rw-r--r-- | simple_gemac/simple_gemac.v | 12 | ||||
| -rw-r--r-- | simple_gemac/simple_gemac_tb.v | 7 | ||||
| -rw-r--r-- | simple_gemac/simple_gemac_wb.v | 134 | ||||
| -rw-r--r-- | simple_gemac/simple_gemac_wrapper.v | 74 | 
4 files changed, 221 insertions, 6 deletions
| diff --git a/simple_gemac/simple_gemac.v b/simple_gemac/simple_gemac.v index adcc2d2fb..5ec2fa2ba 100644 --- a/simple_gemac/simple_gemac.v +++ b/simple_gemac/simple_gemac.v @@ -8,6 +8,10 @@ module simple_gemac     // Flow Control Interface     input pause_req, input [15:0] pause_time, input pause_en, +   // Settings +   input [47:0] ucast_addr, input [47:0] mcast_addr, +   input pass_ucast, input pass_mcast, input pass_bcast, input pass_pause, input pass_all, +        // RX Client Interface     output rx_clk, output [7:0] rx_data, output rx_valid, output rx_error, output rx_ack, @@ -18,15 +22,11 @@ module simple_gemac     localparam SGE_IFG 		     = 8'd12;  // 12 should be the absolute minimum     wire rst_rxclk, rst_txclk;    -   oneshot_2clk tx_rst_1shot (.clk_in(tx_clk),.in(reset),.clk_out(tx_clk),.out(rst_txclk));  // FIXME clocks -   oneshot_2clk rx_rst_1shot (.clk_in(rx_clk),.in(reset),.clk_out(rx_clk),.out(rst_rxclk)); +   reset_sync reset_sync_tx (.clk(tx_clk),.reset_in(reset),.reset_out(rst_txclk)); +   reset_sync reset_sync_rx (.clk(rx_clk),.reset_in(reset),.reset_out(rst_rxclk));     wire [15:0] pause_quanta_rcvd; -   wire [47:0] ucast_addr = 48'hF1F2_F3F4_F5F6; -   wire [47:0] mcast_addr = 0; -   wire pass_ucast  =1, pass_mcast=0, pass_bcast=1, pass_pause=0, pass_all=0; -        simple_gemac_tx simple_gemac_tx       (.clk125(clk125),.reset(rst_txclk),        .GMII_GTX_CLK(GMII_GTX_CLK), .GMII_TX_EN(GMII_TX_EN), diff --git a/simple_gemac/simple_gemac_tb.v b/simple_gemac/simple_gemac_tb.v index cd2db01b5..6091751a7 100644 --- a/simple_gemac/simple_gemac_tb.v +++ b/simple_gemac/simple_gemac_tb.v @@ -29,6 +29,10 @@ module simple_gemac_tb;     assign GMII_RX_DV  = GMII_TX_EN;     assign GMII_RX_ER  = GMII_TX_ER | FORCE_ERR;     assign GMII_RXD    = GMII_TXD ^ FORCE_DAT_ERR; + +   wire [47:0] ucast_addr = 48'hF1F2_F3F4_F5F6; +   wire [47:0] mcast_addr = 0; +   wire        pass_ucast  =1, pass_mcast=0, pass_bcast=1, pass_pause=0, pass_all=0;     simple_gemac simple_gemac       (.clk125(clk),  .reset(reset), @@ -37,6 +41,9 @@ module simple_gemac_tb;        .GMII_RX_CLK(GMII_RX_CLK), .GMII_RX_DV(GMII_RX_DV),          .GMII_RX_ER(GMII_RX_ER), .GMII_RXD(GMII_RXD),        .pause_req(pause_req), .pause_time(pause_time), .pause_en(1), +      .ucast_addr(ucast_addr), .mcast_addr(mcast_addr), +      .pass_ucast(pass_ucast), .pass_mcast(pass_mcast), .pass_bcast(pass_bcast),  +      .pass_pause(pass_pause), .pass_all(pass_all),        .rx_clk(rx_clk), .rx_data(rx_data),        .rx_valid(rx_valid), .rx_error(rx_error), .rx_ack(rx_ack),        .tx_clk(tx_clk), .tx_data(tx_data),  diff --git a/simple_gemac/simple_gemac_wb.v b/simple_gemac/simple_gemac_wb.v new file mode 100644 index 000000000..96189e1d9 --- /dev/null +++ b/simple_gemac/simple_gemac_wb.v @@ -0,0 +1,134 @@ + +module wb_reg +  #(parameter ADDR=0, +    parameter DEFAULT=0) +   (input clk, input rst,  +    input [5:0] adr, input wr_acc, +    input [31:0] dat_i, output reg [31:0] dat_o); + +   always @(posedge clk) +     if(rst) +       dat_o <= DEFAULT; +     else if(wr_acc & (adr == ADDR)) +       dat_o <= dat_i; +    +endmodule // wb_reg + +    + +module simple_gemac_wb +  (input wb_clk, input wb_rst, +   input wb_cyc, input wb_stb, input wb_ack, input wb_we, +   input [7:0] wb_adr, input [31:0] wb_dat_i, output reg [31:0] wb_dat_o, +    +   inout mdio, output mdc, +   output [47:0] ucast_addr, output [47:0] mcast_addr, +   output pass_ucast, output pass_mcast, output pass_bcast, +   output pass_pause, output pass_all, output pause_en  ); + +   wire   wr_acc  = wb_cyc & wb_stb & wb_we; +   wire   rd_acc  = wb_cyc & wb_stb & ~wb_we; +    +   wire [5:0] misc_settings; +   assign {pass_ucast, pass_mcast, pass_bcast, pass_pause, pass_all, pause_en} 	= misc_settings; + +   wb_reg #(.ADDR(0),.DEFAULT(6'b111001)) +   wb_reg_settings (.clk(wb_clk), .rst(wb_rst), .adr(wb_adr[7:2]), .dat_i(wb_dat_i), .dat_o(misc_settings) ); +   wb_reg #(.ADDR(1),.DEFAULT(0)) +   wb_reg_ucast_h (.clk(wb_clk), .rst(wb_rst), .adr(wb_adr[7:2]), .dat_i(wb_dat_i), .dat_o(ucast_addr[47:32]) ); +   wb_reg #(.ADDR(2),.DEFAULT(0)) +   wb_reg_ucast_l (.clk(wb_clk), .rst(wb_rst), .adr(wb_adr[7:2]), .dat_i(wb_dat_i), .dat_o(ucast_addr[31:0]) ); +   wb_reg #(.ADDR(3),.DEFAULT(0)) +   wb_reg_mcast_h (.clk(wb_clk), .rst(wb_rst), .adr(wb_adr[7:2]), .dat_i(wb_dat_i), .dat_o(mcast_addr[47:32]) ); +   wb_reg #(.ADDR(4),.DEFAULT(0)) +   wb_reg_mcast_l (.clk(wb_clk), .rst(wb_rst), .adr(wb_adr[7:2]), .dat_i(wb_dat_i), .dat_o(mcast_addr[31:0]) ); + +   //MII to CPU  +   wire [7:0] Divider;            // Divider for the host clock +   wire [15:0] CtrlData;          // Control Data (to be written to the PHY reg.) +   wire [4:0]  Rgad;               // Register Address (within the PHY) +   wire [4:0]  Fiad;               // PHY Address +   wire        NoPre;              // No Preamble (no 32-bit preamble) +   wire        WCtrlData;          // Write Control Data operation +   wire        RStat;              // Read Status operation +   wire        ScanStat;           // Scan Status operation +   wire        Busy;               // Busy Signal +   wire        LinkFail;           // Link Integrity Signal +   wire        Nvalid;             // Invalid Status (qualifier for the valid scan result) +   wire [15:0] Prsd;               // Read Status Data (data read from the PHY) +   wire        WCtrlDataStart;     // This signals resets the WCTRLDATA bit in the MIIM Command register +   wire        RStatStart;         // This signal resets the RSTAT BIT in the MIIM Command register +   wire        UpdateMIIRX_DATAReg; // Updates MII RX_DATA register with read data +    +   // registers for controlling the MII interface +   reg [2:0]   MIICOMMAND; +   wire [12:0] MIIADDRESS; +   reg [15:0]  MIIRX_DATA; +   wire [2:0]  MIISTATUS; + +   wb_reg #(.ADDR(5),.DEFAULT(0)) +   wb_reg_miimoder (.clk(wb_clk), .rst(wb_rst), .adr(wb_adr[7:2]), .dat_i(wb_dat_i), .dat_o({NoPre,Divider}) ); +    +   wb_reg #(.ADDR(6),.DEFAULT(0)) +   wb_reg_miiaddr (.clk(wb_clk), .rst(wb_rst), .adr(wb_adr[7:2]), .dat_i(wb_dat_i), .dat_o(MIIADDRESS) ); +    +   wb_reg #(.ADDR(7),.DEFAULT(0)) +   wb_reg_miidata (.clk(wb_clk), .rst(wb_rst), .adr(wb_adr[7:2]), .dat_i(wb_dat_i), .dat_o(CtrlData) ); +    +   // MIICOMMAND register - needs special treatment because of auto-resetting bits +   always @ (posedge wb_clk) +     if (wb_rst) +       MIICOMMAND <= 0; +     else +       if (wr_acc & (wb_adr == 8'd8)) +         MIICOMMAND <= wb_dat_i; +       else +         begin +            if ( WCtrlDataStart ) +              MIICOMMAND[2] <= 0; +            if ( RStatStart ) +              MIICOMMAND[1] <= 0; +         end +    +   // MIIRX_DATA register +   always @(posedge wb_clk) +     if (wb_rst) +       MIIRX_DATA <= 0; +     else +       if (UpdateMIIRX_DATAReg ) +         MIIRX_DATA <= Prsd; + +   // MIICOMMAND +   assign WCtrlData  = MIICOMMAND[2]; +   assign RStat      = MIICOMMAND[1]; +   assign ScanStat   = MIICOMMAND[0]; +   // MIIADDRESS +   assign Rgad 	     = MIIADDRESS[12:8]; +   assign Fiad 	     = MIIADDRESS[4:0]; +   // MIISTATUS +   assign MIISTATUS[2:0] = { Nvalid, Busy, LinkFail }; +    +   eth_miim eth_miim +     (.Clk(wb_clk), .Reset(wb_rst),  +      .Divider(Divider), .NoPre(NoPre), .CtrlData(CtrlData), .Rgad(Rgad), .Fiad(Fiad),  +      .WCtrlData(WCtrlData), .RStat(RStat), .ScanStat(ScanStat), .Mdio(mdio), .Mdc(mdc),  +      .Busy(Busy), .Prsd(Prsd), .LinkFail(LinkFail), .Nvalid(Nvalid),  +      .WCtrlDataStart(WCtrlDataStart), .RStatStart(RStatStart),  +      .UpdateMIIRX_DATAReg(UpdateMIIRX_DATAReg) ); + +   always @(posedge wb_clk) +     case(wb_adr) +       0 : wb_dat_o <= misc_settings; +       1 : wb_dat_o <= ucast_addr[47:32]; +       2 : wb_dat_o <= ucast_addr[31:0]; +       3 : wb_dat_o <= mcast_addr[47:32]; +       4 : wb_dat_o <= mcast_addr[31:0]; +       5 : wb_dat_o <= {NoPre,Divider}; +       6 : wb_dat_o <= MIIADDRESS; +       7 : wb_dat_o <= CtrlData; +       8 : wb_dat_o <= MIICOMMAND; +       9 : wb_dat_o <= MIISTATUS; +       10: wb_dat_o <= MIIRX_DATA; +     endcase // case (wb_adr) +    +endmodule // simple_gemac_wb diff --git a/simple_gemac/simple_gemac_wrapper.v b/simple_gemac/simple_gemac_wrapper.v new file mode 100644 index 000000000..c9f5044f9 --- /dev/null +++ b/simple_gemac/simple_gemac_wrapper.v @@ -0,0 +1,74 @@ + +module simple_gemac_wrapper +  (input clk125, input reset, +   // GMII +   output GMII_GTX_CLK, output GMII_TX_EN, output GMII_TX_ER, output [7:0] GMII_TXD, +   input GMII_RX_CLK, input GMII_RX_DV, input GMII_RX_ER, input [7:0] GMII_RXD, +    +   // Flow Control Interface +   input pause_req, input [15:0] pause_time, +    +   // RX Client Interface +   output rx_clk, output [7:0] rx_ll_data, output rx_ll_sof, output rx_ll_eof, +   output rx_ll_error, output rx_ll_src_rdy, input rx_ll_dst_rdy, +    +   // TX Client Interface +   output tx_clk, input [7:0] tx_ll_data, input tx_ll_sof, input tx_ll_eof, +   input tx_ll_src_rdy, output tx_ll_dst_rdy, +    +   // Wishbone Interface +   input wb_clk, input wb_rst, input wb_stb, input wb_cyc, output wb_ack, input wb_we, +   input [7:0] wb_adr, input [31:0] wb_dat_i, output [31:0] wb_dat_o, +    +   // MIIM +   inout mdio, output mdc ); +    +   wire [7:0] rx_data, tx_data; +   wire       tx_clk, tx_valid, tx_error, tx_ack; +   wire       rx_clk, rx_valid, rx_error, rx_ack; + +   wire [47:0] ucast_addr, mcast_addr; +   wire pass_ucast, pass_mcast, pass_bcast, pass_pause, pass_all, pause_en; + +   wire rst_rxclk, rst_txclk; +   reset_sync reset_sync_tx (.clk(tx_clk),.reset_in(reset),.reset_out(rst_txclk)); +   reset_sync reset_sync_rx (.clk(rx_clk),.reset_in(reset),.reset_out(rst_rxclk)); + +   simple_gemac simple_gemac +     (.clk125(clk125),  .reset(reset), +      .GMII_GTX_CLK(GMII_GTX_CLK), .GMII_TX_EN(GMII_TX_EN),   +      .GMII_TX_ER(GMII_TX_ER), .GMII_TXD(GMII_TXD), +      .GMII_RX_CLK(GMII_RX_CLK), .GMII_RX_DV(GMII_RX_DV),   +      .GMII_RX_ER(GMII_RX_ER), .GMII_RXD(GMII_RXD), +      .pause_req(pause_req), .pause_time(pause_time), .pause_en(1), +      .ucast_addr(ucast_addr), .mcast_addr(mcast_addr), +      .pass_ucast(pass_ucast), .pass_mcast(pass_mcast), .pass_bcast(pass_bcast),  +      .pass_pause(pass_pause), .pass_all(pass_all), +      .rx_clk(rx_clk), .rx_data(rx_data), +      .rx_valid(rx_valid), .rx_error(rx_error), .rx_ack(rx_ack), +      .tx_clk(tx_clk), .tx_data(tx_data),  +      .tx_valid(tx_valid), .tx_error(tx_error), .tx_ack(tx_ack) +      ); +    +   simple_gemac_wb simple_gemac_wb +     (.wb_clk(wb_clk), .wb_rst(wb_rst), +      .wb_cyc(wb_cyc), .wb_stb(wb_stb), .wb_ack(wb_ack), .wb_we(wb_we), +      .wb_adr(wb_adr), .wb_dat_i(wb_dat_i), .wb_dat_o(wb_dat_o), +      .mdio(mdio), .mdc(mdc), +      .ucast_addr(ucast_addr), .mcast_addr(mcast_addr), +      .pass_ucast(pass_ucast), .pass_mcast(pass_mcast), .pass_bcast(pass_bcast),  +      .pass_pause(pass_pause), .pass_all(pass_all), .pause_en(pause_en) ); + +   rxmac_to_ll8 rx_adapt +     (.clk(rx_clk), .reset(rx_reset), .clear(0), +      .rx_data(rx_data), .rx_valid(rx_valid), .rx_error(rx_error), .rx_ack(rx_ack), +      .ll_data(rx_ll_data), .ll_sof(rx_ll_sof), .ll_eof(rx_ll_eof), .ll_error(rx_ll_error), +      .ll_src_rdy(rx_ll_src_rdy), .ll_dst_rdy(rx_ll_dst_rdy)); +    +   ll8_to_txmac ll8_to_txmac +     (.clk(tx_clk), .reset(tx_reset), .clear(0), +      .ll_data(tx_ll_data), .ll_sof(tx_ll_sof), .ll_eof(tx_ll_eof), +      .ll_src_rdy(tx_ll_src_rdy), .ll_dst_rdy(tx_ll_dst_rdy), +      .tx_data(tx_data), .tx_valid(tx_valid), .tx_error(tx_error), .tx_ack(tx_ack)); + +endmodule // simple_gemac_wrapper | 
