From a6673297d4bc1fb96016faab511278894f186c5a Mon Sep 17 00:00:00 2001 From: David Lenfesty Date: Tue, 10 Jan 2023 20:30:00 -0700 Subject: [PATCH] gateware: failed attempt to add my own peripheral to litex moving to amaranth because it at least has API docs :( --- gateware/led_gpio.py | 14 ++++++++ gateware/led_gpio.v | 80 ++++++++++++++++++++++++++++++++++++++++++++ gateware/main.py | 23 +++++++++++++ 3 files changed, 117 insertions(+) create mode 100644 gateware/led_gpio.py create mode 100644 gateware/led_gpio.v diff --git a/gateware/led_gpio.py b/gateware/led_gpio.py new file mode 100644 index 0000000..d839147 --- /dev/null +++ b/gateware/led_gpio.py @@ -0,0 +1,14 @@ +from migen import * + +from litex.soc.interconnect.csr import * + +from pathlib import Path + +class LedGpio(AutoCSR, Module): + def __init__(self, platform, led: Signal): + #source = Path(__file__).parent / "led_gpio.v" + #platform.add_source(source) + + self.register = CSRStorage(8) + + self.comb += led.eq(self.register.storage[0]) diff --git a/gateware/led_gpio.v b/gateware/led_gpio.v new file mode 100644 index 0000000..2a70e66 --- /dev/null +++ b/gateware/led_gpio.v @@ -0,0 +1,80 @@ +`default_nettype none + +module led_gpio #( + parameter DATA_WIDTH = 32, + parameter ADR_WIDTH = 32, + parameter SEL_WIDTH = 4 // ??? +) ( + // Main signals + input wire clk, + input wire rst, + + // verilator lint_off UNUSED + // ---- LiteX Wishbone interface + // Address + input wire [ADR_WIDTH-1:0] adr, + // Data input (write) + input wire [DATA_WIDTH-1:0] dat_w, + // Data output (read) + output reg [DATA_WIDTH-1:0] dat_r, + // What parts of data are valid? + input wire [SEL_WIDTH-1:0] sel, + // Start cycle + input wire cyc, + // Enables wishbone interface + input wire stb, + // Bus cycle finished + output reg ack, + // Is this cycle a read or write? + input wire we, + // Cycle type + input wire [2:0] cti, + // Burst type + input wire [1:0] bte, + // Asserted if cycle completes with error + output wire err, + // verilator lint_on UNUSED + + // Output + output wire led +); + +// Tracks if we have started a new wishbone cycle. This or similar is needed so we don't +// think we're handling multiple wishbone cycles inside one. +reg cycle_started; +reg led_state; + +always @(posedge clk) begin + // Always reset the cycle started + cycle_started <= 0; + + if (rst) begin + led_state <= 0; + end else begin + // TODO ADR checking + ack <= 0; + err <= 0; // We never have any bus errors + dat_r <= 0; + + if (!cycle_started && stb && cyc) begin + cycle_started <= 1; // Start cycle to be reset next clock + ack <= 1; // We always acknowledge immediately, we only take one clock to process + + if (we) begin + // Writes to LED, so we need to assign output + led_state <= dat_w[0]; + end else begin + // We want reads to get LED status + dat_r <= 3; + end + end + end +end + +always @(*) begin + led = !led_state; +end + +endmodule + +`default_nettype wire diff --git a/gateware/main.py b/gateware/main.py index d3b861c..275a426 100755 --- a/gateware/main.py +++ b/gateware/main.py @@ -15,11 +15,17 @@ from litex.soc.integration.builder import * from litex.soc.interconnect.csr import * +from litex.soc.interconnect import wishbone +from litex.soc.integration.soc import SoCRegion + from litedram.modules import M12L64322A from litedram.phy import GENSDRPHY, HalfRateGENSDRPHY from liteeth.phy.ecp5rgmii import LiteEthPHYRGMII +# My hardware +import led_gpio + # Module to configure clocks and resets class _CRG(Module): def __init__(self, platform, sys_clk_freq, use_internal_osc=False, with_usb_pll=False, with_video_pll=False, sdram_rate="1:1"): @@ -86,6 +92,10 @@ class _CRG(Module): # SoC definition - this basically instantiates hardware class SoC(SoCCore): + + csr_peripherals = ["led_gpio"] + #csr_map_update(SoCCore.csr_map, csr_peripherals) + # While there are more configurations in what I'm basing this off of, I'm reducing it to # one supported config. def __init__(self, **kwargs): @@ -113,6 +123,19 @@ class SoC(SoCCore): l2_cache_size = 8192, ) + # LED blinky thing + #wb_interface = wishbone.Interface() + led = platform.request("user_led_n") + self.submodules.led_gpio = led_gpio.LedGpio(platform, led) + #wb_interface.connect_to_pads(led, mode="slave") + + #self.add_memory_region("led_gpio", 0x8F000000, 0x1000, type="dawda") + #self.add_wb_slave(0x8F000000, wb_interface, 0x1000) + + # vague attempt based on + #region = SoCRegion(origin=0x8F000000, size=0x1000, cached=False) + #self.bus.add_slave(name="led_gpio", slave=wb_interface, region=region) + # TODO ethernet