Skip to content

Commit feb172f

Browse files
rewrite with Veryl
1 parent 985e714 commit feb172f

21 files changed

+2533
-0
lines changed

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,9 @@
11
*.f
22
Gemfile.lock
3+
4+
# Veryl
5+
Veryl.lock
6+
/.build
7+
/dependencies
8+
/generated
9+
/map

Veryl.toml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
[project]
2+
name = "pzbcm"
3+
version = "0.1.0"
4+
authors = ["Taichi Ishitani <ishitani@pezy.co.jp>"]
5+
license = "Apache-2.0"
6+
repository = "https://github.com/pezy-computing/pzbcm"
7+
8+
[build]
9+
clock_type = "posedge"
10+
reset_type = "async_low"
11+
filelist_type = "flgen"
12+
target = {type = "directory", path = "generated"}
13+
sourcemap_target = {type = "directory", path = "map"}
14+
omit_project_prefix = true
15+
reset_low_suffix = "_n"
16+
hashed_mangled_name = true
17+
18+
[format]
19+
indent_width = 2

rtl/pzbcm_sram/pzbcm_sram.veryl

Lines changed: 311 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,311 @@
1+
//========================================
2+
//
3+
// Copyright (c) 2025 PEZY Computing, K.K.
4+
//
5+
//========================================
6+
pub module pzbcm_sram::<PKG: pzbcm_sram_proto_pkg>#(
7+
param OUTPUT_FIFO : bool = true,
8+
param WRITE_FIRST : bool = true,
9+
param RESET_DATA_PATH: bool = true,
10+
)(
11+
i_clk : input clock ,
12+
i_rst : input reset ,
13+
i_clear : input logic ,
14+
i_sram_config: input PKG::SRAM_CONFIG_TYPE ,
15+
port_if : modport pzbcm_sram_if::<PKG>::sram,
16+
) {
17+
import PKG::*;
18+
19+
var write_ready : logic<BANKS>;
20+
var write_enable : logic<BANKS>;
21+
var read_ready : logic<BANKS>;
22+
var read_enable : logic<BANKS>;
23+
var read_enable_delay: logic<READ_LATENCY, BANKS>;
24+
var read_data : logic<BANKS, DATA_WIDTH>;
25+
var read_data_valid : logic<BANKS>;
26+
var read_info : READ_INFO_TYPE;
27+
var read_busy : logic;
28+
var ram_read_data : logic<DATA_WIDTH>;
29+
var fifo_ready : logic;
30+
31+
//--------------------------------------------------------------
32+
// SRAM instance
33+
//--------------------------------------------------------------
34+
always_comb {
35+
port_if.write_ready = write_ready != '0;
36+
port_if.read_ready = read_ready != '0;
37+
}
38+
39+
for i in 0..BANKS :g_bank {
40+
var match_write : bool;
41+
var write_pointer: logic<RAM_POINTER_WIDTH>;
42+
var match_read : bool;
43+
var read_pointer : logic<RAM_POINTER_WIDTH>;
44+
45+
always_comb {
46+
match_write = match_bank(i, port_if.write_pointer);
47+
write_pointer = get_ram_pointer(port_if.write_pointer);
48+
match_read = match_bank(i, port_if.read_pointer);
49+
read_pointer = get_ram_pointer(port_if.read_pointer);
50+
51+
if !SINGLE_PORT {
52+
write_ready[i] = match_write;
53+
write_enable[i] = port_if.write_valid && write_ready[i];
54+
read_ready[i] = match_read && fifo_ready;
55+
read_enable[i] = port_if.read_valid && read_ready[i];
56+
} else if WRITE_FIRST {
57+
write_ready[i] = match_write;
58+
write_enable[i] = port_if.write_valid && write_ready[i];
59+
read_ready[i] = match_read && fifo_ready && (!write_enable[i]);
60+
read_enable[i] = port_if.read_valid && read_ready[i];
61+
} else {
62+
read_ready[i] = match_read && fifo_ready;
63+
read_enable[i] = port_if.read_valid && read_ready[i];
64+
write_ready[i] = match_write && (!read_enable[i]);
65+
write_enable[i] = port_if.write_valid && write_ready[i];
66+
}
67+
}
68+
69+
if SINGLE_PORT :g {
70+
var enable : logic<1>;
71+
var write : logic;
72+
var ram_pointer: logic<1, RAM_POINTER_WIDTH>;
73+
74+
always_comb {
75+
enable[0] = write_enable[i] || read_enable[i];
76+
if write_enable[i] {
77+
write = '1;
78+
ram_pointer[0] = write_pointer;
79+
} else {
80+
write = '0;
81+
ram_pointer[0] = read_pointer;
82+
}
83+
}
84+
85+
inst u_sram_wrapper: SRAM_WRAPPER #(
86+
WORDS : RAM_WORDS ,
87+
DATA_WIDTH : DATA_WIDTH ,
88+
POINTER_WIDTH : RAM_POINTER_WIDTH,
89+
N_PORT : 1 ,
90+
SRAM_CONFIG_TYPE: SRAM_CONFIG_TYPE ,
91+
)(
92+
i_clk : i_clk ,
93+
i_enable : enable ,
94+
i_pointer: ram_pointer ,
95+
i_write : write ,
96+
i_data : port_if.write_data,
97+
o_data : read_data[i] ,
98+
i_config : i_sram_config ,
99+
);
100+
} else {
101+
var enable : logic<2> ;
102+
var ram_pointer: logic<2, RAM_POINTER_WIDTH>;
103+
104+
always_comb {
105+
enable[0] = write_enable[i];
106+
ram_pointer[0] = write_pointer;
107+
enable[1] = read_enable[i];
108+
ram_pointer[1] = read_pointer;
109+
}
110+
111+
inst u_sram_wrapper: SRAM_WRAPPER #(
112+
DATA_WIDTH : DATA_WIDTH ,
113+
POINTER_WIDTH : RAM_POINTER_WIDTH,
114+
N_PORT : 2 ,
115+
SRAM_CONFIG_TYPE: SRAM_CONFIG_TYPE ,
116+
)(
117+
i_clk : i_clk ,
118+
i_enable : enable ,
119+
i_pointer: ram_pointer ,
120+
i_write : '0 ,
121+
i_data : port_if.write_data,
122+
o_data : read_data[i] ,
123+
i_config : i_sram_config ,
124+
);
125+
}
126+
}
127+
128+
function get_ram_pointer_map() -> bit<RAM_POINTER_WIDTH, 16> {
129+
var map : bit<RAM_POINTER_WIDTH, 16>;
130+
var bank_lsb : u16;
131+
var bank_msb : u16;
132+
var ram_pointer_pos: u16;
133+
134+
if BANKS >= 2 {
135+
bank_lsb = BANK_LSB;
136+
bank_msb = bank_lsb - BANK_WIDTH - 1;
137+
} else {
138+
bank_lsb = 0;
139+
bank_msb = 0;
140+
}
141+
142+
ram_pointer_pos = 0;
143+
for i: u16 in 0..POINTER_WIDTH {
144+
if (BANKS == 1) || ((i <: bank_lsb) || (i >: bank_msb)) {
145+
map[ram_pointer_pos] = i;
146+
ram_pointer_pos += 1;
147+
}
148+
}
149+
150+
return map;
151+
}
152+
153+
const POINTER_MAP: bit<RAM_POINTER_WIDTH, 16> = get_ram_pointer_map();
154+
155+
function get_ram_pointer(
156+
pointer: input logic<POINTER_WIDTH>
157+
) -> logic<RAM_POINTER_WIDTH> {
158+
if BANKS == 1 {
159+
return pointer;
160+
} else if BANK_LSB == 0 {
161+
return (pointer >> BANK_WIDTH) as RAM_POINTER_WIDTH;
162+
} else {
163+
var ram_pointer: logic<RAM_POINTER_WIDTH>;
164+
for i: u16 in 0..RAM_POINTER_WIDTH {
165+
ram_pointer[i] = pointer[POINTER_MAP[i]];
166+
}
167+
168+
return ram_pointer;
169+
}
170+
}
171+
172+
function match_bank(
173+
bank_index: input u16 ,
174+
pointer : input logic<POINTER_WIDTH>,
175+
) -> bool {
176+
if BANKS == 1 {
177+
return true;
178+
} else {
179+
let bank: logic<BANK_WIDTH> = pointer[BANK_LSB+:BANK_WIDTH];
180+
return bank == (bank_index as BANK_WIDTH);
181+
}
182+
}
183+
184+
//--------------------------------------------------------------
185+
// Read Data
186+
//--------------------------------------------------------------
187+
always_comb {
188+
port_if.read_busy = read_busy;
189+
}
190+
191+
always_comb {
192+
read_busy = read_enable_delay != '0;
193+
read_data_valid = read_enable_delay[READ_LATENCY - 1];
194+
}
195+
196+
always_ff {
197+
if_reset {
198+
read_enable_delay = '0;
199+
} else if i_clear {
200+
read_enable_delay = '0;
201+
} else {
202+
for i: u16 in 0..READ_LATENCY {
203+
if i == 0 {
204+
read_enable_delay[i] = read_enable;
205+
} else {
206+
read_enable_delay[i] = read_enable_delay[i - 1];
207+
}
208+
}
209+
}
210+
}
211+
212+
if READ_INFO :g_read_info {
213+
inst u_read_info_delay: $std::delay #(
214+
DELAY: READ_LATENCY ,
215+
TYPE : READ_INFO_TYPE,
216+
) (
217+
i_clk: i_clk ,
218+
i_rst: i_rst ,
219+
i_d : port_if.read_info,
220+
o_d : read_info ,
221+
);
222+
} else {
223+
always_comb {
224+
read_info = 0 as READ_INFO_TYPE;
225+
}
226+
}
227+
228+
if BANKS == 1 :g_ram_read_data {
229+
always_comb {
230+
ram_read_data = read_data[0];
231+
}
232+
} else {
233+
inst u_read_data_mux: $std::mux #(
234+
WIDTH : DATA_WIDTH ,
235+
ENTRIES: BANKS ,
236+
KIND : $std::selector_pkg::selector_kind::ONEHOT,
237+
)(
238+
i_select: read_data_valid,
239+
i_data : read_data ,
240+
o_data : ram_read_data ,
241+
);
242+
}
243+
244+
//--------------------------------------------------------------
245+
// Output FIFO
246+
//--------------------------------------------------------------
247+
if OUTPUT_FIFO :g_output_fifo {
248+
const FIFO_DATA_WIDTH: u16 = DATA_WIDTH + (if READ_INFO ? $bits(READ_INFO_TYPE) : 0);
249+
const FIFO_DEPTH : u16 = READ_LATENCY + 2;
250+
251+
var empty : logic;
252+
var almost_full: logic;
253+
var full : logic;
254+
var push : logic;
255+
var push_data : logic<FIFO_DATA_WIDTH>;
256+
var pop : logic;
257+
var pop_data : logic<FIFO_DATA_WIDTH>;
258+
259+
always_comb {
260+
port_if.fifo_empty = empty;
261+
port_if.fifo_almost_full = almost_full;
262+
port_if.fifo_full = full;
263+
}
264+
265+
always_comb {
266+
fifo_ready = (!almost_full) || ((!read_busy) && (!full));
267+
}
268+
269+
always_comb {
270+
push = read_data_valid != '0;
271+
push_data = {read_info, ram_read_data} as FIFO_DATA_WIDTH;
272+
}
273+
274+
always_comb {
275+
pop = port_if.read_data_ready;
276+
port_if.read_data_valid = !empty;
277+
port_if.read_data = pop_data as pzbcm_sram_read_data;
278+
}
279+
280+
inst u_read_data_fifo: $std::fifo #(
281+
WIDTH : FIFO_DATA_WIDTH,
282+
DEPTH : FIFO_DEPTH ,
283+
THRESHOLD : 2 ,
284+
RESET_DATA_FF : RESET_DATA_PATH,
285+
)(
286+
i_clk : i_clk ,
287+
i_rst : i_rst ,
288+
i_clear : i_clear ,
289+
o_empty : empty ,
290+
o_almost_full: almost_full,
291+
o_full : full ,
292+
o_word_count : _ ,
293+
i_push : push ,
294+
i_data : push_data ,
295+
i_pop : pop ,
296+
o_data : pop_data ,
297+
);
298+
} else {
299+
always_comb {
300+
fifo_ready = '1;
301+
}
302+
303+
always_comb {
304+
port_if.fifo_empty = '1;
305+
port_if.fifo_almost_full = '0;
306+
port_if.fifo_full = '0;
307+
port_if.read_data_valid = read_data_valid;
308+
port_if.read_data = pzbcm_sram_read_data'{ data: ram_read_data, info: read_info };
309+
}
310+
}
311+
}

0 commit comments

Comments
 (0)