Clock Domains
Overview
Clock domains are explicit in JZ-HDL. Registers have a single home domain (the clock they are synchronized to). Direct use of a register across different clock domains is forbidden. The CDC block provides explicit, designer‑declared crossings that create safe, compiler‑understood synchronized views of register values between domains.
Key goals:
- Make cross‑domain behavior explicit and auditable.
- Prevent accidental multi‑domain register usage.
- Let the compiler enforce domain locality and generate appropriate synchronizer structures.
Syntax
CDC entries appear inside a module body in a CDC { ... } block.
Basic form:
text
CDC {
<cdc_type>[n_stages] <source_reg> (<src_clk>) => <dest_alias> (<dest_clk>);
...
}cdc_typeis one of:BIT,BUS,FIFO,HANDSHAKE,PULSE,MCP,RAW[n_stages]optional positive integer; default = 2 (must NOT be provided forRAW)source_reg: aREGISTERidentifier defined in the same module (plain name, no slices/concat)(src_clk): clock identifier for the source/home domain (must match aSYNCHRONOUSblockCLKor a top-level clock input)=> dest_alias (dest_clk): creates a read‑only alias visible in the destination clock domain
Examples:
text
CDC {
BIT status_sync (clk_io) => cpu_status (clk_cpu);
BUS[3] flags_bus (clk_a) => flags_view (clk_b);
FIFO[4] payload (clk_prod) => consumer_view (clk_cons);
}Semantics
- The CDC entry sets the home clock domain of the source register to
src_clk. - The dest alias is a read‑only signal that represents the synchronized view of the source register after approximately
n_stagescycles in the destination clock. - The source register may only be read/written in
SYNCHRONOUSblocks whoseCLKequalssrc_clk(its home domain). - The dest alias may only be read in
SYNCHRONOUSblocks whoseCLKequalsdest_clk. It can also be read combinationally inASYNCHRONOUSblocks, but that combinational use must respect domain semantics (see "Usage Notes"). - The compiler elaborates the
CDCentry into appropriate synchronization hardware:BIT[n]: N-stage single-bit flip-flop synchronizer. The source register must have width [1] — using BIT with a multi-bit register is a compile error (CDC_BIT_WIDTH_NOT_1).BUS[n]: Multi‑bit synchronized path; intended only when the source follows Gray‑code or single‑bit change discipline.FIFO[n]: Asynchronous FIFO for arbitrary multi‑bit transfers (handles wide or multi‑bit simultaneous changes safely).HANDSHAKE[n]: Req/ack handshake protocol for infrequent multi‑bit transfers.PULSE[n]: Toggle-based pulse synchronizer. The source register must have width [1] — using PULSE with a multi-bit register is a compile error (CDC_PULSE_WIDTH_NOT_1).MCP[n]: Multi‑cycle path formulation for stable multi‑bit data.RAW: Direct unsynchronized wire connection (no crossing logic).
CDC Types and Intended Use
BIT[n_stages]
- Use for single‑bit control/status signals.
- Result
dest_aliaswidth: 1. n_stagestypically 2 or 3 in practice.- Latency: exactly
n_stagescycles ofdest_clk.
BUS[n_stages]
- Use for multi‑bit values that change in a safe, bounded way (e.g., Gray‑encoded counters, handshaked state encodings where only one bit flips at a time).
- Not safe for arbitrary parallel changes (multi‑bit updates).
- If source can change arbitrarily, prefer
FIFO. - Latency: exactly
n_stagescycles ofdest_clk.
FIFO[n_stages]
- Use for arbitrary multi‑bit transfers (data buses, registers updated with new values every cycle).
- Produces a staged, safe transfer; semantics approximates a buffer or asynchronous FIFO depending on implementation.
- Latency: between 1 cycle (existing data) and
n_stages + 2cycles (fresh write).
HANDSHAKE[n_stages]
- Use for infrequent multi‑bit transfers where throughput is not critical.
- Source latches data and asserts request; destination syncs request, latches data, and asserts ack; source syncs ack and deasserts request.
- Safe for arbitrary data widths.
- Latency: variable depending on clock ratio; transfer completes after full req/ack handshake.
PULSE[n_stages]
- Use for single‑bit pulse events (width == 1 only).
- Source toggles a register on each pulse; destination syncs the toggle and XOR‑detects edges to produce output pulses.
- Latency:
n_stagescycles for pulse detection; one output pulse per input pulse.
MCP[n_stages]
- Multi‑cycle path formulation for stable multi‑bit data transfers.
- Source holds data stable and asserts an enable; destination syncs the enable and samples data when the enable is seen.
- Uses the same req/ack protocol as HANDSHAKE for safe handoff.
- Latency: variable, similar to HANDSHAKE; data held stable during transfer.
RAW
- Direct unsynchronized view — no crossing logic is inserted.
- The destination alias is a direct wire connection (
assign) to the source register. - The
[n_stages]parameter must NOT be provided (compile error if present). - Any register width is allowed.
- Latency: 0 cycles (direct connection).
- Use only when the designer knows the signals are safe (e.g., quasi‑static configuration registers, signals with external synchronization, or signals that are stable at the time of sampling).
- Warning: RAW explicitly opts out of CDC safety guarantees. Metastability protection is the designer's responsibility.
Validation Rules (Compiler Enforced)
- Source register must be a
REGISTERdeclared in the containing module. - Source register identifier must be a plain name (no slices, concatenations, instance-qualified names).
- The
CDCentry establishes the home domain for the source register; that register:- May only be assigned (in
SYNCHRONOUS) inside aSYNCHRONOUSblock whoseCLKequalssrc_clk. - May only be read inside
SYNCHRONOUSblocks whoseCLKequalssrc_clk. - Any attempt to use the source register in a
SYNCHRONOUSblock with a differentCLKis a DOMAIN_CONFLICT error.
- May only be assigned (in
- The dest alias:
- Is created by the compiler as a read‑only signal name (not a register the designer assigns).
- May only be read in
SYNCHRONOUSblocks whoseCLKequalsdest_clk. - Attempting to assign to the dest alias is a compile error.
- A module may have at most one
SYNCHRONOUSblock per unique clock signal. (See SYNCHRONOUS block rules.) - Multiple CDC entries may declare crossings between the same pair of clocks or different clocks; each source register's home domain is set by its CORESCDC entry.
- If a register is referenced by a CDC entry, that CDC entry must appear before any
SYNCHRONOUSblock that uses the alias or the source register (tool-specific ordering rule for resolvability). - For
BUS[n_stages], compiler may generate warnings if it detects potential multi‑bit simultaneous changes that violate Gray‑code assumptions (static/flow analysis best‑effort).
Usage Notes
- The
CDCblock does not replace proper CDC design discipline; it documents intent and enables the toolchain to synthesize correct synchronizers and raise violations. - The destination alias is an explicit name you should use in the destination domain's synchronous logic, not the source register name.
- Correct:
IF (cpu_status) { ... }wherecpu_statusisdest_alias. - Incorrect: reading
status_reginsideCLK=cpu_clkwhenstatus_regis home toclk_io.
- Correct:
dest_aliasis visible combinationally inASYNCHRONOUSblocks, but be careful: combinational logic that mixesdest_aliaswith signals from the destination clock domain should not be used to create cross‑domain control paths (avoid asynchronous handshakes without explicit synchronizers).- If you need to sample a multi‑bit value that changes arbitrarily, use
FIFOto avoid metastability and data corruption. - A single register may have multiple destination aliases to different clocks (fan‑out synchronization to multiple domains).
Examples
Single‑bit synchronizer (BIT, 2 stages default)
A 1‑bit event_flag is written in the clk_a domain and read via the synchronized alias event_flag_sync in the clk_b domain. The compiler inserts a 2‑stage flip‑flop chain.
jz
// CDC BIT example: single-bit synchronizer (2 stages default)
//
// Demonstrates crossing a 1-bit flag from clk_a to clk_b.
// The BIT synchronizer inserts a 2-stage flip-flop chain.
@module cdc_bit
PORT {
IN [1] clk_a;
IN [1] clk_b;
IN [1] rst_n;
IN [1] trigger;
OUT [1] led;
}
REGISTER {
event_flag [1] = 1'b0;
cpu_seen [1] = 1'b0;
}
CDC {
BIT event_flag (clk_a) => event_flag_sync (clk_b);
}
ASYNCHRONOUS {
led <= cpu_seen;
}
SYNCHRONOUS(CLK=clk_a RESET=rst_n RESET_ACTIVE=Low) {
IF (trigger) {
event_flag <= 1'b1;
} ELSE {
event_flag <= 1'b0;
}
}
SYNCHRONOUS(CLK=clk_b RESET=rst_n RESET_ACTIVE=Low) {
IF (event_flag_sync) {
cpu_seen <= 1'b1;
} ELSE {
cpu_seen <= 1'b0;
}
}
@endmodjz
@project(CHIP="GW1NR-9-QN88-C6-I5") CDC_BIT_EXAMPLE
@import "cdc_bit.jz"
CLOCKS {
SCLK = { period=37.04 }; // 27MHz
CLK_FAST; // 108MHz (PLL)
}
IN_PINS {
SCLK = { standard=LVCMOS33 };
DONE = { standard=LVCMOS33 };
KEY[2] = { standard=LVCMOS33 };
}
OUT_PINS {
LED[1] = { standard=LVCMOS33, drive=8 };
}
MAP {
SCLK = 52;
KEY[0] = 3;
KEY[1] = 4;
LED[0] = 10;
DONE = IOL14A;
}
CLOCK_GEN {
PLL {
IN REF_CLK SCLK;
OUT BASE CLK_FAST;
CONFIG {
IDIV = 2;
FBDIV = 7;
ODIV = 8;
};
};
}
@top cdc_bit {
IN [1] clk_a = SCLK;
IN [1] clk_b = CLK_FAST;
IN [1] rst_n = KEY[0];
IN [1] trigger = KEY[1];
OUT [1] led = ~LED;
}
@endprojv
// This Verilog was transpiled from JZ-HDL.
// jz-hdl version: Version 0.1.8 (4a569a5)
// Intended for use with yosys.
`default_nettype none
module JZHDL_LIB_CDC_BIT (
clk_dest,
data_in,
data_out
);
// Ports
input clk_dest;
input data_in;
output data_out;
// Signals
reg sync_ff1;
reg sync_ff2;
assign data_out = sync_ff2;
always @(posedge clk_dest) begin
sync_ff1 <= data_in;
sync_ff2 <= sync_ff1;
end
endmodule
module cdc_bit (
clk_a,
clk_b,
rst_n,
trigger,
led
);
// Ports
input clk_a;
input clk_b;
input rst_n;
input trigger;
output reg led;
// Signals
reg event_flag;
reg cpu_seen;
wire event_flag_sync;
JZHDL_LIB_CDC_BIT u_cdc_bit_event_flag_sync (
.clk_dest(clk_b),
.data_in(event_flag),
.data_out(event_flag_sync)
);
always @* begin
led = cpu_seen;
end
always @(posedge clk_a) begin
if (!rst_n) begin
event_flag <= 1'b0;
end
else begin
if (trigger) begin
event_flag <= 1'b1;
end
else begin
event_flag <= 1'b0;
end
end
end
always @(posedge clk_b) begin
if (!rst_n) begin
cpu_seen <= 1'b0;
end
else begin
if (event_flag_sync) begin
cpu_seen <= 1'b1;
end
else begin
cpu_seen <= 1'b0;
end
end
end
endmodule
module top (
SCLK,
DONE,
KEY,
LED
);
input SCLK;
input DONE;
input [1:0] KEY;
output LED;
// Top-level logical→physical pin mapping
// cdc_bit.clk_a -> SCLK (board 52)
// cdc_bit.clk_b -> CLK_FAST (clock gen)
// cdc_bit.rst_n -> KEY[0] (board 3)
// cdc_bit.trigger -> KEY[1] (board 4)
// cdc_bit.led -> LED[0] (board 10)
wire jz_inv_led;
assign LED[0] = ~jz_inv_led;
wire CLK_FAST;
wire jz_unused_pll_LOCK_cg0_u0;
wire jz_unused_pll_PHASE_cg0_u0;
wire jz_unused_pll_DIV_cg0_u0;
wire jz_unused_pll_DIV3_cg0_u0;
// CLOCK_GEN PLL instantiation (from chip data)
rPLL #(
.DEVICE("GW1N-9C"), // Specify your device
.FCLKIN("26.998"), // Input frequency in MHz
.IDIV_SEL(2), // IDIV: Input divider
.FBDIV_SEL(7), // FBDIV: Feedback divider
.ODIV_SEL(8), // ODIV: Output divider
.PSDA_SEL("0000"),
.DUTYDA_SEL("1000"),
.DYN_IDIV_SEL("FALSE"),
.DYN_FBDIV_SEL("FALSE"),
.DYN_ODIV_SEL("FALSE"),
.DYN_DA_EN("FALSE"),
.DYN_SDIV_SEL(2),
.CLKOUT_FT_DIR(1'b1),
.CLKOUTP_FT_DIR(1'b1),
.CLKOUT_DLY_STEP(0),
.CLKOUTP_DLY_STEP(0),
.CLKFB_SEL("internal"),
.CLKOUT_BYPASS("FALSE"),
.CLKOUTP_BYPASS("FALSE"),
.CLKOUTD_BYPASS("FALSE"),
.CLKOUTD_SRC("CLKOUT"),
.CLKOUTD3_SRC("CLKOUT")
) u_pll_0_0 (
.CLKOUT(CLK_FAST), // Primary output
.LOCK(jz_unused_pll_LOCK_cg0_u0), // High when stable
.CLKOUTP(jz_unused_pll_PHASE_cg0_u0), // Phase shifted output
.CLKOUTD(jz_unused_pll_DIV_cg0_u0), // Divided output
.CLKOUTD3(jz_unused_pll_DIV3_cg0_u0), // Divided by 3 output
.RESET(1'b0), // Reset signal
.RESET_P(1'b0), // PLL power down
.CLKIN(SCLK), // Reference clock input
.CLKFB(1'b0) // External feedback
);
cdc_bit u_top (
.clk_a(SCLK),
.clk_b(CLK_FAST),
.rst_n(KEY[0]),
.trigger(KEY[1]),
.led(jz_inv_led)
);
endmoduleil
# Generated by jz-hdl RTLIL backend
# jz-hdl version: Version 0.1.8 (4a569a5)
attribute \src "unknown:1"
module \JZHDL_LIB_CDC_BIT
wire width 1 input 1 \clk_dest
wire width 1 input 2 \data_in
wire width 1 output 3 \data_out
wire width 1 \sync_ff1
wire width 1 \sync_ff2
connect \data_out \sync_ff2
wire $0\sync_ff1[0:0]
wire $0\sync_ff2[0:0]
process $proc$clk0$1
assign $0\sync_ff1[0:0] \sync_ff1
assign $0\sync_ff2[0:0] \sync_ff2
assign $0\sync_ff1[0:0] \data_in
assign $0\sync_ff2[0:0] \sync_ff1
sync posedge \clk_dest
update \sync_ff1 $0\sync_ff1[0:0]
update \sync_ff2 $0\sync_ff2[0:0]
end
end
attribute \src "jz-hdl:6"
module \cdc_bit
wire width 1 input 1 \clk_a
wire width 1 input 2 \clk_b
wire width 1 input 3 \rst_n
wire width 1 input 4 \trigger
wire width 1 output 5 \led
wire width 1 \event_flag
wire width 1 \cpu_seen
wire width 1 \event_flag_sync
cell \JZHDL_LIB_CDC_BIT \u_cdc_bit_event_flag_sync
connect \clk_dest \clk_b
connect \data_in \event_flag
connect \data_out \event_flag_sync
end
wire $0\led[0:0]
process $proc$async$2
assign $0\led[0:0] \cpu_seen
sync always
update \led $0\led[0:0]
end
wire $0\event_flag[0:0]
wire width 1 $auto$3
cell $logic_not $auto$4
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \Y_WIDTH 1
connect \A \rst_n
connect \Y $auto$3
end
process $proc$clk0$5
assign $0\event_flag[0:0] \event_flag
switch $auto$3
case 1'1
assign $0\event_flag[0:0] 1'0
case
switch \trigger
case 1'1
assign $0\event_flag[0:0] 1'1
case
assign $0\event_flag[0:0] 1'0
end
end
sync posedge \clk_a
update \event_flag $0\event_flag[0:0]
end
wire $0\cpu_seen[0:0]
wire width 1 $auto$6
cell $logic_not $auto$7
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \Y_WIDTH 1
connect \A \rst_n
connect \Y $auto$6
end
process $proc$clk1$8
assign $0\cpu_seen[0:0] \cpu_seen
switch $auto$6
case 1'1
assign $0\cpu_seen[0:0] 1'0
case
switch \event_flag_sync
case 1'1
assign $0\cpu_seen[0:0] 1'1
case
assign $0\cpu_seen[0:0] 1'0
end
end
sync posedge \clk_b
update \cpu_seen $0\cpu_seen[0:0]
end
end
attribute \top 1
module \top
wire width 1 input 1 \SCLK
wire width 1 input 2 \DONE
wire width 2 input 3 \KEY
wire width 1 output 4 \LED
wire width 1 \CLK_FAST
wire width 1 \jz_unused_pll_LOCK_cg0_u0
wire width 1 \jz_unused_pll_PHASE_cg0_u0
wire width 1 \jz_unused_pll_DIV_cg0_u0
wire width 1 \jz_unused_pll_DIV3_cg0_u0
cell \rPLL $auto$0_0
parameter \DEVICE "GW1N-9C"
parameter \FCLKIN "26.998"
parameter \IDIV_SEL 2
parameter \FBDIV_SEL 7
parameter \ODIV_SEL 8
parameter \PSDA_SEL "0000"
parameter \DUTYDA_SEL "1000"
parameter \DYN_IDIV_SEL "FALSE"
parameter \DYN_FBDIV_SEL "FALSE"
parameter \DYN_ODIV_SEL "FALSE"
parameter \DYN_DA_EN "FALSE"
parameter \DYN_SDIV_SEL 2
parameter \CLKOUT_FT_DIR 1
parameter \CLKOUTP_FT_DIR 1
parameter \CLKOUT_DLY_STEP 0
parameter \CLKOUTP_DLY_STEP 0
parameter \CLKFB_SEL "internal"
parameter \CLKOUT_BYPASS "FALSE"
parameter \CLKOUTP_BYPASS "FALSE"
parameter \CLKOUTD_BYPASS "FALSE"
parameter \CLKOUTD_SRC "CLKOUT"
parameter \CLKOUTD3_SRC "CLKOUT"
connect \CLKIN \SCLK
connect \CLKOUT \CLK_FAST
connect \LOCK \jz_unused_pll_LOCK_cg0_u0
connect \CLKOUTP \jz_unused_pll_PHASE_cg0_u0
connect \CLKOUTD \jz_unused_pll_DIV_cg0_u0
connect \CLKOUTD3 \jz_unused_pll_DIV3_cg0_u0
connect \RESET 1'0
connect \RESET_P 1'0
connect \CLKFB 1'0
end
wire \jz_inv_led
cell $not $auto$9
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \Y_WIDTH 1
connect \A \jz_inv_led
connect \Y \LED [0]
end
cell \cdc_bit \u_top
connect \clk_a \SCLK
connect \clk_b \CLK_FAST
connect \rst_n \KEY [0]
connect \trigger \KEY [1]
connect \led \jz_inv_led
end
endMulti‑bit Gray‑code bus (BUS, 3 stages)
An 8‑bit gray_ptr register crosses from clk_a to clk_b using a 3‑stage BUS synchronizer. This is safe only when the source follows Gray‑code or single‑bit‑change discipline.
jz
// CDC BUS example: multi-bit Gray-code synchronizer (3 stages)
//
// Demonstrates crossing an 8-bit Gray-coded pointer from clk_a to clk_b.
// The BUS synchronizer safely transfers multi-bit values that follow
// Gray-code discipline (only one bit changes at a time).
@module cdc_bus
PORT {
IN [1] clk_a;
IN [1] clk_b;
IN [1] rst_n;
OUT [6] leds;
}
REGISTER {
gray_ptr [8] = 8'h00;
read_ptr [8] = 8'h00;
}
CDC {
BUS[3] gray_ptr (clk_a) => gray_ptr_sync (clk_b);
}
ASYNCHRONOUS {
leds <= read_ptr[5:0];
}
SYNCHRONOUS(CLK=clk_a RESET=rst_n RESET_ACTIVE=Low) {
gray_ptr <= gray_ptr + 8'h01;
}
SYNCHRONOUS(CLK=clk_b RESET=rst_n RESET_ACTIVE=Low) {
read_ptr <= gray_ptr_sync;
}
@endmodjz
@project(CHIP="GW1NR-9-QN88-C6-I5") CDC_BUS_EXAMPLE
@import "cdc_bus.jz"
CLOCKS {
SCLK = { period=37.04 }; // 27MHz
CLK_FAST; // 108MHz (PLL)
}
IN_PINS {
SCLK = { standard=LVCMOS33 };
DONE = { standard=LVCMOS33 };
KEY[1] = { standard=LVCMOS33 };
}
OUT_PINS {
LED[6] = { standard=LVCMOS33, drive=8 };
}
MAP {
SCLK = 52;
KEY[0] = 3;
LED[0] = 10;
LED[1] = 11;
LED[2] = 13;
LED[3] = 14;
LED[4] = 15;
LED[5] = 16;
DONE = IOL14A;
}
CLOCK_GEN {
PLL {
IN REF_CLK SCLK;
OUT BASE CLK_FAST;
CONFIG {
IDIV = 2;
FBDIV = 7;
ODIV = 8;
};
};
}
@top cdc_bus {
IN [1] clk_a = SCLK;
IN [1] clk_b = CLK_FAST;
IN [1] rst_n = KEY[0];
OUT [6] leds = ~LED;
}
@endprojv
// This Verilog was transpiled from JZ-HDL.
// jz-hdl version: Version 0.1.8 (4a569a5)
// Intended for use with yosys.
`default_nettype none
module JZHDL_LIB_CDC_BUS__W8 (
clk_src,
clk_dest,
data_in,
data_out
);
// Ports
input clk_src;
input clk_dest;
input [7:0] data_in;
output reg [7:0] data_out;
// Signals
reg [7:0] gray_src;
reg [7:0] gray_sync1;
reg [7:0] gray_sync2;
always @* begin
data_out[7] = gray_sync2[7];
data_out[6] = data_out[7] ^ gray_sync2[6];
data_out[5] = data_out[6] ^ gray_sync2[5];
data_out[4] = data_out[5] ^ gray_sync2[4];
data_out[3] = data_out[4] ^ gray_sync2[3];
data_out[2] = data_out[3] ^ gray_sync2[2];
data_out[1] = data_out[2] ^ gray_sync2[1];
data_out[0] = data_out[1] ^ gray_sync2[0];
end
always @(posedge clk_src) begin
gray_src <= data_in >> 8'b00000001 ^ data_in;
end
always @(posedge clk_dest) begin
gray_sync1 <= gray_src;
gray_sync2 <= gray_sync1;
end
endmodule
module cdc_bus (
clk_a,
clk_b,
rst_n,
leds
);
// Ports
input clk_a;
input clk_b;
input rst_n;
output reg [5:0] leds;
// Signals
reg [7:0] gray_ptr;
reg [7:0] read_ptr;
wire [7:0] gray_ptr_sync;
JZHDL_LIB_CDC_BUS__W8 u_cdc_bus_gray_ptr_sync (
.clk_src(clk_a),
.clk_dest(clk_b),
.data_in(gray_ptr),
.data_out(gray_ptr_sync)
);
always @* begin
leds = read_ptr[5:0];
end
always @(posedge clk_a) begin
if (!rst_n) begin
gray_ptr <= 8'b00000000;
end
else begin
gray_ptr <= gray_ptr + 8'b00000001;
end
end
always @(posedge clk_b) begin
if (!rst_n) begin
read_ptr <= 8'b00000000;
end
else begin
read_ptr <= gray_ptr_sync;
end
end
endmodule
module top (
SCLK,
DONE,
KEY,
LED
);
input SCLK;
input DONE;
input KEY;
output [5:0] LED;
// Top-level logical→physical pin mapping
// cdc_bus.clk_a -> SCLK (board 52)
// cdc_bus.clk_b -> CLK_FAST (clock gen)
// cdc_bus.rst_n -> KEY[0] (board 3)
// cdc_bus.leds[5] -> LED[5] (board 16)
// cdc_bus.leds[4] -> LED[4] (board 15)
// cdc_bus.leds[3] -> LED[3] (board 14)
// cdc_bus.leds[2] -> LED[2] (board 13)
// cdc_bus.leds[1] -> LED[1] (board 11)
// cdc_bus.leds[0] -> LED[0] (board 10)
wire [5:0] jz_inv_leds;
assign LED[5] = ~jz_inv_leds[5];
assign LED[4] = ~jz_inv_leds[4];
assign LED[3] = ~jz_inv_leds[3];
assign LED[2] = ~jz_inv_leds[2];
assign LED[1] = ~jz_inv_leds[1];
assign LED[0] = ~jz_inv_leds[0];
wire CLK_FAST;
wire jz_unused_pll_LOCK_cg0_u0;
wire jz_unused_pll_PHASE_cg0_u0;
wire jz_unused_pll_DIV_cg0_u0;
wire jz_unused_pll_DIV3_cg0_u0;
// CLOCK_GEN PLL instantiation (from chip data)
rPLL #(
.DEVICE("GW1N-9C"), // Specify your device
.FCLKIN("26.998"), // Input frequency in MHz
.IDIV_SEL(2), // IDIV: Input divider
.FBDIV_SEL(7), // FBDIV: Feedback divider
.ODIV_SEL(8), // ODIV: Output divider
.PSDA_SEL("0000"),
.DUTYDA_SEL("1000"),
.DYN_IDIV_SEL("FALSE"),
.DYN_FBDIV_SEL("FALSE"),
.DYN_ODIV_SEL("FALSE"),
.DYN_DA_EN("FALSE"),
.DYN_SDIV_SEL(2),
.CLKOUT_FT_DIR(1'b1),
.CLKOUTP_FT_DIR(1'b1),
.CLKOUT_DLY_STEP(0),
.CLKOUTP_DLY_STEP(0),
.CLKFB_SEL("internal"),
.CLKOUT_BYPASS("FALSE"),
.CLKOUTP_BYPASS("FALSE"),
.CLKOUTD_BYPASS("FALSE"),
.CLKOUTD_SRC("CLKOUT"),
.CLKOUTD3_SRC("CLKOUT")
) u_pll_0_0 (
.CLKOUT(CLK_FAST), // Primary output
.LOCK(jz_unused_pll_LOCK_cg0_u0), // High when stable
.CLKOUTP(jz_unused_pll_PHASE_cg0_u0), // Phase shifted output
.CLKOUTD(jz_unused_pll_DIV_cg0_u0), // Divided output
.CLKOUTD3(jz_unused_pll_DIV3_cg0_u0), // Divided by 3 output
.RESET(1'b0), // Reset signal
.RESET_P(1'b0), // PLL power down
.CLKIN(SCLK), // Reference clock input
.CLKFB(1'b0) // External feedback
);
cdc_bus u_top (
.clk_a(SCLK),
.clk_b(CLK_FAST),
.rst_n(KEY[0]),
.leds({jz_inv_leds[5], jz_inv_leds[4], jz_inv_leds[3], jz_inv_leds[2], jz_inv_leds[1], jz_inv_leds[0]})
);
endmoduleil
# Generated by jz-hdl RTLIL backend
# jz-hdl version: Version 0.1.8 (4a569a5)
attribute \src "unknown:1"
module \JZHDL_LIB_CDC_BUS__W8
wire width 1 input 1 \clk_src
wire width 1 input 2 \clk_dest
wire width 8 input 3 \data_in
wire width 8 output 4 \data_out
wire width 8 \gray_src
wire width 8 \gray_sync1
wire width 8 \gray_sync2
wire width 8 $0\data_out[7:0]
wire width 1 $auto$1
cell $xor $auto$2
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \B_SIGNED 0
parameter \B_WIDTH 1
parameter \Y_WIDTH 1
connect \A \data_out [7]
connect \B \gray_sync2 [6]
connect \Y $auto$1
end
wire width 1 $auto$3
cell $xor $auto$4
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \B_SIGNED 0
parameter \B_WIDTH 1
parameter \Y_WIDTH 1
connect \A \data_out [6]
connect \B \gray_sync2 [5]
connect \Y $auto$3
end
wire width 1 $auto$5
cell $xor $auto$6
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \B_SIGNED 0
parameter \B_WIDTH 1
parameter \Y_WIDTH 1
connect \A \data_out [5]
connect \B \gray_sync2 [4]
connect \Y $auto$5
end
wire width 1 $auto$7
cell $xor $auto$8
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \B_SIGNED 0
parameter \B_WIDTH 1
parameter \Y_WIDTH 1
connect \A \data_out [4]
connect \B \gray_sync2 [3]
connect \Y $auto$7
end
wire width 1 $auto$9
cell $xor $auto$10
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \B_SIGNED 0
parameter \B_WIDTH 1
parameter \Y_WIDTH 1
connect \A \data_out [3]
connect \B \gray_sync2 [2]
connect \Y $auto$9
end
wire width 1 $auto$11
cell $xor $auto$12
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \B_SIGNED 0
parameter \B_WIDTH 1
parameter \Y_WIDTH 1
connect \A \data_out [2]
connect \B \gray_sync2 [1]
connect \Y $auto$11
end
wire width 1 $auto$13
cell $xor $auto$14
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \B_SIGNED 0
parameter \B_WIDTH 1
parameter \Y_WIDTH 1
connect \A \data_out [1]
connect \B \gray_sync2 [0]
connect \Y $auto$13
end
process $proc$async$15
assign $0\data_out[7:0] [7] \gray_sync2 [7]
assign $0\data_out[7:0] [6] $auto$1
assign $0\data_out[7:0] [5] $auto$3
assign $0\data_out[7:0] [4] $auto$5
assign $0\data_out[7:0] [3] $auto$7
assign $0\data_out[7:0] [2] $auto$9
assign $0\data_out[7:0] [1] $auto$11
assign $0\data_out[7:0] [0] $auto$13
sync always
update \data_out $0\data_out[7:0]
end
wire width 8 $0\gray_src[7:0]
wire width 8 $auto$16
cell $shr $auto$17
parameter \A_SIGNED 0
parameter \A_WIDTH 8
parameter \B_SIGNED 0
parameter \B_WIDTH 8
parameter \Y_WIDTH 8
connect \A \data_in
connect \B 8'00000001
connect \Y $auto$16
end
wire width 8 $auto$18
cell $xor $auto$19
parameter \A_SIGNED 0
parameter \A_WIDTH 8
parameter \B_SIGNED 0
parameter \B_WIDTH 8
parameter \Y_WIDTH 8
connect \A $auto$16
connect \B \data_in
connect \Y $auto$18
end
process $proc$clk0$20
assign $0\gray_src[7:0] \gray_src
assign $0\gray_src[7:0] $auto$18
sync posedge \clk_src
update \gray_src $0\gray_src[7:0]
end
wire width 8 $0\gray_sync1[7:0]
wire width 8 $0\gray_sync2[7:0]
process $proc$clk1$21
assign $0\gray_sync1[7:0] \gray_sync1
assign $0\gray_sync2[7:0] \gray_sync2
assign $0\gray_sync1[7:0] \gray_src
assign $0\gray_sync2[7:0] \gray_sync1
sync posedge \clk_dest
update \gray_sync1 $0\gray_sync1[7:0]
update \gray_sync2 $0\gray_sync2[7:0]
end
end
attribute \src "jz-hdl:7"
module \cdc_bus
wire width 1 input 1 \clk_a
wire width 1 input 2 \clk_b
wire width 1 input 3 \rst_n
wire width 6 output 4 \leds
wire width 8 \gray_ptr
wire width 8 \read_ptr
wire width 8 \gray_ptr_sync
cell \JZHDL_LIB_CDC_BUS__W8 \u_cdc_bus_gray_ptr_sync
connect \clk_src \clk_a
connect \clk_dest \clk_b
connect \data_in \gray_ptr
connect \data_out \gray_ptr_sync
end
wire width 6 $0\leds[5:0]
process $proc$async$22
assign $0\leds[5:0] \read_ptr [5:0]
sync always
update \leds $0\leds[5:0]
end
wire width 8 $0\gray_ptr[7:0]
wire width 1 $auto$23
cell $logic_not $auto$24
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \Y_WIDTH 1
connect \A \rst_n
connect \Y $auto$23
end
wire width 8 $auto$25
cell $add $auto$26
parameter \A_SIGNED 0
parameter \A_WIDTH 8
parameter \B_SIGNED 0
parameter \B_WIDTH 8
parameter \Y_WIDTH 8
connect \A \gray_ptr
connect \B 8'00000001
connect \Y $auto$25
end
process $proc$clk0$27
assign $0\gray_ptr[7:0] \gray_ptr
switch $auto$23
case 1'1
assign $0\gray_ptr[7:0] 8'00000000
case
assign $0\gray_ptr[7:0] $auto$25
end
sync posedge \clk_a
update \gray_ptr $0\gray_ptr[7:0]
end
wire width 8 $0\read_ptr[7:0]
wire width 1 $auto$28
cell $logic_not $auto$29
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \Y_WIDTH 1
connect \A \rst_n
connect \Y $auto$28
end
process $proc$clk1$30
assign $0\read_ptr[7:0] \read_ptr
switch $auto$28
case 1'1
assign $0\read_ptr[7:0] 8'00000000
case
assign $0\read_ptr[7:0] \gray_ptr_sync
end
sync posedge \clk_b
update \read_ptr $0\read_ptr[7:0]
end
end
attribute \top 1
module \top
wire width 1 input 1 \SCLK
wire width 1 input 2 \DONE
wire width 1 input 3 \KEY
wire width 6 output 4 \LED
wire width 1 \CLK_FAST
wire width 1 \jz_unused_pll_LOCK_cg0_u0
wire width 1 \jz_unused_pll_PHASE_cg0_u0
wire width 1 \jz_unused_pll_DIV_cg0_u0
wire width 1 \jz_unused_pll_DIV3_cg0_u0
cell \rPLL $auto$0_0
parameter \DEVICE "GW1N-9C"
parameter \FCLKIN "26.998"
parameter \IDIV_SEL 2
parameter \FBDIV_SEL 7
parameter \ODIV_SEL 8
parameter \PSDA_SEL "0000"
parameter \DUTYDA_SEL "1000"
parameter \DYN_IDIV_SEL "FALSE"
parameter \DYN_FBDIV_SEL "FALSE"
parameter \DYN_ODIV_SEL "FALSE"
parameter \DYN_DA_EN "FALSE"
parameter \DYN_SDIV_SEL 2
parameter \CLKOUT_FT_DIR 1
parameter \CLKOUTP_FT_DIR 1
parameter \CLKOUT_DLY_STEP 0
parameter \CLKOUTP_DLY_STEP 0
parameter \CLKFB_SEL "internal"
parameter \CLKOUT_BYPASS "FALSE"
parameter \CLKOUTP_BYPASS "FALSE"
parameter \CLKOUTD_BYPASS "FALSE"
parameter \CLKOUTD_SRC "CLKOUT"
parameter \CLKOUTD3_SRC "CLKOUT"
connect \CLKIN \SCLK
connect \CLKOUT \CLK_FAST
connect \LOCK \jz_unused_pll_LOCK_cg0_u0
connect \CLKOUTP \jz_unused_pll_PHASE_cg0_u0
connect \CLKOUTD \jz_unused_pll_DIV_cg0_u0
connect \CLKOUTD3 \jz_unused_pll_DIV3_cg0_u0
connect \RESET 1'0
connect \RESET_P 1'0
connect \CLKFB 1'0
end
cell \cdc_bus \u_top
connect \clk_a \SCLK
connect \clk_b \CLK_FAST
connect \rst_n \KEY [0]
connect \leds { \LED [5] \LED [4] \LED [3] \LED [2] \LED [1] \LED [0] }
end
endWide arbitrary data via FIFO (FIFO, 4 stages)
A 64‑bit packet_word register crosses from clk_a to clk_b using a 4‑stage FIFO synchronizer. Unlike BUS, FIFO handles arbitrary multi‑bit changes safely.
jz
// CDC FIFO example: wide arbitrary data transfer (4 stages)
//
// Demonstrates crossing a 64-bit data word from clk_a to clk_b.
// The FIFO synchronizer handles arbitrary multi-bit changes safely,
// unlike BUS which requires Gray-code discipline.
@module cdc_fifo
PORT {
IN [1] clk_a;
IN [1] clk_b;
IN [1] rst_n;
OUT [6] leds;
}
REGISTER {
packet_word [64] = 64'h0000_0000_0000_0000;
data_out [64] = 64'h0000_0000_0000_0000;
}
CDC {
FIFO[4] packet_word (clk_a) => packet_view (clk_b);
}
ASYNCHRONOUS {
leds <= data_out[5:0];
}
SYNCHRONOUS(CLK=clk_a RESET=rst_n RESET_ACTIVE=Low) {
packet_word <= packet_word + 64'h0000_0000_0000_0001;
}
SYNCHRONOUS(CLK=clk_b RESET=rst_n RESET_ACTIVE=Low) {
data_out <= packet_view;
}
@endmodjz
@project(CHIP="GW1NR-9-QN88-C6-I5") CDC_FIFO_EXAMPLE
@import "cdc_fifo.jz"
CLOCKS {
SCLK = { period=37.04 }; // 27MHz
CLK_FAST; // 108MHz (PLL)
}
IN_PINS {
SCLK = { standard=LVCMOS33 };
DONE = { standard=LVCMOS33 };
KEY[1] = { standard=LVCMOS33 };
}
OUT_PINS {
LED[6] = { standard=LVCMOS33, drive=8 };
}
MAP {
SCLK = 52;
KEY[0] = 3;
LED[0] = 10;
LED[1] = 11;
LED[2] = 13;
LED[3] = 14;
LED[4] = 15;
LED[5] = 16;
DONE = IOL14A;
}
CLOCK_GEN {
PLL {
IN REF_CLK SCLK;
OUT BASE CLK_FAST;
CONFIG {
IDIV = 2;
FBDIV = 7;
ODIV = 8;
};
};
}
@top cdc_fifo {
IN [1] clk_a = SCLK;
IN [1] clk_b = CLK_FAST;
IN [1] rst_n = KEY[0];
OUT [6] leds = ~LED;
}
@endprojv
// This Verilog was transpiled from JZ-HDL.
// jz-hdl version: Version 0.1.8 (4a569a5)
// Intended for use with yosys.
`default_nettype none
module JZHDL_LIB_CDC_FIFO__W64 (
clk_wr,
clk_rd,
rst_wr,
rst_rd,
data_in,
write_en,
read_en,
data_out,
full,
empty
);
// Ports
input clk_wr;
input clk_rd;
input rst_wr;
input rst_rd;
input [63:0] data_in;
input write_en;
input read_en;
output [63:0] data_out;
output full;
output empty;
// Signals
reg [4:0] wr_ptr_bin;
reg [4:0] wr_ptr_gray;
reg [4:0] rd_ptr_bin;
reg [4:0] rd_ptr_gray;
reg [4:0] wr_ptr_gray_sync1;
reg [4:0] wr_ptr_gray_sync2;
reg [4:0] rd_ptr_gray_sync1;
reg [4:0] rd_ptr_gray_sync2;
// Memories
(* ram_style = "distributed" *) reg [63:0] mem[0:15];
assign data_out = mem[rd_ptr_bin[3:0]];
assign full = wr_ptr_gray == {~rd_ptr_gray_sync2[4:3], rd_ptr_gray_sync2[2:0]};
assign empty = rd_ptr_gray == wr_ptr_gray_sync2;
always @(posedge clk_wr or posedge rst_wr) begin
if (rst_wr) begin
wr_ptr_bin <= 5'b00000;
wr_ptr_gray <= 5'b00000;
end
else begin
if (write_en && ~full) begin
mem[wr_ptr_bin[3:0]] <= data_in;
wr_ptr_bin <= wr_ptr_bin + 5'b00001;
wr_ptr_gray <= wr_ptr_bin + 5'b00001 >> 5'b00001 ^ wr_ptr_bin + 5'b00001;
end
end
end
always @(posedge clk_rd or posedge rst_rd) begin
if (rst_rd) begin
rd_ptr_bin <= 5'b00000;
rd_ptr_gray <= 5'b00000;
end
else begin
if (read_en && ~empty) begin
rd_ptr_bin <= rd_ptr_bin + 5'b00001;
rd_ptr_gray <= rd_ptr_bin + 5'b00001 >> 5'b00001 ^ rd_ptr_bin + 5'b00001;
end
end
end
always @(posedge clk_wr or posedge rst_wr) begin
if (rst_wr) begin
rd_ptr_gray_sync1 <= 5'b00000;
rd_ptr_gray_sync2 <= 5'b00000;
end
else begin
rd_ptr_gray_sync1 <= rd_ptr_gray;
rd_ptr_gray_sync2 <= rd_ptr_gray_sync1;
end
end
always @(posedge clk_rd or posedge rst_rd) begin
if (rst_rd) begin
wr_ptr_gray_sync1 <= 5'b00000;
wr_ptr_gray_sync2 <= 5'b00000;
end
else begin
wr_ptr_gray_sync1 <= wr_ptr_gray;
wr_ptr_gray_sync2 <= wr_ptr_gray_sync1;
end
end
endmodule
module cdc_fifo (
clk_a,
clk_b,
rst_n,
leds
);
// Ports
input clk_a;
input clk_b;
input rst_n;
output reg [5:0] leds;
// Signals
reg [63:0] packet_word;
reg [63:0] data_out;
wire [63:0] packet_view;
wire _fifo_packet_view_wr_en;
wire _fifo_packet_view_rst_wr;
wire _fifo_packet_view_rst_rd;
assign _fifo_packet_view_wr_en = !rst_n || 1'b1;
assign _fifo_packet_view_rst_wr = ~rst_n;
assign _fifo_packet_view_rst_rd = ~rst_n;
JZHDL_LIB_CDC_FIFO__W64 u_cdc_fifo_packet_view (
.clk_wr(clk_a),
.clk_rd(clk_b),
.rst_wr(_fifo_packet_view_rst_wr),
.rst_rd(_fifo_packet_view_rst_rd),
.data_in(packet_word),
.write_en(_fifo_packet_view_wr_en),
.read_en(1'b1),
.data_out(packet_view)
);
always @* begin
leds = data_out[5:0];
end
always @(posedge clk_a) begin
if (!rst_n) begin
packet_word <= 64'b0000000000000000000000000000000000000000000000000000000000000000;
end
else begin
packet_word <= packet_word + 64'b0000000000000000000000000000000000000000000000000000000000000001;
end
end
always @(posedge clk_b) begin
if (!rst_n) begin
data_out <= 64'b0000000000000000000000000000000000000000000000000000000000000000;
end
else begin
data_out <= packet_view;
end
end
endmodule
module top (
SCLK,
DONE,
KEY,
LED
);
input SCLK;
input DONE;
input KEY;
output [5:0] LED;
// Top-level logical→physical pin mapping
// cdc_fifo.clk_a -> SCLK (board 52)
// cdc_fifo.clk_b -> CLK_FAST (clock gen)
// cdc_fifo.rst_n -> KEY[0] (board 3)
// cdc_fifo.leds[5] -> LED[5] (board 16)
// cdc_fifo.leds[4] -> LED[4] (board 15)
// cdc_fifo.leds[3] -> LED[3] (board 14)
// cdc_fifo.leds[2] -> LED[2] (board 13)
// cdc_fifo.leds[1] -> LED[1] (board 11)
// cdc_fifo.leds[0] -> LED[0] (board 10)
wire [5:0] jz_inv_leds;
assign LED[5] = ~jz_inv_leds[5];
assign LED[4] = ~jz_inv_leds[4];
assign LED[3] = ~jz_inv_leds[3];
assign LED[2] = ~jz_inv_leds[2];
assign LED[1] = ~jz_inv_leds[1];
assign LED[0] = ~jz_inv_leds[0];
wire CLK_FAST;
wire jz_unused_pll_LOCK_cg0_u0;
wire jz_unused_pll_PHASE_cg0_u0;
wire jz_unused_pll_DIV_cg0_u0;
wire jz_unused_pll_DIV3_cg0_u0;
// CLOCK_GEN PLL instantiation (from chip data)
rPLL #(
.DEVICE("GW1N-9C"), // Specify your device
.FCLKIN("26.998"), // Input frequency in MHz
.IDIV_SEL(2), // IDIV: Input divider
.FBDIV_SEL(7), // FBDIV: Feedback divider
.ODIV_SEL(8), // ODIV: Output divider
.PSDA_SEL("0000"),
.DUTYDA_SEL("1000"),
.DYN_IDIV_SEL("FALSE"),
.DYN_FBDIV_SEL("FALSE"),
.DYN_ODIV_SEL("FALSE"),
.DYN_DA_EN("FALSE"),
.DYN_SDIV_SEL(2),
.CLKOUT_FT_DIR(1'b1),
.CLKOUTP_FT_DIR(1'b1),
.CLKOUT_DLY_STEP(0),
.CLKOUTP_DLY_STEP(0),
.CLKFB_SEL("internal"),
.CLKOUT_BYPASS("FALSE"),
.CLKOUTP_BYPASS("FALSE"),
.CLKOUTD_BYPASS("FALSE"),
.CLKOUTD_SRC("CLKOUT"),
.CLKOUTD3_SRC("CLKOUT")
) u_pll_0_0 (
.CLKOUT(CLK_FAST), // Primary output
.LOCK(jz_unused_pll_LOCK_cg0_u0), // High when stable
.CLKOUTP(jz_unused_pll_PHASE_cg0_u0), // Phase shifted output
.CLKOUTD(jz_unused_pll_DIV_cg0_u0), // Divided output
.CLKOUTD3(jz_unused_pll_DIV3_cg0_u0), // Divided by 3 output
.RESET(1'b0), // Reset signal
.RESET_P(1'b0), // PLL power down
.CLKIN(SCLK), // Reference clock input
.CLKFB(1'b0) // External feedback
);
cdc_fifo u_top (
.clk_a(SCLK),
.clk_b(CLK_FAST),
.rst_n(KEY[0]),
.leds({jz_inv_leds[5], jz_inv_leds[4], jz_inv_leds[3], jz_inv_leds[2], jz_inv_leds[1], jz_inv_leds[0]})
);
endmoduleil
# Generated by jz-hdl RTLIL backend
# jz-hdl version: Version 0.1.8 (4a569a5)
attribute \src "unknown:1"
module \JZHDL_LIB_CDC_FIFO__W64
wire width 1 input 1 \clk_wr
wire width 1 input 2 \clk_rd
wire width 1 input 3 \rst_wr
wire width 1 input 4 \rst_rd
wire width 64 input 5 \data_in
wire width 1 input 6 \write_en
wire width 1 input 7 \read_en
wire width 64 output 8 \data_out
wire width 1 output 9 \full
wire width 1 output 10 \empty
wire width 5 \wr_ptr_bin
wire width 5 \wr_ptr_gray
wire width 5 \rd_ptr_bin
wire width 5 \rd_ptr_gray
wire width 5 \wr_ptr_gray_sync1
wire width 5 \wr_ptr_gray_sync2
wire width 5 \rd_ptr_gray_sync1
wire width 5 \rd_ptr_gray_sync2
memory width 64 size 16 \mem
wire width 64 $auto$1
cell $memrd_v2 $auto$2
parameter \MEMID "\\mem"
parameter \ABITS 4
parameter \WIDTH 64
parameter \CLK_ENABLE 0
parameter \CLK_POLARITY 1
parameter \TRANSPARENCY_MASK 0
parameter \COLLISION_X_MASK 0
parameter \CE_OVER_SRST 0
parameter \ARST_VALUE 64'0000000000000000000000000000000000000000000000000000000000000000
parameter \SRST_VALUE 64'0000000000000000000000000000000000000000000000000000000000000000
parameter \INIT_VALUE 64'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
connect \ADDR \rd_ptr_bin [3:0]
connect \DATA $auto$1
connect \EN 1'1
connect \ARST 1'0
connect \SRST 1'0
connect \CLK 1'0
end
connect \data_out $auto$1
wire width 2 $auto$3
cell $not $auto$4
parameter \A_SIGNED 0
parameter \A_WIDTH 2
parameter \Y_WIDTH 2
connect \A \rd_ptr_gray_sync2 [4:3]
connect \Y $auto$3
end
wire width 1 $auto$5
cell $eq $auto$6
parameter \A_SIGNED 0
parameter \A_WIDTH 5
parameter \B_SIGNED 0
parameter \B_WIDTH 5
parameter \Y_WIDTH 1
connect \A \wr_ptr_gray
connect \B { $auto$3 \rd_ptr_gray_sync2 [2:0] }
connect \Y $auto$5
end
connect \full $auto$5
wire width 1 $auto$7
cell $eq $auto$8
parameter \A_SIGNED 0
parameter \A_WIDTH 5
parameter \B_SIGNED 0
parameter \B_WIDTH 5
parameter \Y_WIDTH 1
connect \A \rd_ptr_gray
connect \B \wr_ptr_gray_sync2
connect \Y $auto$7
end
connect \empty $auto$7
wire width 1 $auto$9
cell $not $auto$10
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \Y_WIDTH 1
connect \A \full
connect \Y $auto$9
end
wire width 1 $auto$11
cell $logic_and $auto$12
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \B_SIGNED 0
parameter \B_WIDTH 1
parameter \Y_WIDTH 1
connect \A \write_en
connect \B $auto$9
connect \Y $auto$11
end
cell $memwr_v2 $auto$13
parameter \MEMID "\\mem"
parameter \ABITS 4
parameter \WIDTH 64
parameter \CLK_ENABLE 1
parameter \CLK_POLARITY 1
parameter \PORTID 0
parameter \PRIORITY_MASK 0
connect \ADDR \wr_ptr_bin [3:0]
connect \DATA \data_in
connect \EN { $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 $auto$11 }
connect \CLK \clk_wr
end
wire width 5 $0\wr_ptr_bin[4:0]
wire width 5 $0\wr_ptr_gray[4:0]
wire width 1 $auto$14
cell $not $auto$15
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \Y_WIDTH 1
connect \A \full
connect \Y $auto$14
end
wire width 1 $auto$16
cell $logic_and $auto$17
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \B_SIGNED 0
parameter \B_WIDTH 1
parameter \Y_WIDTH 1
connect \A \write_en
connect \B $auto$14
connect \Y $auto$16
end
wire width 5 $auto$18
cell $add $auto$19
parameter \A_SIGNED 0
parameter \A_WIDTH 5
parameter \B_SIGNED 0
parameter \B_WIDTH 5
parameter \Y_WIDTH 5
connect \A \wr_ptr_bin
connect \B 5'00001
connect \Y $auto$18
end
wire width 5 $auto$20
cell $add $auto$21
parameter \A_SIGNED 0
parameter \A_WIDTH 5
parameter \B_SIGNED 0
parameter \B_WIDTH 5
parameter \Y_WIDTH 5
connect \A \wr_ptr_bin
connect \B 5'00001
connect \Y $auto$20
end
wire width 5 $auto$22
cell $shr $auto$23
parameter \A_SIGNED 0
parameter \A_WIDTH 5
parameter \B_SIGNED 0
parameter \B_WIDTH 5
parameter \Y_WIDTH 5
connect \A $auto$20
connect \B 5'00001
connect \Y $auto$22
end
wire width 5 $auto$24
cell $add $auto$25
parameter \A_SIGNED 0
parameter \A_WIDTH 5
parameter \B_SIGNED 0
parameter \B_WIDTH 5
parameter \Y_WIDTH 5
connect \A \wr_ptr_bin
connect \B 5'00001
connect \Y $auto$24
end
wire width 5 $auto$26
cell $xor $auto$27
parameter \A_SIGNED 0
parameter \A_WIDTH 5
parameter \B_SIGNED 0
parameter \B_WIDTH 5
parameter \Y_WIDTH 5
connect \A $auto$22
connect \B $auto$24
connect \Y $auto$26
end
process $proc$clk0$28
assign $0\wr_ptr_bin[4:0] \wr_ptr_bin
assign $0\wr_ptr_gray[4:0] \wr_ptr_gray
switch \rst_wr
case 1'1
assign $0\wr_ptr_bin[4:0] 5'00000
assign $0\wr_ptr_gray[4:0] 5'00000
case
switch $auto$16
case 1'1
# memory write: mem (handled by $memwr_v2 cell)
assign $0\wr_ptr_bin[4:0] $auto$18
assign $0\wr_ptr_gray[4:0] $auto$26
case
end
end
sync posedge \clk_wr
update \wr_ptr_bin $0\wr_ptr_bin[4:0]
update \wr_ptr_gray $0\wr_ptr_gray[4:0]
sync high \rst_wr
update \wr_ptr_bin 5'00000
update \wr_ptr_gray 5'00000
end
wire width 5 $0\rd_ptr_bin[4:0]
wire width 5 $0\rd_ptr_gray[4:0]
wire width 1 $auto$29
cell $not $auto$30
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \Y_WIDTH 1
connect \A \empty
connect \Y $auto$29
end
wire width 1 $auto$31
cell $logic_and $auto$32
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \B_SIGNED 0
parameter \B_WIDTH 1
parameter \Y_WIDTH 1
connect \A \read_en
connect \B $auto$29
connect \Y $auto$31
end
wire width 5 $auto$33
cell $add $auto$34
parameter \A_SIGNED 0
parameter \A_WIDTH 5
parameter \B_SIGNED 0
parameter \B_WIDTH 5
parameter \Y_WIDTH 5
connect \A \rd_ptr_bin
connect \B 5'00001
connect \Y $auto$33
end
wire width 5 $auto$35
cell $add $auto$36
parameter \A_SIGNED 0
parameter \A_WIDTH 5
parameter \B_SIGNED 0
parameter \B_WIDTH 5
parameter \Y_WIDTH 5
connect \A \rd_ptr_bin
connect \B 5'00001
connect \Y $auto$35
end
wire width 5 $auto$37
cell $shr $auto$38
parameter \A_SIGNED 0
parameter \A_WIDTH 5
parameter \B_SIGNED 0
parameter \B_WIDTH 5
parameter \Y_WIDTH 5
connect \A $auto$35
connect \B 5'00001
connect \Y $auto$37
end
wire width 5 $auto$39
cell $add $auto$40
parameter \A_SIGNED 0
parameter \A_WIDTH 5
parameter \B_SIGNED 0
parameter \B_WIDTH 5
parameter \Y_WIDTH 5
connect \A \rd_ptr_bin
connect \B 5'00001
connect \Y $auto$39
end
wire width 5 $auto$41
cell $xor $auto$42
parameter \A_SIGNED 0
parameter \A_WIDTH 5
parameter \B_SIGNED 0
parameter \B_WIDTH 5
parameter \Y_WIDTH 5
connect \A $auto$37
connect \B $auto$39
connect \Y $auto$41
end
process $proc$clk1$43
assign $0\rd_ptr_bin[4:0] \rd_ptr_bin
assign $0\rd_ptr_gray[4:0] \rd_ptr_gray
switch \rst_rd
case 1'1
assign $0\rd_ptr_bin[4:0] 5'00000
assign $0\rd_ptr_gray[4:0] 5'00000
case
switch $auto$31
case 1'1
assign $0\rd_ptr_bin[4:0] $auto$33
assign $0\rd_ptr_gray[4:0] $auto$41
case
end
end
sync posedge \clk_rd
update \rd_ptr_bin $0\rd_ptr_bin[4:0]
update \rd_ptr_gray $0\rd_ptr_gray[4:0]
sync high \rst_rd
update \rd_ptr_bin 5'00000
update \rd_ptr_gray 5'00000
end
wire width 5 $0\rd_ptr_gray_sync1[4:0]
wire width 5 $0\rd_ptr_gray_sync2[4:0]
process $proc$clk2$44
assign $0\rd_ptr_gray_sync1[4:0] \rd_ptr_gray_sync1
assign $0\rd_ptr_gray_sync2[4:0] \rd_ptr_gray_sync2
switch \rst_wr
case 1'1
assign $0\rd_ptr_gray_sync1[4:0] 5'00000
assign $0\rd_ptr_gray_sync2[4:0] 5'00000
case
assign $0\rd_ptr_gray_sync1[4:0] \rd_ptr_gray
assign $0\rd_ptr_gray_sync2[4:0] \rd_ptr_gray_sync1
end
sync posedge \clk_wr
update \rd_ptr_gray_sync1 $0\rd_ptr_gray_sync1[4:0]
update \rd_ptr_gray_sync2 $0\rd_ptr_gray_sync2[4:0]
sync high \rst_wr
update \rd_ptr_gray_sync1 5'00000
update \rd_ptr_gray_sync2 5'00000
end
wire width 5 $0\wr_ptr_gray_sync1[4:0]
wire width 5 $0\wr_ptr_gray_sync2[4:0]
process $proc$clk3$45
assign $0\wr_ptr_gray_sync1[4:0] \wr_ptr_gray_sync1
assign $0\wr_ptr_gray_sync2[4:0] \wr_ptr_gray_sync2
switch \rst_rd
case 1'1
assign $0\wr_ptr_gray_sync1[4:0] 5'00000
assign $0\wr_ptr_gray_sync2[4:0] 5'00000
case
assign $0\wr_ptr_gray_sync1[4:0] \wr_ptr_gray
assign $0\wr_ptr_gray_sync2[4:0] \wr_ptr_gray_sync1
end
sync posedge \clk_rd
update \wr_ptr_gray_sync1 $0\wr_ptr_gray_sync1[4:0]
update \wr_ptr_gray_sync2 $0\wr_ptr_gray_sync2[4:0]
sync high \rst_rd
update \wr_ptr_gray_sync1 5'00000
update \wr_ptr_gray_sync2 5'00000
end
end
attribute \src "jz-hdl:7"
module \cdc_fifo
wire width 1 input 1 \clk_a
wire width 1 input 2 \clk_b
wire width 1 input 3 \rst_n
wire width 6 output 4 \leds
wire width 64 \packet_word
wire width 64 \data_out
wire width 64 \packet_view
wire width 1 \_fifo_packet_view_wr_en
wire width 1 \_fifo_packet_view_rst_wr
wire width 1 \_fifo_packet_view_rst_rd
wire width 1 $auto$46
cell $logic_not $auto$47
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \Y_WIDTH 1
connect \A \rst_n
connect \Y $auto$46
end
wire width 1 $auto$48
cell $logic_or $auto$49
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \B_SIGNED 0
parameter \B_WIDTH 1
parameter \Y_WIDTH 1
connect \A $auto$46
connect \B 1'1
connect \Y $auto$48
end
connect \_fifo_packet_view_wr_en $auto$48
wire width 1 $auto$50
cell $not $auto$51
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \Y_WIDTH 1
connect \A \rst_n
connect \Y $auto$50
end
connect \_fifo_packet_view_rst_wr $auto$50
wire width 1 $auto$52
cell $not $auto$53
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \Y_WIDTH 1
connect \A \rst_n
connect \Y $auto$52
end
connect \_fifo_packet_view_rst_rd $auto$52
cell \JZHDL_LIB_CDC_FIFO__W64 \u_cdc_fifo_packet_view
connect \clk_wr \clk_a
connect \clk_rd \clk_b
connect \rst_wr \_fifo_packet_view_rst_wr
connect \rst_rd \_fifo_packet_view_rst_rd
connect \data_in \packet_word
connect \write_en \_fifo_packet_view_wr_en
connect \read_en 1'1
connect \data_out \packet_view
end
wire width 6 $0\leds[5:0]
process $proc$async$54
assign $0\leds[5:0] \data_out [5:0]
sync always
update \leds $0\leds[5:0]
end
wire width 64 $0\packet_word[63:0]
wire width 1 $auto$55
cell $logic_not $auto$56
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \Y_WIDTH 1
connect \A \rst_n
connect \Y $auto$55
end
wire width 64 $auto$57
cell $add $auto$58
parameter \A_SIGNED 0
parameter \A_WIDTH 64
parameter \B_SIGNED 0
parameter \B_WIDTH 64
parameter \Y_WIDTH 64
connect \A \packet_word
connect \B 64'0000000000000000000000000000000000000000000000000000000000000001
connect \Y $auto$57
end
process $proc$clk0$59
assign $0\packet_word[63:0] \packet_word
switch $auto$55
case 1'1
assign $0\packet_word[63:0] 64'0000000000000000000000000000000000000000000000000000000000000000
case
assign $0\packet_word[63:0] $auto$57
end
sync posedge \clk_a
update \packet_word $0\packet_word[63:0]
end
wire width 64 $0\data_out[63:0]
wire width 1 $auto$60
cell $logic_not $auto$61
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \Y_WIDTH 1
connect \A \rst_n
connect \Y $auto$60
end
process $proc$clk1$62
assign $0\data_out[63:0] \data_out
switch $auto$60
case 1'1
assign $0\data_out[63:0] 64'0000000000000000000000000000000000000000000000000000000000000000
case
assign $0\data_out[63:0] \packet_view
end
sync posedge \clk_b
update \data_out $0\data_out[63:0]
end
end
attribute \top 1
module \top
wire width 1 input 1 \SCLK
wire width 1 input 2 \DONE
wire width 1 input 3 \KEY
wire width 6 output 4 \LED
wire width 1 \CLK_FAST
wire width 1 \jz_unused_pll_LOCK_cg0_u0
wire width 1 \jz_unused_pll_PHASE_cg0_u0
wire width 1 \jz_unused_pll_DIV_cg0_u0
wire width 1 \jz_unused_pll_DIV3_cg0_u0
cell \rPLL $auto$0_0
parameter \DEVICE "GW1N-9C"
parameter \FCLKIN "26.998"
parameter \IDIV_SEL 2
parameter \FBDIV_SEL 7
parameter \ODIV_SEL 8
parameter \PSDA_SEL "0000"
parameter \DUTYDA_SEL "1000"
parameter \DYN_IDIV_SEL "FALSE"
parameter \DYN_FBDIV_SEL "FALSE"
parameter \DYN_ODIV_SEL "FALSE"
parameter \DYN_DA_EN "FALSE"
parameter \DYN_SDIV_SEL 2
parameter \CLKOUT_FT_DIR 1
parameter \CLKOUTP_FT_DIR 1
parameter \CLKOUT_DLY_STEP 0
parameter \CLKOUTP_DLY_STEP 0
parameter \CLKFB_SEL "internal"
parameter \CLKOUT_BYPASS "FALSE"
parameter \CLKOUTP_BYPASS "FALSE"
parameter \CLKOUTD_BYPASS "FALSE"
parameter \CLKOUTD_SRC "CLKOUT"
parameter \CLKOUTD3_SRC "CLKOUT"
connect \CLKIN \SCLK
connect \CLKOUT \CLK_FAST
connect \LOCK \jz_unused_pll_LOCK_cg0_u0
connect \CLKOUTP \jz_unused_pll_PHASE_cg0_u0
connect \CLKOUTD \jz_unused_pll_DIV_cg0_u0
connect \CLKOUTD3 \jz_unused_pll_DIV3_cg0_u0
connect \RESET 1'0
connect \RESET_P 1'0
connect \CLKFB 1'0
end
cell \cdc_fifo \u_top
connect \clk_a \SCLK
connect \clk_b \CLK_FAST
connect \rst_n \KEY [0]
connect \leds { \LED [5] \LED [4] \LED [3] \LED [2] \LED [1] \LED [0] }
end
endRaw unsynchronized view (RAW, quasi‑static config)
A 16‑bit config_word register crosses unsynchronized via RAW. No CDC logic is inserted — the designer guarantees the value is stable when read.
jz
// CDC RAW example: unsynchronized quasi-static register
//
// Demonstrates a RAW crossing for a configuration register written
// once at startup and stable thereafter. No synchronization logic
// is inserted — the designer guarantees the value is stable when read.
@module cdc_raw
PORT {
IN [1] clk_a;
IN [1] clk_b;
IN [1] rst_n;
OUT [6] leds;
}
REGISTER {
config_word [16] = 16'hA5A5;
local_config [16] = 16'h0000;
}
CDC {
RAW config_word (clk_a) => config_view (clk_b);
}
ASYNCHRONOUS {
leds <= local_config[5:0];
}
SYNCHRONOUS(CLK=clk_a RESET=rst_n RESET_ACTIVE=Low) {
// config_word is quasi-static: written once, stable thereafter
config_word <= config_word;
}
SYNCHRONOUS(CLK=clk_b RESET=rst_n RESET_ACTIVE=Low) {
local_config <= config_view;
}
@endmodjz
@project(CHIP="GW1NR-9-QN88-C6-I5") CDC_RAW_EXAMPLE
@import "cdc_raw.jz"
CLOCKS {
SCLK = { period=37.04 }; // 27MHz
CLK_FAST; // 108MHz (PLL)
}
IN_PINS {
SCLK = { standard=LVCMOS33 };
DONE = { standard=LVCMOS33 };
KEY[1] = { standard=LVCMOS33 };
}
OUT_PINS {
LED[6] = { standard=LVCMOS33, drive=8 };
}
MAP {
SCLK = 52;
KEY[0] = 3;
LED[0] = 10;
LED[1] = 11;
LED[2] = 13;
LED[3] = 14;
LED[4] = 15;
LED[5] = 16;
DONE = IOL14A;
}
CLOCK_GEN {
PLL {
IN REF_CLK SCLK;
OUT BASE CLK_FAST;
CONFIG {
IDIV = 2;
FBDIV = 7;
ODIV = 8;
};
};
}
@top cdc_raw {
IN [1] clk_a = SCLK;
IN [1] clk_b = CLK_FAST;
IN [1] rst_n = KEY[0];
OUT [6] leds = ~LED;
}
@endprojv
// This Verilog was transpiled from JZ-HDL.
// jz-hdl version: Version 0.1.8 (4a569a5)
// Intended for use with yosys.
`default_nettype none
module cdc_raw (
clk_a,
clk_b,
rst_n,
leds
);
// Ports
input clk_a;
input clk_b;
input rst_n;
output reg [5:0] leds;
// Signals
reg [15:0] config_word;
reg [15:0] local_config;
wire [15:0] config_view;
assign config_view = config_word;
always @* begin
leds = local_config[5:0];
end
always @(posedge clk_a) begin
if (!rst_n) begin
config_word <= 16'b1010010110100101;
end
else begin
config_word <= config_word;
end
end
always @(posedge clk_b) begin
if (!rst_n) begin
local_config <= 16'b0000000000000000;
end
else begin
local_config <= config_view;
end
end
endmodule
module top (
SCLK,
DONE,
KEY,
LED
);
input SCLK;
input DONE;
input KEY;
output [5:0] LED;
// Top-level logical→physical pin mapping
// cdc_raw.clk_a -> SCLK (board 52)
// cdc_raw.clk_b -> CLK_FAST (clock gen)
// cdc_raw.rst_n -> KEY[0] (board 3)
// cdc_raw.leds[5] -> LED[5] (board 16)
// cdc_raw.leds[4] -> LED[4] (board 15)
// cdc_raw.leds[3] -> LED[3] (board 14)
// cdc_raw.leds[2] -> LED[2] (board 13)
// cdc_raw.leds[1] -> LED[1] (board 11)
// cdc_raw.leds[0] -> LED[0] (board 10)
wire [5:0] jz_inv_leds;
assign LED[5] = ~jz_inv_leds[5];
assign LED[4] = ~jz_inv_leds[4];
assign LED[3] = ~jz_inv_leds[3];
assign LED[2] = ~jz_inv_leds[2];
assign LED[1] = ~jz_inv_leds[1];
assign LED[0] = ~jz_inv_leds[0];
wire CLK_FAST;
wire jz_unused_pll_LOCK_cg0_u0;
wire jz_unused_pll_PHASE_cg0_u0;
wire jz_unused_pll_DIV_cg0_u0;
wire jz_unused_pll_DIV3_cg0_u0;
// CLOCK_GEN PLL instantiation (from chip data)
rPLL #(
.DEVICE("GW1N-9C"), // Specify your device
.FCLKIN("26.998"), // Input frequency in MHz
.IDIV_SEL(2), // IDIV: Input divider
.FBDIV_SEL(7), // FBDIV: Feedback divider
.ODIV_SEL(8), // ODIV: Output divider
.PSDA_SEL("0000"),
.DUTYDA_SEL("1000"),
.DYN_IDIV_SEL("FALSE"),
.DYN_FBDIV_SEL("FALSE"),
.DYN_ODIV_SEL("FALSE"),
.DYN_DA_EN("FALSE"),
.DYN_SDIV_SEL(2),
.CLKOUT_FT_DIR(1'b1),
.CLKOUTP_FT_DIR(1'b1),
.CLKOUT_DLY_STEP(0),
.CLKOUTP_DLY_STEP(0),
.CLKFB_SEL("internal"),
.CLKOUT_BYPASS("FALSE"),
.CLKOUTP_BYPASS("FALSE"),
.CLKOUTD_BYPASS("FALSE"),
.CLKOUTD_SRC("CLKOUT"),
.CLKOUTD3_SRC("CLKOUT")
) u_pll_0_0 (
.CLKOUT(CLK_FAST), // Primary output
.LOCK(jz_unused_pll_LOCK_cg0_u0), // High when stable
.CLKOUTP(jz_unused_pll_PHASE_cg0_u0), // Phase shifted output
.CLKOUTD(jz_unused_pll_DIV_cg0_u0), // Divided output
.CLKOUTD3(jz_unused_pll_DIV3_cg0_u0), // Divided by 3 output
.RESET(1'b0), // Reset signal
.RESET_P(1'b0), // PLL power down
.CLKIN(SCLK), // Reference clock input
.CLKFB(1'b0) // External feedback
);
cdc_raw u_top (
.clk_a(SCLK),
.clk_b(CLK_FAST),
.rst_n(KEY[0]),
.leds({jz_inv_leds[5], jz_inv_leds[4], jz_inv_leds[3], jz_inv_leds[2], jz_inv_leds[1], jz_inv_leds[0]})
);
endmoduleil
# Generated by jz-hdl RTLIL backend
# jz-hdl version: Version 0.1.8 (4a569a5)
attribute \src "jz-hdl:7"
module \cdc_raw
wire width 1 input 1 \clk_a
wire width 1 input 2 \clk_b
wire width 1 input 3 \rst_n
wire width 6 output 4 \leds
wire width 16 \config_word
wire width 16 \local_config
wire width 16 \config_view
connect \config_view \config_word
wire width 6 $0\leds[5:0]
process $proc$async$1
assign $0\leds[5:0] \local_config [5:0]
sync always
update \leds $0\leds[5:0]
end
wire width 16 $0\config_word[15:0]
wire width 1 $auto$2
cell $logic_not $auto$3
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \Y_WIDTH 1
connect \A \rst_n
connect \Y $auto$2
end
process $proc$clk0$4
assign $0\config_word[15:0] \config_word
switch $auto$2
case 1'1
assign $0\config_word[15:0] 16'1010010110100101
case
assign $0\config_word[15:0] \config_word
end
sync posedge \clk_a
update \config_word $0\config_word[15:0]
end
wire width 16 $0\local_config[15:0]
wire width 1 $auto$5
cell $logic_not $auto$6
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \Y_WIDTH 1
connect \A \rst_n
connect \Y $auto$5
end
process $proc$clk1$7
assign $0\local_config[15:0] \local_config
switch $auto$5
case 1'1
assign $0\local_config[15:0] 16'0000000000000000
case
assign $0\local_config[15:0] \config_view
end
sync posedge \clk_b
update \local_config $0\local_config[15:0]
end
end
attribute \top 1
module \top
wire width 1 input 1 \SCLK
wire width 1 input 2 \DONE
wire width 1 input 3 \KEY
wire width 6 output 4 \LED
wire width 1 \CLK_FAST
wire width 1 \jz_unused_pll_LOCK_cg0_u0
wire width 1 \jz_unused_pll_PHASE_cg0_u0
wire width 1 \jz_unused_pll_DIV_cg0_u0
wire width 1 \jz_unused_pll_DIV3_cg0_u0
cell \rPLL $auto$0_0
parameter \DEVICE "GW1N-9C"
parameter \FCLKIN "26.998"
parameter \IDIV_SEL 2
parameter \FBDIV_SEL 7
parameter \ODIV_SEL 8
parameter \PSDA_SEL "0000"
parameter \DUTYDA_SEL "1000"
parameter \DYN_IDIV_SEL "FALSE"
parameter \DYN_FBDIV_SEL "FALSE"
parameter \DYN_ODIV_SEL "FALSE"
parameter \DYN_DA_EN "FALSE"
parameter \DYN_SDIV_SEL 2
parameter \CLKOUT_FT_DIR 1
parameter \CLKOUTP_FT_DIR 1
parameter \CLKOUT_DLY_STEP 0
parameter \CLKOUTP_DLY_STEP 0
parameter \CLKFB_SEL "internal"
parameter \CLKOUT_BYPASS "FALSE"
parameter \CLKOUTP_BYPASS "FALSE"
parameter \CLKOUTD_BYPASS "FALSE"
parameter \CLKOUTD_SRC "CLKOUT"
parameter \CLKOUTD3_SRC "CLKOUT"
connect \CLKIN \SCLK
connect \CLKOUT \CLK_FAST
connect \LOCK \jz_unused_pll_LOCK_cg0_u0
connect \CLKOUTP \jz_unused_pll_PHASE_cg0_u0
connect \CLKOUTD \jz_unused_pll_DIV_cg0_u0
connect \CLKOUTD3 \jz_unused_pll_DIV3_cg0_u0
connect \RESET 1'0
connect \RESET_P 1'0
connect \CLKFB 1'0
end
cell \cdc_raw \u_top
connect \clk_a \SCLK
connect \clk_b \CLK_FAST
connect \rst_n \KEY [0]
connect \leds { \LED [5] \LED [4] \LED [3] \LED [2] \LED [1] \LED [0] }
end
endCommon Errors and Diagnostics
DOMAIN_CONFLICT
- Cause: Using a
REGISTERin a synchronous block whoseCLKdiffers from the register's home domain (as set by CDC or by where the register is first assigned). - Fix: Move the register usage to the correct
SYNCHRONOUSblock or add a CDC entry that creates an alias for cross‑domain use.
- Cause: Using a
DUPLICATE_CDC_ENTRY
- Cause: Two CDC entries attempt to set home domain for the same source register inconsistently.
- Fix: Consolidate CDC entries; each register should have a single definitive home domain.
INVALID_CDC_TARGET
- Cause: The source register is not a plain register identifier (slice, concat, or undefined).
- Fix: Use the plain register name; if you need to cross slices or fields, create separate registers or use FIFO.
INVALID_CDC_TYPE
- Cause: Using
BITfor multi‑bit sources orBUSfor sources that change arbitrarily. - Fix: Use the correct CDC type. Use
BITfor width==1,BUSonly when Gray‑code discipline is followed, otherwiseFIFO.
- Cause: Using
UNSAFE_BUS_WARNING (warning)
- Cause: Static/heuristic analysis detects that a
BUSsource may change multiple bits simultaneously. - Fix: Use
FIFOor redesign the producer to follow Gray‑code or single‑bit change discipline.
- Cause: Static/heuristic analysis detects that a
MISSING_CDC_FOR_CROSS_DOMAIN_USE
- Cause: A register is referenced in a different domain without a CDC entry.
- Fix: Add a CDC entry or redesign to avoid cross‑domain reads.
MULTI_CLK_ASSIGN / REGISTER_LOCALITY_VIOLATION
- Cause: Assigning the same register in more than one
SYNCHRONOUSblock for different clocks. - Fix: Ensure a register is written only in its home domain; use CDC to observe it elsewhere.
- Cause: Assigning the same register in more than one
Best Practices
Be explicit and conservative:
- Prefer
FIFOfor multi‑bit transfers unless you can guarantee single‑bit changes (Gray code) and understand the implications. - Use
BIT[2]orBIT[3]for status/control signals; 2 stages is common, 3 for safety in noisy environments.
- Prefer
Name aliases clearly:
- Use systematic naming like
reg_sync_destclkorsrc_to_dst_signalso intent is obvious.
- Use systematic naming like
One synchronous block per clock:
- Place all logic for a given clock in the same
SYNCHRONOUS(CLK=...)block to satisfy Synchronous Block Uniqueness.
- Place all logic for a given clock in the same
Keep CDC block near register declarations:
- Place
CDC { ... }entries close to theREGISTERdeclarations for readability and to help tools resolve names.
- Place
Document constraints:
- If a
BUSCDC requires Gray‑coding, document the producer's requirement in comments and add static checks or assertions when possible.
- If a
Verify with static checks and timing:
- Run CDC-specific static checks and, where possible, formal checks to ensure no combinational paths create control hazards across domains.
- Ensure timing constraints for synchronizers are included in downstream SDC (synthesis/timing) flows.
Anti‑patterns (What to avoid)
- Reading a source register directly in another clock domain without CDC — causes DOMAIN_CONFLICT and metastability.
- Using
BUSfor wide registers that can change every cycle with arbitrary bit patterns — leads to data corruption. - Mixing alias names and source register names across domains (ambiguous intent).
- Trying to synchronize slices of a multi‑bit register via separate
BITsynchronizers without ensuring atomic update semantics on the producer side.
Checklist for Adding a CDC Crossing
- Confirm the source is a
REGISTERand has a single, clear producer domain. - Decide the appropriate CDC type:
- BIT → single‑bit flag.
- BUS → multi‑bit Gray‑code or single‑bit change guaranteed.
- FIFO → arbitrary multi‑bit transfers.
- RAW → quasi‑static or externally synchronized signals (no CDC logic inserted).
- Choose
n_stages(default 2). For safety or noisy inputs, increase to 3. - Add the
CDCentry near the register declaration. - Replace any cross‑domain uses with reads of the
dest_alias. - Run static checks; address compiler warnings/errors.
- Add documentation/comments explaining invariants (e.g., Gray‑code property).
Synthesis and Implementation Notes
- The compiler will lower
CDCentries into synthesizable primitives:- BIT → chain of flip‑flops with optional meta‑stable handling.
- BUS → bank of flip‑flops and optional handshaking or gating depending on implementation.
- FIFO → dual‑clock FIFO or asynchronous FIFO implementation using pointers and synchronizers.
- Downstream tools should map these to:
- Vendor synchronizer primitives or hand‑optimized flops.
- FIFO IP blocks for
FIFOCDC entries when available.
- Ensure timing constraints (SDC) include created synchronizer registers so STA correctly analyzes setup/hold for destination domain.