
Caravel Nucleo v2-M.2
efabless/caravel_board
This repo provides firmware examples, flash programming and diagnostic tools for testing Open MPW and chipIgnite projects using Caravel.

An open-source hardware platform that accelerates the design and deployment of customizable graphical interfaces for embedded systems.
Lacerta v2 1 is an open-source printed circuit board by MifralTech, from the MifralTech/Lacerta_CF repository on GitHub, published under the Apache-2.0 licence. It is a 2-layer board of 76.2 × 73.8 mm with 80 parts on 109 nets, routed with 1,797 tracks and 158 vias.
It is built around the SN74LVC1G125DCKR-GK, W25Q32FVSSIG and DS1086LU+T, with the FT232H, IS61C5128AL-10KLI and TMUX4053BQBR among its other parts. Its parts include 25 capacitors, 20 resistors, 13 connectors, 11 ICs and 3 diodes. It belongs with the interfaces and adapters boards of this library.

Lacerta is an open-source hardware platform that enables the rapid creation of graphical interfaces for embedded systems using custom silicon.
The whole documentation can be found here.
The system allows developers to design graphical interfaces using a graphical configuration tool and deploy them directly to hardware implemented in a custom ASIC integrated with the Caravel SoC platform. The hardware renders the interface in real time and outputs the result to SPI-driven TFT/OLED screens commonly used in embedded devices.
The generated interface may include visual components such as:
Figure 1. Examples of graphical components supported by Lacerta, including buttons, horizontal and vertical bars, numeric indicators, graphics, and status indicators used to visualize real-time system data.
The ASIC receives information via UART streams and supports two main modes of operation for updating the display:
Direct Mode: Data received via UART is sent directly to the user project area. In this mode, the values are updated on the SPI TFT/OLED screen with minimal latency, ideal for simple or time-critical updates.
Processing Mode: Data from UART is first routed to the integrated RISC-V core, where any mathematical operations, functions, or custom logic can be applied. After processing, the results are sent to the user project area to update the display. This mode is suitable for applications requiring data manipulation or more complex interface logic.
This flexible architecture allows Lacerta to efficiently manage multiple inputs and screen objects using a single UART protocol, adapting to both straightforward and advanced use cases. Any other signal types must be converted to UART beforehand by external interface circuitry or preprocessing devices.
Figure 2. Lacerta system concept: signals are processed by the Lacerta ASIC to generate the custom graphical HMI displayed on SPI-driven TFT/OLED displays for compact embedded installations.
The Lacerta platform is an open-source embedded graphics system built from four main parts: custom silicon, board-level hardware, firmware/control logic, and interface software. Together, these layers allow a host system to load graphics data, update interface objects, and drive a small SPI-connected display efficiently.
Lacerta platform is a custom ASIC implemented in the SKY130 process and integrated inside the Caravel user project area. This subsystem realizes the hardware graphics engine that receives interface commands, updates the internal display state, and generates the output stream presented on the display.
The Lacerta ASIC follows a memory-centric architecture. Configuration data and runtime values enter the system through UART. Depending on the selected operating mode, the received data can be forwarded directly to the user project area or first processed by the embedded Caravel RISC-V processor. Internal transactions are routed through the Wishbone interconnect to the rendering logic, which updates the frame contents stored in memory. The display output block then reads that memory and continuously converts it into the signal required by the connected SPI TFT/OLED display.
The ASIC includes the following main modules:
Figure 3. Block diagram of the Lacerta ASIC inside the Caravel environment. The figure shows how UART data and the embedded Caravel RISC-V processor interact through the Wishbone-connected control path, rendering logic, and memory subsystem; the updated frame data is then read by the display output block to drive the screen.
The memory subsystem manages buffered access to external SRAM. It uses FIFOs, read/write buffering, and arbitration logic so several blocks can share memory safely without needing to handle low-level SRAM timing directly.
The screen path reads pixel data from memory and converts it into SPI transactions for the display. It supports TFT initialization, full or partial region refreshes, and a color lookup mechanism that maps compact pixel codes to RGB565 values. This reduces memory usage and makes repeated HMI colors efficient to store.
The drawing logic updates only the parts of the image that change. The mask_generator reads current pixel data, modifies selected regions based on object type, writes the result back to SRAM, and then triggers a refresh of the affected rectangle. This makes the system well suited for HMI elements such as bars, graphs, booleans, and segmented displays.
The control path is coordinated by command_arbiter_decoder, which receives transactions from UART and Wishbone interfaces and turns them into actions such as memory access, object redraws, screen refreshes, color-table updates, and reset/control operations.
UART provides an external host-facing command port for loading assets, configuring the display, and triggering updates. Wishbone provides processor-oriented access to both control registers and shared memory, allowing the embedded Caravel processor or another SoC master to work with the same graphics system.
In normal use, a host first loads graphics assets or configuration data into SRAM. The display is initialized, then object updates are triggered through UART or processor commands. The drawing engine modifies only the required image region in memory, and the screen subsystem refreshes only that changed rectangle on the TFT. This avoids full-screen redraws and improves efficiency for dynamic interfaces.
The Lacerta Board packages the SoC with the supporting hardware needed for practical use, including power regulation, clocking, USB-to-serial connectivity, SPI Flash support, GPIO access, and display/peripheral connections. It serves as the physical platform for development, testing, and demonstration of the Lacerta graphics architecture.
The development of the Lacerta platform spans the complete hardware and software realization flow, from digital design and verification to physical implementation and system-level integration. This section describes the main stages used to transform the Lacerta concept into a functional platform, including RTL design, verification, layout generation, gate-level validation, PCB development, and the creation of the interface design software.
Together, these activities define the engineering workflow followed to implement, test, and deploy Lacerta as an open-source embedded graphical interface system. Each subsection highlights a different part of this process and explains how the individual development tasks contribute to the final platform.
RTL code can be found here.
The system is designed to display graphical HMI content on a TFT screen and to update only the screen regions that change.
At a functional level, the system must:
The design is organized around a shared memory architecture. Instead of each module touching the SRAM directly, all active clients use a common memory subsystem with buffered read and write channels, as shown in the figure below.
The complete display flow is:
mask_generator reads the corresponding image region, updates the stored bytes, and writes the modified data back into SRAM.screen_system requests the affected window from memory.tft_control_fsm streams TFT commands and pixel bytes through spi_master.This makes the system well suited for dashboards, indicators, bars, graphs, and symbolic objects that change frequently in small areas.
dig_top.vdig_top is the main integration point of the RTL system.
It connects:
The clients connected to the shared memory system are:
Inside dig_top, each client is assigned to a dedicated buffer slot. The top-level combinational logic packs the individual requests into the vectors expected by mem_sys.
dig_top also derives the frame-update rectangle used by the display block:
frame_st_xframe_end_xframe_widthframe_st_yframe_end_yframe_heightframe_st_pixThese values are taken from the drawing object parameters so that, after a drawing operation, the correct screen region can be refreshed automatically.
Another important top-level task is Wishbone routing. dig_top chooses whether a Wishbone transaction goes to:
wb_slave_memory_mapped for control/MMIO accesses,wb_slave_to_mem_sys_ports for direct SRAM-backed data accesses.uart_ip_memory_mapped converts them into internal writes.command_arbiter_decoder interprets those writes as host memory-transfer commands.mem_sys schedules the write burst.buffers_discharger sends the bytes to SRAM through sram_controller.command_arbiter_decoder stores width, height, position, object value, and memory addresses.drw_inc_start.mask_generator begins a read-modify-write sequence.mem_sys.mem_sys.mask_generator asserts ss_start.screen_system refreshes the affected rectangle on the TFT.ss_ld_sidebar.tft_control_fsm programs the sidebar coordinates into the TFT.spi_master.dig_top: integrates the whole system and routes all subsystem interfaces.command_arbiter_decoder: converts UART/Wishbone commands into internal control actions.uart_ip_memory_mapped: converts UART packets into internal memory-mapped transactions.wb_slave_memory_mapped: converts Wishbone MMIO accesses into control transactions.wb_slave_to_mem_sys_ports: converts Wishbone data accesses into shared-memory bursts.mem_sys: arbitrates shared access to external SRAM.buffers: stores temporary read and write data for all clients.buffers_filler: fills read buffers from SRAM.buffers_discharger: empties write buffers into SRAM.sram_controller: drives the physical SRAM pins.mask_generator: updates image regions according to HMI object logic.screen_system: top display block for TFT output.tft_control_fsm: performs TFT initialization and region-based pixel transfer.color_mapping_table: converts compact pixel codes into RGB565 colors.spi_master: serializes commands and pixel bytes onto the TFT SPI bus.Verilog TB code can be found here.
A layered verification strategy was used to validate Lacerta from block level up to full-system behavior. The intent was not only to prove that individual modules operate correctly in isolation, but also to verify that the complete command, memory, drawing, and display paths remain coherent when exercised through the same interfaces used in deployment.
At the block level, dedicated environments were created for the UART front end, the shared memory subsystem, the Wishbone adapters, the command decoder, and the display-related logic. These environments focused on local protocol correctness, handshake legality, data stability, and forward progress. The later sections of this document list the principal checks captured for each block.
At the system level, the main integration environment is verif/dig_top_tb.sv. This testbench drives the top-level dig_top instance through the UART path, connects the design to an SRAM behavioral model (CY7C1049GN_i), and observes the TFT SPI outputs exactly as a real deployment would use them. In practice, this makes the testbench an end-to-end verification vehicle: a command is injected as UART traffic, decoded by the control plane, executed through the memory subsystem, and finally checked either at the SRAM image or at the TFT serial output.
Figure 4. The diagram summarizes the main verification components, including the clock and reset infrastructure, golden reference data, stimulus path, UART bus functional model, SRAM model, and checker logic used to validate the DUT behavior during gate-level simulation.
More information about the simulation flow, active checkers, and expected data paths can be found in dig_top_tb_flow_diagram.html.
The full-system verification flow is organized around three complementary ideas:
Interface-faithful stimulus
The testbench does not force deep internal signals to mimic system behavior. Instead, it uses the UART Bus Functional Model (uart_bfm) and the helper task uart_write_mem() to generate valid command packets byte by byte. This ensures that the UART receive path, packet decoder, command arbiter, and downstream blocks are exercised together.
Independent reference data
The testbench builds its own expected data structures before execution begins:
tft_init_mem stores the expected TFT initialization sequence, including command, data, and delay entries.
tft_sidebar stores the expected sidebar stream sent to the TFT.
tft_active_area stores the logical active-screen image used for full-frame display verification.
tb_sram acts as a golden SRAM image. It is initialized from the active-area data and then updated by the testbench's own object-drawing rules before being compared against the DUT-visible SRAM model.
Concurrent checking
Verification is not deferred to a single final comparison. The testbench runs several checker threads in parallel, so protocol violations, timing mismatches, stream ordering errors, and memory corruption are detected close to the cycle where they occur. This is especially important for gate-level simulation, where failures may arise from control sequencing or handshake timing rather than purely functional logic.
dig_top_tb.sv Verification FlowThe top-level testbench starts from a simple but realistic infrastructure:
always #10ns clk = !clk;,After reset, the system verification scenario progresses through the following phases.
The testbench writes every entry of tft_init_mem through UART to the control address used by the screen subsystem. This stage verifies that Lacerta accepts configuration traffic through the host path and correctly stores screen-initialization data before any display action is requested.
Once the initialization table is loaded, the testbench configures the SPI clock divider and triggers screen initialization. A dedicated checker thread waits until the TFT control FSM enters its initialization state and then validates each emitted entry:
{rom_type, tnsm_data} against the expected tft_init_mem content;CLK_CYCLES_PER_MS.This stage verifies more than register programming. It checks that the initialization ROM is consumed in the correct order, that delay entries are honored in time, and that the SPI path receives the exact bytes expected by the TFT controller. After the sequence completes, the testbench asserts that initialization_done is high.
The testbench then prepares a burst write into the shared memory system and streams the sidebar payload through repeated UART writes. After the sidebar-load command is issued, the testbench checks both control behavior and output behavior:
sidebar_ongoing must assert after the command and later deassert when the transfer completes;tft_sidebar sequence;tft_dc line must indicate command bytes for CASET, RASET, and RAMWR, and data bytes everywhere else.This verifies the complete path from host programming, to SRAM write buffering, to screen-system memory fetch, to TFT serialization.
The testbench writes randomized RGB565 values into every color-map entry and then reads the corresponding internal table state after a short propagation delay. This confirms that compact logical pixel codes used in the screen image are translated through the correct table entries before being sent to the TFT interface.
To verify full-image display behavior, the testbench first loads the active-screen image into SRAM through the UART-controlled write path. It then programs object geometry fields so the screen subsystem fetches the entire active display region and emits it over SPI.
During this phase, the verification logic checks:
busy after the fetch request and later returns to idle;CASET, RASET, RAMWR, and coordinate bytes) match the expected tft_active_area header;tft_active_area is converted into the correct two-byte RGB565 value using the live color_map table;tft_dc remains correct during the whole transfer.This is an important system-level check because it validates the interaction among stored pixel data, color expansion, frame-window generation, TFT command sequencing, and SPI serialization.
After the static display paths are verified, the testbench executes TB_NUM_OBJECTS randomized drawing scenarios. For each iteration it selects:
st_x, st_y),The object type rotates through the drawing modes implemented in the testbench tasks:
draw_horizontal_type()draw_vertical_type()draw_graph_type()draw_mask_type()Each task programs the DUT through UART exactly as software would: it writes object type, dimensions, start address, screen coordinates, and trigger/value fields. The testbench then waits for the drawing engine completion handshake (MASK_GEN_PATH.done) and updates the shadow image tb_sram according to an independent expected-behavior model:
obj_value.obj_value.After every object operation, check_sram_consistency() compares the golden tb_sram contents against the actual external SRAM model seen by the DUT. This immediate comparison is valuable because it localizes failures to the most recent object operation instead of postponing diagnosis to the end of the simulation.
At the end of the scenario, the testbench issues the UART command that enables the embedded microprocessor path and verifies that up_enable is asserted. This closes the loop on one more top-level control action and ensures the system can hand control to the processor-side flow after host-side configuration.
The dig_top_tb.sv environment contains several simultaneously active verification mechanisms:
tft_mosi on tft_sck edges and confirms that every acknowledged tnsm_data byte is serialized MSB first.initialization_done, sidebar_ongoing, busy, buffer-empty conditions, and up_enable.Together, these checkers provide both transaction-level and bit-level confidence. A failure can therefore be caught as a bad control transition, a wrong memory update, an incorrect TFT byte, or even a serialization mismatch on the SPI output pin.
This same end-to-end style is especially useful for gate-level simulation because it exercises long control sequences, back-pressure conditions, and external-interface timing without simplifying the problem to a purely combinational comparison. More detailed information about the simulation flow, active checkers, and expected data paths can be found in dig_top_tb_flow_diagram.html. That file documents the actual structure implemented in dig_top_tb.sv: UART-driven initialization, sidebar transfer, color-map programming, full active-area fetch, constrained-random object drawing with per-object SRAM comparison, and final processor enable.
Overall, the Lacerta verification methodology combines block-level protocol checking, system-level end-to-end stimulus, reference-model comparison, and gate-level observability. This gives strong confidence that the platform is not only logically correct, but also integration-ready across its communication, memory, drawing, and display subsystems.
The verification plan for the WB Slave to Memory Mapped block focuses on protocol correctness, proper memory-side control generation, and legal read/write handshaking.
wb_ack_o is asserted for only one clock cycle per transaction.mem_we is asserted, and mem_re is not asserted, during Wishbone write requests.mem_re is asserted, and mem_we is not asserted, during Wishbone read requests.wb_cyc_i and wb_stb_i are deasserted only after wb_ack_o, preventing overlapping requests.mem_waddr, mem_wdata, and mem_wmask correctly reflect the Wishbone address, data, and byte-select signals during write requests.mem_raddr correctly reflects the Wishbone address during read requests.wb_dat_o returns the same data received from memory when a Wishbone read request completes.mem_wr_data_ack can be asserted only while a Wishbone write transaction is in progress.mem_rdy can be asserted only while a Wishbone read transaction is in progress.The verification plan for the WB Slave to Read/Write Ports block checks correct Wishbone behavior, proper coordination with the memory-system ports, and correct sequencing of read and write transactions initiated by the microprocessor side.
wb_ack_o is asserted for only one clock cycle per transaction.wpg_busy is asserted only for Wishbone write requests and remains clear for read requests.wpg_busy remains asserted until wpg_ack is received.rpg_busy is asserted only for Wishbone read requests and remains clear for write requests.rpg_busy remains asserted until rpg_ack is received.wb_cyc_i and wb_stb_i are deasserted only after wb_ack_o, preventing overlapping requests.up_en does not change while a read or write process is in progress.up_soft_reset does not change while a read or write process is in progress.wpg_st_addr, wpg_burst_length, and wr_buff_wdata are correctly loaded during Wishbone write requests.wpg_st_addr, wpg_burst_length, and wr_buff_wdata remain stable until wpg_ack is asserted.rpg_st_addr and rpg_burst_length are correctly loaded during Wishbone read requests.rpg_st_addr and rpg_burst_length remain stable until rpg_ack is asserted.wr_buff_wren is asserted only during Wishbone write requests and only once per write transaction.rd_buff_rden is asserted only during Wishbone read requests and exactly NUM_ACCESSES times per read transaction.rpg_ack can be asserted only while a master read operation is ongoing.wpg_ack can be asserted only while a master write operation is ongoing.rpg_ack is asserted.wpg_ack is asserted.The verification plan for the Command Arbiter Decoder block checks the validity of drawing commands, busy-state behavior, and the control rules used when enabling or resetting the memory-access path.
drw_inc_start is asserted, the drawing object type is within the valid range and both object width and object height are greater than MIN_OBJECT_WIDTH_HEIGHT.drw_inc_start causes drw_inc_busy to transition from 0 to 1.drw_inc_busy is asserted.drw_inc_busy is not asserted for longer than DRW_BUSY_TIMEOUT clock cycles.wb_slave_up_en is asserted when the UART write command address is 18.wb_slave_up_en can be deasserted only when no memory-system access transaction is in progress.up_soft_reset can be asserted only when no memory-system access transaction is in progress.The verification plan for the Mask Generator block validates correct start/busy sequencing and ensures that internal read/write activity occurs only while the block is actively processing a drawing operation.
start causes busy to transition from 0 to 1.start cannot be asserted while busy or done is already asserted.busy is deasserted, rpg_busy and wpg_busy are both low and rd_buff_empty is high.rd_buff_rden cannot be asserted when rd_buff_empty is high.wr_buff_wren cannot be asserted when wr_buff_full is high.rpg_busy, wpg_busy, rpg_ack, wpg_ack, wr_buff_full, rd_buff_rden, and wr_buff_wren can be asserted only while busy is high.Verilog TB code can be found here.
The RTL simulation stage was used to verify the functional behavior of the Lacerta top-level design and to confirm the correctness of the TFT initialization transaction sequence before physical implementation. In this test, the simulation output shows that the expected delays were observed and that the initialization values stored in tft_init_mem were transmitted correctly to spi_master. The resulting log provides evidence that the initialization FSM and SPI output path behave as intended during the early display bring-up sequence at the RTL verification stage.
A section from the RTL simulation log is shown below. The complete log file is available for download here: lacerta_gate_level_simulation.log.
Time resolution is 1 ps
open_wave_config /home/miguel/Documents/lacerta/verif/work/work.dig_top_tb.wcfg
run -all
delay encountered 20
PASS: correct delay 1020321 for entry 0 was measured
delay encountered 120
PASS: correct delay 6049997 for entry 1 was measured
PASS: correct tft_init_mem data 0001 for entry 2 was sent to spi_master
delay encountered 150
PASS: correct delay 7549959 for entry 3 was measured
PASS: correct tft_init_mem data 0011 for entry 4 was sent to spi_master
delay encountered 120
PASS: correct delay 6049959 for entry 5 was measured
PASS: correct tft_init_mem data 003a for entry 6 was sent to spi_master
PASS: correct tft_init_mem data 0155 for entry 7 was sent to spi_master
delay encountered 10
PASS: correct delay 549920 for entry 8 was measured
PASS: correct tft_init_mem data 0036 for entry 9 was sent to spi_master
PASS: correct tft_init_mem data 01a8 for entry 10 was sent to spi_master
PASS: correct tft_init_mem data 002a for entry 11 was sent to spi_master
PASS: correct tft_init_mem data 0100 for entry 12 was sent to spi_master
PASS: correct tft_init_mem data 0100 for entry 13 was sent to spi_master
PASS: correct tft_init_mem data 0101 for entry 14 was sent to spi_master
PASS: correct tft_init_mem data 013f for entry 15 was sent to spi_masterA custom script was developed to execute RTL and GL simulations with the Caravel infrastructure, as the default Caravel simulation flow was out of date and only supported cocotb-based testbenches. This approach was necessary to correctly run assertion-based testbenches and ensure compatibility with the current Lacerta verification environment, which relies on SystemVerilog assertions and traditional testbench flows.
The custom script, located in the dv_setup directory (lacerta/dv_setup), automates the setup and execution of both RTL and gate-level (GL) simulations. It handles environment configuration, Makefile patching, and the selection of the appropriate simulation mode (SIM_MODE=RTL or SIM_MODE=GL). The script also allows users to select which DV test to run via the DV_TEST variable, making it flexible for different verification scenarios.
This approach ensures that all assertions and checkers in the testbenches are properly evaluated during simulation, which is not possible with the default Caravel cocotb-only flow. The script supports both host-based and Docker-based simulation environments, making it suitable for a variety of development setups.
The main testbench (lacerta_tb.sv) and its associated waveform files can be found in the lacerta/verilog/dv/lacerta folder. The following figure shows an example waveform generated during simulation:
Figure 6. Example simulation waveform from the Lacerta RTL testbench, illustrating the verification an initial configuration of the memory_system through UART using IO port 5 an 6.
For detailed instructions on how to use the RTL/GL simulation flow, refer to the documentation and scripts in
Librelane configuration can be found here.
This page documents the OpenLane hardening setup used for the user_project_wrapper flow in Lacerta and records the top-level hardening option selected for the project.
The selected hardening option is:
Flat on Top-Level (Single Flat Design)
In this approach, the full user project is hardened directly at the user_project_wrapper level. OpenLane reads the top-level wrapper together with the project RTL and generates a single physical implementation for the wrapper.
This option is typically used when:
For this flow, the top-level OpenLane run is performed inside:
openlane/user_project_wrapper
For a flat top-level hardening flow, the wrapper configuration should:
DESIGN_IS_CORE to 1 when required by the selected OpenLane flow,user_project_wrapper.v together with the full user RTL in VERILOG_FILES,user_project_wrapper.v directly instantiates the project design.In Lacerta, the wrapper configuration includes the top-level RTL together with the main functional blocks such as:
dig_top.vcommand_arbiter_decoder.vThe wrapper hardening file is:
openlane/user_project_wrapper/config.json
This configuration includes the full RTL list under VERILOG_FILES, which matches the flat top-level hardening strategy. The file also enables several implementation and signoff-related options for a full wrapper run.
Key settings from config.json:
"SYNTH_ELABORATE_ONLY": false,
"RUN_POST_GPL_DESIGN_REPAIR": true,
"RUN_POST_CTS_RESIZER_TIMING": true,
"DESIGN_REPAIR_BUFFER_INPUT_PORTS": true,
"FP_PDN_ENABLE_RAILS": true,
"RUN_ANTENNA_REPAIR": true,
"RUN_FILL_INSERTION": true,
"RUN_TAP_ENDCAP_INSERTION": true,
"RUN_CTS": true,
"RUN_IRDROP_REPORT": trueAdditional implementation-oriented settings used in the same file include:
"SYNTH_STRATEGY": "DELAY 4",
"FP_CORE_UTIL": 30,
"DESIGN_REPAIR_REMOVE_BUFFERS": true,
"DESIGN_REPAIR_MAX_CAP_PCT": 85,
"DESIGN_REPAIR_MAX_SLEW_PCT": 85,
"RUN_POST_GRT_DESIGN_REPAIR": true,
"RUN_POST_GRT_RESIZER_TIMING": true,
"PL_RESIZER_HOLD_SLACK_MARGIN": 0.3,
"GRT_RESIZER_HOLD_SLACK_MARGIN": 0.3The following variables were identified as the hardening option reference for top-level integration:
"QUIT_ON_SYNTH_CHECKS": 1,
"FP_PDN_CHECK_NODES": 1,
"SYNTH_ELABORATE_ONLY": 0,
"PL_RANDOM_GLB_PLACEMENT": 0,
"PL_RESIZER_DESIGN_OPTIMIZATIONS": 1,
"PL_RESIZER_TIMING_OPTIMIZATIONS": 1,
"GLB_RESIZER_DESIGN_OPTIMIZATIONS": 1,
"GLB_RESIZER_TIMING_OPTIMIZATIONS": 1,
"PL_RESIZER_BUFFER_INPUT_PORTS": 1,
"FP_PDN_ENABLE_RAILS": 1,
"GRT_REPAIR_ANTENNAS": 1,
"RUN_FILL_INSERTION": 1,
"RUN_TAP_DECAP_INSERTION": 1,
"RUN_CTS": 1,
"RUN_CVC": 1These settings describe the intended behavior of a robust full-wrapper hardening run, including synthesis checking, placement control, timing optimization, PDN generation, antenna repair, filler insertion, tap/decap insertion, clock-tree synthesis, and final electrical checks.
Figure 5. KLayout view of the Lacerta custom ASIC layout, showing the physical implementation of the design within the SKY130 Caravel user project area.
To complement the layout view, Table 1 summarizes the main implementation metrics of the Lacerta chip extracted from the final OpenLane hardening results. These values provide a compact overview of the physical size, logic complexity, utilization, power, timing, and routing quality achieved for the final ASIC integration.
| Parameter | Value |
|---|---|
| Technology / integration platform | SKY130 in Caravel user project area |
| Die size | 2920 um x 3520 um |
| Die area | 10.2784 mm² |
| Core size | 2908.58 um x 3497.92 um |
| Core area | 10.1740 mm² |
| User I/O count | 645 |
| Standard-cell instance count | 170,896 |
| Standard-cell area | 465,176 um² |
| Core utilization | 4.57% |
| Total power | 0.0250 W |
| Internal power | 0.0186 W |
| Switching power | 0.0065 W |
| Leakage power | 4.02e-7 W |
| Worst setup slack (WNS) | 0.0 ns |
| Worst hold slack (WNS) | 0.0 ns |
| Worst setup slack margin | 0.9290 ns |
| Worst hold slack margin | 0.0151 ns |
| Total negative setup slack (TNS) | 0.0 ns |
| Total negative hold slack (TNS) | 0.0 ns |
| Setup violations | 0 |
| Hold violations | 0 |
| Final routing DRC errors | 0 |
| Total routed wirelength | 1,287,756 um |
| Total vias | 159,152 |
| Power-grid violations | 0 |
Table 2 summarizes the post-layout timing and electrical-check results for the Lacerta chip across the main process, voltage, and temperature corners evaluated during signoff. It highlights hold and setup slack, total negative slack, violation counts, and basic design-rule indicators such as maximum capacitance and slew violations. Together, these results provide a compact view of implementation robustness and show that the design closes timing without setup or hold violations across all analyzed corners, while only a small number of electrical violations remain in the worst-case conditions.
| Corner / Group | Hold Worst Slack (ns) | Reg-to-Reg Hold (ns) | Hold TNS (ns) | Hold Violations | Setup Worst Slack (ns) | Reg-to-Reg Setup (ns) | Setup TNS (ns) | Setup Violations | Max Cap Violations | Max Slew Violations |
|---|---|---|---|---|---|---|---|---|---|---|
| Overall | 0.0151 | 0.2878 | 0.0000 | 0 | 0.9290 | 8.1509 | 0.0000 | 0 | 6 | 47 |
nom_tt_025C_1v80 | 0.2248 | 0.6272 | 0.0000 | 0 | 6.0692 | 13.9265 | 0.0000 | 0 | 0 | 0 |
nom_ss_100C_1v60 | 0.0929 | 1.4592 | 0.0000 | 0 | 0.9719 | 8.4898 | 0.0000 | 0 | 2 | 15 |
nom_ff_n40C_1v95 | 0.1791 | 0.2879 | 0.0000 | 0 | 7.8085 | 15.9307 | 0.0000 | 0 | 0 | 0 |
min_tt_025C_1v80 | 0.2767 | 0.6248 | 0.0000 | 0 | 6.1163 | 14.1220 | 0.0000 | 0 | 0 | 0 |
min_ss_100C_1v60 | 0.1648 | 1.4278 | 0.0000 | 0 | 0.9884 | 8.8070 | 0.0000 | 0 | 1 | 9 |
min_ff_n40C_1v95 | 0.2279 | 0.2885 | 0.0000 | 0 | 7.8413 | 16.0592 | 0.0000 | 0 | 0 | 0 |
max_tt_025C_1v80 | 0.1682 | 0.6288 | 0.0000 | 0 | 6.0312 | 13.7420 | 0.0000 | 0 | 0 | 0 |
max_ss_100C_1v60 | 0.0151 | 1.4767 | 0.0000 | 0 | 0.9290 | 8.1509 | 0.0000 | 0 | 6 | 47 |
max_ff_n40C_1v95 | 0.1249 | 0.2878 | 0.0000 | 0 | 7.7814 | 15.8059 | 0.0000 | 0 | 0 | 0 |
**Precheck logs can be found** [**here**](https://github.com/MifralTech/Lacerta_CF/tree/main/precheck_results).
2026-04-30 11:20:10 [INFO] Extracting compressed files in: /home/baungarten/Desktop/lacerta_march
2026-04-30 11:20:11 [INFO] Project type: digital
2026-04-30 11:20:12 [INFO] GDS hash (user_project_wrapper): 6b97c7a8678942fc2cc9d44b268f9c97943aedf2
2026-04-30 11:20:13 [INFO] Tools: KLayout v0.29.2 | Magic v8.3.471
2026-04-30 11:20:13 [INFO] PDK: SKY130A unknown
2026-04-30 11:20:13 [INFO] Running 13 checks: [topcell_check, gpio_defines, xor, klayout_feol, klayout_beol, klayout_offgrid, klayout_met_min_ca_density, klayout_pin_label_purposes_overlapping_drawing, klayout_zeroarea, spike_check, illegal_cellname_check, lvs, oeb]
2026-04-30 11:20:15 [INFO] Single top cell 'user_project_wrapper' found
2026-04-30 11:20:15 [INFO] GPIO defines: parsing verilog/rtl/user_defines.v
2026-04-30 11:20:15 [INFO] GPIO defines report: /home/baungarten/Desktop/lacerta_march/precheck_results/30_APR_2026___11_20_10/outputs/reports/gpio_defines.report
2026-04-30 11:20:32 [INFO] Total XOR differences: 0
2026-04-30 11:20:32 [INFO] Running: klayout -b -r /usr/local/lib/python3.9/site-packages/cf_precheck/drc_scripts/sky130A_mr.drc -rd input=/home/baungarten/Desktop/lacerta_march/gds/user_project_wrapper.gds -rd topcell=user_project_wrapper -rd report=/home/baungarten/Desktop/lacerta_march/precheck_results/30_APR_2026___11_20_10/outputs/reports/klayout_feol_check.xml -rd thr=32 -rd feol=true
2026-04-30 11:25:24 [INFO] No DRC violations found
2026-04-30 11:25:24 [INFO] Running: klayout -b -r /usr/local/lib/python3.9/site-packages/cf_precheck/drc_scripts/sky130A_mr.drc -rd input=/home/baungarten/Desktop/lacerta_march/gds/user_project_wrapper.gds -rd topcell=user_project_wrapper -rd report=/home/baungarten/Desktop/lacerta_march/precheck_results/30_APR_2026___11_20_10/outputs/reports/klayout_beol_check.xml -rd thr=32 -rd beol=true
2026-04-30 11:37:27 [INFO] No DRC violations found
2026-04-30 11:37:27 [INFO] Running: klayout -b -r /usr/local/lib/python3.9/site-packages/cf_precheck/drc_scripts/sky130A_mr.drc -rd input=/home/baungarten/Desktop/lacerta_march/gds/user_project_wrapper.gds -rd topcell=user_project_wrapper -rd report=/home/baungarten/Desktop/lacerta_march/precheck_results/30_APR_2026___11_20_10/outputs/reports/klayout_offgrid_check.xml -rd thr=32 -rd offgrid=true
2026-04-30 11:40:26 [INFO] No DRC violations found
2026-04-30 11:40:26 [INFO] Running: klayout -b -r /usr/local/lib/python3.9/site-packages/cf_precheck/drc_scripts/met_min_ca_density.lydrc -rd input=/home/baungarten/Desktop/lacerta_march/gds/user_project_wrapper.gds -rd topcell=user_project_wrapper -rd report=/home/baungarten/Desktop/lacerta_march/precheck_results/30_APR_2026___11_20_10/outputs/reports/klayout_met_min_ca_density_check.xml -rd thr=32
2026-04-30 11:41:15 [INFO] No DRC violations found
2026-04-30 11:41:15 [INFO] Running: klayout -b -r /usr/local/lib/python3.9/site-packages/cf_precheck/drc_scripts/pin_label_purposes_overlapping_drawing.rb.drc -rd input=/home/baungarten/Desktop/lacerta_march/gds/user_project_wrapper.gds -rd topcell=user_project_wrapper -rd report=/home/baungarten/Desktop/lacerta_march/precheck_results/30_APR_2026___11_20_10/outputs/reports/klayout_pin_label_purposes_overlapping_drawing_check.xml -rd thr=32 -rd top_cell_name=user_project_wrapper
2026-04-30 11:41:48 [INFO] No DRC violations found
2026-04-30 11:41:48 [INFO] Running: klayout -b -r /usr/local/lib/python3.9/site-packages/cf_precheck/drc_scripts/zeroarea.rb.drc -rd input=/home/baungarten/Desktop/lacerta_march/gds/user_project_wrapper.gds -rd topcell=user_project_wrapper -rd report=/home/baungarten/Desktop/lacerta_march/precheck_results/30_APR_2026___11_20_10/outputs/reports/klayout_zeroarea_check.xml -rd thr=32 -rd cleaned_output=/home/baungarten/Desktop/lacerta_march/precheck_results/30_APR_2026___11_20_10/outputs/user_project_wrapper_no_zero_areas.gds
2026-04-30 11:41:56 [INFO] No DRC violations foundPCB files can be found here.
The Lacerta PCB provides the physical platform used to power, configure, and evaluate the Lacerta hardware. At a general level, the board brings together the Caravel device, external memory, communication interfaces, clock generation, power regulation, and display connectivity required to operate the Lacerta graphics subsystem as a complete embedded system. In addition to hosting the main integrated circuits, the board exposes test points, headers, and peripheral connectors that simplify bring-up, debugging, and laboratory validation.
From the schematic point of view, the board is organized into clearly separated functional domains. These include the Caravel interface, the USB-to-serial path used for configuration and communication, the flash-memory interface, the clock-generator circuit, the power-supply section, and the display/output connectors. This partitioning makes the design easier to validate and reflects the main operational needs of Lacerta: receiving commands, storing data, accessing the Caravel platform, and driving an external display.
From a cost perspective, the Lacerta board was designed around widely available commercial parts, keeping the supporting electronics relatively affordable for prototyping and laboratory validation. Based on the current bill of materials in lacerta_bom.csv, the populated board components with listed prices sum to approximately USD 28.46. This estimate covers the off-the-shelf electronic components only and does not include PCB fabrication, board assembly, shipping, taxes, or the cost of the custom Lacerta/Caravel chip itself, which appears in the BOM as a non-priced item.
The cost distribution is dominated by a small number of active devices, especially the external SRAM, the programmable oscillator, and the FT232H USB interface. In contrast, most passive parts and headers contribute only a small fraction of the total. This is typical for a development-oriented board, where communication, memory, and clock-generation devices account for much of the material cost while still enabling a flexible and easy-to-evaluate hardware platform.
| Cost category | Estimated cost (USD) | Notes |
|---|---|---|
External SRAM (U12) | 5.72 | CY7C1049GN-10VXI |
Programmable oscillator (U10) | 4.47 | DS1086LU+T |
USB interface (U1) | 4.09 | FT232HQ |
| Resistor networks and discretes | 2.42 | Main resistor lines combined |
| Capacitors | 2.50 | All capacitor lines combined |
Flash memory (U7) | 0.93 | W25Q32JVSSIQ |
Regulators (U5, U6) | 0.98 | TAR5S16U |
| Connectors and headers | 4.04 | USB, sockets, and pin headers |
Clock sources (X1, Y1) | 1.13 | 10 MHz oscillator and 12 MHz crystal |
| LEDs, switch, mux, buffers, ferrite bead | 2.18 | Support circuitry |
Custom Lacerta/Caravel chip (U11) | Not priced | ASIC cost not included in BOM total |
| Total priced components | 28.46 | Excludes PCB, assembly, shipping, taxes, and ASIC fabrication |
Table 3 lists the main priced BOM entries together with direct supplier links. These links document the exact components used for the current board revision and make the cost estimate traceable to the underlying purchase sources.
| Item | Qty | Part number | Sum (USD) | Supplier link |
|---|---|---|---|---|
U12 | 1 | CY7C1049GN-10VXI | 5.72 | Infineon SRAM |
U10 | 1 | DS1086LU+T | 4.47 | Analog Devices / Maxim oscillator |
U1 | 1 | FT232HQ | 4.09 | FTDI FT232H |
R1,R4,R7,R8,R9,R10,R12,R13,R15,R16,R17,R18,R19,R20 | 14 | RV0805JR-0710KL | 1.82 | Yageo 10 kOhm resistors |
C2,C3,C4,C5,C6,C7,C8,C9,C18,C20,C21,C24 | 12 | CL21B104KBCNNNC | 1.20 | Samsung 0.1 uF capacitors |
U5,U6 | 2 | TAR5S16U | 0.98 | Toshiba regulators |
U7 | 1 | W25Q32JVSSIQ | 0.93 | Winbond flash memory |
J1 | 1 | 105017-0001 | 0.92 | Molex Micro-USB connector |
J11 | 1 | 61301011121 | 0.95 | Wurth 1x10 header |
J10 | 1 | PPTC141LFBN-RC | 0.77 | Sullins socket |
C1,C11,C14,C17,C22,C23 | 6 | CL21B103KBANNNC | 0.60 | Samsung 0.01 uF capacitors |
X1 | 1 | DSC6001JE1B-010.0000 | 0.59 | Microchip 10 MHz oscillator |
U9 | 1 | TMUX4053PWR | 0.58 | TI analog mux |
Y1 | 1 | ABM8-272-T3 | 0.54 | Abracon 12 MHz crystal |
D1,D3,D4 | 3 | LTST-C150KRKT | 0.48 | Lite-On LEDs |
C12,C15,C16,C25 | 4 | CL21A106KPFNNNE | 0.40 | Samsung 10 uF capacitors |
J3,J5,J8,J9 | 4 | M50-3530242 | 0.40 | Harwin 1x02 headers |
R5,R6,R11,R14 | 4 | RC0402FR-071KL | 0.40 | Yageo 1 kOhm resistors |
Figure 6. Schematic of the Lacerta development board, showing the main functional blocks including the Caravel connection, USB-to-serial interface, flash memory, clock generator, power regulation, and display/output connectors.
The PCB implementation translates this schematic into a compact development board that places the major components and user interfaces in accessible locations. The 3D view highlights the physical arrangement of the display and interface connectors, the Caravel-related devices, the USB/FTDI section, memory devices, headers, and support circuitry. This representation is useful for understanding the mechanical integration of the board and for checking connector placement, component accessibility, and assembly feasibility during the hardware-development process.
Figure 7. 3D view of the Lacerta PCB, illustrating the assembled component placement, external connectors, and overall physical organization of the development board.
The routed PCB layout shows how the electrical connections between these subsystems are realized on the board. It provides a detailed view of component placement, copper routing, and board dimensions, and it reflects the practical constraints of signal integrity, power distribution, and connector accessibility. Together, the schematic, 3D rendering, and final layout document the complete PCB-development flow for Lacerta, from circuit definition to manufacturable board implementation.
Figure 8. PCB layout of the Lacerta development board, showing the routed interconnections, component placement, and board geometry used to implement the final hardware platform.
The first video presents a short demonstration of the Lacerta GUI. It gives an overview of the design environment and shows how graphical HMI elements can be arranged and edited inside the software.
YouTube link: Quick example of the Lacerta GUI
The second video shows the implementation of the HMI created in the first demonstration. Its purpose is to connect the GUI design stage with the actual hardware execution stage, showing how the interface behaves once deployed on the target platform.
YouTube link: Implementation of the HMI shown in Video 1
Lacerta is designed as a fully open-source reference architecture. The project includes all required design artifacts to reproduce the system, including:
Lacerta Software can be found here.
Important:
Interface_Design_Software/exe_file_GUI (the RAR parts). Ensure all parts are in the same directory and extract them with a tool such as 7-Zip or WinRAR.Quick steps
Lacerta is licensed under the Apache License 2.0. Attributions required by third-party licenses are in NOTICE, and every third-party component with its license is listed in THIRD-PARTY-LICENSES.md. The Mifral and Lacerta names and logos are not licensed for reuse.
| Qty | Value | Footprint | References |
|---|---|---|---|
| 14 | 10K | Resistor_SMD:R_0805_2012Metric | R1, R4, R7, R8, R9, R10, R12, R13, R15, R16, R17, R18, R19, R20 |
| 12 | 0.1uF | Capacitor_SMD:C_0805_2012Metric | C2, C3, C4, C5, C6, C7, C8, C9, C18, C20, C21, C24 |
| 6 | 0.01uF | Capacitor_SMD:C_0805_2012Metric | C1, C11, C14, C17, C22, C23 |
| 4 | 10uF | Capacitor_SMD:C_0805_2012Metric | C12, C15, C16, C25 |
| 4 | 1K | Resistor_SMD:R_0805_2012Metric | R5, R6, R11, R14 |
| 4 | Conn_01x02_Pin | Caravel_Board:Shorted_PinHeader_1x02_P2.54mm_Vertical | J3, J5, J8, J9 |
| 3 | 1uF | Capacitor_SMD:C_0805_2012Metric | C10, C13, C19 |
| 3 | Conn_01x02_Pin | Connector_PinHeader_2.54mm:PinHeader_1x02_P2.54mm_Vertical | J2, J6, J12 |
| 3 | RED | LED_SMD:LED_1206_3216Metric | D1, D3, D4 |
| 3 | SN74LVC1G125DCKR | strive_foot_prints:SOT65P210X110-5N | U2, U3, U4 |
| 2 | TAR5SxxU | Caravel_Board:SOT-353F | U5, U6 |
| 2 | TestPoint | TestPoint:TestPoint_Bridge_Pitch2.54mm_Drill1.0mm | TP1, TP2 |
| 1 | 12K 1% | Resistor_SMD:R_0805_2012Metric | R2 |
| 1 | 12MHz | strive_foot_prints:CSTNE12M0GH5L000R0 | Y1 |
| 1 | 150 | Resistor_SMD:R_0805_2012Metric | R3 |
| 1 | 600R/0.5A | Inductor_SMD:L_0805_2012Metric | FB1 |
| 1 | Caravel_QFN | Package_DFN_QFN:QFN-64-1EP_9x9mm_P0.5mm_EP7.65x7.65mm | U11 |
| 1 | Conn_01x03_Pin | Connector_PinHeader_2.54mm:PinHeader_1x03_P2.54mm_Vertical | J4 |
| 1 | Conn_01x06_Pin | Connector_PinHeader_2.54mm:PinHeader_1x06_P2.54mm_Vertical | J7 |
| 1 | Conn_01x10_Pin | Connector_PinHeader_2.54mm:PinHeader_1x10_P2.54mm_Vertical | J11 |
| 1 | Conn_01x14_Socket | Connector_PinSocket_1.00mm:PinSocket_1x14_P1.00mm_Vertical | J10 |
| 1 | Conn_01x15_Pin | Connector_PinHeader_2.54mm:PinHeader_1x15_P2.54mm_Vertical | J14 |
| 1 | DS1086LU | Caravel_Board:SOP65P490X110-8N | U10 |
| 1 | DSC6001_10MHZ | strive_foot_prints:DSC6001JE1A-010.0000 | X1 |
| 1 | FT232H | Package_DFN_QFN:QFN-48-1EP_8x8mm_P0.5mm_EP6.2x6.2mm | U1 |
| 1 | IS61C5128AL-10KLI | Package_SO:SOJ-36_10.16x23.495mm_P1.27mm | U12 |
| 1 | LOGO | Mifral:Mifral_logo | G*** |
| 1 | SW_Push - SKQGADE010 | strive_foot_prints:SW4-SMD-5.2X5.2X1.5MM | SW1 |
| 1 | TMUX4053-BQB | Caravel_Board:WQFN-16-1EP_2.5x3.5mm_P0.5mm_EP1x2mm | U9 |
| 1 | TestPoint | TestPoint:TestPoint_THTPad_2.0x2.0mm_Drill1.0mm | TP3 |
| 1 | USB_B_Micro | strive_foot_prints:FCI_10118193-0001LF | J1 |
| 1 | W25Q32FVSS | strive_foot_prints:SOIC127P790X216-8N | U7 |

efabless/caravel_board
This repo provides firmware examples, flash programming and diagnostic tools for testing Open MPW and chipIgnite projects using Caravel.

chipfoundry/caravel_board
This repository provides firmware examples, flash programming tools, and diagnostic utilities for testing chipIgnite projects using the Caravel SoC.


weyer7/Caravel-Breakout-Rev-1.1
A small-footprint caravel breakout board based off of efabless Caravel REV 5 development board


FPGA-Research/FABulous_board
A PCB created for FABulous FPGAs, based on the caravel board.


It measures 76.2 × 73.8 mm and has 2 copper layers, 1.6 mm thick.
80 parts, built around the SN74LVC1G125DCKR-GK, W25Q32FVSSIG, DS1086LU+T and FT232H. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.
From the MifralTech/Lacerta_CF repository on GitHub, at the commit this page was made from: the board is PCB/Lacerta_v2_1.kicad_pcb and its schematic PCB/Lacerta_v2_1.kicad_sch. PCBKit opens the board in the browser, with nothing to install.
Its repository publishes it under the Apache-2.0 licence: you may reuse it on that licence's terms (keep the author's notice, and for a copyleft licence share your changes alike).