1 |
7 |
marcus.erl |
-- lem1_9min.vhd 9-bit instruction block memory, 64x1 distributed data memory
|
2 |
|
|
-- targets Spartan-2/3 on Digilent board
|
3 |
|
|
-- uses distributed RAM for data RAM, block RAM for instruction ROM & LUT tables
|
4 |
|
|
-- single clock cycle instruction execution, 9-bit fixed instruction format
|
5 |
|
|
-- Processing cycle: sync instruction read, async data RAM read, ALU, sync data RAM write 15-20ns
|
6 |
|
|
-- one clock per instruction
|
7 |
|
|
|
8 |
|
|
------ 64x1 single port RAM with async read (distributed RAM)
|
9 |
|
|
library ieee;
|
10 |
|
|
use IEEE.STD_LOGIC_1164.ALL;
|
11 |
|
|
use IEEE.std_logic_unsigned.all;
|
12 |
|
|
entity async_ram64x1 is port(
|
13 |
|
|
clk: in std_logic;
|
14 |
|
|
-- en: in std_logic;
|
15 |
|
|
we: in std_logic;
|
16 |
|
|
a: in std_logic_vector(5 downto 0);
|
17 |
|
|
di: in std_logic;
|
18 |
|
|
do: out std_logic);
|
19 |
|
|
end async_ram64x1;
|
20 |
|
|
architecture arch3 of async_ram64x1 is
|
21 |
|
|
type ram_type is array(63 downto 0) of std_logic;
|
22 |
|
|
signal RAM: ram_type;
|
23 |
|
|
begin
|
24 |
|
|
process(clk)
|
25 |
|
|
begin
|
26 |
|
|
if clk'event and clk='1' then
|
27 |
|
|
-- if en = '1' then
|
28 |
|
|
if we='1' then RAM(conv_integer(a))<=di; end if;
|
29 |
|
|
-- end if;
|
30 |
|
|
end if;
|
31 |
|
|
end process;
|
32 |
|
|
do <= RAM(conv_integer(a));
|
33 |
|
|
end arch3;
|
34 |
|
|
|
35 |
|
|
|
36 |
|
|
------ 2048x9 single port RAM with sync read (block RAM)
|
37 |
|
|
library ieee;
|
38 |
|
|
use IEEE.STD_LOGIC_1164.ALL;
|
39 |
|
|
use IEEE.std_logic_unsigned.all;
|
40 |
|
|
entity sync_ram2048x9 is port(
|
41 |
|
|
clk: in std_logic;
|
42 |
|
|
-- en: in std_logic;
|
43 |
|
|
we: in std_logic;
|
44 |
|
|
a: in std_logic_vector(10 downto 0);
|
45 |
|
|
di: in std_logic_vector(8 downto 0);
|
46 |
|
|
do: out std_logic_vector(8 downto 0));
|
47 |
|
|
end sync_ram2048x9;
|
48 |
|
|
architecture arch4 of sync_ram2048x9 is
|
49 |
|
|
type ram_type is array(2047 downto 0) of std_logic_vector(8 downto 0);
|
50 |
|
|
signal RAM: ram_type;
|
51 |
|
|
signal read_a: std_logic_vector(10 downto 0);
|
52 |
|
|
begin
|
53 |
|
|
process(clk)
|
54 |
|
|
begin
|
55 |
|
|
if clk'event and clk='1' then
|
56 |
|
|
-- if en = '1' then
|
57 |
|
|
if we='1' then RAM(conv_integer(a))<=di; end if;
|
58 |
|
|
-- end if;
|
59 |
|
|
read_a <= a;
|
60 |
|
|
end if;
|
61 |
|
|
end process;
|
62 |
|
|
do <= RAM(conv_integer(read_a));
|
63 |
|
|
end arch4;
|
64 |
|
|
|
65 |
|
|
|
66 |
|
|
------ processor definition
|
67 |
|
|
library ieee;
|
68 |
|
|
use IEEE.STD_LOGIC_1164.ALL;
|
69 |
|
|
use IEEE.std_logic_arith.all;
|
70 |
|
|
use IEEE.std_logic_misc.all;
|
71 |
|
|
use IEEE.std_logic_signed.all;
|
72 |
|
|
use work.definitions.all;
|
73 |
|
|
|
74 |
|
|
entity lem1_9 is port(
|
75 |
|
|
clk: in std_logic;
|
76 |
|
|
reset: in std_logic;
|
77 |
|
|
start: in std_logic;
|
78 |
|
|
pc_reg: out std_logic_vector(10 downto 0);
|
79 |
|
|
mem_rd: out std_logic_vector(8 downto 0);
|
80 |
|
|
nxdata: out std_logic;
|
81 |
|
|
data_we: out std_logic;
|
82 |
|
|
acc_cpy: out std_logic;
|
83 |
|
|
cry_cpy: out std_logic
|
84 |
|
|
);
|
85 |
|
|
end entity lem1_9;
|
86 |
|
|
|
87 |
|
|
architecture arch of lem1_9 is
|
88 |
|
|
-- signal naming: nx prefix: new value, x prefix: new value enable
|
89 |
|
|
type dly_type is (run, hlt); -- states: run, halt
|
90 |
|
|
signal dly, nxdly: dly_type; -- processing state variable & next dly
|
91 |
|
|
|
92 |
|
|
-- instruction register & renamings
|
93 |
|
|
signal ir: std_logic_vector(8 downto 0); -- instruction register
|
94 |
|
|
signal inst: std_logic_vector(2 downto 0); -- ir(8..6), op-code field
|
95 |
|
|
signal pc, nxpc: std_logic_vector(10 downto 0); -- program counter & next pc
|
96 |
|
|
signal xpc: std_logic; -- pc update enable
|
97 |
|
|
signal acc, nxacc: std_logic; -- accumulator & next acc
|
98 |
|
|
signal xacc: std_logic; -- acc update enable
|
99 |
|
|
signal cry, nxcry: std_logic; -- carry & next carry
|
100 |
|
|
signal xcry: std_logic; -- carry update enable
|
101 |
|
|
signal nxadr: std_logic_vector(5 downto 0); -- ir(5..0), data read/write address
|
102 |
|
|
signal nxmem: std_logic; -- write data
|
103 |
|
|
signal memrd: std_logic; -- read data
|
104 |
|
|
signal nxwe: std_logic; -- data write enable
|
105 |
|
|
|
106 |
|
|
-- Block RAM with parity bits
|
107 |
|
|
component RAMB16_S9 is
|
108 |
|
|
generic (
|
109 |
|
|
WRITE_MODE : string := "WRITE_FIRST";
|
110 |
|
|
INIT : bit_vector := X"000";
|
111 |
|
|
SRVAL : bit_vector := X"000";
|
112 |
|
|
-- use hexidecimal encoding
|
113 |
|
|
-- little endian: right most bit of INIT_00 is bit 0 of location 0
|
114 |
|
|
INIT_00 : bit_vector(255 downto 0) := X"000000000000000000000000000000000000000000000000000000000000000F";
|
115 |
|
|
INIT_01 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000";
|
116 |
|
|
INIT_02 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000";
|
117 |
|
|
INIT_03 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000";
|
118 |
|
|
INIT_04 : bit_vector(255 downto 0) := X"000000000000000000000000000000000000000000000000000000000000000F";
|
119 |
|
|
INIT_05 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000";
|
120 |
|
|
INIT_06 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000";
|
121 |
|
|
INIT_07 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000";
|
122 |
|
|
-- little endian: right most bit of INITP_00 is bit9 of location 0
|
123 |
|
|
INITP_00 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000001";
|
124 |
|
|
INITP_01 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000";
|
125 |
|
|
INITP_02 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000";
|
126 |
|
|
INITP_03 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"
|
127 |
|
|
);
|
128 |
|
|
port (DI : in STD_LOGIC_VECTOR (7 downto 0);
|
129 |
|
|
DIP : in STD_LOGIC_VECTOR (0 downto 0);
|
130 |
|
|
EN : in STD_logic;
|
131 |
|
|
WE : in STD_logic;
|
132 |
|
|
SSR : in STD_logic;
|
133 |
|
|
CLK : in STD_logic;
|
134 |
|
|
ADDR : in STD_LOGIC_VECTOR (10 downto 0);
|
135 |
|
|
DO : out STD_LOGIC_VECTOR (7 downto 0);
|
136 |
|
|
DOP : out STD_LOGIC_VECTOR (0 downto 0));
|
137 |
|
|
end component;
|
138 |
|
|
|
139 |
|
|
begin
|
140 |
|
|
-- renamings
|
141 |
|
|
inst <= ir(8 downto 6);
|
142 |
|
|
nxadr <= ir(5 downto 0);
|
143 |
|
|
|
144 |
|
|
-- monitoring signals
|
145 |
|
|
--pc_reg <= pc;
|
146 |
|
|
--acc_cpy <= acc;
|
147 |
|
|
--cry_cpy <= cry;
|
148 |
|
|
--nxdata <= nxmem;
|
149 |
|
|
--data_we <= nxwe;
|
150 |
|
|
--mem_rd <= inst & nxadr;
|
151 |
|
|
|
152 |
|
|
-- port maps
|
153 |
|
|
data_bit: entity work.async_ram64x1 port map(
|
154 |
|
|
clk => clk,
|
155 |
|
|
-- en => sig1,
|
156 |
|
|
we => nxwe,
|
157 |
|
|
a => nxadr(5 downto 0),
|
158 |
|
|
di => nxmem,
|
159 |
|
|
do => memrd);
|
160 |
|
|
|
161 |
|
|
memory: RAMB16_S9 generic map(
|
162 |
|
|
-- toggle ACC & CRY (clear ACC & CRY; set ACC & CRY; HALT)
|
163 |
|
|
-- INIT_00 => X"00000000000000000000000000000000000000000000000000000000007F1A1F",
|
164 |
|
|
-- INITP_00 => X"0000000000000000000000000000000000000000000000000000000000000000")
|
165 |
|
|
-- increment 24-bit counter at memory locations 23..0
|
166 |
|
|
-- INIT_00 => X"CD164ECE164FCF1650D01651D11652D21653D31654D41655D51656D61657D711",
|
167 |
|
|
-- INIT_01 => X"1643C31644C41645C51646C61647C71648C81649C9164ACA164BCB164CCC164D",
|
168 |
|
|
-- INIT_02 => X"00000000000000000000000000000000000000000000000040C01641C11642C2",
|
169 |
|
|
-- INITP_00 => X"0000000000000000000000000000000000000000000000492492492492492492")
|
170 |
|
|
-- four-bit adder at memory locations 59..56 (mem loc 7..4 + "00" & loc 15..14)
|
171 |
|
|
-- mem loc 63..60: active low decode of loc 15..14
|
172 |
|
|
-- mem loc 55..48: active low drive of 7-seg display
|
173 |
|
|
-- HELLO UJOrLd
|
174 |
|
|
INIT_00 => X"CD164ECE164FCF1650D01651D11652D21653D31654D41655D51656D61657D711",
|
175 |
|
|
INIT_01 => X"1643C31644C41645C51646C61647C71648C81649C9164ACA164BCB164CCC164D",
|
176 |
|
|
INIT_02 => X"177E8F7C8E7D4FCE7F4F8E7BC2167AC31679C48E78C58F1040C01641C11642C2",
|
177 |
|
|
INIT_03 => X"6C38AA776F6E6D792AF86939F86A197ABB6B3A6C38F96D38BA6E38BB6F3ABB70",
|
178 |
|
|
INIT_04 => X"39FB726F6EAD736FAB746F6B682CBB682A1978B9756F6C6829FA6839AA766F69",
|
179 |
|
|
INIT_05 => X"000000000000000000000000000000000000000000000000000071687A3BF868",
|
180 |
|
|
INITP_00 => X"00000000000000000000001C993CA793CF9129242A4924492492492492492492")
|
181 |
|
|
|
182 |
|
|
-- HEllo UJorld
|
183 |
|
|
-- INIT_00 => X"CD164ECE164FCF1650D01651D11652D21653D31654D41655D51656D61657D711",
|
184 |
|
|
-- INIT_01 => X"1643C31644C41645C51646C61647C71648C81649C9164ACA164BCB164CCC164D",
|
185 |
|
|
-- INIT_02 => X"177E8F7C8E7D4FCE7F4F8E7BC2167AC31679C48E78C58F1040C01641C11642C2",
|
186 |
|
|
-- INIT_03 => X"79BA6E7B1939BA762F7A193839BB6F2F7B193839BA6F78797ABB77797A7BF870",
|
187 |
|
|
-- INIT_04 => X"BB6D2D78797AFB6D2D7B1939BA6D787BFA752E7879BB6E2E7A193839BB6E2E78",
|
188 |
|
|
-- INIT_05 => X"BB6A79BA722B787AF96B2B787BF96B7ABB733A2C7BF96C78BB74372D7A193839",
|
189 |
|
|
-- INIT_06 => X"00000000000000000000000000000000000000000000712A7A1938BB6A2A7879",
|
190 |
|
|
-- INITP_00 => X"00000000000001A72739393B3CD339B394D9B39C2A4924492492492492492492")
|
191 |
|
|
--
|
192 |
|
|
port map(
|
193 |
|
|
DI => (others => '0'),
|
194 |
|
|
DIP => (others => '0'),
|
195 |
|
|
EN => '1',
|
196 |
|
|
WE => '0',
|
197 |
|
|
SSR => '0',
|
198 |
|
|
CLK => clk,
|
199 |
|
|
ADDR => nxpc(10 downto 0),
|
200 |
|
|
DO => ir(7 downto 0),
|
201 |
|
|
DOP => ir(8 downto 8));
|
202 |
|
|
|
203 |
|
|
--memory: entity work.sync_ram2048x9 port map(
|
204 |
|
|
-- clk => clk,
|
205 |
|
|
---- en => vcc,
|
206 |
|
|
-- we => gnd,
|
207 |
|
|
-- a => nxpc(10 downto 0),
|
208 |
|
|
-- di => (others => '0'),
|
209 |
|
|
-- do => ir);
|
210 |
|
|
|
211 |
|
|
-- instruction processing
|
212 |
|
|
decode: process(dly,start,memrd,acc,cry,inst,pc,ir) begin
|
213 |
|
|
-- default values for update enables & "nx" signals
|
214 |
|
|
nxdly <= hlt;
|
215 |
|
|
xpc <= '-';
|
216 |
|
|
nxpc <= (others => '-');
|
217 |
|
|
nxwe <= '-';
|
218 |
|
|
nxmem <= '-';
|
219 |
|
|
xacc <= '-';
|
220 |
|
|
nxacc <= '-';
|
221 |
|
|
xcry <= '-';
|
222 |
|
|
nxcry <= '-';
|
223 |
|
|
|
224 |
|
|
-- state dispatch
|
225 |
|
|
case dly is
|
226 |
|
|
when hlt =>
|
227 |
|
|
if start = '1' then nxdly <= run; else nxdly <= hlt; end if;
|
228 |
|
|
xacc <= '1'; nxacc <= '0';
|
229 |
|
|
xpc <= '1'; nxpc <= (others => '0'); -- keep PC reset
|
230 |
|
|
xcry <= '1'; nxcry <= '0';
|
231 |
|
|
nxwe <= '0';
|
232 |
|
|
|
233 |
|
|
when run =>
|
234 |
|
|
-- op-code dispatch
|
235 |
|
|
case inst is
|
236 |
|
|
|
237 |
|
|
when opMSC =>
|
238 |
|
|
case ir(5 downto 4) is
|
239 |
|
|
when opHLT =>
|
240 |
|
|
nxdly <= hlt;
|
241 |
|
|
|
242 |
|
|
when opAnC =>
|
243 |
|
|
nxdly <= run;
|
244 |
|
|
case ir(3 downto 0) is
|
245 |
|
|
when "0000" => xacc <= '1'; nxacc <= '0'; xcry <= '1'; nxcry <= '0'; -- A,C = 0,0
|
246 |
|
|
when "0001" => xacc <= '1'; nxacc <= '0'; xcry <= '1'; nxcry <= '1'; -- A,C = 0,1
|
247 |
|
|
when "0010" => xacc <= '1'; nxacc <= '1'; xcry <= '1'; nxcry <= '0'; -- A,C = 1,0
|
248 |
|
|
when "0011" => xacc <= '1'; nxacc <= '1'; xcry <= '1'; nxcry <= '1'; -- A,C = 1,1
|
249 |
|
|
when "0100" => xacc <= '0'; xcry <= '1'; nxcry <= '0'; -- C = 0
|
250 |
|
|
when "0101" => xacc <= '0'; xcry <= '1'; nxcry <= '1'; -- C = 1
|
251 |
|
|
when "0110" => xacc <= '1'; nxacc <= '0'; xcry <= '0'; -- A = 0
|
252 |
|
|
when "0111" => xacc <= '1'; nxacc <= '1'; xcry <= '0'; -- A = 1
|
253 |
|
|
when "1000" => xacc <= '0'; xcry <= '1'; nxcry <= acc OR cry; -- C = A | C
|
254 |
|
|
when "1001" => xacc <= '1'; nxacc <= not acc; xcry <= '0'; -- A = not A
|
255 |
|
|
when "1010" => xacc <= '0'; xcry <= '1'; nxcry <= not cry; -- C = not C
|
256 |
|
|
when "1011" => xacc <= '1'; nxacc <= not acc; xcry <= '1'; nxcry <= not cry; -- A,C = not A, not C
|
257 |
|
|
when "1100" => xacc <= '0'; xcry <= '1'; nxcry <= acc AND cry; -- C = A & C
|
258 |
|
|
when "1101" => xacc <= '1'; nxacc <= cry; xcry <= '0'; -- A = C
|
259 |
|
|
when "1110" => xacc <= '0'; xcry <= '1'; nxcry <= acc; -- C = A
|
260 |
|
|
when "1111" => xacc <= '1'; nxacc <= cry; xcry <= '1'; nxcry <= acc; -- A,C = C,A
|
261 |
|
|
when others => xacc <= '0'; xcry <= '0';
|
262 |
|
|
end case;
|
263 |
|
|
xpc <= '1'; nxpc <= pc + 1;
|
264 |
|
|
nxwe <= '0';
|
265 |
|
|
when others => null;
|
266 |
|
|
end case;
|
267 |
|
|
|
268 |
|
|
when opST =>
|
269 |
|
|
nxdly<= run;
|
270 |
|
|
xacc <= '0';
|
271 |
|
|
xpc <= '1'; nxpc <= pc + 1;
|
272 |
|
|
xcry <= '0';
|
273 |
|
|
nxwe <= '1'; nxmem <= acc;
|
274 |
|
|
|
275 |
|
|
when opLD =>
|
276 |
|
|
nxdly<= run;
|
277 |
|
|
xacc <= '1'; nxacc <= memrd;
|
278 |
|
|
xpc <= '1'; nxpc <= pc + 1;
|
279 |
|
|
xcry <= '0';
|
280 |
|
|
nxwe <= '0';
|
281 |
|
|
|
282 |
|
|
when opLDC =>
|
283 |
|
|
nxdly<= run;
|
284 |
|
|
xacc <= '1'; nxacc <= not memrd;
|
285 |
|
|
xpc <= '1'; nxpc <= pc + 1;
|
286 |
|
|
xcry <= '0';
|
287 |
|
|
nxwe <= '0';
|
288 |
|
|
|
289 |
|
|
when opAND =>
|
290 |
|
|
nxdly<= run;
|
291 |
|
|
xacc <= '1'; nxacc <= acc and memrd;
|
292 |
|
|
xpc <= '1'; nxpc <= pc + 1;
|
293 |
|
|
xcry <= '0';
|
294 |
|
|
nxwe <= '0';
|
295 |
|
|
|
296 |
|
|
when opOR =>
|
297 |
|
|
nxdly<= run;
|
298 |
|
|
xacc <= '1'; nxacc <= acc or memrd;
|
299 |
|
|
xpc <= '1'; nxpc <= pc + 1;
|
300 |
|
|
xcry <= '0';
|
301 |
|
|
nxwe <= '0';
|
302 |
|
|
|
303 |
|
|
when opXOR =>
|
304 |
|
|
nxdly<= run;
|
305 |
|
|
xacc <= '1'; nxacc <= acc xor memrd;
|
306 |
|
|
xpc <= '1'; nxpc <= pc + 1;
|
307 |
|
|
xcry <= '0';
|
308 |
|
|
nxwe <= '0';
|
309 |
|
|
|
310 |
|
|
when opADC =>
|
311 |
|
|
nxdly<= run;
|
312 |
|
|
xacc <= '1'; nxacc <= acc xor memrd xor cry;
|
313 |
|
|
xpc <= '1'; nxpc <= pc + 1;
|
314 |
|
|
xcry <= '1'; nxcry <= (acc and cry) or (acc and memrd) or (cry and memrd);
|
315 |
|
|
nxwe <= '0';
|
316 |
|
|
|
317 |
|
|
when others => null;
|
318 |
|
|
end case;
|
319 |
|
|
when others => null;
|
320 |
|
|
end case;
|
321 |
|
|
|
322 |
|
|
end process decode;
|
323 |
|
|
|
324 |
|
|
-- all processor register updates
|
325 |
|
|
update: process(clk,reset) begin
|
326 |
|
|
if reset='1' -- master reset
|
327 |
|
|
then dly <= hlt;
|
328 |
|
|
acc <= '0';
|
329 |
|
|
cry <= '0';
|
330 |
|
|
pc <= (others => '0');
|
331 |
|
|
-- monitoring signals
|
332 |
|
|
acc_cpy <= '0';
|
333 |
|
|
cry_cpy <= '0';
|
334 |
|
|
nxdata <= '0';
|
335 |
|
|
data_we <= '0';
|
336 |
|
|
pc_reg <= (others => '0');
|
337 |
|
|
mem_rd <= (others => '0');
|
338 |
|
|
elsif (clk'event and clk='1')
|
339 |
|
|
then
|
340 |
|
|
-- state variable update
|
341 |
|
|
dly <= nxdly;
|
342 |
|
|
-- accumulator update
|
343 |
|
|
if xacc = '1' then acc <= nxacc; end if;
|
344 |
|
|
-- update carry bit
|
345 |
|
|
if xcry = '1' then cry <= nxcry; end if;
|
346 |
|
|
-- Program counter update
|
347 |
|
|
if xpc = '1' then pc <= nxpc; end if;
|
348 |
|
|
---- monitoring signals
|
349 |
|
|
acc_cpy <= acc;
|
350 |
|
|
cry_cpy <= cry;
|
351 |
|
|
nxdata <= nxmem;
|
352 |
|
|
data_we <= nxwe;
|
353 |
|
|
pc_reg <= pc;
|
354 |
|
|
mem_rd <= inst & nxadr;
|
355 |
|
|
end if;
|
356 |
|
|
end process update;
|
357 |
|
|
|
358 |
|
|
end arch;
|