├── ISE
├── TPU_miniSpartan6plus.xise
└── minispartan6.ucf
├── README.md
├── isa
└── TPU Instruction Set Architecture.pdf
├── tasm
└── tasm_main.cs
└── vhdl
├── core
├── alu.vhd
├── control_unit.vhd
├── core.vhd
├── decode.vhd
├── mem_controller.vhd
├── pc_unit.vhd
├── reg16_8.vhd
└── tpu_constants.vhd
├── dvid
├── TDMS_encoder.vhd
├── dvid.vhd
└── vga_gen.vhd
├── test
└── tpu_top_test.vhd
├── top
├── clocking.vhd
├── ebram.vhd
├── ebram2port.vhd
├── empty_font_rom.vhd
├── text_gen.vhd
└── tpu_top.vhd
└── xilinx
├── uart_rx6.vhd
└── uart_tx6.vhd
/ISE/TPU_miniSpartan6plus.xise:
--------------------------------------------------------------------------------
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 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 |
419 |
420 |
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
--------------------------------------------------------------------------------
/ISE/minispartan6.ucf:
--------------------------------------------------------------------------------
1 | #Created by Constraints Editor (xc6slx25-ftg256-3) - 2015/01/02
2 | NET "I_clk" PERIOD = 20 ns | LOC = "K3" ;
3 |
4 | NET "O_LEDS<0>" LOC="P11" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW;
5 | NET "O_LEDS<1>" LOC="N9" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW;
6 | NET "O_LEDS<2>" LOC="M9" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW;
7 | NET "O_LEDS<3>" LOC="P9" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW;
8 | NET "O_LEDS<4>" LOC="T8" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW;
9 | NET "O_LEDS<5>" LOC="N8" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW;
10 | NET "O_LEDS<6>" LOC="P8" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW;
11 | NET "O_LEDS<7>" LOC="P7" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW;
12 |
13 | NET "I_SWITCHES<0>" LOC="L1" | IOSTANDARD=LVTTL | PULLUP;
14 | NET "I_SWITCHES<1>" LOC="L3" | IOSTANDARD=LVTTL | PULLUP;
15 | NET "I_SWITCHES<2>" LOC="L4" | IOSTANDARD=LVTTL | PULLUP;
16 | NET "I_SWITCHES<3>" LOC="L5" | IOSTANDARD=LVTTL | PULLUP;
17 |
18 | NET "I_rx" LOC = M7 | IOSTANDARD = LVTTL; #FTDI M7
19 | NET "O_tx" LOC = N6 | IOSTANDARD = LVTTL; #FTDI N6
20 |
21 | NET "hdmi_out_p<0>" LOC="C13" | IOSTANDARD="TMDS_33"; # IO_L63P_SCP7_0
22 | NET "hdmi_out_n<0>" LOC="A13" | IOSTANDARD="TMDS_33"; # IO_L63N_SCP6_0
23 | NET "hdmi_out_p<1>" LOC="B12" | IOSTANDARD="TMDS_33"; # IO_L62P_0
24 | NET "hdmi_out_n<1>" LOC="A12" | IOSTANDARD="TMDS_33"; # IO_L62N_VREF_0
25 | NET "hdmi_out_p<2>" LOC="C11" | IOSTANDARD="TMDS_33"; # IO_L39P_0
26 | NET "hdmi_out_n<2>" LOC="A11" | IOSTANDARD="TMDS_33"; # IO_L39N_0
27 | NET "hdmi_out_p<3>" LOC="B14" | IOSTANDARD="TMDS_33"; # IO_L65P_SCP3_0
28 | NET "hdmi_out_n<3>" LOC="A14" | IOSTANDARD="TMDS_33"; # IO_L65N_SCP2_0
29 |
30 |
31 | # Audio Pins
32 | NET "O_AUDIO1" LOC="B8" | IOSTANDARD=LVTTL;
33 | NET "O_AUDIO2" LOC="A8" | IOSTANDARD=LVTTL;
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # TPU
2 | TPU, The Test Processing Unit. Or Terrible Processing Unit. A simple 16-bit CPU in VHDL for education as to the dataflow within a CPU. Designed to run on miniSpartan6+.
3 |
4 | Some code in vhdl/top and vhdl/dvid is not owned by myself. Please refer to those files for information.
5 |
6 | This is implemented with ISE Webpack (The free Xilinx tools) however the project is not committed here - yet.
7 |
8 | This is the implementation being written about over at http://labs.domipheus.com/blog/category/projects/tpu/
9 |
--------------------------------------------------------------------------------
/isa/TPU Instruction Set Architecture.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Domipheus/TPU/458a9877a6598cdd750ad1a5b8826d2e022837d3/isa/TPU Instruction Set Architecture.pdf
--------------------------------------------------------------------------------
/vhdl/core/alu.vhd:
--------------------------------------------------------------------------------
1 | ----------------------------------------------------------------------------------
2 | -- Project Name: TPU
3 | -- Description: ALU unit of TPU
4 | --
5 | -- Revision: 2
6 | ----------------------------------------------------------------------------------
7 | library IEEE;
8 | use IEEE.STD_LOGIC_1164.ALL;
9 |
10 | use IEEE.NUMERIC_STD.ALL;
11 |
12 | library work;
13 | use work.tpu_constants.all;
14 |
15 | entity alu is
16 | Port ( I_clk : in STD_LOGIC;
17 | I_en : in STD_LOGIC;
18 | I_dataA : in STD_LOGIC_VECTOR (15 downto 0);
19 | I_dataB : in STD_LOGIC_VECTOR (15 downto 0);
20 | I_dataDwe : in STD_LOGIC;
21 | I_aluop : in STD_LOGIC_VECTOR (4 downto 0);
22 | I_PC : in STD_LOGIC_VECTOR (15 downto 0);
23 | I_dataIMM : in STD_LOGIC_VECTOR (15 downto 0);
24 | O_dataResult : out STD_LOGIC_VECTOR (15 downto 0);
25 | O_dataWriteReg : out STD_LOGIC;
26 | O_shouldBranch : out STD_LOGIC;
27 | I_idata: in STD_LOGIC_VECTOR(15 downto 0); -- interrupt register data
28 | I_set_idata:in STD_LOGIC; -- set interrup register data
29 | I_set_irpc: in STD_LOGIC; -- set interrupt return pc
30 | O_int_enabled: out STD_LOGIC;
31 | O_memMode : out STD_LOGIC
32 | );
33 | end alu;
34 |
35 | architecture Behavioral of alu is
36 | -- The internal register for results of operations.
37 | -- 16 bit + carry/overflow
38 | signal s_result: STD_LOGIC_VECTOR(17 downto 0) := (others => '0');
39 |
40 | signal s_shouldBranch: STD_LOGIC := '0';
41 | signal s_interrupt_register: STD_LOGIC_VECTOR(15 downto 0) := X"0000";
42 | signal s_interrupt_rpc: STD_LOGIC_VECTOR(15 downto 0) := X"0000";
43 | signal s_interrupt_enable: std_logic := '0'; -- interrupts are disabled by default.
44 | signal s_prev_interrupt_enable: std_logic := '0';
45 |
46 | -- TODO: this is an in-test signal
47 | signal s_32_result: STD_LOGIC_VECTOR(31 downto 0) := (others => '0');
48 | signal s_32_cyclecounter: unsigned(31 downto 0) := (others => '0');
49 | begin
50 | O_int_enabled <= s_interrupt_enable;
51 |
52 | process (I_clk)
53 | begin
54 | if rising_edge(I_clk) then
55 | s_32_cyclecounter <= s_32_cyclecounter + 1;
56 | end if;
57 | end process;
58 |
59 | process (I_clk, I_en)
60 | begin
61 | if rising_edge(I_clk) then
62 | if I_set_irpc = '1' then
63 | s_interrupt_rpc <= I_PC;
64 | end if;
65 | if I_set_idata = '1' then
66 | s_prev_interrupt_enable <= s_interrupt_enable;
67 | s_interrupt_enable <= '0';
68 | s_interrupt_register <= I_idata;
69 | end if;
70 | if I_en = '1' then
71 | O_dataWriteReg <= I_dataDwe;
72 | case I_aluop(4 downto 1) is
73 | -- TODO: Handle correct overflow result (s_result 17)
74 | when OPCODE_ADD =>
75 | if I_aluop(0) = '0' then
76 | if I_dataImm(0) = '0' then
77 | s_result(16 downto 0) <= std_logic_vector(unsigned('0' & I_dataA) + unsigned( '0' & I_dataB));
78 | else
79 | s_result(16 downto 0) <= std_logic_vector(unsigned('0' & I_dataA) + unsigned( '0' & X"000" & I_dataIMM(4 downto 1)));
80 | end if;
81 | else
82 | s_result(16 downto 0) <= std_logic_vector(signed(I_dataA(15) & I_dataA) + signed( I_dataB(15) & I_dataB));
83 | end if;
84 | s_shouldBranch <= '0';
85 |
86 | -- TODO: Handle correct overflow result (s_result 17)
87 | when OPCODE_SUB =>
88 | if I_aluop(0) = '0' then
89 | if I_dataImm(0) = '0' then
90 | s_result(16 downto 0) <= std_logic_vector(unsigned('0' & I_dataA) - unsigned( '0' & I_dataB));
91 | else
92 | s_result(16 downto 0) <= std_logic_vector(unsigned('0' & I_dataA) - unsigned( '0' & X"000" & I_dataIMM(4 downto 1)));
93 | end if;
94 | else
95 | s_result(16 downto 0) <= std_logic_vector(signed(I_dataA(15) & I_dataA) - signed( I_dataB(15) & I_dataB));
96 | end if;
97 | s_shouldBranch <= '0';
98 |
99 | when OPCODE_OR =>
100 | s_result(15 downto 0) <= I_dataA or I_dataB;
101 | s_shouldBranch <= '0';
102 |
103 | when OPCODE_XOR =>
104 | s_result(15 downto 0) <= I_dataA xor I_dataB;
105 | s_shouldBranch <= '0';
106 |
107 | when OPCODE_AND =>
108 | s_result(15 downto 0) <= I_dataA and I_dataB;
109 | s_shouldBranch <= '0';
110 |
111 | when OPCODE_NOT =>
112 | s_result(15 downto 0) <= not I_dataA;
113 | s_shouldBranch <= '0';
114 |
115 | when OPCODE_READ =>
116 | -- The result is the address we want.
117 | -- Last 5 bits of the Imm value is a signed offset.
118 | s_result(15 downto 0) <= std_logic_vector(signed(I_dataA) + signed(I_dataIMM(4 downto 0)));
119 | s_shouldBranch <= '0';
120 | O_memMode <= I_aluop(0); -- 1 when 1 byte read, 0 16bit
121 | when OPCODE_WRITE => -- result is again the address
122 | s_result(15 downto 0) <= std_logic_vector(signed(I_dataA) + signed(I_dataIMM(15 downto 11)));
123 | s_shouldBranch <= '0';
124 | O_memMode <= I_aluop(0); -- 1 when 1 byte read, 0 16bit
125 | when OPCODE_LOAD =>
126 | if I_aluop(0) = '0' then
127 | s_result(15 downto 0) <= I_dataIMM(7 downto 0) & X"00";
128 | else
129 | s_result(15 downto 0) <= X"00" & I_dataIMM(7 downto 0);
130 | end if;
131 | s_shouldBranch <= '0';
132 |
133 | when OPCODE_CMP =>
134 | if I_dataA = I_dataB then
135 | s_result(CMP_BIT_EQ) <= '1';
136 | else
137 | s_result(CMP_BIT_EQ) <= '0';
138 | end if;
139 |
140 | if I_dataA = X"0000" then
141 | s_result(CMP_BIT_AZ) <= '1';
142 | else
143 | s_result(CMP_BIT_AZ) <= '0';
144 | end if;
145 |
146 | if I_dataB = X"0000" then
147 | s_result(CMP_BIT_BZ) <= '1';
148 | else
149 | s_result(CMP_BIT_BZ) <= '0';
150 | end if;
151 |
152 | if I_aluop(0) = '0' then
153 | if unsigned(I_dataA) > unsigned(I_dataB) then
154 | s_result(CMP_BIT_AGB) <= '1';
155 | else
156 | s_result(CMP_BIT_AGB) <= '0';
157 | end if;
158 | if unsigned(I_dataA) < unsigned(I_dataB) then
159 | s_result(CMP_BIT_ALB) <= '1';
160 | else
161 | s_result(CMP_BIT_ALB) <= '0';
162 | end if;
163 | else
164 | if signed(I_dataA) > signed(I_dataB) then
165 | s_result(CMP_BIT_AGB) <= '1';
166 | else
167 | s_result(CMP_BIT_AGB) <= '0';
168 | end if;
169 | if signed(I_dataA) < signed(I_dataB) then
170 | s_result(CMP_BIT_ALB) <= '1';
171 | else
172 | s_result(CMP_BIT_ALB) <= '0';
173 | end if;
174 | end if;
175 | s_result(15) <= '0';
176 | s_result(9 downto 0) <= "0000000000";
177 | s_shouldBranch <= '0';
178 |
179 | when OPCODE_SHL =>
180 | case I_dataB(3 downto 0) is
181 | when "0001" =>
182 | s_result(15 downto 0) <= std_logic_vector(shift_left(unsigned(I_dataA), 1));
183 | when "0010" =>
184 | s_result(15 downto 0) <= std_logic_vector(shift_left(unsigned(I_dataA), 2));
185 | when "0011" =>
186 | s_result(15 downto 0) <= std_logic_vector(shift_left(unsigned(I_dataA), 3));
187 | when "0100" =>
188 | s_result(15 downto 0) <= std_logic_vector(shift_left(unsigned(I_dataA), 4));
189 | when "0101" =>
190 | s_result(15 downto 0) <= std_logic_vector(shift_left(unsigned(I_dataA), 5));
191 | when "0110" =>
192 | s_result(15 downto 0) <= std_logic_vector(shift_left(unsigned(I_dataA), 6));
193 | when "0111" =>
194 | s_result(15 downto 0) <= std_logic_vector(shift_left(unsigned(I_dataA), 7));
195 | when "1000" =>
196 | s_result(15 downto 0) <= std_logic_vector(shift_left(unsigned(I_dataA), 8));
197 | when "1001" =>
198 | s_result(15 downto 0) <= std_logic_vector(shift_left(unsigned(I_dataA), 9));
199 | when "1010" =>
200 | s_result(15 downto 0) <= std_logic_vector(shift_left(unsigned(I_dataA), 10));
201 | when "1011" =>
202 | s_result(15 downto 0) <= std_logic_vector(shift_left(unsigned(I_dataA), 11));
203 | when "1100" =>
204 | s_result(15 downto 0) <= std_logic_vector(shift_left(unsigned(I_dataA), 12));
205 | when "1101" =>
206 | s_result(15 downto 0) <= std_logic_vector(shift_left(unsigned(I_dataA), 13));
207 | when "1110" =>
208 | s_result(15 downto 0) <= std_logic_vector(shift_left(unsigned(I_dataA), 14));
209 | when "1111" =>
210 | s_result(15 downto 0) <= std_logic_vector(shift_left(unsigned(I_dataA), 15));
211 | when others =>
212 | s_result(15 downto 0) <= I_dataA;
213 | end case;
214 | s_shouldBranch <= '0';
215 |
216 | when OPCODE_SHR =>
217 | case I_dataB(3 downto 0) is
218 | when "0001" =>
219 | s_result(15 downto 0) <= std_logic_vector(shift_right(unsigned(I_dataA), 1));
220 | when "0010" =>
221 | s_result(15 downto 0) <= std_logic_vector(shift_right(unsigned(I_dataA), 2));
222 | when "0011" =>
223 | s_result(15 downto 0) <= std_logic_vector(shift_right(unsigned(I_dataA), 3));
224 | when "0100" =>
225 | s_result(15 downto 0) <= std_logic_vector(shift_right(unsigned(I_dataA), 4));
226 | when "0101" =>
227 | s_result(15 downto 0) <= std_logic_vector(shift_right(unsigned(I_dataA), 5));
228 | when "0110" =>
229 | s_result(15 downto 0) <= std_logic_vector(shift_right(unsigned(I_dataA), 6));
230 | when "0111" =>
231 | s_result(15 downto 0) <= std_logic_vector(shift_right(unsigned(I_dataA), 7));
232 | when "1000" =>
233 | s_result(15 downto 0) <= std_logic_vector(shift_right(unsigned(I_dataA), 8));
234 | when "1001" =>
235 | s_result(15 downto 0) <= std_logic_vector(shift_right(unsigned(I_dataA), 9));
236 | when "1010" =>
237 | s_result(15 downto 0) <= std_logic_vector(shift_right(unsigned(I_dataA), 10));
238 | when "1011" =>
239 | s_result(15 downto 0) <= std_logic_vector(shift_right(unsigned(I_dataA), 11));
240 | when "1100" =>
241 | s_result(15 downto 0) <= std_logic_vector(shift_right(unsigned(I_dataA), 12));
242 | when "1101" =>
243 | s_result(15 downto 0) <= std_logic_vector(shift_right(unsigned(I_dataA), 13));
244 | when "1110" =>
245 | s_result(15 downto 0) <= std_logic_vector(shift_right(unsigned(I_dataA), 14));
246 | when "1111" =>
247 | s_result(15 downto 0) <= std_logic_vector(shift_right(unsigned(I_dataA), 15));
248 | when others =>
249 | s_result(15 downto 0) <= I_dataA;
250 | end case;
251 | s_shouldBranch <= '0';
252 |
253 | when OPCODE_JUMP =>
254 | if I_aluop(0) = '0' then
255 | -- set PC to reg(a)
256 | s_result(15 downto 0) <= I_dataA;
257 | else
258 | --biro - v1.5isa
259 | s_result(15 downto 0) <= std_logic_vector(signed(I_PC) + signed(I_dataIMM(10 downto 0) & '0'));
260 | end if;
261 | s_shouldBranch <= '1';
262 | when OPCODE_JUMPEQ =>
263 | -- set branch target regardless
264 | if I_aluop(0) = '1' then
265 | s_result(15 downto 0) <= std_logic_vector(signed(I_PC) + signed(I_dataIMM(4 downto 0)));
266 | else
267 | s_result(15 downto 0) <= I_dataB;
268 | end if;
269 |
270 | -- the condition to jump is based on aluop(0) and dataimm(1 downto 0);
271 | case I_dataIMM(15 downto 13) is
272 | when CJF_EQ =>
273 | s_shouldBranch <= I_dataA(CMP_BIT_EQ);
274 | when CJF_AZ =>
275 | s_shouldBranch <= I_dataA(CMP_BIT_Az);
276 | when CJF_BZ =>
277 | s_shouldBranch <= I_dataA(CMP_BIT_Bz);
278 | when CJF_ANZ =>
279 | s_shouldBranch <= not I_dataA(CMP_BIT_AZ);
280 | when CJF_BNZ =>
281 | s_shouldBranch <= not I_dataA(CMP_BIT_Bz);
282 | when CJF_AGB =>
283 | s_shouldBranch <= I_dataA(CMP_BIT_AGB);
284 | when CJF_ALB =>
285 | s_shouldBranch <= I_dataA(CMP_BIT_ALB);
286 | when others =>
287 | s_shouldBranch <= '0';
288 | end case;
289 | when OPCODE_SPEC => -- special instructions
290 | if I_aluop(0) = '1' then
291 | case I_dataIMM(IFO_F2_BEGIN downto IFO_F2_END) is
292 |
293 | when OPCODE_SPEC_F2_GIEF =>
294 | s_result(15 downto 0) <= s_interrupt_register;
295 | s_shouldBranch <= '0';
296 | when OPCODE_SPEC_F2_BBI =>
297 | s_result(15 downto 0) <= s_interrupt_rpc;
298 | s_shouldBranch <= '1';
299 | s_interrupt_enable <= s_prev_interrupt_enable;
300 | when OPCODE_SPEC_F2_EI =>
301 | s_result(15 downto 0) <= X"0000";
302 | s_interrupt_enable <= '1';
303 | s_shouldBranch <= '0';
304 | when OPCODE_SPEC_F2_DI =>
305 | s_result(15 downto 0) <= X"0000";
306 | s_interrupt_enable <= '0';
307 | s_shouldBranch <= '0';
308 | when others =>
309 | end case;
310 | else
311 | case I_dataIMM(IFO_F2_BEGIN downto IFO_F2_END) is
312 | when OPCODE_SPEC_F2_GETPC =>
313 | s_result(15 downto 0) <= I_PC;
314 | s_shouldBranch <= '0';
315 | when OPCODE_SPEC_F2_GETSTATUS =>
316 | s_result(1 downto 0) <= s_result(17 downto 16);
317 | s_shouldBranch <= '0';
318 | when OPCODE_SPEC_F2_INT =>
319 | s_result(15 downto 0) <= ADDR_INTVEC;
320 | s_interrupt_rpc <= std_logic_vector(unsigned(I_PC) + 2);
321 | s_interrupt_register <= X"00" & "00" & I_dataIMM(7 downto 2);
322 |
323 | s_prev_interrupt_enable <= s_interrupt_enable;
324 | s_interrupt_enable <= '0';
325 | s_shouldBranch <= '1';
326 | when others =>
327 | end case;
328 | end if;
329 | when OPCODE_RES2 =>
330 | -- Currently the RES2 opcode is under investigation. Instructions are not documented yet
331 | if I_aluop(0) = '1' then
332 | s_shouldBranch <= '0';
333 | -- todo: multiply is not tested
334 | -- Synthesizes to a DSP block on Spartan6
335 | s_32_result <= std_logic_vector(unsigned(I_dataA) * unsigned( I_dataB));
336 | s_result(16 downto 0) <= s_32_result(16 downto 0);
337 | else
338 | case I_dataIMM(IFO_F2_BEGIN downto IFO_F2_END) is
339 |
340 | when OPCODE_SPEC_F2_GETCOUNTLOW =>
341 | s_result(15 downto 0) <= std_logic_vector(s_32_cyclecounter(15 downto 0));
342 | s_shouldBranch <= '0';
343 |
344 | when OPCODE_SPEC_F2_GETCOUNTHIGH =>
345 | s_result(15 downto 0) <= std_logic_vector(s_32_cyclecounter(31 downto 16));
346 | s_shouldBranch <= '0';
347 | when others =>
348 | end case;
349 | end if;
350 | when others =>
351 | s_result <= "00" & X"FEFE";
352 | end case;
353 | end if;
354 | end if;
355 | end process;
356 |
357 | O_dataResult <= s_result(15 downto 0);
358 | O_shouldBranch <= s_shouldBranch;
359 |
360 | end Behavioral;
361 |
362 |
--------------------------------------------------------------------------------
/vhdl/core/control_unit.vhd:
--------------------------------------------------------------------------------
1 | ----------------------------------------------------------------------------------
2 | -- Project Name: TPU
3 | -- Description: control unit
4 | --
5 | -- Revision: 1
6 | ----------------------------------------------------------------------------------
7 | library IEEE;
8 | use IEEE.STD_LOGIC_1164.ALL;
9 |
10 | library work;
11 | use work.tpu_constants.all;
12 |
13 | entity control_unit is
14 | Port ( I_clk : in STD_LOGIC;
15 | I_reset : in STD_LOGIC;
16 | I_aluop : in STD_LOGIC_VECTOR (4 downto 0);
17 |
18 | -- interrupts
19 | I_int_enabled: in std_logic;
20 | I_int: in STD_LOGIC;
21 | O_int_ack: out STD_LOGIC;
22 | I_int_mem_data: in STD_LOGIC_VECTOR(15 downto 0); -- mem bus in (before controller)
23 | O_idata: out STD_LOGIC_VECTOR(15 downto 0);
24 | O_set_idata:out STD_LOGIC;
25 | O_set_ipc: out STD_LOGIC;
26 | O_set_irpc: out STD_LOGIC;
27 |
28 | -- mem controller state and control
29 | I_ready: in STD_LOGIC;
30 | O_execute: out STD_LOGIC;
31 | I_dataReady: in STD_LOGIC;
32 |
33 | O_state : out STD_LOGIC_VECTOR (6 downto 0)
34 | );
35 | end control_unit;
36 |
37 | architecture Behavioral of control_unit is
38 | signal s_state: STD_LOGIC_VECTOR(6 downto 0) := "0000001";
39 |
40 | signal mem_ready: std_logic;
41 | signal mem_execute: std_logic:='0';
42 | signal mem_dataReady: std_logic;
43 |
44 | signal mem_cycles : integer := 0;
45 |
46 | signal next_s_state: STD_LOGIC_VECTOR(6 downto 0) := "0000001";
47 |
48 | signal interrupt_state: STD_LOGIC_VECTOR(2 downto 0) := "000";
49 | signal interrupt_ack: STD_LOGIC := '0';
50 | signal interrupt_was_inactive: STD_LOGIC := '1';
51 | signal set_idata: STD_LOGIC := '0';
52 | signal set_ipc: STD_LOGIC := '0';
53 |
54 | begin
55 |
56 | O_execute <= mem_execute;
57 | mem_ready <= I_ready;
58 | mem_dataReady <= I_dataReady;
59 | O_int_ack <= interrupt_ack;
60 | O_set_idata <= set_idata;
61 | O_set_irpc <= set_idata;
62 | O_set_ipc <= set_ipc;
63 |
64 | process(I_clk)
65 | begin
66 | if rising_edge(I_clk) then
67 | if I_reset = '1' then
68 | s_state <= "0000001";
69 | mem_cycles <= 0;
70 | interrupt_was_inactive <= '1';
71 | interrupt_ack <= '0';
72 | interrupt_state <= "000";
73 | set_ipc <= '0';
74 | O_idata <= X"0000";
75 | set_idata <= '0';
76 | else
77 | if I_int = '0' then
78 | interrupt_was_inactive <= '1';
79 | end if;
80 | case s_state is
81 | when "0000001" => -- fetch
82 | if mem_cycles = 0 and mem_ready = '1' then
83 | mem_execute <= '1';
84 | mem_cycles <= 1;
85 |
86 | elsif mem_cycles = 1 then
87 | mem_execute <= '0';
88 | if mem_dataReady = '1' then
89 | mem_cycles <= 0;
90 | s_state <= "0000010";
91 | end if;
92 | end if;
93 | when "0000010" => -- read?
94 | s_state <= "0000100"; --R
95 | when "0000100" => -- decode
96 | s_state <= "0001000"; --E
97 | when "0001000" => -- execute
98 | --MEM/WB
99 | -- if it's not a memory alu op, goto writeback
100 | if (I_aluop(4 downto 1) = OPCODE_READ or
101 | I_aluop(4 downto 1) = OPCODE_WRITE) then
102 | s_state <= "0010000"; -- MEM
103 | if mem_cycles = 0 and mem_ready = '1' then
104 | mem_execute <= '1';
105 | mem_cycles <= 1;
106 | end if;
107 | else
108 | s_state <= "0100000"; -- WB
109 | end if;
110 | when "0010000" => -- mem
111 | -- sometimes memory can be busy, if so we need to relook here
112 | if mem_cycles = 0 and mem_ready = '1' then
113 | mem_execute <= '1';
114 | mem_cycles <= 1;
115 |
116 | elsif mem_cycles = 1 then
117 | mem_execute <= '0';
118 | -- if it's a write, go through
119 | if I_aluop(4 downto 1) = OPCODE_WRITE then
120 | mem_cycles <= 0;
121 | s_state <= "0100000"; -- WB
122 | elsif mem_dataReady = '1' then
123 | -- if read, wait for data
124 | mem_cycles <= 0;
125 | s_state <= "0100000"; -- WB
126 | end if;
127 | end if;
128 | when "0100000" => -- writeback
129 | -- check interrupt?
130 | if I_int_enabled='1' and interrupt_was_inactive = '1' and I_int = '1' then
131 | interrupt_ack <= '1';
132 | interrupt_was_inactive <= '0';
133 | interrupt_state <= "001";
134 | next_s_state <= "0000001"; --F
135 | s_state <= "1000000"; --F
136 | else
137 | s_state <= "0000001"; --F
138 | end if;
139 |
140 | when "1000000" => -- stalls
141 | -- interrupt stall
142 | if interrupt_state = "001" then
143 | -- give a cycle of latency
144 | interrupt_state <= "010";
145 | elsif interrupt_state = "010" then
146 | -- sample input data for state?
147 | O_idata <= I_int_mem_data;
148 | set_idata <= '1';
149 | interrupt_state <= "100";
150 | elsif interrupt_state = "100" then
151 | set_idata <= '0';
152 | -- set PC to interrupt vector.
153 | set_ipc <= '1';
154 | interrupt_state <= "101";
155 | elsif interrupt_state = "101" then
156 | set_ipc <= '0';
157 | interrupt_ack <= '0';
158 | interrupt_state <= "000";
159 | s_state <= "0000001"; --F
160 | end if;
161 |
162 | when others =>
163 | s_state <= "0000001";
164 | end case;
165 | end if;
166 | end if;
167 | end process;
168 |
169 | O_state <= s_state;
170 | end Behavioral;
171 |
172 |
173 |
174 |
--------------------------------------------------------------------------------
/vhdl/core/core.vhd:
--------------------------------------------------------------------------------
1 | ----------------------------------------------------------------------------------
2 | -- Project Name: TPU
3 | -- Description: TPU core glue entity
4 | --
5 | -- Brings all core components together with a little glue logic.
6 | -- This is the CPU interface required.
7 | --
8 | -- Revision: 1
9 | ----------------------------------------------------------------------------------
10 | library IEEE;
11 | use IEEE.STD_LOGIC_1164.ALL;
12 |
13 |
14 | library work;
15 | use work.tpu_constants.all;
16 |
17 |
18 | entity core is
19 | Port (I_clk : in STD_LOGIC;
20 | I_reset : in STD_LOGIC;
21 | I_halt : in STD_LOGIC;
22 |
23 | I_int: in STD_LOGIC;
24 | O_int_ack: out STD_LOGIC;
25 |
26 | -- new memory interface
27 | MEM_I_ready : IN std_logic;
28 | MEM_O_cmd : OUT std_logic;
29 | MEM_O_we : OUT std_logic;
30 | MEM_O_byteEnable : OUT std_logic_vector(1 downto 0);
31 | MEM_O_addr : OUT std_logic_vector(15 downto 0);
32 | MEM_O_data : OUT std_logic_vector(15 downto 0);
33 | MEM_I_data : IN std_logic_vector(15 downto 0);
34 | MEM_I_dataReady : IN std_logic
35 | );
36 | end core;
37 |
38 | architecture Behavioral of core is
39 | COMPONENT pc_unit
40 | PORT(
41 | I_clk : IN std_logic;
42 | I_nPC : IN std_logic_vector(15 downto 0);
43 | I_nPCop : IN std_logic_vector(1 downto 0);
44 | I_intVec: IN std_logic;
45 | O_PC : OUT std_logic_vector(15 downto 0)
46 | );
47 | END COMPONENT;
48 |
49 | COMPONENT control_unit
50 | PORT (
51 | I_clk : in STD_LOGIC;
52 | I_reset : in STD_LOGIC;
53 | I_aluop : in STD_LOGIC_VECTOR (4 downto 0);
54 | O_state : out STD_LOGIC_VECTOR (6 downto 0);
55 |
56 | I_int: in STD_LOGIC;
57 | O_int_ack: out STD_LOGIC;
58 |
59 | I_int_enabled: in STD_LOGIC;
60 | I_int_mem_data: in STD_LOGIC_VECTOR(15 downto 0);
61 | O_idata: out STD_LOGIC_VECTOR(15 downto 0);
62 | O_set_idata:out STD_LOGIC;
63 | O_set_ipc: out STD_LOGIC;
64 | O_set_irpc: out STD_LOGIC;
65 |
66 | I_ready: in STD_LOGIC;
67 | O_execute: out STD_LOGIC;
68 | I_dataReady: in STD_LOGIC
69 | );
70 | END COMPONENT;
71 |
72 | COMPONENT decode
73 | PORT(
74 | I_clk : IN std_logic;
75 | I_dataInst : IN std_logic_vector(15 downto 0);
76 | I_en : IN std_logic;
77 | O_selA : OUT std_logic_vector(2 downto 0);
78 | O_selB : OUT std_logic_vector(2 downto 0);
79 | O_selD : OUT std_logic_vector(2 downto 0);
80 | O_dataIMM : OUT std_logic_vector(15 downto 0);
81 | O_regDwe : OUT std_logic;
82 | O_aluop : OUT std_logic_vector(4 downto 0)
83 | );
84 | END COMPONENT;
85 |
86 | COMPONENT alu
87 | PORT(
88 | I_clk : IN std_logic;
89 | I_en : IN std_logic;
90 | I_dataA : IN std_logic_vector(15 downto 0);
91 | I_dataB : IN std_logic_vector(15 downto 0);
92 | I_dataDwe : IN std_logic;
93 | I_aluop : IN std_logic_vector(4 downto 0);
94 | I_PC : IN std_logic_vector(15 downto 0);
95 | I_dataIMM : IN std_logic_vector(15 downto 0);
96 | O_dataResult : OUT std_logic_vector(15 downto 0);
97 | O_dataWriteReg : OUT std_logic;
98 | O_shouldBranch : OUT std_logic;
99 | I_idata: in STD_LOGIC_VECTOR(15 downto 0); --interrupt register data
100 | I_set_idata:in STD_LOGIC;-- set interrup register data
101 | I_set_irpc: in STD_LOGIC; -- set interrupt return pc
102 |
103 | O_int_enabled: out STD_LOGIC;
104 | O_memMode : out STD_LOGIC
105 | );
106 | END COMPONENT;
107 |
108 | COMPONENT reg16_8
109 | PORT(
110 | I_clk : IN std_logic;
111 | I_en: in STD_LOGIC;
112 | I_dataD : IN std_logic_vector(15 downto 0);
113 | O_dataA : OUT std_logic_vector(15 downto 0);
114 | O_dataB : OUT std_logic_vector(15 downto 0);
115 | I_selA : IN std_logic_vector(2 downto 0);
116 | I_selB : IN std_logic_vector(2 downto 0);
117 | I_selD : IN std_logic_vector(2 downto 0);
118 | I_we : IN std_logic
119 | );
120 | END COMPONENT;
121 |
122 |
123 |
124 | COMPONENT mem_controller
125 | PORT(
126 | I_clk : IN std_logic;
127 | I_reset : IN std_logic;
128 | O_ready : OUT std_logic;
129 | I_execute : IN std_logic;
130 | I_dataWe : IN std_logic;
131 | I_address : IN std_logic_vector(15 downto 0);
132 | I_data : IN std_logic_vector(15 downto 0);
133 | I_dataByteEn : IN std_logic_vector(1 downto 0);
134 | O_data : OUT std_logic_vector(15 downto 0);
135 | O_dataReady : OUT std_logic;
136 | MEM_I_ready : IN std_logic;
137 | MEM_O_cmd : OUT std_logic;
138 | MEM_O_we : OUT std_logic;
139 | MEM_O_byteEnable : OUT std_logic_vector(1 downto 0);
140 | MEM_O_addr : OUT std_logic_vector(15 downto 0);
141 | MEM_O_data : OUT std_logic_vector(15 downto 0);
142 | MEM_I_data : IN std_logic_vector(15 downto 0);
143 | MEM_I_dataReady : IN std_logic
144 | );
145 | END COMPONENT;
146 |
147 |
148 | signal state : std_logic_vector(6 downto 0) := (others => '0');
149 |
150 |
151 | signal pcop: std_logic_vector(1 downto 0);
152 | signal in_pc: std_logic_vector(15 downto 0);
153 |
154 | signal instruction : std_logic_vector(15 downto 0) := (others => '0');
155 | signal dataA : std_logic_vector(15 downto 0) := (others => '0');
156 | signal dataB : std_logic_vector(15 downto 0) := (others => '0');
157 | signal dataDwe : std_logic := '0';
158 | signal aluop : std_logic_vector(4 downto 0) := (others => '0');
159 | signal dataIMM : std_logic_vector(15 downto 0) := (others => '0');
160 | signal selA : std_logic_vector(2 downto 0) := (others => '0');
161 | signal selB : std_logic_vector(2 downto 0) := (others => '0');
162 | signal selD : std_logic_vector(2 downto 0) := (others => '0');
163 | signal dataregWrite: std_logic := '0';
164 | signal dataResult : std_logic_vector(15 downto 0) := (others => '0');
165 | signal dataWriteReg : std_logic := '0';
166 | signal shouldBranch : std_logic := '0';
167 | signal memMode : std_logic := '0';
168 | signal ram_req_size : std_logic := '0';
169 |
170 | signal reg_en: std_logic := '0';
171 | signal reg_we: std_logic := '0';
172 |
173 | signal registerWriteData : std_logic_vector(15 downto 0) := (others=>'0');
174 |
175 | signal en_fetch : std_logic := '0';
176 | signal en_decode : std_logic := '0';
177 | signal en_regread : std_logic := '0';
178 | signal en_alu : std_logic := '0';
179 | signal en_memory : std_logic := '0';
180 | signal en_regwrite : std_logic := '0';
181 | signal en_stall : std_logic := '0';
182 |
183 | signal PC : std_logic_vector(15 downto 0) := (others => '0');
184 |
185 | signal memctl_ready : std_logic;
186 | signal memctl_execute : std_logic := '0';
187 | signal memctl_dataWe : std_logic;
188 | signal memctl_address : std_logic_vector(15 downto 0);
189 | signal memctl_in_data : std_logic_vector(15 downto 0);
190 | signal memctl_dataByteEn : std_logic_vector(1 downto 0);
191 | signal memctl_out_data : std_logic_vector(15 downto 0);
192 | signal memctl_dataReady : std_logic;
193 |
194 | signal PCintVec: STD_LOGIC := '0';
195 |
196 | signal int_idata: STD_LOGIC_VECTOR(15 downto 0);
197 | signal int_set_idata: STD_LOGIC;
198 | signal int_enabled: std_logic;
199 | signal int_set_irpc: STD_LOGIC;
200 |
201 | signal core_clock:STD_LOGIC := '0';
202 |
203 | signal leds : STD_LOGIC_VECTOR (7 downto 0):= "11011100";
204 | begin
205 | core_clock <= I_clk;
206 |
207 | memctl: mem_controller PORT MAP (
208 | I_clk => I_clk,
209 | I_reset => I_reset,
210 |
211 | O_ready => memctl_ready,
212 | I_execute => memctl_execute,
213 | I_dataWe => memctl_dataWe,
214 | I_address => memctl_address,
215 | I_data => memctl_in_data,
216 | I_dataByteEn => memctl_dataByteEn,
217 | O_data => memctl_out_data,
218 | O_dataReady => memctl_dataReady,
219 |
220 | MEM_I_ready => MEM_I_ready,
221 | MEM_O_cmd => MEM_O_cmd,
222 | MEM_O_we => MEM_O_we,
223 | MEM_O_byteEnable => MEM_O_byteEnable,
224 | MEM_O_addr => MEM_O_addr,
225 | MEM_O_data => MEM_O_data,
226 | MEM_I_data => MEM_I_data,
227 | MEM_I_dataReady => MEM_I_dataReady
228 | );
229 |
230 | uut_pcunit: pc_unit Port map (
231 | I_clk => core_clock,
232 | I_nPC => in_pc,
233 | I_nPCop => pcop,
234 | I_intVec => PCintVec,
235 | O_PC => PC
236 | );
237 |
238 | uut_control: control_unit PORT MAP (
239 | I_clk => core_clock,
240 | I_reset => I_reset,
241 | I_aluop => aluop,
242 |
243 | I_int => I_int,
244 | O_int_ack => O_int_ack,
245 |
246 | I_int_enabled => int_enabled,
247 | I_int_mem_data=>MEM_I_data,
248 | O_idata=> int_idata,
249 | O_set_idata=> int_set_idata,
250 | O_set_ipc=> PCintVec,
251 | O_set_irpc => int_set_irpc,
252 | I_ready => memctl_ready,
253 | O_execute => memctl_execute,
254 | I_dataReady => memctl_dataReady,
255 |
256 | O_state => state
257 | );
258 |
259 | uut_decoder: decode PORT MAP (
260 | I_clk => core_clock,
261 | I_dataInst => instruction,
262 | I_en => en_decode,
263 | O_selA => selA,
264 | O_selB => selB,
265 | O_selD => selD,
266 | O_dataIMM => dataIMM,
267 | O_regDwe => dataDwe,
268 | O_aluop => aluop
269 | );
270 |
271 | uut_alu: alu PORT MAP (
272 | I_clk => core_clock,
273 | I_en => en_alu,
274 | I_dataA => dataA,
275 | I_dataB => dataB,
276 | I_dataDwe => dataDwe,
277 | I_aluop => aluop,
278 | I_PC => PC,
279 | I_dataIMM => dataIMM,
280 | O_dataResult => dataResult,
281 | O_dataWriteReg => dataWriteReg,
282 | O_shouldBranch => shouldBranch,
283 | O_int_enabled => int_enabled,
284 | I_idata => int_idata,
285 | I_set_idata => int_set_idata,
286 | I_set_irpc => int_set_irpc,
287 | O_memMode => memMode
288 | );
289 |
290 | uut_reg: reg16_8 PORT MAP (
291 | I_clk => core_clock,
292 | I_en => reg_en,
293 | I_dataD => registerWriteData,
294 | O_dataA => dataA,
295 | O_dataB => dataB,
296 | I_selA => selA,
297 | I_selB => selB,
298 | I_selD => selD,
299 | I_we => reg_we
300 | );
301 |
302 | reg_en <= en_regread or en_regwrite;
303 | reg_we <= dataWriteReg and en_regwrite;
304 |
305 |
306 | en_fetch <= state(0);
307 | en_decode <= state(1);
308 | en_regread <= state(2);
309 | en_alu <= state(3);
310 | en_memory <= state(4);
311 | en_regwrite <= state(5);
312 | en_stall <= state(6);
313 |
314 |
315 | pcop <= PCU_OP_RESET when I_reset = '1' else
316 | PCU_OP_ASSIGN when shouldBranch = '1' and state(5) = '1' else
317 | PCU_OP_INC when shouldBranch = '0' and state(5) = '1' else
318 | PCU_OP_NOP;
319 |
320 | in_pc <= dataResult;
321 |
322 | memctl_address <= dataResult when en_memory = '1' else PC;
323 | ram_req_size <= memMode when en_memory = '1' else '0';
324 | memctl_dataByteEn <= "10" when ram_req_size = '1' else "11";
325 | memctl_in_data <= dataB;
326 |
327 | memctl_dataWe <= '1' when en_memory = '1' and aluop(4 downto 1) = OPCODE_WRITE else '0';
328 |
329 | registerWriteData <= memctl_out_data when en_regwrite = '1' and aluop(4 downto 1) = OPCODE_READ else dataResult;
330 | instruction <= memctl_out_data;
331 |
332 | end Behavioral;
333 |
334 |
--------------------------------------------------------------------------------
/vhdl/core/decode.vhd:
--------------------------------------------------------------------------------
1 | ----------------------------------------------------------------------------------
2 | -- Project Name: TPU
3 | -- Description: Decoder unit of TPU
4 | --
5 | -- Revision: 1
6 | ----------------------------------------------------------------------------------
7 | library IEEE;
8 | use IEEE.STD_LOGIC_1164.ALL;
9 |
10 | library work;
11 | use work.tpu_constants.all;
12 |
13 | entity decode is
14 | Port ( I_clk : in STD_LOGIC;
15 | I_en : in STD_LOGIC;
16 | I_dataInst : in STD_LOGIC_VECTOR (15 downto 0); -- Instruction to be decoded
17 | O_selA : out STD_LOGIC_VECTOR (2 downto 0); -- Selection out for regA
18 | O_selB : out STD_LOGIC_VECTOR (2 downto 0); -- Selection out for regB
19 | O_selD : out STD_LOGIC_VECTOR (2 downto 0); -- Selection out for regD
20 | O_dataIMM : out STD_LOGIC_VECTOR (15 downto 0); -- Immediate value out
21 | O_regDwe : out STD_LOGIC; -- RegD wrtite enable
22 | O_aluop : out STD_LOGIC_VECTOR (4 downto 0) -- ALU opcode
23 | );
24 | end decode;
25 |
26 | architecture Behavioral of decode is
27 |
28 | begin
29 |
30 | process (I_clk, I_en)
31 | begin
32 | if rising_edge(I_clk) and I_en = '1' then
33 |
34 | O_selA <= I_dataInst(IFO_RA_BEGIN downto IFO_RA_END);
35 | O_selB <= I_dataInst(IFO_RB_BEGIN downto IFO_RB_END);
36 | O_selD <= I_dataInst(IFO_RD_BEGIN downto IFO_RD_END);
37 | O_dataIMM(7 downto 0) <= I_dataInst(IFO_IMM_BEGIN downto IFO_IMM_END);
38 |
39 | O_aluop <= I_dataInst(IFO_OPCODE_BEGIN downto IFO_OPCODE_END)
40 | & I_dataInst(IFO_F_LOC);
41 |
42 | case I_dataInst(IFO_OPCODE_BEGIN downto IFO_OPCODE_END) is
43 | when OPCODE_WRITE =>
44 | O_dataIMM(15 downto 8) <= I_dataInst(IFO_RD_BEGIN downto IFO_RD_END)
45 | & I_dataInst(IFO_F2_BEGIN downto IFO_F2_END) & "000";
46 | O_regDwe <= '0';
47 | when OPCODE_JUMP =>
48 | O_dataIMM(15 downto 8) <= "00000" & I_dataInst(IFO_RD_BEGIN downto IFO_RD_END);
49 | O_regDwe <= '0';
50 | when OPCODE_JUMPEQ =>
51 | O_dataIMM(15 downto 8) <= I_dataInst(IFO_RD_BEGIN downto IFO_RD_END)
52 | & I_dataInst(IFO_RB_BEGIN downto IFO_RB_END) & "00";
53 | O_regDwe <= '0';
54 |
55 | when OPCODE_SPEC => -- special
56 |
57 | if I_dataInst(IFO_F_LOC) = '1' then
58 | case I_dataInst(IFO_F2_BEGIN downto IFO_F2_END) is
59 |
60 | when OPCODE_SPEC_F2_GIEF =>
61 | O_regDwe <= '1';
62 | when OPCODE_SPEC_F2_BBI =>
63 | O_regDwe <= '0';
64 | when OPCODE_SPEC_F2_EI =>
65 | O_regDwe <= '0';
66 | when OPCODE_SPEC_F2_DI =>
67 | O_regDwe <= '0';
68 | when others =>
69 | end case;
70 | else
71 | case I_dataInst(IFO_F2_BEGIN downto IFO_F2_END) is
72 | when OPCODE_SPEC_F2_GETPC =>
73 | O_regDwe <= '1';
74 | when OPCODE_SPEC_F2_GETSTATUS =>
75 | O_regDwe <= '1';
76 | when OPCODE_SPEC_F2_INT =>
77 | O_regDwe <= '0';
78 | when others =>
79 | end case;
80 | end if;
81 |
82 | O_dataIMM(15 downto 8) <= I_dataInst(IFO_RD_BEGIN downto IFO_RD_END) & "00000";
83 | when OPCODE_RES2 =>
84 | O_regDwe <= '1';
85 | when others =>
86 | O_dataIMM(15 downto 8) <= X"00";
87 | O_regDwe <= '1';
88 | end case;
89 | end if;
90 | end process;
91 |
92 | end Behavioral;
93 |
94 |
--------------------------------------------------------------------------------
/vhdl/core/mem_controller.vhd:
--------------------------------------------------------------------------------
1 | ----------------------------------------------------------------------------------
2 | -- Project Name: TPU
3 | -- Description: Memory controller unit of TPU
4 | --
5 | -- Very simple. Allows for delays in reads, whilsts writes go through immediately.
6 | --
7 | -- Revision: 1
8 | ----------------------------------------------------------------------------------
9 | library IEEE;
10 | use IEEE.STD_LOGIC_1164.ALL;
11 |
12 |
13 | entity mem_controller is
14 | Port ( I_clk : in STD_LOGIC;
15 | I_reset : in STD_LOGIC;
16 |
17 | O_ready : out STD_LOGIC;
18 | I_execute: in STD_LOGIC;
19 | I_dataWe : in STD_LOGIC;
20 | I_address : in STD_LOGIC_VECTOR (15 downto 0);
21 | I_data : in STD_LOGIC_VECTOR (15 downto 0);
22 | I_dataByteEn : in STD_LOGIC_VECTOR(1 downto 0);
23 | O_data : out STD_LOGIC_VECTOR (15 downto 0);
24 | O_dataReady: out STD_LOGIC;
25 |
26 | MEM_I_ready: in STD_LOGIC;
27 | MEM_O_cmd: out STD_LOGIC;
28 | MEM_O_we : out STD_LOGIC;
29 | MEM_O_byteEnable : out STD_LOGIC_VECTOR (1 downto 0);
30 | MEM_O_addr : out STD_LOGIC_VECTOR (15 downto 0);
31 | MEM_O_data : out STD_LOGIC_VECTOR (15 downto 0);
32 | MEM_I_data : in STD_LOGIC_VECTOR (15 downto 0);
33 | MEM_I_dataReady : in STD_LOGIC
34 | );
35 | end mem_controller;
36 |
37 | architecture Behavioral of mem_controller is
38 |
39 | signal we : std_logic := '0';
40 | signal addr : STD_LOGIC_VECTOR (15 downto 0) := X"0000";
41 | signal indata: STD_LOGIC_VECTOR (15 downto 0) := X"0000";
42 | signal byteEnable: STD_LOGIC_VECTOR ( 1 downto 0) := "11";
43 | signal cmd : STD_LOGIC := '0';
44 | signal state: integer := 0;
45 |
46 | signal ready: STD_LOGIC := '0';
47 |
48 | begin
49 |
50 | process (I_clk, I_execute)
51 | begin
52 | if rising_edge(I_clk) then
53 | if I_reset = '1' then
54 | we <= '0';
55 | cmd <= '0';
56 | state <= 0;
57 | elsif state = 0 and I_execute = '1' and MEM_I_ready = '1' then
58 | we <= I_dataWe;
59 | addr <= I_address;
60 | indata <= I_data;
61 | byteEnable <= I_dataByteEn;
62 | cmd <= '1';
63 | O_dataReady <= '0';
64 | if I_dataWe = '0' then
65 | -- read
66 | state <= 1;
67 | else
68 | state <= 2;-- write
69 | end if;
70 | elsif state = 1 then
71 | cmd <= '0';
72 | if MEM_I_dataReady = '1' then
73 | O_dataReady <= '1';
74 | state <= 2;
75 | end if;
76 | elsif state = 2 then
77 | cmd <= '0';
78 | state <= 0;
79 | O_dataReady <= '0';
80 | end if;
81 | end if;
82 | end process;
83 |
84 | O_ready <= ( MEM_I_ready and not I_execute ) when state = 0 else '0';
85 |
86 | --
87 | MEM_O_cmd <= cmd;
88 | O_data <= MEM_I_data;
89 | MEM_O_byteEnable <= byteEnable;
90 | MEM_O_data <= indata;
91 | MEM_O_addr <= addr;
92 | MEM_O_we <= we;
93 |
94 | end Behavioral;
95 |
96 |
--------------------------------------------------------------------------------
/vhdl/core/pc_unit.vhd:
--------------------------------------------------------------------------------
1 | ----------------------------------------------------------------------------------
2 | -- Project Name: TPU
3 | -- Description: Program Counter unit of TPU
4 | --
5 | -- Simple black box for holding and manipulating the PC
6 | --
7 | -- Revision: 1
8 | ----------------------------------------------------------------------------------
9 | library IEEE;
10 | use IEEE.STD_LOGIC_1164.ALL;
11 |
12 | use IEEE.NUMERIC_STD.ALL;
13 |
14 | library work;
15 | use work.tpu_constants.all;
16 |
17 | entity pc_unit is
18 | Port ( I_clk : in STD_LOGIC;
19 | I_nPC : in STD_LOGIC_VECTOR (15 downto 0);
20 | I_nPCop : in STD_LOGIC_VECTOR (1 downto 0);
21 | I_intVec: in STD_LOGIC;
22 | O_PC : out STD_LOGIC_VECTOR (15 downto 0)
23 | );
24 | end pc_unit;
25 |
26 | architecture Behavioral of pc_unit is
27 | signal current_pc: std_logic_vector( 15 downto 0) := ADDR_RESET;
28 | begin
29 |
30 | process (I_clk)
31 | begin
32 | if rising_edge(I_clk) then
33 | case I_nPCop is
34 | when PCU_OP_NOP => -- NOP, keep PC the same/halt
35 | if I_intVec = '1' then -- in a NOP, you can get intterupts. check.
36 | current_pc <= ADDR_INTVEC;-- set PC to interrupt vector;
37 | end if;
38 | when PCU_OP_INC => -- increment
39 | current_pc <= std_logic_vector(unsigned(current_pc) + 2); -- BYTE ADDRESSING!
40 | when PCU_OP_ASSIGN => -- set from external input
41 | current_pc <= I_nPC;
42 | when PCU_OP_RESET => -- Reset
43 | current_pc <= ADDR_RESET;
44 | when others =>
45 | end case;
46 | end if;
47 | end process;
48 |
49 | O_PC <= current_pc;
50 |
51 | end Behavioral;
52 |
53 |
--------------------------------------------------------------------------------
/vhdl/core/reg16_8.vhd:
--------------------------------------------------------------------------------
1 | ----------------------------------------------------------------------------------
2 | -- Project Name: TPU
3 | -- Description: Register file unit of TPU
4 | --
5 | -- Revision: 1
6 | ----------------------------------------------------------------------------------
7 | library IEEE;
8 | use IEEE.STD_LOGIC_1164.ALL;
9 |
10 | use IEEE.NUMERIC_STD.ALL;
11 |
12 | entity reg16_8 is
13 | Port ( I_clk : in STD_LOGIC;
14 | I_en: in STD_LOGIC;
15 | I_dataD : in STD_LOGIC_VECTOR (15 downto 0); -- Data to write to regD
16 | I_selA : in STD_LOGIC_VECTOR (2 downto 0); -- Select line for regA
17 | I_selB : in STD_LOGIC_VECTOR (2 downto 0); -- Select line for regB
18 | I_selD : in STD_LOGIC_VECTOR (2 downto 0); -- Select line for regD
19 | I_we : in STD_LOGIC; -- Write enable for regD
20 | O_dataA : out STD_LOGIC_VECTOR (15 downto 0);-- regA data out
21 | O_dataB : out STD_LOGIC_VECTOR (15 downto 0) -- regB data out
22 | );
23 | end reg16_8;
24 |
25 | architecture Behavioral of reg16_8 is
26 | type store_t is array (0 to 7) of std_logic_vector(15 downto 0);
27 | signal regs: store_t := (others => X"0000");
28 | begin
29 |
30 | process(I_clk, I_en)
31 | begin
32 | if rising_edge(I_clk) and I_en='1' then
33 | O_dataA <= regs(to_integer(unsigned(I_selA)));
34 | O_dataB <= regs(to_integer(unsigned(I_selB)));
35 | if (I_we = '1') then
36 | regs(to_integer(unsigned(I_selD))) <= I_dataD;
37 | end if;
38 | end if;
39 | end process;
40 |
41 | end Behavioral;
42 |
43 |
--------------------------------------------------------------------------------
/vhdl/core/tpu_constants.vhd:
--------------------------------------------------------------------------------
1 | ----------------------------------------------------------------------------------
2 | -- Project Name: TPU
3 | -- Description: Constants for instruction forms, opcodes, conditional flags, etc.
4 | --
5 | -- Revision: 1.5
6 | ----------------------------------------------------------------------------------
7 |
8 | library IEEE;
9 | use IEEE.STD_LOGIC_1164.all;
10 |
11 | package tpu_constants is
12 |
13 | constant ADDR_RESET: std_logic_vector(15 downto 0) := X"0000";
14 | constant ADDR_INTVEC: std_logic_vector(15 downto 0) := X"0008";
15 |
16 | -- Opcodes
17 | constant OPCODE_ADD: std_logic_vector(3 downto 0) := "0000"; -- ADD
18 | constant OPCODE_SUB: std_logic_vector(3 downto 0) := "0001"; -- SUB
19 | constant OPCODE_OR: std_logic_vector(3 downto 0) := "0010"; -- OR
20 | constant OPCODE_XOR: std_logic_vector(3 downto 0) := "0011"; -- XOR
21 | constant OPCODE_AND: std_logic_vector(3 downto 0) := "0100"; -- AND
22 | constant OPCODE_NOT: std_logic_vector(3 downto 0) := "0101"; -- NOT
23 | constant OPCODE_READ: std_logic_vector(3 downto 0) := "0110"; -- READ
24 | constant OPCODE_WRITE: std_logic_vector(3 downto 0) := "0111"; -- WRITE
25 | constant OPCODE_LOAD: std_logic_vector(3 downto 0) := "1000"; -- LOAD
26 | constant OPCODE_CMP: std_logic_vector(3 downto 0) := "1001"; -- CMP
27 | constant OPCODE_SHL: std_logic_vector(3 downto 0) := "1010"; -- SHL
28 | constant OPCODE_SHR: std_logic_vector(3 downto 0) := "1011"; -- SHR
29 | constant OPCODE_JUMP: std_logic_vector(3 downto 0) := "1100"; -- JUMP
30 | constant OPCODE_JUMPEQ: std_logic_vector(3 downto 0) := "1101"; -- JUMPEQ
31 | constant OPCODE_SPEC: std_logic_vector(3 downto 0) := "1110"; -- SPECIAL
32 | constant OPCODE_RES2: std_logic_vector(3 downto 0) := "1111"; -- RESERVED
33 |
34 | constant OPCODE_SPEC_F2_GETPC: std_logic_vector(1 downto 0) := "00";
35 | constant OPCODE_SPEC_F2_GETSTATUS: std_logic_vector(1 downto 0) := "01";
36 | constant OPCODE_SPEC_F2_INT: std_logic_vector(1 downto 0) := "10";
37 |
38 | constant OPCODE_SPEC_F2_GIEF: std_logic_vector(1 downto 0) := "00";
39 | constant OPCODE_SPEC_F2_BBI: std_logic_vector(1 downto 0) := "01";
40 | constant OPCODE_SPEC_F2_EI: std_logic_vector(1 downto 0) := "10";
41 | constant OPCODE_SPEC_F2_DI: std_logic_vector(1 downto 0) := "11";
42 |
43 |
44 | constant OPCODE_SPEC_F2_GETCOUNTLOW: std_logic_vector(1 downto 0) := "00";
45 | constant OPCODE_SPEC_F2_GETCOUNTHIGH: std_logic_vector(1 downto 0) := "01";
46 |
47 | -- Instruction Form Offsets
48 | constant IFO_OPCODE_BEGIN: integer := 15;
49 | constant IFO_OPCODE_END: integer := 12;
50 |
51 | constant IFO_RD_BEGIN: integer := 11;
52 | constant IFO_RD_END: integer := 9;
53 |
54 | constant IFO_RA_BEGIN: integer := 7;
55 | constant IFO_RA_END: integer := 5;
56 |
57 | constant IFO_RB_BEGIN: integer := 4;
58 | constant IFO_RB_END: integer := 2;
59 |
60 | constant IFO_IMM_BEGIN: integer := 7;
61 | constant IFO_IMM_END: integer := 0;
62 |
63 | constant IFO_F_LOC: integer := 8;
64 |
65 | constant IFO_F2_BEGIN: integer := 1;
66 | constant IFO_F2_END: integer := 0;
67 |
68 | -- Conditional jump flags
69 | constant CJF_EQ: std_logic_vector(2 downto 0):= "000";
70 | constant CJF_AZ: std_logic_vector(2 downto 0):= "001";
71 | constant CJF_BZ: std_logic_vector(2 downto 0):= "010";
72 | constant CJF_ANZ: std_logic_vector(2 downto 0):= "011";
73 | constant CJF_BNZ: std_logic_vector(2 downto 0):= "100";
74 | constant CJF_AGB: std_logic_vector(2 downto 0):= "101";
75 | constant CJF_ALB: std_logic_vector(2 downto 0):= "110";
76 |
77 | -- cmp output bits
78 | constant CMP_BIT_EQ: integer := 14;
79 | constant CMP_BIT_AGB: integer := 13;
80 | constant CMP_BIT_ALB: integer := 12;
81 | constant CMP_BIT_AZ: integer := 11;
82 | constant CMP_BIT_BZ: integer := 10;
83 |
84 | -- the bits are offset when writing the intermediate register
85 | constant CMP_BIT_OFFSET: integer := 0;
86 |
87 | -- PC unit opcodes
88 | constant PCU_OP_NOP: std_logic_vector(1 downto 0):= "00";
89 | constant PCU_OP_INC: std_logic_vector(1 downto 0):= "01";
90 | constant PCU_OP_ASSIGN: std_logic_vector(1 downto 0):= "10";
91 | constant PCU_OP_RESET: std_logic_vector(1 downto 0):= "11";
92 |
93 | end tpu_constants;
94 |
95 | package body tpu_constants is
96 |
97 | end tpu_constants;
98 |
--------------------------------------------------------------------------------
/vhdl/dvid/TDMS_encoder.vhd:
--------------------------------------------------------------------------------
1 | ----------------------------------------------------------------------------------
2 | -- Engineer: Mike Field
3 | --
4 | -- Description: TDMS Encoder
5 | -- 8 bits colour, 2 control bits and one blanking bits in
6 | -- 10 bits of TDMS encoded data out
7 | -- Clocked at the pixel clock
8 | --
9 | ----------------------------------------------------------------------------------
10 | library IEEE;
11 | use IEEE.STD_LOGIC_1164.ALL;
12 | use IEEE.STD_LOGIC_UNSIGNED.ALL;
13 |
14 | entity TDMS_encoder is
15 | Port ( clk : in STD_LOGIC;
16 | data : in STD_LOGIC_VECTOR (7 downto 0);
17 | c : in STD_LOGIC_VECTOR (1 downto 0);
18 | blank : in STD_LOGIC;
19 | encoded : out STD_LOGIC_VECTOR (9 downto 0));
20 | end TDMS_encoder;
21 |
22 | architecture Behavioral of TDMS_encoder is
23 | signal xored : STD_LOGIC_VECTOR (8 downto 0);
24 | signal xnored : STD_LOGIC_VECTOR (8 downto 0);
25 |
26 | signal ones : STD_LOGIC_VECTOR (3 downto 0);
27 | signal data_word : STD_LOGIC_VECTOR (8 downto 0);
28 | signal data_word_inv : STD_LOGIC_VECTOR (8 downto 0);
29 | signal data_word_disparity : STD_LOGIC_VECTOR (3 downto 0);
30 | signal dc_bias : STD_LOGIC_VECTOR (3 downto 0) := (others => '0');
31 | signal e : STD_LOGIC_VECTOR (9 downto 0) := (others => '0');
32 | begin
33 | encoded <= e;
34 |
35 | -- Work our the two different encodings for the byte
36 | xored(0) <= data(0);
37 | xored(1) <= data(1) xor xored(0);
38 | xored(2) <= data(2) xor xored(1);
39 | xored(3) <= data(3) xor xored(2);
40 | xored(4) <= data(4) xor xored(3);
41 | xored(5) <= data(5) xor xored(4);
42 | xored(6) <= data(6) xor xored(5);
43 | xored(7) <= data(7) xor xored(6);
44 | xored(8) <= '1';
45 |
46 | xnored(0) <= data(0);
47 | xnored(1) <= data(1) xnor xnored(0);
48 | xnored(2) <= data(2) xnor xnored(1);
49 | xnored(3) <= data(3) xnor xnored(2);
50 | xnored(4) <= data(4) xnor xnored(3);
51 | xnored(5) <= data(5) xnor xnored(4);
52 | xnored(6) <= data(6) xnor xnored(5);
53 | xnored(7) <= data(7) xnor xnored(6);
54 | xnored(8) <= '0';
55 |
56 | -- Count how many ones are set in data
57 | ones <= "0000" + data(0) + data(1) + data(2) + data(3)
58 | + data(4) + data(5) + data(6) + data(7);
59 |
60 | -- Decide which encoding to use
61 | process(ones, data(0), xnored, xored)
62 | begin
63 | if ones > 4 or (ones = 4 and data(0) = '0') then
64 | data_word <= xnored;
65 | data_word_inv <= NOT(xnored);
66 | else
67 | data_word <= xored;
68 | data_word_inv <= NOT(xored);
69 | end if;
70 | end process;
71 |
72 | -- Work out the DC bias of the dataword;
73 | data_word_disparity <= "1100" + data_word(0) + data_word(1) + data_word(2) + data_word(3)
74 | + data_word(4) + data_word(5) + data_word(6) + data_word(7);
75 |
76 | -- Now work out what the output should be
77 | process(clk)
78 | begin
79 | if rising_edge(clk) then
80 | if blank = '1' then
81 | -- In the control periods, all values have and have balanced bit count
82 | case c is
83 | when "00" => e <= "1101010100";
84 | when "01" => e <= "0010101011";
85 | when "10" => e <= "0101010100";
86 | when others => e <= "1010101011";
87 | end case;
88 | dc_bias <= (others => '0');
89 | else
90 | if dc_bias = "00000" or data_word_disparity = 0 then
91 | -- dataword has no disparity
92 | if data_word(8) = '1' then
93 | e <= "01" & data_word(7 downto 0);
94 | dc_bias <= dc_bias + data_word_disparity;
95 | else
96 | e <= "10" & data_word_inv(7 downto 0);
97 | dc_bias <= dc_bias - data_word_disparity;
98 | end if;
99 | elsif (dc_bias(3) = '0' and data_word_disparity(3) = '0') or
100 | (dc_bias(3) = '1' and data_word_disparity(3) = '1') then
101 | e <= '1' & data_word(8) & data_word_inv(7 downto 0);
102 | dc_bias <= dc_bias + data_word(8) - data_word_disparity;
103 | else
104 | e <= '0' & data_word;
105 | dc_bias <= dc_bias - data_word_inv(8) + data_word_disparity;
106 | end if;
107 | end if;
108 | end if;
109 | end process;
110 | end Behavioral;
--------------------------------------------------------------------------------
/vhdl/dvid/dvid.vhd:
--------------------------------------------------------------------------------
1 | --------------------------------------------------------------------------------
2 | -- Engineer: Mike Field
3 | -- Description: Converts VGA signals into DVID bitstreams.
4 | --
5 | -- 'clk' and 'clk_n' should be 5x clk_pixel.
6 | --
7 | -- 'blank' should be asserted during the non-display
8 | -- portions of the frame
9 | --------------------------------------------------------------------------------
10 | library IEEE;
11 | use IEEE.STD_LOGIC_1164.ALL;
12 | Library UNISIM;
13 | use UNISIM.vcomponents.all;
14 |
15 | entity dvid is
16 | Port ( clk : in STD_LOGIC;
17 | clk_n : in STD_LOGIC;
18 | clk_pixel : in STD_LOGIC;
19 | red_p : in STD_LOGIC_VECTOR (7 downto 0);
20 | green_p : in STD_LOGIC_VECTOR (7 downto 0);
21 | blue_p : in STD_LOGIC_VECTOR (7 downto 0);
22 | blank : in STD_LOGIC;
23 | hsync : in STD_LOGIC;
24 | vsync : in STD_LOGIC;
25 | red_s : out STD_LOGIC;
26 | green_s : out STD_LOGIC;
27 | blue_s : out STD_LOGIC;
28 | clock_s : out STD_LOGIC);
29 | end dvid;
30 |
31 | architecture Behavioral of dvid is
32 | COMPONENT TDMS_encoder
33 | PORT(
34 | clk : IN std_logic;
35 | data : IN std_logic_vector(7 downto 0);
36 | c : IN std_logic_vector(1 downto 0);
37 | blank : IN std_logic;
38 | encoded : OUT std_logic_vector(9 downto 0)
39 | );
40 | END COMPONENT;
41 |
42 | signal encoded_red, encoded_green, encoded_blue : std_logic_vector(9 downto 0);
43 | signal latched_red, latched_green, latched_blue : std_logic_vector(9 downto 0) := (others => '0');
44 | signal shift_red, shift_green, shift_blue : std_logic_vector(9 downto 0) := (others => '0');
45 |
46 | signal shift_clock : std_logic_vector(9 downto 0) := "0000011111";
47 |
48 |
49 | constant c_red : std_logic_vector(1 downto 0) := (others => '0');
50 | constant c_green : std_logic_vector(1 downto 0) := (others => '0');
51 | signal c_blue : std_logic_vector(1 downto 0);
52 |
53 | begin
54 | c_blue <= vsync & hsync;
55 |
56 | TDMS_encoder_red: TDMS_encoder PORT MAP(clk => clk_pixel, data => red_p, c => c_red, blank => blank, encoded => encoded_red);
57 | TDMS_encoder_green: TDMS_encoder PORT MAP(clk => clk_pixel, data => green_p, c => c_green, blank => blank, encoded => encoded_green);
58 | TDMS_encoder_blue: TDMS_encoder PORT MAP(clk => clk_pixel, data => blue_p, c => c_blue, blank => blank, encoded => encoded_blue);
59 |
60 | ODDR2_red : ODDR2 generic map( DDR_ALIGNMENT => "C0", INIT => '0', SRTYPE => "ASYNC")
61 | port map (Q => red_s, D0 => shift_red(0), D1 => shift_red(1), C0 => clk, C1 => clk_n, CE => '1', R => '0', S => '0');
62 |
63 | ODDR2_green : ODDR2 generic map( DDR_ALIGNMENT => "C0", INIT => '0', SRTYPE => "ASYNC")
64 | port map (Q => green_s, D0 => shift_green(0), D1 => shift_green(1), C0 => clk, C1 => clk_n, CE => '1', R => '0', S => '0');
65 |
66 | ODDR2_blue : ODDR2 generic map( DDR_ALIGNMENT => "C0", INIT => '0', SRTYPE => "ASYNC")
67 | port map (Q => blue_s, D0 => shift_blue(0), D1 => shift_blue(1), C0 => clk, C1 => clk_n, CE => '1', R => '0', S => '0');
68 |
69 | ODDR2_clock : ODDR2 generic map( DDR_ALIGNMENT => "C0", INIT => '0', SRTYPE => "ASYNC")
70 | port map (Q => clock_s, D0 => shift_clock(0), D1 => shift_clock(1), C0 => clk, C1 => clk_n, CE => '1', R => '0', S => '0');
71 |
72 |
73 | process(clk_pixel)
74 | begin
75 | if rising_edge(clk_pixel) then
76 | latched_red <= encoded_red;
77 | latched_green <= encoded_green;
78 | latched_blue <= encoded_blue;
79 | end if;
80 | end process;
81 |
82 | process(clk)
83 | begin
84 | if rising_edge(clk) then
85 | if shift_clock = "0000011111" then
86 | shift_red <= latched_red;
87 | shift_green <= latched_green;
88 | shift_blue <= latched_blue;
89 | else
90 | shift_red <= "00" & shift_red (9 downto 2);
91 | shift_green <= "00" & shift_green(9 downto 2);
92 | shift_blue <= "00" & shift_blue (9 downto 2);
93 | end if;
94 | shift_clock <= shift_clock(1 downto 0) & shift_clock(9 downto 2);
95 | end if;
96 | end process;
97 |
98 | end Behavioral;
--------------------------------------------------------------------------------
/vhdl/dvid/vga_gen.vhd:
--------------------------------------------------------------------------------
1 | --
2 | -- Module modified for TPU use by Colin Riley, original header below.
3 | --
4 | ----------------------------------------------------------------------------------
5 | -- Engineer: Mike Field
6 | -- Module Name: ColourTest - Behavioral
7 | -- Description: Generates an 640x480 VGA showing all colours
8 | ----------------------------------------------------------------------------------
9 | library IEEE;
10 | use IEEE.STD_LOGIC_1164.ALL;
11 | use IEEE.STD_LOGIC_UNSIGNED.ALL;
12 |
13 | entity vga_gen is
14 | generic (
15 | hRez : natural := 640;
16 | hStartSync : natural := 656;
17 | hEndSync : natural := 752;
18 | hMaxCount : natural := 800;
19 | hsyncActive : std_logic := '0';
20 |
21 | vRez : natural := 480;
22 | vStartSync : natural := 490;
23 | vEndSync : natural := 492;
24 | vMaxCount : natural := 525;
25 | vsyncActive : std_logic := '1'
26 | );
27 |
28 | Port (
29 | pixel_clock : in std_logic;
30 |
31 | pixel_h : out STD_LOGIC_VECTOR(11 downto 0) := (others => '0');
32 | pixel_v : out STD_LOGIC_VECTOR(11 downto 0) := (others => '0');
33 |
34 |
35 | pixel_h_pref : out STD_LOGIC_VECTOR(11 downto 0) := (others => '0');
36 | pixel_v_pref : out STD_LOGIC_VECTOR(11 downto 0) := (others => '0');
37 | blank_pref : OUT std_logic;
38 |
39 | blank : out STD_LOGIC := '0';
40 | hsync : out STD_LOGIC := '0';
41 | vsync : out STD_LOGIC := '0'
42 | );
43 | end vga_gen;
44 |
45 | architecture Behavioral of vga_gen is
46 | type reg is record
47 | hCounter : std_logic_vector(11 downto 0);
48 | vCounter : std_logic_vector(11 downto 0);
49 |
50 |
51 | red : std_logic_vector(7 downto 0);
52 | green : std_logic_vector(7 downto 0);
53 | blue : std_logic_vector(7 downto 0);
54 |
55 | hSync : std_logic;
56 | vSync : std_logic;
57 | blank : std_logic;
58 | end record;
59 |
60 | signal r : reg := ((others=>'0'), (others=>'0'),
61 | (others=>'0'), (others=>'0'), (others=>'0'),
62 | '0', '0', '1');
63 | signal n : reg;
64 |
65 |
66 | type regqueue is array (15 downto 0) of reg;
67 |
68 | signal queue: regqueue := (others=> ((others=>'0'), (others=>'0'),
69 | (others=>'0'), (others=>'0'), (others=>'0'),
70 | '0', '0', '1') );
71 | begin
72 | -- Assign the outputs
73 | hsync <= queue(15).hSync;
74 | vsync <= queue(15).vSync;
75 |
76 | pixel_h <= queue(15).hCounter;
77 | pixel_v <= queue(15).vCounter;
78 | blank <= queue(15).blank;
79 |
80 | pixel_h_pref <= queue(8).hCounter;
81 | pixel_v_pref <= queue(8).vCounter;
82 | blank_pref <= queue(8).blank;
83 |
84 |
85 | process(queue(0),n)
86 | begin
87 | n <= queue(0);
88 | n.hSync <= not hSyncActive;
89 | n.vSync <= not vSyncActive;
90 |
91 | -- Count the lines and rows
92 | if queue(0).hCounter = hMaxCount-1 then
93 | n.hCounter <= (others => '0');
94 | if queue(0).vCounter = vMaxCount-1 then
95 | n.vCounter <= (others => '0');
96 | else
97 | n.vCounter <= queue(0).vCounter +1; --r.vCounter+1;
98 | end if;
99 | else
100 | n.hCounter <= queue(0).hCounter + 1; --r.hCounter+1;
101 | end if;
102 |
103 | if queue(0).hCounter < hRez and queue(0).vCounter < vRez then
104 | n.red <= n.hCounter(5 downto 0) & n.hCounter(5 downto 4);
105 | n.green <= n.hCounter(7 downto 0);
106 | n.blue <= n.vCounter(7 downto 0);
107 | n.blank <= '0';
108 | else
109 | n.red <= (others => '0');
110 | n.green <= (others => '0');
111 | n.blue <= (others => '0');
112 | n.blank <= '1';
113 | end if;
114 |
115 | -- Are we in the hSync pulse?
116 | if queue(0).hCounter >= hStartSync and queue(0).hCounter < hEndSync then
117 | n.hSync <= hSyncActive;
118 | end if;
119 |
120 | -- Are we in the vSync pulse?
121 | if queue(0).vCounter >= vStartSync and queue(0).vCounter < vEndSync then
122 | n.vSync <= vSyncActive;
123 | end if;
124 | end process;
125 |
126 | process(pixel_clock,n)
127 | begin
128 | if rising_edge(pixel_clock)
129 | then
130 | queue(15 downto 1) <= queue(14 downto 0);
131 | queue(0) <= n;
132 | end if;
133 | end process;
134 | end Behavioral;
--------------------------------------------------------------------------------
/vhdl/test/tpu_top_test.vhd:
--------------------------------------------------------------------------------
1 | --------------------------------------------------------------------------------
2 | -- Company:
3 | -- Engineer:
4 | --
5 | -- Create Date: 08:43:06 01/12/2016
6 | -- Design Name:
7 | -- Module Name: C:/dev/github/MiniSpartan6plus/testpu - part10b - otheruart/tpu_top_test.vhd
8 | -- Project Name: testpu
9 | -- Target Device:
10 | -- Tool versions:
11 | -- Description:
12 | --
13 | -- VHDL Test Bench Created by ISE for module: tpu_top
14 | --
15 | -- Dependencies:
16 | --
17 | -- Revision:
18 | -- Revision 0.01 - File Created
19 | -- Additional Comments:
20 | --
21 | -- Notes:
22 | -- This testbench has been automatically generated using types std_logic and
23 | -- std_logic_vector for the ports of the unit under test. Xilinx recommends
24 | -- that these types always be used for the top-level I/O of a design in order
25 | -- to guarantee that the testbench will bind correctly to the post-implementation
26 | -- simulation model.
27 | --------------------------------------------------------------------------------
28 | LIBRARY ieee;
29 | USE ieee.std_logic_1164.ALL;
30 |
31 | -- Uncomment the following library declaration if using
32 | -- arithmetic functions with Signed or Unsigned values
33 | --USE ieee.numeric_std.ALL;
34 |
35 | ENTITY tpu_top_test IS
36 | END tpu_top_test;
37 |
38 | ARCHITECTURE behavior OF tpu_top_test IS
39 |
40 | -- Component Declaration for the Unit Under Test (UUT)
41 |
42 | COMPONENT tpu_top
43 | PORT(
44 | I_clk : IN std_logic;
45 | O_tx : OUT std_logic;
46 | I_rx : IN std_logic;
47 | -- O_tx2 : OUT std_logic;
48 | -- I_rx2 : IN std_logic;
49 | O_leds : OUT std_logic_vector(7 downto 0);
50 | I_switches : IN std_logic_vector(3 downto 0);
51 |
52 | hdmi_out_p : out STD_LOGIC_VECTOR(3 downto 0);
53 | hdmi_out_n : out STD_LOGIC_VECTOR(3 downto 0)
54 |
55 | ; --
56 | D_vram_addr : out std_logic_vector(15 downto 0);
57 | D_vram_data : out std_logic_vector(15 downto 0)
58 | ;
59 | D_I_int : out std_logic;
60 | D_O_int_ack : OUT std_logic;
61 | D_MEM_I_ready : OUT std_logic;
62 | D_MEM_O_cmd : OUT std_logic;
63 | D_MEM_O_we : OUT std_logic;
64 | D_MEM_O_byteEnable : OUT std_logic_vector(1 downto 0);
65 | D_MEM_O_addr : OUT std_logic_vector(15 downto 0);
66 | D_MEM_O_data : OUT std_logic_vector(15 downto 0);
67 | D_MEM_I_data : OUT std_logic_vector(15 downto 0);
68 | D_MEM_I_dataReady : OUT std_logic;
69 | D_MEM_readyState : OUT std_logic_vector(7 downto 0)
70 | );
71 | END COMPONENT;
72 |
73 |
74 | --Inputs
75 | signal I_clk : std_logic := '0';
76 | signal I_rx : std_logic := '0';
77 | signal I_rx2 : std_logic := '0';
78 | signal I_switches : std_logic_vector(3 downto 0) := (others => '0');
79 | signal D_I_int : std_logic := '0';
80 |
81 | --Outputs
82 | signal O_tx : std_logic;
83 | signal O_tx2 : std_logic;
84 | signal O_leds : std_logic_vector(7 downto 0);
85 | signal D_O_int_ack : std_logic;
86 | signal D_MEM_I_ready : std_logic;
87 | signal D_MEM_O_cmd : std_logic;
88 | signal D_MEM_O_we : std_logic;
89 | signal D_MEM_O_byteEnable : std_logic_vector(1 downto 0);
90 | signal D_MEM_O_addr : std_logic_vector(15 downto 0);
91 | signal D_MEM_O_data : std_logic_vector(15 downto 0);
92 | signal D_MEM_I_data : std_logic_vector(15 downto 0);
93 | signal D_MEM_I_dataReady : std_logic;
94 | signal D_MEM_readyState : std_logic_vector(7 downto 0);
95 |
96 |
97 | signal hdmi_out_p : STD_LOGIC_VECTOR(3 downto 0);
98 | signal hdmi_out_n : STD_LOGIC_VECTOR(3 downto 0)
99 |
100 | ; --
101 | signal D_vram_addr : std_logic_vector(15 downto 0);
102 | signal D_vram_data : std_logic_vector(15 downto 0);
103 |
104 | -- Clock period definitions
105 | constant I_clk_period : time := 20 ns;
106 |
107 | BEGIN
108 |
109 | I_rx2 <= O_tx2;
110 |
111 | -- Instantiate the Unit Under Test (UUT)
112 | uut: tpu_top PORT MAP (
113 | I_clk => I_clk,
114 | O_tx => O_tx,
115 | I_rx => I_rx,
116 | -- O_tx2 => O_tx2,
117 | -- I_rx2 => I_rx2,
118 | O_leds => O_leds,
119 | I_switches => I_switches,
120 |
121 | hdmi_out_p => hdmi_out_p,
122 | hdmi_out_n => hdmi_out_n,
123 |
124 | D_vram_addr => D_vram_addr,
125 | D_vram_data => D_vram_data,
126 |
127 | D_I_int => D_I_int,
128 | D_O_int_ack => D_O_int_ack,
129 | D_MEM_I_ready => D_MEM_I_ready,
130 | D_MEM_O_cmd => D_MEM_O_cmd,
131 | D_MEM_O_we => D_MEM_O_we,
132 | D_MEM_O_byteEnable => D_MEM_O_byteEnable,
133 | D_MEM_O_addr => D_MEM_O_addr,
134 | D_MEM_O_data => D_MEM_O_data,
135 | D_MEM_I_data => D_MEM_I_data,
136 | D_MEM_I_dataReady => D_MEM_I_dataReady,
137 | D_MEM_readyState => D_MEM_readyState
138 | );
139 |
140 | -- Clock process definitions
141 | I_clk_process :process
142 | begin
143 | I_clk <= '0';
144 | wait for I_clk_period/2;
145 | I_clk <= '1';
146 | wait for I_clk_period/2;
147 | end process;
148 |
149 |
150 | -- Stimulus process
151 | stim_proc: process
152 | begin
153 | -- hold reset state for 100 ns.
154 | wait for 100 ns;
155 |
156 | wait for I_clk_period*10;
157 |
158 | -- insert stimulus here
159 |
160 | wait;
161 | end process;
162 |
163 | END;
164 |
--------------------------------------------------------------------------------
/vhdl/top/clocking.vhd:
--------------------------------------------------------------------------------
1 | ----------------------------------------------------------------------------------
2 | -- Company:
3 | -- Engineer:
4 | --
5 | -- Create Date: 17:25:40 04/27/2016
6 | -- Design Name:
7 | -- Module Name: clocking - Behavioral
8 | -- Project Name:
9 | -- Target Devices:
10 | -- Tool versions:
11 | -- Description:
12 | --
13 | -- Dependencies:
14 | --
15 | -- Revision:
16 | -- Revision 0.01 - File Created
17 | -- Additional Comments:
18 | --
19 | ----------------------------------------------------------------------------------
20 | library IEEE;
21 | use IEEE.STD_LOGIC_1164.ALL;
22 |
23 | library UNISIM;
24 | use UNISIM.VComponents.all;
25 |
26 |
27 | entity clocking is
28 | Port ( I_unbuff_clk50 : in STD_LOGIC;
29 | O_buff_clkcore : out STD_LOGIC;
30 | O_buff_clkpixel : out STD_LOGIC;
31 | O_buff_clk5xpixel : out STD_LOGIC;
32 | O_buff_clk5xpixelinv : out STD_LOGIC;
33 | O_buff_clkfmem : out STD_LOGIC;
34 | O_buff_clk50 : out STD_LOGIC;
35 | I_state : in STD_LOGIC_VECTOR(7 downto 0)
36 | );
37 | end clocking;
38 |
39 | architecture Behavioral of clocking is
40 | signal clock_core : std_logic;
41 | signal clock_core_unbuffered : std_logic;
42 | signal clock_pixel : std_logic;
43 | signal clock_pixel_unbuffered : std_logic;
44 | signal clock_x5pixel : std_logic;
45 | signal clock_x5pixel_unbuffered : std_logic;
46 | signal clock_x5pixelinv : std_logic;
47 | signal clock_x5pixelinv_unbuffered : std_logic;
48 | signal clock_fmem : std_logic;
49 | signal clock_fmem_unbuffered : std_logic;
50 | signal clk_feedback : std_logic;
51 | signal clk50_buffered : std_logic;
52 | signal pll_locked : std_logic;
53 | signal state : std_logic_vector(7 downto 0);
54 | begin
55 |
56 | -- State will at some point allow for switching of clocks
57 | state <= I_state;
58 |
59 | PLL_BASE_inst : PLL_BASE
60 | generic map (
61 | CLKFBOUT_MULT => 10, --500MHz
62 | CLKOUT0_DIVIDE => 20, --25MHz
63 | CLKOUT0_PHASE => 0.0,
64 |
65 | CLKOUT1_DIVIDE => 4, --125MHz
66 | CLKOUT1_PHASE => 0.0,
67 |
68 | CLKOUT2_DIVIDE => 4, --125MHz
69 | CLKOUT2_PHASE => 180.0,
70 |
71 | CLKOUT3_DIVIDE => 5, --100MHz
72 | CLKOUT3_PHASE => 0.0,
73 |
74 | CLKOUT4_DIVIDE => 2, --250MHz
75 | CLKOUT4_PHASE => 0.0,
76 |
77 | CLK_FEEDBACK => "CLKFBOUT",
78 | CLKIN_PERIOD => 20.0,
79 | DIVCLK_DIVIDE => 1
80 | )
81 | port map (
82 | CLKFBOUT => clk_feedback,
83 | CLKOUT0 => clock_pixel_unbuffered,
84 | CLKOUT1 => clock_x5pixel_unbuffered,
85 | CLKOUT2 => clock_x5pixelinv_unbuffered,
86 | CLKOUT3 => clock_core_unbuffered,
87 | CLKOUT4 => clock_fmem_unbuffered,
88 | CLKOUT5 => open,
89 | LOCKED => pll_locked,
90 | CLKFBIN => clk_feedback,
91 | CLKIN => clk50_buffered,
92 | RST => '0'
93 | );
94 |
95 | BUFG_clk : BUFG port map
96 | (
97 | I => I_unbuff_clk50,
98 | O => clk50_buffered
99 | );
100 |
101 | BUFG_core : BUFG port map
102 | (
103 | I => clock_core_unbuffered,
104 | O => clock_core
105 | );
106 |
107 | BUFG_pclock : BUFG port map
108 | (
109 | I => clock_pixel_unbuffered,
110 | O => clock_pixel
111 | );
112 |
113 | BUFG_pclockx5 : BUFG port map
114 | (
115 | I => clock_x5pixel_unbuffered,
116 | O => clock_x5pixel
117 | );
118 |
119 | BUFG_pclockx5_180 : BUFG port map
120 | (
121 | I => clock_x5pixelinv_unbuffered,
122 | O => clock_x5pixelinv
123 | );
124 |
125 |
126 | BUFG_fmem : BUFG port map
127 | (
128 | I => clock_fmem_unbuffered,
129 | O => clock_fmem
130 | );
131 |
132 |
133 | O_buff_clk50 <= clk50_buffered;
134 | O_buff_clkcore <= clock_core;
135 | O_buff_clkpixel <= clock_pixel;
136 | O_buff_clk5xpixel <= clock_x5pixel;
137 | O_buff_clk5xpixelinv <= clock_x5pixelinv;
138 | O_buff_clkfmem <= clock_fmem;
139 |
140 | end Behavioral;
141 |
142 |
--------------------------------------------------------------------------------
/vhdl/top/ebram.vhd:
--------------------------------------------------------------------------------
1 | LIBRARY ieee;
2 | USE ieee.std_logic_1164.ALL;
3 |
4 | use IEEE.NUMERIC_STD.ALL;
5 |
6 | Library UNISIM;
7 | use UNISIM.vcomponents.all;
8 |
9 | entity ebram is
10 | Port (I_clk : in STD_LOGIC;
11 | I_cs : in STD_LOGIC;
12 | I_we : in STD_LOGIC;
13 | I_addr : in STD_LOGIC_VECTOR (15 downto 0);
14 | I_data : in STD_LOGIC_VECTOR (15 downto 0);
15 | I_size : in STD_LOGIC;
16 | O_data : out STD_LOGIC_VECTOR (15 downto 0));
17 | end ebram;
18 |
19 | architecture Behavioral of ebram is
20 |
21 |
22 | -- Port A Data: 32-bit (each) output: Port A data
23 | signal DOA : std_logic_vector( 31 downto 0) := (others => '0'); -- 32-bit output: A port data output
24 | signal DOPA : std_logic_vector( 3 downto 0); -- 4-bit output: A port parity output
25 | -- Port A Address/Control Signals: 14-bit (each) input: Port A address and control signals
26 | signal ADDRA : std_logic_vector( 13 downto 0); -- 14-bit input: A port address input
27 | signal CLKA : std_logic:= '1'; -- 1-bit input: A port clock input
28 | signal ENA : std_logic:= '1'; -- 1-bit input: A port enable input
29 | signal REGCEA : std_logic:= '0'; -- 1-bit input: A port register clock enable input
30 | signal RSTA : std_logic:= '0'; -- 1-bit input: A port register set/reset input
31 | signal WEA : std_logic_vector( 3 downto 0) := "0000"; -- 4-bit input: Port A byte-wide write enable input
32 | -- Port A Data: 32-bit (each) input: Port A data
33 | signal DIA : std_logic_vector( 31 downto 0); -- 32-bit input: A port data input
34 | signal DIPA : std_logic_vector( 3 downto 0); -- 4-bit input: A port parity input
35 |
36 | -- Port B Data: 32-bit (each) output: Port B data
37 | signal DOB : std_logic_vector( 31 downto 0); -- 32-bit output: B port data output
38 | signal DOPB : std_logic_vector( 3 downto 0); -- 4-bit output: B port parity output
39 | -- Port B Address/Control Signals: 14-bit (each) input: Port B address and control signals
40 | signal ADDRB : std_logic_vector( 13 downto 0); -- 14-bit input: B port address input
41 | signal CLKB : std_logic:= '1'; -- 1-bit input: B port clock input
42 | signal ENB : std_logic:= '1'; -- 1-bit input: B port enable input
43 | signal REGCEB : std_logic:= '0'; -- 1-bit input: B port register clock enable input
44 | signal RSTB : std_logic:= '0'; -- 1-bit input: B port register set/reset input
45 | signal WEB : std_logic_vector( 3 downto 0) := "0000"; -- 4-bit input: Port B byte-wide write enable input
46 | -- Port B Data: 32-bit (each) input: Port B data
47 | signal DIB : std_logic_vector( 31 downto 0); -- 32-bit input: B port data input
48 | signal DIPB : std_logic_vector( 3 downto 0); -- 4-bit input: B port parity input
49 |
50 | signal data: std_logic_vector(15 downto 0) := X"0000";
51 | signal int_addr: integer := 0;
52 | begin
53 | -- RAMB16BWER: 16k-bit Data and 2k-bit Parity Configurable Synchronous Dual Port Block RAM with Optional Output Registers
54 | -- Spartan-6
55 | -- Xilinx HDL Language Template, version 14.4
56 |
57 | RAMB16BWER_inst : RAMB16BWER
58 | generic map (
59 | -- DATA_WIDTH_A/DATA_WIDTH_B: 0, 1, 2, 4, 9, 18, or 36
60 | DATA_WIDTH_A => 18,
61 | DATA_WIDTH_B => 18,
62 | -- DOA_REG/DOB_REG: Optional output register (0 or 1)
63 | DOA_REG => 0,
64 | DOB_REG => 0,
65 | -- EN_RSTRAM_A/EN_RSTRAM_B: Enable/disable RST
66 | EN_RSTRAM_A => TRUE,
67 | EN_RSTRAM_B => TRUE,
68 | -- INITP_00 to INITP_07: Initial memory contents.
69 | INITP_00 => X"0000000000000000000000000000000000000000000000000000000000000000",
70 | INITP_01 => X"0000000000000000000000000000000000000000000000000000000000000000",
71 | INITP_02 => X"0000000000000000000000000000000000000000000000000000000000000000",
72 | INITP_03 => X"0000000000000000000000000000000000000000000000000000000000000000",
73 | INITP_04 => X"0000000000000000000000000000000000000000000000000000000000000000",
74 | INITP_05 => X"0000000000000000000000000000000000000000000000000000000000000000",
75 | INITP_06 => X"0000000000000000000000000000000000000000000000000000000000000000",
76 | INITP_07 => X"0000000000000000000000000000000000000000000000000000000000000000",
77 | -- INIT_00 to INIT_3F: Initial memory contents.
78 |
79 | -- BEGIN TASM RAMB16BWER INIT OUTPUT
80 | INIT_00 => X"189C408D00E1F876F674F074EE72E872E670E070FD1E03E100C00420A6830080",
81 | INIT_01 => X"D10C00ECE51EE666E464E262E060C06AC00C04A00183D42C748B008C15C1C4DD",
82 | INIT_02 => X"0C7001874420A285008206C144D72494204280820BC1E670E070E50EA0C0F870",
83 | INIT_03 => X"3C0402049004D003C203000001E102E1FD0EEC6CEA6AE868E666E464E262E060",
84 | INIT_04 => X"000000000000000000000000000000B0000000000F0050050000000000000000",
85 | INIT_05 => X"0F810EE020810EE010810AE00083098106E0028116E0E91E088E000000000000",
86 | INIT_06 => X"0283098112E028200584B6830AE00183098106E0088112E028200584608306E0",
87 | INIT_07 => X"0183028112E028200584D8830AE00083028106E00E8112E02820058492830AE0",
88 | INIT_08 => X"A485008212E028200584E8830AE00483018106E00F8112E028200584E0830AE0",
89 | INIT_09 => X"F51E0AE004830A8128709582038584DB2C982B868ADD2C982A86008500624420",
90 | INIT_0A => X"DD0C00ECE8740085EA720A85E472230200624420A4850082E270442092850082",
91 | INIT_0B => X"A485008212E028200584F28312E0282000849283F50E00C00420BC830480F870",
92 | INIT_0C => X"44201C850182A4706CD7009600604C20A285008603E1206502E12302A062442A",
93 | INIT_0D => X"06E00F810EE05F8106E08F8112E028200584AE830AE00683018106E0038100C0",
94 | INIT_0E => X"0AE006830781A070282A0384BC8314C1A4D7B49A141B0D8B2AE092800EE02081",
95 | INIT_0F => X"0F810AE008830181E7CF0EE05F8106E08F810EE0A060282A0384BC8306E00F81",
96 | INIT_10 => X"648B15C1A4D7B49A141B6C8B0EE0A060282A0384BC8312E028200684028306E0",
97 | INIT_11 => X"06840E8306E004810AE008830A8121C1A4D7B49A141B6D8B1BC1A4D7B49A141B",
98 | INIT_12 => X"08830A81A4CF0470FF83908012E02820068418830AE008830A81AFCF12E02820",
99 | INIT_13 => X"12E0282006842C830AE008830A8199CF04700083908012E02820068422830AE0",
100 | INIT_14 => X"0F81047004834420BE850382047009834420C0850382047000834420A4850082",
101 | INIT_15 => X"0082E270442092850082F51E0AE020624422C085038200604420BE85038206E0",
102 | INIT_16 => X"F50E00C00420BC830480F870DD0C00ECE8740485EA721085E47200624420A485",
103 | INIT_17 => X"0082E270442092850082F51E0EE02D8112E028200084928312E028200584FA83",
104 | INIT_18 => X"BC830480F870DD0C00ECE8740485EA721085E4723802C31C088C00624420A485",
105 | INIT_19 => X"00820EE020810EE03A8112E028200084928312E028200584FA83F50E00C00420",
106 | INIT_1A => X"088C00604C20A285008603E1206502E14C7000874C24A2850086A062442AA485",
107 | INIT_1B => X"0684368306E0028107C112E0282006843E8306E0048108C164D70096A4703802",
108 | INIT_1C => X"09834420C085038284CF64D1289618850470230200624420C085038212E02820",
109 | INIT_1D => X"0000000000C1F5CD74CF64DB2896328504703F023F0200624420BE8503820470",
110 | INIT_1E => X"F870DD0C00ECEC72EA70ED1E5087E464C0C0E06C2C7028228A850082E2660000",
111 | INIT_1F => X"E06C20702822908500820400B08204A001830400E262ED0E00C004205E830480",
112 | INIT_20 => X"F870DD0C00ECE670E91EE070E51EA0C0B82A388D048A4AD724940063E260C0C0",
113 | INIT_21 => X"BF84B082C0C0E06CA0C0B82A048D048A0300E50EE060E90E00C0042090830480",
114 | INIT_22 => X"E462C0C0E06C2C70B086282290850082FCCF2502307068DB28960F894C24BF87",
115 | INIT_23 => X"0ED706E066D740960081E464E262C0C0E06CFCCF43140400A8D3489A0081E264",
116 | INIT_24 => X"B086A4DD109AC0882066282290850082C0C0E06C76D3FF86281203006ADD2896",
117 | INIT_25 => X"E460E26AC0C0E06C2C70282290850082650668716571E262216528228A850082",
118 | INIT_26 => X"E06AED0E00C0042072830480F870DD0C00ECE872E270ED1EF470E51EE664E664",
119 | INIT_27 => X"B01CE26860C07026C28904866AD30096A30AAC7180672C0870263E890586E50E",
120 | INIT_28 => X"05826ADD9496E268A31AAC710087F6CFA30AA47130836ADD649701837817E866",
121 | INIT_29 => X"3130C0C0E06C40C044241A850582A31A8308A4718871A065806340C044243A85",
122 | INIT_2A => X"C0C0E06C46617CD36C964867E264018300004645444342413938373635343332",
123 | INIT_2B => X"2020312E30206E6F697372655620534F4942202B366E617472617053696E696D",
124 | INIT_2C => X"6F642E7362616C2F2F3A70747468202D000020352E312041534920555043202D",
125 | INIT_2D => X"3A726F737365636F725000003E2320646D630000206D6F632E7375656870696D",
126 | INIT_2E => X"00000084838281800000207A484D30303120746120555054207469622D363120",
127 | INIT_2F => X"58580000783000007365747962200000203A79726F6D654D0000008988878685",
128 | INIT_30 => X"006E6F205344454C0000216E776F6E6B6E55000000203A646E616D6D6F430000",
129 | INIT_31 => X"6E55000064657070614D0000203F79726F6D654D000066666F205344454C0000",
130 | INIT_32 => X"76207373656363612079726F6D656D2064657070616D6E55000064657070616D",
131 | INIT_33 => X"0000000000000000000000000000000000007830207461206E6F6974616C6F69",
132 | INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",
133 | INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",
134 | INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",
135 | INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",
136 | INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",
137 | INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",
138 | INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",
139 | INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",
140 | INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",
141 | INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",
142 | INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",
143 | INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000",
144 | -- END TASM RAMB16BWER INIT OUTPUT
145 |
146 |
147 |
148 |
149 |
150 |
151 | -- INIT_A/INIT_B: Initial values on output port
152 | INIT_A => X"000000000",
153 | INIT_B => X"000000000",
154 | -- INIT_FILE: Optional file used to specify initial RAM contents
155 | INIT_FILE => "NONE",
156 | -- RSTTYPE: "SYNC" or "ASYNC"
157 | RSTTYPE => "SYNC",
158 | -- RST_PRIORITY_A/RST_PRIORITY_B: "CE" or "SR"
159 | RST_PRIORITY_A => "CE",
160 | RST_PRIORITY_B => "CE",
161 | -- SIM_COLLISION_CHECK: Collision check enable "ALL", "WARNING_ONLY", "GENERATE_X_ONLY" or "NONE"
162 | SIM_COLLISION_CHECK => "ALL",
163 | -- SIM_DEVICE: Must be set to "SPARTAN6" for proper simulation behavior
164 | SIM_DEVICE => "SPARTAN6",
165 | -- SRVAL_A/SRVAL_B: Set/Reset value for RAM output
166 | SRVAL_A => X"af0000000",
167 | SRVAL_B => X"bf0000000",
168 | -- WRITE_MODE_A/WRITE_MODE_B: "WRITE_FIRST", "READ_FIRST", or "NO_CHANGE"
169 | WRITE_MODE_A => "WRITE_FIRST",
170 | WRITE_MODE_B => "WRITE_FIRST"
171 | )
172 | port map (
173 | -- Port A Data: 32-bit (each) output: Port A data
174 | DOA => DOA, -- 32-bit output: A port data output
175 | DOPA => DOPA, -- 4-bit output: A port parity output
176 | -- Port B Data: 32-bit (each) output: Port B data
177 | DOB => DOB, -- 32-bit output: B port data output
178 | DOPB => DOPB, -- 4-bit output: B port parity output
179 | -- Port A Address/Control Signals: 14-bit (each) input: Port A address and control signals
180 | ADDRA => ADDRA, -- 14-bit input: A port address input
181 | CLKA => CLKA, -- 1-bit input: A port clock input
182 | ENA => ENA, -- 1-bit input: A port enable input
183 | REGCEA => REGCEA, -- 1-bit input: A port register clock enable input
184 | RSTA => RSTA, -- 1-bit input: A port register set/reset input
185 | WEA => WEA, -- 4-bit input: Port A byte-wide write enable input
186 | -- Port A Data: 32-bit (each) input: Port A data
187 | DIA => DIA, -- 32-bit input: A port data input
188 | DIPA => DIPA, -- 4-bit input: A port parity input
189 | -- Port B Address/Control Signals: 14-bit (each) input: Port B address and control signals
190 | ADDRB => ADDRB, -- 14-bit input: B port address input
191 | CLKB => CLKB, -- 1-bit input: B port clock input
192 | ENB => ENB, -- 1-bit input: B port enable input
193 | REGCEB => REGCEB, -- 1-bit input: B port register clock enable input
194 | RSTB => RSTB, -- 1-bit input: B port register set/reset input
195 | WEB => WEB, -- 4-bit input: Port B byte-wide write enable input
196 | -- Port B Data: 32-bit (each) input: Port B data
197 | DIB => DIB, -- 32-bit input: B port data input
198 | DIPB => DIPB -- 4-bit input: B port parity input
199 | );
200 |
201 | -- End of RAMB16BWER_inst instantiation
202 |
203 |
204 | --
205 | --todo: assertion on non-aligned 16b read?
206 | --
207 |
208 | CLKA <= I_clk;
209 | CLKB <= I_clk;
210 |
211 | ENA <= I_cs;
212 | ENB <= '0';--port B unused
213 |
214 | ADDRA <= I_addr(10 downto 1) & "0000";
215 |
216 | process (I_clk, I_cs)
217 | begin
218 | if rising_edge(I_clk) and I_cs = '1' then
219 | if (I_we = '1') then
220 | if I_size = '1' then
221 | -- 1 byte
222 | if I_addr(0) = '1' then
223 | WEA <= "0010";
224 | DIA <= X"0000" & I_data(7 downto 0) & X"00";
225 | else
226 | WEA <= "0001";
227 | DIA <= X"000000" & I_data(7 downto 0);
228 | end if;
229 | else
230 | WEA <= "0011";
231 | DIA <= X"0000" & I_data(7 downto 0)& I_data(15 downto 8);
232 | end if;
233 | else
234 | WEA <= "0000";
235 | WEB <= "0000";
236 | if I_size = '1' then
237 | if I_addr(0) = '0' then
238 | data(15 downto 8) <= X"00";
239 | data(7 downto 0) <= DOA(7 downto 0);
240 | else
241 | data(15 downto 8) <= X"00";
242 | data(7 downto 0) <= DOA(15 downto 8);
243 | end if;
244 | else
245 | data(15 downto 8) <= DOA(7 downto 0);
246 | data(7 downto 0) <= DOA(15 downto 8);
247 | end if;
248 | end if;
249 | end if;
250 | end process;
251 |
252 | O_data <= data when I_cs = '1' else "ZZZZZZZZZZZZZZZZ";
253 |
254 | end Behavioral;
--------------------------------------------------------------------------------
/vhdl/top/ebram2port.vhd:
--------------------------------------------------------------------------------
1 | LIBRARY ieee;
2 | USE ieee.std_logic_1164.ALL;
3 |
4 | use IEEE.NUMERIC_STD.ALL;
5 |
6 | Library UNISIM;
7 | use UNISIM.vcomponents.all;
8 |
9 | entity ebram2port is
10 | Port (I_clk : in STD_LOGIC;
11 | I_cs : in STD_LOGIC;
12 | I_we : in STD_LOGIC;
13 | I_addr : in STD_LOGIC_VECTOR (15 downto 0);
14 | I_data : in STD_LOGIC_VECTOR (15 downto 0);
15 | I_size : in STD_LOGIC;
16 | O_data : out STD_LOGIC_VECTOR (15 downto 0);
17 |
18 | I_p2_clk : in STD_LOGIC;
19 | I_p2_cs : in STD_LOGIC;
20 | I_p2_addr : in STD_LOGIC_VECTOR (15 downto 0);
21 | O_p2_data : out STD_LOGIC_VECTOR (15 downto 0)
22 |
23 | );
24 | end ebram2port;
25 |
26 | architecture Behavioral of ebram2port is
27 |
28 |
29 | -- Port A Data: 32-bit (each) output: Port A data
30 | signal DOA : std_logic_vector( 31 downto 0) := (others => '0'); -- 32-bit output: A port data output
31 | signal DOPA : std_logic_vector( 3 downto 0); -- 4-bit output: A port parity output
32 | -- Port A Address/Control Signals: 14-bit (each) input: Port A address and control signals
33 | signal ADDRA : std_logic_vector( 13 downto 0); -- 14-bit input: A port address input
34 | signal CLKA : std_logic:= '1'; -- 1-bit input: A port clock input
35 | signal ENA : std_logic:= '1'; -- 1-bit input: A port enable input
36 | signal REGCEA : std_logic:= '0'; -- 1-bit input: A port register clock enable input
37 | signal RSTA : std_logic:= '0'; -- 1-bit input: A port register set/reset input
38 | signal WEA : std_logic_vector( 3 downto 0) := "0000"; -- 4-bit input: Port A byte-wide write enable input
39 | -- Port A Data: 32-bit (each) input: Port A data
40 | signal DIA : std_logic_vector( 31 downto 0); -- 32-bit input: A port data input
41 | signal DIPA : std_logic_vector( 3 downto 0); -- 4-bit input: A port parity input
42 |
43 | -- Port B Data: 32-bit (each) output: Port B data
44 | signal DOB : std_logic_vector( 31 downto 0); -- 32-bit output: B port data output
45 | signal DOPB : std_logic_vector( 3 downto 0); -- 4-bit output: B port parity output
46 | -- Port B Address/Control Signals: 14-bit (each) input: Port B address and control signals
47 | signal ADDRB : std_logic_vector( 13 downto 0); -- 14-bit input: B port address input
48 | signal CLKB : std_logic:= '1'; -- 1-bit input: B port clock input
49 | signal ENB : std_logic:= '1'; -- 1-bit input: B port enable input
50 | signal REGCEB : std_logic:= '0'; -- 1-bit input: B port register clock enable input
51 | signal RSTB : std_logic:= '0'; -- 1-bit input: B port register set/reset input
52 | signal WEB : std_logic_vector( 3 downto 0) := "0000"; -- 4-bit input: Port B byte-wide write enable input
53 | -- Port B Data: 32-bit (each) input: Port B data
54 | signal DIB : std_logic_vector( 31 downto 0); -- 32-bit input: B port data input
55 | signal DIPB : std_logic_vector( 3 downto 0); -- 4-bit input: B port parity input
56 |
57 | signal data: std_logic_vector(15 downto 0) := X"0000";
58 | signal int_addr: integer := 0;
59 |
60 | signal data_p2: std_logic_vector(15 downto 0) := X"0000";
61 |
62 | begin
63 | -- RAMB16BWER: 16k-bit Data and 2k-bit Parity Configurable Synchronous Dual Port Block RAM with Optional Output Registers
64 | -- Spartan-6
65 | -- Xilinx HDL Language Template, version 14.4
66 |
67 | RAMB16BWER_inst : RAMB16BWER
68 | generic map (
69 | -- DATA_WIDTH_A/DATA_WIDTH_B: 0, 1, 2, 4, 9, 18, or 36
70 | DATA_WIDTH_A => 18,
71 | DATA_WIDTH_B => 18,
72 | -- DOA_REG/DOB_REG: Optional output register (0 or 1)
73 | DOA_REG => 0,
74 | DOB_REG => 0,
75 | -- EN_RSTRAM_A/EN_RSTRAM_B: Enable/disable RST
76 | EN_RSTRAM_A => TRUE,
77 | EN_RSTRAM_B => TRUE,
78 | -- INITP_00 to INITP_07: Initial memory contents.
79 | INITP_00 => X"0000000000000000000000000000000000000000000000000000000000000000",
80 | INITP_01 => X"0000000000000000000000000000000000000000000000000000000000000000",
81 | INITP_02 => X"0000000000000000000000000000000000000000000000000000000000000000",
82 | INITP_03 => X"0000000000000000000000000000000000000000000000000000000000000000",
83 | INITP_04 => X"0000000000000000000000000000000000000000000000000000000000000000",
84 | INITP_05 => X"0000000000000000000000000000000000000000000000000000000000000000",
85 | INITP_06 => X"0000000000000000000000000000000000000000000000000000000000000000",
86 | INITP_07 => X"0000000000000000000000000000000000000000000000000000000000000000",
87 | -- INIT_00 to INIT_3F: Initial memory contents.
88 |
89 | -- 565
90 | -- R F800
91 | -- G 07e0
92 | -- B 001F
93 |
94 | -- BEGIN TASM RAMB16BWER INIT OUTPUT
95 | INIT_00 => X"020f010f00000000000000000000000000000000000000000000000000000000",
96 | INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",
97 | INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",
98 | INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",
99 | INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",
100 |
101 | INIT_05 => X"040f030f00000000000000000000000000000000000000000000000000000000",
102 | INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",
103 | INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",
104 | INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",
105 | INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",
106 |
107 | INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",
108 | INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",
109 | INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",
110 | INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",
111 | INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",
112 | INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",
113 | INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",
114 | INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",
115 | INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",
116 | INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",
117 | INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",
118 | INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",
119 | INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",
120 | INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",
121 | INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",
122 | INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",
123 | INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",
124 | INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",
125 | INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",
126 | INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",
127 | INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",
128 | INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",
129 | INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",
130 | INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",
131 | INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",
132 | INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",
133 | INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",
134 | INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",
135 | INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",
136 | INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",
137 | INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",
138 | INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",
139 | INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",
140 | INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",
141 | INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",
142 | INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",
143 | INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",
144 | INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",
145 | INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",
146 | INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",
147 | INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",
148 | INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",
149 | INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",
150 | INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",
151 | INIT_36 => X"002f002f002f002f002f002f002f002f002f002f002f002f002f002f002f002f",
152 | INIT_37 => X"002f002f002f002f002f002f002f002f002f002f002f002f002f002f002f002f",
153 | INIT_38 => X"002f002f002f002f002f002f002f002f002f002f002f002f002f002f002f002f",
154 | INIT_39 => X"002f002f002f002f002f002f002f002f002f002f002f002f002f002f002f002f",
155 | INIT_3A => X"002f002f002f002f002f002f002f002f002f002f002f002f002f002f002f002f",
156 | INIT_3B => X"002f002f002f002f002f002f002f002f002f002f002f002f002f002f002f002f",
157 | INIT_3C => X"002f002f002f002f002f002f002f002f002f002f002f002f002f002f002f002f",
158 | INIT_3D => X"002f002f002f002f002f002f002f002f002f002f002f002f002f002f002f002f",
159 | INIT_3E => X"002f002f002f002f002f002f002f002f002f002f002f002f002f002f002f002f",
160 | INIT_3F => X"002f002f002f002f002f002f002f002f002f002f002f002f002f002f002f002f",
161 | -- END TASM RAMB16BWER INIT OUTPUT
162 |
163 |
164 |
165 |
166 | -- INIT_A/INIT_B: Initial values on output port
167 | INIT_A => X"000000000",
168 | INIT_B => X"000000000",
169 | -- INIT_FILE: Optional file used to specify initial RAM contents
170 | INIT_FILE => "NONE",
171 | -- RSTTYPE: "SYNC" or "ASYNC"
172 | RSTTYPE => "SYNC",
173 | -- RST_PRIORITY_A/RST_PRIORITY_B: "CE" or "SR"
174 | RST_PRIORITY_A => "CE",
175 | RST_PRIORITY_B => "CE",
176 | -- SIM_COLLISION_CHECK: Collision check enable "ALL", "WARNING_ONLY", "GENERATE_X_ONLY" or "NONE"
177 | SIM_COLLISION_CHECK => "ALL",
178 | -- SIM_DEVICE: Must be set to "SPARTAN6" for proper simulation behavior
179 | SIM_DEVICE => "SPARTAN6",
180 | -- SRVAL_A/SRVAL_B: Set/Reset value for RAM output
181 | SRVAL_A => X"af0000000",
182 | SRVAL_B => X"bf0000000",
183 | -- WRITE_MODE_A/WRITE_MODE_B: "WRITE_FIRST", "READ_FIRST", or "NO_CHANGE"
184 | WRITE_MODE_A => "WRITE_FIRST",
185 | WRITE_MODE_B => "WRITE_FIRST"
186 | )
187 | port map (
188 | -- Port A Data: 32-bit (each) output: Port A data
189 | DOA => DOA, -- 32-bit output: A port data output
190 | DOPA => DOPA, -- 4-bit output: A port parity output
191 | -- Port B Data: 32-bit (each) output: Port B data
192 | DOB => DOB, -- 32-bit output: B port data output
193 | DOPB => DOPB, -- 4-bit output: B port parity output
194 | -- Port A Address/Control Signals: 14-bit (each) input: Port A address and control signals
195 | ADDRA => ADDRA, -- 14-bit input: A port address input
196 | CLKA => CLKA, -- 1-bit input: A port clock input
197 | ENA => ENA, -- 1-bit input: A port enable input
198 | REGCEA => REGCEA, -- 1-bit input: A port register clock enable input
199 | RSTA => RSTA, -- 1-bit input: A port register set/reset input
200 | WEA => WEA, -- 4-bit input: Port A byte-wide write enable input
201 | -- Port A Data: 32-bit (each) input: Port A data
202 | DIA => DIA, -- 32-bit input: A port data input
203 | DIPA => DIPA, -- 4-bit input: A port parity input
204 | -- Port B Address/Control Signals: 14-bit (each) input: Port B address and control signals
205 | ADDRB => ADDRB, -- 14-bit input: B port address input
206 | CLKB => CLKB, -- 1-bit input: B port clock input
207 | ENB => ENB, -- 1-bit input: B port enable input
208 | REGCEB => REGCEB, -- 1-bit input: B port register clock enable input
209 | RSTB => RSTB, -- 1-bit input: B port register set/reset input
210 | WEB => WEB, -- 4-bit input: Port B byte-wide write enable input
211 | -- Port B Data: 32-bit (each) input: Port B data
212 | DIB => DIB, -- 32-bit input: B port data input
213 | DIPB => DIPB -- 4-bit input: B port parity input
214 | );
215 |
216 | -- End of RAMB16BWER_inst instantiation
217 |
218 |
219 | --
220 | --todo: assertion on non-aligned 16b read?
221 | --
222 |
223 | CLKA <= I_clk;
224 | CLKB <= I_p2_clk;
225 |
226 | ENA <= I_cs;
227 | ENB <= I_p2_cs;
228 |
229 | ADDRA <= I_addr(10 downto 1) & "0000";
230 | ADDRB <= I_p2_addr(10 downto 1) & "0000";
231 |
232 | WEB <= "0000";
233 |
234 | process (I_clk, I_cs)
235 | begin
236 | if rising_edge(I_clk) and I_cs = '1' then
237 | if (I_we = '1') then
238 | if I_size = '1' then
239 | -- 1 byte
240 | if I_addr(0) = '1' then
241 | WEA <= "0010";
242 | DIA <= X"0000" & I_data(7 downto 0) & X"00";
243 | else
244 | WEA <= "0001";
245 | DIA <= X"000000" & I_data(7 downto 0);
246 | end if;
247 | else
248 | WEA <= "0011";
249 | DIA <= X"0000" & I_data(7 downto 0)& I_data(15 downto 8);
250 | end if;
251 | else
252 | WEA <= "0000";
253 | if I_size = '1' then
254 | if I_addr(0) = '0' then
255 | data(15 downto 8) <= X"00";
256 | data(7 downto 0) <= DOA(7 downto 0);
257 | else
258 | data(15 downto 8) <= X"00";
259 | data(7 downto 0) <= DOA(15 downto 8);
260 | end if;
261 | else
262 | data(15 downto 8) <= DOA(7 downto 0);
263 | data(7 downto 0) <= DOA(15 downto 8);
264 | end if;
265 | end if;
266 | end if;
267 |
268 |
269 | end process;
270 |
271 | process (I_p2_clk, I_p2_cs)
272 | begin
273 | -- read port b
274 | if rising_edge(I_p2_clk) and I_p2_cs = '1' then
275 | data_p2(15 downto 8) <= DOB(7 downto 0);
276 | data_p2(7 downto 0) <= DOB(15 downto 8);
277 | end if;
278 | end process;
279 |
280 | O_data <= data when I_cs = '1' else "ZZZZZZZZZZZZZZZZ";
281 | O_p2_data <= data_p2 when I_p2_cs = '1' else "ZZZZZZZZZZZZZZZZ";
282 |
283 | end Behavioral;
--------------------------------------------------------------------------------
/vhdl/top/empty_font_rom.vhd:
--------------------------------------------------------------------------------
1 | -- Empty Font ram for use in sim tests
2 | -- you can find a near (this interface is double the size) drop in
3 | -- for synthesis from http://ece320web.groups.et.byu.net/labs/VGATextGeneration/list_ch13_01_font_rom.vhd
4 | -- I didn't include it as I am unsure of licencing.
5 |
6 | library ieee;
7 | use ieee.std_logic_1164.all;
8 | use ieee.numeric_std.all;
9 | entity font_rom is
10 | port(
11 | clk: in std_logic;
12 | addr: in std_logic_vector(11 downto 0);
13 | data: out std_logic_vector(7 downto 0)
14 | );
15 | end font_rom;
16 |
17 | architecture arch of font_rom is
18 | constant ADDR_WIDTH: integer:=12;
19 | constant DATA_WIDTH: integer:=8;
20 | signal addr_reg: std_logic_vector(ADDR_WIDTH-1 downto 0);
21 | type rom_type is array (0 to 2**ADDR_WIDTH-1)
22 | of std_logic_vector(DATA_WIDTH-1 downto 0);
23 | -- ROM definition
24 | constant ROM: rom_type:=(
25 | others => "00000000"
26 | );
27 | begin
28 | -- addr register to infer block RAM
29 | process (clk)
30 | begin
31 | if (clk'event and clk = '1') then
32 | addr_reg <= addr;
33 | end if;
34 | end process;
35 | data <= ROM(to_integer(unsigned(addr_reg)));
36 | end arch;
37 |
38 |
--------------------------------------------------------------------------------
/vhdl/top/text_gen.vhd:
--------------------------------------------------------------------------------
1 | ----------------------------------------------------------------------------------
2 | -- Company: Domipheus Labs
3 | -- Engineer: Colin Riley
4 | --
5 | -- Create Date: 16:27:52 05/01/2016
6 | -- Design Name: Text-mode output generator
7 | -- Module Name: text_gen - Behavioral
8 | -- Project Name:
9 | -- Target Devices: Tested on Spartan6
10 | -- Tool versions:
11 | -- Description:
12 | --
13 | -- For a 640x480 resolution set of input pixel locations an 80x25 text-mode
14 | -- representation is generated. It is assumed the x direction pixels are
15 | -- scanned linearly.
16 | --
17 | -- Glyphs are stored in a font ram as 16 bytes, each bit selecting a foreground
18 | -- or background colour to display for a given pizel in an 8x16 glyph.
19 | --
20 | -- A clock faster than the pixel clock is needed to account for latency from
21 | -- worse-case two dependant memory reads per pixel. It is adviced that pixel
22 | -- locations are inputted early to the text_gen so data can be prefetched.
23 | --
24 | --
25 | -- Dependencies:
26 | --
27 | -- Revision:
28 | -- Revision 0.01 - File Created
29 | -- Additional Comments:
30 | --
31 | ----------------------------------------------------------------------------------
32 | library IEEE;
33 | use IEEE.STD_LOGIC_1164.ALL;
34 | use IEEE.NUMERIC_STD.ALL;
35 |
36 | entity text_gen is
37 | Port ( I_clk_pixel : in STD_LOGIC;
38 | I_clk_pixel10x : in STD_LOGIC;
39 |
40 | -- Inputs from VGA signal generator
41 | -- defines the 'next pixel'
42 | I_blank : in STD_LOGIC;
43 | I_x : in STD_LOGIC_VECTOR (11 downto 0);
44 | I_y : in STD_LOGIC_VECTOR (11 downto 0);
45 |
46 | -- Request data for a glyph row from FRAM
47 | O_FRAM_ADDR : out STD_LOGIC_VECTOR (15 downto 0);
48 | I_FRAM_DATA : in STD_LOGIC_VECTOR (15 downto 0);
49 |
50 | -- Request data from textual memory TRAM
51 | O_TRAM_ADDR : out STD_LOGIC_VECTOR (15 downto 0);
52 | I_TRAM_DATA : in STD_LOGIC_VECTOR (15 downto 0);
53 |
54 | -- The data for the relevant requested pixel
55 | O_R : out STD_LOGIC_VECTOR (7 downto 0);
56 | O_G : out STD_LOGIC_VECTOR (7 downto 0);
57 | O_B : out STD_LOGIC_VECTOR (7 downto 0)
58 | );
59 | end text_gen;
60 |
61 | architecture Behavioral of text_gen is
62 | -- state tracks the location in our state machine
63 | signal state: integer := 0;
64 |
65 | -- The blinking speed of characters is controlled by loctions
66 | -- in this counter
67 | signal blinker_count: unsigned(31 downto 0) := X"00000000";
68 |
69 | -- _us is the result of the address computation,
70 | -- whereas the logic_vector is the latched output to memory
71 | signal fram_addr_us: unsigned(15 downto 0):= X"0000";
72 | signal fram_addr: std_logic_vector( 15 downto 0) := X"0000";
73 | signal fram_data_latched: std_logic_vector(15 downto 0);
74 |
75 | -- Font ram addresses for glyphs above, text ram for ascii and
76 | -- attributes below.
77 | signal tram_addr_us: unsigned(15 downto 0):= X"0000";
78 | signal tram_addr: std_logic_vector( 15 downto 0) := X"0000";
79 | signal tram_data_latched: std_logic_vector(15 downto 0);
80 |
81 | -- the latched current_x value we are computing
82 | signal current_x: std_logic_vector( 11 downto 0) := X"FFF";
83 |
84 | -- Current fg and bg colours
85 | signal colour_fg: std_logic_vector(23 downto 0) := X"FFFFFF";
86 | signal colour_bg: std_logic_vector(23 downto 0) := X"FFFFFF";
87 | signal blink: std_logic := '1';
88 |
89 | -- outputs for our pixel colour
90 | signal r: std_logic_vector(7 downto 0) := X"00";
91 | signal g: std_logic_vector(7 downto 0) := X"00";
92 | signal b: std_logic_vector(7 downto 0) := X"00";
93 |
94 | type colour_rom_t is array (0 to 15) of std_logic_vector(23 downto 0);
95 | -- ROM definition
96 | constant colours: colour_rom_t:=(
97 | X"000000", -- 0 Black
98 | X"0000AA", -- 1 Blue
99 | X"00AA00", -- 2 Green
100 | X"00AAAA", -- 3 Cyan
101 | X"AA0000", -- 4 Red
102 | X"AA00AA", -- 5 Magenta
103 | X"AA5500", -- 6 Brown
104 | X"AAAAAA", -- 7 Light Gray
105 | X"555555", -- 8 Dark Gray
106 | X"5555FF", -- 9 Light Blue
107 | X"55FF55", -- a Light Green
108 | X"55FFFF", -- b Light Cyan
109 | X"FF5555", -- c Light Red
110 | X"FF55FF", -- d Light Magenta
111 | X"FFFF00", -- e Yellow
112 | X"FFFFFF" -- f White
113 | );
114 |
115 | begin
116 |
117 |
118 | tram_addr <= std_logic_vector(tram_addr_us);
119 | O_TRAM_ADDR <= tram_addr(14 downto 0) & '0';
120 |
121 |
122 | fram_addr <= std_logic_vector(fram_addr_us);
123 | O_FRAM_ADDR <= fram_addr(15 downto 0);
124 |
125 | process(I_clk_pixel)
126 | begin
127 | if rising_edge(I_clk_pixel) then
128 | blinker_count <= blinker_count + 1;
129 | end if;
130 | end process;
131 |
132 | process(I_clk_pixel10x)
133 | begin
134 | if rising_edge(I_clk_pixel10x) then
135 | if state < 8 then
136 | -- each clock either stay in a state, or move to the next one
137 | state <= state + 1;
138 | end if;
139 |
140 | if state = 3 then
141 | -- latch the data from TRAM and kick off FRAM read
142 | tram_data_latched <= I_TRAM_DATA;
143 | fram_addr_us <= (unsigned(tram_data_latched(7 downto 0)) * 16 ) + unsigned(I_y(3 downto 0));
144 | blink <= tram_data_latched(15);
145 | colour_fg <= colours( to_integer(unsigned( tram_data_latched(11 downto 8))));
146 | colour_bg <= colours( to_integer(unsigned( tram_data_latched(14 downto 12))));
147 |
148 | elsif state = 6 then
149 | -- latch the data from FRAM
150 | fram_data_latched <= I_FRAM_DATA;
151 | state <= 8;
152 |
153 | elsif current_x /= I_x then
154 | if (I_x(2 downto 0) = "000") then
155 |
156 | -- Each 8-byte pixel start, set the state and kick off TRAM fetch
157 | state <= 1;
158 | -- this multiply becomes a DSP slice
159 | tram_addr_us <= (unsigned( I_y(11 downto 4)) * 80) + unsigned(I_x(11 downto 3));
160 | else
161 | -- short circuit straight to shade state
162 | state <= 7;
163 | end if;
164 | current_x <= I_x;
165 |
166 | elsif state >= 8 then
167 | -- shade a pixel
168 |
169 | -- If the curret pixel should be foreground, and is not in a blink state, shade it foreground
170 | if (fram_data_latched(7 - to_integer(unsigned(I_x(2 downto 0)))) = '1')
171 | and (blinker_count(24) = '1' or (blink = '0')) then
172 |
173 | r <= colour_fg(23 downto 16);
174 | g <= colour_fg(15 downto 8);
175 | b <= colour_fg(7 downto 0);
176 | else
177 | r <= colour_bg(23 downto 16);
178 | g <= colour_bg(15 downto 8);
179 | b <= colour_bg(7 downto 0);
180 | end if;
181 |
182 | end if;
183 |
184 | end if;
185 | end process;
186 |
187 | -- When we are outside of our text area, have black pixels
188 | O_r <= r when unsigned(I_y) < 400 else X"00";
189 | O_g <= g when unsigned(I_y) < 400 else X"00";
190 | O_b <= b when unsigned(I_y) < 400 else X"00";
191 |
192 | end Behavioral;
193 |
194 |
--------------------------------------------------------------------------------
/vhdl/top/tpu_top.vhd:
--------------------------------------------------------------------------------
1 | ----------------------------------------------------------------------------------
2 | -- Company:
3 | -- Engineer:
4 | --
5 | -- Create Date: 08:18:24 10/13/2015
6 | -- Design Name:
7 | -- Module Name: tpu_top - Behavioral
8 | -- Project Name:
9 | -- Target Devices:
10 | -- Tool versions:
11 | -- Description:
12 | --
13 | -- Dependencies:
14 | --
15 | -- Revision:
16 | -- Revision 0.01 - File Created
17 | -- Additional Comments:
18 | --
19 | ----------------------------------------------------------------------------------
20 | library IEEE;
21 | use IEEE.STD_LOGIC_1164.ALL;
22 |
23 | use IEEE.NUMERIC_STD.ALL;
24 |
25 | library UNISIM;
26 | use UNISIM.VComponents.all;
27 |
28 | entity tpu_top is
29 | Port (
30 | I_clk : in STD_LOGIC;
31 |
32 | O_tx : out STD_LOGIC;
33 | I_rx : in STD_LOGIC;
34 |
35 | O_AUDIO1 : out STD_LOGIC;
36 | O_AUDIO2 : out STD_LOGIC;
37 |
38 | O_leds : out STD_LOGIC_VECTOR (7 downto 0);
39 | I_switches : in STD_LOGIC_VECTOR (3 downto 0);
40 |
41 | hdmi_out_p : out STD_LOGIC_VECTOR(3 downto 0);
42 | hdmi_out_n : out STD_LOGIC_VECTOR(3 downto 0)
43 |
44 | ; -- debug signals - useful for simulation
45 | D_vram_addr : out std_logic_vector(15 downto 0);
46 | D_vram_data : out std_logic_vector(15 downto 0);
47 | D_I_int : out std_logic;
48 | D_O_int_ack : out std_logic;
49 | D_MEM_I_ready : out std_logic;
50 | D_MEM_O_cmd : out std_logic;
51 | D_MEM_O_we : out std_logic;
52 | D_MEM_O_byteEnable : out std_logic_vector(1 downto 0);
53 | D_MEM_O_addr : out std_logic_vector(15 downto 0);
54 | D_MEM_O_data : out std_logic_vector(15 downto 0);
55 | D_MEM_I_data :out std_logic_vector(15 downto 0);
56 | D_MEM_I_dataReady : out std_logic;
57 | D_MEM_readyState: out std_logic_vector (7 downto 0)
58 | );
59 | end tpu_top;
60 |
61 | architecture Behavioral of tpu_top is
62 |
63 | COMPONENT clocking
64 | PORT (
65 | I_unbuff_clk50 : in STD_LOGIC;
66 | O_buff_clkcore : out STD_LOGIC;
67 | O_buff_clkpixel : out STD_LOGIC;
68 | O_buff_clk5xpixel : out STD_LOGIC;
69 | O_buff_clk5xpixelinv : out STD_LOGIC;
70 | O_buff_clkfmem : out STD_LOGIC;
71 | O_buff_clk50 : out STD_LOGIC;
72 | I_state : in STD_LOGIC_VECTOR(7 downto 0)
73 | );
74 | END COMPONENT;
75 |
76 | COMPONENT core
77 | PORT(
78 | I_clk : IN std_logic;
79 | I_reset : IN std_logic;
80 | I_halt : IN std_logic;
81 |
82 | I_int: in STD_LOGIC;
83 | O_int_ack: out STD_LOGIC;
84 |
85 | MEM_I_ready : IN std_logic;
86 | MEM_O_cmd : OUT std_logic;
87 | MEM_O_we : OUT std_logic;
88 | MEM_O_byteEnable : OUT std_logic_vector(1 downto 0);
89 | MEM_O_addr : OUT std_logic_vector(15 downto 0);
90 | MEM_O_data : OUT std_logic_vector(15 downto 0);
91 | MEM_I_data : IN std_logic_vector(15 downto 0);
92 | MEM_I_dataReady : IN std_logic
93 | );
94 | END COMPONENT;
95 |
96 | component ebram
97 | Port ( I_clk : in STD_LOGIC;
98 | I_cs : in STD_LOGIC;
99 | I_we : in STD_LOGIC;
100 | I_addr : in STD_LOGIC_VECTOR (15 downto 0);
101 | I_data : in STD_LOGIC_VECTOR (15 downto 0);
102 | I_size : in STD_LOGIC;
103 | O_data : out STD_LOGIC_VECTOR (15 downto 0)
104 | );
105 | end component;
106 |
107 | component ebram2port
108 | Port (I_clk : in STD_LOGIC;
109 | I_cs : in STD_LOGIC;
110 | I_we : in STD_LOGIC;
111 | I_addr : in STD_LOGIC_VECTOR (15 downto 0);
112 | I_data : in STD_LOGIC_VECTOR (15 downto 0);
113 | I_size : in STD_LOGIC;
114 | O_data : out STD_LOGIC_VECTOR (15 downto 0);
115 |
116 | I_p2_clk : in STD_LOGIC;
117 | I_p2_cs : in STD_LOGIC;
118 | I_p2_addr : in STD_LOGIC_VECTOR (15 downto 0);
119 | O_p2_data : out STD_LOGIC_VECTOR (15 downto 0)
120 |
121 | );
122 | end component;
123 |
124 | COMPONENT uart_simple
125 | PORT(
126 | I_clk : IN std_logic;
127 | I_clk_baud_count : in STD_LOGIC_VECTOR (15 downto 0);
128 | I_reset : IN std_logic;
129 | I_txData : IN std_logic_vector(7 downto 0);
130 | I_txSig : IN std_logic;
131 | O_txRdy : OUT std_logic;
132 | O_tx : OUT std_logic;
133 | I_rx : IN std_logic;
134 | I_rxCont : IN std_logic;
135 | O_rxData : OUT std_logic_vector(7 downto 0);
136 | O_rxSig : OUT std_logic;
137 | O_rxFrameError : out STD_LOGIC;
138 |
139 |
140 | D_rxClk : out STD_LOGIC;
141 | D_rxState: out integer;
142 | D_txClk : out STD_LOGIC;
143 | D_txState: out integer
144 | );
145 | END COMPONENT;
146 |
147 | component uart_tx6
148 | Port (
149 | data_in : in std_logic_vector(7 downto 0);
150 | en_16_x_baud : in std_logic;
151 | serial_out : out std_logic;
152 | buffer_write : in std_logic;
153 | buffer_data_present : out std_logic;
154 | buffer_half_full : out std_logic;
155 | buffer_full : out std_logic;
156 | buffer_reset : in std_logic;
157 | clk : in std_logic);
158 | end component;
159 |
160 | component uart_rx6
161 | Port (
162 | serial_in : in std_logic;
163 | en_16_x_baud : in std_logic;
164 | data_out : out std_logic_vector(7 downto 0);
165 | buffer_read : in std_logic;
166 | buffer_data_present : out std_logic;
167 | buffer_half_full : out std_logic;
168 | buffer_full : out std_logic;
169 | buffer_reset : in std_logic;
170 | clk : in std_logic);
171 | end component;
172 |
173 | ------------ VIDEO SUBSYSTEM ---------
174 |
175 | COMPONENT vga_gen
176 | PORT(
177 | pixel_clock : in std_logic;
178 |
179 | pixel_h : out STD_LOGIC_VECTOR(11 downto 0);
180 | pixel_v : out STD_LOGIC_VECTOR(11 downto 0);
181 |
182 |
183 |
184 | pixel_h_pref : out STD_LOGIC_VECTOR(11 downto 0) := (others => '0');
185 | pixel_v_pref : out STD_LOGIC_VECTOR(11 downto 0) := (others => '0');
186 | blank_pref : OUT std_logic;
187 |
188 | blank : OUT std_logic;
189 | hsync : OUT std_logic;
190 | vsync : OUT std_logic
191 | );
192 | END COMPONENT;
193 |
194 | COMPONENT text_gen is
195 | Port ( I_clk_pixel : in STD_LOGIC;
196 | I_clk_pixel10x : in STD_LOGIC;
197 |
198 | -- Inputs from VGA signal generator
199 | -- defines the 'next pixel'
200 | I_blank : in STD_LOGIC;
201 | I_x : in STD_LOGIC_VECTOR (11 downto 0);
202 | I_y : in STD_LOGIC_VECTOR (11 downto 0);
203 |
204 | -- Request data for a glyph row from FRAM
205 | O_FRAM_ADDR : out STD_LOGIC_VECTOR (15 downto 0);
206 | I_FRAM_DATA : in STD_LOGIC_VECTOR (15 downto 0);
207 |
208 | -- Request data from textual memory TRAM
209 | O_TRAM_ADDR : out STD_LOGIC_VECTOR (15 downto 0);
210 | I_TRAM_DATA : in STD_LOGIC_VECTOR (15 downto 0);
211 |
212 | -- The data for the relevant requested pixel
213 | O_R : out STD_LOGIC_VECTOR (7 downto 0);
214 | O_G : out STD_LOGIC_VECTOR (7 downto 0);
215 | O_B : out STD_LOGIC_VECTOR (7 downto 0)
216 | );
217 | end COMPONENT;
218 |
219 | COMPONENT font_rom is
220 | port(
221 | clk: in std_logic;
222 | addr: in std_logic_vector(11 downto 0);
223 | data: out std_logic_vector(7 downto 0)
224 | );
225 | end COMPONENT;
226 |
227 |
228 | COMPONENT dvid
229 | PORT(
230 | clk : IN std_logic;
231 | clk_n : IN std_logic;
232 | clk_pixel: IN std_logic;
233 | red_p : IN std_logic_vector(7 downto 0);
234 | green_p : IN std_logic_vector(7 downto 0);
235 | blue_p : IN std_logic_vector(7 downto 0);
236 | blank : IN std_logic;
237 | hsync : IN std_logic;
238 | vsync : IN std_logic;
239 | red_s : OUT std_logic;
240 | green_s : OUT std_logic;
241 | blue_s : OUT std_logic;
242 | clock_s : OUT std_logic
243 | );
244 | END COMPONENT;
245 |
246 | ----------------------------------------------------------------------------
247 | -- Memory Systems
248 |
249 | signal MEM_readyState: integer := 0;
250 |
251 | signal MEM_REQ_SIZE: std_logic := '0';
252 | signal MEM_WE : std_logic := '0';
253 |
254 | signal MEM_2KB_ADDR : std_logic_vector(15 downto 0);
255 | signal MEM_BANK_ID : std_logic_vector(4 downto 0);
256 |
257 | signal MEM_CS_ERAM_1 : std_logic := '0';
258 | signal MEM_CS_ERAM_2 : std_logic := '0';
259 | signal MEM_CS_ERAM_3 : std_logic := '0';
260 | signal MEM_CS_ERAM_4 : std_logic := '0';
261 | signal MEM_CS_ERAM_5 : std_logic := '0';
262 | signal MEM_CS_ERAM_6 : std_logic := '0';
263 | signal MEM_CS_ERAM_7 : std_logic := '0';
264 | signal MEM_CS_ERAM_8 : std_logic := '0';
265 |
266 | signal MEM_CS_FRAM_1 : std_logic := '0';
267 | signal MEM_CS_FRAM_2 : std_logic := '0';
268 |
269 | signal MEM_CS_TRAM_1 : std_logic := '0';
270 | signal MEM_CS_TRAM_2 : std_logic := '0';
271 |
272 | signal MEM_CS_VRAM_1 : std_logic := '0';
273 | signal MEM_CS_VRAM_2 : std_logic := '0';
274 | signal MEM_CS_VRAM_3 : std_logic := '0';
275 | signal MEM_CS_VRAM_4 : std_logic := '0';
276 | signal MEM_CS_VRAM_5 : std_logic := '0';
277 | signal MEM_CS_VRAM_6 : std_logic := '0';
278 | signal MEM_CS_VRAM_7 : std_logic := '0';
279 | signal MEM_CS_VRAM_8 : std_logic := '0';
280 |
281 | signal MEM_CS_SYSTEM : std_logic := '0';
282 |
283 |
284 | signal MEM_ANY_CS : std_logic := '0';
285 |
286 | signal MEM_DATA_OUT_ERAM_1: std_logic_vector(15 downto 0);
287 | signal MEM_DATA_OUT_ERAM_2: std_logic_vector(15 downto 0);
288 | signal MEM_DATA_OUT_ERAM_3: std_logic_vector(15 downto 0);
289 | signal MEM_DATA_OUT_ERAM_4: std_logic_vector(15 downto 0);
290 | signal MEM_DATA_OUT_ERAM_5: std_logic_vector(15 downto 0);
291 | signal MEM_DATA_OUT_ERAM_6: std_logic_vector(15 downto 0);
292 | signal MEM_DATA_OUT_ERAM_7: std_logic_vector(15 downto 0);
293 | signal MEM_DATA_OUT_ERAM_8: std_logic_vector(15 downto 0);
294 |
295 | signal MEM_DATA_OUT_FRAM_1: std_logic_vector(15 downto 0);
296 | signal MEM_DATA_OUT_FRAM_2: std_logic_vector(15 downto 0);
297 |
298 | signal MEM_DATA_OUT_TRAM_1: std_logic_vector(15 downto 0);
299 | signal MEM_DATA_OUT_TRAM_2: std_logic_vector(15 downto 0);
300 |
301 | signal MEM_DATA_OUT_VRAM_1: std_logic_vector(15 downto 0);
302 |
303 | signal MEM_Access_error : std_logic := '0';
304 | signal MEM_Access_error_bank : std_logic_vector(7 downto 0);
305 | signal MEM_access_int_state : integer := 0;
306 |
307 | ----------------------------------------------------------------------------
308 | -- UART
309 | signal uart_tx_data_in : std_logic_vector (7 downto 0) := X"00";
310 | signal uart_tx_data_present : std_logic ;
311 | signal uart_tx_half_full : std_logic ;
312 | signal uart_tx_full : std_logic ;
313 | signal uart_tx_reset : std_logic := '0';
314 | signal uart_rx_data_out: std_logic_vector (7 downto 0) := X"00";
315 | signal uart_rx_read : std_logic := '0';
316 | signal uart_rx_data_present: std_logic ;
317 | signal uart_rx_half_full: std_logic ;
318 | signal uart_rx_full: std_logic ;
319 | signal uart_rx_reset : std_logic := '0';
320 |
321 | signal write_to_uart_tx : std_logic := '0';
322 |
323 | signal baud_count : integer range 0 to 325:= 0;
324 | signal en_16_x_baud : std_logic := '0';
325 |
326 |
327 | ----------------------------------------------------------------------------
328 | -- Clock engine
329 | signal cEng_state : std_logic_vector(7 downto 0) := X"00";
330 | signal cEng_clk_core : std_logic;
331 | signal cEng_clk_pixel : std_logic;
332 | signal cEng_clk_5xpixel : std_logic;
333 | signal cEng_clk_5xpixel_inv : std_logic;
334 | signal cEng_clk_fmem : std_logic;
335 | signal cEng_clk_50 : std_logic;
336 |
337 | ----------------------------------------------------------------------------
338 | -- I/O
339 | signal IO_DATA : std_logic_vector(15 downto 0) := X"0000";
340 | signal IO_LEDS : std_logic_vector(7 downto 0) := X"00";
341 | signal IO_SWITCH: std_logic_vector(3 downto 0) := "0000";
342 |
343 | ----------------------------------------------------------------------------
344 | -- TPU Core 1 memory
345 | signal MEM_I_ready : std_logic := '1';
346 | signal MEM_I_data : std_logic_vector(15 downto 0) := (others => '0');
347 | signal MEM_I_dataReady : std_logic := '1';
348 | signal MEM_O_cmd : std_logic;
349 | signal MEM_O_we : std_logic;
350 | signal MEM_O_byteEnable : std_logic_vector(1 downto 0);
351 | signal MEM_O_addr : std_logic_vector(15 downto 0);
352 | signal MEM_O_data : std_logic_vector(15 downto 0);
353 |
354 | ----------------------------------------------------------------------------
355 | -- VRAM
356 | signal MEM_VRAM_ADDR: std_logic_vector (15 downto 0) := X"0000";
357 | signal vram_output_data: std_logic_vector (15 downto 0) := X"0000";
358 |
359 | ----------------------------------------------------------------------------
360 | -- Interrupts
361 | signal INT_DATA : std_logic_vector(15 downto 0) := X"0000";
362 | signal I_int: std_logic := '0';
363 | signal O_int_ack: std_logic;
364 |
365 | ----------------------------------------------------------------------------
366 | -- TPU Control
367 | signal I_reset : std_logic := '0';
368 | signal I_halt : std_logic := '0';
369 |
370 | ----------------------------------------------------------------------------
371 | -- TPU Control
372 | signal red_p : std_logic_vector(7 downto 0);
373 | signal green_p : std_logic_vector(7 downto 0);
374 | signal blue_p : std_logic_vector(7 downto 0);
375 | signal blank : std_logic;
376 | signal hsync : std_logic;
377 | signal vsync : std_logic;
378 |
379 | ----------------------------------------------------------------------------
380 | -- Graphics Subsystem
381 | signal pixel_h : STD_LOGIC_VECTOR(11 downto 0);
382 | signal pixel_v : STD_LOGIC_VECTOR(11 downto 0);
383 |
384 | signal pixel_h_pref : STD_LOGIC_VECTOR(11 downto 0);
385 | signal pixel_v_pref : STD_LOGIC_VECTOR(11 downto 0);
386 | signal blank_pref: std_logic;
387 | signal vram_addr : std_logic_vector(15 downto 0);
388 | signal vram_data : std_logic_vector(15 downto 0);
389 | signal vram_output_2: std_logic_vector(15 downto 0);
390 | signal ram_write_addr: std_logic_vector(15 downto 0);
391 | signal vram_we : std_logic := '0';
392 | signal red_ram_p : std_logic_vector(7 downto 0) := (others => '0');
393 | signal green_ram_p : std_logic_vector(7 downto 0) := (others => '0');
394 | signal blue_ram_p : std_logic_vector(7 downto 0) := (others => '0');
395 | signal video_enable : std_logic := '1';
396 | signal CS_VRAM : std_logic:= '0';
397 | signal red_s : std_logic;
398 | signal green_s : std_logic;
399 | signal blue_s : std_logic;
400 | signal clock_s : std_logic;
401 |
402 | ----------------------------------------------------------------------------
403 | -- Text Graphics Subsystem
404 |
405 | signal SYS_TRAM1_OUTDATA: std_logic_vector(15 downto 0);
406 | signal SYS_TRAM2_OUTDATA: std_logic_vector(15 downto 0);
407 | signal SYS_TRAM_2K_ADDR: std_logic_vector(15 downto 0);
408 |
409 | signal SYS_FRAM1_ADDR: std_logic_vector(15 downto 0);
410 | signal SYS_FRAM1_OUTDATA: std_logic_vector(15 downto 0);
411 |
412 | signal SYS_FRAM2_ADDR: std_logic_vector(15 downto 0);
413 | signal SYS_FRAM2_OUTDATA: std_logic_vector(15 downto 0);
414 |
415 |
416 | signal GFX_MODE: std_logic := '0'; -- 0 = text 1 = pixel
417 |
418 | signal TXT_R: std_logic_vector(7 downto 0);
419 | signal TXT_G: std_logic_vector(7 downto 0);
420 | signal TXT_B: std_logic_vector(7 downto 0);
421 |
422 | signal FRAM_DATA: std_logic_vector(15 downto 0);
423 | signal FRAM_ADDR: std_logic_vector(15 downto 0);
424 |
425 |
426 | signal FRAM_DATA_TEST: std_logic_vector(7 downto 0);
427 | signal FRAM_ADDR_TEST: std_logic_vector(11 downto 0);
428 |
429 | signal TRAM_DATA: std_logic_vector(15 downto 0);
430 | signal TRAM_ADDR: std_logic_vector(15 downto 0);
431 |
432 |
433 | signal SYS_COUNTER: integer := 0;
434 | signal SYS_AUDIO : std_logic:='0';
435 | signal SYS_AUDIO_REGISTER: std_logic_vector(15 downto 0) := X"0000";
436 | BEGIN
437 | I_reset <= I_switches(0);
438 | IO_SWITCH <= I_switches;
439 | --O_leds <= I_reset & I_rx & uart_rx_data_present & IO_LEDS( 4 downto 0);
440 | O_leds <= IO_LEDS(7 downto 0);
441 |
442 | -- D_MEM_I_ready <= MEM_I_ready ;
443 | -- D_MEM_O_cmd <= MEM_O_cmd;
444 | -- D_MEM_O_we <= MEM_O_we;
445 | -- D_MEM_O_byteEnable <= MEM_O_byteEnable;
446 | D_MEM_O_addr <= MEM_O_addr;
447 | D_MEM_O_data <= MEM_O_data;
448 | D_MEM_I_data <= MEM_I_data;
449 | D_MEM_I_dataReady <=MEM_I_dataReady ;
450 | -- D_MEM_readyState <= std_logic_vector(to_unsigned(MEM_readyState, D_MEM_readyState'length));
451 | --D_vram_addr <= X"00" & "000" & MEM_Access_error_bank;
452 | -- D_vram_data <= X"00" & "000" & MEM_O_addr(15 downto 11);
453 |
454 | clock_engine: clocking port map (
455 | I_unbuff_clk50 => I_clk,
456 | O_buff_clkcore => cEng_clk_core,
457 | O_buff_clkpixel => cEng_clk_pixel,
458 | O_buff_clk5xpixel => cEng_clk_5xpixel,
459 | O_buff_clk5xpixelinv => cEng_clk_5xpixel_inv,
460 | O_buff_clkfmem => cEng_clk_fmem,
461 | O_buff_clk50 => cEng_clk_50,
462 | I_state => cEng_state
463 | );
464 |
465 |
466 | -- at 0x1200
467 | tx1: uart_tx6 port map (
468 | data_in => uart_tx_data_in, --0x1200
469 | en_16_x_baud => en_16_x_baud,
470 | serial_out => O_tx,
471 | buffer_write => write_to_uart_tx, --0x1201
472 | buffer_data_present => uart_tx_data_present, --0x1202
473 | buffer_half_full => uart_tx_half_full, --0x1203
474 | buffer_full => uart_tx_full, --0x1204
475 | buffer_reset => uart_tx_reset, --0x1205
476 | clk => cEng_clk_50
477 | );
478 |
479 | rx1: uart_rx6 port map (
480 | serial_in => I_rx,
481 | en_16_x_baud => en_16_x_baud,
482 | data_out => uart_rx_data_out, --0x1206
483 | buffer_read => uart_rx_read, --0x1207
484 | buffer_data_present => uart_rx_data_present, --0x1208
485 | buffer_half_full => uart_rx_half_full, --0x1209
486 | buffer_full => uart_rx_full, --0x120a
487 | buffer_reset => uart_rx_reset, --0x120b
488 | clk => cEng_clk_50
489 | );
490 |
491 |
492 | core_1: core PORT MAP (
493 | I_clk => cEng_clk_core,
494 | I_reset => I_reset,
495 | I_halt => I_halt,
496 |
497 | I_int => I_int,
498 | O_int_ack => O_int_ack,
499 | MEM_I_ready => MEM_I_ready,
500 | MEM_O_cmd => MEM_O_cmd,
501 | MEM_O_we => MEM_O_we,
502 | MEM_O_byteEnable => MEM_O_byteEnable,
503 | MEM_O_addr => MEM_O_addr,
504 | MEM_O_data => MEM_O_data,
505 | MEM_I_data => MEM_I_data,
506 | MEM_I_dataReady => MEM_I_dataReady
507 | );
508 |
509 | ebram_1: ebram Port map (
510 | I_clk => cEng_clk_core,
511 | I_cs => MEM_CS_ERAM_1,
512 | I_we => MEM_WE,
513 | I_addr => MEM_2KB_ADDR,
514 | I_data => MEM_O_data,
515 | I_size => MEM_REQ_SIZE,
516 | O_data => MEM_DATA_OUT_ERAM_1
517 | );
518 |
519 | ebram_2: ebram Port map (
520 | I_clk => cEng_clk_core,
521 | I_cs => MEM_CS_ERAM_2,
522 | I_we => MEM_WE,
523 | I_addr => MEM_2KB_ADDR,
524 | I_data => MEM_O_data,
525 | I_size => MEM_REQ_SIZE,
526 | O_data => MEM_DATA_OUT_ERAM_2
527 | );
528 |
529 | ebram_3: ebram Port map (
530 | I_clk => cEng_clk_core,
531 | I_cs => MEM_CS_ERAM_3,
532 | I_we => MEM_WE,
533 | I_addr => MEM_2KB_ADDR,
534 | I_data => MEM_O_data,
535 | I_size => MEM_REQ_SIZE,
536 | O_data => MEM_DATA_OUT_ERAM_3
537 | );
538 |
539 | ebram_4: ebram Port map (
540 | I_clk => cEng_clk_core,
541 | I_cs => MEM_CS_ERAM_4,
542 | I_we => MEM_WE,
543 | I_addr => MEM_2KB_ADDR,
544 | I_data => MEM_O_data,
545 | I_size => MEM_REQ_SIZE,
546 | O_data => MEM_DATA_OUT_ERAM_4
547 | );
548 |
549 |
550 | ebram_5: ebram Port map (
551 | I_clk => cEng_clk_core,
552 | I_cs => MEM_CS_ERAM_5,
553 | I_we => MEM_WE,
554 | I_addr => MEM_2KB_ADDR,
555 | I_data => MEM_O_data,
556 | I_size => MEM_REQ_SIZE,
557 | O_data => MEM_DATA_OUT_ERAM_5
558 | );
559 |
560 | ebram_6: ebram Port map (
561 | I_clk => cEng_clk_core,
562 | I_cs => MEM_CS_ERAM_6,
563 | I_we => MEM_WE,
564 | I_addr => MEM_2KB_ADDR,
565 | I_data => MEM_O_data,
566 | I_size => MEM_REQ_SIZE,
567 | O_data => MEM_DATA_OUT_ERAM_6
568 | );
569 |
570 | ebram_7: ebram Port map (
571 | I_clk => cEng_clk_core,
572 | I_cs => MEM_CS_ERAM_7,
573 | I_we => MEM_WE,
574 | I_addr => MEM_2KB_ADDR,
575 | I_data => MEM_O_data,
576 | I_size => MEM_REQ_SIZE,
577 | O_data => MEM_DATA_OUT_ERAM_7
578 | );
579 |
580 | ebram_8: ebram Port map (
581 | I_clk => cEng_clk_core,
582 | I_cs => MEM_CS_ERAM_8,
583 | I_we => MEM_WE,
584 | I_addr => MEM_2KB_ADDR,
585 | I_data => MEM_O_data,
586 | I_size => MEM_REQ_SIZE,
587 | O_data => MEM_DATA_OUT_ERAM_8
588 | );
589 |
590 | audio_counter: process(cEng_clk_50)
591 | begin
592 | if rising_edge(cEng_clk_50) then
593 | if SYS_COUNTER > (50000)/2 then
594 | SYS_COUNTER <= 0;
595 | SYS_AUDIO <= not SYS_AUDIO;
596 | else
597 | SYS_COUNTER <= SYS_COUNTER + 1;
598 | end if;
599 | end if;
600 | end process;
601 |
602 | O_AUDIO2 <= SYS_AUDIO and SYS_AUDIO_REGISTER(0);
603 | O_AUDIO1 <= SYS_AUDIO and SYS_AUDIO_REGISTER(1);
604 |
605 |
606 | --50MHz => ~9600baud
607 | baud_rate: process(cEng_clk_50)
608 | begin
609 | if cEng_clk_50'event and cEng_clk_50 = '1' then
610 | if baud_count = 325 then
611 | baud_count <= 0;
612 | en_16_x_baud <= '1';
613 | else
614 | baud_count <= baud_count + 1;
615 | en_16_x_baud <= '0';
616 | end if;
617 | end if;
618 | end process baud_rate;
619 |
620 | MEM_REQ_SIZE <= '1' when MEM_O_byteEnable = "10" else '0';
621 |
622 | -- select the correct data to send to tpu
623 | MEM_I_data <= INT_DATA when O_int_ack = '1'
624 | else MEM_DATA_OUT_ERAM_1 when MEM_CS_ERAM_1 = '1'
625 | else MEM_DATA_OUT_ERAM_2 when MEM_CS_ERAM_2 = '1'
626 | else MEM_DATA_OUT_ERAM_3 when MEM_CS_ERAM_3 = '1'
627 | else MEM_DATA_OUT_ERAM_4 when MEM_CS_ERAM_4 = '1'
628 | else MEM_DATA_OUT_ERAM_5 when MEM_CS_ERAM_5 = '1'
629 | else MEM_DATA_OUT_ERAM_6 when MEM_CS_ERAM_6 = '1'
630 | else MEM_DATA_OUT_ERAM_7 when MEM_CS_ERAM_7 = '1'
631 | else MEM_DATA_OUT_ERAM_8 when MEM_CS_ERAM_8 = '1'
632 |
633 | else MEM_DATA_OUT_FRAM_1 when MEM_CS_FRAM_1 = '1'
634 | else MEM_DATA_OUT_FRAM_2 when MEM_CS_FRAM_2 = '1'
635 |
636 | else MEM_DATA_OUT_TRAM_1 when MEM_CS_TRAM_1 = '1'
637 | else MEM_DATA_OUT_TRAM_2 when MEM_CS_TRAM_2 = '1'
638 |
639 | else MEM_DATA_OUT_VRAM_1 when MEM_CS_VRAM_1 = '1'
640 | else IO_DATA ;
641 |
642 |
643 | MEM_WE <= MEM_O_cmd and MEM_O_we;
644 |
645 | -- mem brams banks are 2KB. to address inside we need to and with 0x07ff
646 | MEM_2KB_ADDR <= MEM_O_addr and X"07FF";
647 | MEM_BANK_ID <= MEM_O_addr(15 downto 11);
648 |
649 | -- Embedded ram
650 | MEM_CS_ERAM_1 <= '1' when (MEM_BANK_ID = X"0"&'0') else '0'; -- 0x00 bank
651 | MEM_CS_ERAM_2 <= '1' when (MEM_BANK_ID = X"0"&'1') else '0'; -- 0x08 bank
652 | MEM_CS_ERAM_3 <= '1' when (MEM_BANK_ID = X"1"&'0') else '0'; -- 0x10 bank
653 | MEM_CS_ERAM_4 <= '1' when (MEM_BANK_ID = X"1"&'1') else '0'; -- 0x18 bank
654 | MEM_CS_ERAM_5 <= '1' when (MEM_BANK_ID = X"2"&'0') else '0'; -- 0x20 bank
655 | MEM_CS_ERAM_6 <= '1' when (MEM_BANK_ID = X"2"&'1') else '0'; -- 0x28 bank
656 | MEM_CS_ERAM_7 <= '1' when (MEM_BANK_ID = X"3"&'0') else '0'; -- 0x30 bank
657 | MEM_CS_ERAM_8 <= '1' when (MEM_BANK_ID = X"3"&'1') else '0'; -- 0x38 bank
658 |
659 | MEM_CS_SYSTEM <= '1' when (MEM_BANK_ID = X"9"&'0') else '0'; -- 0x90 bank - system maps
660 | -- 4KB of font bitmap ram
661 | MEM_CS_FRAM_1 <= '1' when (MEM_BANK_ID = X"A"&'0') else '0'; -- 0xA0 bank
662 | MEM_CS_FRAM_2 <= '1' when (MEM_BANK_ID = X"A"&'1') else '0'; -- 0xA8 bank
663 | -- 4KB of text character ram
664 | MEM_CS_TRAM_1 <= '1' when (MEM_BANK_ID = X"B"&'0') else '0'; -- 0xB0 bank
665 | MEM_CS_TRAM_2 <= '1' when (MEM_BANK_ID = X"B"&'1') else '0'; -- 0xB8 bank
666 |
667 | -- 16KB of video ram
668 | MEM_CS_VRAM_1 <= '1' when (MEM_BANK_ID = X"C"&'0') else '0'; -- 0xC0 bank
669 | MEM_CS_VRAM_2 <= '1' when (MEM_BANK_ID = X"C"&'1') else '0'; -- 0xC8 bank
670 | MEM_CS_VRAM_3 <= '1' when (MEM_BANK_ID = X"D"&'0') else '0'; -- 0xD0 bank
671 | MEM_CS_VRAM_4 <= '1' when (MEM_BANK_ID = X"D"&'1') else '0'; -- 0xD8 bank
672 | MEM_CS_VRAM_5 <= '1' when (MEM_BANK_ID = X"E"&'0') else '0'; -- 0xE0 bank
673 | MEM_CS_VRAM_6 <= '1' when (MEM_BANK_ID = X"E"&'1') else '0'; -- 0xE8 bank
674 | MEM_CS_VRAM_7 <= '1' when (MEM_BANK_ID = X"F"&'0') else '0'; -- 0xF0 bank
675 | MEM_CS_VRAM_8 <= '1' when (MEM_BANK_ID = X"F"&'1') else '0'; -- 0xF8 bank
676 |
677 | -- if any CS line is active, this is 1
678 | MEM_ANY_CS <= MEM_CS_ERAM_1 or MEM_CS_ERAM_2 or MEM_CS_ERAM_3 or MEM_CS_ERAM_4 or
679 | MEM_CS_ERAM_5 or MEM_CS_ERAM_6 or MEM_CS_ERAM_7 or MEM_CS_ERAM_8 or
680 | MEM_CS_FRAM_1 or MEM_CS_FRAM_2 or MEM_CS_TRAM_1 or MEM_CS_TRAM_2 or
681 | MEM_CS_VRAM_1 or MEM_CS_VRAM_2 or MEM_CS_VRAM_3 or MEM_CS_VRAM_4 or
682 | MEM_CS_VRAM_5 or MEM_CS_VRAM_6 or MEM_CS_VRAM_7 or MEM_CS_VRAM_8 or
683 | MEM_CS_SYSTEM;
684 |
685 |
686 |
687 |
688 | --MEM_VRAM_ADDR <= X"0" & MEM_O_addr(11 downto 0);
689 |
690 | -- exception line handling:
691 | exception_notifier: process (cEng_clk_core, MEM_Access_error)
692 | begin
693 | if rising_edge(cEng_clk_core) then
694 | if MEM_Access_error = '1' and MEM_access_int_state = 0 then
695 | I_int <= '1';
696 | MEM_access_int_state <= 1;
697 | INT_DATA <= X"80" & MEM_Access_error_bank;
698 | elsif MEM_access_int_state = 1 and I_int = '1' and O_int_ack = '1' then
699 | I_int <= '0';
700 | MEM_access_int_state <= 2;
701 | elsif MEM_access_int_state = 2 then
702 | MEM_access_int_state <= 3;
703 | elsif MEM_access_int_state = 3 then
704 | MEM_access_int_state <= 0;
705 | end if;
706 | end if;
707 |
708 | end process;
709 |
710 | MEM_proc: process(cEng_clk_core)
711 | begin
712 | if rising_edge(cEng_clk_core) then
713 |
714 | if MEM_readyState = 0 then
715 | if MEM_O_cmd = '1' then
716 |
717 | if MEM_ANY_CS = '0' then
718 | -- a memory command with unmapped memory
719 | -- throw interrupt
720 | MEM_Access_error <= '1';
721 | MEM_Access_error_bank <= MEM_O_addr(15 downto 8);
722 | end if;
723 |
724 | -- system memory maps
725 | if MEM_O_addr = X"9000" and MEM_O_we = '1' then
726 | -- onboard leds
727 | IO_LEDS <= MEM_O_data( 7 downto 0);
728 | end if;
729 |
730 | if MEM_O_addr = X"9001" and MEM_O_we = '0' then
731 | -- onboard switches
732 | IO_DATA <= X"000" & IO_SWITCH;
733 | end if;
734 |
735 | -- Memory mapped audio config register
736 | if MEM_O_addr = X"9500" and MEM_O_we = '1' then
737 | SYS_AUDIO_REGISTER <= MEM_O_data( 15 downto 0);
738 | end if;
739 |
740 | if MEM_O_addr = X"9500" and MEM_O_we = '0' then
741 | IO_DATA <= SYS_AUDIO_REGISTER;
742 | end if;
743 |
744 | --tx
745 | --uart_tx_data_in, --0x9200
746 | --buffer_write => write_to_uart_tx, --0x9201 nop
747 | --buffer_data_present => uart_tx_data_present, --0x9202
748 | --buffer_half_full => uart_tx_half_full, --0x9203
749 | --buffer_full => uart_tx_full, --0x9204
750 | --buffer_reset => uart_tx_reset, --0x9205
751 | --rx
752 | --data_out => uart_rx_data_out, --0x9206
753 | --buffer_read => uart_rx_read, --0x9207 nop
754 | --buffer_data_present => uart_rx_data_present, --0x9208
755 | --buffer_half_full => uart_rx_half_full, --0x9209
756 | --buffer_full => uart_rx_full, --0x920a
757 | --buffer_reset => uart_rx_reset, --0x920b
758 |
759 | case MEM_O_addr is
760 | when X"9200" =>
761 | if MEM_O_we = '1' then
762 | uart_tx_data_in <= MEM_O_data(7 downto 0);
763 | write_to_uart_tx <= '1';
764 | end if;
765 | when X"9201" =>
766 | if MEM_O_we = '1' then
767 | -- NOP
768 | end if;
769 | when X"9202" =>
770 | if MEM_O_we = '0' then
771 | IO_DATA <= X"000" & "000" & uart_tx_data_present;
772 | end if;
773 | when X"9203" =>
774 | if MEM_O_we = '0' then
775 | IO_DATA <= X"000" & "000" & uart_tx_half_full;
776 | end if;
777 | when X"9204" =>
778 | if MEM_O_we = '0' then
779 | IO_DATA <= X"000" & "000" & uart_tx_full;
780 | end if;
781 | when X"9205" =>
782 | if MEM_O_we = '1' then
783 | uart_tx_reset <= MEM_O_data(0);
784 | end if;
785 |
786 | --rx2
787 | when X"9206" =>
788 | if MEM_O_we = '0' then
789 | IO_DATA <= X"00" & uart_rx_data_out;
790 | uart_rx_read <= '1';
791 | -- The 'real' read into IO_DATA is performed a cycle later
792 | -- Check readystate > 0 block below.
793 | end if;
794 | when X"9208" =>
795 | if MEM_O_we = '0' then
796 | IO_DATA <= X"000" & "000" & uart_rx_data_present;
797 | end if;
798 | when X"9209" =>
799 | if MEM_O_we = '0' then
800 | IO_DATA <= X"000" & "000" & uart_rx_half_full;
801 | end if;
802 | when X"920a" =>
803 | if MEM_O_we = '0' then
804 | IO_DATA <= X"000" & "000" & uart_rx_full;
805 | end if;
806 | when X"920b" =>
807 | if MEM_O_we = '1' then
808 | uart_rx_reset <= MEM_O_data(0);
809 | end if;
810 |
811 | when others =>
812 | end case;
813 |
814 | MEM_I_ready <= '0';
815 | MEM_I_dataReady <= '0';
816 | if MEM_O_we = '1' then
817 | MEM_readyState <= 7;
818 | else
819 | MEM_readyState <= 4;
820 | end if;
821 | end if;
822 | elsif MEM_readyState >= 1 then
823 | -- reset any strobes
824 | write_to_uart_tx <= '0';
825 | if uart_rx_read = '1' then
826 | uart_rx_read <= '0';
827 | IO_DATA <= X"00" & uart_rx_data_out;
828 | end if;
829 |
830 | if MEM_readyState = 6 then
831 | MEM_I_ready <= '1';
832 | MEM_I_dataReady <= '1';
833 | MEM_Access_error <= '0';
834 | MEM_readyState <= 0;
835 | elsif MEM_readyState = 8 then
836 | MEM_I_ready <= '0';
837 | MEM_I_dataReady <= '0';
838 | MEM_readyState <= 9;
839 | elsif MEM_readyState = 9 then
840 | MEM_I_ready <= '1';
841 | MEM_Access_error <= '0';
842 | MEM_readyState <= 0;
843 | else
844 | MEM_readyState <= MEM_readyState + 1;
845 | end if;
846 | end if;
847 |
848 | end if;
849 |
850 | end process;
851 |
852 |
853 | -- fram_1: ebram2port Port map (
854 | -- I_clk => cEng_clk_core,
855 | -- I_cs => MEM_CS_FRAM_1,
856 | -- I_we => MEM_WE,
857 | -- I_addr => MEM_2KB_ADDR,
858 | -- I_data => MEM_O_data,
859 | -- I_size => MEM_REQ_SIZE,
860 | -- O_data => MEM_DATA_OUT_FRAM_1,
861 | --
862 | -- I_p2_clk => cEng_clk_5xpixel,
863 | -- I_p2_cs => video_enable,
864 | -- I_p2_addr => SYS_FRAM1_ADDR,
865 | -- O_p2_data => SYS_FRAM1_OUTDATA
866 | -- );
867 | --
868 | -- fram_2: ebram2port Port map (
869 | -- I_clk => cEng_clk_core,
870 | -- I_cs => MEM_CS_FRAM_2,
871 | -- I_we => MEM_WE,
872 | -- I_addr => MEM_2KB_ADDR,
873 | -- I_data => MEM_O_data,
874 | -- I_size => MEM_REQ_SIZE,
875 | -- O_data => MEM_DATA_OUT_FRAM_2,
876 | --
877 | -- I_p2_clk => cEng_clk_5xpixel,
878 | -- I_p2_cs => video_enable,
879 | -- I_p2_addr => SYS_FRAM2_ADDR,
880 | -- O_p2_data => SYS_FRAM2_OUTDATA
881 | -- );
882 |
883 | -- at the moment I'm using an external font rom and the above frams
884 | -- are not connected This will change in the future.
885 | fram_test: font_rom port map(
886 | clk => cEng_clk_fmem,
887 | addr => FRAM_ADDR_TEST,
888 | data => FRAM_DATA_TEST
889 | );
890 |
891 | ---------------- TEXT MODE RAM
892 |
893 | tram_1: ebram2port Port map (
894 | I_clk => cEng_clk_core,
895 | I_cs => MEM_CS_TRAM_1,
896 | I_we => MEM_WE,
897 | I_addr => MEM_2KB_ADDR,
898 | I_data => MEM_O_data,
899 | I_size => MEM_REQ_SIZE,
900 | O_data => MEM_DATA_OUT_TRAM_1,
901 |
902 | I_p2_clk => cEng_clk_fmem,
903 | I_p2_cs => video_enable,
904 | I_p2_addr => SYS_TRAM_2K_ADDR,
905 | O_p2_data => SYS_TRAM1_OUTDATA
906 | );
907 |
908 | tram_2: ebram2port Port map (
909 | I_clk => cEng_clk_core,
910 | I_cs => MEM_CS_TRAM_2,
911 | I_we => MEM_WE,
912 | I_addr => MEM_2KB_ADDR,
913 | I_data => MEM_O_data,
914 | I_size => MEM_REQ_SIZE,
915 | O_data => MEM_DATA_OUT_TRAM_2,
916 |
917 | I_p2_clk => cEng_clk_fmem,
918 | I_p2_cs => video_enable,
919 | I_p2_addr => SYS_TRAM_2K_ADDR,
920 | O_p2_data => SYS_TRAM2_OUTDATA
921 | );
922 |
923 | SYS_TRAM_2K_ADDR <= TRAM_ADDR AND X"07FF";
924 |
925 | TRAM_DATA <= SYS_TRAM1_OUTDATA when (TRAM_ADDR(15 downto 11) = X"0"& '0') else
926 | SYS_TRAM2_OUTDATA when (TRAM_ADDR(15 downto 11) = X"0"& '1');
927 |
928 | ---------------- VIDEO SYSTEM BELOW
929 |
930 |
931 | vram_1: ebram2port Port map (
932 | I_clk => cEng_clk_core,
933 | I_cs => MEM_CS_VRAM_1,
934 | I_we => MEM_WE,
935 | I_addr => MEM_2KB_ADDR,
936 | I_data => MEM_O_data,
937 | I_size => MEM_REQ_SIZE,
938 | O_data => MEM_DATA_OUT_VRAM_1,
939 |
940 | I_p2_clk => cEng_clk_5xpixel,
941 | I_p2_cs => video_enable,
942 | I_p2_addr => vram_addr,
943 | O_p2_data => vram_output_2
944 | );
945 |
946 | -- This generates clocks, controls and offsets required for a fixed resolution
947 | Inst_vga_gen: vga_gen PORT MAP(
948 | pixel_clock => cEng_clk_pixel,
949 |
950 | pixel_h => pixel_h,
951 | pixel_v => pixel_v,
952 |
953 |
954 | pixel_h_pref => pixel_h_pref ,
955 | pixel_v_pref => pixel_v_pref ,
956 | blank_pref => blank_pref,
957 |
958 | blank => blank,
959 | hsync => hsync,
960 | vsync => vsync
961 | );
962 |
963 | FRAM_ADDR_TEST <= FRAM_ADDR(11 downto 0);
964 | FRAM_DATA <= X"00" & FRAM_DATA_TEST;
965 |
966 | text_generator_engine: text_gen PORT MAP (
967 | I_clk_pixel => cEng_clk_pixel,
968 | I_clk_pixel10x => cEng_clk_fmem,
969 |
970 | I_blank => blank_pref,
971 | I_x => pixel_h_pref ,
972 | I_y => pixel_v_pref ,
973 |
974 | O_FRAM_ADDR => FRAM_ADDR,
975 | I_FRAM_DATA => FRAM_DATA,
976 |
977 | O_TRAM_ADDR => TRAM_ADDR,
978 | I_TRAM_DATA => TRAM_DATA,
979 |
980 | O_R => TXT_R,
981 | O_G => TXT_G,
982 | O_B => TXT_B
983 | );
984 |
985 |
986 | -- generate the vram scan address, forcing reads at 2 byte boundaries
987 | vram_addr <= X"0" & "000" & pixel_v(8 downto 5) & pixel_h(8 downto 5) & '0';
988 |
989 | -- Only show 512x512 of the display with our expanded virtual pixels
990 | vram_data <= vram_output_2 when ((pixel_h(11 downto 9) = "000") and (pixel_v(11 downto 9) = "000"))
991 | else X"0000" ;
992 |
993 |
994 |
995 | red_ram_p <= X"FF" when unsigned(pixel_h) < 0 else TXT_R;
996 | green_ram_p <= X"FF" when( unsigned(pixel_h) < 0 and unsigned(pixel_h) > 8) else TXT_G;
997 | blue_ram_p <= X"FF" when (unsigned(pixel_h) < 0 and unsigned(pixel_h) > 16) else TXT_B;
998 |
999 | -- red_ram_p(7) <= vram_data(15);
1000 | -- red_ram_p(6) <= vram_data(14);
1001 | -- red_ram_p(5) <= vram_data(13);
1002 | -- red_ram_p(4) <= vram_data(13);
1003 | -- red_ram_p(3) <= vram_data(12);
1004 | -- red_ram_p(2) <= vram_data(12);
1005 | -- red_ram_p(1) <= vram_data(11);
1006 | -- red_ram_p(0) <= vram_data(11);
1007 | --
1008 | -- green_ram_p(7) <= vram_data(10);
1009 | -- green_ram_p(6) <= vram_data(9);
1010 | -- green_ram_p(5) <= vram_data(8);
1011 | -- green_ram_p(4) <= vram_data(7);
1012 | -- green_ram_p(3) <= vram_data(6);
1013 | -- green_ram_p(2) <= vram_data(6);
1014 | -- green_ram_p(1) <= vram_data(5);
1015 | -- green_ram_p(0) <= vram_data(5);
1016 | --
1017 | -- blue_ram_p(7) <= vram_data(4);
1018 | -- blue_ram_p(6) <= vram_data(3);
1019 | -- blue_ram_p(5) <= vram_data(2);
1020 | -- blue_ram_p(4) <= vram_data(2);
1021 | -- blue_ram_p(3) <= vram_data(1);
1022 | -- blue_ram_p(2) <= vram_data(1);
1023 | -- blue_ram_p(1) <= vram_data(0);
1024 | -- blue_ram_p(0) <= vram_data(0);
1025 |
1026 | -- this generates the dvi tmds signalling, depening on the inputs for pixels
1027 | -- and sync/blank controls. Input signal neds to be well formed.
1028 | -- clk and clk_n should be 5x pixel, with clkn at 180 degrees phase
1029 | dvid_1: dvid PORT MAP(
1030 | clk => cEng_clk_5xpixel,
1031 | clk_n => cEng_clk_5xpixel_inv,
1032 | clk_pixel => cEng_clk_pixel,
1033 |
1034 | red_p => red_ram_p,
1035 | green_p => green_ram_p,
1036 | blue_p => blue_ram_p,
1037 |
1038 | blank => blank,
1039 | hsync => hsync,
1040 | vsync => vsync,
1041 |
1042 | -- outputs to TMDS drivers
1043 | red_s => red_s,
1044 | green_s => green_s,
1045 | blue_s => blue_s,
1046 | clock_s => clock_s
1047 | );
1048 |
1049 |
1050 | OBUFDS_blue : OBUFDS port map ( O => hdmi_out_p(0), OB => hdmi_out_n(0), I => blue_s );
1051 | OBUFDS_green : OBUFDS port map ( O => hdmi_out_p(1), OB => hdmi_out_n(1), I => green_s );
1052 | OBUFDS_red : OBUFDS port map ( O => hdmi_out_p(2), OB => hdmi_out_n(2), I => red_s );
1053 | OBUFDS_clock : OBUFDS port map ( O => hdmi_out_p(3), OB => hdmi_out_n(3), I => clock_s );
1054 |
1055 | end Behavioral;
1056 |
1057 |
--------------------------------------------------------------------------------
/vhdl/xilinx/uart_rx6.vhd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Domipheus/TPU/458a9877a6598cdd750ad1a5b8826d2e022837d3/vhdl/xilinx/uart_rx6.vhd
--------------------------------------------------------------------------------
/vhdl/xilinx/uart_tx6.vhd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Domipheus/TPU/458a9877a6598cdd750ad1a5b8826d2e022837d3/vhdl/xilinx/uart_tx6.vhd
--------------------------------------------------------------------------------