forked from M-Labs/nix-servo
194 lines
7.5 KiB
Python
194 lines
7.5 KiB
Python
|
# This file is part of Fast Servo Software Package.
|
||
|
#
|
||
|
# Copyright (C) 2023 Jakub Matyas
|
||
|
# Warsaw University of Technology <jakubk.m@gmail.com>
|
||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||
|
#
|
||
|
# This program is free software: you can redistribute it and/or modify
|
||
|
# it under the terms of the GNU General Public License as published by
|
||
|
# the Free Software Foundation, either version 3 of the License, or
|
||
|
# (at your option) any later version.
|
||
|
#
|
||
|
# This program is distributed in the hope that it will be useful,
|
||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
# GNU General Public License for more details.
|
||
|
#
|
||
|
# You should have received a copy of the GNU General Public License
|
||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||
|
|
||
|
from migen import *
|
||
|
|
||
|
|
||
|
class PS7(Module):
|
||
|
def __init__(self, platform, ps7_name=None):
|
||
|
self.frstn = Signal()
|
||
|
self.ps7_tcl = []
|
||
|
self.platform = platform
|
||
|
|
||
|
self.ps7_name = "Zynq" if ps7_name is None else ps7_name
|
||
|
|
||
|
ps7_clk = platform.request("ps7_clk")
|
||
|
ps7_porb = platform.request("ps7_porb")
|
||
|
ps7_srstb = platform.request("ps7_srstb")
|
||
|
ps7_mio = platform.request("ps7_mio")
|
||
|
ps7_ddram = platform.request("ps7_ddram")
|
||
|
|
||
|
self.cpu_params = dict(
|
||
|
# Clk / Rst.
|
||
|
io_PS_CLK = ps7_clk,
|
||
|
io_PS_PORB = ps7_porb,
|
||
|
io_PS_SRSTB = ps7_srstb,
|
||
|
|
||
|
# MIO.
|
||
|
io_MIO = ps7_mio,
|
||
|
|
||
|
# DDRAM.
|
||
|
io_DDR_Addr = ps7_ddram.addr,
|
||
|
io_DDR_BankAddr = ps7_ddram.ba,
|
||
|
io_DDR_CAS_n = ps7_ddram.cas_n,
|
||
|
io_DDR_Clk_n = ps7_ddram.ck_n,
|
||
|
io_DDR_Clk = ps7_ddram.ck_p,
|
||
|
io_DDR_CKE = ps7_ddram.cke,
|
||
|
io_DDR_CS_n = ps7_ddram.cs_n,
|
||
|
io_DDR_DM = ps7_ddram.dm,
|
||
|
io_DDR_DQ = ps7_ddram.dq,
|
||
|
io_DDR_DQS_n = ps7_ddram.dqs_n,
|
||
|
io_DDR_DQS = ps7_ddram.dqs_p,
|
||
|
io_DDR_ODT = ps7_ddram.odt,
|
||
|
io_DDR_RAS_n = ps7_ddram.ras_n,
|
||
|
io_DDR_DRSTB = ps7_ddram.reset_n,
|
||
|
io_DDR_WEB = ps7_ddram.we_n,
|
||
|
io_DDR_VRN = ps7_ddram.vrn,
|
||
|
io_DDR_VRP = ps7_ddram.vrp,
|
||
|
|
||
|
# USB0.
|
||
|
# i_USB0_VBUS_PWRFAULT = 0,
|
||
|
|
||
|
# Fabric Clk / Rst.
|
||
|
# o_FCLK_CLK0 = ClockSignal("ps7"),
|
||
|
o_FCLK_RESET0_N = self.frstn
|
||
|
)
|
||
|
|
||
|
self.set_ps7(name=self.ps7_name,
|
||
|
config={
|
||
|
**self.platform.ps7_config
|
||
|
})
|
||
|
|
||
|
def add_ps7_config(self, config):
|
||
|
# Config must be provided as a config, value dict.
|
||
|
assert isinstance(config, dict)
|
||
|
# Add configs to PS7.
|
||
|
self.ps7_tcl.append("set_property -dict [list \\")
|
||
|
for config, value in config.items():
|
||
|
self.ps7_tcl.append("CONFIG.{} {} \\".format(config, '{{' + str(value) + '}}'))
|
||
|
self.ps7_tcl.append(f"] [get_ips {self.ps7_name}]")
|
||
|
|
||
|
def set_ps7(self, name=None, config=None, preset=None):
|
||
|
self.ps7_name = name
|
||
|
self.ps7_tcl.append(f"set ps7 [create_ip -vendor xilinx.com -name processing_system7 -module_name {self.ps7_name}]")
|
||
|
self.add_ps7_config(config)
|
||
|
|
||
|
def add_axi_gp_master(self, interface):
|
||
|
# assert type(interface) is Axi2Sys
|
||
|
|
||
|
axi_interface = interface
|
||
|
|
||
|
self.cpu_params.update({
|
||
|
# AXI GP clk.
|
||
|
f"i_M_AXI_GP0_ACLK" : axi_interface.aclk,
|
||
|
|
||
|
# AXI GP aw.
|
||
|
f"o_M_AXI_GP0_AWVALID" : axi_interface.awvalid,
|
||
|
f"i_M_AXI_GP0_AWREADY" : axi_interface.awready,
|
||
|
f"o_M_AXI_GP0_AWADDR" : axi_interface.awaddr,
|
||
|
f"o_M_AXI_GP0_AWBURST" : axi_interface.awburst,
|
||
|
f"o_M_AXI_GP0_AWLEN" : axi_interface.awlen,
|
||
|
f"o_M_AXI_GP0_AWSIZE" : axi_interface.awsize,
|
||
|
f"o_M_AXI_GP0_AWID" : axi_interface.awid,
|
||
|
f"o_M_AXI_GP0_AWLOCK" : axi_interface.awlock,
|
||
|
f"o_M_AXI_GP0_AWPROT" : axi_interface.awprot,
|
||
|
f"o_M_AXI_GP0_AWCACHE" : axi_interface.awcache,
|
||
|
f"o_M_AXI_GP0_AWQOS" : axi_interface.awqos,
|
||
|
|
||
|
# AXI GP w.
|
||
|
f"o_M_AXI_GP0_WVALID" : axi_interface.wvalid,
|
||
|
f"o_M_AXI_GP0_WLAST" : axi_interface.wlast,
|
||
|
f"i_M_AXI_GP0_WREADY" : axi_interface.wready,
|
||
|
f"o_M_AXI_GP0_WID" : axi_interface.wid,
|
||
|
f"o_M_AXI_GP0_WDATA" : axi_interface.wdata,
|
||
|
f"o_M_AXI_GP0_WSTRB" : axi_interface.wstrb,
|
||
|
|
||
|
# AXI GP b.
|
||
|
f"i_M_AXI_GP0_BVALID" : axi_interface.bvalid,
|
||
|
f"o_M_AXI_GP0_BREADY" : axi_interface.bready,
|
||
|
f"i_M_AXI_GP0_BID" : axi_interface.bid,
|
||
|
f"i_M_AXI_GP0_BRESP" : axi_interface.bresp,
|
||
|
|
||
|
# AXI GP ar.
|
||
|
f"o_M_AXI_GP0_ARVALID" : axi_interface.arvalid,
|
||
|
f"i_M_AXI_GP0_ARREADY" : axi_interface.arready,
|
||
|
f"o_M_AXI_GP0_ARADDR" : axi_interface.araddr,
|
||
|
f"o_M_AXI_GP0_ARBURST" : axi_interface.arburst,
|
||
|
f"o_M_AXI_GP0_ARLEN" : axi_interface.arlen,
|
||
|
f"o_M_AXI_GP0_ARID" : axi_interface.arid,
|
||
|
f"o_M_AXI_GP0_ARLOCK" : axi_interface.arlock,
|
||
|
f"o_M_AXI_GP0_ARSIZE" : axi_interface.arsize,
|
||
|
f"o_M_AXI_GP0_ARPROT" : axi_interface.arprot,
|
||
|
f"o_M_AXI_GP0_ARCACHE" : axi_interface.arcache,
|
||
|
f"o_M_AXI_GP0_ARQOS" : axi_interface.arqos,
|
||
|
|
||
|
# AXI GP r.
|
||
|
f"i_M_AXI_GP0_RVALID" : axi_interface.rvalid,
|
||
|
f"o_M_AXI_GP0_RREADY" : axi_interface.rready,
|
||
|
f"i_M_AXI_GP0_RLAST" : axi_interface.rlast,
|
||
|
f"i_M_AXI_GP0_RID" : axi_interface.rid,
|
||
|
f"i_M_AXI_GP0_RRESP" : axi_interface.rresp,
|
||
|
f"i_M_AXI_GP0_RDATA" : axi_interface.rdata,
|
||
|
})
|
||
|
|
||
|
def add_i2c_emio(self, platform, i2c_name, i2c_number):
|
||
|
ps7_i2c_pads = platform.request(i2c_name, i2c_number) #, loose=True)
|
||
|
if ps7_i2c_pads is not None:
|
||
|
o_i2c_scl = Signal()
|
||
|
i_i2c_scl = Signal()
|
||
|
t_i2c_scl = Signal()
|
||
|
o_i2c_sda = Signal()
|
||
|
i_i2c_sda = Signal()
|
||
|
t_i2c_sda = Signal()
|
||
|
|
||
|
self.specials += Instance("IOBUF",
|
||
|
i_T = t_i2c_sda,
|
||
|
i_I = o_i2c_sda,
|
||
|
io_IO = ps7_i2c_pads.sda,
|
||
|
o_O = i_i2c_sda,
|
||
|
)
|
||
|
|
||
|
self.specials += Instance("IOBUF",
|
||
|
i_T = t_i2c_scl,
|
||
|
i_I = o_i2c_scl,
|
||
|
io_IO = ps7_i2c_pads.scl,
|
||
|
o_O = i_i2c_scl,
|
||
|
)
|
||
|
|
||
|
self.cpu_params.update({
|
||
|
f"i_I2C{i2c_number}_SCL_I" : i_i2c_scl,
|
||
|
f"o_I2C{i2c_number}_SCL_T" : t_i2c_scl,
|
||
|
f"o_I2C{i2c_number}_SCL_O" : o_i2c_scl,
|
||
|
|
||
|
f"i_I2C{i2c_number}_SDA_I" : i_i2c_sda,
|
||
|
f"o_I2C{i2c_number}_SDA_T" : t_i2c_sda,
|
||
|
f"o_I2C{i2c_number}_SDA_O" : o_i2c_sda,
|
||
|
})
|
||
|
|
||
|
def do_finalize(self):
|
||
|
if len(self.ps7_tcl):
|
||
|
self.ps7_tcl += [
|
||
|
f"upgrade_ip [get_ips {self.ps7_name}]",
|
||
|
f"generate_target all [get_ips {self.ps7_name}]",
|
||
|
f"synth_ip [get_ips {self.ps7_name}]"
|
||
|
]
|
||
|
self.platform.toolchain.pre_synthesis_commands += self.ps7_tcl
|
||
|
|
||
|
self.specials += Instance(self.ps7_name, **self.cpu_params)
|