├── 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 --------------------------------------------------------------------------------