Skip to content

Commit c6bda10

Browse files
DDR: Improve API, document
The existing constraint can be redefined in terms of `DomainPeriod`. Since the virtual DDR domain only exists in simulation, it really doesn't matter if it doesn't match with the real domain in all its parameters, so we can drop those and make the constraints more intuitive to read. The primitives for Xilinx and Intel only support the rising edge as the active edge of the domain. The real domain of the functions was the `slow` domain, and the `fast` domain was the virtual domain. The new names `dom` and `domDDR` reinforce the fact that `dom` is the real domain.
1 parent 44f9551 commit c6bda10

17 files changed

+711
-557
lines changed

changelog/2024-12-14T13_35_37+01_00_fix_ddr_prims

+2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ FIXED: `Clash.Explicit.DDR`:
22
- `ddrIn`: VHDL: Remove data input from sensitivity list of `ddrIn_neg_latch` register as it is superfluous. This should not affect functionality.
33
- `ddrOut`: VHDL: Fix incorrect usage of `Enable` input when the domain is set to asynchronous resets. Deasserting the `Enable` exhibited wrong behavior before this fix.
44
FIXED: `Clash.Xilinx.DDR`:
5+
- These primitives only support clocks where the rising edge is the active edge. Using them in a domain with falling active edges now causes an error.
56
- `oddr`: Fix VHDL and SystemVerilog erroring out during HDL generation
67
- Symbols in HDL for both `iddr` and `oddr` were renamed to match their function.
78
FIXED: `Clash.Intel.DDR`:
9+
- These primitives only support clocks where the rising edge is the active edge. Using them in a domain with falling active edges now causes an error.
810
- Fix rendering HDL. It variously errored out or generated non-working HDL.
911
- Rendering HDL no longer causes Clash to issue a warning about an argument unused in Haskell but used in the primitive black box.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
CHANGED: `Clash.Explicit.DDR`, `Clash.Intel.DDR` and `Clash.Xilinx.DDR`:
2+
- The constraints for the functions have been rewritten to use `DomainPeriod`, which makes them more readable and relaxes unnecessary constraints on the virtual DDR domain. The type-level variables for the domains have been renamed. `dom` is a real domain, `domDDR` is the virtual DDR domain.
3+
- The Xilinx and Intel primitives only support domains where the rising edge is the active edge. This is now enforced at the type level by adding a constraint.
4+
- The Xilinx and Intel primitives now directly support any data type that has a `BitPack` instance.

clash-lib/prims/commonverilog/Clash_Intel_DDR.primitives.yaml

