gateware

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit 112785d363e382214bfff21d6d064884d1781406
parent 6ef5a58eb0c8908a70335e429ebca27207e4e5d7
Author: Brian Swetland <swetland@frotz.net>
Date:   Wed, 22 Jan 2020 18:22:58 -0800

ethernet: rgmii rx and colorlight demo project

- eth_rgmii_rx handles the relatively simple processing
  of inbound gigabit ethernet packets, including discarding
  the preamble and validating the FCS
- colorlight project dumps packets on to VGA display
  connected to J1 (2bpp resistor-ladder dac style)
- packets are dumped in hex, the inverted byte at the end
  of each packet indicates FCS status (green is ok, red is not)
- tested on colorlight 5A-75E

Diffstat:
Ahdl/colorlight.lpf | 42++++++++++++++++++++++++++++++++++++++++++
Ahdl/colorlight.sv | 95+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ahdl/ethernet/eth_rgmii_rx.sv | 128+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ahdl/ethernet/eth_rgmii_rx_glue_ecp5.sv | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ahdl/lattice/ecp5_pll_25_125_250.v | 58++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aproject/colorlight.def | 9+++++++++
6 files changed, 392 insertions(+), 0 deletions(-)

diff --git a/hdl/colorlight.lpf b/hdl/colorlight.lpf @@ -0,0 +1,42 @@ +FREQUENCY NET "phy_clk" 25 MHZ; +FREQUENCY NET "phy0_rxc" 125 MHZ; + +fREQUENCY NET "clk250m" 250 MHZ; +FREQUENCY NET "clk125m" 125 MHZ; + +LOCATE COMP "phy_clk" SITE "P3"; +LOCATE COMP "phy_reset_n" SITE "P4"; + +LOCATE COMP "btn" SITE "R16"; + +LOCATE COMP "phy_mdc" SITE "N5"; +LOCATE COMP "phy_mdio" SITE "P5"; + +LOCATE COMP "phy0_gtxclk" SITE "G1"; +LOCATE COMP "phy0_txd[0]" SITE "G2"; +LOCATE COMP "phy0_txd[1]" SITE "H1"; +LOCATE COMP "phy0_txd[2]" SITE "J1"; +LOCATE COMP "phy0_txd[3]" SITE "J3"; +LOCATE COMP "phy0_tx_en" SITE "K1"; +LOCATE COMP "phy0_rxc" SITE "H2"; +LOCATE COMP "phy0_rxd[0]" SITE "K2"; +LOCATE COMP "phy0_rxd[1]" SITE "L1"; +LOCATE COMP "phy0_rxd[2]" SITE "N1"; +LOCATE COMP "phy0_rxd[3]" SITE "P1"; +LOCATE COMP "phy0_rx_dv" SITE "P2"; + +LOCATE COMP "j1r0" SITE "B3"; +LOCATE COMP "j1g0" SITE "A2"; +LOCATE COMP "j1b0" SITE "B2"; +LOCATE COMP "j1r1" SITE "B1"; +LOCATE COMP "j1g1" SITE "C2"; +LOCATE COMP "j1b1" SITE "C1"; +LOCATE COMP "glb_e" SITE "J17"; +LOCATE COMP "glb_a" SITE "F1"; +LOCATE COMP "glb_b" SITE "F2"; +LOCATE COMP "glb_c" SITE "E1"; +LOCATE COMP "glb_d" SITE "E2"; +LOCATE COMP "glb_clk" SITE "C18"; +LOCATE COMP "glb_alat" SITE "J18"; +LOCATE COMP "glb_bln" SITE "H16"; + diff --git a/hdl/colorlight.sv b/hdl/colorlight.sv @@ -0,0 +1,95 @@ +`default_nettype none + +module top( + input wire phy_clk, + output wire phy_reset_n, + input wire phy0_rxc, + input wire [3:0]phy0_rxd, + input wire phy0_rx_dv, +// output wire glb_clk, +// output wire glb_bln, + output wire j1r0, + output wire j1r1, + output wire j1g0, + output wire j1g1, + output wire j1b0, + output wire j1b1, + output wire glb_a, + output wire glb_b, + input wire btn +); + +wire clk25m = phy_clk; + +`ifdef PLL +wire clk125m; +wire clk250m; + +pll_25_125_250 pll( + .clk25m_in(phy_clk_in), + .clk125m_out(clk125m), + .clk250m_out(clk250m), + .locked() +); +`endif + +wire [7:0]rx_data; +wire rx_valid; +wire rx_sop; +wire rx_eop; +wire rx_crc_ok; + +eth_rgmii_rx eth_rx( + .rx_clk(phy0_rxc), + .pin_rx_dv(phy0_rx_dv), + .pin_rx_data(phy0_rxd), + .data(rx_data), + .valid(rx_valid), + .sop(rx_sop), + .eop(rx_eop), + .crc_ok(rx_crc_ok) +); + +assign j1r1 = j1r0; +assign j1b1 = j1b0; +assign j1g1 = j1g0; + +reg [31:0]reset = 32'd0; +always @(posedge clk25m) + reset <= { reset[30:0], 1'b1 }; + +assign phy_reset_n = reset[31]; + +reg [11:0]waddr = 12'd0; + +reg [27:0]color = 28'h1234567; + +always_ff @(posedge phy0_rxc) begin + color <= rx_eop ? { color[23:0], color[27:24] } : color; + waddr <= (rx_eop | rx_valid) ? (waddr + 12'd2) : waddr; +end + +wire [15:0]mark = rx_crc_ok ? { 16'h0200 } : { 16'h04FF }; + +display #( + .BPP(1), + .RGB(1), + .WIDE(0), + .HEXMODE(1) + ) display0 ( + .clk(clk25m), + .red(j1r0), + .grn(j1g0), + .blu(j1b0), + .hsync(glb_a), + .vsync(glb_b), + .active(), + .frame(), + .wclk(phy0_rxc), + .waddr(waddr), + .wdata(rx_eop ? mark : { color[27:24], 4'h0, rx_data }), + .we((rx_eop | rx_valid) & btn) +); + +endmodule + diff --git a/hdl/ethernet/eth_rgmii_rx.sv b/hdl/ethernet/eth_rgmii_rx.sv @@ -0,0 +1,128 @@ +// Copyright 2020 Brian Swetland <swetland@frotz.net> +// Licensed under the Apache License, Version 2.0. + +`default_nettype none + +module eth_rgmii_rx ( + // 2.5MHz / 25MHz / 125MHz RGMII clock + input wire rx_clk, + + // RGMII input + input wire pin_rx_dv, + input wire [3:0]pin_rx_data, + + // Packet byte data output + output reg [7:0] data = 0, + + // Active when data is a valid byte + output reg valid = 0, + + // Active for one rx_clk cycle when start of packet detected + // (start of preamble). Typically 8 rx_clk's before the first + // valid data byte arrives. + output reg sop = 0, + + // Active for one rx_clk cycle when the packet has ended + // (*after) the last valid data byte arrives + output reg eop = 0, + + // Active when eop is active if packet FCS was valid + output reg crc_ok = 0 +); + +// NOTES: +// 1. This is only functional for 1Gbe rates (125MHz clock) at present +// 2. It considers any packet preamble consisting of one or more 0x55s +// and ending with an 0xD5 valid + +wire rx_dv; +wire rx_err; +wire [7:0]rx_data; + +// hardware-specific io buffers, delays, etc. +eth_rgmii_rx_glue glue ( + .rx_clk(rx_clk), + .pin_rx_dv(pin_rx_dv), + .pin_rx_data(pin_rx_data), + .rx_dv(rx_dv), + .rx_err(rx_err), + .rx_data(rx_data) +); + +wire [31:0]crc; + +localparam IDLE = 2'd0; +localparam PREAMBLE = 2'd1; +localparam PACKET = 2'd2; +localparam INVALID = 2'd3; + +reg [1:0]state = IDLE; +reg [1:0]next_state; +reg next_valid; +reg [7:0]next_data; +reg next_sop; +reg next_eop; +reg next_crc_ok; +reg crc_en; + +always_comb begin + next_state = state; + next_data = data; + next_valid = 1'b0; + next_sop = 1'b0; + next_eop = 1'b0; + next_crc_ok = crc_ok; + crc_en = 1'b0; + + case (state) + IDLE: if (rx_dv) begin + if (rx_data != 8'h55) begin + next_state = INVALID; + end else begin + next_state = PREAMBLE; + next_crc_ok = 1'b0; + next_sop = 1'b1; + end + end + PREAMBLE: begin // .. 55 55 55 D5 + if (rx_data == 8'hD5) begin + next_state = PACKET; + end else if (rx_data != 8'h55) begin + next_state = INVALID; + end + end + PACKET: begin + if (rx_dv == 1'b1) begin + crc_en = 1'b1; + next_data = rx_data; + next_valid = 1'b1; + end else begin + next_crc_ok = (crc == 32'hDEBB20E3); + next_eop = 1'b1; + next_state = IDLE; + end + end + INVALID: if (rx_dv == 1'b0) begin + next_state = IDLE; + end + endcase +end + +always_ff @(posedge rx_clk) begin + state <= next_state; + data <= next_data; + valid <= next_valid; + sop <= next_sop; + eop <= next_eop; + crc_ok <= next_crc_ok; +end + +eth_crc32_8 crc32( + .clk(rx_clk), + .en(crc_en), + .rst(sop), + .din(rx_data), + .crc(crc) +); + +endmodule diff --git a/hdl/ethernet/eth_rgmii_rx_glue_ecp5.sv b/hdl/ethernet/eth_rgmii_rx_glue_ecp5.sv @@ -0,0 +1,60 @@ +// Copyright 2020 Brian Swetland <swetland@frotz.net> +// Licensed under the Apache License, Version 2.0. + +`default_nettype none + +module eth_rgmii_rx_glue ( + input wire rx_clk, + input wire pin_rx_dv, + input wire [3:0]pin_rx_data, + output wire rx_dv, + output wire rx_err, + output wire [7:0]rx_data +); + +`ifndef verilator +wire delay_rx_dv; +wire [3:0]delay_rx_data; + +DELAYF #( + .DEL_MODE("SCLK_CENTERED"), + .DEL_VALUE(80) // units of ~25ps + ) ctrl_delay ( + .LOADN(1), + .MOVE(0), + .DIRECTION(0), + .A(pin_rx_dv), + .Z(delay_rx_dv) +); +IDDRX1F ctrl_ddr ( + .D(delay_rx_dv), + .SCLK(rx_clk), + .RST(0), + .Q0(rx_dv), + .Q1(rx_err) +); + +genvar i; + +generate for (i = 0; i < 4; i++) begin +DELAYF #( + .DEL_MODE("SCLK_CENTERED"), + .DEL_VALUE(80) // units of ~25ps + ) data_delay ( + .LOADN(1), + .MOVE(0), + .DIRECTION(0), + .A(pin_rx_data[i]), + .Z(delay_rx_data[i]) +); +IDDRX1F data_ddr ( + .D(delay_rx_data[i]), + .SCLK(rx_clk), + .RST(0), + .Q0(rx_data[i]), + .Q1(rx_data[i+4]) +); +end endgenerate +`endif + +endmodule diff --git a/hdl/lattice/ecp5_pll_25_125_250.v b/hdl/lattice/ecp5_pll_25_125_250.v @@ -0,0 +1,58 @@ +// $ ecppll -i 25 -o 250 --clkout1 125 +// diamond 3.7 accepts this PLL +// diamond 3.8-3.9 is untested +// diamond 3.10 or higher is likely to abort with error about unable to use feedback signal +// cause of this could be from wrong CPHASE/FPHASE parameters +module pll_25_125_250 +( + input clk25m_in, // 25 MHz, 0 deg + output clk250m_out, // 250 MHz, 0 deg + output clk125m_out, // 125 MHz, 0 deg + output locked +); + +`ifndef verilator +(* FREQUENCY_PIN_CLKI="25" *) +(* FREQUENCY_PIN_CLKOP="250" *) +(* FREQUENCY_PIN_CLKOS="125" *) +(* ICP_CURRENT="12" *) (* LPF_RESISTOR="8" *) (* MFG_ENABLE_FILTEROPAMP="1" *) (* MFG_GMCREF_SEL="2" *) +EHXPLLL #( + .PLLRST_ENA("DISABLED"), + .INTFB_WAKE("DISABLED"), + .STDBY_ENABLE("DISABLED"), + .DPHASE_SOURCE("DISABLED"), + .OUTDIVIDER_MUXA("DIVA"), + .OUTDIVIDER_MUXB("DIVB"), + .OUTDIVIDER_MUXC("DIVC"), + .OUTDIVIDER_MUXD("DIVD"), + .CLKI_DIV(1), + .CLKOP_ENABLE("ENABLED"), + .CLKOP_DIV(2), + .CLKOP_CPHASE(0), + .CLKOP_FPHASE(0), + .CLKOS_ENABLE("ENABLED"), + .CLKOS_DIV(4), + .CLKOS_CPHASE(0), + .CLKOS_FPHASE(0), + .FEEDBK_PATH("CLKOP"), + .CLKFB_DIV(10) + ) pll_i ( + .RST(1'b0), + .STDBY(1'b0), + .CLKI(clk25m_in), + .CLKOP(clk250m_out), + .CLKOS(clk125m_out), + .CLKFB(clk250m_out), + .CLKINTFB(), + .PHASESEL0(1'b0), + .PHASESEL1(1'b0), + .PHASEDIR(1'b1), + .PHASESTEP(1'b1), + .PHASELOADREG(1'b1), + .PLLWAKESYNC(1'b0), + .ENCLKOP(1'b0), + .LOCK(locked) + ); +`endif + +endmodule diff --git a/project/colorlight.def b/project/colorlight.def @@ -0,0 +1,9 @@ +PROJECT_TYPE := nextpnr-ecp5 + +PROJECT_SRCS := hdl/colorlight.sv hdl/colorlight.lpf +PROJECT_SRCS += hdl/lattice/ecp5_pll_25_125_250.v +PROJECT_SRCS += hdl/ethernet/eth_rgmii_rx.sv hdl/ethernet/eth_rgmii_rx_glue_ecp5.sv +PROJECT_SRCS += hdl/ethernet/eth_crc32_8.sv +PROJECT_SRCS += hdl/display/display.sv hdl/display/display_timing.sv + +PROJECT_NEXTPNR_OPTS := --25k --package CABGA381 --speed 6