-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmodules.vhd
310 lines (257 loc) · 10.3 KB
/
modules.vhd
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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
-------------------------------------------------------------------------------
--
-- Title Modular VHDL peripheral
-- https://github.com/the-moog/vhdl_modular_blocks
-- File modules.vhd
-- Author Jason Morgan
--
-- Copyright © Jason Morgan 2018
-- License This work is licensed under a Creative Commons Attribution-NoDerivatives 4.0 International License.
-- CC-BY-ND, see LICENSE.TXT
--
-------------------------------------------------------------------------------
--
-- Date 17/7/2018
-- Version 2
--
-- ChangeLog
-- =========
-- Version By Date Change
--
-- 1 J A Morgan 2009 Initial version
-- 2 J A Morgan 17/7/18 Updated to VHDL2008
--
-------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_ARITH.all;
use work.utils.all;
use work.types.all;
--pragma translate_off
use STD.TEXTIO.all;
--pragma translate_on
--! @brief A modular approach to building an internal bus structure
--! @details The modular approach handles the memory map automatically.<BR>
--! NOTE: Some code is usually non-synthesizable and for test bench use only.
package modules is
--! @brief A structure to hold details about the module to save lots of signal passing
type module_t is record
--pragma translate_off
name : string( 1 to 20);
--pragma translate_on
BASE : integer;
SIZE : integer;
sixteen_bit : boolean;
end record;
--pragma translate_off
--The memory map is not synthesizable
type memory_map_t;
type memory_map_ptr is access memory_map_t;
--! @brief An access type is a dynamicly allocated instance of a type
type module_ptr is access module_t;
--! @brief a helper for creating memory maps
type memory_map_t is record
module : module_ptr;
next_entry : memory_map_ptr;
end record;
--pragma translate_on
--! @brief Used to instantiate the module in the target
impure function create_module(constant name: string; constant prev_module : module_t; signal size : positive; constant sixteen_bit : boolean := False) return module_t;
--pragma translate_off
--Memory map functions are no use inside the target hardware
--! @brief Print out the memory map
procedure print_memorymap;
--! @brief Returns the module details as a string
impure function str_module(constant module : module_t) return string;
--! @brief Returns the module base address as an integer
impure function get_module_base(module_name : string) return integer;
--! @brief Returns the module memory map as C header file text
impure function c_str_module(constant module : module_t) return string;
--! @prints out the C style memory map
procedure print_c_map;
--! @Saves the C header file text to a file
procedure write_c_header(filename : string);
--pragma translate_on
component testreg is
port (
clk : in std_logic;
rst : in std_logic;
module : in module_t;
addr : in std_logic_vector;
data : inout std_logic_vector; --Sampled on the rising edge of clk
size : out positive;
cs : in std_logic; --Module enable active high, sampled on the rising edge of clk
rd_nwr : in std_logic); --Read/not Write
end component;
component bit_io is
generic (npins : integer := 16;
rst_value : std_logic_vector(npins - 1 downto 0) := (others => '0'));
port (
clk : in std_logic;
rst : in std_logic;
module : in module_t;
addr : in std_logic_vector;
data : inout std_logic_vector; --Sampled on the rising edge of clk
io_pins : inout std_logic_vector(npins - 1 downto 0);
ip_data : out std_logic_vector(npins - 1 downto 0);
size : out positive;
cs : in std_logic; --Module enable active high, sampled on the rising edge of clk
rd_nwr : in std_logic); --Read/not Write
end component;
component bitio_op is
generic (npins : integer := 16;
rst_value : std_logic_vector(npins - 1 downto 0) := (others => '0'));
port (
clk : in std_logic;
rst : in std_logic;
module : in module_t;
addr : in std_logic_vector;
data : inout std_logic_vector; --Sampled on the rising edge of clk
op_pins : out std_logic_vector(npins - 1 downto 0);
size : out positive;
cs : in std_logic; --Module enable active high, sampled on the rising edge of clk
rd_nwr : in std_logic); --Read/not Write
end component;
component bitio_ip is
generic (npins : integer := 16);
port (
clk : in std_logic;
rst : in std_logic;
module : in module_t;
addr : in std_logic_vector;
data : inout std_logic_vector; --Sampled on the rising edge of clk
ip_pins : in std_logic_vector(npins - 1 downto 0);
ip_data : out std_logic_vector(npins - 1 downto 0);
size : out positive;
cs : in std_logic; --Module enable active high, sampled on the rising edge of clk
rd_nwr : in std_logic); --Read/not Write
end component;
end package;
package body modules is
--pragma translate_off
variable memory_map : memory_map_ptr := new memory_map_t;
--pragma translate_on
impure function create_module(constant name: string; constant prev_module : module_t; signal size : positive; constant sixteen_bit : boolean := False) return module_t is
variable module : module_t;
variable base_binary : std_logic_vector(15 downto 0);
--pragma translate_off
variable entry : memory_map_ptr := memory_map;
variable text : line;
--pragma translate_on
begin
--pragma translate_off
module.name := ucase(pads(name, module_t.name'length));
--pragma translate_on
module.base := prev_module.base + prev_module.size;
module.size := size;
module.sixteen_bit := sixteen_bit;
--pragma translate_off
--this code is no use during synthisis but it allows us to generate a useful memory map during simulation
if memory_map = null then
memory_map := new memory_map_t;
end if;
entry := memory_map;
--Entry points to the start of the map, if it's empty populate it
if entry.next_entry = null and entry.module = null then
entry.module := new module_t'(prev_module);
end if;
--Find the head entry in the map
--Or the entry that has a higher address
entry := memory_map;
find_head : while entry.next_entry /= null and entry.module /= null and entry.module.name /= module.name loop
entry := entry.next_entry;
end loop;
if entry.module.name /= module.name then
--Add the new entry to the map
entry.next_entry := new memory_map_t;
entry := entry.next_entry;
entry.module := new module_t'(module);
--write(output, "Creating " & str_module(module));
else
--Update an existing entry
entry.module := new module_t'(module);
--write(output, "Updating " & str_module(module));
end if;
--pragma translate_on
return module;
end function;
--pragma translate_off
impure function get_module_base(module_name : string) return integer is
variable entry : memory_map_ptr;
variable module_name_i : string(module_t.name'range) := ucase(pads(module_name, module_t.name'length));
begin
entry := memory_map;
scanmap : loop
exit scanmap when entry = null;
exit scanmap when entry.module.name = module_name_i;
entry := entry.next_entry;
end loop;
if entry=null then
report "Unknown module: " & module_name severity failure;
return -1;
else
return entry.module.base;
end if;
end function;
--pragma translate_on
--pragma translate_off
procedure print_memorymap is
variable entry : memory_map_ptr := memory_map;
begin
scanmap : loop
write(output, str_module(entry.module.all));
exit scanmap when entry.next_entry = null;
entry := entry.next_entry;
end loop;
end procedure;
impure function str_module(constant module : module_t) return string is
variable base_binary : std_logic_vector(15 downto 0);
begin
base_binary := std_logic_vector(conv_unsigned(module.base, base_binary'length));
return "Module: " & module.name & " (size: " & integer'image(module.size) & ") 0x" & to_hstring(base_binary);
end function;
impure function c_str_module(constant module : module_t) return string is
variable base_binary : std_logic_vector(15 downto 0);
function get_c_name(name : string) return string is
variable ret : integer;
begin
find_last_non_space : for n in name'reverse_range loop
ret := n;
exit find_last_non_space when name(n) /= ' ';
end loop;
return "CPLD_SPI_" & str_simplify(str_replace_char(name(1 to ret), ' ', '_'));
end function;
begin
base_binary := std_logic_vector(conv_unsigned(module.base, base_binary'length));
return "#DEFINE " & pads(get_c_name(module.name), 25) & " 0x" & to_hstring(base_binary);
end function;
procedure print_c_map is
variable entry : memory_map_ptr := memory_map;
variable text : line;
begin
write(text, CR & LF);
scanmap : loop
write(text, c_str_module(entry.module.all) & CR & LF);
exit scanmap when entry.next_entry = null;
entry := entry.next_entry;
end loop;
writeline(output, text);
end procedure;
procedure write_c_header(filename : string) is
file header : std.textio.text;
variable entry : memory_map_ptr := memory_map;
variable op : line;
begin
file_open(header, filename, write_mode);
write(op, "#ifdef CPLD_SPI_MAP_H" & CR & LF);
write(op, "#DEFINE CPLD_SPI_MAP_H" & CR & LF);
scanmap : loop
write(op, c_str_module(entry.module.all) & CR & LF);
exit scanmap when entry.next_entry = null;
entry := entry.next_entry;
end loop;
write(op, "#endif" & CR & LF);
writeline(header, op);
end procedure;
--pragma translate_on
end package body;