1216 lines
43 KiB
Smarty
1216 lines
43 KiB
Smarty
// Copyright lowRISC contributors.
|
|
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
${gencmd}
|
|
<%
|
|
import re
|
|
import topgen.lib as lib
|
|
from copy import deepcopy
|
|
|
|
# Provide shortcuts for some commonly used variables
|
|
pinmux = top['pinmux']
|
|
pinout = top['pinout']
|
|
|
|
num_mio_inputs = pinmux['io_counts']['muxed']['inouts'] + \
|
|
pinmux['io_counts']['muxed']['inputs']
|
|
num_mio_outputs = pinmux['io_counts']['muxed']['inouts'] + \
|
|
pinmux['io_counts']['muxed']['outputs']
|
|
num_mio_pads = pinmux['io_counts']['muxed']['pads']
|
|
|
|
num_dio_inputs = pinmux['io_counts']['dedicated']['inouts'] + \
|
|
pinmux['io_counts']['dedicated']['inputs']
|
|
num_dio_outputs = pinmux['io_counts']['dedicated']['inouts'] + \
|
|
pinmux['io_counts']['dedicated']['outputs']
|
|
num_dio_total = pinmux['io_counts']['dedicated']['inouts'] + \
|
|
pinmux['io_counts']['dedicated']['inputs'] + \
|
|
pinmux['io_counts']['dedicated']['outputs']
|
|
|
|
def get_dio_sig(pinmux: {}, pad: {}):
|
|
'''Get DIO signal associated with this pad or return None'''
|
|
for sig in pinmux["ios"]:
|
|
if sig["connection"] == "direct" and pad["name"] == sig["pad"]:
|
|
return sig
|
|
else:
|
|
return None
|
|
|
|
# Modify the pad lists on the fly, based on target config
|
|
maxwidth = 0
|
|
muxed_pads = []
|
|
dedicated_pads = []
|
|
k = 0
|
|
for pad in pinout["pads"]:
|
|
if pad["connection"] == "muxed":
|
|
if pad["name"] not in target["pinout"]["remove_pads"]:
|
|
maxwidth = max(maxwidth, len(pad["name"]))
|
|
muxed_pads.append(pad)
|
|
else:
|
|
k = pad["idx"]
|
|
if pad["name"] not in target["pinout"]["remove_pads"]:
|
|
maxwidth = max(maxwidth, len(pad["name"]))
|
|
dedicated_pads.append(pad)
|
|
|
|
for pad in target["pinout"]["add_pads"]:
|
|
# Since these additional pads have not been elaborated in the merge phase,
|
|
# we need to add their global index here.
|
|
amended_pad = deepcopy(pad)
|
|
amended_pad.update({"idx" : k})
|
|
dedicated_pads.append(pad)
|
|
k += 1
|
|
|
|
num_im = sum([x["width"] if "width" in x else 1 for x in top["inter_signal"]["external"]])
|
|
|
|
max_sigwidth = max([x["width"] if "width" in x else 1 for x in top["pinmux"]["ios"]])
|
|
max_sigwidth = len("{}".format(max_sigwidth))
|
|
|
|
cpu_clk = top['clocks'].hier_paths['top'] + "clk_proc_main"
|
|
|
|
unused_im_defs, undriven_im_defs = lib.get_dangling_im_def(top["inter_signal"]["definitions"])
|
|
|
|
%>\
|
|
% if target["name"] != "asic":
|
|
module chip_${top["name"]}_${target["name"]} #(
|
|
// Path to a VMEM file containing the contents of the boot ROM, which will be
|
|
// baked into the FPGA bitstream.
|
|
parameter BootRomInitFile = "boot_rom_fpga_${target["name"]}.32.vmem",
|
|
// Path to a VMEM file containing the contents of the emulated OTP, which will be
|
|
// baked into the FPGA bitstream.
|
|
parameter OtpCtrlMemInitFile = "otp_img_fpga_${target["name"]}.vmem"
|
|
) (
|
|
% else:
|
|
module chip_${top["name"]}_${target["name"]} (
|
|
% endif
|
|
<%
|
|
|
|
%>\
|
|
// Dedicated Pads
|
|
% for pad in dedicated_pads:
|
|
<%
|
|
sig = get_dio_sig(pinmux, pad)
|
|
if sig is not None:
|
|
comment = "// Dedicated Pad for {}".format(sig["name"])
|
|
else:
|
|
comment = "// Manual Pad"
|
|
%>\
|
|
inout ${pad["name"]}, ${comment}
|
|
% endfor
|
|
|
|
// Muxed Pads
|
|
% for pad in muxed_pads:
|
|
inout ${pad["name"]}${" " if loop.last else ","} // MIO Pad ${pad["idx"]}
|
|
% endfor
|
|
);
|
|
|
|
import top_${top["name"]}_pkg::*;
|
|
import prim_pad_wrapper_pkg::*;
|
|
|
|
% if target["pinmux"]["special_signals"]:
|
|
////////////////////////////
|
|
// Special Signal Indices //
|
|
////////////////////////////
|
|
|
|
% for entry in target["pinmux"]["special_signals"]:
|
|
<% param_name = (lib.Name.from_snake_case(entry["name"]) +
|
|
lib.Name(["pad", "idx"])).as_camel_case()
|
|
%>\
|
|
parameter int ${param_name} = ${entry["idx"]};
|
|
% endfor
|
|
% endif
|
|
|
|
// DFT and Debug signal positions in the pinout.
|
|
localparam pinmux_pkg::target_cfg_t PinmuxTargetCfg = '{
|
|
tck_idx: TckPadIdx,
|
|
tms_idx: TmsPadIdx,
|
|
trst_idx: TrstNPadIdx,
|
|
tdi_idx: TdiPadIdx,
|
|
tdo_idx: TdoPadIdx,
|
|
tap_strap0_idx: Tap0PadIdx,
|
|
tap_strap1_idx: Tap1PadIdx,
|
|
dft_strap0_idx: Dft0PadIdx,
|
|
dft_strap1_idx: Dft1PadIdx,
|
|
// TODO: check whether there is a better way to pass these USB-specific params
|
|
usb_dp_idx: DioUsbdevDp,
|
|
usb_dn_idx: DioUsbdevDn,
|
|
usb_dp_pullup_idx: DioUsbdevDpPullup,
|
|
usb_dn_pullup_idx: DioUsbdevDnPullup,
|
|
// Pad types for attribute WARL behavior
|
|
dio_pad_type: {
|
|
<%
|
|
pad_attr = []
|
|
for sig in list(reversed(top["pinmux"]["ios"])):
|
|
if sig["connection"] != "muxed":
|
|
pad_attr.append((sig['name'], sig["attr"]))
|
|
%>\
|
|
% for name, attr in pad_attr:
|
|
${attr}${" " if loop.last else ","} // DIO ${name}
|
|
% endfor
|
|
},
|
|
mio_pad_type: {
|
|
<%
|
|
pad_attr = []
|
|
for pad in list(reversed(pinout["pads"])):
|
|
if pad["connection"] == "muxed":
|
|
pad_attr.append(pad["type"])
|
|
%>\
|
|
% for attr in pad_attr:
|
|
${attr}${" " if loop.last else ","} // MIO Pad ${len(pad_attr) - loop.index - 1}
|
|
% endfor
|
|
}
|
|
};
|
|
|
|
////////////////////////
|
|
// Signal definitions //
|
|
////////////////////////
|
|
|
|
pad_attr_t [pinmux_reg_pkg::NMioPads-1:0] mio_attr;
|
|
pad_attr_t [pinmux_reg_pkg::NDioPads-1:0] dio_attr;
|
|
logic [pinmux_reg_pkg::NMioPads-1:0] mio_out;
|
|
logic [pinmux_reg_pkg::NMioPads-1:0] mio_oe;
|
|
logic [pinmux_reg_pkg::NMioPads-1:0] mio_in;
|
|
logic [pinmux_reg_pkg::NMioPads-1:0] mio_in_raw;
|
|
logic [pinmux_reg_pkg::NDioPads-1:0] dio_out;
|
|
logic [pinmux_reg_pkg::NDioPads-1:0] dio_oe;
|
|
logic [pinmux_reg_pkg::NDioPads-1:0] dio_in;
|
|
|
|
logic unused_mio_in_raw;
|
|
assign unused_mio_in_raw = ^mio_in_raw;
|
|
|
|
// Manual pads
|
|
% for pad in dedicated_pads:
|
|
<%
|
|
pad_prefix = pad["name"].lower()
|
|
%>\
|
|
% if not get_dio_sig(pinmux, pad):
|
|
logic manual_in_${pad_prefix}, manual_out_${pad_prefix}, manual_oe_${pad_prefix};
|
|
% endif
|
|
% endfor
|
|
|
|
% for pad in dedicated_pads:
|
|
<%
|
|
pad_prefix = pad["name"].lower()
|
|
%>\
|
|
% if not get_dio_sig(pinmux, pad):
|
|
pad_attr_t manual_attr_${pad_prefix};
|
|
% endif
|
|
% endfor
|
|
|
|
% if target["pinout"]["remove_pads"]:
|
|
/////////////////////////
|
|
// Stubbed pad tie-off //
|
|
/////////////////////////
|
|
|
|
// Only signals going to non-custom pads need to be tied off.
|
|
logic [${len(pinout["pads"])-1}:0] unused_sig;
|
|
% for pad in pinout["pads"]:
|
|
% if pad["connection"] == 'muxed':
|
|
% if pad["name"] in target["pinout"]["remove_pads"]:
|
|
assign mio_in[${pad["idx"]}] = 1'b0;
|
|
assign mio_in_raw[${pad["idx"]}] = 1'b0;
|
|
assign unused_sig[${loop.index}] = mio_out[${pad["idx"]}] ^ mio_oe[${pad["idx"]}];
|
|
% endif
|
|
% else:
|
|
% if pad["name"] in target["pinout"]["remove_pads"]:
|
|
<%
|
|
## Only need to tie off if this is not a custom pad.
|
|
sig = get_dio_sig(pinmux, pad)
|
|
if sig is not None:
|
|
sig_index = lib.get_io_enum_literal(sig, 'dio')
|
|
%>\
|
|
% if sig is not None:
|
|
assign dio_in[${lib.get_io_enum_literal(sig, 'dio')}] = 1'b0;
|
|
assign unused_sig[${loop.index}] = dio_out[${sig_index}] ^ dio_oe[${sig_index}];
|
|
% endif
|
|
% endif
|
|
% endif
|
|
% endfor
|
|
%endif
|
|
|
|
//////////////////////
|
|
// Padring Instance //
|
|
//////////////////////
|
|
|
|
% if target["name"] == "asic":
|
|
// AST signals needed in padring
|
|
ast_pkg::ast_clks_t ast_base_clks;
|
|
logic scan_rst_n;
|
|
lc_ctrl_pkg::lc_tx_t scanmode;
|
|
% endif
|
|
|
|
padring #(
|
|
// Padring specific counts may differ from pinmux config due
|
|
// to custom, stubbed or added pads.
|
|
.NDioPads(${len(dedicated_pads)}),
|
|
.NMioPads(${len(muxed_pads)}),
|
|
% if target["name"] == "asic":
|
|
.PhysicalPads(1),
|
|
.NIoBanks(int'(IoBankCount)),
|
|
.DioScanRole ({
|
|
% for pad in list(reversed(dedicated_pads)):
|
|
scan_role_pkg::${lib.Name.from_snake_case('dio_pad_' + pad["name"] + '_scan_role').as_camel_case()}${"" if loop.last else ","}
|
|
% endfor
|
|
}),
|
|
.MioScanRole ({
|
|
% for pad in list(reversed(muxed_pads)):
|
|
scan_role_pkg::${lib.Name.from_snake_case('mio_pad_' + pad["name"] + '_scan_role').as_camel_case()}${"" if loop.last else ","}
|
|
% endfor
|
|
}),
|
|
.DioPadBank ({
|
|
% for pad in list(reversed(dedicated_pads)):
|
|
${lib.Name.from_snake_case('io_bank_' + pad["bank"]).as_camel_case()}${" " if loop.last else ","} // ${pad['name']}
|
|
% endfor
|
|
}),
|
|
.MioPadBank ({
|
|
% for pad in list(reversed(muxed_pads)):
|
|
${lib.Name.from_snake_case('io_bank_' + pad["bank"]).as_camel_case()}${" " if loop.last else ","} // ${pad['name']}
|
|
% endfor
|
|
}),
|
|
% endif
|
|
\
|
|
\
|
|
.DioPadType ({
|
|
% for pad in list(reversed(dedicated_pads)):
|
|
${pad["type"]}${" " if loop.last else ","} // ${pad['name']}
|
|
% endfor
|
|
}),
|
|
.MioPadType ({
|
|
% for pad in list(reversed(muxed_pads)):
|
|
${pad["type"]}${" " if loop.last else ","} // ${pad['name']}
|
|
% endfor
|
|
})
|
|
) u_padring (
|
|
// This is only used for scan and DFT purposes
|
|
% if target["name"] == "asic":
|
|
.clk_scan_i ( ast_base_clks.clk_sys ),
|
|
.scanmode_i ( scanmode ),
|
|
% else:
|
|
.clk_scan_i ( 1'b0 ),
|
|
.scanmode_i ( lc_ctrl_pkg::Off ),
|
|
% endif
|
|
.dio_in_raw_o ( ),
|
|
// Chip IOs
|
|
.dio_pad_io ({
|
|
% for pad in list(reversed(dedicated_pads)):
|
|
${pad["name"]}${"" if loop.last else ","}
|
|
% endfor
|
|
}),
|
|
|
|
.mio_pad_io ({
|
|
% for pad in list(reversed(muxed_pads)):
|
|
${pad["name"]}${"" if loop.last else ","}
|
|
% endfor
|
|
}),
|
|
|
|
// Core-facing
|
|
% for port in ["in_o", "out_i", "oe_i", "attr_i"]:
|
|
.dio_${port} ({
|
|
% for pad in list(reversed(dedicated_pads)):
|
|
<%
|
|
sig = get_dio_sig(pinmux, pad)
|
|
%>\
|
|
% if sig is None:
|
|
manual_${port[:-2]}_${pad["name"].lower()}${"" if loop.last else ","}
|
|
% else:
|
|
dio_${port[:-2]}[${lib.get_io_enum_literal(sig, 'dio')}]${"" if loop.last else ","}
|
|
% endif
|
|
% endfor
|
|
}),
|
|
% endfor
|
|
|
|
% for port in ["in_o", "out_i", "oe_i", "attr_i", "in_raw_o"]:
|
|
<%
|
|
sig_name = 'mio_' + port[:-2]
|
|
indices = list(reversed(list(pad['idx'] for pad in muxed_pads)))
|
|
%>\
|
|
.mio_${port} (${lib.make_bit_concatenation(sig_name, indices, 6)})${"" if loop.last else ","}
|
|
% endfor
|
|
);
|
|
|
|
|
|
###################################################################
|
|
## USB for CW305 ##
|
|
###################################################################
|
|
% if target["name"] == "cw305":
|
|
// Connect the DP pad
|
|
assign dio_in[DioUsbdevDp] = manual_in_usb_p;
|
|
assign manual_out_usb_p = dio_out[DioUsbdevDp];
|
|
assign manual_oe_usb_p = dio_oe[DioUsbdevDp];
|
|
assign manual_attr_usb_p = dio_attr[DioUsbdevDp];
|
|
|
|
// Connect the DN pad
|
|
assign dio_in[DioUsbdevDn] = manual_in_usb_n;
|
|
assign manual_out_usb_n = dio_out[DioUsbdevDn];
|
|
assign manual_oe_usb_n = dio_oe[DioUsbdevDn];
|
|
assign manual_attr_usb_n = dio_attr[DioUsbdevDn];
|
|
|
|
// Connect sense pad
|
|
assign dio_in[DioUsbdevSense] = manual_in_io_usb_sense0;
|
|
assign manual_out_io_usb_sense0 = dio_out[DioUsbdevSense];
|
|
assign manual_oe_io_usb_sense0 = dio_oe[DioUsbdevSense];
|
|
assign manual_attr_io_sense0 = dio_attr[DioUsbdevSense];
|
|
|
|
// Connect DN pullup
|
|
assign dio_in[DioUsbdevDnPullup] = manual_in_io_usb_dnpullup0;
|
|
assign manual_out_io_usb_dnpullup0 = dio_out[DioUsbdevDnPullup];
|
|
assign manual_oe_io_usb_dnpullup0 = dio_oe[DioUsbdevDnPullup];
|
|
assign manual_attr_io_dnpullup0 = dio_attr[DioUsbdevDnPullup];
|
|
|
|
// Connect DP pullup
|
|
assign dio_in[DioUsbdevDpPullup] = manual_in_io_usb_dppullup0;
|
|
assign manual_out_io_usb_dppullup0 = dio_out[DioUsbdevDpPullup];
|
|
assign manual_oe_io_usb_dppullup0 = dio_oe[DioUsbdevDpPullup];
|
|
assign manual_attr_io_dppullup0 = dio_attr[DioUsbdevDpPullup];
|
|
|
|
// Tie-off unused signals
|
|
assign dio_in[DioUsbdevSe0] = 1'b0;
|
|
assign dio_in[DioUsbdevTxModeSe] = 1'b0;
|
|
assign dio_in[DioUsbdevSuspend] = 1'b0;
|
|
|
|
logic unused_usb_sigs;
|
|
assign unused_usb_sigs = ^{
|
|
// SE0
|
|
dio_out[DioUsbdevSe0],
|
|
dio_oe[DioUsbdevSe0],
|
|
dio_attr[DioUsbdevSe0],
|
|
// TX Mode
|
|
dio_out[DioUsbdevTxModeSe],
|
|
dio_oe[DioUsbdevTxModeSe],
|
|
dio_attr[DioUsbdevTxModeSe],
|
|
// Suspend
|
|
dio_out[DioUsbdevSuspend],
|
|
dio_oe[DioUsbdevSuspend],
|
|
dio_attr[DioUsbdevSuspend],
|
|
// D is used as an input only
|
|
dio_out[DioUsbdevD],
|
|
dio_oe[DioUsbdevD],
|
|
dio_attr[DioUsbdevD]
|
|
};
|
|
|
|
% endif
|
|
|
|
###################################################################
|
|
## USB for CW310 and Nexysvideo ##
|
|
###################################################################
|
|
% if target["name"] in ["cw310", "nexysvideo"]:
|
|
|
|
/////////////////////
|
|
// USB Overlay Mux //
|
|
/////////////////////
|
|
|
|
// TODO: generalize this USB mux code and align with other tops.
|
|
|
|
// Software can enable the pinflip feature inside usbdev.
|
|
// The example hello_usbdev does this based on GPIO0 (a switch on the board)
|
|
//
|
|
// Here, we use the state of the DN pullup to effectively undo the
|
|
// swapping such that the PCB always sees the unflipped D+/D-. We
|
|
// could do the same inside the .xdc file but then two FPGA
|
|
// bitstreams would be needed for testing.
|
|
//
|
|
// dio_in/out/oe map is: PADS <- _padring <- JTAG mux -> _umux -> USB mux -> _core
|
|
|
|
// Split out for differential PHY testing
|
|
|
|
// Outputs always drive and just copy the value
|
|
// Let them go to the normal place too because it won't do any harm
|
|
// and it simplifies the changes needed
|
|
|
|
// The output enable for IO_USB_DNPULLUP0 is used to decide whether we need to undo the swapping.
|
|
logic undo_swap;
|
|
assign undo_swap = dio_oe[DioUsbdevDnPullup];
|
|
|
|
// GPIO[2] = Switch 2 on board is used to select using the UPHY
|
|
// Keep GPIO[1] for selecting differential in sw
|
|
logic use_uphy;
|
|
assign use_uphy = mio_in[MioPadIoa2];
|
|
|
|
// DioUsbdevDn
|
|
assign manual_attr_usb_n = '0;
|
|
assign manual_attr_io_uphy_dn_tx = '0;
|
|
|
|
assign manual_out_io_uphy_dn_tx = manual_out_usb_n;
|
|
assign manual_out_usb_n = undo_swap ? dio_out[DioUsbdevDp] :
|
|
dio_out[DioUsbdevDn];
|
|
|
|
assign manual_oe_io_uphy_dn_tx = manual_oe_usb_n;
|
|
assign manual_oe_usb_n = undo_swap ? dio_oe[DioUsbdevDp] :
|
|
dio_oe[DioUsbdevDn];
|
|
|
|
assign dio_in[DioUsbdevDn] = use_uphy ?
|
|
(undo_swap ? manual_in_io_uphy_dp_rx :
|
|
manual_in_io_uphy_dn_rx) :
|
|
(undo_swap ? manual_in_usb_p :
|
|
manual_in_usb_n);
|
|
// DioUsbdevDp
|
|
assign manual_attr_usb_p = '0;
|
|
assign manual_attr_io_uphy_dp_tx = '0;
|
|
|
|
assign manual_out_io_uphy_dp_tx = manual_out_usb_p;
|
|
assign manual_out_usb_p = undo_swap ? dio_out[DioUsbdevDn] :
|
|
dio_out[DioUsbdevDp];
|
|
|
|
assign manual_oe_io_uphy_dp_tx = manual_oe_usb_p;
|
|
assign manual_oe_usb_p = undo_swap ? dio_oe[DioUsbdevDn] :
|
|
dio_oe[DioUsbdevDp];
|
|
assign dio_in[DioUsbdevDp] = use_uphy ?
|
|
(undo_swap ? manual_in_io_uphy_dn_rx :
|
|
manual_in_io_uphy_dp_rx) :
|
|
(undo_swap ? manual_in_usb_n :
|
|
manual_in_usb_p);
|
|
// DioUsbdevD
|
|
// This is not connected at the moment
|
|
logic unused_out_usb_d;
|
|
assign unused_out_usb_d = dio_out[DioUsbdevD] ^
|
|
dio_oe[DioUsbdevD];
|
|
assign dio_in[DioUsbdevD] = use_uphy ?
|
|
(undo_swap ? ~manual_in_io_uphy_d_rx :
|
|
manual_in_io_uphy_d_rx) :
|
|
// This is not connected at the moment
|
|
(undo_swap ? 1'b1 : 1'b0);
|
|
assign manual_out_io_uphy_d_rx = 1'b0;
|
|
assign manual_oe_io_uphy_d_rx = 1'b0;
|
|
|
|
// DioUsbdevDnPullup
|
|
assign manual_attr_io_usb_dnpullup0 = '0;
|
|
assign manual_out_io_usb_dnpullup0 = undo_swap ? dio_out[DioUsbdevDpPullup] :
|
|
dio_out[DioUsbdevDnPullup];
|
|
assign manual_oe_io_usb_dnpullup0 = undo_swap ? dio_oe[DioUsbdevDpPullup] :
|
|
dio_oe[DioUsbdevDnPullup];
|
|
assign dio_in[DioUsbdevDnPullup] = manual_in_io_usb_dnpullup0;
|
|
|
|
// DioUsbdevDpPullup
|
|
assign manual_attr_io_usb_dppullup0 = '0;
|
|
assign manual_out_io_usb_dppullup0 = undo_swap ? dio_out[DioUsbdevDnPullup] :
|
|
dio_out[DioUsbdevDpPullup];
|
|
assign manual_oe_io_usb_dppullup0 = undo_swap ? dio_oe[DioUsbdevDnPullup] :
|
|
dio_oe[DioUsbdevDpPullup];
|
|
assign dio_in[DioUsbdevDpPullup] = manual_in_io_usb_dppullup0;
|
|
|
|
// DioUsbdevSense
|
|
assign manual_out_io_usb_sense0 = dio_out[DioUsbdevSense];
|
|
assign manual_oe_io_usb_sense0 = dio_oe[DioUsbdevSense];
|
|
assign dio_in[DioUsbdevSense] = use_uphy ? manual_in_io_uphy_sense :
|
|
manual_in_io_usb_sense0;
|
|
assign manual_out_io_uphy_sense = 1'b0;
|
|
assign manual_oe_io_uphy_sense = 1'b0;
|
|
|
|
// DioUsbdevRxEnable
|
|
assign dio_in[DioUsbdevRxEnable] = 1'b0;
|
|
|
|
// Additional outputs for uphy
|
|
assign manual_oe_io_uphy_dppullup = 1'b1;
|
|
assign manual_out_io_uphy_dppullup = manual_out_io_usb_dppullup0 &
|
|
manual_oe_io_usb_dppullup0;
|
|
|
|
logic unused_in_io_uphy_dppullup;
|
|
assign unused_in_io_uphy_dppullup = manual_in_io_uphy_dppullup;
|
|
|
|
assign manual_oe_io_uphy_oe_n = 1'b1;
|
|
assign manual_out_io_uphy_oe_n = ~manual_oe_usb_p;
|
|
|
|
logic unused_in_io_uphy_oe_n;
|
|
assign unused_in_io_uphy_oe_n = manual_in_io_uphy_oe_n;
|
|
|
|
% endif
|
|
|
|
###################################################################
|
|
## ASIC ##
|
|
###################################################################
|
|
% if target["name"] == "asic":
|
|
|
|
//////////////////////////////////
|
|
// Manual Pad / Signal Tie-offs //
|
|
//////////////////////////////////
|
|
|
|
assign manual_out_por_n = 1'b0;
|
|
assign manual_oe_por_n = 1'b0;
|
|
|
|
assign manual_out_cc1 = 1'b0;
|
|
assign manual_oe_cc1 = 1'b0;
|
|
assign manual_out_cc2 = 1'b0;
|
|
assign manual_oe_cc2 = 1'b0;
|
|
|
|
assign manual_out_flash_test_mode0 = 1'b0;
|
|
assign manual_oe_flash_test_mode0 = 1'b0;
|
|
assign manual_out_flash_test_mode1 = 1'b0;
|
|
assign manual_oe_flash_test_mode1 = 1'b0;
|
|
assign manual_out_flash_test_volt = 1'b0;
|
|
assign manual_oe_flash_test_volt = 1'b0;
|
|
assign manual_out_otp_ext_volt = 1'b0;
|
|
assign manual_oe_otp_ext_volt = 1'b0;
|
|
|
|
// These pad attributes currently tied off permanently (these are all input-only pads).
|
|
assign manual_attr_por_n = '0;
|
|
assign manual_attr_cc1 = '0;
|
|
assign manual_attr_cc2 = '0;
|
|
assign manual_attr_flash_test_mode0 = '0;
|
|
assign manual_attr_flash_test_mode1 = '0;
|
|
assign manual_attr_flash_test_volt = '0;
|
|
assign manual_attr_otp_ext_volt = '0;
|
|
|
|
logic unused_manual_sigs;
|
|
assign unused_manual_sigs = ^{
|
|
manual_in_cc2,
|
|
manual_in_cc1,
|
|
manual_in_flash_test_volt,
|
|
manual_in_flash_test_mode0,
|
|
manual_in_flash_test_mode1,
|
|
manual_in_otp_ext_volt
|
|
};
|
|
|
|
///////////////////////////////
|
|
// Differential USB Receiver //
|
|
///////////////////////////////
|
|
|
|
// TODO: generalize this USB mux code and align with other tops.
|
|
|
|
// Connect the DP pad
|
|
assign dio_in[DioUsbdevDp] = manual_in_usb_p;
|
|
assign manual_out_usb_p = dio_out[DioUsbdevDp];
|
|
assign manual_oe_usb_p = dio_oe[DioUsbdevDp];
|
|
assign manual_attr_usb_p = dio_attr[DioUsbdevDp];
|
|
|
|
// Connect the DN pad
|
|
assign dio_in[DioUsbdevDn] = manual_in_usb_n;
|
|
assign manual_out_usb_n = dio_out[DioUsbdevDn];
|
|
assign manual_oe_usb_n = dio_oe[DioUsbdevDn];
|
|
assign manual_attr_usb_n = dio_attr[DioUsbdevDn];
|
|
|
|
// Pullups
|
|
logic usb_pullup_p_en, usb_pullup_n_en;
|
|
assign usb_pullup_p_en = dio_out[DioUsbdevDpPullup] & dio_oe[DioUsbdevDpPullup];
|
|
assign usb_pullup_n_en = dio_out[DioUsbdevDnPullup] & dio_oe[DioUsbdevDnPullup];
|
|
|
|
logic usb_rx_enable;
|
|
assign usb_rx_enable = dio_out[DioUsbdevRxEnable] & dio_oe[DioUsbdevRxEnable];
|
|
|
|
logic [ast_pkg::UsbCalibWidth-1:0] usb_io_pu_cal;
|
|
|
|
// pwrmgr interface
|
|
pwrmgr_pkg::pwr_ast_req_t base_ast_pwr;
|
|
pwrmgr_pkg::pwr_ast_rsp_t ast_base_pwr;
|
|
|
|
prim_usb_diff_rx #(
|
|
.CalibW(ast_pkg::UsbCalibWidth)
|
|
) u_prim_usb_diff_rx (
|
|
.input_pi ( USB_P ),
|
|
.input_ni ( USB_N ),
|
|
.input_en_i ( usb_rx_enable ),
|
|
.core_pok_i ( ast_base_pwr.main_pok ),
|
|
.pullup_p_en_i ( usb_pullup_p_en ),
|
|
.pullup_n_en_i ( usb_pullup_n_en ),
|
|
.calibration_i ( usb_io_pu_cal ),
|
|
.input_o ( dio_in[DioUsbdevD] )
|
|
);
|
|
|
|
// Tie-off unused signals
|
|
assign dio_in[DioUsbdevSense] = 1'b0;
|
|
assign dio_in[DioUsbdevSe0] = 1'b0;
|
|
assign dio_in[DioUsbdevDpPullup] = 1'b0;
|
|
assign dio_in[DioUsbdevDnPullup] = 1'b0;
|
|
assign dio_in[DioUsbdevTxModeSe] = 1'b0;
|
|
assign dio_in[DioUsbdevSuspend] = 1'b0;
|
|
assign dio_in[DioUsbdevRxEnable] = 1'b0;
|
|
|
|
logic unused_usb_sigs;
|
|
assign unused_usb_sigs = ^{
|
|
// Sense
|
|
dio_out[DioUsbdevSense],
|
|
dio_oe[DioUsbdevSense],
|
|
dio_attr[DioUsbdevSense],
|
|
// SE0
|
|
dio_out[DioUsbdevSe0],
|
|
dio_oe[DioUsbdevSe0],
|
|
dio_attr[DioUsbdevSe0],
|
|
// TX Mode
|
|
dio_out[DioUsbdevTxModeSe],
|
|
dio_oe[DioUsbdevTxModeSe],
|
|
dio_attr[DioUsbdevTxModeSe],
|
|
// Suspend
|
|
dio_out[DioUsbdevSuspend],
|
|
dio_oe[DioUsbdevSuspend],
|
|
dio_attr[DioUsbdevSuspend],
|
|
// Rx enable
|
|
dio_attr[DioUsbdevRxEnable],
|
|
// D is used as an input only
|
|
dio_out[DioUsbdevD],
|
|
dio_oe[DioUsbdevD],
|
|
dio_attr[DioUsbdevD],
|
|
// Pullup/down
|
|
dio_attr[DioUsbdevDpPullup],
|
|
dio_attr[DioUsbdevDnPullup]
|
|
};
|
|
|
|
//////////////////////
|
|
// AST //
|
|
//////////////////////
|
|
// TLUL interface
|
|
tlul_pkg::tl_h2d_t base_ast_bus;
|
|
tlul_pkg::tl_d2h_t ast_base_bus;
|
|
|
|
// assorted ast status
|
|
ast_pkg::ast_status_t ast_status;
|
|
|
|
// ast clocks and resets
|
|
logic aon_pok;
|
|
|
|
// synchronization clocks / rests
|
|
clkmgr_pkg::clkmgr_ast_out_t clks_ast;
|
|
rstmgr_pkg::rstmgr_ast_out_t rsts_ast;
|
|
|
|
// otp power sequence
|
|
otp_ctrl_pkg::otp_ast_req_t otp_ctrl_otp_ast_pwr_seq;
|
|
otp_ctrl_pkg::otp_ast_rsp_t otp_ctrl_otp_ast_pwr_seq_h;
|
|
|
|
logic usb_ref_pulse;
|
|
logic usb_ref_val;
|
|
|
|
// adc
|
|
ast_pkg::adc_ast_req_t adc_req;
|
|
ast_pkg::adc_ast_rsp_t adc_rsp;
|
|
|
|
// entropy source interface
|
|
// The entropy source pacakge definition should eventually be moved to es
|
|
entropy_src_pkg::entropy_src_rng_req_t es_rng_req;
|
|
entropy_src_pkg::entropy_src_rng_rsp_t es_rng_rsp;
|
|
logic es_rng_fips;
|
|
|
|
// entropy distribution network
|
|
edn_pkg::edn_req_t ast_edn_edn_req;
|
|
edn_pkg::edn_rsp_t ast_edn_edn_rsp;
|
|
|
|
// alerts interface
|
|
ast_pkg::ast_alert_rsp_t ast_alert_rsp;
|
|
ast_pkg::ast_alert_req_t ast_alert_req;
|
|
|
|
// Flash connections
|
|
lc_ctrl_pkg::lc_tx_t flash_bist_enable;
|
|
logic flash_power_down_h;
|
|
logic flash_power_ready_h;
|
|
|
|
// Life cycle clock bypass req/ack
|
|
lc_ctrl_pkg::lc_tx_t ast_clk_byp_req;
|
|
lc_ctrl_pkg::lc_tx_t ast_clk_byp_ack;
|
|
|
|
// DFT connections
|
|
logic scan_en;
|
|
lc_ctrl_pkg::lc_tx_t dft_en;
|
|
pinmux_pkg::dft_strap_test_req_t dft_strap_test;
|
|
|
|
// Debug connections
|
|
logic [ast_pkg::Ast2PadOutWidth-1:0] ast2pinmux;
|
|
logic [ast_pkg::Pad2AstInWidth-1:0] pad2ast;
|
|
|
|
assign pad2ast = {
|
|
mio_in_raw[MioPadIoc3],
|
|
mio_in_raw[MioPadIob8],
|
|
mio_in_raw[MioPadIob7],
|
|
mio_in_raw[MioPadIob2],
|
|
mio_in_raw[MioPadIob1],
|
|
mio_in_raw[MioPadIob0]
|
|
};
|
|
|
|
|
|
// Jitter enable
|
|
logic jen;
|
|
|
|
// reset domain connections
|
|
import rstmgr_pkg::PowerDomains;
|
|
import rstmgr_pkg::DomainAonSel;
|
|
import rstmgr_pkg::Domain0Sel;
|
|
|
|
// external clock comes in at a fixed position
|
|
logic ext_clk;
|
|
assign ext_clk = mio_in_raw[MioPadIoc6];
|
|
|
|
// Memory configuration connections
|
|
ast_pkg::spm_rm_t ast_ram_1p_cfg;
|
|
ast_pkg::spm_rm_t ast_rf_cfg;
|
|
ast_pkg::spm_rm_t ast_rom_cfg;
|
|
ast_pkg::dpm_rm_t ast_ram_2p_fcfg;
|
|
ast_pkg::dpm_rm_t ast_ram_2p_lcfg;
|
|
|
|
prim_ram_1p_pkg::ram_1p_cfg_t ram_1p_cfg;
|
|
prim_ram_2p_pkg::ram_2p_cfg_t ram_2p_cfg;
|
|
prim_rom_pkg::rom_cfg_t rom_cfg;
|
|
|
|
// conversion from ast structure to memory centric structures
|
|
assign ram_1p_cfg = '{
|
|
ram_cfg: '{
|
|
cfg_en: ast_ram_1p_cfg.marg_en,
|
|
cfg: ast_ram_1p_cfg.marg
|
|
},
|
|
rf_cfg: '{
|
|
cfg_en: ast_rf_cfg.marg_en,
|
|
cfg: ast_rf_cfg.marg
|
|
}
|
|
};
|
|
|
|
assign ram_2p_cfg = '{
|
|
a_ram_fcfg: '{
|
|
cfg_en: ast_ram_2p_fcfg.marg_en_a,
|
|
cfg: ast_ram_2p_fcfg.marg_a
|
|
},
|
|
a_ram_lcfg: '{
|
|
cfg_en: ast_ram_2p_lcfg.marg_en_a,
|
|
cfg: ast_ram_2p_lcfg.marg_a
|
|
},
|
|
b_ram_fcfg: '{
|
|
cfg_en: ast_ram_2p_fcfg.marg_en_b,
|
|
cfg: ast_ram_2p_fcfg.marg_b
|
|
},
|
|
b_ram_lcfg: '{
|
|
cfg_en: ast_ram_2p_lcfg.marg_en_b,
|
|
cfg: ast_ram_2p_lcfg.marg_b
|
|
}
|
|
};
|
|
|
|
assign rom_cfg = '{
|
|
cfg_en: ast_rom_cfg.marg_en,
|
|
cfg: ast_rom_cfg.marg
|
|
};
|
|
|
|
|
|
// AST does not use all clocks / resets forwarded to it
|
|
logic unused_slow_clk_en;
|
|
logic unused_usb_clk_aon;
|
|
logic unused_usb_clk_io_div4;
|
|
assign unused_slow_clk_en = base_ast_pwr.slow_clk_en;
|
|
assign unused_usb_clk_aon = clks_ast.clk_ast_usbdev_aon_peri;
|
|
assign unused_usb_clk_io_div4 = clks_ast.clk_ast_usbdev_io_div4_peri;
|
|
|
|
logic unused_usb_usb_rst;
|
|
logic [PowerDomains-1:0] unused_usb_sys_io_div4_rst;
|
|
logic [PowerDomains-1:0] unused_usb_sys_aon_rst;
|
|
logic unused_ast_sys_io_div4_rst;
|
|
logic unused_sensor_ctrl_sys_io_div4_rst;
|
|
logic unused_adc_ctrl_sys_io_div4_rst;
|
|
logic unused_entropy_sys_rst;
|
|
logic unused_edn_sys_rst;
|
|
assign unused_usb_usb_rst = rsts_ast.rst_ast_usbdev_usb_n[DomainAonSel];
|
|
assign unused_usb_sys_io_div4_rst = rsts_ast.rst_ast_usbdev_sys_io_div4_n;
|
|
assign unused_usb_sys_aon_rst = rsts_ast.rst_ast_usbdev_sys_aon_n;
|
|
assign unused_ast_sys_io_div4_rst =
|
|
rsts_ast.rst_ast_ast_sys_io_div4_n[Domain0Sel];
|
|
assign unused_sensor_ctrl_sys_io_div4_rst =
|
|
rsts_ast.rst_ast_sensor_ctrl_aon_sys_io_div4_n[Domain0Sel];
|
|
assign unused_adc_ctrl_sys_io_div4_rst =
|
|
rsts_ast.rst_ast_adc_ctrl_aon_sys_io_div4_n[Domain0Sel];
|
|
assign unused_entropy_sys_rst = rsts_ast.rst_ast_entropy_src_sys_n[DomainAonSel];
|
|
assign unused_edn_sys_rst = rsts_ast.rst_ast_edn0_sys_n[DomainAonSel];
|
|
|
|
ast_pkg::ast_dif_t flash_alert;
|
|
ast_pkg::ast_dif_t otp_alert;
|
|
logic ast_init_done;
|
|
|
|
ast #(
|
|
.EntropyStreams(ast_pkg::EntropyStreams),
|
|
.AdcChannels(ast_pkg::AdcChannels),
|
|
.AdcDataWidth(ast_pkg::AdcDataWidth),
|
|
.UsbCalibWidth(ast_pkg::UsbCalibWidth),
|
|
.Ast2PadOutWidth(ast_pkg::Ast2PadOutWidth),
|
|
.Pad2AstInWidth(ast_pkg::Pad2AstInWidth)
|
|
) u_ast (
|
|
// tlul
|
|
.tl_i ( base_ast_bus ),
|
|
.tl_o ( ast_base_bus ),
|
|
// init done indication
|
|
.ast_init_done_o ( ast_init_done ),
|
|
// buffered clocks & resets
|
|
// Reset domain connection is manual at the moment
|
|
.clk_ast_adc_i ( clks_ast.clk_ast_adc_ctrl_aon_io_div4_peri ),
|
|
.rst_ast_adc_ni ( rsts_ast.rst_ast_adc_ctrl_aon_sys_io_div4_n[DomainAonSel] ),
|
|
.clk_ast_alert_i ( clks_ast.clk_ast_sensor_ctrl_aon_io_div4_secure ),
|
|
.rst_ast_alert_ni ( rsts_ast.rst_ast_sensor_ctrl_aon_sys_io_div4_n[DomainAonSel] ),
|
|
.clk_ast_es_i ( clks_ast.clk_ast_edn0_main_secure ),
|
|
.rst_ast_es_ni ( rsts_ast.rst_ast_edn0_sys_n[Domain0Sel] ),
|
|
.clk_ast_rng_i ( clks_ast.clk_ast_entropy_src_main_secure ),
|
|
.rst_ast_rng_ni ( rsts_ast.rst_ast_entropy_src_sys_n[Domain0Sel] ),
|
|
.clk_ast_tlul_i ( clks_ast.clk_ast_ast_io_div4_secure ),
|
|
.rst_ast_tlul_ni ( rsts_ast.rst_ast_ast_sys_io_div4_n[DomainAonSel] ),
|
|
.clk_ast_usb_i ( clks_ast.clk_ast_usbdev_usb_peri ),
|
|
.rst_ast_usb_ni ( rsts_ast.rst_ast_usbdev_usb_n[Domain0Sel] ),
|
|
.clk_ast_ext_i ( ext_clk ),
|
|
.por_ni ( manual_in_por_n ),
|
|
// clocks' oschillator bypass for FPGA
|
|
.clk_osc_byp_i ( '0 ),
|
|
// pok test for FPGA
|
|
.vcc_supp_i ( 1'b1 ),
|
|
.vcaon_supp_i ( 1'b1 ),
|
|
.vcmain_supp_i ( 1'b1 ),
|
|
.vioa_supp_i ( 1'b1 ),
|
|
.viob_supp_i ( 1'b1 ),
|
|
// pok
|
|
.vcaon_pok_o ( aon_pok ),
|
|
.vcmain_pok_o ( ast_base_pwr.main_pok ),
|
|
.vioa_pok_o ( ast_status.io_pok[0] ),
|
|
.viob_pok_o ( ast_status.io_pok[1] ),
|
|
// main regulator
|
|
.main_env_iso_en_i ( base_ast_pwr.pwr_clamp_env ),
|
|
.main_pd_ni ( base_ast_pwr.main_pd_n ),
|
|
// pdm control (flash)/otp
|
|
.flash_power_down_h_o ( flash_power_down_h ),
|
|
.flash_power_ready_h_o ( flash_power_ready_h ),
|
|
.otp_power_seq_i ( otp_ctrl_otp_ast_pwr_seq ),
|
|
.otp_power_seq_h_o ( otp_ctrl_otp_ast_pwr_seq_h ),
|
|
// system source clock
|
|
.clk_src_sys_en_i ( base_ast_pwr.core_clk_en ),
|
|
// need to add function in clkmgr
|
|
.clk_src_sys_jen_i ( jen ),
|
|
.clk_src_sys_o ( ast_base_clks.clk_sys ),
|
|
.clk_src_sys_val_o ( ast_base_pwr.core_clk_val ),
|
|
// aon source clock
|
|
.clk_src_aon_o ( ast_base_clks.clk_aon ),
|
|
.clk_src_aon_val_o ( ast_base_pwr.slow_clk_val ),
|
|
// io source clock
|
|
.clk_src_io_en_i ( base_ast_pwr.io_clk_en ),
|
|
.clk_src_io_o ( ast_base_clks.clk_io ),
|
|
.clk_src_io_val_o ( ast_base_pwr.io_clk_val ),
|
|
// usb source clock
|
|
.usb_ref_pulse_i ( usb_ref_pulse ),
|
|
.usb_ref_val_i ( usb_ref_val ),
|
|
.clk_src_usb_en_i ( base_ast_pwr.usb_clk_en ),
|
|
.clk_src_usb_o ( ast_base_clks.clk_usb ),
|
|
.clk_src_usb_val_o ( ast_base_pwr.usb_clk_val ),
|
|
// USB IO Pull-up Calibration Setting
|
|
.usb_io_pu_cal_o ( usb_io_pu_cal ),
|
|
// adc
|
|
.adc_a0_ai ( CC1 ),
|
|
.adc_a1_ai ( CC2 ),
|
|
.adc_pd_i ( adc_req.pd ),
|
|
.adc_chnsel_i ( adc_req.channel_sel ),
|
|
.adc_d_o ( adc_rsp.data ),
|
|
.adc_d_val_o ( adc_rsp.data_valid ),
|
|
// rng
|
|
.rng_en_i ( es_rng_req.rng_enable ),
|
|
.rng_fips_i ( es_rng_fips ),
|
|
.rng_val_o ( es_rng_rsp.rng_valid ),
|
|
.rng_b_o ( es_rng_rsp.rng_b ),
|
|
// entropy
|
|
.entropy_rsp_i ( ast_edn_edn_rsp ),
|
|
.entropy_req_o ( ast_edn_edn_req ),
|
|
// alerts
|
|
.fla_alert_src_i ( flash_alert ),
|
|
.otp_alert_src_i ( otp_alert ),
|
|
.alert_rsp_i ( ast_alert_rsp ),
|
|
.alert_req_o ( ast_alert_req ),
|
|
// dft
|
|
.dft_strap_test_i ( dft_strap_test ),
|
|
.lc_dft_en_i ( dft_en ),
|
|
// pinmux related
|
|
.padmux2ast_i ( pad2ast ),
|
|
.ast2padmux_o ( ast2pinmux ),
|
|
// Direct short to PAD
|
|
.pad2ast_t0_ai ( IOA4 ),
|
|
.pad2ast_t1_ai ( IOA5 ),
|
|
.ast2pad_t0_ao ( IOA2 ),
|
|
.ast2pad_t1_ao ( IOA3 ),
|
|
.lc_clk_byp_req_i ( ast_clk_byp_req ),
|
|
.lc_clk_byp_ack_o ( ast_clk_byp_ack ),
|
|
.flash_bist_en_o ( flash_bist_enable ),
|
|
// Memory configuration connections
|
|
.dpram_rmf_o ( ast_ram_2p_fcfg ),
|
|
.dpram_rml_o ( ast_ram_2p_lcfg ),
|
|
.spram_rm_o ( ast_ram_1p_cfg ),
|
|
.sprgf_rm_o ( ast_rf_cfg ),
|
|
.sprom_rm_o ( ast_rom_cfg ),
|
|
// scan
|
|
.dft_scan_md_o ( scanmode ),
|
|
.scan_shift_en_o ( scan_en ),
|
|
.scan_reset_no ( scan_rst_n )
|
|
);
|
|
|
|
//////////////////////
|
|
// Top-level design //
|
|
//////////////////////
|
|
|
|
top_${top["name"]} #(
|
|
.PinmuxAonTargetCfg(PinmuxTargetCfg)
|
|
) top_${top["name"]} (
|
|
.rst_ni ( aon_pok ),
|
|
// ast connections
|
|
.clk_main_i ( ast_base_clks.clk_sys ),
|
|
.clk_io_i ( ast_base_clks.clk_io ),
|
|
.clk_usb_i ( ast_base_clks.clk_usb ),
|
|
.clk_aon_i ( ast_base_clks.clk_aon ),
|
|
.clks_ast_o ( clks_ast ),
|
|
.clk_main_jitter_en_o ( jen ),
|
|
.rsts_ast_o ( rsts_ast ),
|
|
.pwrmgr_ast_req_o ( base_ast_pwr ),
|
|
.pwrmgr_ast_rsp_i ( ast_base_pwr ),
|
|
.sensor_ctrl_ast_alert_req_i ( ast_alert_req ),
|
|
.sensor_ctrl_ast_alert_rsp_o ( ast_alert_rsp ),
|
|
.sensor_ctrl_ast_status_i ( ast_status ),
|
|
.usbdev_usb_ref_val_o ( usb_ref_pulse ),
|
|
.usbdev_usb_ref_pulse_o ( usb_ref_val ),
|
|
.ast_tl_req_o ( base_ast_bus ),
|
|
.ast_tl_rsp_i ( ast_base_bus ),
|
|
.adc_req_o ( adc_req ),
|
|
.adc_rsp_i ( adc_rsp ),
|
|
.ast_edn_req_i ( ast_edn_edn_req ),
|
|
.ast_edn_rsp_o ( ast_edn_edn_rsp ),
|
|
.otp_ctrl_otp_ast_pwr_seq_o ( otp_ctrl_otp_ast_pwr_seq ),
|
|
.otp_ctrl_otp_ast_pwr_seq_h_i ( otp_ctrl_otp_ast_pwr_seq_h ),
|
|
.otp_alert_o ( otp_alert ),
|
|
.flash_bist_enable_i ( flash_bist_enable ),
|
|
.flash_power_down_h_i ( flash_power_down_h ),
|
|
.flash_power_ready_h_i ( flash_power_ready_h ),
|
|
.flash_alert_o ( flash_alert ),
|
|
.es_rng_req_o ( es_rng_req ),
|
|
.es_rng_rsp_i ( es_rng_rsp ),
|
|
.es_rng_fips_o ( es_rng_fips ),
|
|
.ast_clk_byp_req_o ( ast_clk_byp_req ),
|
|
.ast_clk_byp_ack_i ( ast_clk_byp_ack ),
|
|
.ast2pinmux_i ( ast2pinmux ),
|
|
.ast_init_done_i ( ast_init_done ),
|
|
|
|
// Flash test mode voltages
|
|
.flash_test_mode_a_io ( {FLASH_TEST_MODE1,
|
|
FLASH_TEST_MODE0} ),
|
|
.flash_test_voltage_h_io ( FLASH_TEST_VOLT ),
|
|
|
|
// OTP external voltage
|
|
.otp_ext_voltage_h_io ( OTP_EXT_VOLT ),
|
|
|
|
// Multiplexed I/O
|
|
.mio_in_i ( mio_in ),
|
|
.mio_out_o ( mio_out ),
|
|
.mio_oe_o ( mio_oe ),
|
|
|
|
// Dedicated I/O
|
|
.dio_in_i ( dio_in ),
|
|
.dio_out_o ( dio_out ),
|
|
.dio_oe_o ( dio_oe ),
|
|
|
|
// Pad attributes
|
|
.mio_attr_o ( mio_attr ),
|
|
.dio_attr_o ( dio_attr ),
|
|
|
|
// Memory attributes
|
|
.ram_1p_cfg_i ( ram_1p_cfg ),
|
|
.ram_2p_cfg_i ( ram_2p_cfg ),
|
|
.rom_cfg_i ( rom_cfg ),
|
|
|
|
// DFT signals
|
|
.ast_lc_dft_en_o ( dft_en ),
|
|
.dft_strap_test_o ( dft_strap_test ),
|
|
.dft_hold_tap_sel_i ( '0 ),
|
|
.scan_rst_ni ( scan_rst_n ),
|
|
.scan_en_i ( scan_en ),
|
|
.scanmode_i ( scanmode )
|
|
);
|
|
% endif
|
|
|
|
###################################################################
|
|
## FPGA shared ##
|
|
###################################################################
|
|
% if target["name"] in ["cw310", "cw305", "nexysvideo"]:
|
|
//////////////////
|
|
// PLL for FPGA //
|
|
//////////////////
|
|
|
|
assign manual_out_io_clk = 1'b0;
|
|
assign manual_oe_io_clk = 1'b0;
|
|
assign manual_out_por_n = 1'b0;
|
|
assign manual_oe_por_n = 1'b0;
|
|
assign manual_out_io_jsrst_n = 1'b0;
|
|
assign manual_oe_io_jsrst_n = 1'b0;
|
|
|
|
logic clk_main, clk_usb_48mhz, clk_aon, rst_n;
|
|
clkgen_xil7series # (
|
|
.AddClkBuf(0)
|
|
) clkgen (
|
|
.clk_i(manual_in_io_clk),
|
|
.rst_ni(manual_in_por_n),
|
|
.jtag_srst_ni(manual_in_io_jsrst_n),
|
|
.clk_main_o(clk_main),
|
|
.clk_48MHz_o(clk_usb_48mhz),
|
|
.clk_aon_o(clk_aon),
|
|
.rst_no(rst_n)
|
|
);
|
|
|
|
//////////////////////
|
|
// Top-level design //
|
|
//////////////////////
|
|
pwrmgr_pkg::pwr_ast_rsp_t ast_base_pwr;
|
|
ast_pkg::ast_alert_req_t ast_base_alerts;
|
|
ast_pkg::ast_status_t ast_base_status;
|
|
|
|
assign ast_base_pwr.slow_clk_val = 1'b1;
|
|
assign ast_base_pwr.core_clk_val = 1'b1;
|
|
assign ast_base_pwr.io_clk_val = 1'b1;
|
|
assign ast_base_pwr.usb_clk_val = 1'b1;
|
|
assign ast_base_pwr.main_pok = 1'b1;
|
|
|
|
ast_pkg::ast_dif_t silent_alert = '{
|
|
p: 1'b0,
|
|
n: 1'b1
|
|
};
|
|
|
|
assign ast_base_alerts.alerts = {ast_pkg::NumAlerts{silent_alert}};
|
|
assign ast_base_status.io_pok = {ast_pkg::NumIoRails{1'b1}};
|
|
|
|
// the rst_ni pin only goes to AST
|
|
// the rest of the logic generates reset based on the 'pok' signal.
|
|
// for verilator purposes, make these two the same.
|
|
lc_ctrl_pkg::lc_tx_t lc_clk_bypass;
|
|
|
|
% if target["name"] == "cw305":
|
|
// This is used for outputting the capture trigger
|
|
logic [pinmux_reg_pkg::NMioPads-1:0] mio_out_pre;
|
|
% endif
|
|
|
|
// TODO: align this with ASIC version to minimize the duplication.
|
|
// Also need to add AST simulation and FPGA emulation models for things like entropy source -
|
|
// otherwise Verilator / FPGA will hang.
|
|
top_${top["name"]} #(
|
|
% if target["name"] == "cw310":
|
|
.AesMasking(1'b1),
|
|
.AesSBoxImpl(aes_pkg::SBoxImplDom),
|
|
.KmacEnMasking(0),
|
|
.CsrngSBoxImpl(aes_pkg::SBoxImplLut),
|
|
.OtbnRegFile(otbn_pkg::RegFileFPGA),
|
|
.OtpCtrlMemInitFile(OtpCtrlMemInitFile),
|
|
% elif target["name"] == "cw305":
|
|
.AesMasking(1'b1),
|
|
.AesSBoxImpl(aes_pkg::SBoxImplDom),
|
|
.SecAesStartTriggerDelay(40),
|
|
.SecAesAllowForcingMasks(1'b1),
|
|
.SecAesSkipPRNGReseeding(1'b1),
|
|
.RvCoreIbexICache(0),
|
|
% else:
|
|
.AesMasking(1'b0),
|
|
.AesSBoxImpl(aes_pkg::SBoxImplLut),
|
|
.KmacEnMasking(1'b0),
|
|
.SecAesStartTriggerDelay(0),
|
|
.SecAesAllowForcingMasks(1'b0),
|
|
.SecAesSkipPRNGReseeding(1'b0),
|
|
.EntropySrcStub(1'b1),
|
|
.CsrngSBoxImpl(aes_pkg::SBoxImplLut),
|
|
.OtbnRegFile(otbn_pkg::RegFileFPGA),
|
|
.OtbnStub(1'b1),
|
|
.OtpCtrlMemInitFile(OtpCtrlMemInitFile),
|
|
% endif
|
|
.RomCtrlBootRomInitFile(BootRomInitFile),
|
|
.RvCoreIbexRegFile(ibex_pkg::RegFileFPGA),
|
|
.RvCoreIbexPipeLine(1),
|
|
.SecRvCoreIbexureIbex(0),
|
|
.SramCtrlRetAonInstrExec(0),
|
|
.SramCtrlMainInstrExec(1),
|
|
.PinmuxAonTargetCfg(PinmuxTargetCfg)
|
|
) top_${top["name"]} (
|
|
.rst_ni ( rst_n ),
|
|
.clk_main_i ( clk_main ),
|
|
.clk_io_i ( clk_main ),
|
|
.clk_usb_i ( clk_usb_48mhz ),
|
|
.clk_aon_i ( clk_aon ),
|
|
.clks_ast_o ( ),
|
|
.clk_main_jitter_en_o ( ),
|
|
.rsts_ast_o ( ),
|
|
.pwrmgr_ast_req_o ( ),
|
|
.pwrmgr_ast_rsp_i ( ast_base_pwr ),
|
|
.sensor_ctrl_ast_alert_req_i ( ast_base_alerts ),
|
|
.sensor_ctrl_ast_alert_rsp_o ( ),
|
|
.sensor_ctrl_ast_status_i ( ast_base_status ),
|
|
.usbdev_usb_ref_val_o ( ),
|
|
.usbdev_usb_ref_pulse_o ( ),
|
|
.ast_edn_req_i ( '0 ),
|
|
.ast_edn_rsp_o ( ),
|
|
.flash_bist_enable_i ( lc_ctrl_pkg::Off ),
|
|
.flash_power_down_h_i ( 1'b0 ),
|
|
.flash_power_ready_h_i ( 1'b1 ),
|
|
.ast_clk_byp_req_o ( lc_clk_bypass ),
|
|
.ast_clk_byp_ack_i ( lc_clk_bypass ),
|
|
|
|
% if target["name"] != "cw305":
|
|
.ast_tl_req_o ( ),
|
|
.ast_tl_rsp_i ( '0 ),
|
|
.otp_ctrl_otp_ast_pwr_seq_o ( ),
|
|
.otp_ctrl_otp_ast_pwr_seq_h_i ( '0 ),
|
|
.otp_alert_o ( ),
|
|
.es_rng_req_o ( ),
|
|
.es_rng_rsp_i ( '0 ),
|
|
.es_rng_fips_o ( ),
|
|
.ast2pinmux_i ( '0 ),
|
|
% endif
|
|
|
|
// Multiplexed I/O
|
|
.mio_in_i ( mio_in ),
|
|
% if target["name"] == "cw305":
|
|
.mio_out_o ( mio_out_pre ),
|
|
% else:
|
|
.mio_out_o ( mio_out ),
|
|
% endif
|
|
.mio_oe_o ( mio_oe ),
|
|
|
|
// Dedicated I/O
|
|
.dio_in_i ( dio_in ),
|
|
.dio_out_o ( dio_out ),
|
|
.dio_oe_o ( dio_oe ),
|
|
|
|
// Pad attributes
|
|
.mio_attr_o ( mio_attr ),
|
|
.dio_attr_o ( dio_attr ),
|
|
|
|
// Memory attributes
|
|
.ram_1p_cfg_i ( '0 ),
|
|
.ram_2p_cfg_i ( '0 ),
|
|
.rom_cfg_i ( '0 ),
|
|
|
|
// DFT signals
|
|
.dft_hold_tap_sel_i ( '0 ),
|
|
.scan_rst_ni ( 1'b1 ),
|
|
.scan_en_i ( 1'b0 ),
|
|
.scanmode_i ( lc_ctrl_pkg::Off )
|
|
);
|
|
% endif
|
|
|
|
|
|
###################################################################
|
|
## CW305 capture board interface ##
|
|
###################################################################
|
|
## TODO: This needs to be adapted to enable captures on the CW310. In particular,
|
|
## - a precise capture trigger and the target clock need to be output, and
|
|
## - a separate UART should be used for the simpleserial communication with the capture board.
|
|
## See also pins_cw310.xdc
|
|
% if target["name"] in ["cw305"]:
|
|
|
|
//////////////////////////////////////
|
|
// Generate precise capture trigger //
|
|
//////////////////////////////////////
|
|
|
|
// TODO: make this a "manual" IO specific to the CW305 target
|
|
// such that we can decouple this from the MIO signals.
|
|
localparam int MioIdxTrigger = 15;
|
|
|
|
// To obtain a more precise capture trigger for side-channel analysis, we only forward the
|
|
// software-controlled capture trigger when the AES module is actually busy (performing
|
|
// either encryption/decryption or clearing internal registers).
|
|
// GPIO15 is used as capture trigger (mapped to IOB6 at the moment in pinmux.c).
|
|
always_comb begin : p_trigger
|
|
mio_out = mio_out_pre;
|
|
mio_out[MioIdxTrigger] = mio_out_pre[MioIdxTrigger] &
|
|
~top_${top["name"]}.clkmgr_aon_idle[clkmgr_pkg::Aes];
|
|
end
|
|
|
|
//////////////////////
|
|
// ChipWhisperer IO //
|
|
//////////////////////
|
|
|
|
logic unused_inputs;
|
|
assign unused_inputs = manual_in_tio_clkout ^ manual_in_io_utx_debug;
|
|
|
|
// Clock output to capture board.
|
|
assign manual_out_tio_clkout = manual_in_io_clk;
|
|
assign manual_oe_tio_clkout = 1'b1;
|
|
|
|
% endif
|
|
## This separate UART debugging output is needed for the CW305 only.
|
|
% if target["name"] == "cw305":
|
|
|
|
// UART Tx for debugging. The UART itself is connected to the capture board.
|
|
assign manual_out_io_utx_debug = top_${top["name"]}.cio_uart0_tx_d2p;
|
|
assign manual_oe_io_utx_debug = 1'b1;
|
|
|
|
% endif
|
|
|
|
endmodule : chip_${top["name"]}_${target["name"]}
|