Compare commits
2 commits
master
...
orangecrab
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9da113b53e | ||
|
|
ad5e7e29e9 |
5 changed files with 1695 additions and 2 deletions
|
|
@ -2,11 +2,14 @@
|
||||||
// See Notices.txt for copyright information
|
// See Notices.txt for copyright information
|
||||||
|
|
||||||
pub mod xilinx;
|
pub mod xilinx;
|
||||||
|
pub mod lattice;
|
||||||
|
|
||||||
pub(crate) fn built_in_job_kinds() -> impl IntoIterator<Item = crate::build::DynJobKind> {
|
pub(crate) fn built_in_job_kinds() -> impl IntoIterator<Item = crate::build::DynJobKind> {
|
||||||
xilinx::built_in_job_kinds()
|
xilinx::built_in_job_kinds();
|
||||||
|
lattice::built_in_job_kinds()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn built_in_platforms() -> impl IntoIterator<Item = crate::platform::DynPlatform> {
|
pub(crate) fn built_in_platforms() -> impl IntoIterator<Item = crate::platform::DynPlatform> {
|
||||||
xilinx::built_in_platforms()
|
xilinx::built_in_platforms();
|
||||||
|
lattice::built_in_platforms()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
191
crates/fayalite/src/vendor/lattice.rs
vendored
Normal file
191
crates/fayalite/src/vendor/lattice.rs
vendored
Normal file
|
|
@ -0,0 +1,191 @@
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
// See Notices.txt for copyright information
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
annotations::make_annotation_enum,
|
||||||
|
build::{GlobalParams, ToArgs, WriteArgs},
|
||||||
|
intern::Interned,
|
||||||
|
prelude::{DynPlatform, Platform},
|
||||||
|
};
|
||||||
|
use clap::ValueEnum;
|
||||||
|
use ordered_float::NotNan;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
pub mod orangecrab;
|
||||||
|
pub mod primitives;
|
||||||
|
pub mod yosys_nextpnr;
|
||||||
|
|
||||||
|
/* fixme make_annotation_enum! {
|
||||||
|
#[non_exhaustive]
|
||||||
|
pub enum LatticeAnnotation {
|
||||||
|
XdcIOStandard(XdcIOStandardAnnotation),
|
||||||
|
XdcLocation(XdcLocationAnnotation),
|
||||||
|
XdcCreateClock(XdcCreateClockAnnotation),
|
||||||
|
}
|
||||||
|
} */
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Eq, Hash, Debug, clap::Args)]
|
||||||
|
pub struct LatticeArgs {
|
||||||
|
#[arg(long)]
|
||||||
|
pub device: Option<Device>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LatticeArgs {
|
||||||
|
pub fn require_device(
|
||||||
|
&self,
|
||||||
|
platform: Option<&DynPlatform>,
|
||||||
|
global_params: &GlobalParams,
|
||||||
|
) -> clap::error::Result<Device> {
|
||||||
|
if let Some(device) = self.device {
|
||||||
|
return Ok(device);
|
||||||
|
}
|
||||||
|
if let Some(device) =
|
||||||
|
platform.and_then(|platform| platform.aspects().get_single_by_type::<Device>().copied())
|
||||||
|
{
|
||||||
|
return Ok(device);
|
||||||
|
}
|
||||||
|
Err(global_params.clap_error(
|
||||||
|
clap::error::ErrorKind::MissingRequiredArgument,
|
||||||
|
"missing --device option",
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToArgs for LatticeArgs {
|
||||||
|
fn to_args(&self, args: &mut (impl WriteArgs + ?Sized)) {
|
||||||
|
if let Some(device) = self.device {
|
||||||
|
args.write_long_option_eq("device", device.as_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! make_device_enum {
|
||||||
|
($vis:vis enum $Device:ident {
|
||||||
|
$(
|
||||||
|
#[
|
||||||
|
name = $name:literal,
|
||||||
|
xray_part = $xray_part:literal,
|
||||||
|
xray_device = $xray_device:literal,
|
||||||
|
xray_family = $xray_family:literal,
|
||||||
|
]
|
||||||
|
$variant:ident,
|
||||||
|
)*
|
||||||
|
}) => {
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, ValueEnum)]
|
||||||
|
$vis enum $Device {
|
||||||
|
$(
|
||||||
|
#[value(name = $name, alias = $xray_part)]
|
||||||
|
$variant,
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
|
||||||
|
impl $Device {
|
||||||
|
$vis fn as_str(self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
$(Self::$variant => $name,)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$vis fn xray_part(self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
$(Self::$variant => $xray_part,)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$vis fn xray_device(self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
$(Self::$variant => $xray_device,)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$vis fn xray_family(self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
$(Self::$variant => $xray_family,)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DeviceVisitor;
|
||||||
|
|
||||||
|
impl<'de> serde::de::Visitor<'de> for DeviceVisitor {
|
||||||
|
type Value = $Device;
|
||||||
|
|
||||||
|
fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
f.write_str("a Lattice device string")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: serde::de::Error,
|
||||||
|
{
|
||||||
|
match $Device::from_str(v, false) {
|
||||||
|
Ok(v) => Ok(v),
|
||||||
|
Err(_) => Err(E::invalid_value(serde::de::Unexpected::Str(v), &self)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: serde::de::Error,
|
||||||
|
{
|
||||||
|
match str::from_utf8(v).ok().and_then(|v| $Device::from_str(v, false).ok()) {
|
||||||
|
Some(v) => Ok(v),
|
||||||
|
None => Err(E::invalid_value(serde::de::Unexpected::Bytes(v), &self)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> Deserialize<'de> for $Device {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: serde::Deserializer<'de>,
|
||||||
|
{
|
||||||
|
deserializer.deserialize_string(DeviceVisitor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Serialize for $Device {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: serde::Serializer,
|
||||||
|
{
|
||||||
|
self.as_str().serialize(serializer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
make_device_enum! {
|
||||||
|
pub enum Device {
|
||||||
|
#[
|
||||||
|
name = "xc7a35ticsg324-1L",
|
||||||
|
xray_part = "xc7a35tcsg324-1",
|
||||||
|
xray_device = "xc7a35t",
|
||||||
|
xray_family = "artix7",
|
||||||
|
]
|
||||||
|
Xc7a35ticsg324_1l,
|
||||||
|
#[
|
||||||
|
name = "xc7a100ticsg324-1L",
|
||||||
|
xray_part = "xc7a100tcsg324-1",
|
||||||
|
xray_device = "xc7a100t",
|
||||||
|
xray_family = "artix7",
|
||||||
|
]
|
||||||
|
Xc7a100ticsg324_1l,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Device {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
f.write_str(self.as_str())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn built_in_job_kinds() -> impl IntoIterator<Item = crate::build::DynJobKind> {
|
||||||
|
orangecrab::built_in_job_kinds()
|
||||||
|
.into_iter()
|
||||||
|
.chain(yosys_nextpnr::built_in_job_kinds())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn built_in_platforms() -> impl IntoIterator<Item = crate::platform::DynPlatform> {
|
||||||
|
orangecrab::built_in_platforms()
|
||||||
|
.into_iter()
|
||||||
|
.chain(yosys_nextpnr::built_in_platforms())
|
||||||
|
}
|
||||||
405
crates/fayalite/src/vendor/lattice/orangecrab.rs
vendored
Normal file
405
crates/fayalite/src/vendor/lattice/orangecrab.rs
vendored
Normal file
|
|
@ -0,0 +1,405 @@
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
// See Notices.txt for copyright information
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
intern::{Intern, Interned},
|
||||||
|
module::{instance_with_loc, reg_builder_with_loc, wire_with_loc},
|
||||||
|
platform::{
|
||||||
|
DynPlatform, Peripheral, PeripheralRef, Peripherals, PeripheralsBuilderFactory,
|
||||||
|
PeripheralsBuilderFinished, Platform, PlatformAspectSet,
|
||||||
|
peripherals::{ClockInput, Led, RgbLed, Uart},
|
||||||
|
},
|
||||||
|
prelude::*,
|
||||||
|
vendor::lattice::{
|
||||||
|
Device,
|
||||||
|
primitives,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use ordered_float::NotNan;
|
||||||
|
use std::sync::OnceLock;
|
||||||
|
|
||||||
|
macro_rules! orangecrab_platform {
|
||||||
|
(
|
||||||
|
$vis:vis enum $ArtyA7Platform:ident {
|
||||||
|
$(#[name = $name:literal, device = $device:ident]
|
||||||
|
$Variant:ident,)*
|
||||||
|
}
|
||||||
|
) => {
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
$vis enum $ArtyA7Platform {
|
||||||
|
$($Variant,)*
|
||||||
|
}
|
||||||
|
|
||||||
|
impl $ArtyA7Platform {
|
||||||
|
$vis const VARIANTS: &'static [Self] = &[$(Self::$Variant,)*];
|
||||||
|
$vis fn device(self) -> Device {
|
||||||
|
match self {
|
||||||
|
$(Self::$Variant => Device::$device,)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$vis const fn as_str(self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
$(Self::$Variant => $name,)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn get_aspects(self) -> &'static PlatformAspectSet {
|
||||||
|
match self {
|
||||||
|
$(Self::$Variant => {
|
||||||
|
static ASPECTS_SET: OnceLock<PlatformAspectSet> = OnceLock::new();
|
||||||
|
ASPECTS_SET.get_or_init(|| self.make_aspects())
|
||||||
|
})*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
orangecrab_platform! {
|
||||||
|
pub enum ArtyA7Platform {
|
||||||
|
#[name = "arty-a7-35t", device = Xc7a35ticsg324_1l]
|
||||||
|
ArtyA7_35T,
|
||||||
|
#[name = "arty-a7-100t", device = Xc7a100ticsg324_1l]
|
||||||
|
ArtyA7_100T,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ArtyA7Peripherals {
|
||||||
|
clk100_div_pow2: [Peripheral<ClockInput>; 4],
|
||||||
|
rst: Peripheral<Reset>,
|
||||||
|
rst_sync: Peripheral<SyncReset>,
|
||||||
|
ld0: Peripheral<RgbLed>,
|
||||||
|
ld1: Peripheral<RgbLed>,
|
||||||
|
ld2: Peripheral<RgbLed>,
|
||||||
|
ld3: Peripheral<RgbLed>,
|
||||||
|
ld4: Peripheral<Led>,
|
||||||
|
ld5: Peripheral<Led>,
|
||||||
|
ld6: Peripheral<Led>,
|
||||||
|
ld7: Peripheral<Led>,
|
||||||
|
uart: Peripheral<Uart>,
|
||||||
|
// TODO: add rest of peripherals when we need them
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Peripherals for ArtyA7Peripherals {
|
||||||
|
fn append_peripherals<'a>(&'a self, peripherals: &mut Vec<PeripheralRef<'a, CanonicalType>>) {
|
||||||
|
let Self {
|
||||||
|
clk100_div_pow2,
|
||||||
|
rst,
|
||||||
|
rst_sync,
|
||||||
|
ld0,
|
||||||
|
ld1,
|
||||||
|
ld2,
|
||||||
|
ld3,
|
||||||
|
ld4,
|
||||||
|
ld5,
|
||||||
|
ld6,
|
||||||
|
ld7,
|
||||||
|
uart,
|
||||||
|
} = self;
|
||||||
|
clk100_div_pow2.append_peripherals(peripherals);
|
||||||
|
rst.append_peripherals(peripherals);
|
||||||
|
rst_sync.append_peripherals(peripherals);
|
||||||
|
ld0.append_peripherals(peripherals);
|
||||||
|
ld1.append_peripherals(peripherals);
|
||||||
|
ld2.append_peripherals(peripherals);
|
||||||
|
ld3.append_peripherals(peripherals);
|
||||||
|
ld4.append_peripherals(peripherals);
|
||||||
|
ld5.append_peripherals(peripherals);
|
||||||
|
ld6.append_peripherals(peripherals);
|
||||||
|
ld7.append_peripherals(peripherals);
|
||||||
|
uart.append_peripherals(peripherals);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ArtyA7Platform {
|
||||||
|
fn make_aspects(self) -> PlatformAspectSet {
|
||||||
|
let mut retval = PlatformAspectSet::new();
|
||||||
|
retval.insert_new(self.device());
|
||||||
|
retval
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[hdl_module(extern)]
|
||||||
|
fn reset_sync() {
|
||||||
|
#[hdl]
|
||||||
|
let clk: Clock = m.input();
|
||||||
|
#[hdl]
|
||||||
|
let inp: Bool = m.input();
|
||||||
|
#[hdl]
|
||||||
|
let out: SyncReset = m.output();
|
||||||
|
m.annotate_module(BlackBoxInlineAnnotation {
|
||||||
|
path: "fayalite_orangecrab_reset_sync.v".intern(),
|
||||||
|
text: r#"module __fayalite_orangecrab_reset_sync(input clk, input inp, output out);
|
||||||
|
wire reset_0_out;
|
||||||
|
(* ASYNC_REG = "TRUE" *)
|
||||||
|
FDPE #(
|
||||||
|
.INIT(1'b1)
|
||||||
|
) reset_0 (
|
||||||
|
.Q(reset_0_out),
|
||||||
|
.C(clk),
|
||||||
|
.CE(1'b1),
|
||||||
|
.PRE(inp),
|
||||||
|
.D(1'b0)
|
||||||
|
);
|
||||||
|
(* ASYNC_REG = "TRUE" *)
|
||||||
|
FDPE #(
|
||||||
|
.INIT(1'b1)
|
||||||
|
) reset_1 (
|
||||||
|
.Q(out),
|
||||||
|
.C(clk),
|
||||||
|
.CE(1'b1),
|
||||||
|
.PRE(inp),
|
||||||
|
.D(reset_0_out)
|
||||||
|
);
|
||||||
|
endmodule
|
||||||
|
"#
|
||||||
|
.intern(),
|
||||||
|
});
|
||||||
|
m.verilog_name("__fayalite_orangecrab_reset_sync");
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Platform for ArtyA7Platform {
|
||||||
|
type Peripherals = ArtyA7Peripherals;
|
||||||
|
|
||||||
|
fn name(&self) -> Interned<str> {
|
||||||
|
self.as_str().intern()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_peripherals<'builder>(
|
||||||
|
&self,
|
||||||
|
builder_factory: PeripheralsBuilderFactory<'builder>,
|
||||||
|
) -> (Self::Peripherals, PeripheralsBuilderFinished<'builder>) {
|
||||||
|
let mut builder = builder_factory.builder();
|
||||||
|
|
||||||
|
let clk100_div_pow2 = std::array::from_fn(|log2_divisor| {
|
||||||
|
let divisor = 1u64 << log2_divisor;
|
||||||
|
let name = if divisor != 1 {
|
||||||
|
format!("clk100_div_{divisor}")
|
||||||
|
} else {
|
||||||
|
"clk100".into()
|
||||||
|
};
|
||||||
|
builder.input_peripheral(name, ClockInput::new(100e6 / divisor as f64))
|
||||||
|
});
|
||||||
|
builder.add_conflicts(Vec::from_iter(clk100_div_pow2.iter().map(|v| v.id())));
|
||||||
|
(
|
||||||
|
ArtyA7Peripherals {
|
||||||
|
clk100_div_pow2,
|
||||||
|
rst: builder.input_peripheral("rst", Reset),
|
||||||
|
rst_sync: builder.input_peripheral("rst_sync", SyncReset),
|
||||||
|
ld0: builder.output_peripheral("ld0", RgbLed),
|
||||||
|
ld1: builder.output_peripheral("ld1", RgbLed),
|
||||||
|
ld2: builder.output_peripheral("ld2", RgbLed),
|
||||||
|
ld3: builder.output_peripheral("ld3", RgbLed),
|
||||||
|
ld4: builder.output_peripheral("ld4", Led),
|
||||||
|
ld5: builder.output_peripheral("ld5", Led),
|
||||||
|
ld6: builder.output_peripheral("ld6", Led),
|
||||||
|
ld7: builder.output_peripheral("ld7", Led),
|
||||||
|
uart: builder.output_peripheral("uart", Uart),
|
||||||
|
},
|
||||||
|
builder.finish(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn source_location(&self) -> SourceLocation {
|
||||||
|
SourceLocation::builtin()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_peripherals_in_wrapper_module(&self, m: &ModuleBuilder, peripherals: Self::Peripherals) {
|
||||||
|
let ArtyA7Peripherals {
|
||||||
|
clk100_div_pow2,
|
||||||
|
rst,
|
||||||
|
rst_sync,
|
||||||
|
ld0,
|
||||||
|
ld1,
|
||||||
|
ld2,
|
||||||
|
ld3,
|
||||||
|
ld4,
|
||||||
|
ld5,
|
||||||
|
ld6,
|
||||||
|
ld7,
|
||||||
|
uart,
|
||||||
|
} = peripherals;
|
||||||
|
let make_buffered_input = |name: &str, location: &str, io_standard: &str, invert: bool| {
|
||||||
|
let pin = m.input_with_loc(name, SourceLocation::builtin(), Bool);
|
||||||
|
/* fixme annotate(
|
||||||
|
pin,
|
||||||
|
XdcLocationAnnotation {
|
||||||
|
location: location.intern(),
|
||||||
|
},
|
||||||
|
); */
|
||||||
|
/* fixme annotate(
|
||||||
|
pin,
|
||||||
|
XdcIOStandardAnnotation {
|
||||||
|
value: io_standard.intern(),
|
||||||
|
},
|
||||||
|
); */
|
||||||
|
let buf = instance_with_loc(
|
||||||
|
&format!("{name}_buf"),
|
||||||
|
primitives::IBUF(),
|
||||||
|
SourceLocation::builtin(),
|
||||||
|
);
|
||||||
|
connect(buf.I, pin);
|
||||||
|
if invert { !buf.O } else { buf.O }
|
||||||
|
};
|
||||||
|
let make_buffered_output = |name: &str, location: &str, io_standard: &str| {
|
||||||
|
let pin = m.output_with_loc(name, SourceLocation::builtin(), Bool);
|
||||||
|
/* fixme annotate(
|
||||||
|
pin,
|
||||||
|
XdcLocationAnnotation {
|
||||||
|
location: location.intern(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
annotate(
|
||||||
|
pin,
|
||||||
|
XdcIOStandardAnnotation {
|
||||||
|
value: io_standard.intern(),
|
||||||
|
},
|
||||||
|
); */
|
||||||
|
let buf = instance_with_loc(
|
||||||
|
&format!("{name}_buf"),
|
||||||
|
primitives::OBUFT(),
|
||||||
|
SourceLocation::builtin(),
|
||||||
|
);
|
||||||
|
connect(pin, buf.O);
|
||||||
|
connect(buf.T, false);
|
||||||
|
buf.I
|
||||||
|
};
|
||||||
|
let mut frequency = clk100_div_pow2[0].ty().frequency();
|
||||||
|
let mut log2_divisor = 0;
|
||||||
|
let mut clk = None;
|
||||||
|
for (cur_log2_divisor, p) in clk100_div_pow2.into_iter().enumerate() {
|
||||||
|
let Some(p) = p.into_used() else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
debug_assert!(
|
||||||
|
clk.is_none(),
|
||||||
|
"conflict-handling logic should ensure at most one clock is used",
|
||||||
|
);
|
||||||
|
frequency = p.ty().frequency();
|
||||||
|
clk = Some(p);
|
||||||
|
log2_divisor = cur_log2_divisor;
|
||||||
|
}
|
||||||
|
let clk100_buf = make_buffered_input("clk100", "E3", "LVCMOS33", false);
|
||||||
|
let startup = instance_with_loc(
|
||||||
|
"startup",
|
||||||
|
primitives::STARTUPE2_default_inputs(),
|
||||||
|
SourceLocation::builtin(),
|
||||||
|
);
|
||||||
|
let clk_global_buf = instance_with_loc(
|
||||||
|
"clk_global_buf",
|
||||||
|
primitives::BUFGCE(),
|
||||||
|
SourceLocation::builtin(),
|
||||||
|
);
|
||||||
|
connect(clk_global_buf.CE, startup.EOS);
|
||||||
|
let mut clk_global_buf_in = clk100_buf.to_clock();
|
||||||
|
for prev_log2_divisor in 0..log2_divisor {
|
||||||
|
let prev_divisor = 1u64 << prev_log2_divisor;
|
||||||
|
let clk_in = wire_with_loc(
|
||||||
|
&format!("clk_div_{prev_divisor}"),
|
||||||
|
SourceLocation::builtin(),
|
||||||
|
Clock,
|
||||||
|
);
|
||||||
|
connect(clk_in, clk_global_buf_in);
|
||||||
|
/* fixme
|
||||||
|
annotate(
|
||||||
|
clk_in,
|
||||||
|
XdcCreateClockAnnotation {
|
||||||
|
period: NotNan::new(1e9 / (100e6 / prev_divisor as f64))
|
||||||
|
.expect("known to be valid"),
|
||||||
|
},
|
||||||
|
); */
|
||||||
|
annotate(clk_in, DontTouchAnnotation);
|
||||||
|
let cd = wire_with_loc(
|
||||||
|
&format!("clk_div_{prev_divisor}_in"),
|
||||||
|
SourceLocation::builtin(),
|
||||||
|
ClockDomain[AsyncReset],
|
||||||
|
);
|
||||||
|
connect(cd.clk, clk_in);
|
||||||
|
connect(cd.rst, (!startup.EOS).to_async_reset());
|
||||||
|
let divider = reg_builder_with_loc("divider", SourceLocation::builtin())
|
||||||
|
.clock_domain(cd)
|
||||||
|
.reset(false)
|
||||||
|
.build();
|
||||||
|
connect(divider, !divider);
|
||||||
|
clk_global_buf_in = divider.to_clock();
|
||||||
|
}
|
||||||
|
connect(clk_global_buf.I, clk_global_buf_in);
|
||||||
|
let clk_out = wire_with_loc("clk_out", SourceLocation::builtin(), Clock);
|
||||||
|
connect(clk_out, clk_global_buf.O);
|
||||||
|
/* fixme annotate(
|
||||||
|
clk_out,
|
||||||
|
XdcCreateClockAnnotation {
|
||||||
|
period: NotNan::new(1e9 / frequency).expect("known to be valid"),
|
||||||
|
},
|
||||||
|
); */
|
||||||
|
annotate(clk_out, DontTouchAnnotation);
|
||||||
|
if let Some(clk) = clk {
|
||||||
|
connect(clk.instance_io_field().clk, clk_out);
|
||||||
|
}
|
||||||
|
let rst_value = {
|
||||||
|
let rst_buf = make_buffered_input("rst", "C2", "LVCMOS33", true);
|
||||||
|
let rst_sync = instance_with_loc("rst_sync", reset_sync(), SourceLocation::builtin());
|
||||||
|
connect(rst_sync.clk, clk_out);
|
||||||
|
connect(rst_sync.inp, rst_buf | !startup.EOS);
|
||||||
|
rst_sync.out
|
||||||
|
};
|
||||||
|
if let Some(rst) = rst.into_used() {
|
||||||
|
connect(rst.instance_io_field(), rst_value.to_reset());
|
||||||
|
}
|
||||||
|
if let Some(rst_sync) = rst_sync.into_used() {
|
||||||
|
connect(rst_sync.instance_io_field(), rst_value);
|
||||||
|
}
|
||||||
|
let rgb_leds = [
|
||||||
|
(ld0, ("G6", "F6", "E1")),
|
||||||
|
(ld1, ("G3", "J4", "G4")),
|
||||||
|
(ld2, ("J3", "J2", "H4")),
|
||||||
|
(ld3, ("K1", "H6", "K2")),
|
||||||
|
];
|
||||||
|
for (rgb_led, (r_loc, g_loc, b_loc)) in rgb_leds {
|
||||||
|
let r = make_buffered_output(&format!("{}_r", rgb_led.name()), r_loc, "LVCMOS33");
|
||||||
|
let g = make_buffered_output(&format!("{}_g", rgb_led.name()), g_loc, "LVCMOS33");
|
||||||
|
let b = make_buffered_output(&format!("{}_b", rgb_led.name()), b_loc, "LVCMOS33");
|
||||||
|
if let Some(rgb_led) = rgb_led.into_used() {
|
||||||
|
connect(r, rgb_led.instance_io_field().r);
|
||||||
|
connect(g, rgb_led.instance_io_field().g);
|
||||||
|
connect(b, rgb_led.instance_io_field().b);
|
||||||
|
} else {
|
||||||
|
connect(r, false);
|
||||||
|
connect(g, false);
|
||||||
|
connect(b, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let leds = [(ld4, "H5"), (ld5, "J5"), (ld6, "T9"), (ld7, "T10")];
|
||||||
|
for (led, loc) in leds {
|
||||||
|
let o = make_buffered_output(&led.name(), loc, "LVCMOS33");
|
||||||
|
if let Some(led) = led.into_used() {
|
||||||
|
connect(o, led.instance_io_field().on);
|
||||||
|
} else {
|
||||||
|
connect(o, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let uart_tx = make_buffered_output("uart_tx", "D10", "LVCMOS33");
|
||||||
|
let uart_rx = make_buffered_input("uart_rx", "A9", "LVCMOS33", false);
|
||||||
|
if let Some(uart) = uart.into_used() {
|
||||||
|
connect(uart_tx, uart.instance_io_field().tx);
|
||||||
|
connect(uart.instance_io_field().rx, uart_rx);
|
||||||
|
} else {
|
||||||
|
connect(uart_tx, true); // idle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn aspects(&self) -> PlatformAspectSet {
|
||||||
|
self.get_aspects().clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn built_in_job_kinds() -> impl IntoIterator<Item = crate::build::DynJobKind> {
|
||||||
|
[]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn built_in_platforms() -> impl IntoIterator<Item = DynPlatform> {
|
||||||
|
ArtyA7Platform::VARIANTS
|
||||||
|
.iter()
|
||||||
|
.map(|&v| DynPlatform::new(v))
|
||||||
|
}
|
||||||
50
crates/fayalite/src/vendor/lattice/primitives.rs
vendored
Normal file
50
crates/fayalite/src/vendor/lattice/primitives.rs
vendored
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
// See Notices.txt for copyright information
|
||||||
|
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
#[hdl_module(extern)]
|
||||||
|
pub fn IBUF() {
|
||||||
|
m.verilog_name("IBUF");
|
||||||
|
#[hdl]
|
||||||
|
let O: Bool = m.output();
|
||||||
|
#[hdl]
|
||||||
|
let I: Bool = m.input();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[hdl_module(extern)]
|
||||||
|
pub fn OBUFT() {
|
||||||
|
m.verilog_name("OBUFT");
|
||||||
|
#[hdl]
|
||||||
|
let O: Bool = m.output();
|
||||||
|
#[hdl]
|
||||||
|
let I: Bool = m.input();
|
||||||
|
#[hdl]
|
||||||
|
let T: Bool = m.input();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[hdl_module(extern)]
|
||||||
|
pub fn BUFGCE() {
|
||||||
|
m.verilog_name("BUFGCE");
|
||||||
|
#[hdl]
|
||||||
|
let O: Clock = m.output();
|
||||||
|
#[hdl]
|
||||||
|
let CE: Bool = m.input();
|
||||||
|
#[hdl]
|
||||||
|
let I: Clock = m.input();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[hdl_module(extern)]
|
||||||
|
pub fn STARTUPE2_default_inputs() {
|
||||||
|
m.verilog_name("STARTUPE2");
|
||||||
|
#[hdl]
|
||||||
|
let CFGCLK: Clock = m.output();
|
||||||
|
#[hdl]
|
||||||
|
let CFGMCLK: Clock = m.output();
|
||||||
|
#[hdl]
|
||||||
|
let EOS: Bool = m.output();
|
||||||
|
#[hdl]
|
||||||
|
let PREQ: Bool = m.output();
|
||||||
|
}
|
||||||
1044
crates/fayalite/src/vendor/lattice/yosys_nextpnr.rs
vendored
Normal file
1044
crates/fayalite/src/vendor/lattice/yosys_nextpnr.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue