# This file is part of Fast Servo Software Package. # # Copyright (C) 2023 Jakub Matyas # Warsaw University of Technology # 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 . 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)