gateware: failed attempt to add my own peripheral to litex

moving to amaranth because it at least has API docs :(
This commit is contained in:
David Lenfesty 2023-01-10 20:30:00 -07:00
parent d46dcc4a43
commit a6673297d4
3 changed files with 117 additions and 0 deletions

14
gateware/led_gpio.py Normal file
View File

@ -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])

80
gateware/led_gpio.v Normal file
View File

@ -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

View File

@ -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