Skip to content

Commit 6bdfd61

Browse files
committed
[+] Add cdc_afifo system verilog implementation
1 parent 9f29cfc commit 6bdfd61

File tree

5 files changed

+177
-5
lines changed

5 files changed

+177
-5
lines changed

sc/rtl/techmap/mem/ram_mmu_tech.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@ ram_mmu_tech<abits, dbits>::ram_mmu_tech(sc_module_name name)
6161

6262
template<int abits, int dbits>
6363
void ram_mmu_tech<abits, dbits>::registers() {
64-
6564
if (i_wena.read() == 1) {
6665
mem[i_addr.read().to_int()] = i_wdata;
6766
} else {

sc/rtl/techmap/mem/ram_tech.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@ ram_tech<abits, dbits>::ram_tech(sc_module_name name)
6161

6262
template<int abits, int dbits>
6363
void ram_tech<abits, dbits>::registers() {
64-
6564
if (i_wena.read() == 1) {
6665
mem[i_addr.read().to_int()] = i_wdata;
6766
}

sc/rtl/techmap/mem/rom_inferred_2x32.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ rom_inferred_2x32<abits>::rom_inferred_2x32(sc_module_name name,
7676

7777
template<int abits>
7878
void rom_inferred_2x32<abits>::registers() {
79-
8079
wb_rdata0 = mem0[i_addr.read().to_int()];
8180
wb_rdata1 = mem1[i_addr.read().to_int()];
8281

sv/rtl/techmap/cdc/cdc_afifo.sv

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
//
2+
// Copyright 2022 Sergey Khabarov, sergeykhbr@gmail.com
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
//
16+
17+
`timescale 1ns/10ps
18+
19+
module cdc_afifo #(
20+
parameter int abits = 3, // fifo log2(depth)
21+
parameter int dbits = 32 // payload width
22+
)
23+
(
24+
input logic i_wclk, // clock write
25+
input logic i_wrstn, // write reset active LOW
26+
input logic i_wr, // write enable strob
27+
input logic [dbits-1:0] i_wdata, // write data
28+
output logic o_wfull, // fifo is full in wclk domain
29+
input logic i_rclk, // read clock
30+
input logic i_rrstn, // read reset active LOW
31+
input logic i_rd, // read enable strob
32+
output logic [dbits-1:0] o_rdata, // fifo payload read
33+
output logic o_rempty // fifo is empty it rclk domain
34+
);
35+
36+
localparam int DEPTH = (2**abits);
37+
38+
typedef struct {
39+
logic [(abits + 1)-1:0] wgray;
40+
logic [(abits + 1)-1:0] wbin;
41+
logic [(abits + 1)-1:0] wq2_rgray;
42+
logic [(abits + 1)-1:0] wq1_rgray;
43+
logic wfull;
44+
} cdc_afifo_registers;
45+
46+
const cdc_afifo_registers cdc_afifo_r_reset = '{
47+
4'd0, // wgray
48+
4'd0, // wbin
49+
4'd0, // wq2_rgray
50+
4'd0, // wq1_rgray
51+
1'b0 // wfull
52+
};
53+
54+
typedef struct {
55+
logic [(abits + 1)-1:0] rgray;
56+
logic [(abits + 1)-1:0] rbin;
57+
logic [(abits + 1)-1:0] rq2_wgray;
58+
logic [(abits + 1)-1:0] rq1_wgray;
59+
logic rempty;
60+
} cdc_afifo_r2egisters;
61+
62+
const cdc_afifo_r2egisters cdc_afifo_r2_reset = '{
63+
4'd0, // rgray
64+
4'd0, // rbin
65+
4'd0, // rq2_wgray
66+
4'd0, // rq1_wgray
67+
1'b1 // rempty
68+
};
69+
70+
typedef struct {
71+
logic [dbits-1:0] mem[0: DEPTH - 1];
72+
} cdc_afifo_rx2egisters;
73+
74+
cdc_afifo_registers r, rin;
75+
cdc_afifo_r2egisters r2, r2in;
76+
cdc_afifo_rx2egisters rx2, rx2in;
77+
78+
79+
always_comb
80+
begin: comb_proc
81+
cdc_afifo_registers v;
82+
cdc_afifo_r2egisters v2;
83+
cdc_afifo_rx2egisters vx2;
84+
logic [abits-1:0] vb_waddr;
85+
logic [abits-1:0] vb_raddr;
86+
logic v_wfull_next;
87+
logic v_rempty_next;
88+
logic [(abits + 1)-1:0] vb_wgraynext;
89+
logic [(abits + 1)-1:0] vb_wbinnext;
90+
logic [(abits + 1)-1:0] vb_rgraynext;
91+
logic [(abits + 1)-1:0] vb_rbinnext;
92+
93+
vb_waddr = 3'd0;
94+
vb_raddr = 3'd0;
95+
v_wfull_next = 1'b0;
96+
v_rempty_next = 1'b0;
97+
vb_wgraynext = 4'd0;
98+
vb_wbinnext = 4'd0;
99+
vb_rgraynext = 4'd0;
100+
vb_rbinnext = 4'd0;
101+
102+
v = r;
103+
v2 = r2;
104+
for (int i = 0; i < DEPTH; i++) begin
105+
vx2.mem[i] = rx2.mem[i];
106+
end
107+
108+
// Cross the Gray pointer to write clock domain:
109+
v.wq1_rgray = r2.rgray;
110+
v.wq2_rgray = r.wq1_rgray;
111+
112+
// Next write address and Gray write pointer
113+
vb_wbinnext = (r.wbin + {3'd0, (i_wr && (~r.wfull))});
114+
vb_wgraynext = ({'0, vb_wbinnext[(abits + 1) - 1: 1]} ^ vb_wbinnext);
115+
vb_waddr = r.wbin[(abits - 1): 0];
116+
v.wgray = vb_wgraynext;
117+
v.wbin = vb_wbinnext;
118+
119+
if (vb_wgraynext == {(~r.wq2_rgray[abits: (abits - 1)]), r.wq2_rgray[(abits - 2): 0]}) begin
120+
v_wfull_next = 1'b1;
121+
end
122+
v.wfull = v_wfull_next;
123+
124+
if ((i_wr && (~r.wfull)) == 1'b1) begin
125+
vx2.mem[int'(vb_waddr)] = i_wdata;
126+
end
127+
128+
// Write Gray pointer into read clock domain
129+
v2.rq1_wgray = r.wgray;
130+
v2.rq2_wgray = r2.rq1_wgray;
131+
vb_rbinnext = (r2.rbin + {3'd0, (i_rd && (~r2.rempty))});
132+
vb_rgraynext = ({'0, vb_rbinnext[(abits + 1) - 1: 1]} ^ vb_rbinnext);
133+
v2.rgray = vb_rgraynext;
134+
v2.rbin = vb_rbinnext;
135+
vb_raddr = r2.rbin[(abits - 1): 0];
136+
137+
if (vb_rgraynext == r2.rq2_wgray) begin
138+
v_rempty_next = 1'b1;
139+
end
140+
v2.rempty = v_rempty_next;
141+
142+
o_wfull = r.wfull;
143+
o_rempty = r2.rempty;
144+
o_rdata = rx2.mem[int'(vb_raddr)];
145+
146+
rin = v;
147+
r2in = v2;
148+
for (int i = 0; i < DEPTH; i++) begin
149+
rx2in.mem[i] = vx2.mem[i];
150+
end
151+
end: comb_proc
152+
153+
always_ff @(posedge i_wclk, negedge i_wrstn) begin: rg_proc
154+
if (i_wrstn == 1'b0) begin
155+
r <= cdc_afifo_r_reset;
156+
end else begin
157+
r <= rin;
158+
end
159+
end: rg_proc
160+
161+
always_ff @(posedge i_rclk, negedge i_rrstn) begin: r2g_proc
162+
if (i_rrstn == 1'b0) begin
163+
r2 <= cdc_afifo_r2_reset;
164+
end else begin
165+
r2 <= r2in;
166+
end
167+
end: r2g_proc
168+
169+
always_ff @(posedge i_wclk) begin: rx2g_proc
170+
for (int i = 0; i < DEPTH; i++) begin
171+
rx2.mem[i] <= rx2in.mem[i];
172+
end
173+
end: rx2g_proc
174+
175+
endmodule: cdc_afifo

sv/rtl/techmap/mem/ram_mmu_tech.sv

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,15 @@ localparam int DEPTH = (2**abits);
3333
logic [dbits-1:0] rdata;
3434
logic [dbits-1:0] mem[0: DEPTH - 1];
3535

36-
always_ff @(posedge i_clk) begin: rg_proc
3736

37+
always_ff @(posedge i_clk) begin: registers_proc
3838
if (i_wena == 1'b1) begin
3939
mem[int'(i_addr)] = i_wdata;
4040
end else begin
4141
rdata = mem[int'(i_addr)];
4242
end
4343

4444
o_rdata = rdata;
45-
end: rg_proc
45+
end: registers_proc
4646

4747
endmodule: ram_mmu_tech

0 commit comments

Comments
 (0)