### Rust-HDL Blinky Logic and Simulation Setup Source: https://github.com/samitbasu/rust-hdl/blob/main/rust-hdl-org/docs/simulation.md This Rust code defines a 'Blinky' hardware component using Rust-HDL's declarative macros and traits. It includes logic for a clock, a pulser, and an LED output. The 'main' function sets up a simple simulation environment, runs the 'Blinky' logic, and generates VCD and SVG output files for waveform visualization. ```rust use std::time::Duration; use rust_hdl::prelude::*; const CLOCK_SPEED_HZ : u64 = 10_000; #[derive(LogicBlock)] // <- This turns the struct into something you can simulate/synthesize struct Blinky { pub clock: Signal, pulser: Pulser, pub led: Signal, } impl Default for Blinky { fn default() -> Self { Self { clock: Default::default(), pulser: Pulser::new(CLOCK_SPEED_HZ, 1.0, Duration::from_millis(250)), led: Default::default(), } } } impl Logic for Blinky { #[hdl_gen] // <- this turns the update function into an HDL Kernel that can be turned into Verilog fn update(&mut self) { self.pulser.clock.next = self.clock.val(); self.pulser.enable.next = true.into(); self.led.next = self.pulser.pulse.val(); } } fn main() { let mut sim = simple_sim!(Blinky, clock, CLOCK_SPEED_HZ, ep, { let mut x = ep.init()?; wait_clock_cycles!(ep, clock, x, 4*CLOCK_SPEED_HZ); ep.done(x) }); let uut = Blinky::default(); sim.run_to_file(Box::new(uut), 5 * sim_time::ONE_SEC, "blinky.vcd").unwrap(); vcd_to_svg("blinky.vcd","blinky_all.svg",&["uut.clock", "uut.led"], 0, 4 * sim_time::ONE_SEC).unwrap(); vcd_to_svg("blinky.vcd","blinky_pulse.svg",&["uut.clock", "uut.led"], 900 * sim_time::ONE_MILLISECOND, 1500 * sim_time::ONE_MILLISECOND).unwrap(); } ``` -------------------------------- ### Start Local Development Server with Yarn Source: https://github.com/samitbasu/rust-hdl/blob/main/rust-hdl-org/README.md Starts a local development server for the website. Changes are reflected live without requiring a server restart. Opens the site in a browser. ```shell yarn start ``` -------------------------------- ### Install Dependencies with Yarn Source: https://github.com/samitbasu/rust-hdl/blob/main/rust-hdl-org/README.md Installs project dependencies using the Yarn package manager. This is typically the first step before running other commands. ```shell yarn ``` -------------------------------- ### Install mdbook for RustHDL Builds Source: https://github.com/samitbasu/rust-hdl/blob/main/guide/README.md Installs the mdbook tool, which is required for building the RustHDL project documentation. This command assumes you have Rust and Cargo installed and configured. ```sh cargo install mdbook ``` -------------------------------- ### RustHDL Blinky Example: Simulation and SVG Generation Source: https://github.com/samitbasu/rust-hdl/blob/main/README.md This Rust code defines a simple Blinky logic block with a clock input and LED output, driven by a Pulser widget. It includes simulation setup using `simple_sim!`, circuit instantiation, running the simulation to a VCD file, and converting the VCD trace to SVG images for visualization. The example demonstrates the core RustHDL workflow for creating and verifying hardware designs. ```rust use std::time::Duration; use rust_hdl::prelude::*; use rust_hdl::docs::vcd2svg::vcd_to_svg; const CLOCK_SPEED_HZ : u64 = 10_000; #[derive(LogicBlock)] // <- This turns the struct into something you can simulate/synthesize struct Blinky { pub clock: Signal, // <- input signal, type is clock pulser: Pulser, // <- sub-circuit, a widget that generates pulses pub led: Signal, // <- output signal, type is single bit } impl Default for Blinky { fn default() -> Self { Self { clock: Default::default(), pulser: Pulser::new(CLOCK_SPEED_HZ, 1.0, Duration::from_millis(250)), led: Default::default(), } } } impl Logic for Blinky { #[hdl_gen] // <- this turns the update function into an HDL Kernel that can be turned into Verilog fn update(&mut self) { // v-- write to the .next member v-- read from .val() method self.pulser.clock.next = self.clock.val(); self.pulser.enable.next = true.into(); self.led.next = self.pulser.pulse.val(); } } fn main() { // v--- build a simple simulation (1 testbench, single clock) let mut sim = simple_sim!(Blinky, clock, CLOCK_SPEED_HZ, ep, { let mut x = ep.init()?; wait_clock_cycles!(ep, clock, x, 4*CLOCK_SPEED_HZ); ep.done(x) }); // v--- construct the circuit let mut uut = Blinky::default(); uut.connect_all(); sim.run_to_file(Box::new(uut), 5 * SIMULATION_TIME_ONE_SECOND, "blinky.vcd").unwrap(); vcd_to_svg("/tmp/blinky.vcd","images/blinky_all.svg",&["uut.clock", "uut.led"], 0, 4_000_000_000_000).unwrap(); vcd_to_svg("/tmp/blinky.vcd","images/blinky_pulse.svg",&["uut.clock", "uut.led"], 900_000_000_000, 1_500_000_000_000).unwrap(); } ``` -------------------------------- ### Build RustHDL Project Documentation Source: https://github.com/samitbasu/rust-hdl/blob/main/guide/README.md Builds the project's documentation using mdbook. Ensure that the Cargo installation directory is in your system's PATH before running this command from the project's root directory. ```sh mdbook build ``` -------------------------------- ### Add Rust-HDL Dependency to Cargo Project Source: https://github.com/samitbasu/rust-hdl/blob/main/rust-hdl-org/docs/simulation.md This snippet shows how to add the 'rust-hdl' crate as a dependency to a new or existing Rust project using Cargo. It assumes you have Cargo installed and are in your project directory. ```shell cargo new testme cd testme cargo add rust-hdl ``` -------------------------------- ### RustHDL Blinky Example: Circuit and Simulation Source: https://github.com/samitbasu/rust-hdl/blob/main/rust-hdl/README.md Defines a simple Blinky circuit using RustHDL and sets up a simulation environment. This example demonstrates defining a LogicBlock, implementing the Logic trait, and running a simulation to a VCD file. It requires the rust_hdl crate. ```rust use std::time::Duration; use rust_hdl::docs::vcd2svg::vcd_to_svg; use rust_hdl::prelude::*; const CLOCK_SPEED_HZ : u64 = 10_000; #[derive(LogicBlock)] // <- This turns the struct into something you can simulate/synthesize struct Blinky { pub clock: Signal, // <- input signal, type is clock pulser: Pulser, // <- sub-circuit, a widget that generates pulses pub led: Signal, // <- output signal, type is single bit } impl Default for Blinky { fn default() -> Self { Self { clock: Default::default(), pulser: Pulser::new(CLOCK_SPEED_HZ, 1.0, Duration::from_millis(250)), led: Default::default(), } } } impl Logic for Blinky { #[hdl_gen] // <- this turns the update function into an HDL Kernel that can be turned into Verilog fn update(&mut self) { // v-- write to the .next member v-- read from .val() method self.pulser.clock.next = self.clock.val(); self.pulser.enable.next = true.into(); self.led.next = self.pulser.pulse.val(); } } fn main() { // v--- build a simple simulation (1 testbench, single clock) let mut sim = simple_sim!(Blinky, clock, CLOCK_SPEED_HZ, ep, { let mut x = ep.init()?; wait_clock_cycles!(ep, clock, x, 4*CLOCK_SPEED_HZ); ep.done(x) }); // v--- construct the circuit let mut uut = Blinky::default(); uut.connect_all(); sim.run_to_file(Box::new(uut), 5 * SIMULATION_TIME_ONE_SECOND, "blinky.vcd").unwrap(); vcd_to_svg("/tmp/blinky.vcd","images/blinky_all.svg",&["uut.clock", "uut.led"], 0, 4_000_000_000_000).unwrap(); vcd_to_svg("/tmp/blinky.vcd","images/blinky_pulse.svg",&["uut.clock", "uut.led"], 900_000_000_000, 1_500_000_000_000).unwrap(); } ``` -------------------------------- ### Rust HDL Signal Assignment Examples Source: https://github.com/samitbasu/rust-hdl/blob/main/rust-hdl-org/docs/guide/rusthdl/synthesizable.md Shows valid signal assignments within a RustHDL kernel. It includes examples of binary operations with literals and other signals, demonstrating how to update output signals using `.next`. ```rust # use rust_hdl::prelude::*; struct Foo { pub sig1: Signal>, pub sig2: Signal>, pub sig3: Signal>, } impl Logic for Foo { #[hdl_gen] fn update(&mut self) { self.sig3.next = self.sig1.val() + 4; // Example of binop with a literal self.sig3.next = self.sig1.val() ^ self.sig2.val(); // Example of a binop with two bitvecs } } ``` -------------------------------- ### Rust HDL LED Blinker Implementation and Simulation Source: https://github.com/samitbasu/rust-hdl/blob/main/rust-hdl/doc/md/quickstart.md This Rust code defines a logic block for an LED blinker using Rust HDL. It includes the hardware logic for blinking an LED at a specified interval and a simulation setup to generate a VCD trace file. The simulation can be run to a file, and the trace can be converted to SVG for visualization. ```rust use std::time::Duration; use rust_hdl::core::prelude::*; use rust_hdl::docs::vcd2svg::vcd_to_svg; use rust_hdl::widgets::prelude::*; const CLOCK_SPEED_HZ : u64 = 10_000; #[derive(LogicBlock)] struct Blinky { pub clock: Signal, pulser: Pulser, pub led: Signal, } impl Default for Blinky { fn default() -> Self { Self { clock: Default::default(), pulser: Pulser::new(CLOCK_SPEED_HZ, 1.0, Duration::from_millis(250)), led: Default::default(), } } } impl Logic for Blinky { #[hdl_gen] fn update(&mut self) { self.pulser.clock.next = self.clock.val(); self.pulser.enable.next = true.into(); self.led.next = self.pulser.pulse.val(); } } fn main() { let mut sim = simple_sim!(Blinky, clock, CLOCK_SPEED_HZ, ep, { let mut x = ep.init()?; wait_clock_cycles!(ep, clock, x, 4*CLOCK_SPEED_HZ); ep.done(x) }); let mut uut = Blinky::default(); uut.connect_all(); sim.run_to_file(Box::new(uut), 5 * SIMULATION_TIME_ONE_SECOND, "blinky.vcd").unwrap(); vcd_to_svg("/tmp/blinky.vcd","images/blinky_all.svg",&["uut.clock", "uut.led"], 0, 4_000_000_000_000).unwrap(); vcd_to_svg("/tmp/blinky.vcd","images/blinky_pulse.svg",&["uut.clock", "uut.led"], 900_000_000_000, 1_500_000_000_000).unwrap(); } ``` -------------------------------- ### Run Rust-HDL Simulation with Cargo Source: https://github.com/samitbasu/rust-hdl/blob/main/rust-hdl-org/docs/simulation.md This snippet demonstrates how to compile and run the Rust-HDL simulation project using Cargo. The '--release' flag is used for optimized performance during execution. Successful execution will produce compiled binaries and the simulation output files. ```shell cargo run --release ``` -------------------------------- ### Verilog Output for Blinky Example Source: https://github.com/samitbasu/rust-hdl/blob/main/rust-hdl-org/docs/intro.md This is the Verilog code generated for the 'blinky' example using RustHDL. It defines the top-level module and its sub-modules, including logic for clocking, enabling, and output signals. ```verilog module top(clock,leds); // Module arguments input wire clock; output reg [7:0] leds; // Stub signals reg pulser$clock; reg pulser$enable; wire pulser$pulse; // Sub module instances top$pulser pulser( .clock(pulser$clock), .enable(pulser$enable), .pulse(pulser$pulse) ); // Update code always @(*) begin pulser$enable = 1'b1; pulser$clock = clock; leds = 32'h0; if (pulser$pulse) begin leds = 32'haa; end end endmodule // top module top$pulser(clock,enable,pulse); // Module arguments input wire clock; input wire enable; output reg pulse; // Stub signals reg strobe$enable; wire strobe$strobe; reg strobe$clock; reg shot$trigger; wire shot$active; reg shot$clock; wire shot$fired; // Sub module instances top$pulser$strobe strobe( .enable(strobe$enable), .strobe(strobe$strobe), .clock(strobe$clock) ); top$pulser$shot shot( .trigger(shot$trigger), .active(shot$active), .clock(shot$clock), .fired(shot$fired) ); // Update code always @(*) begin strobe$clock = clock; shot$clock = clock; strobe$enable = enable; shot$trigger = strobe$strobe; pulse = shot$active; end endmodule // top$pulser module top$pulser$shot(trigger,active,clock,fired); // Module arguments input wire trigger; output reg active; input wire clock; output reg fired; // Constant declarations localparam duration = 32'h17d7840; // Stub signals reg [31:0] counter$d; wire [31:0] counter$q; reg counter$clock; reg state$d; wire state$q; reg state$clock; // Sub module instances top$pulser$shot$counter counter( .d(counter$d), .q(counter$q), .clock(counter$clock) ); top$pulser$shot$state state( .d(state$d), .q(state$q), .clock(state$clock) ); // Update code always @(*) begin counter$clock = clock; state$clock = clock; counter$d = counter$q; state$d = state$q; if (state$q) begin counter$d = counter$q + 32'h1; end fired = 1'b0; if (state$q && (counter$q == duration)) begin state$d = 1'b0; fired = 1'b1; end active = state$q; if (trigger) begin state$d = 1'b1; counter$d = 32'h0; end end endmodule // top$pulser$shot module top$pulser$shot$counter(d,q,clock); // Module arguments input wire [31:0] d; output reg [31:0] q; input wire clock; // Update code (custom) initial begin q = 32'h0; end always @(posedge clock) begin q <= d; end endmodule // top$pulser$shot$counter module top$pulser$shot$state(d,q,clock); // Module arguments input wire d; output reg q; input wire clock; // Update code (custom) initial begin q = 1'h0; end always @(posedge clock) begin q <= d; end endmodule // top$pulser$shot$state module top$pulser$strobe(enable,strobe,clock); // Module arguments input wire enable; output reg strobe; input wire clock; // Constant declarations localparam threshold = 32'h5f5e100; // Stub signals reg [31:0] counter$d; wire [31:0] counter$q; reg counter$clock; // Sub module instances top$pulser$strobe$counter counter( .d(counter$d), .q(counter$q), .clock(counter$clock) ); // Update code always @(*) begin counter$clock = clock; counter$d = counter$q; if (enable) begin counter$d = counter$q + 32'h1; end strobe = enable & (counter$q == threshold); if (strobe) begin counter$d = 32'h1; end end ``` -------------------------------- ### Draw Line on HTML Canvas using JavaScript Source: https://github.com/samitbasu/rust-hdl/blob/main/rust-hdl/src/fig.md This snippet illustrates how to draw a line on an HTML canvas. It first gets a reference to the canvas element by its ID and then obtains the 2D rendering context. It proceeds to define a path, move to a starting point, draw a line to an endpoint, and finally makes the line visible by calling stroke(). Browser compatibility checks are recommended. ```javascript var canvas = document.getElementById('DemoCanvas'); //Always check for properties and methods, to make sure your code doesn't break in other browsers. if (canvas.getContext) { var context = canvas.getContext('2d'); // Reset the current path context.beginPath(); // Staring point (10,45) context.moveTo(10,45); // End point (180,47) context.lineTo(180,47); // Make the line visible context.stroke(); } ``` -------------------------------- ### Pulser Circuit Constructor in Rust Source: https://github.com/samitbasu/rust-hdl/blob/main/guide/src/chapter_1.md The constructor for the Pulser circuit. It takes the clock rate in Hz, the desired pulse rate in Hz, and the duration of each pulse as parameters to initialize the Pulser struct. ```rust impl Pulser { pub fn new(clock_rate_hz: u64, pulse_rate_hz: f64, pulse_duration: Duration) -> Self # { # Self #} } ``` -------------------------------- ### Rust HDL Conditional Logic Examples Source: https://github.com/samitbasu/rust-hdl/blob/main/rust-hdl-org/docs/guide/rusthdl/synthesizable.md Demonstrates the use of conditional statements (`if`, `else if`, `else`) within a RustHDL kernel. It highlights how to prevent latches through unconditional assignments and the proper use of `else` clauses. ```rust # use rust_hdl::prelude::*; struct Foo { pub sig1: Signal, pub sig2: Signal>, pub sig3: Signal>, pub sig4: Signal>, } impl Logic for Foo { #[hdl_gen] fn update(&mut self) { self.sig2.next = 0.into(); // Latch prevention! // Straight `if`s are supported, but beware of latches! // This `if` statement would generate a latch if not for // the unconditional assign to `sig2` if self.sig1.val() { self.sig2.next = 1.into(); } // You can use `else` clauses also if self.sig1.val() { self.sig2.next = 1.into(); } else { self.sig2.next = 2.into(); } // Nesting and chaining are also fine if self.sig3.val() == 0 { self.sig4.next = 3.into(); } else if self.sig3.val() == 1 { self.sig4.next = 2.into(); } else { self.sig4.next = 0.into(); // <- Fall through else prevents latch } } } ``` -------------------------------- ### Simulate Circuit and Generate VCD Waveform Output (Rust) Source: https://context7.com/samitbasu/rust-hdl/llms.txt This Rust code demonstrates simulating a simple circuit (likely a Blinky example) and generating a VCD (Value Change Dump) file for waveform viewing. It also shows how to convert the VCD file to an SVG image for easier analysis in a browser. ```rust use rust_hdl::prelude::*; #[test] fn test_with_vcd_output() { const CLOCK_HZ: u64 = 10_000; let mut sim = simple_sim!(Blinky, clock, CLOCK_HZ, ep, { let mut x = ep.init()?; // Run for 4 seconds worth of simulation time wait_clock_cycles!(ep, clock, x, 4 * CLOCK_HZ); ep.done(x) }); let mut uut = Blinky::default(); uut.connect_all(); // Run and save to VCD file sim.run_to_file( Box::new(uut), 5_000_000_000_000, // 5 seconds in picoseconds "output.vcd" ).unwrap(); // Optional: Convert VCD to SVG for viewing in browser vcd_to_svg( "output.vcd", "output.svg", &["uut.clock", "uut.led"], 0, 4_000_000_000_000 ).unwrap(); } ``` -------------------------------- ### Synthesize AlchitryCuPulser Design using Test Function (Rust) Source: https://github.com/samitbasu/rust-hdl/blob/main/guide/src/chapter_1.md A test function to synthesize the AlchitryCuPulser circuit into a bitstream. It instantiates the circuit using its default implementation and calls `generate_bitstream` to output the synthesized Verilog and target file for programming the FPGA. ```Rust #[test] fn synthesize_alchitry_cu_pulser() { let uut = AlchitryCuPulser::default(); generate_bitstream(uut, target_path!("alchitry_cu/pulser")); } ``` -------------------------------- ### Define AlchitryCuPulser Circuit Structure (Rust) Source: https://github.com/samitbasu/rust-hdl/blob/main/guide/src/chapter_1.md Defines the structure for the Alchitry CU pulser circuit, including its components like a Pulser instance, clock signal, and LED output. This sets up the basic building blocks for the FPGA logic. ```Rust #[derive(LogicBlock)] pub struct AlchitryCuPulser { pulser: Pulser, clock: Signal, leds: Signal>, } ``` -------------------------------- ### Construct AlchitryCuPulser Circuit using Default (Rust) Source: https://github.com/samitbasu/rust-hdl/blob/main/guide/src/chapter_1.md Provides a default constructor for the AlchitryCuPulser circuit using Rust's `Default` trait. It instantiates the `Pulser` component with specific parameters and connects the `clock` and `leds` signals using the Alchitry CU board support package (BSP). ```Rust impl Default for AlchitryCuPulser { fn default() -> Self { let pulser = Pulser::new(rust_hdl_bsp_alchitry_cu::pins::CLOCK_SPEED_100MHZ, 1.0, Duration::from_millis(250)); Self { pulser, clock: rust_hdl_bsp_alchitry_cu::pins::clock(), leds: rust_hdl_bsp_alchitry_cu::pins::leds(), } } } ``` -------------------------------- ### Basic Circuit with LogicBlock Derive in Rust Source: https://context7.com/samitbasu/rust-hdl/llms.txt Defines a simple 'Blinky' circuit that uses the `LogicBlock` derive macro for synthesizable Rust code. It includes a `Pulser` to toggle an LED signal based on a clock input. The example demonstrates circuit instantiation, static analysis, and Verilog generation. ```rust use rust_hdl::prelude::*; use std::time::Dualog_speed_hz: u64 = 10_000; // Derive LogicBlock to make this struct synthesizable #[derive(LogicBlock)] struct Blinky { pub clock: Signal, pulser: Pulser, pub led: Signal, } impl Default for Blinky { fn default() -> Self { Self { clock: Default::default(), pulser: Pulser::new(CLOCK_SPEED_HZ, 1.0, Duration::from_millis(250)), led: Default::default(), } } } // Implement Logic trait with HDL kernel impl Logic for Blinky { #[hdl_gen] // Compiles this method to Verilog fn update(&mut self) { // Connect clock to pulser self.pulser.clock.next = self.clock.val(); self.pulser.enable.next = true.into(); // Drive LED output from pulser self.led.next = self.pulser.pulse.val(); } } fn main() { // Create and validate circuit let mut uut = Blinky::default(); uut.connect_all(); // Static analysis checks check_all(&uut).unwrap(); // Generate Verilog let verilog = generate_verilog(&uut); println!("{}", verilog); // Optional: validate with yosys if installed yosys_validate("blinky", &verilog).unwrap(); } ``` -------------------------------- ### Signal Class Definition in Rust Source: https://github.com/samitbasu/rust-hdl/blob/main/guide/src/chapter_1.md Defines the fundamental Signal class in RustHDL, used for representing inputs and outputs within logic blocks. It includes fields for next value, current value, previous value, change status, and internal identifiers. ```rust #[derive(Clone, Debug)] pub struct Signal { pub next: T, val: T, prev: T, pub changed: bool, claimed: bool, id: usize, constraints: Vec, dir: std::marker::PhantomData, } ``` -------------------------------- ### Create New Rust Binary Project Source: https://github.com/samitbasu/rust-hdl/blob/main/rust-hdl-org/docs/intro.md Initializes a new Rust project of the binary type using Cargo. This command creates the basic file structure for a standalone Rust application. ```bash samitbasu@samitbasu-virtual-machine:~/Devel$ cargo new blinky Created binary (application) `blinky` package ``` -------------------------------- ### Build Static Website Content with Yarn Source: https://github.com/samitbasu/rust-hdl/blob/main/rust-hdl-org/README.md Generates the static content for the website, typically placing it in a 'build' directory. This content can then be hosted on any static hosting service. ```shell yarn build ``` -------------------------------- ### Add Alchitry Cu Board Support Package Source: https://github.com/samitbasu/rust-hdl/blob/main/rust-hdl-org/docs/intro.md Adds the 'rust-hdl-bsp-alchitry-cu' crate, which provides board-specific definitions and peripherals for the Alchitry Cu FPGA board, as a project dependency. ```bash samitbasu@samitbasu-virtual-machine:~/Devel/blinky$ cargo add rust-hdl-bsp-alchitry-cu Updating crates.io index Adding rust-hdl-bsp-alchitry-cu v0.45.0 to dependencies. ``` -------------------------------- ### Rust LogicBlock Derivation Example Source: https://github.com/samitbasu/rust-hdl/blob/main/rust-hdl-org/docs/guide/rusthdl/traits.md An example of implementing the `Logic` trait for a `Blinky` struct using the `#[derive(LogicBlock)]` macro. This macro automatically generates most of the trait implementations, allowing developers to focus on the core `update` logic written in Rust. ```rust #[derive(LogicBlock)] struct Blinky { pub clock: Signal, pulser: Pulser, pub led: Signal, } impl Logic for Blinky { #[hdl_gen] fn update(&mut self) { self.pulser.clock.next = self.clock.val(); self.pulser.enable.next = true.into(); self.led.next = self.pulser.pulse.val(); } } ``` -------------------------------- ### Deploy Website with Yarn (SSH) Source: https://github.com/samitbasu/rust-hdl/blob/main/rust-hdl-org/README.md Deploys the website using SSH. This command builds the static content and pushes it to the 'gh-pages' branch, suitable for GitHub Pages. ```shell USE_SSH=true yarn deploy ``` -------------------------------- ### Build and Run Rust HDL Project Source: https://github.com/samitbasu/rust-hdl/blob/main/rust-hdl-org/docs/intro.md Compiles and runs the Rust HDL project using Cargo. This process generates the bitstream file required for programming the FPGA. ```bash samitbasu@samitbasu-virtual-machine:~/Devel/blinky$ cargo run Finished dev [unoptimized + debuginfo] target(s) in 15.74s Running `target/debug/blinky` samitbasu@samitbasu-virtual-machine:~/Devel/blinky$ ``` -------------------------------- ### Rust HDL: Synchronous Logic Example Source: https://github.com/samitbasu/rust-hdl/blob/main/docs/ideas.md Illustrates a generic synchronous logic function in Rust, representing a clocked process. It outlines the structure for handling clock edges, inputs, state updates, and outputs. ```rust fn synchronous_thing(clock, state, update, inputs) -> outputs { loop { on_clock_edge { inputs = get_inputs_from_outside(); let (state, outputs) = state.update(inputs); push_outputs_to_outside(outpus); } } } ``` -------------------------------- ### Flash Firmware to Alchitry Cu Board Source: https://github.com/samitbasu/rust-hdl/blob/main/rust-hdl-org/docs/intro.md Uses the 'iceprog' tool to program the generated bitstream file onto the Alchitry Cu FPGA. This command verifies the programming process after writing the firmware. ```bash samitbasu@samitbasu-virtual-machine:~/Devel/blinky$ iceprog firmware/blinky/top.bin init.. cdone: high reset.. cdone: low flash ID: 0xEF 0x40 0x16 0x00 file size: 135100 erase 64kB sector at 0x000000.. erase 64kB sector at 0x010000.. erase 64kB sector at 0x020000.. programming.. done. reading.. VERIFY OK cdone: high Bye. ``` -------------------------------- ### Simulate an 8-bit Adder Circuit with Test Cases in Rust Source: https://github.com/samitbasu/rust-hdl/blob/main/rust-hdl-org/docs/guide/rusthdl/simulation.md Sets up and runs a simulation for the `MyAdder` circuit using the `simple_sim!` macro. It generates random test cases, defines the clock speed, and iterates through the test cases to verify the adder's output against expected sums. The simulation uses `Wrapping` to emulate hardware arithmetic. ```rust use rand::{thread_rng, Rng}; use std::num::Wrapping; // Build a set of test cases for the circuit. Use Wrapping to emulate hardware. let test_cases = (0..512) .map(|_| { let a_val = thread_rng().gen::(); let b_val = thread_rng().gen::(); let c_val = (Wrapping(a_val) + Wrapping(b_val)).0; ( a_val.to_bits::<8>(), b_val.to_bits::<8>(), c_val.to_bits::<8>(), ) }) .collect::>(); // The clock speed doesn't really matter here. So 100MHz is fine. let mut sim = simple_sim!(MyAdder, clock, 100_000_000, ep, { let mut x = ep.init()?; for test_case in &test_cases { // +-- This should look familiar. Same rules as for HDL kernels // v Write to .next, read from .val() x.sig_a.next = test_case.0; x.sig_b.next = test_case.1; // Helpful macro to delay the simulate by 1 clock cycle (to allow the output to update) wait_clock_cycle!(ep, clock, x); // You can use any standard Rust stuff inside the testbench. println!( ``` -------------------------------- ### Rust HDL Kernel Structure Example Source: https://github.com/samitbasu/rust-hdl/blob/main/rust-hdl-org/docs/guide/rusthdl/synthesizable.md Demonstrates the basic structure of an HDL kernel in RustHDL. The `#[hdl_gen]` attribute is applied to an `update` function that takes `&mut self`. The body of this function contains the synthesizable Rust code. ```rust struct Foo {} impl Logic for Foo { #[hdl_gen] fn update(&mut self) { // Put your synthesizable subset of Rust here... } } ``` -------------------------------- ### Implement Logic for AlchitryCuPulser Circuit (Rust) Source: https://github.com/samitbasu/rust-hdl/blob/main/guide/src/chapter_1.md Implements the behavioral logic for the AlchitryCuPulser circuit using the `Logic` trait and the `#[hdl_gen]` attribute. This function describes how the `pulser` component controls the `leds` based on the input `clock`. ```Rust impl Logic for AlchitryCuPulser { #[hdl_gen] fn update(&mut self) { self.pulser.enable.next = true; self.pulser.clock.next = self.clock.val(); self.leds.next = 0x00_u32.into(); if self.pulser.pulse.val() { self.leds.next = 0xAA_u32.into(); } } } ``` -------------------------------- ### Define Pulser Circuit Structure in Rust Source: https://github.com/samitbasu/rust-hdl/blob/main/guide/src/chapter_1.md Defines the structure of the Pulser circuit, which includes clock and enable inputs, a pulse output, and internal Strobe and Shot components. It utilizes the LogicBlock derive macro for circuit definition. ```rust #[derive(LogicBlock)] pub struct Pulser { pub clock: Signal, pub enable: Signal, pub pulse: Signal, strobe: Strobe<32>, shot: Shot<32>, } ``` -------------------------------- ### Rust HDL Kernel Invalid Local Item Example Source: https://github.com/samitbasu/rust-hdl/blob/main/rust-hdl-org/docs/guide/rusthdl/synthesizable.md Illustrates an invalid HDL kernel structure where local definitions are attempted within the `update` function. This code is valid Rust but not allowed in HDL kernels as it would not translate to hardware logic. ```rust struct Foo {} impl Logic for Foo { #[hdl_gen] fn update (&mut self) { // Fails because local items are not allowed in HDL kernels. let x = 32; } } ``` -------------------------------- ### Deploy Website with Yarn (Non-SSH) Source: https://github.com/samitbasu/rust-hdl/blob/main/rust-hdl-org/README.md Deploys the website without using SSH, requiring your GitHub username. This command builds the static content and pushes it to the 'gh-pages' branch. ```shell GIT_USER= yarn deploy ``` -------------------------------- ### Rust Simulation Testbench Function Structure Source: https://github.com/samitbasu/rust-hdl/blob/main/rust-hdl/doc/notes.md Illustrates a typical structure for a Rust testbench function using a 'Sim' struct. It shows how to initiate a simulation, schedule actions at specific times, and conclude the simulation. ```rust fn my_rust_testbench(sim: &Sim) { let x = sim.start(); // Do stuff to x let x = sim.at_time(t0, x); // Do stuff to x let x = sim.at_time(t1, x); // Do stuff to x sim.finish(x) } ``` -------------------------------- ### Implement Adder Logic: Drive Output from Inputs Source: https://github.com/samitbasu/rust-hdl/blob/main/rust-hdl/doc/md/signals_intro.md Illustrates the implementation of the update logic for the My8BitAdder circuit. It shows the standard pattern of reading input signals using '.val()' and writing to the output signal's '.next' field to perform the addition. ```rust use rust_hdl::core::prelude::*; pub struct My8BitAdder { pub input_1: Signal>, pub input_2: Signal>, pub output: Signal>, } impl Logic for My8BitAdder { fn update(&mut self) { self.output.next = self.input_1.val() + self.input_2.val(); } } ``` -------------------------------- ### Rust HDL: Pulser for Timed Event Generation Source: https://context7.com/samitbasu/rust-hdl/llms.txt Demonstrates the Pulser widget in Rust HDL for generating periodic pulses with configurable duration and rate. Examples include a single pulser for blink control and multiple pulsers for different timed events. ```rust use rust_hdl::prelude::*; use std::time::Duration; #[derive(LogicBlock)] struct BlinkController { pub clock: Signal, pub enable: Signal, pub led_output: Signal, // Pulser generates 250ms pulses at 1Hz rate pulser: Pulser, } impl Default for BlinkController { fn default() -> Self { const CLOCK_FREQ: u64 = 100_000_000; // 100 MHz Self { clock: Default::default(), enable: Default::default(), led_output: Default::default(), pulser: Pulser::new( CLOCK_FREQ, // Clock frequency in Hz 1.0, // Pulse rate: 1 Hz (once per second) Duration::from_millis(250) // Pulse duration: 250ms ), } } } impl Logic for BlinkController { #[hdl_gen] fn update(&mut self) { // Connect clock to pulser self.pulser.clock.next = self.clock.val(); // Enable/disable pulser self.pulser.enable.next = self.enable.val(); // Output pulse signal self.led_output.next = self.pulser.pulse.val(); } } // Example: Multiple pulsers with different rates #[derive(LogicBlock)] struct MultiPulser { pub clock: Signal, pub fast_pulse: Signal, pub slow_pulse: Signal, fast: Pulser, slow: Pulser, } impl Default for MultiPulser { fn default() -> Self { const MHZ: u64 = 1_000_000; Self { clock: Default::default(), fast_pulse: Default::default(), slow_pulse: Default::default(), // 10 Hz pulser with 10ms duration fast: Pulser::new(MHZ, 10.0, Duration::from_millis(10)), // 1 Hz pulser with 100ms duration slow: Pulser::new(MHZ, 1.0, Duration::from_millis(100)), } } } impl Logic for MultiPulser { #[hdl_gen] fn update(&mut self) { clock!(self, clock, fast, slow); // Connect clock to both pulsers self.fast.enable.next = true.into(); self.slow.enable.next = true.into(); self.fast_pulse.next = self.fast.pulse.val(); self.slow_pulse.next = self.slow.pulse.val(); } } ``` -------------------------------- ### Add rust-hdl Dependency with fpga Feature Source: https://github.com/samitbasu/rust-hdl/blob/main/rust-hdl-org/docs/intro.md Adds the 'rust-hdl' meta-package as a project dependency using Cargo. The 'fpga' feature must be enabled for hardware description language capabilities. ```bash samitbasu@samitbasu-virtual-machine:~/Devel/blinky$ cargo add rust-hdl --features fpga Updating crates.io index Adding rust-hdl v0.45.0 to dependencies. Features: + fpga samitbasu@samitbasu-virtual-machine:~/Devel/blinky$ ```