add base.v

This commit is contained in:
Peter McGoron 2023-03-09 04:17:41 +00:00
parent 89938a2ff6
commit 295eb8fad8
2 changed files with 258 additions and 159 deletions

View File

@ -3,20 +3,20 @@
* *
* This crossbar is entirely controlled by the kernel. * This crossbar is entirely controlled by the kernel.
*/ */
module spi_crossbar #( module spi_switch #(
parameter PORTS = 8, parameter PORTS = 3,
( (
input select[PORTS-1:0], input select[PORTS-1:0],
output mosi, output mosi,
input miso, input miso,
output sck, output sck,
output ss, output ss_L,
input mosi_ports[PORTS-1:0], input [PORTS-1:0] mosi_ports,
output miso_ports[PORTS-1:0], output [PORTS-1:0] miso_ports,
input sck_ports[PORTS-1:0], input [PORTS-1:0] sck_ports,
input ss_ports[PORTS-1:0] input [PORTS-1:0] ss_L_ports
); );
/* Avoid using for loops, they might not synthesize correctly. /* Avoid using for loops, they might not synthesize correctly.
@ -27,23 +27,21 @@ module spi_crossbar #(
mosi = mosi_ports[n]; \ mosi = mosi_ports[n]; \
miso = miso_ports[n]; \ miso = miso_ports[n]; \
sck = sck_ports[n]; \ sck = sck_ports[n]; \
ss = ss_ports[n] ss_L = ss_L_ports[n]
`define check_select(n) \ `define check_select(n) \
if (select[n]) begin \ if (select[n]) begin \
do_select(n); \ do_select(n); \
end end
always @(*) begin generate if (PORTS == 2) always @(*) begin
check_select(7) check_select(2)
else check_select(6)
else check_select(5)
else check_select(4)
else check_select(3)
else check_select(2)
else check_select(1) else check_select(1)
else do_select(0) else do_select(0)
end end else always @(*) begin
check_select(1)
else do_select(0)
end endgenerate
endmodule endmodule
`undefineall `undefineall

View File

@ -20,154 +20,245 @@ from liteeth.phy.mii import LiteEthPHYMII
# IO with Subsignals make Record types, which have the name of the # IO with Subsignals make Record types, which have the name of the
# subsignal as an attribute. # subsignal as an attribute.
io = [ io = [
("dac", 0, ("dac_ss", 0, Pins("G13 D13 E15 J17 U12 U14 D4 E2"), IOStandard("LVCMOS33")),
Subsignal("ss", Pins("G13")), ("dac_mosi", 0, Pins("B11 B18 E16 J18 V12 V14 D3 D2"), IOStandard("LVCMOS33")),
Subsignal("mosi", Pins("B11")), ("dac_miso", 0, Pins("A11 A18 D15 K15 V10 T13 F4 H2"), IOStandard("LVCMOS33")),
Subsignal("miso", Pins("A11")), ("dac_sck", 0, Pins("D12 K16 C15 J15 V11 U13 F3 G2"), IOStandard("LVCMOS33")),
Subsignal("sck", Pins("D12")), ("adc_conv", 0, Pins("V15 T11 N15 U18 U11 R10 R16 U17"), IOStandard("LVCMOS33")),
IOStandard("LVCMOS33")), ("adc_sck", 0, Pins("U16 R12 M16 R17 V16 R11 N16 T18"), IOStandard("LVCMOS33")),
("dac", 1, ("adc_sdo", 0, Pins("P14 T14 V17 P17 M13 R13 N14 R18"), IOStandard("LVCMOS33"))
Subsignal("ss", Pins("D13")),
Subsignal("mosi", Pins("B18")),
Subsignal("miso", Pins("A18")),
Subsignal("sck", Pins("K16")),
IOStandard("LVCMOS33")),
("dac", 2,
Subsignal("ss", Pins("E15")),
Subsignal("mosi", Pins("E16")),
Subsignal("miso", Pins("D15")),
Subsignal("sck", Pins("C15")),
IOStandard("LVCMOS33")),
("dac", 3,
Subsignal("ss", Pins("J17")),
Subsignal("mosi", Pins("J18")),
Subsignal("miso", Pins("K15")),
Subsignal("sck", Pins("J15")),
IOStandard("LVCMOS33")),
("dac", 4,
Subsignal("ss", Pins("U12")),
Subsignal("mosi", Pins("V12")),
Subsignal("miso", Pins("V10")),
Subsignal("sck", Pins("V11")),
IOStandard("LVCMOS33")),
("dac", 5,
Subsignal("ss", Pins("U14")),
Subsignal("mosi", Pins("V14")),
Subsignal("miso", Pins("T13")),
Subsignal("sck", Pins("U13")),
IOStandard("LVCMOS33")),
("dac", 6,
Subsignal("ss", Pins("D4")),
Subsignal("mosi", Pins("D3")),
Subsignal("miso", Pins("F4")),
Subsignal("sck", Pins("F3")),
IOStandard("LVCMOS33")),
("dac", 7,
Subsignal("ss", Pins("E2")),
Subsignal("mosi", Pins("D2")),
Subsignal("miso", Pins("H2")),
Subsignal("sck", Pins("G2")),
IOStandard("LVCMOS33")),
("adc", 0,
Subsignal("conv", Pins("V15")),
Subsignal("sck", Pins("U16")),
Subsignal("sdo", Pins("P14")),
IOStandard("LVCMOS33")),
("adc", 1,
Subsignal("conv", Pins("T11")),
Subsignal("sck", Pins("R12")),
Subsignal("sdo", Pins("T14")),
IOStandard("LVCMOS33")),
("adc", 2,
Subsignal("conv", Pins("N15")),
Subsignal("sck", Pins("M16")),
Subsignal("sdo", Pins("V17")),
IOStandard("LVCMOS33")),
("adc", 3,
Subsignal("conv", Pins("U18")),
Subsignal("sck", Pins("R17")),
Subsignal("sdo", Pins("P17")),
IOStandard("LVCMOS33")),
("adc", 4,
Subsignal("conv", Pins("U11")),
Subsignal("sck", Pins("V16")),
Subsignal("sdo", Pins("M13")),
IOStandard("LVCMOS33")),
("adc", 5,
Subsignal("conv", Pins("R10")),
Subsignal("sck", Pins("R11")),
Subsignal("sdo", Pins("R13")),
IOStandard("LVCMOS33")),
("adc", 6,
Subsignal("conv", Pins("R16")),
Subsignal("sck", Pins("N16")),
Subsignal("sdo", Pins("N14")),
IOStandard("LVCMOS33")),
("adc", 7,
Subsignal("conv", Pins("U17")),
Subsignal("sck", Pins("T18")),
Subsignal("sdo", Pins("R18")),
IOStandard("LVCMOS33"))
] ]
class SPIMaster(Module, AutoCSR): class Base(Module, AutoCSR):
def __init__(self, wid, clk, pins): def __init__(self, clk, sdram):
self.pins = pins for i in range(0,8):
setattr(self, f"dac_sel_{i}", CSRStorage(3))
setattr(self, f"dac_finished_{i}", CSRStatus(1))
setattr(self, f"dac_arm_{i}", CSRStorage(1))
setattr(self, f"from_dac_{i}", CSRStatus(24))
setattr(self, f"to_dac_{i}", CSRStorage(24))
setattr(self, f"wf_arm_{i}", CSRStorage(1))
setattr(self, f"wf_time_to_wait_{i}", CSRStorage(16))
setattr(self, f"wf_refresh_start_{i}", CSRStorage(1))
setattr(self, f"wf_refresh_finished_{i}", CSRStatus(1))
setattr(self, f"wf_start_addr_{i}", CSRStorage(32))
port = sdram.crossbar.get_port()
setattr(self, f"wf_sdram_{i}", LiteDRAMDMAReader(port))
self.from_slave = CSRStatus(wid, description="Data from slave (Status)") setattr(self, f"adc_finished_{i}", CSRStatus(1))
self.to_slave = CSRStorage(wid, description="Data to slave (Control)") setattr(self, f"adc_arm_{i}", CSRStorage(1))
self.finished = CSRStatus(1, description="Finished transmission (Status)") setattr(self, f"from_adc_{i}", CSRStatus(32))
self.arm = CSRStorage(1, description="Initiate transmission (Status)")
self.ss = CSRStorage(1, description="Slave Select (active high)")
self.comb += self.pins.ss.eq(~self.ss.storage) self.adc_sel_0 = CSRStorage(2)
self.cl_in_loop = CSRStatus(1)
self.cl_cmd = CSRStorage(64)
self.cl_word_in = CSRStorage(32)
self.cl_word_out = CSRStatus(32)
self.cl_start_cmd = CSRStorage(1)
self.cl_finish_cmd = CSRStatus(1)
import math self.specials = Instance("base",
i_clk(clk),
.i_dac_miso(platform.request("dac_miso")),
.o_dac_mosi(platform.request("dac_mosi")),
.o_dac_sck(platform.request("dac_sck")),
.o_dac_ss_L(platform.request("dac_ss_L")),
.o_adc_conv(platform.request("adc_conv")),
.i_adc_sdo(platform.request("adc_sdo")),
.o_adc_sck(platform.request("adc_sck")),
self.specials += Instance("spi_master", # dac_0
p_WID=wid, .i_dac_sel_0(self.dac_sel_0.storage),
p_WID_LEN=math.ceil(math.log2(wid)), .o_dac_finished_0(self.dac_finished_0.status),
p_CYCLE_HALF_WAIT = 3, # 3 + 2 = 5, total sck = 10 cycles .i_dac_arm_0(self.dac_arm_0.storage),
p_TIMER_LEN = 3, .o_from_dac_0(self.from_dac_0.status),
p_POLARITY = 0, .i_to_dac_0(self.to_dac_0.storage),
p_PHASE = 1,
i_clk = clk,
o_from_slave = self.from_slave.status,
i_miso = self.pins.miso,
i_to_slave = self.to_slave.storage,
o_mosi = self.pins.mosi,
o_sck_wire = self.pins.sck,
o_finished = self.finished.status,
i_arm = self.arm.storage
)
class SPIMasterReadOnly(Module, AutoCSR): .i_wf_arm_0(self.wf_arm_0.storage),
def __init__(self, wid, clk, pins): .i_wf_time_to_wait_0(self.wf_time_to_wait_0.storage),
self.pins = pins .i_wf_refresh_start_0(self.wf_refresh_start_0.storage),
.o_wf_refresh_finished_0(self.wf_refresh_finished_0.status),
.o_wf_start_addr_0(self.wf_start_addr_0.storage),
self.from_slave = CSRStatus(wid, description="Data from slave (Status)description=") .o_wf_ram_dma_addr_0(self.wf_sdram_0.sink.address),
self.finished = CSRStatus(1, description="Finished transmission (Status)description=") .i_wf_ram_word_0(self.wf_sdram_0.source.data),
self.arm = CSRStorage(1, description="Initiate transmission (Status)description=") .o_wf_ram_read_0(self.wf_sdram_0.sink.valid),
self.conv = CSRStorage(1, description="Conversion (active high)description=") .i_wf_ram_valid_0(self.wf_sdram_0.source.valid),
self.comb += self.pins.conv.eq(self.conv.storage) # dac_1
.i_dac_sel_1(self.dac_sel_1.storage),
.o_dac_finished_1(self.dac_finished_1.status),
.i_dac_arm_1(self.dac_arm_1.storage),
.o_from_dac_1(self.from_dac_1.status),
.i_to_dac_1(self.to_dac_1.storage),
import math .i_wf_arm_1(self.wf_arm_1.storage),
.i_wf_time_to_wait_1(self.wf_time_to_wait_1.storage),
.i_wf_refresh_start_1(self.wf_refresh_start_1.storage),
.o_wf_refresh_finished_1(self.wf_refresh_finished_1.status),
.o_wf_start_addr_1(self.wf_start_addr_1.storage),
self.specials += Instance("spi_master_no_write", .o_wf_ram_dma_addr_1(self.wf_sdram_1.sink.address),
p_WID=wid, .i_wf_ram_word_1(self.wf_sdram_1.source.data),
p_WID_LEN=math.ceil(math.log2(wid)), .o_wf_ram_read_1(self.wf_sdram_1.sink.valid),
p_CYCLE_HALF_WAIT = 1, # 1 + 2 = 3, total sck = 6 cycles .i_wf_ram_valid_1(self.wf_sdram_1.source.valid),
p_TIMER_LEN = 3,
p_POLARITY = 1, # dac_2
p_PHASE = 0, .i_dac_sel_2(self.dac_sel_2.storage),
i_clk = clk, .o_dac_finished_2(self.dac_finished_2.status),
o_from_slave = self.from_slave.status, .i_dac_arm_2(self.dac_arm_2.storage),
i_miso = self.pins.sdo, .o_from_dac_2(self.from_dac_2.status),
o_sck_wire = self.pins.sck, .i_to_dac_2(self.to_dac_2.storage),
o_finished = self.finished.status,
i_arm = self.arm.storage .i_wf_arm_2(self.wf_arm_2.storage),
.i_wf_time_to_wait_2(self.wf_time_to_wait_2.storage),
.i_wf_refresh_start_2(self.wf_refresh_start_2.storage),
.o_wf_refresh_finished_2(self.wf_refresh_finished_2.status),
.o_wf_start_addr_2(self.wf_start_addr_2.storage),
.o_wf_ram_dma_addr_2(self.wf_sdram_2.sink.address),
.i_wf_ram_word_2(self.wf_sdram_2.source.data),
.o_wf_ram_read_2(self.wf_sdram_2.sink.valid),
.i_wf_ram_valid_2(self.wf_sdram_2.source.valid),
# dac_3
.i_dac_sel_3(self.dac_sel_3.storage),
.o_dac_finished_3(self.dac_finished_3.status),
.i_dac_arm_3(self.dac_arm_3.storage),
.o_from_dac_3(self.from_dac_3.status),
.i_to_dac_3(self.to_dac_3.storage),
.i_wf_arm_3(self.wf_arm_3.storage),
.i_wf_time_to_wait_3(self.wf_time_to_wait_3.storage),
.i_wf_refresh_start_3(self.wf_refresh_start_3.storage),
.o_wf_refresh_finished_3(self.wf_refresh_finished_3.status),
.o_wf_start_addr_3(self.wf_start_addr_3.storage),
.o_wf_ram_dma_addr_3(self.wf_sdram_3.sink.address),
.i_wf_ram_word_3(self.wf_sdram_3.source.data),
.o_wf_ram_read_3(self.wf_sdram_3.sink.valid),
.i_wf_ram_valid_3(self.wf_sdram_3.source.valid),
# dac_4
.i_dac_sel_4(self.dac_sel_4.storage),
.o_dac_finished_4(self.dac_finished_4.status),
.i_dac_arm_4(self.dac_arm_4.storage),
.o_from_dac_4(self.from_dac_4.status),
.i_to_dac_4(self.to_dac_4.storage),
.i_wf_arm_4(self.wf_arm_4.storage),
.i_wf_time_to_wait_4(self.wf_time_to_wait_4.storage),
.i_wf_refresh_start_4(self.wf_refresh_start_4.storage),
.o_wf_refresh_finished_4(self.wf_refresh_finished_4.status),
.o_wf_start_addr_4(self.wf_start_addr_4.storage),
.o_wf_ram_dma_addr_4(self.wf_sdram_4.sink.address),
.i_wf_ram_word_4(self.wf_sdram_4.source.data),
.o_wf_ram_read_4(self.wf_sdram_4.sink.valid),
.i_wf_ram_valid_4(self.wf_sdram_4.source.valid),
# dac_5
.i_dac_sel_5(self.dac_sel_5.storage),
.o_dac_finished_5(self.dac_finished_5.status),
.i_dac_arm_5(self.dac_arm_5.storage),
.o_from_dac_5(self.from_dac_5.status),
.i_to_dac_5(self.to_dac_5.storage),
.i_wf_arm_5(self.wf_arm_5.storage),
.i_wf_time_to_wait_5(self.wf_time_to_wait_5.storage),
.i_wf_refresh_start_5(self.wf_refresh_start_5.storage),
.o_wf_refresh_finished_5(self.wf_refresh_finished_5.status),
.o_wf_start_addr_5(self.wf_start_addr_5.storage),
.o_wf_ram_dma_addr_5(self.wf_sdram_5.sink.address),
.i_wf_ram_word_5(self.wf_sdram_5.source.data),
.o_wf_ram_read_5(self.wf_sdram_5.sink.valid),
.i_wf_ram_valid_5(self.wf_sdram_5.source.valid),
# dac_6
.i_dac_sel_6(self.dac_sel_6.storage),
.o_dac_finished_6(self.dac_finished_6.status),
.i_dac_arm_6(self.dac_arm_6.storage),
.o_from_dac_6(self.from_dac_6.status),
.i_to_dac_6(self.to_dac_6.storage),
.i_wf_arm_6(self.wf_arm_6.storage),
.i_wf_time_to_wait_6(self.wf_time_to_wait_6.storage),
.i_wf_refresh_start_6(self.wf_refresh_start_6.storage),
.o_wf_refresh_finished_6(self.wf_refresh_finished_6.status),
.o_wf_start_addr_6(self.wf_start_addr_6.storage),
.o_wf_ram_dma_addr_6(self.wf_sdram_6.sink.address),
.i_wf_ram_word_6(self.wf_sdram_6.source.data),
.o_wf_ram_read_6(self.wf_sdram_6.sink.valid),
.i_wf_ram_valid_6(self.wf_sdram_6.source.valid),
# dac_7
.i_dac_sel_7(self.dac_sel_7.storage),
.o_dac_finished_7(self.dac_finished_7.status),
.i_dac_arm_7(self.dac_arm_7.storage),
.o_from_dac_7(self.from_dac_7.status),
.i_to_dac_7(self.to_dac_7.storage),
.i_wf_arm_7(self.wf_arm_7.storage),
.i_wf_time_to_wait_7(self.wf_time_to_wait_7.storage),
.i_wf_refresh_start_7(self.wf_refresh_start_7.storage),
.o_wf_refresh_finished_7(self.wf_refresh_finished_7.status),
.o_wf_start_addr_7(self.wf_start_addr_7.storage),
.o_wf_ram_dma_addr_7(self.wf_sdram_7.sink.address),
.i_wf_ram_word_7(self.wf_sdram_7.source.data),
.o_wf_ram_read_7(self.wf_sdram_7.sink.valid),
.i_wf_ram_valid_7(self.wf_sdram_7.source.valid),
.i_adc_sel_0(self.adc_sel_0.storage),
# adc_0
.o_adc_finished_0(self.adc_finished_0.status),
.i_adc_arm_0(self.adc_arm_0.storage),
.o_from_adc_0(self.from_adc_0.status),
# adc_1
.o_adc_finished_1(self.adc_finished_1.status),
.i_adc_arm_1(self.adc_arm_1.storage),
.o_from_adc_1(self.from_adc_1.status),
# adc_2
.o_adc_finished_2(self.adc_finished_2.status),
.i_adc_arm_2(self.adc_arm_2.storage),
.o_from_adc_2(self.from_adc_2.status),
# adc_3
.o_adc_finished_3(self.adc_finished_3.status),
.i_adc_arm_3(self.adc_arm_3.storage),
.o_from_adc_3(self.from_adc_3.status),
# adc_4
.o_adc_finished_4(self.adc_finished_4.status),
.i_adc_arm_4(self.adc_arm_4.storage),
.o_from_adc_4(self.from_adc_4.status),
# adc_5
.o_adc_finished_5(self.adc_finished_5.status),
.i_adc_arm_5(self.adc_arm_5.storage),
.o_from_adc_5(self.from_adc_5.status),
# adc_6
.o_adc_finished_6(self.adc_finished_6.status),
.i_adc_arm_6(self.adc_arm_6.storage),
.o_from_adc_6(self.from_adc_6.status),
# adc_7
.o_adc_finished_7(self.adc_finished_7.status),
.i_adc_arm_7(self.adc_arm_7.storage),
.o_from_adc_7(self.from_adc_7.status),
.o_cl_in_loop(self.cl_in_loop.status),
.i_cl_cmd(self.cl_cmd.storage),
.i_cl_word_in(self.cl_word_in.storage),
.o_cl_word_out(self.cl_word_out.status),
.i_cl_start_cmd(self.cl_start_cmd.storage),
.o_cl_finish_cmd(self.cl_finish_cmd.status)
) )
# Clock and Reset Generator # Clock and Reset Generator
@ -207,8 +298,16 @@ class CryoSNOM1SoC(SoCCore):
sys_clk_freq = int(100e6) sys_clk_freq = int(100e6)
platform = board_spec.Platform(variant=variant, toolchain="symbiflow") platform = board_spec.Platform(variant=variant, toolchain="symbiflow")
self.submodules.crg = _CRG(platform, sys_clk_freq, True) self.submodules.crg = _CRG(platform, sys_clk_freq, True)
platform.add_source("rtl/spi/spi_master.v") platform.add_source("rtl/spi/spi_master_ss.v")
platform.add_source("rtl/spi/spi_master_no_write.v") platform.add_source("rtl/spi/spi_master_ss_no_write.v")
platform.add_source("rtl/control_loop/sign_extend.v")
platform.add_source("rtl/control_loop/intsat.v")
platform.add_source("rtl/control_loop/boothmul.v")
platform.add_source("rtl/control_loop/control_loop_math.v")
platform.add_source("rtl/control_loop/control_loop.v")
platform.add_source("rtl/control_loop/spi_switch.v")
platform.add_source("rtl/waveform/waveform.v")
platform.add_source("rtl/spi/base/base.v")
# SoCCore does not have sane defaults (no integrated rom) # SoCCore does not have sane defaults (no integrated rom)
SoCCore.__init__(self, SoCCore.__init__(self,
@ -229,10 +328,14 @@ class CryoSNOM1SoC(SoCCore):
csr_ordering="big", csr_ordering="big",
timer_uptime = True) timer_uptime = True)
# This initializes the connection to the physical DRAM interface.
self.submodules.ddrphy = s7ddrphy.A7DDRPHY(platform.request("ddram"), self.submodules.ddrphy = s7ddrphy.A7DDRPHY(platform.request("ddram"),
memtype = "DDR3", memtype = "DDR3",
nphases = 4, nphases = 4,
sys_clk_freq = sys_clk_freq) sys_clk_freq = sys_clk_freq)
# Synchronous dynamic ram. This is what controls all access to RAM.
# This houses the "crossbar", which negotiates all RAM accesses to different
# modules, including the verilog interfaces (waveforms etc.)
self.add_sdram("sdram", self.add_sdram("sdram",
phy = self.ddrphy, phy = self.ddrphy,
module = MT41K128M16(sys_clk_freq, "1:4"), module = MT41K128M16(sys_clk_freq, "1:4"),
@ -246,9 +349,7 @@ class CryoSNOM1SoC(SoCCore):
# Add the DAC and ADC pins as GPIO. They will be used directly # Add the DAC and ADC pins as GPIO. They will be used directly
# by Zephyr. # by Zephyr.
platform.add_extension(io) platform.add_extension(io)
for i in range(0,8): self.submodules.sdram = Base(ClockSignal(), self.sdram)
setattr(self.submodules, f"dac{i}", SPIMaster(24, ClockSignal(), platform.request("dac", i)))
setattr(self.submodules, f"adc{i}", SPIMasterReadOnly(24, ClockSignal(), platform.request("adc", i)))
def main(): def main():
soc = CryoSNOM1SoC("a7-35") soc = CryoSNOM1SoC("a7-35")