+22-19
Original file line numberDiff line numberDiff line change
@@ -5,39 +5,42 @@
55
- altera_mf
66
type: |-
77
altddioOut#
8-
:: ( HasCallStack -- ARG[0]
9-
, KnownConfi~ fast domf -- ARG[1]
10-
, KnownConfi~ slow doms -- ARG[2]
11-
, KnownNat m ) -- ARG[3]
12-
=> SSymbol deviceFamily -- ARG[4]
13-
-> Clock slow -- ARG[5]
14-
-> Reset slow -- ARG[6]
15-
-> Enable slow -- ARG[7]
16-
-> Signal slow (BitVector m) -- ARG[8]
17-
-> Signal slow (BitVector m) -- ARG[9]
18-
-> Signal fast (BitVector m)
8+
:: forall deviceFamily n dom domDDR
9+
. HasCallStack -- ARG[0]
10+
=> KnownDomain dom -- ARG[1]
11+
=> KnownDomain domDDR -- ARG[2]
12+
=> DomPeriod ~ 2 * ... -- ARG[3]
13+
=> DomEdge ~ Rising -- ARG[4]
14+
=> KnownNat n -- ARG[5]
15+
=> SSymbol deviceFamily -- ARG[6]
16+
-> Clock dom -- ARG[7]
17+
-> Reset dom -- ARG[8]
18+
-> Enable dom -- ARG[9]
19+
-> Signal dom (BitVector n) -- ARG[10]
20+
-> Signal dom (BitVector n) -- ARG[11]
21+
-> Signal domDDR (BitVector n)
1922
template: |-
2023
// altddioOut begin
2124
altddio_out
2225
#(
2326
.extend_oe_disable ("OFF"),
24-
.intended_device_family (~LIT[4]),
27+
.intended_device_family (~LIT[6]),
2528
.invert_output ("OFF"),
2629
.lpm_hint ("UNUSED"),
2730
.lpm_type ("altddio_out"),
2831
.oe_reg ("UNREGISTERED"),
2932
.power_up_high ("OFF"),
3033
.width (~SIZE[~TYPO])
3134
)
32-
~GENSYM[~COMPNAME_ALTDDIO_OUT][7] (~IF ~ISSYNC[2] ~THEN
33-
.sclr (~ARG[6]),
35+
~GENSYM[~COMPNAME_ALTDDIO_OUT][7] (~IF ~ISSYNC[1] ~THEN
36+
.sclr (~ARG[8]),
3437
.aclr (1'b0),~ELSE
35-
.aclr (~ARG[6]),
38+
.aclr (~ARG[8]),
3639
.sclr (1'b0),~FI
37-
.datain_h (~ARG[8]),
38-
.datain_l (~ARG[9]),
39-
.outclock (~ARG[5]),
40-
.outclocken (~IF ~ISACTIVEENABLE[7] ~THEN ~ARG[7] ~ELSE 1'b1 ~FI),
40+
.datain_h (~ARG[10]),
41+
.datain_l (~ARG[11]),
42+
.outclock (~ARG[7]),
43+
.outclocken (~IF ~ISACTIVEENABLE[9] ~THEN ~ARG[9] ~ELSE 1'b1 ~FI),
4144
.dataout (~RESULT),
4245
.aset (1'b0),
4346
.sset (1'b0),

clash-lib/prims/systemverilog/Clash_Explicit_DDR.primitives.yaml

+55-52
Original file line numberDiff line numberDiff line change
@@ -2,42 +2,43 @@
22
name: Clash.Explicit.DDR.ddrIn#
33
kind: Declaration
44
type: |-
5-
ddrIn# :: forall a slow fast n pFast gated synchronous.
6-
( HasCallStack -- ARG[0]
7-
, NFDataX a -- ARG[1]
8-
, KnownConfi~ fast domf -- ARG[2]
9-
, KnownConfi~ slow doms -- ARG[3]
10-
=> Clock slow -- ARG[4], clk
11-
-> Reset slow -- ARG[5], rst
12-
-> Enable slow -- ARG[6], en
13-
-> a -- ARG[7]
14-
-> a -- ARG[8]
15-
-> a -- ARG[9]
16-
-> Signal fast a -- ARG[10]
17-
-> Signal slow (a,a)
5+
ddrIn# :: forall a dom domDDR
6+
. HasCallStack -- ARG[0]
7+
=> NFDataX a -- ARG[1]
8+
=> KnownDomain dom -- ARG[2]
9+
=> KnownDomain domDDR -- ARG[3]
10+
=> DomPeriod ~ 2 * ... -- ARG[4]
11+
=> Clock dom -- ARG[5]
12+
-> Reset dom -- ARG[6]
13+
-> Enable dom -- ARG[7]
14+
-> a -- ARG[8]
15+
-> a -- ARG[9]
16+
-> a -- ARG[10]
17+
-> Signal domDDR a -- ARG[11]
18+
-> Signal dom (a,a)
1819
template: |-
1920
// ddrIn begin
20-
~SIGD[~GENSYM[data_Pos][1]][9];
21-
~SIGD[~GENSYM[data_Neg][2]][9];
22-
~SIGD[~GENSYM[data_Neg_Latch][3]][9];
23-
always @(~IF~ACTIVEEDGE[Rising][2]~THENposedge~ELSEnegedge~FI ~ARG[4]~IF~ISSYNC[3]~THEN)~ELSE or ~IF~ISACTIVEHIGH[2]~THENposedge~ELSEnegedge~FI ~ARG[5])~FI begin : ~GENSYM[~COMPNAME_ddrIn_pos][6]
24-
if (~IF~ISACTIVEHIGH[2]~THEN~ARG[5]~ELSE! ~ARG[5]~FI) begin
25-
~SYM[1] <= ~ARG[8];
26-
end else ~IF ~ISACTIVEENABLE[6] ~THEN if (~ARG[6]) ~ELSE ~FI begin
27-
~SYM[1] <= ~ARG[10];
21+
~SIGD[~GENSYM[data_Pos][1]][11];
22+
~SIGD[~GENSYM[data_Neg][2]][11];
23+
~SIGD[~GENSYM[data_Neg_Latch][3]][11];
24+
always @(~IF~ACTIVEEDGE[Rising][2]~THENposedge~ELSEnegedge~FI ~ARG[5]~IF~ISSYNC[2]~THEN)~ELSE or ~IF~ISACTIVEHIGH[2]~THENposedge~ELSEnegedge~FI ~ARG[6])~FI begin : ~GENSYM[~COMPNAME_ddrIn_pos][6]
25+
if (~IF~ISACTIVEHIGH[2]~THEN~ARG[6]~ELSE! ~ARG[6]~FI) begin
26+
~SYM[1] <= ~ARG[9];
27+
end else ~IF ~ISACTIVEENABLE[7] ~THEN if (~ARG[7]) ~ELSE ~FI begin
28+
~SYM[1] <= ~ARG[11];
2829
end
2930
end
30-
always @(~IF~ACTIVEEDGE[Rising][2]~THENnegedge~ELSEposedge~FI ~ARG[4]~IF~ISSYNC[3]~THEN)~ELSE or ~IF~ISACTIVEHIGH[2]~THENposedge~ELSEnegedge~FI ~ARG[5])~FI begin : ~GENSYM[~COMPNAME_ddrIn_neg][7]
31-
if (~IF~ISACTIVEHIGH[2]~THEN~ARG[5]~ELSE! ~ARG[5]~FI) begin
32-
~SYM[2] <= ~ARG[9];
33-
end else ~IF ~ISACTIVEENABLE[6] ~THEN if (~ARG[6]) ~ELSE ~FI begin
31+
always @(~IF~ACTIVEEDGE[Rising][2]~THENnegedge~ELSEposedge~FI ~ARG[5]~IF~ISSYNC[2]~THEN)~ELSE or ~IF~ISACTIVEHIGH[2]~THENposedge~ELSEnegedge~FI ~ARG[6])~FI begin : ~GENSYM[~COMPNAME_ddrIn_neg][7]
32+
if (~IF~ISACTIVEHIGH[2]~THEN~ARG[6]~ELSE! ~ARG[6]~FI) begin
3433
~SYM[2] <= ~ARG[10];
34+
end else ~IF ~ISACTIVEENABLE[7] ~THEN if (~ARG[7]) ~ELSE ~FI begin
35+
~SYM[2] <= ~ARG[11];
3536
end
3637
end
37-
always @(~IF~ACTIVEEDGE[Rising][2]~THENposedge~ELSEnegedge~FI ~ARG[4]~IF~ISSYNC[3]~THEN)~ELSE or ~IF~ISACTIVEHIGH[2]~THENposedge~ELSEnegedge~FI ~ARG[5])~FI begin : ~GENSYM[~COMPNAME_ddrIn_neg_latch][8]
38-
if (~IF~ISACTIVEHIGH[2]~THEN~ARG[5]~ELSE! ~ARG[5]~FI) begin
39-
~SYM[3] <= ~ARG[7];
40-
end else ~IF ~ISACTIVEENABLE[6] ~THEN if (~ARG[6]) ~ELSE ~FI begin
38+
always @(~IF~ACTIVEEDGE[Rising][2]~THENposedge~ELSEnegedge~FI ~ARG[5]~IF~ISSYNC[2]~THEN)~ELSE or ~IF~ISACTIVEHIGH[2]~THENposedge~ELSEnegedge~FI ~ARG[6])~FI begin : ~GENSYM[~COMPNAME_ddrIn_neg_latch][8]
39+
if (~IF~ISACTIVEHIGH[2]~THEN~ARG[6]~ELSE! ~ARG[6]~FI) begin
40+
~SYM[3] <= ~ARG[8];
41+
end else ~IF ~ISACTIVEENABLE[7] ~THEN if (~ARG[7]) ~ELSE ~FI begin
4142
~SYM[3] <= ~SYM[2];
4243
end
4344
end
@@ -49,38 +50,40 @@
4950
kind: Declaration
5051
outputUsage: Blocking
5152
type: |-
52-
ddrOut# :: ( HasCallStack -- ARG[0]
53-
, NFDataX a -- ARG[1]
54-
, KnownConfi~ fast domf -- ARG[2]
55-
, KnownConfi~ slow doms -- ARG[3]
56-
=> Clock slow -- ARG[4]
57-
-> Reset slow -- ARG[5]
58-
-> Enable slow -- ARG[6]
59-
-> a -- ARG[7]
60-
-> Signal slow a -- ARG[8]
61-
-> Signal slow a -- ARG[9]
62-
-> Signal fast a
53+
ddrOut# :: forall a dom domDDR
54+
. HasCallStack -- ARG[0]
55+
=> NFDataX a -- ARG[1]
56+
=> KnownDomain dom -- ARG[2]
57+
=> KnownDomain domDDR -- ARG[3]
58+
=> DomPeriod ~ 2 * ... -- ARG[4]
59+
=> Clock dom -- ARG[5]
60+
-> Reset dom -- ARG[6]
61+
-> Enable dom -- ARG[7]
62+
-> a -- ARG[8]
63+
-> Signal dom a -- ARG[9]
64+
-> Signal dom a -- ARG[10]
65+
-> Signal domDDR a
6366
template: |-
6467
// ddrOut begin
65-
~SIGD[~GENSYM[data_Pos][1]][7];
66-
~SIGD[~GENSYM[data_Neg][2]][7];
67-
always @(~IF~ACTIVEEDGE[Rising][2]~THENposedge~ELSEnegedge~FI ~ARG[4]~IF~ISSYNC[3]~THEN)~ELSE or ~IF~ISACTIVEHIGH[2]~THENposedge~ELSEnegedge~FI ~ARG[5])~FI begin : ~GENSYM[~COMPNAME_ddrOut_pos][5]
68-
if (~IF~ISACTIVEHIGH[2]~THEN~ARG[5]~ELSE! ~ARG[5]~FI) begin
69-
~SYM[1] <= ~ARG[7];
70-
end else ~IF ~ISACTIVEENABLE[6] ~THEN if (~ARG[6]) ~ELSE ~FI begin
68+
~SIGD[~GENSYM[data_Pos][1]][8];
69+
~SIGD[~GENSYM[data_Neg][2]][8];
70+
always @(~IF~ACTIVEEDGE[Rising][2]~THENposedge~ELSEnegedge~FI ~ARG[5]~IF~ISSYNC[2]~THEN)~ELSE or ~IF~ISACTIVEHIGH[2]~THENposedge~ELSEnegedge~FI ~ARG[6])~FI begin : ~GENSYM[~COMPNAME_ddrOut_pos][5]
71+
if (~IF~ISACTIVEHIGH[2]~THEN~ARG[6]~ELSE! ~ARG[6]~FI) begin
7172
~SYM[1] <= ~ARG[8];
73+
end else ~IF ~ISACTIVEENABLE[7] ~THEN if (~ARG[7]) ~ELSE ~FI begin
74+
~SYM[1] <= ~ARG[9];
7275
end
7376
end
74-
always @(~IF~ACTIVEEDGE[Rising][2]~THENposedge~ELSEnegedge~FI ~ARG[4]~IF~ISSYNC[3]~THEN)~ELSE or ~IF~ISACTIVEHIGH[2]~THENposedge~ELSEnegedge~FI ~ARG[5])~FI begin : ~GENSYM[~COMPNAME_ddrOut_neg][6]
75-
if (~IF~ISACTIVEHIGH[2]~THEN~ARG[5]~ELSE! ~ARG[5]~FI) begin
76-
~SYM[2] <= ~ARG[7];
77-
end else ~IF ~ISACTIVEENABLE[6] ~THEN if (~ARG[6]) ~ELSE ~FI begin
78-
~SYM[2] <= ~ARG[9];
77+
always @(~IF~ACTIVEEDGE[Rising][2]~THENposedge~ELSEnegedge~FI ~ARG[5]~IF~ISSYNC[2]~THEN)~ELSE or ~IF~ISACTIVEHIGH[2]~THENposedge~ELSEnegedge~FI ~ARG[6])~FI begin : ~GENSYM[~COMPNAME_ddrOut_neg][6]
78+
if (~IF~ISACTIVEHIGH[2]~THEN~ARG[6]~ELSE! ~ARG[6]~FI) begin
79+
~SYM[2] <= ~ARG[8];
80+
end else ~IF ~ISACTIVEENABLE[7] ~THEN if (~ARG[7]) ~ELSE ~FI begin
81+
~SYM[2] <= ~ARG[10];
7982
end
8083
end
8184
8285
always @(*) begin
83-
if (~ARG[4]) begin
86+
if (~ARG[5]) begin
8487
~RESULT = ~IF~ACTIVEEDGE[Rising][2]~THEN~SYM[1]~ELSE~SYM[2]~FI;
8588
end else begin
8689
~RESULT = ~IF~ACTIVEEDGE[Rising][2]~THEN~SYM[2]~ELSE~SYM[1]~FI;

