Skip to content

Commit 3f0f8ac

Browse files
committed
AlmaIF: Add Intel FPGA compatible RAM models
Variants of xilinx_dp_blockram which infer BRAM on Arria 10.
1 parent e825cdf commit 3f0f8ac

File tree

8 files changed

+561
-38
lines changed

8 files changed

+561
-38
lines changed

openasip/CHANGES

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ Main changes and features
1313
- Added register file generator (RFGen), which allows RF RTL to be directly
1414
generated from ADF descriptions. Verilog and VHDL supported.
1515
- Improved Verilog RTL generation, especially in FUGen.
16+
- AlmaIF: add RAM models which infer the BRAM on Intel Arria 10
17+
- Enabled with bram-vendor:intel in generateprocessor parameters.
1618
- Add a latency to clock/lock cycle counter to increase clock frequency
1719

1820
Deprecation notice
Lines changed: 273 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
1+
-- Copyright (c) 2017-2023 Tampere University
2+
--
3+
-- Permission is hereby granted, free of charge, to any person obtaining a
4+
-- copy of this software and associated documentation files (the "Software"),
5+
-- to deal in the Software without restriction, including without limitation
6+
-- the rights to use, copy, modify, merge, publish, distribute, sublicense,
7+
-- and/or sell copies of the Software, and to permit persons to whom the
8+
-- Software is furnished to do so, subject to the following conditions:
9+
--
10+
-- The above copyright notice and this permission notice shall be included in
11+
-- all copies or substantial portions of the Software.
12+
--
13+
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18+
-- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19+
-- DEALINGS IN THE SOFTWARE.
20+
-------------------------------------------------------------------------------
21+
-- Title : Intel dual-port BRAM model with handshaking
22+
-- Project :
23+
-------------------------------------------------------------------------------
24+
-- File : intel_dp_blockram.vhdl
25+
-- Author : Aleksi Tervo
26+
-- Company : Tampere University
27+
-- Created : 2017-06-01
28+
-- Last update: 2023-06-08
29+
-- Platform :
30+
-- Standard : VHDL'93
31+
-------------------------------------------------------------------------------
32+
-- Description: Parametric-width byte strobe memory with handshaking
33+
-- which infers BRAM on (at least) Intel Arria 10 FPGAs
34+
-------------------------------------------------------------------------------
35+
-- Revisions :
36+
-- Date Version Author Description
37+
-- 2017-06-01 1.0 tervoa Created (xilinx_dp_blockram.vhdl)
38+
-- 2023-06-08 1.1 leppanet Modified the xilinx_db_bram to support Intel
39+
-- Arria 10 FGPA
40+
-------------------------------------------------------------------------------
41+
library ieee;
42+
use ieee.std_logic_1164.all;
43+
use std.textio.all;
44+
use ieee.numeric_std.all;
45+
46+
entity intel_dp_blockram is generic (
47+
addrw_g : integer := 10;
48+
dataw_g : integer := 32;
49+
addrw_b_g : integer := 10;
50+
dataw_b_g : integer := 32);
51+
port (
52+
clk : in std_logic;
53+
rstx : in std_logic;
54+
-- PORT A -------------------------------------------------------
55+
-- Access channel
56+
a_avalid_in : in std_logic;
57+
a_aready_out : out std_logic;
58+
a_aaddr_in : in std_logic_vector(addrw_g-1 downto 0);
59+
a_awren_in : in std_logic;
60+
a_astrb_in : in std_logic_vector((dataw_g+7)/8-1 downto 0);
61+
a_adata_in : in std_logic_vector(dataw_g-1 downto 0);
62+
-- Read channel
63+
a_rvalid_out : out std_logic;
64+
a_rready_in : in std_logic;
65+
a_rdata_out : out std_logic_vector(dataw_g-1 downto 0);
66+
-- PORT B -------------------------------------------------------
67+
-- Access channel
68+
b_avalid_in : in std_logic;
69+
b_aready_out : out std_logic;
70+
b_aaddr_in : in std_logic_vector(addrw_b_g-1 downto 0);
71+
b_awren_in : in std_logic;
72+
b_astrb_in : in std_logic_vector((dataw_b_g+7)/8-1 downto 0);
73+
b_adata_in : in std_logic_vector(dataw_b_g-1 downto 0);
74+
-- Read channel
75+
b_rvalid_out : out std_logic;
76+
b_rready_in : in std_logic;
77+
b_rdata_out : out std_logic_vector(dataw_b_g-1 downto 0)
78+
);
79+
end intel_dp_blockram;
80+
81+
architecture rtl of intel_dp_blockram is
82+
constant b_astrb_width_c : integer := dataw_b_g/8;
83+
constant a_dataw_padded_c : integer := (dataw_g+dataw_b_g-1)/dataw_b_g*dataw_b_g;
84+
constant a_astrb_width_c : integer := a_dataw_padded_c/8;
85+
constant a_padding_c : std_logic_vector(a_dataw_padded_c-dataw_g-1 downto 0)
86+
:= (others => '0');
87+
constant b_addr_padding_c : integer := addrw_b_g-addrw_g;
88+
constant need_select_c : boolean := b_addr_padding_c > 0;
89+
90+
constant a_astrb_padding_c : std_logic_vector(a_astrb_width_c-a_astrb_in'high-2
91+
downto 0) := (others => '0');
92+
constant a_word_count_c : integer := a_dataw_padded_c/dataw_b_g;
93+
94+
signal a_addr : unsigned(addrw_g-1 downto 0);
95+
signal b_addr : unsigned(addrw_g-1 downto 0);
96+
signal b_select, b_select_r : unsigned(b_addr_padding_c-1 downto 0);
97+
signal a_wdata, a_adata, a_rdata_r, a_ram_rdata_r : std_logic_vector(a_dataw_padded_c-1 downto 0);
98+
signal b_wdata, b_adata, b_ram_rdata_r : std_logic_vector(a_dataw_padded_c-1 downto 0);
99+
signal b_rdata_sel, b_rdata_r : std_logic_vector(dataw_b_g-1 downto 0);
100+
signal a_enable, b_enable : std_logic;
101+
signal a_aready_r, b_aready_r : std_logic;
102+
signal a_live_read, b_live_read : std_logic;
103+
signal a_live_read_r, b_live_read_r : std_logic;
104+
signal a_rdata_valid_r, b_rdata_valid_r : std_logic;
105+
signal a_rvalid, b_rvalid : std_logic;
106+
signal a_astrb, b_astrb : std_logic_vector(a_astrb_width_c-1 downto 0);
107+
108+
type ram_type is array (2**addrw_g-1 downto 0) of std_logic_vector
109+
(a_dataw_padded_c-1 downto 0);
110+
shared variable RAM_ARR : ram_type;
111+
112+
attribute ramstyle : string;
113+
attribute ramstyle of RAM_ARR : variable is "no_rw_check";
114+
115+
begin
116+
117+
control_comb_a : process(a_aaddr_in, a_avalid_in, a_aready_r,
118+
a_awren_in, a_live_read_r, a_rdata_valid_r)
119+
begin
120+
if a_avalid_in = '1' and a_aready_r = '1' then
121+
a_enable <= '1';
122+
a_live_read <= not a_awren_in;
123+
else
124+
a_enable <= '0';
125+
a_live_read <= '0';
126+
end if;
127+
128+
a_addr <= unsigned(a_aaddr_in);
129+
a_rvalid <= a_live_read_r or a_rdata_valid_r;
130+
end process;
131+
132+
control_comb_b : process(b_aaddr_in, b_avalid_in, b_aready_r,
133+
b_awren_in, b_live_read_r, b_rdata_valid_r,
134+
b_astrb_in, b_select, b_adata_in)
135+
begin
136+
if b_avalid_in = '1' and b_aready_r = '1' then
137+
b_enable <= '1';
138+
b_live_read <= not b_awren_in;
139+
else
140+
b_enable <= '0';
141+
b_live_read <= '0';
142+
end if;
143+
144+
b_addr <= unsigned(b_aaddr_in(b_aaddr_in'high downto b_addr_padding_c));
145+
b_select <= unsigned(b_aaddr_in(b_addr_padding_c-1 downto 0));
146+
b_astrb <= (others => '0');
147+
148+
if need_select_c then
149+
b_astrb((to_integer(b_select)+1)*b_astrb_width_c-1 downto to_integer(b_select)*b_astrb_width_c) <= b_astrb_in;
150+
else
151+
b_astrb(b_astrb_width_c-1 downto 0) <= b_astrb_in;
152+
end if;
153+
154+
for i in 0 to a_word_count_c - 1 loop
155+
b_wdata((i+1)*dataw_b_g-1 downto i*dataw_b_g) <= b_adata_in;
156+
end loop;
157+
b_rvalid <= b_live_read_r or b_rdata_valid_r;
158+
end process;
159+
160+
161+
control_sync_a : process(clk, rstx)
162+
begin
163+
if rstx = '0' then
164+
a_live_read_r <= '0';
165+
a_aready_r <= '0';
166+
a_rdata_valid_r <= '0';
167+
a_rdata_r <= (others => '0');
168+
elsif rising_edge(clk) then
169+
if a_rvalid = '1' and a_rready_in = '1' then
170+
a_rdata_valid_r <= '0';
171+
end if;
172+
173+
if a_rvalid = '1' and a_rready_in = '0' then
174+
a_aready_r <= '0';
175+
else
176+
a_aready_r <= '1';
177+
end if;
178+
179+
a_live_read_r <= a_live_read or a_live_read_r;
180+
if a_live_read_r = '1' and (a_rready_in = '1' or a_rdata_valid_r = '0') then
181+
a_live_read_r <= a_live_read;
182+
if a_rready_in = '0' or a_rdata_valid_r = '1' then
183+
a_rdata_valid_r <= '1';
184+
a_rdata_r <= a_ram_rdata_r;
185+
end if;
186+
end if;
187+
end if;
188+
end process;
189+
190+
control_sync_b : process(clk, rstx)
191+
begin
192+
if rstx = '0' then
193+
b_live_read_r <= '0';
194+
b_aready_r <= '0';
195+
b_rdata_valid_r <= '0';
196+
b_rdata_r <= (others => '0');
197+
b_select_r <= (others => '0');
198+
elsif rising_edge(clk) then
199+
200+
if b_live_read = '1' then
201+
b_select_r <= b_select;
202+
end if;
203+
204+
if b_rvalid = '1' and b_rready_in = '1' then
205+
b_rdata_valid_r <= '0';
206+
end if;
207+
208+
if b_rvalid = '1' and b_rready_in = '0' then
209+
b_aready_r <= '0';
210+
else
211+
b_aready_r <= '1';
212+
end if;
213+
214+
b_live_read_r <= b_live_read or b_live_read_r;
215+
if b_live_read_r = '1' and (b_rready_in = '1' or b_rdata_valid_r = '0') then
216+
b_live_read_r <= b_live_read;
217+
if b_rready_in = '0' or b_rdata_valid_r = '1' then
218+
b_rdata_valid_r <= '1';
219+
b_rdata_r <= b_rdata_sel;
220+
end if;
221+
end if;
222+
end if;
223+
end process;
224+
225+
a_wdata <= a_padding_c & a_adata_in;
226+
a_astrb <= a_astrb_padding_c & a_astrb_in;
227+
228+
RAM_A : process(clk)
229+
begin
230+
if rising_edge(clk) then
231+
if a_awren_in = '1' and a_enable = '1' then
232+
for b in 0 to a_astrb_width_c-1 loop
233+
if a_astrb(b) = '1' then
234+
RAM_ARR(to_integer(a_addr))((b+1)*8-1 downto b*8)
235+
:= a_wdata((b+1)*8-1 downto b*8);
236+
end if;
237+
end loop;
238+
end if;
239+
a_ram_rdata_r <= RAM_ARR(to_integer(a_addr));
240+
end if;
241+
end process;
242+
243+
RAM_B : process(clk)
244+
begin
245+
if rising_edge(clk) then
246+
if b_awren_in = '1' and b_enable = '1' then
247+
for i in 0 to a_astrb_width_c-1 loop
248+
if b_astrb(i) = '1' then
249+
RAM_ARR(to_integer(b_addr))((i+1)*8-1 downto i*8)
250+
:= b_wdata((i+1)*8-1 downto i*8);
251+
end if;
252+
end loop;
253+
end if;
254+
b_ram_rdata_r <= RAM_ARR(to_integer(b_addr));
255+
end if;
256+
end process;
257+
258+
pad: if need_select_c generate
259+
b_rdata_sel <= b_ram_rdata_r((to_integer(b_select_r)+1)*dataw_b_g-1
260+
downto to_integer(b_select_r)*dataw_b_g);
261+
end generate;
262+
no_pad: if not need_select_c generate
263+
b_rdata_sel <= b_ram_rdata_r(dataw_b_g-1 downto 0);
264+
end generate;
265+
a_rdata_out <= a_ram_rdata_r(a_rdata_out'range) when a_rdata_valid_r = '0'
266+
else a_rdata_r(a_rdata_out'range);
267+
b_rdata_out <= b_rdata_sel when b_rdata_valid_r = '0' else b_rdata_r;
268+
a_aready_out <= a_aready_r;
269+
a_rvalid_out <= a_rvalid;
270+
b_aready_out <= b_aready_r;
271+
b_rvalid_out <= b_rvalid;
272+
273+
end architecture rtl;

0 commit comments

Comments
 (0)