Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
-------------------------------------------------------------------------------
-- Title : Parametrizable single-port synchronous RAM (Altera version)
-- Project : Generics RAMs and FIFOs collection
-------------------------------------------------------------------------------
-- File : generic_spram.vhd
-- Author : Tomasz Wlostowski
-- Company : CERN BE-Co-HT
-- Created : 2011-01-25
-- Last update: 2011-01-25
-- Platform :
-- Standard : VHDL'93
-------------------------------------------------------------------------------
-- Description: Single-port synchronous RAM for Altera FPGAs with:
-- - configurable address and data bus width
-- - byte-addressing mode (data bus width restricted to multiple of 8 bits)
-- Todo:
-- - loading initial contents from file
-------------------------------------------------------------------------------
-- Copyright (c) 2011 CERN
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2011-01-25 1.0 twlostow Created
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.genram_pkg.all;
entity generic_spram is
generic (
-- standard parameters
g_data_width : natural := 32;
g_size : natural := 1024;
g_with_byte_enable : boolean := false;
g_addr_conflict_resolution : string := "read_first";
g_init_file : string := ""
);
port (
rst_n_i : in std_logic := '1'; -- synchronous reset, active LO
clk_i : in std_logic; -- clock input
-- byte write enable, actiwe when g_with_byte_enable == true
bwe_i : in std_logic_vector(g_data_width/8-1 downto 0);
-- global write enable (masked by bwe_i if g_with_byte_enable = true)
we_i : in std_logic;
-- address input
a_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0);
-- data input
d_i : in std_logic_vector(g_data_width-1 downto 0);
-- data output
q_o : out std_logic_vector(g_data_width-1 downto 0)
);
end generic_spram;
architecture syn of generic_spram is
constant c_num_bytes : integer := g_data_width/8;
type t_ram_type is array(0 to g_size-1) of std_logic_vector(g_data_width-1 downto 0);
type t_ram_word_bs is array (0 to 7) of std_logic_vector(7 downto 0);
type t_ram_type_bs is array (0 to g_size - 1) of t_ram_word_bs;
signal ram : t_ram_type;
signal ram_bs : t_ram_type_bs;
signal q_local : t_ram_word_bs;
signal bwe_int : std_logic_vector(7 downto 0);
begin
assert (g_init_file = "") report "generic_spram: Memory initialization files not supported yet. Sorry :(" severity failure;
assert (g_addr_conflict_resolution = "read_first") report "generic_spram: Altera template supports only read-first mode." severity failure;
assert (((g_data_width / 8) * 8) = g_data_width) or (g_with_byte_enable = false) report "generic_spram: in byte-enabled mode the data width must be a multiple of 8" severity failure;
assert(g_data_width <= 64 or g_with_byte_enable = false) report "generic_spram: byte-selectable memories can be have 64-bit data width due to synthesis tool limitation" severity failure;
bwe_int <= std_logic_vector(to_unsigned(0, 8-bwe_i'length)) & bwe_i;
gen_with_byte_enable : if(g_with_byte_enable = true) generate
unpack : for i in 0 to c_num_bytes - 1 generate
q_o(8*(i+1) - 1 downto 8*i) <= q_local(i);
end generate unpack;
process(clk_i)
begin
if(rising_edge(clk_i)) then
if(we_i = '1') then
-- I know the code below is stupid, but it's the only way to make Quartus
-- recongnize it as a memory block
if(bwe_int(0) = '1' and g_data_width >= 8) then
ram_bs(to_integer(unsigned(a_i)))(0) <= d_i(7 downto 0);
end if;
if(bwe_int(1) = '1' and g_data_width >= 16) then
ram_bs(to_integer(unsigned(a_i)))(1) <= d_i(15 downto 8);
end if;
if(bwe_int(2) = '1' and g_data_width >= 24) then
ram_bs(to_integer(unsigned(a_i)))(2) <= d_i(23 downto 16);
end if;
if(bwe_int(3) = '1' and g_data_width >= 32) then
ram_bs(to_integer(unsigned(a_i)))(3) <= d_i(31 downto 24);
end if;
if(bwe_int(4) = '1' and g_data_width >= 40) then
ram_bs(to_integer(unsigned(a_i)))(4) <= d_i(39 downto 32);
end if;
if(bwe_int(5) = '1' and g_data_width >= 48) then
ram_bs(to_integer(unsigned(a_i)))(5) <= d_i(47 downto 40);
end if;
if(bwe_int(6) = '1' and g_data_width >= 56) then
ram_bs(to_integer(unsigned(a_i)))(6) <= d_i(55 downto 48);
end if;
if(bwe_int(7) = '1' and g_data_width >= 64) then
ram_bs(to_integer(unsigned(a_i)))(7) <= d_i(64 downto 57);
end if;
end if;
q_local <= ram_bs(to_integer(unsigned(a_i)));
end if;
end process;
end generate gen_with_byte_enable;
gen_without_byte_enable_readfirst : if(g_with_byte_enable = false) generate
process(clk_i)
begin
if rising_edge(clk_i) then
if(we_i = '1') then
ram(to_integer(unsigned(a_i))) <= d_i;
end if;
q_o <= ram(to_integer(unsigned(a_i)));
end if;
end process;
end generate gen_without_byte_enable_readfirst;
end syn;