Parcourir la source

Initial working version.

Kestrel il y a 1 an
commit
1079404de0
5 fichiers modifiés avec 119 ajouts et 0 suppressions
  1. 2 0
      .gitignore
  2. 9 0
      Cargo.toml
  3. 2 0
      src/lib.rs
  4. 44 0
      src/pins.rs
  5. 62 0
      src/synth.rs

+ 2 - 0
.gitignore

@@ -0,0 +1,2 @@
+/target
+/Cargo.lock

+ 9 - 0
Cargo.toml

@@ -0,0 +1,9 @@
+[package]
+name = "rust-hdl-bsp-upduino-3"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+rust-hdl = { version = "0.46.0", features = ["fpga"] }

+ 2 - 0
src/lib.rs

@@ -0,0 +1,2 @@
+pub mod pins;
+pub mod synth;

+ 44 - 0
src/pins.rs

@@ -0,0 +1,44 @@
+use rust_hdl::core::prelude::*;
+
+pub const CLOCK_SPEED_12MHZ: u64 = 12_000_000;
+
+#[derive(LogicBlock)]
+pub struct InternalClock {
+    pub clk: Signal<Out, Clock>,
+}
+
+impl InternalClock {
+    pub fn new() -> Self {
+        let clk = Signal::<Out, _>::default();
+        Self { clk }
+    }
+}
+
+impl Logic for InternalClock {
+    fn update(&mut self) {}
+
+    fn connect(&mut self) {
+        self.clk.connect();
+    }
+
+    fn hdl(&self) -> Verilog {
+        Verilog::Wrapper(Wrapper {
+            code: "SB_HFOSC hfosc(.CLKHFPU(1'b1), .CLKHFEN(1'b1), .CLKHF(clk));".into(),
+            cores: r#"
+                module SB_HFOSC(CLKHFPU, CLKHFEN, CLKHF);
+                    input CLKHFPU;
+                    input CLKHFEN;
+                    output CLKHF;
+                endmodule"#
+                .into(),
+        })
+    }
+}
+
+pub fn leds() -> Signal<Out, Bits<3>> {
+    let mut x = Signal::<Out, _>::default();
+    for (ndx, uname) in ["39", "40", "41"].iter().enumerate() {
+        x.add_location(ndx, uname);
+    }
+    x
+}

+ 62 - 0
src/synth.rs

@@ -0,0 +1,62 @@
+use rust_hdl::core::check_error::check_all;
+use rust_hdl::core::prelude::*;
+use rust_hdl::fpga::toolchains::icestorm::generate_pcf;
+use std::fs::{create_dir_all, remove_dir_all, File};
+use std::io::Write;
+use std::path::PathBuf;
+use std::process::{Command, Output};
+use std::str::FromStr;
+
+fn save_stdout(output: Output, dir: &PathBuf, basename: &str) -> Result<(), std::io::Error> {
+    let stdout = String::from_utf8(output.stdout).unwrap();
+    let stderr = String::from_utf8(output.stderr).unwrap();
+    let mut out_file = File::create(dir.clone().join(format!("{}.out", basename)))?;
+    write!(out_file, "{}", stdout)?;
+    let mut err_file = File::create(dir.clone().join(format!("{}.err", basename)))?;
+    write!(err_file, "{}", stderr)?;
+    Ok(())
+}
+
+pub fn generate_bitstream<U: Block>(mut uut: U, prefix: &str) {
+    uut.connect_all();
+    check_all(&uut).unwrap(); // TODO - Change from panic to return an error
+    let verilog_text = generate_verilog(&uut);
+    let pcf_text = generate_pcf(&uut);
+    let dir = PathBuf::from_str(prefix).unwrap();
+    let _ = remove_dir_all(&dir);
+    let _ = create_dir_all(&dir);
+    let mut v_file = File::create(dir.join("top.v")).unwrap();
+    write!(v_file, "{}", verilog_text).unwrap();
+    let pcf_filename = "top.pcf".to_string();
+    let mut pcf_file = File::create(dir.join(pcf_filename)).unwrap();
+    write!(pcf_file, "{}", pcf_text).unwrap();
+    let output = Command::new("yosys")
+        .current_dir(dir.clone())
+        .arg(r#"-p synth_ice40 -top top -json top.json"#)
+        .arg("top.v")
+        .output()
+        .unwrap();
+    save_stdout(output, &dir, "yosys_synth").unwrap();
+    let output = Command::new("nextpnr-ice40")
+        .current_dir(dir.clone())
+        .args([
+            "--up5k",
+            "--package",
+            "sg48",
+            "--pcf",
+            "top.pcf",
+            "--asc",
+            "top.asc",
+            "--json",
+            "top.json",
+        ])
+        .output()
+        .unwrap();
+    save_stdout(output, &dir, "nextpnr").unwrap();
+    let output = Command::new("icepack")
+        .current_dir(dir.clone())
+        .args(["top.asc", "top.bin"])
+        .output()
+        .unwrap();
+    save_stdout(output, &dir, "icepack").unwrap();
+}