clash-lib/prims/systemverilog/Clash_Intel_DDR.primitives.yaml

+25-22
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,45 @@
11
- BlackBox:
2-
name: Clash.Intel.DDR.altddioIn
2+
name: Clash.Intel.DDR.altddioIn#
33
kind: Declaration
44
libraries:
55
- altera_mf
66
type: |-
7-
altddioIn
8-
:: ( HasCallStack -- ARG[0]
9-
, KnownConfi~ fast domf -- ARG[1]
10-
, KnownConfi~ slow doms -- ARG[2]
11-
, KnownNat m ) -- ARG[3]
12-
=> SSymbol deviceFamily -- ARG[4]
13-
-> Clock slow -- ARG[5]
14-
-> Reset slow -- ARG[6]
15-
-> Enable slow -- ARG[7]
16-
-> Signal fast (BitVector m) -- ARG[8]
17-
-> Signal slow (BitVector m,BitVector m)
7+
altddioIn#
8+
:: forall deviceFamily n dom domDDR
9+
. HasCallStack -- ARG[0]
10+
=> KnownDomain dom -- ARG[1]
11+
=> KnownDomain domDDR -- ARG[2]
12+
=> DomPeriod ~ 2 * ... -- ARG[3]
13+
=> DomEdge ~ Rising -- ARG[4]
14+
=> KnownNat n -- ARG[5]
15+
=> SSymbol deviceFamily -- ARG[6]
16+
-> Clock dom -- ARG[7]
17+
-> Reset dom -- ARG[8]
18+
-> Enable dom -- ARG[9]
19+
-> Signal domDDR (BitVector n) -- ARG[10]
20+
-> Signal dom (BitVector n, BitVector n)
1821
template: |-
1922
// altddioIn begin
20-
~SIGD[~GENSYM[dataout_l][1]][8];
21-
~SIGD[~GENSYM[dataout_h][2]][8];
23+
~SIGD[~GENSYM[dataout_l][1]][10];
24+
~SIGD[~GENSYM[dataout_h][2]][10];
2225
2326
altddio_in
2427
#(
25-
.intended_device_family (~LIT[4]),
28+
.intended_device_family (~LIT[6]),
2629
.invert_input_clocks ("OFF"),
2730
.lpm_hint ("UNUSED"),
2831
.lpm_type ("altddio_in"),
2932
.power_up_high ("OFF"),
30-
.width (~SIZE[~TYP[8]])
33+
.width (~SIZE[~TYP[10]])
3134
)
32-
~GENSYM[~COMPNAME_ALTDDIO_IN][7] (~IF ~ISSYNC[2] ~THEN
33-
.sclr (~ARG[6]),
35+
~GENSYM[~COMPNAME_ALTDDIO_IN][7] (~IF ~ISSYNC[1] ~THEN
36+
.sclr (~ARG[8]),
3437
.aclr (1'b0),~ELSE
35-
.aclr (~ARG[6]),
38+
.aclr (~ARG[8]),
3639
.sclr (1'b0),~FI
37-
.datain (~ARG[8]),
38-
.inclock (~ARG[5]),
39-
.inclocken (~IF ~ISACTIVEENABLE[7] ~THEN~ARG[7]~ELSE1'b1~FI),
40+
.datain (~ARG[10]),
41+
.inclock (~ARG[7]),
42+
.inclocken (~IF ~ISACTIVEENABLE[9] ~THEN~ARG[9]~ELSE1'b1~FI),
4043
.dataout_h (~SYM[2]),
4144
.dataout_l (~SYM[1]),
4245
.aset (1'b0),

0 commit comments

Comments
 (0)