From 34f4a15cfdf0faeedf90768f7ea83c516296eccb Mon Sep 17 00:00:00 2001 From: Jamie Blanks Date: Sat, 19 Mar 2022 15:13:37 -0400 Subject: [PATCH] Initial Commit --- .gitignore | 40 + AdventureVision.qpf | 2 + AdventureVision.qsf | 70 + AdventureVision.sdc | 4 + AdventureVision.srf | 29 + AdventureVision.sv | 462 +++ AdventureVision_Q13.qpf | 2 + AdventureVision_Q13.qsf | 46 + AdventureVision_Q13.srf | 28 + COPYING | 340 ++ LICENSE | 11 + Readme.md | 15 + clean.bat | 36 + files.qip | 103 + releases/AdventureVision_20220319.rbf | Bin 0 -> 2642584 bytes rtl/assets/adventurevision_bios.vhd | 1054 ++++++ rtl/assets/rom_t41x.vhd | 541 ++++ rtl/av_comp_pack-p.vhd | 100 + rtl/av_ctrl.vhd | 201 ++ rtl/av_disp.vhd | 203 ++ rtl/av_machine.vhd | 225 ++ rtl/av_machine_comp_pack-p.vhd | 64 + rtl/av_main.vhd | 345 ++ rtl/pll.qip | 337 ++ rtl/pll.v | 255 ++ rtl/pll/pll_0002.qip | 4 + rtl/pll/pll_0002.v | 90 + rtl/pll/pll_0002_q13.qip | 4 + rtl/t400/CHANGELOG | 19 + rtl/t400/COMPILE_LIST | 92 + rtl/t400/COPYING | 340 ++ rtl/t400/KNOWN_BUGS | 19 + rtl/t400/README | 325 ++ rtl/t400/bench/vhdl/tb_pack-p.vhd | 58 + rtl/t400/rtl/tech/cyclone/t400_por-c.vhd | 23 + rtl/t400/rtl/tech/cyclone/t400_por.vhd | 125 + rtl/t400/rtl/tech/generic/generic_ram-c.vhd | 18 + rtl/t400/rtl/tech/generic/generic_ram.vhd | 94 + .../rtl/tech/generic/generic_ram_ena-c.vhd | 18 + rtl/t400/rtl/tech/generic/generic_ram_ena.vhd | 97 + rtl/t400/rtl/tech/spartan/t400_por-c.vhd | 20 + rtl/t400/rtl/tech/spartan/t400_por.vhd | 107 + rtl/t400/rtl/tech/t400_tech_comp_pack-p.vhd | 70 + .../vhdl/system/t400_system_comp_pack-p.vhd | 278 ++ rtl/t400/rtl/vhdl/system/t410-c.vhd | 69 + rtl/t400/rtl/vhdl/system/t410.vhd | 201 ++ rtl/t400/rtl/vhdl/system/t410_notri-c.vhd | 51 + rtl/t400/rtl/vhdl/system/t410_notri.vhd | 243 ++ rtl/t400/rtl/vhdl/system/t410_rom-e.vhd | 67 + .../rtl/vhdl/system/t410_rom-struct-a.vhd | 78 + rtl/t400/rtl/vhdl/system/t411-c.vhd | 66 + rtl/t400/rtl/vhdl/system/t411.vhd | 196 ++ rtl/t400/rtl/vhdl/system/t420-c.vhd | 69 + rtl/t400/rtl/vhdl/system/t420.vhd | 219 ++ rtl/t400/rtl/vhdl/system/t420_notri-c.vhd | 51 + rtl/t400/rtl/vhdl/system/t420_notri.vhd | 245 ++ rtl/t400/rtl/vhdl/system/t420_rom-e.vhd | 70 + .../rtl/vhdl/system/t420_rom-struct-a.vhd | 78 + rtl/t400/rtl/vhdl/system/t421-c.vhd | 69 + rtl/t400/rtl/vhdl/system/t421.vhd | 205 ++ rtl/t400/rtl/vhdl/t400_alu-c.vhd | 29 + rtl/t400/rtl/vhdl/t400_alu.vhd | 266 ++ rtl/t400/rtl/vhdl/t400_clkgen-c.vhd | 29 + rtl/t400/rtl/vhdl/t400_clkgen.vhd | 152 + rtl/t400/rtl/vhdl/t400_comp_pack-p.vhd | 390 +++ rtl/t400/rtl/vhdl/t400_core-c.vhd | 95 + rtl/t400/rtl/vhdl/t400_core.vhd | 570 ++++ rtl/t400/rtl/vhdl/t400_core_comp_pack-p.vhd | 82 + rtl/t400/rtl/vhdl/t400_decoder-c.vhd | 34 + rtl/t400/rtl/vhdl/t400_decoder.vhd | 884 +++++ rtl/t400/rtl/vhdl/t400_dmem_ctrl-c.vhd | 28 + rtl/t400/rtl/vhdl/t400_dmem_ctrl.vhd | 254 ++ rtl/t400/rtl/vhdl/t400_io_d-c.vhd | 28 + rtl/t400/rtl/vhdl/t400_io_d.vhd | 167 + rtl/t400/rtl/vhdl/t400_io_g-c.vhd | 28 + rtl/t400/rtl/vhdl/t400_io_g.vhd | 185 ++ rtl/t400/rtl/vhdl/t400_io_in-c.vhd | 31 + rtl/t400/rtl/vhdl/t400_io_in.vhd | 187 ++ rtl/t400/rtl/vhdl/t400_io_l-c.vhd | 28 + rtl/t400/rtl/vhdl/t400_io_l.vhd | 234 ++ rtl/t400/rtl/vhdl/t400_io_pack-p.vhd | 92 + rtl/t400/rtl/vhdl/t400_opc_table-c.vhd | 29 + rtl/t400/rtl/vhdl/t400_opc_table.vhd | 302 ++ rtl/t400/rtl/vhdl/t400_opt_pack-p.vhd | 48 + rtl/t400/rtl/vhdl/t400_pack-p.vhd | 178 + rtl/t400/rtl/vhdl/t400_pmem_ctrl-c.vhd | 28 + rtl/t400/rtl/vhdl/t400_pmem_ctrl.vhd | 199 ++ rtl/t400/rtl/vhdl/t400_reset-c.vhd | 28 + rtl/t400/rtl/vhdl/t400_reset.vhd | 148 + rtl/t400/rtl/vhdl/t400_sio-c.vhd | 28 + rtl/t400/rtl/vhdl/t400_sio.vhd | 305 ++ rtl/t400/rtl/vhdl/t400_skip-c.vhd | 29 + rtl/t400/rtl/vhdl/t400_skip.vhd | 239 ++ rtl/t400/rtl/vhdl/t400_stack-c.vhd | 28 + rtl/t400/rtl/vhdl/t400_stack.vhd | 159 + rtl/t400/rtl/vhdl/t400_timer-c.vhd | 31 + rtl/t400/rtl/vhdl/t400_timer.vhd | 128 + rtl/t48/COPYING | 340 ++ rtl/t48/README | 232 ++ rtl/t48/rtl/vhdl/alu-c.vhd | 19 + rtl/t48/rtl/vhdl/alu.vhd | 449 +++ rtl/t48/rtl/vhdl/alu_pack-p.vhd | 51 + rtl/t48/rtl/vhdl/bus_mux-c.vhd | 19 + rtl/t48/rtl/vhdl/bus_mux.vhd | 113 + rtl/t48/rtl/vhdl/clock_ctrl-c.vhd | 14 + rtl/t48/rtl/vhdl/clock_ctrl.vhd | 440 +++ rtl/t48/rtl/vhdl/cond_branch-c.vhd | 19 + rtl/t48/rtl/vhdl/cond_branch.vhd | 217 ++ rtl/t48/rtl/vhdl/cond_branch_pack-p.vhd | 41 + rtl/t48/rtl/vhdl/db_bus-c.vhd | 19 + rtl/t48/rtl/vhdl/db_bus.vhd | 169 + rtl/t48/rtl/vhdl/decoder-c.vhd | 28 + rtl/t48/rtl/vhdl/decoder.vhd | 2069 ++++++++++++ rtl/t48/rtl/vhdl/decoder_pack-p.vhd | 90 + rtl/t48/rtl/vhdl/dmem_ctrl-c.vhd | 19 + rtl/t48/rtl/vhdl/dmem_ctrl.vhd | 219 ++ rtl/t48/rtl/vhdl/dmem_ctrl_pack-p.vhd | 34 + rtl/t48/rtl/vhdl/int-c.vhd | 17 + rtl/t48/rtl/vhdl/int.vhd | 284 ++ rtl/t48/rtl/vhdl/opc_decoder-c.vhd | 23 + rtl/t48/rtl/vhdl/opc_decoder.vhd | 182 ++ rtl/t48/rtl/vhdl/opc_table-c.vhd | 18 + rtl/t48/rtl/vhdl/opc_table.vhd | 425 +++ rtl/t48/rtl/vhdl/p1-c.vhd | 17 + rtl/t48/rtl/vhdl/p1.vhd | 173 + rtl/t48/rtl/vhdl/p2-c.vhd | 17 + rtl/t48/rtl/vhdl/p2.vhd | 270 ++ rtl/t48/rtl/vhdl/pmem_ctrl-c.vhd | 17 + rtl/t48/rtl/vhdl/pmem_ctrl.vhd | 245 ++ rtl/t48/rtl/vhdl/pmem_ctrl_pack-p.vhd | 33 + rtl/t48/rtl/vhdl/psw-c.vhd | 17 + rtl/t48/rtl/vhdl/psw.vhd | 243 ++ rtl/t48/rtl/vhdl/system/lpm_ram_dq.vhd | 439 +++ rtl/t48/rtl/vhdl/system/lpm_rom.vhd | 437 +++ rtl/t48/rtl/vhdl/system/syn_ram-e.vhd | 73 + rtl/t48/rtl/vhdl/system/syn_ram-lpm-a.vhd | 120 + rtl/t48/rtl/vhdl/system/syn_ram-lpm-c.vhd | 34 + rtl/t48/rtl/vhdl/system/syn_rom-e.vhd | 60 + rtl/t48/rtl/vhdl/system/syn_rom-lpm-a.vhd | 115 + rtl/t48/rtl/vhdl/system/syn_rom-lpm-c.vhd | 34 + .../vhdl/system/t48_system_comp_pack-p.vhd | 175 + rtl/t48/rtl/vhdl/system/t8039-c.vhd | 23 + rtl/t48/rtl/vhdl/system/t8039.vhd | 193 ++ rtl/t48/rtl/vhdl/system/t8039_notri-c.vhd | 28 + rtl/t48/rtl/vhdl/system/t8039_notri.vhd | 211 ++ rtl/t48/rtl/vhdl/system/t8048-c.vhd | 23 + rtl/t48/rtl/vhdl/system/t8048.vhd | 219 ++ rtl/t48/rtl/vhdl/system/t8048_notri-c.vhd | 31 + rtl/t48/rtl/vhdl/system/t8048_notri.vhd | 257 ++ rtl/t48/rtl/vhdl/system/t8050_wb-c.vhd | 35 + rtl/t48/rtl/vhdl/system/t8050_wb.vhd | 305 ++ rtl/t48/rtl/vhdl/system/wb_master-c.vhd | 18 + rtl/t48/rtl/vhdl/system/wb_master.vhd | 274 ++ rtl/t48/rtl/vhdl/t48_comp_pack-p.vhd | 395 +++ rtl/t48/rtl/vhdl/t48_core-c.vhd | 71 + rtl/t48/rtl/vhdl/t48_core.vhd | 669 ++++ rtl/t48/rtl/vhdl/t48_core_comp_pack-p.vhd | 88 + rtl/t48/rtl/vhdl/t48_pack-p.vhd | 82 + rtl/t48/rtl/vhdl/t48_tb_pack-p.vhd | 22 + rtl/t48/rtl/vhdl/timer-c.vhd | 16 + rtl/t48/rtl/vhdl/timer.vhd | 280 ++ rtl/tech/cyclone/av_por.vhd | 115 + rtl/tech/generic/dpram.vhd | 104 + rtl/tech/generic/generic_ram.vhd | 99 + rtl/tech/generic/syn_ram-generic_tech-a.vhd | 65 + rtl/tech/generic/syn_rom-av_bios-a.vhd | 66 + rtl/tech/generic/t410_rom-struct-a.vhd | 24 + rtl/tech/spartan/av_por.vhd | 107 + rtl/tech/tech_comp_pack-p.vhd | 85 + rtl/video/av_frame_buffer.vhd | 298 ++ rtl/video/av_raster.vhd | 443 +++ rtl/video/av_video.vhd | 123 + rtl/video/av_video_comp_pack-p.vhd | 78 + sys/alsa.sv | 157 + sys/arcade_video.v | 324 ++ sys/ascal.vhd | 2871 +++++++++++++++++ sys/audio_out.v | 296 ++ sys/build_id.tcl | 73 + sys/ddr_svc.sv | 108 + sys/f2sdram_safe_terminator.sv | 250 ++ sys/gamma_corr.sv | 124 + sys/hdmi_config.sv | 239 ++ sys/hps_io.sv | 999 ++++++ sys/hq2x.sv | 371 +++ sys/i2c.v | 103 + sys/i2s.v | 54 + sys/iir_filter.v | 213 ++ sys/ltc2308.sv | 162 + sys/math.sv | 109 + sys/mcp23009.sv | 113 + sys/mt32pi.sv | 283 ++ sys/osd.v | 286 ++ sys/pll.13.qip | 17 + sys/pll_audio.13.qip | 17 + sys/pll_audio.qip | 337 ++ sys/pll_audio.v | 252 ++ sys/pll_audio/pll_audio_0002.qip | 4 + sys/pll_audio/pll_audio_0002.v | 87 + sys/pll_cfg.qip | 44 + sys/pll_cfg.v | 86 + sys/pll_cfg/altera_pll_reconfig_core.v | 2184 +++++++++++++ sys/pll_cfg/altera_pll_reconfig_top.v | 428 +++ sys/pll_hdmi.13.qip | 17 + sys/pll_hdmi.qip | 483 +++ sys/pll_hdmi.v | 256 ++ sys/pll_hdmi/pll_hdmi_0002.qip | 2 + sys/pll_hdmi/pll_hdmi_0002.v | 241 ++ sys/pll_hdmi_adj.vhd | 433 +++ sys/pll_q13.qip | 6 + sys/pll_q17.qip | 4 + sys/scandoubler.v | 211 ++ sys/scanlines.v | 68 + sys/sd_card.sv | 463 +++ sys/shadowmask.sv | 136 + sys/sigma_delta_dac.v | 33 + sys/spdif.v | 320 ++ sys/sys.qip | 34 + sys/sys.tcl | 227 ++ sys/sys_analog.tcl | 71 + sys/sys_dual_sdram.tcl | 50 + sys/sys_top.sdc | 71 + sys/sys_top.v | 1738 ++++++++++ sys/sysmem.sv | 570 ++++ sys/vga_out.sv | 68 + sys/video_cleaner.sv | 99 + sys/video_freak.sv | 278 ++ sys/video_freezer.sv | 143 + sys/video_mixer.sv | 219 ++ 228 files changed, 43739 insertions(+) create mode 100644 .gitignore create mode 100644 AdventureVision.qpf create mode 100644 AdventureVision.qsf create mode 100644 AdventureVision.sdc create mode 100644 AdventureVision.srf create mode 100644 AdventureVision.sv create mode 100644 AdventureVision_Q13.qpf create mode 100644 AdventureVision_Q13.qsf create mode 100644 AdventureVision_Q13.srf create mode 100644 COPYING create mode 100644 LICENSE create mode 100644 Readme.md create mode 100644 clean.bat create mode 100644 files.qip create mode 100644 releases/AdventureVision_20220319.rbf create mode 100644 rtl/assets/adventurevision_bios.vhd create mode 100644 rtl/assets/rom_t41x.vhd create mode 100644 rtl/av_comp_pack-p.vhd create mode 100644 rtl/av_ctrl.vhd create mode 100644 rtl/av_disp.vhd create mode 100644 rtl/av_machine.vhd create mode 100644 rtl/av_machine_comp_pack-p.vhd create mode 100644 rtl/av_main.vhd create mode 100644 rtl/pll.qip create mode 100644 rtl/pll.v create mode 100644 rtl/pll/pll_0002.qip create mode 100644 rtl/pll/pll_0002.v create mode 100644 rtl/pll/pll_0002_q13.qip create mode 100644 rtl/t400/CHANGELOG create mode 100644 rtl/t400/COMPILE_LIST create mode 100644 rtl/t400/COPYING create mode 100644 rtl/t400/KNOWN_BUGS create mode 100644 rtl/t400/README create mode 100644 rtl/t400/bench/vhdl/tb_pack-p.vhd create mode 100644 rtl/t400/rtl/tech/cyclone/t400_por-c.vhd create mode 100644 rtl/t400/rtl/tech/cyclone/t400_por.vhd create mode 100644 rtl/t400/rtl/tech/generic/generic_ram-c.vhd create mode 100644 rtl/t400/rtl/tech/generic/generic_ram.vhd create mode 100644 rtl/t400/rtl/tech/generic/generic_ram_ena-c.vhd create mode 100644 rtl/t400/rtl/tech/generic/generic_ram_ena.vhd create mode 100644 rtl/t400/rtl/tech/spartan/t400_por-c.vhd create mode 100644 rtl/t400/rtl/tech/spartan/t400_por.vhd create mode 100644 rtl/t400/rtl/tech/t400_tech_comp_pack-p.vhd create mode 100644 rtl/t400/rtl/vhdl/system/t400_system_comp_pack-p.vhd create mode 100644 rtl/t400/rtl/vhdl/system/t410-c.vhd create mode 100644 rtl/t400/rtl/vhdl/system/t410.vhd create mode 100644 rtl/t400/rtl/vhdl/system/t410_notri-c.vhd create mode 100644 rtl/t400/rtl/vhdl/system/t410_notri.vhd create mode 100644 rtl/t400/rtl/vhdl/system/t410_rom-e.vhd create mode 100644 rtl/t400/rtl/vhdl/system/t410_rom-struct-a.vhd create mode 100644 rtl/t400/rtl/vhdl/system/t411-c.vhd create mode 100644 rtl/t400/rtl/vhdl/system/t411.vhd create mode 100644 rtl/t400/rtl/vhdl/system/t420-c.vhd create mode 100644 rtl/t400/rtl/vhdl/system/t420.vhd create mode 100644 rtl/t400/rtl/vhdl/system/t420_notri-c.vhd create mode 100644 rtl/t400/rtl/vhdl/system/t420_notri.vhd create mode 100644 rtl/t400/rtl/vhdl/system/t420_rom-e.vhd create mode 100644 rtl/t400/rtl/vhdl/system/t420_rom-struct-a.vhd create mode 100644 rtl/t400/rtl/vhdl/system/t421-c.vhd create mode 100644 rtl/t400/rtl/vhdl/system/t421.vhd create mode 100644 rtl/t400/rtl/vhdl/t400_alu-c.vhd create mode 100644 rtl/t400/rtl/vhdl/t400_alu.vhd create mode 100644 rtl/t400/rtl/vhdl/t400_clkgen-c.vhd create mode 100644 rtl/t400/rtl/vhdl/t400_clkgen.vhd create mode 100644 rtl/t400/rtl/vhdl/t400_comp_pack-p.vhd create mode 100644 rtl/t400/rtl/vhdl/t400_core-c.vhd create mode 100644 rtl/t400/rtl/vhdl/t400_core.vhd create mode 100644 rtl/t400/rtl/vhdl/t400_core_comp_pack-p.vhd create mode 100644 rtl/t400/rtl/vhdl/t400_decoder-c.vhd create mode 100644 rtl/t400/rtl/vhdl/t400_decoder.vhd create mode 100644 rtl/t400/rtl/vhdl/t400_dmem_ctrl-c.vhd create mode 100644 rtl/t400/rtl/vhdl/t400_dmem_ctrl.vhd create mode 100644 rtl/t400/rtl/vhdl/t400_io_d-c.vhd create mode 100644 rtl/t400/rtl/vhdl/t400_io_d.vhd create mode 100644 rtl/t400/rtl/vhdl/t400_io_g-c.vhd create mode 100644 rtl/t400/rtl/vhdl/t400_io_g.vhd create mode 100644 rtl/t400/rtl/vhdl/t400_io_in-c.vhd create mode 100644 rtl/t400/rtl/vhdl/t400_io_in.vhd create mode 100644 rtl/t400/rtl/vhdl/t400_io_l-c.vhd create mode 100644 rtl/t400/rtl/vhdl/t400_io_l.vhd create mode 100644 rtl/t400/rtl/vhdl/t400_io_pack-p.vhd create mode 100644 rtl/t400/rtl/vhdl/t400_opc_table-c.vhd create mode 100644 rtl/t400/rtl/vhdl/t400_opc_table.vhd create mode 100644 rtl/t400/rtl/vhdl/t400_opt_pack-p.vhd create mode 100644 rtl/t400/rtl/vhdl/t400_pack-p.vhd create mode 100644 rtl/t400/rtl/vhdl/t400_pmem_ctrl-c.vhd create mode 100644 rtl/t400/rtl/vhdl/t400_pmem_ctrl.vhd create mode 100644 rtl/t400/rtl/vhdl/t400_reset-c.vhd create mode 100644 rtl/t400/rtl/vhdl/t400_reset.vhd create mode 100644 rtl/t400/rtl/vhdl/t400_sio-c.vhd create mode 100644 rtl/t400/rtl/vhdl/t400_sio.vhd create mode 100644 rtl/t400/rtl/vhdl/t400_skip-c.vhd create mode 100644 rtl/t400/rtl/vhdl/t400_skip.vhd create mode 100644 rtl/t400/rtl/vhdl/t400_stack-c.vhd create mode 100644 rtl/t400/rtl/vhdl/t400_stack.vhd create mode 100644 rtl/t400/rtl/vhdl/t400_timer-c.vhd create mode 100644 rtl/t400/rtl/vhdl/t400_timer.vhd create mode 100644 rtl/t48/COPYING create mode 100644 rtl/t48/README create mode 100644 rtl/t48/rtl/vhdl/alu-c.vhd create mode 100644 rtl/t48/rtl/vhdl/alu.vhd create mode 100644 rtl/t48/rtl/vhdl/alu_pack-p.vhd create mode 100644 rtl/t48/rtl/vhdl/bus_mux-c.vhd create mode 100644 rtl/t48/rtl/vhdl/bus_mux.vhd create mode 100644 rtl/t48/rtl/vhdl/clock_ctrl-c.vhd create mode 100644 rtl/t48/rtl/vhdl/clock_ctrl.vhd create mode 100644 rtl/t48/rtl/vhdl/cond_branch-c.vhd create mode 100644 rtl/t48/rtl/vhdl/cond_branch.vhd create mode 100644 rtl/t48/rtl/vhdl/cond_branch_pack-p.vhd create mode 100644 rtl/t48/rtl/vhdl/db_bus-c.vhd create mode 100644 rtl/t48/rtl/vhdl/db_bus.vhd create mode 100644 rtl/t48/rtl/vhdl/decoder-c.vhd create mode 100644 rtl/t48/rtl/vhdl/decoder.vhd create mode 100644 rtl/t48/rtl/vhdl/decoder_pack-p.vhd create mode 100644 rtl/t48/rtl/vhdl/dmem_ctrl-c.vhd create mode 100644 rtl/t48/rtl/vhdl/dmem_ctrl.vhd create mode 100644 rtl/t48/rtl/vhdl/dmem_ctrl_pack-p.vhd create mode 100644 rtl/t48/rtl/vhdl/int-c.vhd create mode 100644 rtl/t48/rtl/vhdl/int.vhd create mode 100644 rtl/t48/rtl/vhdl/opc_decoder-c.vhd create mode 100644 rtl/t48/rtl/vhdl/opc_decoder.vhd create mode 100644 rtl/t48/rtl/vhdl/opc_table-c.vhd create mode 100644 rtl/t48/rtl/vhdl/opc_table.vhd create mode 100644 rtl/t48/rtl/vhdl/p1-c.vhd create mode 100644 rtl/t48/rtl/vhdl/p1.vhd create mode 100644 rtl/t48/rtl/vhdl/p2-c.vhd create mode 100644 rtl/t48/rtl/vhdl/p2.vhd create mode 100644 rtl/t48/rtl/vhdl/pmem_ctrl-c.vhd create mode 100644 rtl/t48/rtl/vhdl/pmem_ctrl.vhd create mode 100644 rtl/t48/rtl/vhdl/pmem_ctrl_pack-p.vhd create mode 100644 rtl/t48/rtl/vhdl/psw-c.vhd create mode 100644 rtl/t48/rtl/vhdl/psw.vhd create mode 100644 rtl/t48/rtl/vhdl/system/lpm_ram_dq.vhd create mode 100644 rtl/t48/rtl/vhdl/system/lpm_rom.vhd create mode 100644 rtl/t48/rtl/vhdl/system/syn_ram-e.vhd create mode 100644 rtl/t48/rtl/vhdl/system/syn_ram-lpm-a.vhd create mode 100644 rtl/t48/rtl/vhdl/system/syn_ram-lpm-c.vhd create mode 100644 rtl/t48/rtl/vhdl/system/syn_rom-e.vhd create mode 100644 rtl/t48/rtl/vhdl/system/syn_rom-lpm-a.vhd create mode 100644 rtl/t48/rtl/vhdl/system/syn_rom-lpm-c.vhd create mode 100644 rtl/t48/rtl/vhdl/system/t48_system_comp_pack-p.vhd create mode 100644 rtl/t48/rtl/vhdl/system/t8039-c.vhd create mode 100644 rtl/t48/rtl/vhdl/system/t8039.vhd create mode 100644 rtl/t48/rtl/vhdl/system/t8039_notri-c.vhd create mode 100644 rtl/t48/rtl/vhdl/system/t8039_notri.vhd create mode 100644 rtl/t48/rtl/vhdl/system/t8048-c.vhd create mode 100644 rtl/t48/rtl/vhdl/system/t8048.vhd create mode 100644 rtl/t48/rtl/vhdl/system/t8048_notri-c.vhd create mode 100644 rtl/t48/rtl/vhdl/system/t8048_notri.vhd create mode 100644 rtl/t48/rtl/vhdl/system/t8050_wb-c.vhd create mode 100644 rtl/t48/rtl/vhdl/system/t8050_wb.vhd create mode 100644 rtl/t48/rtl/vhdl/system/wb_master-c.vhd create mode 100644 rtl/t48/rtl/vhdl/system/wb_master.vhd create mode 100644 rtl/t48/rtl/vhdl/t48_comp_pack-p.vhd create mode 100644 rtl/t48/rtl/vhdl/t48_core-c.vhd create mode 100644 rtl/t48/rtl/vhdl/t48_core.vhd create mode 100644 rtl/t48/rtl/vhdl/t48_core_comp_pack-p.vhd create mode 100644 rtl/t48/rtl/vhdl/t48_pack-p.vhd create mode 100644 rtl/t48/rtl/vhdl/t48_tb_pack-p.vhd create mode 100644 rtl/t48/rtl/vhdl/timer-c.vhd create mode 100644 rtl/t48/rtl/vhdl/timer.vhd create mode 100644 rtl/tech/cyclone/av_por.vhd create mode 100644 rtl/tech/generic/dpram.vhd create mode 100644 rtl/tech/generic/generic_ram.vhd create mode 100644 rtl/tech/generic/syn_ram-generic_tech-a.vhd create mode 100644 rtl/tech/generic/syn_rom-av_bios-a.vhd create mode 100644 rtl/tech/generic/t410_rom-struct-a.vhd create mode 100644 rtl/tech/spartan/av_por.vhd create mode 100644 rtl/tech/tech_comp_pack-p.vhd create mode 100644 rtl/video/av_frame_buffer.vhd create mode 100644 rtl/video/av_raster.vhd create mode 100644 rtl/video/av_video.vhd create mode 100644 rtl/video/av_video_comp_pack-p.vhd create mode 100644 sys/alsa.sv create mode 100644 sys/arcade_video.v create mode 100644 sys/ascal.vhd create mode 100644 sys/audio_out.v create mode 100644 sys/build_id.tcl create mode 100644 sys/ddr_svc.sv create mode 100644 sys/f2sdram_safe_terminator.sv create mode 100644 sys/gamma_corr.sv create mode 100644 sys/hdmi_config.sv create mode 100644 sys/hps_io.sv create mode 100644 sys/hq2x.sv create mode 100644 sys/i2c.v create mode 100644 sys/i2s.v create mode 100644 sys/iir_filter.v create mode 100644 sys/ltc2308.sv create mode 100644 sys/math.sv create mode 100644 sys/mcp23009.sv create mode 100644 sys/mt32pi.sv create mode 100644 sys/osd.v create mode 100644 sys/pll.13.qip create mode 100644 sys/pll_audio.13.qip create mode 100644 sys/pll_audio.qip create mode 100644 sys/pll_audio.v create mode 100644 sys/pll_audio/pll_audio_0002.qip create mode 100644 sys/pll_audio/pll_audio_0002.v create mode 100644 sys/pll_cfg.qip create mode 100644 sys/pll_cfg.v create mode 100644 sys/pll_cfg/altera_pll_reconfig_core.v create mode 100644 sys/pll_cfg/altera_pll_reconfig_top.v create mode 100644 sys/pll_hdmi.13.qip create mode 100644 sys/pll_hdmi.qip create mode 100644 sys/pll_hdmi.v create mode 100644 sys/pll_hdmi/pll_hdmi_0002.qip create mode 100644 sys/pll_hdmi/pll_hdmi_0002.v create mode 100644 sys/pll_hdmi_adj.vhd create mode 100644 sys/pll_q13.qip create mode 100644 sys/pll_q17.qip create mode 100644 sys/scandoubler.v create mode 100644 sys/scanlines.v create mode 100644 sys/sd_card.sv create mode 100644 sys/shadowmask.sv create mode 100644 sys/sigma_delta_dac.v create mode 100644 sys/spdif.v create mode 100644 sys/sys.qip create mode 100644 sys/sys.tcl create mode 100644 sys/sys_analog.tcl create mode 100644 sys/sys_dual_sdram.tcl create mode 100644 sys/sys_top.sdc create mode 100644 sys/sys_top.v create mode 100644 sys/sysmem.sv create mode 100644 sys/vga_out.sv create mode 100644 sys/video_cleaner.sv create mode 100644 sys/video_freak.sv create mode 100644 sys/video_freezer.sv create mode 100644 sys/video_mixer.sv diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d4ae7f2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,40 @@ +db +greybox_tmp +incremental_db +output_files +simulation +hc_output +scaler +hps_isw_handoff +vip +*_sim +.qsys_edit +PLLJ_PLLSPE_INFO.txt +*.bak +*.orig +*.rej +*.qdf +*.rpt +*.smsg +*.summary +*.done +*.jdi +*.pin +*.sof +*.qws +*.ppf +*.ddb +build_id.v +c5_pin_model_dump.txt +*.sopcinfo +*.csv +*.f +*.cmp +*.sip +*.spd +*.bsf +*~ +*.xml +*_netlist +*.cdf +**/.DS_Store \ No newline at end of file diff --git a/AdventureVision.qpf b/AdventureVision.qpf new file mode 100644 index 0000000..b0670a6 --- /dev/null +++ b/AdventureVision.qpf @@ -0,0 +1,2 @@ +QUARTUS_VERSION = "17.0" +PROJECT_REVISION = "AdventureVision" diff --git a/AdventureVision.qsf b/AdventureVision.qsf new file mode 100644 index 0000000..4987401 --- /dev/null +++ b/AdventureVision.qsf @@ -0,0 +1,70 @@ +# -------------------------------------------------------------------------- +# +# MiSTer project +# +# WARNING WARNING WARNING: +# Do not add files to project in Quartus IDE! It will mess this file! +# Add the files manually to files.qip file. +# +# -------------------------------------------------------------------------- + +set_global_assignment -name TOP_LEVEL_ENTITY sys_top +set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top +set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top +set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top + +set_global_assignment -name LAST_QUARTUS_VERSION "17.0.2 Standard Edition" + +set_global_assignment -name GENERATE_RBF_FILE ON +set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files +set_global_assignment -name NUM_PARALLEL_PROCESSORS ALL +set_global_assignment -name SAVE_DISK_SPACE OFF +set_global_assignment -name SMART_RECOMPILE ON +set_global_assignment -name MIN_CORE_JUNCTION_TEMP "-40" +set_global_assignment -name MAX_CORE_JUNCTION_TEMP 100 +set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "23 MM HEAT SINK WITH 200 LFPM AIRFLOW" +set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)" +set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS OFF +set_global_assignment -name OPTIMIZE_POWER_DURING_FITTING OFF +set_global_assignment -name FINAL_PLACEMENT_OPTIMIZATION ALWAYS +set_global_assignment -name FITTER_EFFORT "STANDARD FIT" +set_global_assignment -name OPTIMIZATION_MODE "HIGH PERFORMANCE EFFORT" +set_global_assignment -name ALLOW_POWER_UP_DONT_CARE ON +set_global_assignment -name QII_AUTO_PACKED_REGISTERS NORMAL +set_global_assignment -name ROUTER_LCELL_INSERTION_AND_LOGIC_DUPLICATION ON +set_global_assignment -name PHYSICAL_SYNTHESIS_COMBO_LOGIC ON +set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_DUPLICATION ON +set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_RETIMING ON +set_global_assignment -name OPTIMIZATION_TECHNIQUE SPEED +set_global_assignment -name MUX_RESTRUCTURE ON +set_global_assignment -name REMOVE_REDUNDANT_LOGIC_CELLS ON +set_global_assignment -name AUTO_DELAY_CHAINS_FOR_HIGH_FANOUT_INPUT_PINS ON +set_global_assignment -name PHYSICAL_SYNTHESIS_COMBO_LOGIC_FOR_AREA ON +set_global_assignment -name ADV_NETLIST_OPT_SYNTH_WYSIWYG_REMAP ON +set_global_assignment -name SYNTH_GATED_CLOCK_CONVERSION ON +set_global_assignment -name PRE_MAPPING_RESYNTHESIS ON +set_global_assignment -name ROUTER_CLOCKING_TOPOLOGY_ANALYSIS ON +set_global_assignment -name ECO_OPTIMIZE_TIMING ON +set_global_assignment -name PERIPHERY_TO_CORE_PLACEMENT_AND_ROUTING_OPTIMIZATION ON +set_global_assignment -name PHYSICAL_SYNTHESIS_ASYNCHRONOUS_SIGNAL_PIPELINING ON +set_global_assignment -name ALM_REGISTER_PACKING_EFFORT MEDIUM +set_global_assignment -name SEED 1 + +#set_global_assignment -name VERILOG_MACRO "MISTER_FB=1" + +#enable it only if 8bit indexed mode is used in core +#set_global_assignment -name VERILOG_MACRO "MISTER_FB_PALETTE=1" + +#do not enable DEBUG_NOHDMI in release! +#set_global_assignment -name VERILOG_MACRO "MISTER_DEBUG_NOHDMI=1" + +# disable bilinear filtering when downscaling +#set_global_assignment -name VERILOG_MACRO "MISTER_DOWNSCALE_NN=1" + +# disable adaptive scanline filtering +#set_global_assignment -name VERILOG_MACRO "MISTER_DISABLE_ADAPTIVE=1" + +source sys/sys.tcl +source sys/sys_analog.tcl +source files.qip +set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file diff --git a/AdventureVision.sdc b/AdventureVision.sdc new file mode 100644 index 0000000..2344cca --- /dev/null +++ b/AdventureVision.sdc @@ -0,0 +1,4 @@ +derive_pll_clocks +derive_clock_uncertainty + +# core specific constraints diff --git a/AdventureVision.srf b/AdventureVision.srf new file mode 100644 index 0000000..505e355 --- /dev/null +++ b/AdventureVision.srf @@ -0,0 +1,29 @@ +{ "" "" "" "Inferred RAM node \"emu:emu\|mister_io:mister_io\|ps2_kbd_fifo_rtl_0\" from synchronous design logic. Pass-through logic has been added to match the read-during-write behavior of the original design." { } { } 0 276020 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Inferred RAM node \"emu:emu\|mister_io:mister_io\|ps2_mouse_fifo_rtl_0\" from synchronous design logic. Pass-through logic has been added to match the read-during-write behavior of the original design." { } { } 0 276020 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Synthesized away node \"emu:emu\|pll:pll\|pll_0002:pll_inst\|altera_pll:altera_pll_i\|outclk_wire\[2\]\"" { } { } 0 14320 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "RST port on the PLL is not properly connected on instance emu:emu\|pll:pll\|pll_0002:pll_inst\|altera_pll:altera_pll_i\|general\[1\].gpll. The reset port on the PLL should be connected. If the PLL loses lock for any reason, you might need to manually reset the PLL in order to re-establish lock to the reference clock." { } { } 0 0 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "RST port on the PLL is not properly connected on instance emu:emu\|pll:pll\|pll_0002:pll_inst\|altera_pll:altera_pll_i\|general\[0\].gpll. The reset port on the PLL should be connected. If the PLL loses lock for any reason, you might need to manually reset the PLL in order to re-establish lock to the reference clock." { } { } 0 0 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Ignored locations or region assignments to the following nodes" { } { } 0 15705 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "RST port on the PLL is not properly connected on instance emu:emu\|pll:pll\|pll_0002:pll_inst\|altera_pll:altera_pll_i\|general\[2\].gpll. The reset port on the PLL should be connected. If the PLL loses lock for any reason, you might need to manually reset the PLL in order to re-establish lock to the reference clock." { } { } 0 0 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Verilog HDL or VHDL warning at de10_top.v(129): object \"io_win\" assigned a value but never read" { } { } 0 10036 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Verilog HDL or VHDL warning at de10_top.v(134): object \"io_sdd\" assigned a value but never read" { } { } 0 10036 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Verilog HDL or VHDL warning at de10_top.v(97): object \"io_win\" assigned a value but never read" { } { } 0 10036 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Verilog HDL or VHDL warning at de10_top.v(102): object \"io_sdd\" assigned a value but never read" { } { } 0 10036 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Some pins have incomplete I/O assignments. Refer to the I/O Assignment Warnings report for details" { } { } 0 15714 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "LOCKED port on the PLL is not properly connected on instance \"pll_hdmi:pll_hdmi\|pll_hdmi_0002:pll_hdmi_inst\|altera_pll:altera_pll_i\|general\[0\].gpll\". The LOCKED port on the PLL should be connected when the FBOUTCLK port is connected. Although it is unnecessary to connect the LOCKED signal, any logic driven off of an output clock of the PLL will not know when the PLL is locked and ready." { } { } 0 21300 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Found combinational loop of 47 nodes" { } { } 0 332125 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "LOCKED port on the PLL is not properly connected on instance \"emu:emu\|pll:pll\|pll_0002:pll_inst\|altera_pll:altera_pll_i\|general\[0\].gpll\". The LOCKED port on the PLL should be connected when the FBOUTCLK port is connected. Although it is unnecessary to connect the LOCKED signal, any logic driven off of an output clock of the PLL will not know when the PLL is locked and ready." { } { } 0 21300 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Verilog HDL or VHDL warning at sys_top.v(209): object \"vip_newcfg\" assigned a value but never read" { } { } 0 10036 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Verilog HDL or VHDL warning at sys_top.v(594): object \"VSET\" assigned a value but never read" { } { } 0 10036 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Ignored filter at sys_top.sdc(17): vip\|output_inst\|vid_clk could not be matched with a net" { } { } 0 332174 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Ignored create_generated_clock at sys_top.sdc(16): Argument is an empty collection" { } { } 0 332049 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Ignored filter at sys_top.sdc(37): VID_CLK could not be matched with a clock" { } { } 0 332174 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "LOCKED port on the PLL is not properly connected on instance \"pll_audio:pll_audio\|pll_audio_0002:pll_audio_inst\|altera_pll:altera_pll_i\|general\[0\].gpll\". The LOCKED port on the PLL should be connected when the FBOUTCLK port is connected. Although it is unnecessary to connect the LOCKED signal, any logic driven off of an output clock of the PLL will not know when the PLL is locked and ready." { } { } 0 21300 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "*" { } { } 0 21074 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "*" { } { } 0 276020 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "*" { } { } 0 276027 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "RST" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "altera_pll.v" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "altera_cyclonev_pll.v" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "altera_pll_reconfig_core.v" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "cyclonev_pll" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} diff --git a/AdventureVision.sv b/AdventureVision.sv new file mode 100644 index 0000000..03f14c9 --- /dev/null +++ b/AdventureVision.sv @@ -0,0 +1,462 @@ +//============================================================================ +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +//============================================================================ + +module emu +( + //Master input clock + input CLK_50M, + + //Async reset from top-level module. + //Can be used as initial reset. + input RESET, + + //Must be passed to hps_io module + inout [48:0] HPS_BUS, + + //Base video clock. Usually equals to CLK_SYS. + output CLK_VIDEO, + + //Multiple resolutions are supported using different CE_PIXEL rates. + //Must be based on CLK_VIDEO + output CE_PIXEL, + + //Video aspect ratio for HDMI. Most retro systems have ratio 4:3. + //if VIDEO_ARX[12] or VIDEO_ARY[12] is set then [11:0] contains scaled size instead of aspect ratio. + output [12:0] VIDEO_ARX, + output [12:0] VIDEO_ARY, + + output [7:0] VGA_R, + output [7:0] VGA_G, + output [7:0] VGA_B, + output VGA_HS, + output VGA_VS, + output VGA_DE, // = ~(VBlank | HBlank) + output VGA_F1, + output [1:0] VGA_SL, + output VGA_SCALER, // Force VGA scaler + + input [11:0] HDMI_WIDTH, + input [11:0] HDMI_HEIGHT, + output HDMI_FREEZE, + +`ifdef MISTER_FB + // Use framebuffer in DDRAM (USE_FB=1 in qsf) + // FB_FORMAT: + // [2:0] : 011=8bpp(palette) 100=16bpp 101=24bpp 110=32bpp + // [3] : 0=16bits 565 1=16bits 1555 + // [4] : 0=RGB 1=BGR (for 16/24/32 modes) + // + // FB_STRIDE either 0 (rounded to 256 bytes) or multiple of pixel size (in bytes) + output FB_EN, + output [4:0] FB_FORMAT, + output [11:0] FB_WIDTH, + output [11:0] FB_HEIGHT, + output [31:0] FB_BASE, + output [13:0] FB_STRIDE, + input FB_VBL, + input FB_LL, + output FB_FORCE_BLANK, + +`ifdef MISTER_FB_PALETTE + // Palette control for 8bit modes. + // Ignored for other video modes. + output FB_PAL_CLK, + output [7:0] FB_PAL_ADDR, + output [23:0] FB_PAL_DOUT, + input [23:0] FB_PAL_DIN, + output FB_PAL_WR, +`endif +`endif + + output LED_USER, // 1 - ON, 0 - OFF. + + // b[1]: 0 - LED status is system status OR'd with b[0] + // 1 - LED status is controled solely by b[0] + // hint: supply 2'b00 to let the system control the LED. + output [1:0] LED_POWER, + output [1:0] LED_DISK, + + // I/O board button press simulation (active high) + // b[1]: user button + // b[0]: osd button + output [1:0] BUTTONS, + + input CLK_AUDIO, // 24.576 MHz + output [15:0] AUDIO_L, + output [15:0] AUDIO_R, + output AUDIO_S, // 1 - signed audio samples, 0 - unsigned + output [1:0] AUDIO_MIX, // 0 - no mix, 1 - 25%, 2 - 50%, 3 - 100% (mono) + + //ADC + inout [3:0] ADC_BUS, + + //SD-SPI + output SD_SCK, + output SD_MOSI, + input SD_MISO, + output SD_CS, + input SD_CD, + + //High latency DDR3 RAM interface + //Use for non-critical time purposes + output DDRAM_CLK, + input DDRAM_BUSY, + output [7:0] DDRAM_BURSTCNT, + output [28:0] DDRAM_ADDR, + input [63:0] DDRAM_DOUT, + input DDRAM_DOUT_READY, + output DDRAM_RD, + output [63:0] DDRAM_DIN, + output [7:0] DDRAM_BE, + output DDRAM_WE, + + //SDRAM interface with lower latency + output SDRAM_CLK, + output SDRAM_CKE, + output [12:0] SDRAM_A, + output [1:0] SDRAM_BA, + inout [15:0] SDRAM_DQ, + output SDRAM_DQML, + output SDRAM_DQMH, + output SDRAM_nCS, + output SDRAM_nCAS, + output SDRAM_nRAS, + output SDRAM_nWE, + +`ifdef MISTER_DUAL_SDRAM + //Secondary SDRAM + //Set all output SDRAM_* signals to Z ASAP if SDRAM2_EN is 0 + input SDRAM2_EN, + output SDRAM2_CLK, + output [12:0] SDRAM2_A, + output [1:0] SDRAM2_BA, + inout [15:0] SDRAM2_DQ, + output SDRAM2_nCS, + output SDRAM2_nCAS, + output SDRAM2_nRAS, + output SDRAM2_nWE, +`endif + + input UART_CTS, + output UART_RTS, + input UART_RXD, + output UART_TXD, + output UART_DTR, + input UART_DSR, + + // Open-drain User port. + // 0 - D+/RX + // 1 - D-/TX + // 2..6 - USR2..USR6 + // Set USER_OUT to 1 to read from USER_IN. + input [6:0] USER_IN, + output [6:0] USER_OUT, + + input OSD_STATUS +); + +///////// Default values for ports not used in this core ///////// + +assign ADC_BUS = 'Z; +assign USER_OUT = '1; +assign {UART_RTS, UART_TXD, UART_DTR} = 0; +assign {SD_SCK, SD_MOSI, SD_CS} = 'Z; +assign {SDRAM_DQ, SDRAM_A, SDRAM_BA, SDRAM_CLK, SDRAM_CKE, SDRAM_DQML, SDRAM_DQMH, SDRAM_nWE, SDRAM_nCAS, SDRAM_nRAS, SDRAM_nCS} = 'Z; +assign {DDRAM_CLK, DDRAM_BURSTCNT, DDRAM_ADDR, DDRAM_DIN, DDRAM_BE, DDRAM_RD, DDRAM_WE} = '0; + +assign VGA_F1 = 0; +assign VGA_SCALER = 0; +assign HDMI_FREEZE = 0; + +assign AUDIO_MIX = 0; + +assign LED_USER = 0; +assign LED_DISK = 0; +assign LED_POWER = 0; +assign BUTTONS = 0; + +////////////////////////////////////////////////////////////////// + +// Status Bit Map: (0..31 => "O", 32..63 => "o") +// 0 1 2 3 4 5 6 +// 01234567890123456789012345678901 23456789012345678901234567890123 +// 0123456789ABCDEFGHIJKLMNOPQRSTUV 0123456789ABCDEFGHIJKLMNOPQRSTUV +// XXXXXXX XX + +`include "build_id.v" +localparam CONF_STR = { + "AVision;;", + "-;", + "F1,BIN,Load Game;", + "-;", + "O89,Aspect ratio,Original,Full Screen,[ARC1],[ARC2];", + "O46,Scandoubler Fx,None,HQ2x,CRT 25%,CRT 50%,CRT 75%;", + "O23,Scale,Normal,V-Integer,Narrower HV-Integer,Wider HV-Integer;", + "-;", + "O1,Simulate Mirror,Off,On;", + "-;", + "R0,Reset;", + "J1,1,2,3,4;", + "jn,X,A,B,Y;", + "jp,X,A,B,Y;;", + "V,v",`BUILD_DATE +}; + +wire forced_scandoubler; +wire [1:0] buttons; +wire [31:0] status; +wire [10:0] ps2_key; + +wire ioctl_download; +wire [24:0] ioctl_addr; +wire [7:0] ioctl_dout; +wire ioctl_wait; +wire ioctl_wr; +wire [7:0] ioctl_index; + +wire [15:0] joystick0, joystick1; +wire [21:0] gamma_bus; + +assign ioctl_wait = 0; + +hps_io #(.CONF_STR(CONF_STR)) hps_io +( + .clk_sys(clk_sys), + .HPS_BUS(HPS_BUS), + .EXT_BUS(), + .gamma_bus(gamma_bus), + + .ioctl_download(ioctl_download), + .ioctl_wr(ioctl_wr), + .ioctl_addr(ioctl_addr), + .ioctl_dout(ioctl_dout), + .ioctl_wait(ioctl_wait), + .ioctl_index(ioctl_index), + + .joystick_0(joystick0), + .joystick_1(joystick1), + + .forced_scandoubler(forced_scandoubler), + + .buttons(buttons), + .status(status), + .status_menumask(0), + + .ps2_key(ps2_key) +); + +/////////////////////// CLOCKS /////////////////////////////// + +wire clk_sys, clk_vid; +pll pll +( + .refclk(CLK_50M), + .rst(0), + .outclk_0(clk_sys), + .outclk_1(clk_vid) +); + +wire reset = RESET | status[0] | buttons[1] | ioctl_download; + +////////////////////////////////////////////////////////////////// + +wire HBlank; +wire VBlank; + +wire [1:0] av_audio; +wire [39:0] av_led_n; +wire av_disp_photo_int; +wire por_n; +wire [11:0] av_bus_a; +wire [7:0] av_cart_dout; +wire av_cart_select; +wire hsync_n, vsync_n; +wire [2:0] Red; + +// av_audio(1) : volume 0 = high, 1 = low +// av_audio(0) : digital sound waveform +assign AUDIO_R = AUDIO_L; +assign AUDIO_S = 0; +assign AUDIO_L = {av_audio[0], (av_audio[1] ? 8'd0 : 12'd0)}; + +// Physical button layout +// 1 1 +// 2 4 JS 4 2 +// 3 3 +// I'll assume the right buttons are considered primary + +wire joy_up = ~joystick0[3] & ~joystick1[3]; +wire joy_down = ~joystick0[2] & ~joystick1[2]; +wire joy_left = ~joystick0[1] & ~joystick1[1]; +wire joy_right = ~joystick0[0] & ~joystick1[0]; + +wire [7:0] vdd8_s = 8'hFF; // Simulate a pulled up expansion bus + +av_machine AdventureVision +( + //-- System Interface ------------------------------------------------------- + .clk_11m_i (clk_sys), //: in std_logic; + .reset_n_i (~reset), //: in std_logic; + .por_n_o (por_n), //: out std_logic; + //-- Cartridge Interface ---------------------------------------------------- + .cart_a_o (av_bus_a), //: out std_logic_vector(11 downto 0); + .cart_oe_n_o (av_cart_select), //: out std_logic; + .cart_d_i (av_cart_dout), //: in std_logic_vector( 7 downto 0); + //-- Buttons and Stick Interface -------------------------------------------- + .but_1_n_i (~joystick0[4] & ~joystick1[4]), //: in std_logic; + .but_2_n_i (~joystick0[5] & ~joystick1[5]), //: in std_logic; + .but_3_n_i (~joystick0[6] & ~joystick1[6]), //: in std_logic; + .but_4_n_i (~joystick0[7] & ~joystick1[7]), //: in std_logic; + .stick_l_n_i (joy_left), //: in std_logic; + .stick_r_n_i (joy_right), //: in std_logic; + .stick_u_n_i (joy_up), //: in std_logic; + .stick_d_n_i (joy_down), //: in std_logic; + //-- Sound Interface -------------------------------------------------------- + .audio_o (av_audio), //: out std_logic_vector( 1 downto 0); + //-- Display Interface ------------------------------------------------------ + .led_n_o (av_led_n), //: out std_logic_vector(39 downto 0); + .disp_p24_n_o (), //: out std_logic; + .disp_photo_int_o (av_disp_photo_int), //: out std_logic; + //-- Expansion Interface ---------------------------------------------------- + .exp_t0_i (vdd8_s), //: in std_logic; + .exp_t0_o (), //: out std_logic; + .exp_t0_dir_o (), //: out std_logic; + .exp_rd_n_o (), //: out std_logic; + .exp_psen_n_o (), //: out std_logic; + .exp_wr_n_o (), //: out std_logic; + .exp_ale_o (), //: out std_logic; + .exp_d_i (vdd8_s), //: in std_logic_vector( 7 downto 0); + .exp_d_o (), //: out std_logic_vector( 7 downto 0); + .exp_p1_i (vdd8_s), //: in std_logic_vector( 7 downto 3); + .exp_p1_o (), //: out std_logic_vector( 7 downto 3); + .exp_p1_low_imp_o (), //: out std_logic; + .exp_p2_i (vdd8_s), //: in std_logic_vector( 3 downto 0); + .exp_p2_o (), //: out std_logic_vector( 3 downto 0); + .exp_p2l_low_imp_o (), //: out std_logic; + .exp_p2h_low_imp_o (), //: out std_logic; + .exp_prog_n_o () //: out std_logic +); + +av_video #(.is_pal_g(0)) av_video +( + .clk_11m_i (clk_sys), + .por_n_i (por_n), + .disp_photo_int_i (av_disp_photo_int), + .led_n_i (av_led_n), + .rgb_r_o (Red), + .rgb_hsync_n_o (hsync_n), + .rgb_vsync_n_o (vsync_n), + .rgb_csync_n_o (), + .hblank (HBlank), + .vblank (VBlank), + .fixed_intensity (~status[1]) +); + +dpram #(.addr_width_g(12)) cart_ram +( + .clk_b_i (clk_sys), + .addr_b_i (av_bus_a), + .data_b_o (av_cart_dout), + + .clk_a_i (clk_sys), + .addr_a_i (ioctl_addr), + .data_a_i (ioctl_dout), + .we_i (ioctl_wr) +); + +wire [2:0] scale = status[6:4]; +wire [2:0] sl = scale ? scale - 1'd1 : 3'd0; +wire HSync = ~hsync_n; +wire VSync = ~vsync_n; + +typedef struct packed { + logic [7:0] Red; + logic VBlank; + logic VSync; + logic HBlank; + logic HSync; + logic ce_pix; +} video_t; + +video_t [3:0] vid_pipe; + +wire vid_de; + +video_mixer #(.LINE_LENGTH(450),.GAMMA(1),.HALF_DEPTH(0)) video_mixer +( + .CLK_VIDEO (CLK_VIDEO), // should be multiple by (ce_pix*4) + .CE_PIXEL (CE_PIXEL), // output pixel clock enable + .ce_pix (vid_pipe[3].ce_pix), // input pixel clock or clock_enable + .scandoubler (scale || forced_scandoubler), + .hq2x (scale == 1), // high quality 2x scaling + .gamma_bus (gamma_bus), + .R (vid_pipe[3].Red), + .G (8'd0), + .B (8'd0), + .HSync (vid_pipe[3].HSync), + .VSync (vid_pipe[3].VSync), + .HBlank (vid_pipe[3].HBlank), + .VBlank (vid_pipe[3].VBlank), + .HDMI_FREEZE (), + .freeze_sync (), + .VGA_R (VGA_R), + .VGA_G (VGA_G), + .VGA_B (VGA_B), + .VGA_VS (VGA_VS), + .VGA_HS (VGA_HS), + .VGA_DE (vid_de) +); + +wire [1:0] ar = status[9:8]; + +video_freak video_freak +( + .CLK_VIDEO (CLK_VIDEO), + .CE_PIXEL (CE_PIXEL), + .VGA_VS (VGA_VS), + .HDMI_WIDTH (HDMI_HEIGHT), + .HDMI_HEIGHT (HDMI_WIDTH), + .VGA_DE (VGA_DE), + .VIDEO_ARX (VIDEO_ARX), + .VIDEO_ARY (VIDEO_ARY), + .VGA_DE_IN (vid_de), + .ARX ((!ar) ? 12'd1387 : (ar - 1'd1)), + .ARY ((!ar) ? 12'd962 : 12'd0), + .CROP_SIZE (10'd0), + .CROP_OFF (0), + .SCALE (status[3:2]) +); + +reg [1:0] pix_div; + +always @(posedge clk_vid) begin + pix_div <= pix_div + 1'd1; + vid_pipe[0].Red <= {Red, Red, Red[2:1]}; + vid_pipe[0].HSync <= HSync; + vid_pipe[0].VSync <= VSync; + vid_pipe[0].HBlank <= HBlank; + vid_pipe[0].VBlank <= VBlank; + vid_pipe[0].ce_pix <= &pix_div; + + vid_pipe[3:1] <= vid_pipe[2:0]; +end + +assign CLK_VIDEO = clk_vid; +assign VGA_SL = sl[1:0]; + +endmodule diff --git a/AdventureVision_Q13.qpf b/AdventureVision_Q13.qpf new file mode 100644 index 0000000..031089c --- /dev/null +++ b/AdventureVision_Q13.qpf @@ -0,0 +1,2 @@ +QUARTUS_VERSION = "13.1" +PROJECT_REVISION = "AdventureVision_Q13" diff --git a/AdventureVision_Q13.qsf b/AdventureVision_Q13.qsf new file mode 100644 index 0000000..e1b8535 --- /dev/null +++ b/AdventureVision_Q13.qsf @@ -0,0 +1,46 @@ +# -------------------------------------------------------------------------- +# +# MiSTer project +# +# WARNING WARNING WARNING: +# Do not add files to project in Quartus IDE! It will mess this file! +# Add the files manually to files.qip file. +# +# -------------------------------------------------------------------------- + +set_global_assignment -name TOP_LEVEL_ENTITY sys_top +set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top +set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top +set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top + +set_global_assignment -name LAST_QUARTUS_VERSION 13.1 + +set_global_assignment -name GENERATE_RBF_FILE ON +set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files +set_global_assignment -name NUM_PARALLEL_PROCESSORS ALL +set_global_assignment -name SAVE_DISK_SPACE OFF +set_global_assignment -name SMART_RECOMPILE ON +set_global_assignment -name MIN_CORE_JUNCTION_TEMP "-40" +set_global_assignment -name MAX_CORE_JUNCTION_TEMP 100 +set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "23 MM HEAT SINK WITH 200 LFPM AIRFLOW" +set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)" +set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS OFF +set_global_assignment -name OPTIMIZE_POWER_DURING_FITTING OFF +set_global_assignment -name FINAL_PLACEMENT_OPTIMIZATION ALWAYS +set_global_assignment -name FITTER_EFFORT "STANDARD FIT" +set_global_assignment -name SYNTH_TIMING_DRIVEN_SYNTHESIS ON +set_global_assignment -name OPTIMIZATION_TECHNIQUE SPEED +set_global_assignment -name PLACEMENT_EFFORT_MULTIPLIER 2.0 +set_global_assignment -name SYNTH_GATED_CLOCK_CONVERSION ON +set_global_assignment -name ROUTER_CLOCKING_TOPOLOGY_ANALYSIS ON +set_global_assignment -name ALLOW_SYNCH_CTRL_USAGE OFF +set_global_assignment -name OPTIMIZE_POWER_DURING_SYNTHESIS OFF +set_global_assignment -name OPTIMIZE_HOLD_TIMING "ALL PATHS" +set_global_assignment -name OPTIMIZE_MULTI_CORNER_TIMING ON +set_global_assignment -name ALM_REGISTER_PACKING_EFFORT LOW +set_global_assignment -name SEED 1 + +source sys/sys.tcl +source sys/sys_analog.tcl +set_global_assignment -name QIP_FILE files.qip +set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file diff --git a/AdventureVision_Q13.srf b/AdventureVision_Q13.srf new file mode 100644 index 0000000..30734ea --- /dev/null +++ b/AdventureVision_Q13.srf @@ -0,0 +1,28 @@ +{ "" "" "" "Verilog HDL or VHDL warning at sys_top.v(209): object \"vip_newcfg\" assigned a value but never read" { } { } 0 10036 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "Verilog HDL information at MC6845.v(280): always construct contains both blocking and non-blocking assignments" { } { } 0 10268 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "Verilog HDL or VHDL warning at sys_top.v(601): object \"VSET\" assigned a value but never read" { } { } 0 10036 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "Port \"extclk\" on the entity instantiation of \"cyclonev_pll\" is connected to a signal of width 1. The formal width of the signal in the module is 2. The extra bits will be left dangling without any fan-out logic." { } { } 0 12030 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "RST port on the PLL is not properly connected on instance emu:emu\|pll:pll\|pll_0002:pll_inst\|altera_pll:altera_pll_i\|general\[0\].gpll. The reset port on the PLL should be connected. If the PLL loses lock for any reason, you might need to manually reset the PLL in order to re-establish lock to the reference clock." { } { } 0 0 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "Dummy RLC values generated in IBIS model files for device 5CSEBA6 with package UFBGA and pin count 672" { } { } 0 205009 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "Ignored filter at sys_top.sdc(10): vip\|output_inst\|vid_clk could not be matched with a net" { } { } 0 332174 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "Ignored create_generated_clock at sys_top.sdc(9): Argument is an empty collection" { } { } 0 332049 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "Ignored filter at sys_top.sdc(29): VID_CLK could not be matched with a clock" { } { } 0 332174 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "Timing characteristics of device 5CSEBA6U23I7 are preliminary" { } { } 0 334000 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "Inferred RAM node \"emu:emu\|rom_map_rtl_0\" from synchronous design logic. Pass-through logic has been added to match the read-during-write behavior of the original design." { } { } 0 276020 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "RST port on the PLL is not properly connected on instance emu:emu\|pll:pll\|pll_0002:pll_inst\|altera_pll:altera_pll_i\|general\[1\].gpll. The reset port on the PLL should be connected. If the PLL loses lock for any reason, you might need to manually reset the PLL in order to re-establish lock to the reference clock." { } { } 0 0 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "Ignored filter at sys_top.sdc(17): vip\|output_inst\|vid_clk could not be matched with a net" { } { } 0 332174 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "Ignored create_generated_clock at sys_top.sdc(16): Argument is an empty collection" { } { } 0 332049 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "Ignored filter at sys_top.sdc(37): VID_CLK could not be matched with a clock" { } { } 0 332174 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "LOCKED port on the PLL is not properly connected on instance \"emu:emu\|pll:pll\|pll_0002:pll_inst\|altera_pll:altera_pll_i\|general\[0\].gpll\". The LOCKED port on the PLL should be connected when the FBOUTCLK port is connected. Although it is unnecessary to connect the LOCKED signal, any logic driven off of an output clock of the PLL will not know when the PLL is locked and ready." { } { } 0 21300 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "Some pins have incomplete I/O assignments. Refer to the I/O Assignment Warnings report for details" { } { } 0 15714 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "Ignoring invalid fast I/O register assignments. See the Ignored Assignments panel in the Fitter Compilation Report for more information." { } { } 0 176250 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "Ignored locations or region assignments to the following nodes" { } { } 0 15705 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "RST port on the PLL is not properly connected on instance emu:emu\|pll:pll\|pll_0002:pll_inst\|altera_pll:altera_pll_i\|general\[2\].gpll. The reset port on the PLL should be connected. If the PLL loses lock for any reason, you might need to manually reset the PLL in order to re-establish lock to the reference clock." { } { } 0 0 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "RST port on the PLL is not properly connected on instance pll_audio:pll_audio\|pll_audio_0002:pll_audio_inst\|altera_pll:altera_pll_i\|general\[0\].gpll. The reset port on the PLL should be connected. If the PLL loses lock for any reason, you might need to manually reset the PLL in order to re-establish lock to the reference clock." { } { } 0 0 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "LOCKED port on the PLL is not properly connected on instance \"pll_audio:pll_audio\|pll_audio_0002:pll_audio_inst\|altera_pll:altera_pll_i\|general\[0\].gpll\". The LOCKED port on the PLL should be connected when the FBOUTCLK port is connected. Although it is unnecessary to connect the LOCKED signal, any logic driven off of an output clock of the PLL will not know when the PLL is locked and ready." { } { } 0 21300 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "*" { } { } 0 10268 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "*" { } { } 0 276027 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "*" { } { } 0 276020 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "altera_pll.v" { } { } 0 9999 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "altera_cyclonev_pll.v" { } { } 0 9999 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "altera_pll_reconfig_core.v" { } { } 0 9999 "" 0 0 "Quartus II" 0 -1 0 ""} diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..60549be --- /dev/null +++ b/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8f3eda8 --- /dev/null +++ b/LICENSE @@ -0,0 +1,11 @@ +Redistribution and use in source and synthesized forms, with or without modification, are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +Redistributions in synthesized form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +Neither the name of the author nor the names of other contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +See also the file COPYING. \ No newline at end of file diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..a9ba787 --- /dev/null +++ b/Readme.md @@ -0,0 +1,15 @@ +# Adventure Vision + +## General Information +This is a port of the adventure vision core originally written by Arnim Laeuger in 2006. The system has 4 retail games, and two homebrew games. The core uses the folder AVision for its games, and no other setup is required. + +## Technical Details +The screen of the Adventure Vision was a strip of 40 LEDs that reflected off a rapidly rotating mirror, similar to a grocery store scanner. This resulted in a 15 frames per second image of 150x40 pixels. The original system's display was extremely flickery as a result, and the shape of it "wobbled". The core has an option to try to emulate this, but it defaults to having the flicker off for comfort and safety. If you choose to try this feature, it seems to look best on very small CRTs. + +## Button Layout +``` + 1 1 + 2 4 JS 4 2 + 3 3 +``` +There are two sets of buttons, intended for multiplayer, which have slightly different layouts. On the core, both the first and second player controllers will have full access to the controls. \ No newline at end of file diff --git a/clean.bat b/clean.bat new file mode 100644 index 0000000..1e6a801 --- /dev/null +++ b/clean.bat @@ -0,0 +1,36 @@ +@echo off +del /s *.bak +del /s *.orig +del /s *.rej +del /s *~ +rmdir /s /q db +rmdir /s /q incremental_db +rmdir /s /q output_files +rmdir /s /q simulation +rmdir /s /q greybox_tmp +rmdir /s /q hc_output +rmdir /s /q .qsys_edit +rmdir /s /q hps_isw_handoff +rmdir /s /q sys\.qsys_edit +rmdir /s /q sys\vip +for /d %%i in (sys\*_sim) do rmdir /s /q "%%i" +for /d %%i in (rtl\*_sim) do rmdir /s /q "%%i" +del build_id.v +del c5_pin_model_dump.txt +del PLLJ_PLLSPE_INFO.txt +del /s *.qws +del /s *.ppf +del /s *.ddb +del /s *.csv +del /s *.cmp +del /s *.sip +del /s *.spd +del /s *.bsf +del /s *.f +del /s *.sopcinfo +del /s *.xml +del *.cdf +del *.rpt +del /s new_rtl_netlist +del /s old_rtl_netlist +pause diff --git a/files.qip b/files.qip new file mode 100644 index 0000000..ba42985 --- /dev/null +++ b/files.qip @@ -0,0 +1,103 @@ +set_global_assignment -name SDC_FILE AdventureVision.sdc +set_global_assignment -name SYSTEMVERILOG_FILE AdventureVision.sv + +#set_global_assignment -name VHDL_FILE rtl/bram.vhd + +set_global_assignment -name VHDL_FILE rtl/t48/rtl/vhdl/t48_pack-p.vhd +set_global_assignment -name VHDL_FILE rtl/t48/rtl/vhdl/alu_pack-p.vhd +set_global_assignment -name VHDL_FILE rtl/t48/rtl/vhdl/cond_branch_pack-p.vhd +set_global_assignment -name VHDL_FILE rtl/t48/rtl/vhdl/decoder_pack-p.vhd +set_global_assignment -name VHDL_FILE rtl/t48/rtl/vhdl/dmem_ctrl_pack-p.vhd +set_global_assignment -name VHDL_FILE rtl/t48/rtl/vhdl/pmem_ctrl_pack-p.vhd +set_global_assignment -name VHDL_FILE rtl/t400/rtl/vhdl/t400_opt_pack-p.vhd +set_global_assignment -name VHDL_FILE rtl/t400/rtl/vhdl/t400_pack-p.vhd +set_global_assignment -name VHDL_FILE rtl/t48/rtl/vhdl/opc_table.vhd +set_global_assignment -name VHDL_FILE rtl/t48/rtl/vhdl/t48_comp_pack-p.vhd +set_global_assignment -name VHDL_FILE rtl/t400/rtl/vhdl/t400_io_pack-p.vhd +set_global_assignment -name VHDL_FILE rtl/t400/rtl/vhdl/t400_comp_pack-p.vhd +set_global_assignment -name VHDL_FILE rtl/t400/rtl/vhdl/t400_opc_table.vhd +set_global_assignment -name VHDL_FILE rtl/t48/rtl/vhdl/opc_decoder.vhd +set_global_assignment -name VHDL_FILE rtl/t48/rtl/vhdl/int.vhd +set_global_assignment -name VHDL_FILE rtl/t400/rtl/vhdl/t400_clkgen.vhd +set_global_assignment -name VHDL_FILE rtl/t400/rtl/vhdl/t400_reset.vhd +set_global_assignment -name VHDL_FILE rtl/t400/rtl/vhdl/t400_pmem_ctrl.vhd +set_global_assignment -name VHDL_FILE rtl/t400/rtl/vhdl/t400_dmem_ctrl.vhd +set_global_assignment -name VHDL_FILE rtl/t400/rtl/vhdl/t400_decoder.vhd +set_global_assignment -name VHDL_FILE rtl/t400/rtl/vhdl/t400_skip.vhd +set_global_assignment -name VHDL_FILE rtl/t400/rtl/vhdl/t400_alu.vhd +set_global_assignment -name VHDL_FILE rtl/t400/rtl/vhdl/t400_stack.vhd +set_global_assignment -name VHDL_FILE rtl/t400/rtl/vhdl/t400_io_l.vhd +set_global_assignment -name VHDL_FILE rtl/t400/rtl/vhdl/t400_io_d.vhd +set_global_assignment -name VHDL_FILE rtl/t400/rtl/vhdl/t400_io_g.vhd +set_global_assignment -name VHDL_FILE rtl/t400/rtl/vhdl/t400_io_in.vhd +set_global_assignment -name VHDL_FILE rtl/t400/rtl/vhdl/t400_sio.vhd +set_global_assignment -name VHDL_FILE rtl/t400/rtl/vhdl/t400_timer.vhd +set_global_assignment -name VHDL_FILE rtl/t48/rtl/vhdl/alu.vhd +set_global_assignment -name VHDL_FILE rtl/t48/rtl/vhdl/bus_mux.vhd +set_global_assignment -name VHDL_FILE rtl/t48/rtl/vhdl/clock_ctrl.vhd +set_global_assignment -name VHDL_FILE rtl/t48/rtl/vhdl/cond_branch.vhd +set_global_assignment -name VHDL_FILE rtl/t48/rtl/vhdl/db_bus.vhd +set_global_assignment -name VHDL_FILE rtl/t48/rtl/vhdl/decoder.vhd +set_global_assignment -name VHDL_FILE rtl/t48/rtl/vhdl/dmem_ctrl.vhd +set_global_assignment -name VHDL_FILE rtl/t48/rtl/vhdl/timer.vhd +set_global_assignment -name VHDL_FILE rtl/t48/rtl/vhdl/p1.vhd +set_global_assignment -name VHDL_FILE rtl/t48/rtl/vhdl/p2.vhd +set_global_assignment -name VHDL_FILE rtl/t48/rtl/vhdl/pmem_ctrl.vhd +set_global_assignment -name VHDL_FILE rtl/t48/rtl/vhdl/psw.vhd +set_global_assignment -name VHDL_FILE rtl/t400/rtl/tech/t400_tech_comp_pack-p.vhd +set_global_assignment -name VHDL_FILE rtl/t400/rtl/vhdl/t400_core.vhd +set_global_assignment -name VHDL_FILE rtl/t400/rtl/vhdl/system/t410_rom-e.vhd +set_global_assignment -name VHDL_FILE rtl/t400/rtl/tech/generic/generic_ram_ena.vhd +set_global_assignment -name VHDL_FILE rtl/t400/rtl/tech/spartan/t400_por.vhd +set_global_assignment -name VHDL_FILE rtl/t400/rtl/vhdl/t400_core_comp_pack-p.vhd +set_global_assignment -name VHDL_FILE rtl/t48/rtl/vhdl/t48_core.vhd +set_global_assignment -name VHDL_FILE rtl/t48/rtl/vhdl/system/syn_rom-e.vhd +set_global_assignment -name VHDL_FILE rtl/t48/rtl/vhdl/system/syn_ram-e.vhd +set_global_assignment -name VHDL_FILE rtl/t48/rtl/vhdl/t48_core_comp_pack-p.vhd +#set_global_assignment -name VHDL_FILE rtl/board/gamepads/snespad/rtl/vhdl/snespad_pack-p.vhd +set_global_assignment -name VHDL_FILE rtl/tech/generic/generic_ram.vhd +set_global_assignment -name VHDL_FILE rtl/tech/tech_comp_pack-p.vhd +set_global_assignment -name VHDL_FILE rtl/t400/rtl/vhdl/system/t410_notri.vhd +set_global_assignment -name VHDL_FILE rtl/t400/rtl/vhdl/system/t400_system_comp_pack-p.vhd +set_global_assignment -name VHDL_FILE rtl/tech/spartan/av_por.vhd +set_global_assignment -name VHDL_FILE rtl/t48/rtl/vhdl/system/t8048_notri.vhd +set_global_assignment -name VHDL_FILE rtl/t48/rtl/vhdl/system/t48_system_comp_pack-p.vhd +#set_global_assignment -name VHDL_FILE rtl/board/gamepads/snespad/rtl/vhdl/snespad_ctrl.vhd +#set_global_assignment -name VHDL_FILE rtl/board/gamepads/snespad/rtl/vhdl/snespad_pad.vhd +set_global_assignment -name VHDL_FILE rtl/tech/generic/dpram.vhd +set_global_assignment -name VHDL_FILE rtl/video/av_frame_buffer.vhd +set_global_assignment -name VHDL_FILE rtl/video/av_raster.vhd +set_global_assignment -name VHDL_FILE rtl/video/av_video_comp_pack-p.vhd +set_global_assignment -name VHDL_FILE rtl/av_comp_pack-p.vhd +set_global_assignment -name VHDL_FILE rtl/av_main.vhd +set_global_assignment -name VHDL_FILE rtl/av_ctrl.vhd +set_global_assignment -name VHDL_FILE rtl/av_disp.vhd +set_global_assignment -name VHDL_FILE rtl/av_machine_comp_pack-p.vhd +#set_global_assignment -name VHDL_FILE rtl/board/misc/board_misc_comp_pack-p.vhd +#set_global_assignment -name VHDL_FILE rtl/board/gamepads/snespad/rtl/vhdl/snespad_comp-pack.vhd +#set_global_assignment -name VHDL_FILE rtl/board/zefant_xs3/zefant_xs3_pll.vhd +set_global_assignment -name VHDL_FILE rtl/av_machine.vhd +set_global_assignment -name VHDL_FILE rtl/video/av_video.vhd +#set_global_assignment -name VHDL_FILE rtl/board/misc/dblscan.vhd +#set_global_assignment -name VHDL_FILE rtl/board/misc/pcm_sound.vhd +#set_global_assignment -name VHDL_FILE rtl/board/gamepads/snespad/rtl/vhdl/snespad.vhd +#set_global_assignment -name VHDL_FILE rtl/board/zefant_xs3/zefant_xs3_av.vhd +set_global_assignment -name VHDL_FILE rtl/tech/generic/syn_ram-generic_tech-a.vhd +set_global_assignment -name VHDL_FILE rtl/tech/generic/syn_rom-av_bios-a.vhd +set_global_assignment -name VHDL_FILE rtl/tech/generic/t410_rom-struct-a.vhd +#set_global_assignment -name VHDL_FILE rtl/board/misc/ac97_ctrl/rtl/verilog/ac97_fifo_ctrl.v +#set_global_assignment -name VHDL_FILE rtl/board/misc/ac97_ctrl/rtl/verilog/ac97_dma_req.v +#set_global_assignment -name VHDL_FILE rtl/board/misc/ac97_ctrl/rtl/verilog/ac97_wb_if.v +#set_global_assignment -name VHDL_FILE rtl/board/misc/ac97_ctrl/rtl/verilog/ac97_sout.v +#set_global_assignment -name VHDL_FILE rtl/board/misc/ac97_ctrl/rtl/verilog/ac97_soc.v +#set_global_assignment -name VHDL_FILE rtl/board/misc/ac97_ctrl/rtl/verilog/ac97_sin.v +#set_global_assignment -name VHDL_FILE rtl/board/misc/ac97_ctrl/rtl/verilog/ac97_rst.v +#set_global_assignment -name VHDL_FILE rtl/board/misc/ac97_ctrl/rtl/verilog/ac97_rf.v +#set_global_assignment -name VHDL_FILE rtl/board/misc/ac97_ctrl/rtl/verilog/ac97_prc.v +#set_global_assignment -name VHDL_FILE rtl/board/misc/ac97_ctrl/rtl/verilog/ac97_out_fifo.v +#set_global_assignment -name VHDL_FILE rtl/board/misc/ac97_ctrl/rtl/verilog/ac97_int.v +#set_global_assignment -name VHDL_FILE rtl/board/misc/ac97_ctrl/rtl/verilog/ac97_dma_if.v +#set_global_assignment -name VHDL_FILE rtl/board/misc/ac97_ctrl/rtl/verilog/ac97_cra.v +#set_global_assignment -name VHDL_FILE rtl/board/misc/ac97_ctrl/rtl/verilog/ac97_top.v +set_global_assignment -name VHDL_FILE rtl/assets/rom_t41x.vhd +set_global_assignment -name VHDL_FILE rtl/assets/adventurevision_bios.vhd \ No newline at end of file diff --git a/releases/AdventureVision_20220319.rbf b/releases/AdventureVision_20220319.rbf new file mode 100644 index 0000000000000000000000000000000000000000..0c2329a1ea224dedf3d19c5fd414b1d624d73b31 GIT binary patch literal 2642584 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�@+CA(nhl(MI(?=7u#*R$aXfA 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

+fblRLX|#k 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

`;A4$rTkZ=`W7)H5` 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

wN+@+X=ppECFk6dT|eC0+|MF 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
    (cY|J-&0^PBnTllx^ANQ=~?}a9dKH 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 literal 0 HcmV?d00001 diff --git a/rtl/assets/adventurevision_bios.vhd b/rtl/assets/adventurevision_bios.vhd new file mode 100644 index 0000000..3abef54 --- /dev/null +++ b/rtl/assets/adventurevision_bios.vhd @@ -0,0 +1,1054 @@ +-- This file was generated with hex2rom written by Daniel Wallner + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +entity adventurevision_bios is + port( + Clk : in std_logic; + A : in std_logic_vector(9 downto 0); + D : out std_logic_vector(7 downto 0) + ); +end adventurevision_bios; + +architecture rtl of adventurevision_bios is + signal A_r : std_logic_vector(9 downto 0); +begin + process (Clk) + begin + if Clk'event and Clk = '1' then + A_r <= A; + end if; + end process; + process (A_r) + begin + case to_integer(unsigned(A_r)) is + when 000000 => D <= "11110101"; -- 0x0000 + when 000001 => D <= "00000100"; -- 0x0001 + when 000002 => D <= "00000000"; -- 0x0002 + when 000003 => D <= "00000100"; -- 0x0003 + when 000004 => D <= "00110110"; -- 0x0004 + when 000005 => D <= "00000100"; -- 0x0005 + when 000006 => D <= "01110001"; -- 0x0006 + when 000007 => D <= "00000100"; -- 0x0007 + when 000008 => D <= "11110000"; -- 0x0008 + when 000009 => D <= "00100100"; -- 0x0009 + when 000010 => D <= "10100000"; -- 0x000A + when 000011 => D <= "01000100"; -- 0x000B + when 000012 => D <= "10111001"; -- 0x000C + when 000013 => D <= "01100100"; -- 0x000D + when 000014 => D <= "01100001"; -- 0x000E + when 000015 => D <= "01100100"; -- 0x000F + when 000016 => D <= "00100100"; -- 0x0010 + when 000017 => D <= "01000100"; -- 0x0011 + when 000018 => D <= "11100010"; -- 0x0012 + when 000019 => D <= "01000100"; -- 0x0013 + when 000020 => D <= "11101111"; -- 0x0014 + when 000021 => D <= "00000100"; -- 0x0015 + when 000022 => D <= "00101011"; -- 0x0016 + when 000023 => D <= "01100100"; -- 0x0017 + when 000024 => D <= "10011010"; -- 0x0018 + when 000025 => D <= "01100100"; -- 0x0019 + when 000026 => D <= "11001110"; -- 0x001A + when 000027 => D <= "01100100"; -- 0x001B + when 000028 => D <= "10101001"; -- 0x001C + when 000029 => D <= "01000100"; -- 0x001D + when 000030 => D <= "11111111"; -- 0x001E + when 000031 => D <= "01100100"; -- 0x001F + when 000032 => D <= "00001110"; -- 0x0020 + when 000033 => D <= "01100100"; -- 0x0021 + when 000034 => D <= "00011101"; -- 0x0022 + when 000035 => D <= "00100100"; -- 0x0023 + when 000036 => D <= "10010111"; -- 0x0024 + when 000037 => D <= "01100100"; -- 0x0025 + when 000038 => D <= "11110001"; -- 0x0026 + when 000039 => D <= "01100100"; -- 0x0027 + when 000040 => D <= "11101111"; -- 0x0028 + when 000041 => D <= "01100100"; -- 0x0029 + when 000042 => D <= "11101101"; -- 0x002A + when 000043 => D <= "10111000"; -- 0x002B + when 000044 => D <= "00111111"; -- 0x002C + when 000045 => D <= "10111001"; -- 0x002D + when 000046 => D <= "00100000"; -- 0x002E + when 000047 => D <= "00100111"; -- 0x002F + when 000048 => D <= "10110000"; -- 0x0030 + when 000049 => D <= "00000000"; -- 0x0031 + when 000050 => D <= "11001000"; -- 0x0032 + when 000051 => D <= "11101001"; -- 0x0033 + when 000052 => D <= "00110000"; -- 0x0034 + when 000053 => D <= "10000011"; -- 0x0035 + when 000054 => D <= "11000101"; -- 0x0036 + when 000055 => D <= "10111000"; -- 0x0037 + when 000056 => D <= "00111111"; -- 0x0038 + when 000057 => D <= "00010000"; -- 0x0039 + when 000058 => D <= "01000110"; -- 0x003A + when 000059 => D <= "00111010"; -- 0x003B + when 000060 => D <= "01010110"; -- 0x003C + when 000061 => D <= "00111100"; -- 0x003D + when 000062 => D <= "10111001"; -- 0x003E + when 000063 => D <= "00000001"; -- 0x003F + when 000064 => D <= "11111001"; -- 0x0040 + when 000065 => D <= "00111001"; -- 0x0041 + when 000066 => D <= "10111000"; -- 0x0042 + when 000067 => D <= "00000101"; -- 0x0043 + when 000068 => D <= "00011000"; -- 0x0044 + when 000069 => D <= "11111000"; -- 0x0045 + when 000070 => D <= "10010110"; -- 0x0046 + when 000071 => D <= "01010000"; -- 0x0047 + when 000072 => D <= "00100111"; -- 0x0048 + when 000073 => D <= "00111010"; -- 0x0049 + when 000074 => D <= "00011001"; -- 0x004A + when 000075 => D <= "11111001"; -- 0x004B + when 000076 => D <= "01010010"; -- 0x004C + when 000077 => D <= "01101101"; -- 0x004D + when 000078 => D <= "00000100"; -- 0x004E + when 000079 => D <= "01000001"; -- 0x004F + when 000080 => D <= "00100011"; -- 0x0050 + when 000081 => D <= "00100000"; -- 0x0051 + when 000082 => D <= "00111010"; -- 0x0052 + when 000083 => D <= "10000000"; -- 0x0053 + when 000084 => D <= "00100011"; -- 0x0054 + when 000085 => D <= "01000000"; -- 0x0055 + when 000086 => D <= "00111010"; -- 0x0056 + when 000087 => D <= "00011000"; -- 0x0057 + when 000088 => D <= "10000000"; -- 0x0058 + when 000089 => D <= "00100011"; -- 0x0059 + when 000090 => D <= "01100000"; -- 0x005A + when 000091 => D <= "00111010"; -- 0x005B + when 000092 => D <= "00011000"; -- 0x005C + when 000093 => D <= "10000000"; -- 0x005D + when 000094 => D <= "00100011"; -- 0x005E + when 000095 => D <= "10000000"; -- 0x005F + when 000096 => D <= "00111010"; -- 0x0060 + when 000097 => D <= "00011000"; -- 0x0061 + when 000098 => D <= "10000000"; -- 0x0062 + when 000099 => D <= "00100011"; -- 0x0063 + when 000100 => D <= "10100000"; -- 0x0064 + when 000101 => D <= "00111010"; -- 0x0065 + when 000102 => D <= "00011000"; -- 0x0066 + when 000103 => D <= "10000000"; -- 0x0067 + when 000104 => D <= "00100011"; -- 0x0068 + when 000105 => D <= "00010000"; -- 0x0069 + when 000106 => D <= "00111010"; -- 0x006A + when 000107 => D <= "00000100"; -- 0x006B + when 000108 => D <= "01000100"; -- 0x006C + when 000109 => D <= "00100111"; -- 0x006D + when 000110 => D <= "00111001"; -- 0x006E + when 000111 => D <= "11010101"; -- 0x006F + when 000112 => D <= "10000011"; -- 0x0070 + when 000113 => D <= "00100111"; -- 0x0071 + when 000114 => D <= "00111001"; -- 0x0072 + when 000115 => D <= "11111001"; -- 0x0073 + when 000116 => D <= "01010011"; -- 0x0074 + when 000117 => D <= "11111000"; -- 0x0075 + when 000118 => D <= "00000011"; -- 0x0076 + when 000119 => D <= "00000011"; -- 0x0077 + when 000120 => D <= "10101001"; -- 0x0078 + when 000121 => D <= "10000001"; -- 0x0079 + when 000122 => D <= "00000011"; -- 0x007A + when 000123 => D <= "11111100"; -- 0x007B + when 000124 => D <= "11110110"; -- 0x007C + when 000125 => D <= "10101001"; -- 0x007D + when 000126 => D <= "11001001"; -- 0x007E + when 000127 => D <= "11001001"; -- 0x007F + when 000128 => D <= "10000001"; -- 0x0080 + when 000129 => D <= "10101010"; -- 0x0081 + when 000130 => D <= "11111001"; -- 0x0082 + when 000131 => D <= "11000101"; -- 0x0083 + when 000132 => D <= "10101000"; -- 0x0084 + when 000133 => D <= "00011000"; -- 0x0085 + when 000134 => D <= "10000000"; -- 0x0086 + when 000135 => D <= "10101001"; -- 0x0087 + when 000136 => D <= "00011000"; -- 0x0088 + when 000137 => D <= "10000000"; -- 0x0089 + when 000138 => D <= "10101010"; -- 0x008A + when 000139 => D <= "00011000"; -- 0x008B + when 000140 => D <= "10000000"; -- 0x008C + when 000141 => D <= "10101011"; -- 0x008D + when 000142 => D <= "11111011"; -- 0x008E + when 000143 => D <= "00010111"; -- 0x008F + when 000144 => D <= "10101110"; -- 0x0090 + when 000145 => D <= "11111010"; -- 0x0091 + when 000146 => D <= "10101101"; -- 0x0092 + when 000147 => D <= "10010110"; -- 0x0093 + when 000148 => D <= "10011111"; -- 0x0094 + when 000149 => D <= "10111110"; -- 0x0095 + when 000150 => D <= "00000110"; -- 0x0096 + when 000151 => D <= "00011101"; -- 0x0097 + when 000152 => D <= "11111101"; -- 0x0098 + when 000153 => D <= "00000011"; -- 0x0099 + when 000154 => D <= "11111100"; -- 0x009A + when 000155 => D <= "10010110"; -- 0x009B + when 000156 => D <= "10011111"; -- 0x009C + when 000157 => D <= "10111101"; -- 0x009D + when 000158 => D <= "00000001"; -- 0x009E + when 000159 => D <= "10111111"; -- 0x009F + when 000160 => D <= "00000000"; -- 0x00A0 + when 000161 => D <= "11110101"; -- 0x00A1 + when 000162 => D <= "00010100"; -- 0x00A2 + when 000163 => D <= "00000010"; -- 0x00A3 + when 000164 => D <= "11100101"; -- 0x00A4 + when 000165 => D <= "10101100"; -- 0x00A5 + when 000166 => D <= "00010111"; -- 0x00A6 + when 000167 => D <= "10010110"; -- 0x00A7 + when 000168 => D <= "10101101"; -- 0x00A8 + when 000169 => D <= "00100111"; -- 0x00A9 + when 000170 => D <= "00111001"; -- 0x00AA + when 000171 => D <= "11010101"; -- 0x00AB + when 000172 => D <= "10000011"; -- 0x00AC + when 000173 => D <= "00110100"; -- 0x00AD + when 000174 => D <= "01111000"; -- 0x00AE + when 000175 => D <= "11111010"; -- 0x00AF + when 000176 => D <= "00111001"; -- 0x00B0 + when 000177 => D <= "11111011"; -- 0x00B1 + when 000178 => D <= "10101000"; -- 0x00B2 + when 000179 => D <= "10000000"; -- 0x00B3 + when 000180 => D <= "00110111"; -- 0x00B4 + when 000181 => D <= "01011100"; -- 0x00B5 + when 000182 => D <= "11000110"; -- 0x00B6 + when 000183 => D <= "11000010"; -- 0x00B7 + when 000184 => D <= "00100011"; -- 0x00B8 + when 000185 => D <= "00000001"; -- 0x00B9 + when 000186 => D <= "10111000"; -- 0x00BA + when 000187 => D <= "00111011"; -- 0x00BB + when 000188 => D <= "01000000"; -- 0x00BC + when 000189 => D <= "10100000"; -- 0x00BD + when 000190 => D <= "00100111"; -- 0x00BE + when 000191 => D <= "00111001"; -- 0x00BF + when 000192 => D <= "00000100"; -- 0x00C0 + when 000193 => D <= "11001011"; -- 0x00C1 + when 000194 => D <= "11111101"; -- 0x00C2 + when 000195 => D <= "00111001"; -- 0x00C3 + when 000196 => D <= "11111110"; -- 0x00C4 + when 000197 => D <= "10101000"; -- 0x00C5 + when 000198 => D <= "10000000"; -- 0x00C6 + when 000199 => D <= "00110111"; -- 0x00C7 + when 000200 => D <= "01011111"; -- 0x00C8 + when 000201 => D <= "10010110"; -- 0x00C9 + when 000202 => D <= "10111000"; -- 0x00CA + when 000203 => D <= "11111010"; -- 0x00CB + when 000204 => D <= "00111001"; -- 0x00CC + when 000205 => D <= "11111011"; -- 0x00CD + when 000206 => D <= "10101000"; -- 0x00CE + when 000207 => D <= "10000000"; -- 0x00CF + when 000208 => D <= "00110111"; -- 0x00D0 + when 000209 => D <= "01001100"; -- 0x00D1 + when 000210 => D <= "00110111"; -- 0x00D2 + when 000211 => D <= "10010000"; -- 0x00D3 + when 000212 => D <= "11111101"; -- 0x00D4 + when 000213 => D <= "00111001"; -- 0x00D5 + when 000214 => D <= "11111110"; -- 0x00D6 + when 000215 => D <= "10101000"; -- 0x00D7 + when 000216 => D <= "10000000"; -- 0x00D8 + when 000217 => D <= "00110111"; -- 0x00D9 + when 000218 => D <= "01001111"; -- 0x00DA + when 000219 => D <= "00110111"; -- 0x00DB + when 000220 => D <= "10010000"; -- 0x00DC + when 000221 => D <= "11111011"; -- 0x00DD + when 000222 => D <= "00000011"; -- 0x00DE + when 000223 => D <= "00000101"; -- 0x00DF + when 000224 => D <= "10101011"; -- 0x00E0 + when 000225 => D <= "11100110"; -- 0x00E1 + when 000226 => D <= "11101110"; -- 0x00E2 + when 000227 => D <= "00000011"; -- 0x00E3 + when 000228 => D <= "00000110"; -- 0x00E4 + when 000229 => D <= "10101011"; -- 0x00E5 + when 000230 => D <= "00011010"; -- 0x00E6 + when 000231 => D <= "11111010"; -- 0x00E7 + when 000232 => D <= "00000011"; -- 0x00E8 + when 000233 => D <= "11111100"; -- 0x00E9 + when 000234 => D <= "10010110"; -- 0x00EA + when 000235 => D <= "11101110"; -- 0x00EB + when 000236 => D <= "10111010"; -- 0x00EC + when 000237 => D <= "00000001"; -- 0x00ED + when 000238 => D <= "00000100"; -- 0x00EE + when 000239 => D <= "10001110"; -- 0x00EF + when 000240 => D <= "00100111"; -- 0x00F0 + when 000241 => D <= "00111001"; -- 0x00F1 + when 000242 => D <= "11111001"; -- 0x00F2 + when 000243 => D <= "01010011"; -- 0x00F3 + when 000244 => D <= "11111000"; -- 0x00F4 + when 000245 => D <= "00000011"; -- 0x00F5 + when 000246 => D <= "00000011"; -- 0x00F6 + when 000247 => D <= "10101001"; -- 0x00F7 + when 000248 => D <= "10000001"; -- 0x00F8 + when 000249 => D <= "00000011"; -- 0x00F9 + when 000250 => D <= "11111100"; -- 0x00FA + when 000251 => D <= "11100110"; -- 0x00FB + when 000252 => D <= "11111111"; -- 0x00FC + when 000253 => D <= "00100100"; -- 0x00FD + when 000254 => D <= "00101011"; -- 0x00FE + when 000255 => D <= "11001001"; -- 0x00FF + when 000256 => D <= "11001001"; -- 0x0100 + when 000257 => D <= "10000001"; -- 0x0101 + when 000258 => D <= "10101010"; -- 0x0102 + when 000259 => D <= "11111001"; -- 0x0103 + when 000260 => D <= "11000101"; -- 0x0104 + when 000261 => D <= "10101000"; -- 0x0105 + when 000262 => D <= "00011000"; -- 0x0106 + when 000263 => D <= "10000000"; -- 0x0107 + when 000264 => D <= "10101001"; -- 0x0108 + when 000265 => D <= "00011000"; -- 0x0109 + when 000266 => D <= "10000000"; -- 0x010A + when 000267 => D <= "10101010"; -- 0x010B + when 000268 => D <= "00011000"; -- 0x010C + when 000269 => D <= "10000000"; -- 0x010D + when 000270 => D <= "10101011"; -- 0x010E + when 000271 => D <= "11111011"; -- 0x010F + when 000272 => D <= "00000011"; -- 0x0110 + when 000273 => D <= "00000001"; -- 0x0111 + when 000274 => D <= "10101110"; -- 0x0112 + when 000275 => D <= "11111010"; -- 0x0113 + when 000276 => D <= "10101101"; -- 0x0114 + when 000277 => D <= "11100110"; -- 0x0115 + when 000278 => D <= "00100001"; -- 0x0116 + when 000279 => D <= "10111110"; -- 0x0117 + when 000280 => D <= "00000110"; -- 0x0118 + when 000281 => D <= "00011101"; -- 0x0119 + when 000282 => D <= "11111101"; -- 0x011A + when 000283 => D <= "00000011"; -- 0x011B + when 000284 => D <= "11111100"; -- 0x011C + when 000285 => D <= "10010110"; -- 0x011D + when 000286 => D <= "00100001"; -- 0x011E + when 000287 => D <= "10111101"; -- 0x011F + when 000288 => D <= "00000001"; -- 0x0120 + when 000289 => D <= "10111111"; -- 0x0121 + when 000290 => D <= "00000000"; -- 0x0122 + when 000291 => D <= "11110101"; -- 0x0123 + when 000292 => D <= "00010100"; -- 0x0124 + when 000293 => D <= "00000010"; -- 0x0125 + when 000294 => D <= "11100101"; -- 0x0126 + when 000295 => D <= "10101100"; -- 0x0127 + when 000296 => D <= "00010111"; -- 0x0128 + when 000297 => D <= "10010110"; -- 0x0129 + when 000298 => D <= "00101111"; -- 0x012A + when 000299 => D <= "00100111"; -- 0x012B + when 000300 => D <= "00111001"; -- 0x012C + when 000301 => D <= "11010101"; -- 0x012D + when 000302 => D <= "10000011"; -- 0x012E + when 000303 => D <= "00110100"; -- 0x012F + when 000304 => D <= "01111000"; -- 0x0130 + when 000305 => D <= "10111000"; -- 0x0131 + when 000306 => D <= "00111000"; -- 0x0132 + when 000307 => D <= "11110000"; -- 0x0133 + when 000308 => D <= "01101011"; -- 0x0134 + when 000309 => D <= "10010110"; -- 0x0135 + when 000310 => D <= "01000001"; -- 0x0136 + when 000311 => D <= "00011000"; -- 0x0137 + when 000312 => D <= "11110000"; -- 0x0138 + when 000313 => D <= "01101010"; -- 0x0139 + when 000314 => D <= "10010110"; -- 0x013A + when 000315 => D <= "01000001"; -- 0x013B + when 000316 => D <= "00011000"; -- 0x013C + when 000317 => D <= "11110000"; -- 0x013D + when 000318 => D <= "01011100"; -- 0x013E + when 000319 => D <= "10010110"; -- 0x013F + when 000320 => D <= "01010001"; -- 0x0140 + when 000321 => D <= "10111000"; -- 0x0141 + when 000322 => D <= "00111000"; -- 0x0142 + when 000323 => D <= "11110000"; -- 0x0143 + when 000324 => D <= "01101110"; -- 0x0144 + when 000325 => D <= "10010110"; -- 0x0145 + when 000326 => D <= "01010111"; -- 0x0146 + when 000327 => D <= "00011000"; -- 0x0147 + when 000328 => D <= "11110000"; -- 0x0148 + when 000329 => D <= "01101101"; -- 0x0149 + when 000330 => D <= "10010110"; -- 0x014A + when 000331 => D <= "01010111"; -- 0x014B + when 000332 => D <= "00011000"; -- 0x014C + when 000333 => D <= "11110000"; -- 0x014D + when 000334 => D <= "01011111"; -- 0x014E + when 000335 => D <= "11000110"; -- 0x014F + when 000336 => D <= "01010111"; -- 0x0150 + when 000337 => D <= "00100011"; -- 0x0151 + when 000338 => D <= "00000010"; -- 0x0152 + when 000339 => D <= "10111000"; -- 0x0153 + when 000340 => D <= "00111011"; -- 0x0154 + when 000341 => D <= "01000000"; -- 0x0155 + when 000342 => D <= "10100000"; -- 0x0156 + when 000343 => D <= "11111010"; -- 0x0157 + when 000344 => D <= "00111001"; -- 0x0158 + when 000345 => D <= "11111011"; -- 0x0159 + when 000346 => D <= "10101000"; -- 0x015A + when 000347 => D <= "10000000"; -- 0x015B + when 000348 => D <= "01001100"; -- 0x015C + when 000349 => D <= "10010000"; -- 0x015D + when 000350 => D <= "11111101"; -- 0x015E + when 000351 => D <= "00111001"; -- 0x015F + when 000352 => D <= "11111110"; -- 0x0160 + when 000353 => D <= "10101000"; -- 0x0161 + when 000354 => D <= "10000000"; -- 0x0162 + when 000355 => D <= "01001111"; -- 0x0163 + when 000356 => D <= "10010000"; -- 0x0164 + when 000357 => D <= "11111011"; -- 0x0165 + when 000358 => D <= "00000011"; -- 0x0166 + when 000359 => D <= "00000101"; -- 0x0167 + when 000360 => D <= "10101011"; -- 0x0168 + when 000361 => D <= "11100110"; -- 0x0169 + when 000362 => D <= "00001111"; -- 0x016A + when 000363 => D <= "00000011"; -- 0x016B + when 000364 => D <= "00000110"; -- 0x016C + when 000365 => D <= "10101011"; -- 0x016D + when 000366 => D <= "00011010"; -- 0x016E + when 000367 => D <= "11111010"; -- 0x016F + when 000368 => D <= "00000011"; -- 0x0170 + when 000369 => D <= "11111100"; -- 0x0171 + when 000370 => D <= "10010110"; -- 0x0172 + when 000371 => D <= "01110110"; -- 0x0173 + when 000372 => D <= "10111010"; -- 0x0174 + when 000373 => D <= "00000001"; -- 0x0175 + when 000374 => D <= "00100100"; -- 0x0176 + when 000375 => D <= "00001111"; -- 0x0177 + when 000376 => D <= "11111001"; -- 0x0178 + when 000377 => D <= "10101000"; -- 0x0179 + when 000378 => D <= "11000110"; -- 0x017A + when 000379 => D <= "10001001"; -- 0x017B + when 000380 => D <= "00000011"; -- 0x017C + when 000381 => D <= "11111100"; -- 0x017D + when 000382 => D <= "11110110"; -- 0x017E + when 000383 => D <= "10001010"; -- 0x017F + when 000384 => D <= "10010111"; -- 0x0180 + when 000385 => D <= "11111100"; -- 0x0181 + when 000386 => D <= "11110111"; -- 0x0182 + when 000387 => D <= "10101100"; -- 0x0183 + when 000388 => D <= "11111111"; -- 0x0184 + when 000389 => D <= "11110111"; -- 0x0185 + when 000390 => D <= "10101111"; -- 0x0186 + when 000391 => D <= "11101000"; -- 0x0187 + when 000392 => D <= "10000000"; -- 0x0188 + when 000393 => D <= "10000011"; -- 0x0189 + when 000394 => D <= "00010111"; -- 0x018A + when 000395 => D <= "10101000"; -- 0x018B + when 000396 => D <= "11111100"; -- 0x018C + when 000397 => D <= "01010011"; -- 0x018D + when 000398 => D <= "00001111"; -- 0x018E + when 000399 => D <= "01000111"; -- 0x018F + when 000400 => D <= "00101100"; -- 0x0190 + when 000401 => D <= "01010011"; -- 0x0191 + when 000402 => D <= "11110000"; -- 0x0192 + when 000403 => D <= "01000111"; -- 0x0193 + when 000404 => D <= "10101111"; -- 0x0194 + when 000405 => D <= "00100100"; -- 0x0195 + when 000406 => D <= "10000111"; -- 0x0196 + when 000407 => D <= "10111001"; -- 0x0197 + when 000408 => D <= "11100001"; -- 0x0198 + when 000409 => D <= "11111000"; -- 0x0199 + when 000410 => D <= "10010001"; -- 0x019A + when 000411 => D <= "01110100"; -- 0x019B + when 000412 => D <= "00001110"; -- 0x019C + when 000413 => D <= "00010100"; -- 0x019D + when 000414 => D <= "01110001"; -- 0x019E + when 000415 => D <= "10000011"; -- 0x019F + when 000416 => D <= "11010101"; -- 0x01A0 + when 000417 => D <= "10111001"; -- 0x01A1 + when 000418 => D <= "00000000"; -- 0x01A2 + when 000419 => D <= "00100111"; -- 0x01A3 + when 000420 => D <= "00111001"; -- 0x01A4 + when 000421 => D <= "10000001"; -- 0x01A5 + when 000422 => D <= "10010110"; -- 0x01A6 + when 000423 => D <= "10110010"; -- 0x01A7 + when 000424 => D <= "11111001"; -- 0x01A8 + when 000425 => D <= "01010011"; -- 0x01A9 + when 000426 => D <= "11111000"; -- 0x01AA + when 000427 => D <= "00000011"; -- 0x01AB + when 000428 => D <= "00001000"; -- 0x01AC + when 000429 => D <= "10101001"; -- 0x01AD + when 000430 => D <= "10010110"; -- 0x01AE + when 000431 => D <= "10100101"; -- 0x01AF + when 000432 => D <= "01000100"; -- 0x01B0 + when 000433 => D <= "00011000"; -- 0x01B1 + when 000434 => D <= "11110101"; -- 0x01B2 + when 000435 => D <= "00010100"; -- 0x01B3 + when 000436 => D <= "00000110"; -- 0x01B4 + when 000437 => D <= "11100101"; -- 0x01B5 + when 000438 => D <= "11110010"; -- 0x01B6 + when 000439 => D <= "10101000"; -- 0x01B7 + when 000440 => D <= "10111000"; -- 0x01B8 + when 000441 => D <= "00111011"; -- 0x01B9 + when 000442 => D <= "10110000"; -- 0x01BA + when 000443 => D <= "00000000"; -- 0x01BB + when 000444 => D <= "00011001"; -- 0x01BC + when 000445 => D <= "11110101"; -- 0x01BD + when 000446 => D <= "00010100"; -- 0x01BE + when 000447 => D <= "00001000"; -- 0x01BF + when 000448 => D <= "11100101"; -- 0x01C0 + when 000449 => D <= "00010100"; -- 0x01C1 + when 000450 => D <= "11110000"; -- 0x01C2 + when 000451 => D <= "10111000"; -- 0x01C3 + when 000452 => D <= "00111011"; -- 0x01C4 + when 000453 => D <= "11110000"; -- 0x01C5 + when 000454 => D <= "10010110"; -- 0x01C6 + when 000455 => D <= "11010100"; -- 0x01C7 + when 000456 => D <= "11111001"; -- 0x01C8 + when 000457 => D <= "01010011"; -- 0x01C9 + when 000458 => D <= "11111000"; -- 0x01CA + when 000459 => D <= "10101001"; -- 0x01CB + when 000460 => D <= "10000001"; -- 0x01CC + when 000461 => D <= "01010011"; -- 0x01CD + when 000462 => D <= "00001111"; -- 0x01CE + when 000463 => D <= "10101100"; -- 0x01CF + when 000464 => D <= "01010100"; -- 0x01D0 + when 000465 => D <= "11111111"; -- 0x01D1 + when 000466 => D <= "00100100"; -- 0x01D2 + when 000467 => D <= "11100000"; -- 0x01D3 + when 000468 => D <= "10111000"; -- 0x01D4 + when 000469 => D <= "00111110"; -- 0x01D5 + when 000470 => D <= "11110000"; -- 0x01D6 + when 000471 => D <= "00010111"; -- 0x01D7 + when 000472 => D <= "10010110"; -- 0x01D8 + when 000473 => D <= "11001000"; -- 0x01D9 + when 000474 => D <= "11111001"; -- 0x01DA + when 000475 => D <= "01010011"; -- 0x01DB + when 000476 => D <= "11111000"; -- 0x01DC + when 000477 => D <= "10100000"; -- 0x01DD + when 000478 => D <= "00100100"; -- 0x01DE + when 000479 => D <= "10101000"; -- 0x01DF + when 000480 => D <= "10111010"; -- 0x01E0 + when 000481 => D <= "00000000"; -- 0x01E1 + when 000482 => D <= "10111011"; -- 0x01E2 + when 000483 => D <= "00000000"; -- 0x01E3 + when 000484 => D <= "01010100"; -- 0x01E4 + when 000485 => D <= "10111001"; -- 0x01E5 + when 000486 => D <= "11000110"; -- 0x01E6 + when 000487 => D <= "11101110"; -- 0x01E7 + when 000488 => D <= "11110101"; -- 0x01E8 + when 000489 => D <= "00010100"; -- 0x01E9 + when 000490 => D <= "00000100"; -- 0x01EA + when 000491 => D <= "11100101"; -- 0x01EB + when 000492 => D <= "00100100"; -- 0x01EC + when 000493 => D <= "11100100"; -- 0x01ED + when 000494 => D <= "11101100"; -- 0x01EE + when 000495 => D <= "11100100"; -- 0x01EF + when 000496 => D <= "11111010"; -- 0x01F0 + when 000497 => D <= "01110100"; -- 0x01F1 + when 000498 => D <= "01100001"; -- 0x01F2 + when 000499 => D <= "11111011"; -- 0x01F3 + when 000500 => D <= "01110100"; -- 0x01F4 + when 000501 => D <= "00100100"; -- 0x01F5 + when 000502 => D <= "11110101"; -- 0x01F6 + when 000503 => D <= "00010100"; -- 0x01F7 + when 000504 => D <= "00001010"; -- 0x01F8 + when 000505 => D <= "11100101"; -- 0x01F9 + when 000506 => D <= "01110100"; -- 0x01FA + when 000507 => D <= "00001110"; -- 0x01FB + when 000508 => D <= "11001001"; -- 0x01FC + when 000509 => D <= "00010100"; -- 0x01FD + when 000510 => D <= "01110001"; -- 0x01FE + when 000511 => D <= "10111000"; -- 0x01FF + when 000512 => D <= "00111011"; -- 0x0200 + when 000513 => D <= "11110000"; -- 0x0201 + when 000514 => D <= "10010110"; -- 0x0202 + when 000515 => D <= "00000110"; -- 0x0203 + when 000516 => D <= "00100100"; -- 0x0204 + when 000517 => D <= "10101000"; -- 0x0205 + when 000518 => D <= "10111000"; -- 0x0206 + when 000519 => D <= "00111100"; -- 0x0207 + when 000520 => D <= "11110000"; -- 0x0208 + when 000521 => D <= "01101001"; -- 0x0209 + when 000522 => D <= "11100110"; -- 0x020A + when 000523 => D <= "00010110"; -- 0x020B + when 000524 => D <= "10111000"; -- 0x020C + when 000525 => D <= "00111110"; -- 0x020D + when 000526 => D <= "11110000"; -- 0x020E + when 000527 => D <= "00010111"; -- 0x020F + when 000528 => D <= "10010110"; -- 0x0210 + when 000529 => D <= "00010110"; -- 0x0211 + when 000530 => D <= "11111001"; -- 0x0212 + when 000531 => D <= "01010011"; -- 0x0213 + when 000532 => D <= "11111000"; -- 0x0214 + when 000533 => D <= "10100000"; -- 0x0215 + when 000534 => D <= "00100100"; -- 0x0216 + when 000535 => D <= "10101000"; -- 0x0217 + when 000536 => D <= "10000001"; -- 0x0218 + when 000537 => D <= "10010110"; -- 0x0219 + when 000538 => D <= "00100100"; -- 0x021A + when 000539 => D <= "11111001"; -- 0x021B + when 000540 => D <= "01010011"; -- 0x021C + when 000541 => D <= "11111000"; -- 0x021D + when 000542 => D <= "00000011"; -- 0x021E + when 000543 => D <= "00001000"; -- 0x021F + when 000544 => D <= "10101001"; -- 0x0220 + when 000545 => D <= "10010110"; -- 0x0221 + when 000546 => D <= "00011000"; -- 0x0222 + when 000547 => D <= "10000011"; -- 0x0223 + when 000548 => D <= "11110010"; -- 0x0224 + when 000549 => D <= "00101000"; -- 0x0225 + when 000550 => D <= "01000100"; -- 0x0226 + when 000551 => D <= "00011011"; -- 0x0227 + when 000552 => D <= "01010011"; -- 0x0228 + when 000553 => D <= "00001111"; -- 0x0229 + when 000554 => D <= "10101100"; -- 0x022A + when 000555 => D <= "01010100"; -- 0x022B + when 000556 => D <= "11111111"; -- 0x022C + when 000557 => D <= "11111101"; -- 0x022D + when 000558 => D <= "10101000"; -- 0x022E + when 000559 => D <= "00100011"; -- 0x022F + when 000560 => D <= "00000001"; -- 0x0230 + when 000561 => D <= "11100111"; -- 0x0231 + when 000562 => D <= "11101000"; -- 0x0232 + when 000563 => D <= "00110001"; -- 0x0233 + when 000564 => D <= "10101010"; -- 0x0234 + when 000565 => D <= "11111110"; -- 0x0235 + when 000566 => D <= "00111001"; -- 0x0236 + when 000567 => D <= "11111111"; -- 0x0237 + when 000568 => D <= "10101000"; -- 0x0238 + when 000569 => D <= "10000000"; -- 0x0239 + when 000570 => D <= "01001010"; -- 0x023A + when 000571 => D <= "10010000"; -- 0x023B + when 000572 => D <= "00100111"; -- 0x023C + when 000573 => D <= "00111001"; -- 0x023D + when 000574 => D <= "10111010"; -- 0x023E + when 000575 => D <= "00000000"; -- 0x023F + when 000576 => D <= "10111011"; -- 0x0240 + when 000577 => D <= "00000000"; -- 0x0241 + when 000578 => D <= "01010100"; -- 0x0242 + when 000579 => D <= "10111001"; -- 0x0243 + when 000580 => D <= "11000110"; -- 0x0244 + when 000581 => D <= "01011100"; -- 0x0245 + when 000582 => D <= "00100011"; -- 0x0246 + when 000583 => D <= "11111000"; -- 0x0247 + when 000584 => D <= "01011001"; -- 0x0248 + when 000585 => D <= "00000011"; -- 0x0249 + when 000586 => D <= "00000001"; -- 0x024A + when 000587 => D <= "10101001"; -- 0x024B + when 000588 => D <= "10000001"; -- 0x024C + when 000589 => D <= "00000111"; -- 0x024D + when 000590 => D <= "10010001"; -- 0x024E + when 000591 => D <= "11000110"; -- 0x024F + when 000592 => D <= "01010111"; -- 0x0250 + when 000593 => D <= "11110101"; -- 0x0251 + when 000594 => D <= "00010100"; -- 0x0252 + when 000595 => D <= "00000100"; -- 0x0253 + when 000596 => D <= "11100101"; -- 0x0254 + when 000597 => D <= "01000100"; -- 0x0255 + when 000598 => D <= "01000010"; -- 0x0256 + when 000599 => D <= "11001001"; -- 0x0257 + when 000600 => D <= "00100111"; -- 0x0258 + when 000601 => D <= "10010001"; -- 0x0259 + when 000602 => D <= "01000100"; -- 0x025A + when 000603 => D <= "00011011"; -- 0x025B + when 000604 => D <= "11111010"; -- 0x025C + when 000605 => D <= "01110100"; -- 0x025D + when 000606 => D <= "01100001"; -- 0x025E + when 000607 => D <= "11111011"; -- 0x025F + when 000608 => D <= "01110100"; -- 0x0260 + when 000609 => D <= "00100100"; -- 0x0261 + when 000610 => D <= "11110101"; -- 0x0262 + when 000611 => D <= "00010100"; -- 0x0263 + when 000612 => D <= "00001100"; -- 0x0264 + when 000613 => D <= "11100101"; -- 0x0265 + when 000614 => D <= "11111101"; -- 0x0266 + when 000615 => D <= "00010111"; -- 0x0267 + when 000616 => D <= "10101010"; -- 0x0268 + when 000617 => D <= "00100011"; -- 0x0269 + when 000618 => D <= "00000001"; -- 0x026A + when 000619 => D <= "01000100"; -- 0x026B + when 000620 => D <= "01101110"; -- 0x026C + when 000621 => D <= "11100111"; -- 0x026D + when 000622 => D <= "11101010"; -- 0x026E + when 000623 => D <= "01101101"; -- 0x026F + when 000624 => D <= "10101010"; -- 0x0270 + when 000625 => D <= "11111111"; -- 0x0271 + when 000626 => D <= "10101000"; -- 0x0272 + when 000627 => D <= "11111110"; -- 0x0273 + when 000628 => D <= "00111001"; -- 0x0274 + when 000629 => D <= "10000000"; -- 0x0275 + when 000630 => D <= "10101011"; -- 0x0276 + when 000631 => D <= "01001010"; -- 0x0277 + when 000632 => D <= "10010000"; -- 0x0278 + when 000633 => D <= "11111011"; -- 0x0279 + when 000634 => D <= "00110111"; -- 0x027A + when 000635 => D <= "01011010"; -- 0x027B + when 000636 => D <= "10010110"; -- 0x027C + when 000637 => D <= "10001100"; -- 0x027D + when 000638 => D <= "11101100"; -- 0x027E + when 000639 => D <= "00111100"; -- 0x027F + when 000640 => D <= "11111010"; -- 0x0280 + when 000641 => D <= "10000000"; -- 0x0281 + when 000642 => D <= "00110111"; -- 0x0282 + when 000643 => D <= "01001010"; -- 0x0283 + when 000644 => D <= "00110111"; -- 0x0284 + when 000645 => D <= "10010000"; -- 0x0285 + when 000646 => D <= "00100111"; -- 0x0286 + when 000647 => D <= "00111001"; -- 0x0287 + when 000648 => D <= "01110100"; -- 0x0288 + when 000649 => D <= "00001110"; -- 0x0289 + when 000650 => D <= "01000100"; -- 0x028A + when 000651 => D <= "00011011"; -- 0x028B + when 000652 => D <= "00100111"; -- 0x028C + when 000653 => D <= "00111001"; -- 0x028D + when 000654 => D <= "00100011"; -- 0x028E + when 000655 => D <= "11111000"; -- 0x028F + when 000656 => D <= "01011001"; -- 0x0290 + when 000657 => D <= "10101001"; -- 0x0291 + when 000658 => D <= "10000001"; -- 0x0292 + when 000659 => D <= "10101011"; -- 0x0293 + when 000660 => D <= "11111110"; -- 0x0294 + when 000661 => D <= "00111001"; -- 0x0295 + when 000662 => D <= "11111011"; -- 0x0296 + when 000663 => D <= "01010011"; -- 0x0297 + when 000664 => D <= "00110000"; -- 0x0298 + when 000665 => D <= "11000110"; -- 0x0299 + when 000666 => D <= "01111110"; -- 0x029A + when 000667 => D <= "00101000"; -- 0x029B + when 000668 => D <= "10101011"; -- 0x029C + when 000669 => D <= "11111000"; -- 0x029D + when 000670 => D <= "10111000"; -- 0x029E + when 000671 => D <= "00110111"; -- 0x029F + when 000672 => D <= "10100000"; -- 0x02A0 + when 000673 => D <= "00011000"; -- 0x02A1 + when 000674 => D <= "11111111"; -- 0x02A2 + when 000675 => D <= "00110111"; -- 0x02A3 + when 000676 => D <= "00010111"; -- 0x02A4 + when 000677 => D <= "10100000"; -- 0x02A5 + when 000678 => D <= "00011000"; -- 0x02A6 + when 000679 => D <= "11111110"; -- 0x02A7 + when 000680 => D <= "00110111"; -- 0x02A8 + when 000681 => D <= "00010111"; -- 0x02A9 + when 000682 => D <= "10100000"; -- 0x02AA + when 000683 => D <= "11111101"; -- 0x02AB + when 000684 => D <= "10101000"; -- 0x02AC + when 000685 => D <= "00100011"; -- 0x02AD + when 000686 => D <= "00000001"; -- 0x02AE + when 000687 => D <= "11100111"; -- 0x02AF + when 000688 => D <= "11101000"; -- 0x02B0 + when 000689 => D <= "10101111"; -- 0x02B1 + when 000690 => D <= "10111000"; -- 0x02B2 + when 000691 => D <= "00111010"; -- 0x02B3 + when 000692 => D <= "10100000"; -- 0x02B4 + when 000693 => D <= "11111011"; -- 0x02B5 + when 000694 => D <= "10101000"; -- 0x02B6 + when 000695 => D <= "01000100"; -- 0x02B7 + when 000696 => D <= "01111110"; -- 0x02B8 + when 000697 => D <= "00100011"; -- 0x02B9 + when 000698 => D <= "11111000"; -- 0x02BA + when 000699 => D <= "01011001"; -- 0x02BB + when 000700 => D <= "00000011"; -- 0x02BC + when 000701 => D <= "00000101"; -- 0x02BD + when 000702 => D <= "10101001"; -- 0x02BE + when 000703 => D <= "10000001"; -- 0x02BF + when 000704 => D <= "11000110"; -- 0x02C0 + when 000705 => D <= "11011011"; -- 0x02C1 + when 000706 => D <= "11110010"; -- 0x02C2 + when 000707 => D <= "11001000"; -- 0x02C3 + when 000708 => D <= "00011010"; -- 0x02C4 + when 000709 => D <= "00000111"; -- 0x02C5 + when 000710 => D <= "01000100"; -- 0x02C6 + when 000711 => D <= "11001010"; -- 0x02C7 + when 000712 => D <= "11001010"; -- 0x02C8 + when 000713 => D <= "00010111"; -- 0x02C9 + when 000714 => D <= "10010001"; -- 0x02CA + when 000715 => D <= "00011001"; -- 0x02CB + when 000716 => D <= "10000001"; -- 0x02CC + when 000717 => D <= "10010110"; -- 0x02CD + when 000718 => D <= "11010000"; -- 0x02CE + when 000719 => D <= "10000011"; -- 0x02CF + when 000720 => D <= "11110010"; -- 0x02D0 + when 000721 => D <= "11010110"; -- 0x02D1 + when 000722 => D <= "00011011"; -- 0x02D2 + when 000723 => D <= "00000111"; -- 0x02D3 + when 000724 => D <= "01000100"; -- 0x02D4 + when 000725 => D <= "11011000"; -- 0x02D5 + when 000726 => D <= "11001011"; -- 0x02D6 + when 000727 => D <= "00010111"; -- 0x02D7 + when 000728 => D <= "10010001"; -- 0x02D8 + when 000729 => D <= "00100111"; -- 0x02D9 + when 000730 => D <= "10000011"; -- 0x02DA + when 000731 => D <= "00011001"; -- 0x02DB + when 000732 => D <= "10000001"; -- 0x02DC + when 000733 => D <= "10010110"; -- 0x02DD + when 000734 => D <= "11010000"; -- 0x02DE + when 000735 => D <= "00100011"; -- 0x02DF + when 000736 => D <= "11111111"; -- 0x02E0 + when 000737 => D <= "10000011"; -- 0x02E1 + when 000738 => D <= "10111000"; -- 0x02E2 + when 000739 => D <= "00000000"; -- 0x02E3 + when 000740 => D <= "10111011"; -- 0x02E4 + when 000741 => D <= "00000100"; -- 0x02E5 + when 000742 => D <= "11111011"; -- 0x02E6 + when 000743 => D <= "00000111"; -- 0x02E7 + when 000744 => D <= "00111001"; -- 0x02E8 + when 000745 => D <= "00100111"; -- 0x02E9 + when 000746 => D <= "10010000"; -- 0x02EA + when 000747 => D <= "11101000"; -- 0x02EB + when 000748 => D <= "11101010"; -- 0x02EC + when 000749 => D <= "11101011"; -- 0x02ED + when 000750 => D <= "11100110"; -- 0x02EE + when 000751 => D <= "10111000"; -- 0x02EF + when 000752 => D <= "00000000"; -- 0x02F0 + when 000753 => D <= "10111011"; -- 0x02F1 + when 000754 => D <= "00000011"; -- 0x02F2 + when 000755 => D <= "11111011"; -- 0x02F3 + when 000756 => D <= "00111001"; -- 0x02F4 + when 000757 => D <= "00100011"; -- 0x02F5 + when 000758 => D <= "11111111"; -- 0x02F6 + when 000759 => D <= "10010000"; -- 0x02F7 + when 000760 => D <= "11101000"; -- 0x02F8 + when 000761 => D <= "11110111"; -- 0x02F9 + when 000762 => D <= "11101011"; -- 0x02FA + when 000763 => D <= "11110011"; -- 0x02FB + when 000764 => D <= "00100111"; -- 0x02FC + when 000765 => D <= "00111001"; -- 0x02FD + when 000766 => D <= "10000011"; -- 0x02FE + when 000767 => D <= "11111001"; -- 0x02FF + when 000768 => D <= "01010011"; -- 0x0300 + when 000769 => D <= "11111000"; -- 0x0301 + when 000770 => D <= "00000011"; -- 0x0302 + when 000771 => D <= "00000010"; -- 0x0303 + when 000772 => D <= "10101001"; -- 0x0304 + when 000773 => D <= "10000001"; -- 0x0305 + when 000774 => D <= "10101101"; -- 0x0306 + when 000775 => D <= "00011001"; -- 0x0307 + when 000776 => D <= "10000001"; -- 0x0308 + when 000777 => D <= "10101110"; -- 0x0309 + when 000778 => D <= "00011001"; -- 0x030A + when 000779 => D <= "10000001"; -- 0x030B + when 000780 => D <= "10101111"; -- 0x030C + when 000781 => D <= "10000011"; -- 0x030D + when 000782 => D <= "11111001"; -- 0x030E + when 000783 => D <= "01010011"; -- 0x030F + when 000784 => D <= "11111000"; -- 0x0310 + when 000785 => D <= "00000011"; -- 0x0311 + when 000786 => D <= "00000010"; -- 0x0312 + when 000787 => D <= "10101001"; -- 0x0313 + when 000788 => D <= "11111101"; -- 0x0314 + when 000789 => D <= "10010001"; -- 0x0315 + when 000790 => D <= "00011001"; -- 0x0316 + when 000791 => D <= "11111110"; -- 0x0317 + when 000792 => D <= "10010001"; -- 0x0318 + when 000793 => D <= "00011001"; -- 0x0319 + when 000794 => D <= "11111111"; -- 0x031A + when 000795 => D <= "10010001"; -- 0x031B + when 000796 => D <= "10000011"; -- 0x031C + when 000797 => D <= "01110100"; -- 0x031D + when 000798 => D <= "00001110"; -- 0x031E + when 000799 => D <= "00100111"; -- 0x031F + when 000800 => D <= "10010001"; -- 0x0320 + when 000801 => D <= "00011001"; -- 0x0321 + when 000802 => D <= "10010001"; -- 0x0322 + when 000803 => D <= "10000011"; -- 0x0323 + when 000804 => D <= "10111000"; -- 0x0324 + when 000805 => D <= "00101110"; -- 0x0325 + when 000806 => D <= "01101101"; -- 0x0326 + when 000807 => D <= "10101101"; -- 0x0327 + when 000808 => D <= "11110010"; -- 0x0328 + when 000809 => D <= "01001100"; -- 0x0329 + when 000810 => D <= "01010011"; -- 0x032A + when 000811 => D <= "11111000"; -- 0x032B + when 000812 => D <= "10010110"; -- 0x032C + when 000813 => D <= "00101111"; -- 0x032D + when 000814 => D <= "10000011"; -- 0x032E + when 000815 => D <= "11111101"; -- 0x032F + when 000816 => D <= "00000011"; -- 0x0330 + when 000817 => D <= "11111000"; -- 0x0331 + when 000818 => D <= "10101101"; -- 0x0332 + when 000819 => D <= "00011111"; -- 0x0333 + when 000820 => D <= "11111111"; -- 0x0334 + when 000821 => D <= "10010110"; -- 0x0335 + when 000822 => D <= "01000000"; -- 0x0336 + when 000823 => D <= "10111111"; -- 0x0337 + when 000824 => D <= "00000110"; -- 0x0338 + when 000825 => D <= "00011110"; -- 0x0339 + when 000826 => D <= "11111110"; -- 0x033A + when 000827 => D <= "00110111"; -- 0x033B + when 000828 => D <= "00010111"; -- 0x033C + when 000829 => D <= "01100000"; -- 0x033D + when 000830 => D <= "11100110"; -- 0x033E + when 000831 => D <= "01000011"; -- 0x033F + when 000832 => D <= "11111101"; -- 0x0340 + when 000833 => D <= "01100100"; -- 0x0341 + when 000834 => D <= "00101010"; -- 0x0342 + when 000835 => D <= "10111110"; -- 0x0343 + when 000836 => D <= "00000001"; -- 0x0344 + when 000837 => D <= "01100100"; -- 0x0345 + when 000838 => D <= "01000000"; -- 0x0346 + when 000839 => D <= "01010011"; -- 0x0347 + when 000840 => D <= "11111000"; -- 0x0348 + when 000841 => D <= "10010110"; -- 0x0349 + when 000842 => D <= "01001100"; -- 0x034A + when 000843 => D <= "10000011"; -- 0x034B + when 000844 => D <= "11111101"; -- 0x034C + when 000845 => D <= "00000011"; -- 0x034D + when 000846 => D <= "00001000"; -- 0x034E + when 000847 => D <= "10101101"; -- 0x034F + when 000848 => D <= "11001111"; -- 0x0350 + when 000849 => D <= "11111111"; -- 0x0351 + when 000850 => D <= "00000011"; -- 0x0352 + when 000851 => D <= "11111010"; -- 0x0353 + when 000852 => D <= "11100110"; -- 0x0354 + when 000853 => D <= "01011001"; -- 0x0355 + when 000854 => D <= "11111101"; -- 0x0356 + when 000855 => D <= "01100100"; -- 0x0357 + when 000856 => D <= "01000111"; -- 0x0358 + when 000857 => D <= "10111111"; -- 0x0359 + when 000858 => D <= "11111111"; -- 0x035A + when 000859 => D <= "11101110"; -- 0x035B + when 000860 => D <= "01010110"; -- 0x035C + when 000861 => D <= "11110000"; -- 0x035D + when 000862 => D <= "10101110"; -- 0x035E + when 000863 => D <= "01100100"; -- 0x035F + when 000864 => D <= "01010110"; -- 0x0360 + when 000865 => D <= "11110010"; -- 0x0361 + when 000866 => D <= "10000101"; -- 0x0362 + when 000867 => D <= "10101000"; -- 0x0363 + when 000868 => D <= "11100111"; -- 0x0364 + when 000869 => D <= "11100111"; -- 0x0365 + when 000870 => D <= "01101000"; -- 0x0366 + when 000871 => D <= "10101000"; -- 0x0367 + when 000872 => D <= "01101111"; -- 0x0368 + when 000873 => D <= "10101111"; -- 0x0369 + when 000874 => D <= "11110110"; -- 0x036A + when 000875 => D <= "01110101"; -- 0x036B + when 000876 => D <= "10000011"; -- 0x036C + when 000877 => D <= "10101111"; -- 0x036D + when 000878 => D <= "11101110"; -- 0x036E + when 000879 => D <= "01110100"; -- 0x036F + when 000880 => D <= "10111000"; -- 0x0370 + when 000881 => D <= "00101110"; -- 0x0371 + when 000882 => D <= "11110000"; -- 0x0372 + when 000883 => D <= "10101110"; -- 0x0373 + when 000884 => D <= "10000011"; -- 0x0374 + when 000885 => D <= "00000011"; -- 0x0375 + when 000886 => D <= "00000110"; -- 0x0376 + when 000887 => D <= "10101111"; -- 0x0377 + when 000888 => D <= "00011110"; -- 0x0378 + when 000889 => D <= "11111110"; -- 0x0379 + when 000890 => D <= "10111000"; -- 0x037A + when 000891 => D <= "00101110"; -- 0x037B + when 000892 => D <= "00110111"; -- 0x037C + when 000893 => D <= "00010111"; -- 0x037D + when 000894 => D <= "01100000"; -- 0x037E + when 000895 => D <= "11100110"; -- 0x037F + when 000896 => D <= "10000010"; -- 0x0380 + when 000897 => D <= "10000011"; -- 0x0381 + when 000898 => D <= "10111110"; -- 0x0382 + when 000899 => D <= "00000001"; -- 0x0383 + when 000900 => D <= "10000011"; -- 0x0384 + when 000901 => D <= "00110111"; -- 0x0385 + when 000902 => D <= "00010111"; -- 0x0386 + when 000903 => D <= "10101000"; -- 0x0387 + when 000904 => D <= "11100111"; -- 0x0388 + when 000905 => D <= "11100111"; -- 0x0389 + when 000906 => D <= "01101000"; -- 0x038A + when 000907 => D <= "00110111"; -- 0x038B + when 000908 => D <= "00010111"; -- 0x038C + when 000909 => D <= "01101111"; -- 0x038D + when 000910 => D <= "11100110"; -- 0x038E + when 000911 => D <= "10010110"; -- 0x038F + when 000912 => D <= "10101111"; -- 0x0390 + when 000913 => D <= "00000011"; -- 0x0391 + when 000914 => D <= "11111010"; -- 0x0392 + when 000915 => D <= "11100110"; -- 0x0393 + when 000916 => D <= "01101101"; -- 0x0394 + when 000917 => D <= "10000011"; -- 0x0395 + when 000918 => D <= "00000011"; -- 0x0396 + when 000919 => D <= "11111010"; -- 0x0397 + when 000920 => D <= "01100100"; -- 0x0398 + when 000921 => D <= "01101101"; -- 0x0399 + when 000922 => D <= "10111000"; -- 0x039A + when 000923 => D <= "00110100"; -- 0x039B + when 000924 => D <= "01100000"; -- 0x039C + when 000925 => D <= "01010111"; -- 0x039D + when 000926 => D <= "10100000"; -- 0x039E + when 000927 => D <= "11110110"; -- 0x039F + when 000928 => D <= "10100010"; -- 0x03A0 + when 000929 => D <= "10000011"; -- 0x03A1 + when 000930 => D <= "11001000"; -- 0x03A2 + when 000931 => D <= "11110000"; -- 0x03A3 + when 000932 => D <= "00000011"; -- 0x03A4 + when 000933 => D <= "00000001"; -- 0x03A5 + when 000934 => D <= "01010111"; -- 0x03A6 + when 000935 => D <= "10100000"; -- 0x03A7 + when 000936 => D <= "10000011"; -- 0x03A8 + when 000937 => D <= "00100011"; -- 0x03A9 + when 000938 => D <= "11000000"; -- 0x03AA + when 000939 => D <= "00111010"; -- 0x03AB + when 000940 => D <= "00100011"; -- 0x03AC + when 000941 => D <= "00000001"; -- 0x03AD + when 000942 => D <= "00111001"; -- 0x03AE + when 000943 => D <= "10111000"; -- 0x03AF + when 000944 => D <= "00000000"; -- 0x03B0 + when 000945 => D <= "00100111"; -- 0x03B1 + when 000946 => D <= "10010000"; -- 0x03B2 + when 000947 => D <= "10000000"; -- 0x03B3 + when 000948 => D <= "10111010"; -- 0x03B4 + when 000949 => D <= "00010100"; -- 0x03B5 + when 000950 => D <= "11101010"; -- 0x03B6 + when 000951 => D <= "10110110"; -- 0x03B7 + when 000952 => D <= "00000000"; -- 0x03B8 + when 000953 => D <= "00100011"; -- 0x03B9 + when 000954 => D <= "00000001"; -- 0x03BA + when 000955 => D <= "10010000"; -- 0x03BB + when 000956 => D <= "10000000"; -- 0x03BC + when 000957 => D <= "11111001"; -- 0x03BD + when 000958 => D <= "00111010"; -- 0x03BE + when 000959 => D <= "10111010"; -- 0x03BF + when 000960 => D <= "00100110"; -- 0x03C0 + when 000961 => D <= "11101010"; -- 0x03C1 + when 000962 => D <= "11000001"; -- 0x03C2 + when 000963 => D <= "00000000"; -- 0x03C3 + when 000964 => D <= "01000111"; -- 0x03C4 + when 000965 => D <= "00111010"; -- 0x03C5 + when 000966 => D <= "10111010"; -- 0x03C6 + when 000967 => D <= "00100001"; -- 0x03C7 + when 000968 => D <= "11101010"; -- 0x03C8 + when 000969 => D <= "11001000"; -- 0x03C9 + when 000970 => D <= "00100111"; -- 0x03CA + when 000971 => D <= "00111001"; -- 0x03CB + when 000972 => D <= "00111010"; -- 0x03CC + when 000973 => D <= "10000011"; -- 0x03CD + when 000974 => D <= "00100111"; -- 0x03CE + when 000975 => D <= "00111001"; -- 0x03CF + when 000976 => D <= "10111000"; -- 0x03D0 + when 000977 => D <= "00000001"; -- 0x03D1 + when 000978 => D <= "00100111"; -- 0x03D2 + when 000979 => D <= "10010000"; -- 0x03D3 + when 000980 => D <= "11111101"; -- 0x03D4 + when 000981 => D <= "00011000"; -- 0x03D5 + when 000982 => D <= "10010000"; -- 0x03D6 + when 000983 => D <= "11111110"; -- 0x03D7 + when 000984 => D <= "00011000"; -- 0x03D8 + when 000985 => D <= "10010000"; -- 0x03D9 + when 000986 => D <= "11111111"; -- 0x03DA + when 000987 => D <= "00011000"; -- 0x03DB + when 000988 => D <= "10010000"; -- 0x03DC + when 000989 => D <= "11010101"; -- 0x03DD + when 000990 => D <= "10111001"; -- 0x03DE + when 000991 => D <= "00000001"; -- 0x03DF + when 000992 => D <= "00010100"; -- 0x03E0 + when 000993 => D <= "01110001"; -- 0x03E1 + when 000994 => D <= "00010100"; -- 0x03E2 + when 000995 => D <= "00110110"; -- 0x03E3 + when 000996 => D <= "00100011"; -- 0x03E4 + when 000997 => D <= "11111000"; -- 0x03E5 + when 000998 => D <= "00111001"; -- 0x03E6 + when 000999 => D <= "00001001"; -- 0x03E7 + when 001000 => D <= "01110010"; -- 0x03E8 + when 001001 => D <= "11100010"; -- 0x03E9 + when 001002 => D <= "11110101"; -- 0x03EA + when 001003 => D <= "00000100"; -- 0x03EB + when 001004 => D <= "00000000"; -- 0x03EC + when 001005 => D <= "00111100"; -- 0x03ED + when 001006 => D <= "10000011"; -- 0x03EE + when 001007 => D <= "00111101"; -- 0x03EF + when 001008 => D <= "10000011"; -- 0x03F0 + when 001009 => D <= "11111101"; -- 0x03F1 + when 001010 => D <= "00010111"; -- 0x03F2 + when 001011 => D <= "10101001"; -- 0x03F3 + when 001012 => D <= "00100011"; -- 0x03F4 + when 001013 => D <= "10000000"; -- 0x03F5 + when 001014 => D <= "11100111"; -- 0x03F6 + when 001015 => D <= "11101001"; -- 0x03F7 + when 001016 => D <= "11110110"; -- 0x03F8 + when 001017 => D <= "10000011"; -- 0x03F9 + when 001018 => D <= "00110000"; -- 0x03FA + when 001019 => D <= "00101001"; -- 0x03FB + when 001020 => D <= "01011100"; -- 0x03FC + when 001021 => D <= "00110010"; -- 0x03FD + when 001022 => D <= "00110101"; -- 0x03FE + when 001023 => D <= "00110110"; -- 0x03FF + when others => D <= "--------"; + end case; + end process; +end; diff --git a/rtl/assets/rom_t41x.vhd b/rtl/assets/rom_t41x.vhd new file mode 100644 index 0000000..d6d3370 --- /dev/null +++ b/rtl/assets/rom_t41x.vhd @@ -0,0 +1,541 @@ +-- This file was generated with hex2rom written by Daniel Wallner + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +entity rom_t41x is + port( + Clk : in std_logic; + A : in std_logic_vector(8 downto 0); + D : out std_logic_vector(7 downto 0) + ); +end rom_t41x; + +architecture rtl of rom_t41x is + signal A_r : std_logic_vector(8 downto 0); +begin + process (Clk) + begin + if Clk'event and Clk = '1' then + A_r <= A; + end if; + end process; + process (A_r) + begin + case to_integer(unsigned(A_r)) is + when 000000 => D <= "00000000"; -- 0x0000 + when 000001 => D <= "00001000"; -- 0x0001 + when 000002 => D <= "00110011"; -- 0x0002 + when 000003 => D <= "00101110"; -- 0x0003 + when 000004 => D <= "01000100"; -- 0x0004 + when 000005 => D <= "00000100"; -- 0x0005 + when 000006 => D <= "00110011"; -- 0x0006 + when 000007 => D <= "00101110"; -- 0x0007 + when 000008 => D <= "00000100"; -- 0x0008 + when 000009 => D <= "00000000"; -- 0x0009 + when 000010 => D <= "01100001"; -- 0x000A + when 000011 => D <= "11110000"; -- 0x000B + when 000012 => D <= "00110010"; -- 0x000C + when 000013 => D <= "00111000"; -- 0x000D + when 000014 => D <= "00000101"; -- 0x000E + when 000015 => D <= "00110000"; -- 0x000F + when 000016 => D <= "01000100"; -- 0x0010 + when 000017 => D <= "00000100"; -- 0x0011 + when 000018 => D <= "00000101"; -- 0x0012 + when 000019 => D <= "00110000"; -- 0x0013 + when 000020 => D <= "01000100"; -- 0x0014 + when 000021 => D <= "00000100"; -- 0x0015 + when 000022 => D <= "00000101"; -- 0x0016 + when 000023 => D <= "00110000"; -- 0x0017 + when 000024 => D <= "01000100"; -- 0x0018 + when 000025 => D <= "00000100"; -- 0x0019 + when 000026 => D <= "00000101"; -- 0x001A + when 000027 => D <= "00110000"; -- 0x001B + when 000028 => D <= "01000100"; -- 0x001C + when 000029 => D <= "00000100"; -- 0x001D + when 000030 => D <= "00000101"; -- 0x001E + when 000031 => D <= "00110000"; -- 0x001F + when 000032 => D <= "01000100"; -- 0x0020 + when 000033 => D <= "00000110"; -- 0x0021 + when 000034 => D <= "00110011"; -- 0x0022 + when 000035 => D <= "00111010"; -- 0x0023 + when 000036 => D <= "00000000"; -- 0x0024 + when 000037 => D <= "00010001"; -- 0x0025 + when 000038 => D <= "01011000"; -- 0x0026 + when 000039 => D <= "00111011"; -- 0x0027 + when 000040 => D <= "00000011"; -- 0x0028 + when 000041 => D <= "01011000"; -- 0x0029 + when 000042 => D <= "01000100"; -- 0x002A + when 000043 => D <= "00111000"; -- 0x002B + when 000044 => D <= "01011000"; -- 0x002C + when 000045 => D <= "01011000"; -- 0x002D + when 000046 => D <= "01001101"; -- 0x002E + when 000047 => D <= "00111111"; -- 0x002F + when 000048 => D <= "00100001"; -- 0x0030 + when 000049 => D <= "11110011"; -- 0x0031 + when 000050 => D <= "01001000"; -- 0x0032 + when 000051 => D <= "01010001"; -- 0x0033 + when 000052 => D <= "11101111"; -- 0x0034 + when 000053 => D <= "10110101"; -- 0x0035 + when 000054 => D <= "00001110"; -- 0x0036 + when 000055 => D <= "01110011"; -- 0x0037 + when 000056 => D <= "11111100"; -- 0x0038 + when 000057 => D <= "10110101"; -- 0x0039 + when 000058 => D <= "00001110"; -- 0x003A + when 000059 => D <= "01111111"; -- 0x003B + when 000060 => D <= "00011110"; -- 0x003C + when 000061 => D <= "01111111"; -- 0x003D + when 000062 => D <= "00001110"; -- 0x003E + when 000063 => D <= "00000101"; -- 0x003F + when 000064 => D <= "00000110"; -- 0x0040 + when 000065 => D <= "10000000"; -- 0x0041 + when 000066 => D <= "00101111"; -- 0x0042 + when 000067 => D <= "00010011"; -- 0x0043 + when 000068 => D <= "11000111"; -- 0x0044 + when 000069 => D <= "00001110"; -- 0x0045 + when 000070 => D <= "10000000"; -- 0x0046 + when 000071 => D <= "00001110"; -- 0x0047 + when 000072 => D <= "00000101"; -- 0x0048 + when 000073 => D <= "01011111"; -- 0x0049 + when 000074 => D <= "11001100"; -- 0x004A + when 000075 => D <= "11000000"; -- 0x004B + when 000076 => D <= "10011011"; -- 0x004C + when 000077 => D <= "11001101"; -- 0x004D + when 000078 => D <= "01100001"; -- 0x004E + when 000079 => D <= "11110000"; -- 0x004F + when 000080 => D <= "10110101"; -- 0x0050 + when 000081 => D <= "00001110"; -- 0x0051 + when 000082 => D <= "01110000"; -- 0x0052 + when 000083 => D <= "00011110"; -- 0x0053 + when 000084 => D <= "01111111"; -- 0x0054 + when 000085 => D <= "00001110"; -- 0x0055 + when 000086 => D <= "00000101"; -- 0x0056 + when 000087 => D <= "00000110"; -- 0x0057 + when 000088 => D <= "10000000"; -- 0x0058 + when 000089 => D <= "00101111"; -- 0x0059 + when 000090 => D <= "00010011"; -- 0x005A + when 000091 => D <= "11011110"; -- 0x005B + when 000092 => D <= "00001110"; -- 0x005C + when 000093 => D <= "10000000"; -- 0x005D + when 000094 => D <= "00001110"; -- 0x005E + when 000095 => D <= "00000101"; -- 0x005F + when 000096 => D <= "01010001"; -- 0x0060 + when 000097 => D <= "11010111"; -- 0x0061 + when 000098 => D <= "10011011"; -- 0x0062 + when 000099 => D <= "11100011"; -- 0x0063 + when 000100 => D <= "01100001"; -- 0x0064 + when 000101 => D <= "11110000"; -- 0x0065 + when 000102 => D <= "10110101"; -- 0x0066 + when 000103 => D <= "00001110"; -- 0x0067 + when 000104 => D <= "01111000"; -- 0x0068 + when 000105 => D <= "11010011"; -- 0x0069 + when 000106 => D <= "10110101"; -- 0x006A + when 000107 => D <= "00001110"; -- 0x006B + when 000108 => D <= "01111101"; -- 0x006C + when 000109 => D <= "11010011"; -- 0x006D + when 000110 => D <= "00000000"; -- 0x006E + when 000111 => D <= "00000000"; -- 0x006F + when 000112 => D <= "00000000"; -- 0x0070 + when 000113 => D <= "00000000"; -- 0x0071 + when 000114 => D <= "00000000"; -- 0x0072 + when 000115 => D <= "00000000"; -- 0x0073 + when 000116 => D <= "00000000"; -- 0x0074 + when 000117 => D <= "00000000"; -- 0x0075 + when 000118 => D <= "00000000"; -- 0x0076 + when 000119 => D <= "00000000"; -- 0x0077 + when 000120 => D <= "00000000"; -- 0x0078 + when 000121 => D <= "00000000"; -- 0x0079 + when 000122 => D <= "00000000"; -- 0x007A + when 000123 => D <= "00000000"; -- 0x007B + when 000124 => D <= "00000000"; -- 0x007C + when 000125 => D <= "00000000"; -- 0x007D + when 000126 => D <= "00000000"; -- 0x007E + when 000127 => D <= "00000000"; -- 0x007F + when 000128 => D <= "00010101"; -- 0x0080 + when 000129 => D <= "01010001"; -- 0x0081 + when 000130 => D <= "10000001"; -- 0x0082 + when 000131 => D <= "00000101"; -- 0x0083 + when 000132 => D <= "00110011"; -- 0x0084 + when 000133 => D <= "00111010"; -- 0x0085 + when 000134 => D <= "01011111"; -- 0x0086 + when 000135 => D <= "10001010"; -- 0x0087 + when 000136 => D <= "00010110"; -- 0x0088 + when 000137 => D <= "10000000"; -- 0x0089 + when 000138 => D <= "00000110"; -- 0x008A + when 000139 => D <= "01001000"; -- 0x008B + when 000140 => D <= "00001010"; -- 0x008C + when 000141 => D <= "00001011"; -- 0x008D + when 000142 => D <= "00001100"; -- 0x008E + when 000143 => D <= "01001110"; -- 0x008F + when 000144 => D <= "00011000"; -- 0x0090 + when 000145 => D <= "00100010"; -- 0x0091 + when 000146 => D <= "00110000"; -- 0x0092 + when 000147 => D <= "01000100"; -- 0x0093 + when 000148 => D <= "00000100"; -- 0x0094 + when 000149 => D <= "00000000"; -- 0x0095 + when 000150 => D <= "01000000"; -- 0x0096 + when 000151 => D <= "00110000"; -- 0x0097 + when 000152 => D <= "01001001"; -- 0x0098 + when 000153 => D <= "00000110"; -- 0x0099 + when 000154 => D <= "01001000"; -- 0x009A + when 000155 => D <= "00101111"; -- 0x009B + when 000156 => D <= "00000001"; -- 0x009C + when 000157 => D <= "01001001"; -- 0x009D + when 000158 => D <= "01001000"; -- 0x009E + when 000159 => D <= "01101000"; -- 0x009F + when 000160 => D <= "10101101"; -- 0x00A0 + when 000161 => D <= "01101001"; -- 0x00A1 + when 000162 => D <= "11110100"; -- 0x00A2 + when 000163 => D <= "00111111"; -- 0x00A3 + when 000164 => D <= "01110000"; -- 0x00A4 + when 000165 => D <= "01101000"; -- 0x00A5 + when 000166 => D <= "00001100"; -- 0x00A6 + when 000167 => D <= "10100101"; -- 0x00A7 + when 000168 => D <= "00001001"; -- 0x00A8 + when 000169 => D <= "00000101"; -- 0x00A9 + when 000170 => D <= "00101111"; -- 0x00AA + when 000171 => D <= "00000110"; -- 0x00AB + when 000172 => D <= "10101100"; -- 0x00AC + when 000173 => D <= "00101111"; -- 0x00AD + when 000174 => D <= "00000011"; -- 0x00AE + when 000175 => D <= "00001111"; -- 0x00AF + when 000176 => D <= "00001110"; -- 0x00B0 + when 000177 => D <= "00110011"; -- 0x00B1 + when 000178 => D <= "00111110"; -- 0x00B2 + when 000179 => D <= "00101000"; -- 0x00B3 + when 000180 => D <= "01001000"; -- 0x00B4 + when 000181 => D <= "00101111"; -- 0x00B5 + when 000182 => D <= "00000011"; -- 0x00B6 + when 000183 => D <= "00001111"; -- 0x00B7 + when 000184 => D <= "00001110"; -- 0x00B8 + when 000185 => D <= "00110011"; -- 0x00B9 + when 000186 => D <= "00111110"; -- 0x00BA + when 000187 => D <= "01001000"; -- 0x00BB + when 000188 => D <= "00101111"; -- 0x00BC + when 000189 => D <= "00000000"; -- 0x00BD + when 000190 => D <= "00010011"; -- 0x00BE + when 000191 => D <= "01011011"; -- 0x00BF + when 000192 => D <= "01010111"; -- 0x00C0 + when 000193 => D <= "01000100"; -- 0x00C1 + when 000194 => D <= "00111110"; -- 0x00C2 + when 000195 => D <= "00000110"; -- 0x00C3 + when 000196 => D <= "01001000"; -- 0x00C4 + when 000197 => D <= "00101111"; -- 0x00C5 + when 000198 => D <= "00000000"; -- 0x00C6 + when 000199 => D <= "00010011"; -- 0x00C7 + when 000200 => D <= "01010101"; -- 0x00C8 + when 000201 => D <= "01011111"; -- 0x00C9 + when 000202 => D <= "01000100"; -- 0x00CA + when 000203 => D <= "00111110"; -- 0x00CB + when 000204 => D <= "00000110"; -- 0x00CC + when 000205 => D <= "01001000"; -- 0x00CD + when 000206 => D <= "00000000"; -- 0x00CE + when 000207 => D <= "00000000"; -- 0x00CF + when 000208 => D <= "00000000"; -- 0x00D0 + when 000209 => D <= "00000000"; -- 0x00D1 + when 000210 => D <= "00000000"; -- 0x00D2 + when 000211 => D <= "00000000"; -- 0x00D3 + when 000212 => D <= "00000000"; -- 0x00D4 + when 000213 => D <= "00000000"; -- 0x00D5 + when 000214 => D <= "00000000"; -- 0x00D6 + when 000215 => D <= "00000000"; -- 0x00D7 + when 000216 => D <= "00000000"; -- 0x00D8 + when 000217 => D <= "00000000"; -- 0x00D9 + when 000218 => D <= "00000000"; -- 0x00DA + when 000219 => D <= "00000000"; -- 0x00DB + when 000220 => D <= "00000000"; -- 0x00DC + when 000221 => D <= "00000000"; -- 0x00DD + when 000222 => D <= "00000000"; -- 0x00DE + when 000223 => D <= "00000000"; -- 0x00DF + when 000224 => D <= "00000000"; -- 0x00E0 + when 000225 => D <= "00000000"; -- 0x00E1 + when 000226 => D <= "00000000"; -- 0x00E2 + when 000227 => D <= "00000000"; -- 0x00E3 + when 000228 => D <= "00000000"; -- 0x00E4 + when 000229 => D <= "00000000"; -- 0x00E5 + when 000230 => D <= "00000000"; -- 0x00E6 + when 000231 => D <= "00000000"; -- 0x00E7 + when 000232 => D <= "00000000"; -- 0x00E8 + when 000233 => D <= "00000000"; -- 0x00E9 + when 000234 => D <= "00000000"; -- 0x00EA + when 000235 => D <= "00000000"; -- 0x00EB + when 000236 => D <= "00000000"; -- 0x00EC + when 000237 => D <= "00000000"; -- 0x00ED + when 000238 => D <= "00000000"; -- 0x00EE + when 000239 => D <= "00000000"; -- 0x00EF + when 000240 => D <= "00000000"; -- 0x00F0 + when 000241 => D <= "00000000"; -- 0x00F1 + when 000242 => D <= "00000000"; -- 0x00F2 + when 000243 => D <= "00000000"; -- 0x00F3 + when 000244 => D <= "00000000"; -- 0x00F4 + when 000245 => D <= "00000000"; -- 0x00F5 + when 000246 => D <= "00000000"; -- 0x00F6 + when 000247 => D <= "00000000"; -- 0x00F7 + when 000248 => D <= "00000000"; -- 0x00F8 + when 000249 => D <= "00000000"; -- 0x00F9 + when 000250 => D <= "00000000"; -- 0x00FA + when 000251 => D <= "00000000"; -- 0x00FB + when 000252 => D <= "00000000"; -- 0x00FC + when 000253 => D <= "00000000"; -- 0x00FD + when 000254 => D <= "00000000"; -- 0x00FE + when 000255 => D <= "00000000"; -- 0x00FF + when 000256 => D <= "00010011"; -- 0x0100 + when 000257 => D <= "00010101"; -- 0x0101 + when 000258 => D <= "00010111"; -- 0x0102 + when 000259 => D <= "00011001"; -- 0x0103 + when 000260 => D <= "00011011"; -- 0x0104 + when 000261 => D <= "00111001"; -- 0x0105 + when 000262 => D <= "00110111"; -- 0x0106 + when 000263 => D <= "00111110"; -- 0x0107 + when 000264 => D <= "00111011"; -- 0x0108 + when 000265 => D <= "00101110"; -- 0x0109 + when 000266 => D <= "00110001"; -- 0x010A + when 000267 => D <= "01001001"; -- 0x010B + when 000268 => D <= "01000111"; -- 0x010C + when 000269 => D <= "01000101"; -- 0x010D + when 000270 => D <= "01000011"; -- 0x010E + when 000271 => D <= "01000001"; -- 0x010F + when 000272 => D <= "00001001"; -- 0x0110 + when 000273 => D <= "00000000"; -- 0x0111 + when 000274 => D <= "11111111"; -- 0x0112 + when 000275 => D <= "01010101"; -- 0x0113 + when 000276 => D <= "11011100"; -- 0x0114 + when 000277 => D <= "01011000"; -- 0x0115 + when 000278 => D <= "11011100"; -- 0x0116 + when 000279 => D <= "01011011"; -- 0x0117 + when 000280 => D <= "11011100"; -- 0x0118 + when 000281 => D <= "01011110"; -- 0x0119 + when 000282 => D <= "11011100"; -- 0x011A + when 000283 => D <= "11011110"; -- 0x011B + when 000284 => D <= "01010001"; -- 0x011C + when 000285 => D <= "11011100"; -- 0x011D + when 000286 => D <= "10001100"; -- 0x011E + when 000287 => D <= "11100001"; -- 0x011F + when 000288 => D <= "01001000"; -- 0x0120 + when 000289 => D <= "00000000"; -- 0x0121 + when 000290 => D <= "01010010"; -- 0x0122 + when 000291 => D <= "01000100"; -- 0x0123 + when 000292 => D <= "01000100"; -- 0x0124 + when 000293 => D <= "01010001"; -- 0x0125 + when 000294 => D <= "11100011"; -- 0x0126 + when 000295 => D <= "00011111"; -- 0x0127 + when 000296 => D <= "00000101"; -- 0x0128 + when 000297 => D <= "01000000"; -- 0x0129 + when 000298 => D <= "00000110"; -- 0x012A + when 000299 => D <= "00110011"; -- 0x012B + when 000300 => D <= "00111010"; -- 0x012C + when 000301 => D <= "11010000"; -- 0x012D + when 000302 => D <= "01011111"; -- 0x012E + when 000303 => D <= "01010001"; -- 0x012F + when 000304 => D <= "11101111"; -- 0x0130 + when 000305 => D <= "10001101"; -- 0x0131 + when 000306 => D <= "11110100"; -- 0x0132 + when 000307 => D <= "01001000"; -- 0x0133 + when 000308 => D <= "00000000"; -- 0x0134 + when 000309 => D <= "01011000"; -- 0x0135 + when 000310 => D <= "11100011"; -- 0x0136 + when 000311 => D <= "01011010"; -- 0x0137 + when 000312 => D <= "11111100"; -- 0x0138 + when 000313 => D <= "01011000"; -- 0x0139 + when 000314 => D <= "11111100"; -- 0x013A + when 000315 => D <= "01011110"; -- 0x013B + when 000316 => D <= "01100001"; -- 0x013C + when 000317 => D <= "00101111"; -- 0x013D + when 000318 => D <= "01011101"; -- 0x013E + when 000319 => D <= "01100001"; -- 0x013F + when 000320 => D <= "00111100"; -- 0x0140 + when 000321 => D <= "01011011"; -- 0x0141 + when 000322 => D <= "11001011"; -- 0x0142 + when 000323 => D <= "01011010"; -- 0x0143 + when 000324 => D <= "11001011"; -- 0x0144 + when 000325 => D <= "01011001"; -- 0x0145 + when 000326 => D <= "11001011"; -- 0x0146 + when 000327 => D <= "01011000"; -- 0x0147 + when 000328 => D <= "11001011"; -- 0x0148 + when 000329 => D <= "01010111"; -- 0x0149 + when 000330 => D <= "11001011"; -- 0x014A + when 000331 => D <= "01000100"; -- 0x014B + when 000332 => D <= "01000100"; -- 0x014C + when 000333 => D <= "01000100"; -- 0x014D + when 000334 => D <= "01010001"; -- 0x014E + when 000335 => D <= "11001101"; -- 0x014F + when 000336 => D <= "10001110"; -- 0x0150 + when 000337 => D <= "01100001"; -- 0x0151 + when 000338 => D <= "00100111"; -- 0x0152 + when 000339 => D <= "01001000"; -- 0x0153 + when 000340 => D <= "00101111"; -- 0x0154 + when 000341 => D <= "00010001"; -- 0x0155 + when 000342 => D <= "11011001"; -- 0x0156 + when 000343 => D <= "00101111"; -- 0x0157 + when 000344 => D <= "00000011"; -- 0x0158 + when 000345 => D <= "00001111"; -- 0x0159 + when 000346 => D <= "00001110"; -- 0x015A + when 000347 => D <= "00110011"; -- 0x015B + when 000348 => D <= "00111110"; -- 0x015C + when 000349 => D <= "00101111"; -- 0x015D + when 000350 => D <= "00000000"; -- 0x015E + when 000351 => D <= "00010011"; -- 0x015F + when 000352 => D <= "01010111"; -- 0x0160 + when 000353 => D <= "01011111"; -- 0x0161 + when 000354 => D <= "01000100"; -- 0x0162 + when 000355 => D <= "00011001"; -- 0x0163 + when 000356 => D <= "00000110"; -- 0x0164 + when 000357 => D <= "01100001"; -- 0x0165 + when 000358 => D <= "00010000"; -- 0x0166 + when 000359 => D <= "01100000"; -- 0x0167 + when 000360 => D <= "00111001"; -- 0x0168 + when 000361 => D <= "01100000"; -- 0x0169 + when 000362 => D <= "01100110"; -- 0x016A + when 000363 => D <= "00000101"; -- 0x016B + when 000364 => D <= "01011111"; -- 0x016C + when 000365 => D <= "11110000"; -- 0x016D + when 000366 => D <= "00000110"; -- 0x016E + when 000367 => D <= "01001000"; -- 0x016F + when 000368 => D <= "00000111"; -- 0x0170 + when 000369 => D <= "00000101"; -- 0x0171 + when 000370 => D <= "01011111"; -- 0x0172 + when 000371 => D <= "01001001"; -- 0x0173 + when 000372 => D <= "11101110"; -- 0x0174 + when 000373 => D <= "01100000"; -- 0x0175 + when 000374 => D <= "00110101"; -- 0x0176 + when 000375 => D <= "01100000"; -- 0x0177 + when 000376 => D <= "01101010"; -- 0x0178 + when 000377 => D <= "01100000"; -- 0x0179 + when 000378 => D <= "01010000"; -- 0x017A + when 000379 => D <= "00101000"; -- 0x017B + when 000380 => D <= "01110010"; -- 0x017C + when 000381 => D <= "00001111"; -- 0x017D + when 000382 => D <= "00110011"; -- 0x017E + when 000383 => D <= "00111110"; -- 0x017F + when 000384 => D <= "01100001"; -- 0x0180 + when 000385 => D <= "10001100"; -- 0x0181 + when 000386 => D <= "01101000"; -- 0x0182 + when 000387 => D <= "10101101"; -- 0x0183 + when 000388 => D <= "01110001"; -- 0x0184 + when 000389 => D <= "00111111"; -- 0x0185 + when 000390 => D <= "01111100"; -- 0x0186 + when 000391 => D <= "01100001"; -- 0x0187 + when 000392 => D <= "10001110"; -- 0x0188 + when 000393 => D <= "01101000"; -- 0x0189 + when 000394 => D <= "10101101"; -- 0x018A + when 000395 => D <= "01110000"; -- 0x018B + when 000396 => D <= "00111111"; -- 0x018C + when 000397 => D <= "01110000"; -- 0x018D + when 000398 => D <= "01101001"; -- 0x018E + when 000399 => D <= "11110100"; -- 0x018F + when 000400 => D <= "01101000"; -- 0x0190 + when 000401 => D <= "11000101"; -- 0x0191 + when 000402 => D <= "01101000"; -- 0x0192 + when 000403 => D <= "00001100"; -- 0x0193 + when 000404 => D <= "00111101"; -- 0x0194 + when 000405 => D <= "00000101"; -- 0x0195 + when 000406 => D <= "01011111"; -- 0x0196 + when 000407 => D <= "11011010"; -- 0x0197 + when 000408 => D <= "00000110"; -- 0x0198 + when 000409 => D <= "11010010"; -- 0x0199 + when 000410 => D <= "00000100"; -- 0x019A + when 000411 => D <= "00000101"; -- 0x019B + when 000412 => D <= "01011111"; -- 0x019C + when 000413 => D <= "01010001"; -- 0x019D + when 000414 => D <= "11011000"; -- 0x019E + when 000415 => D <= "01101000"; -- 0x019F + when 000416 => D <= "10111100"; -- 0x01A0 + when 000417 => D <= "00101000"; -- 0x01A1 + when 000418 => D <= "00000001"; -- 0x01A2 + when 000419 => D <= "11101110"; -- 0x01A3 + when 000420 => D <= "00010001"; -- 0x01A4 + when 000421 => D <= "11110101"; -- 0x01A5 + when 000422 => D <= "00111111"; -- 0x01A6 + when 000423 => D <= "00000101"; -- 0x01A7 + when 000424 => D <= "01010001"; -- 0x01A8 + when 000425 => D <= "11110010"; -- 0x01A9 + when 000426 => D <= "10011011"; -- 0x01AA + when 000427 => D <= "11101011"; -- 0x01AB + when 000428 => D <= "01100001"; -- 0x01AC + when 000429 => D <= "11110000"; -- 0x01AD + when 000430 => D <= "00111111"; -- 0x01AE + when 000431 => D <= "00000101"; -- 0x01AF + when 000432 => D <= "01011111"; -- 0x01B0 + when 000433 => D <= "11101010"; -- 0x01B1 + when 000434 => D <= "00000110"; -- 0x01B2 + when 000435 => D <= "01100001"; -- 0x01B3 + when 000436 => D <= "10010010"; -- 0x01B4 + when 000437 => D <= "00111111"; -- 0x01B5 + when 000438 => D <= "00010011"; -- 0x01B6 + when 000439 => D <= "11111010"; -- 0x01B7 + when 000440 => D <= "01111010"; -- 0x01B8 + when 000441 => D <= "11100110"; -- 0x01B9 + when 000442 => D <= "00001110"; -- 0x01BA + when 000443 => D <= "00110011"; -- 0x01BB + when 000444 => D <= "00111110"; -- 0x01BC + when 000445 => D <= "11100110"; -- 0x01BD + when 000446 => D <= "00110010"; -- 0x01BE + when 000447 => D <= "11000001"; -- 0x01BF + when 000448 => D <= "00100010"; -- 0x01C0 + when 000449 => D <= "00000000"; -- 0x01C1 + when 000450 => D <= "01010001"; -- 0x01C2 + when 000451 => D <= "00110000"; -- 0x01C3 + when 000452 => D <= "01000100"; -- 0x01C4 + when 000453 => D <= "00000111"; -- 0x01C5 + when 000454 => D <= "00000000"; -- 0x01C6 + when 000455 => D <= "00110000"; -- 0x01C7 + when 000456 => D <= "01000100"; -- 0x01C8 + when 000457 => D <= "00000111"; -- 0x01C9 + when 000458 => D <= "00000000"; -- 0x01CA + when 000459 => D <= "00110000"; -- 0x01CB + when 000460 => D <= "11001110"; -- 0x01CC + when 000461 => D <= "01001000"; -- 0x01CD + when 000462 => D <= "00000110"; -- 0x01CE + when 000463 => D <= "01001001"; -- 0x01CF + when 000464 => D <= "01100000"; -- 0x01D0 + when 000465 => D <= "10011111"; -- 0x01D1 + when 000466 => D <= "01101001"; -- 0x01D2 + when 000467 => D <= "01010100"; -- 0x01D3 + when 000468 => D <= "01101001"; -- 0x01D4 + when 000469 => D <= "01010111"; -- 0x01D5 + when 000470 => D <= "01101001"; -- 0x01D6 + when 000471 => D <= "01010111"; -- 0x01D7 + when 000472 => D <= "10011011"; -- 0x01D8 + when 000473 => D <= "11011001"; -- 0x01D9 + when 000474 => D <= "11010010"; -- 0x01DA + when 000475 => D <= "00000000"; -- 0x01DB + when 000476 => D <= "00000000"; -- 0x01DC + when 000477 => D <= "00000000"; -- 0x01DD + when 000478 => D <= "00000000"; -- 0x01DE + when 000479 => D <= "00000000"; -- 0x01DF + when 000480 => D <= "11111011"; -- 0x01E0 + when 000481 => D <= "11010000"; -- 0x01E1 + when 000482 => D <= "01100111"; -- 0x01E2 + when 000483 => D <= "01111011"; -- 0x01E3 + when 000484 => D <= "01111001"; -- 0x01E4 + when 000485 => D <= "10000010"; -- 0x01E5 + when 000486 => D <= "10001001"; -- 0x01E6 + when 000487 => D <= "01110101"; -- 0x01E7 + when 000488 => D <= "01110111"; -- 0x01E8 + when 000489 => D <= "01101001"; -- 0x01E9 + when 000490 => D <= "01101011"; -- 0x01EA + when 000491 => D <= "01101011"; -- 0x01EB + when 000492 => D <= "01101011"; -- 0x01EC + when 000493 => D <= "01101011"; -- 0x01ED + when 000494 => D <= "11010010"; -- 0x01EE + when 000495 => D <= "11010010"; -- 0x01EF + when 000496 => D <= "00001000"; -- 0x01F0 + when 000497 => D <= "00000000"; -- 0x01F1 + when 000498 => D <= "01011110"; -- 0x01F2 + when 000499 => D <= "11111111"; -- 0x01F3 + when 000500 => D <= "00111000"; -- 0x01F4 + when 000501 => D <= "01110000"; -- 0x01F5 + when 000502 => D <= "01110000"; -- 0x01F6 + when 000503 => D <= "01110000"; -- 0x01F7 + when 000504 => D <= "01110000"; -- 0x01F8 + when 000505 => D <= "01110111"; -- 0x01F9 + when 000506 => D <= "01001000"; -- 0x01FA + when 000507 => D <= "01100000"; -- 0x01FB + when 000508 => D <= "10101000"; -- 0x01FC + when 000509 => D <= "00000000"; -- 0x01FD + when 000510 => D <= "00000000"; -- 0x01FE + when others => D <= "--------"; + end case; + end process; +end; diff --git a/rtl/av_comp_pack-p.vhd b/rtl/av_comp_pack-p.vhd new file mode 100644 index 0000000..2e18017 --- /dev/null +++ b/rtl/av_comp_pack-p.vhd @@ -0,0 +1,100 @@ +------------------------------------------------------------------------------- +-- +-- FPGA Adventure Vision +-- +-- $Id: av_comp_pack-p.vhd,v 1.12 2006/05/06 23:40:56 arnim Exp $ +-- +-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +package av_comp_pack is + + component av_main + port ( + -- System Interface ----------------------------------------------------- + clk_11m_i : in std_logic; + reset_n_i : in std_logic; + por_n_o : out std_logic; + -- Cartridge Interface -------------------------------------------------- + cart_a_o : out std_logic_vector(11 downto 0); + cart_oe_n_o : out std_logic; + cart_d_i : in std_logic_vector( 7 downto 0); + -- Controller Interface ------------------------------------------------- + ctrl_i : in std_logic_vector( 7 downto 3); + -- Sound Interface ------------------------------------------------------ + snd_res_n_o : out std_logic; + snd_p2_o : out std_logic_vector( 7 downto 4); + -- Display Interface ---------------------------------------------------- + disp_d_o : out std_logic_vector( 7 downto 0); + disp_p24_n_o : out std_logic; + disp_rd_n_o : out std_logic; + disp_p2_o : out std_logic_vector( 7 downto 5); + disp_reset_clk_i : in std_logic; + disp_photo_int_i : in std_logic; + -- Expansion Interface -------------------------------------------------- + exp_t0_i : in std_logic; + exp_t0_o : out std_logic; + exp_t0_dir_o : out std_logic; + exp_rd_n_o : out std_logic; + exp_psen_n_o : out std_logic; + exp_wr_n_o : out std_logic; + exp_ale_o : out std_logic; + exp_d_i : in std_logic_vector( 7 downto 0); + exp_d_o : out std_logic_vector( 7 downto 0); + exp_p1_i : in std_logic_vector( 7 downto 3); + exp_p1_o : out std_logic_vector( 7 downto 3); + exp_p1_low_imp_o : out std_logic; + exp_p2_i : in std_logic_vector( 3 downto 0); + exp_p2_o : out std_logic_vector( 3 downto 0); + exp_p2l_low_imp_o : out std_logic; + exp_p2h_low_imp_o : out std_logic; + exp_prog_n_o : out std_logic + ); + end component; + + component av_ctrl + port ( + -- Control Interface ---------------------------------------------------- + ctrl_o : out std_logic_vector(7 downto 3); + -- Buttons and Stick Interface ------------------------------------------ + but_1_n_i : in std_logic; + but_2_n_i : in std_logic; + but_3_n_i : in std_logic; + but_4_n_i : in std_logic; + stick_l_n_i : in std_logic; + stick_r_n_i : in std_logic; + stick_u_n_i : in std_logic; + stick_d_n_i : in std_logic; + -- Sound Interface ------------------------------------------------------ + clk_11m_i : in std_logic; + por_n_i : in std_logic; + snd_res_n_i : in std_logic; + snd_p2_i : in std_logic_vector(7 downto 4); + audio_o : out std_logic_vector(1 downto 0) + ); + end component; + + component av_disp + port ( + -- System Interface ----------------------------------------------------- + clk_11m_i : in std_logic; + por_n_i : in std_logic; + -- Display Interface ---------------------------------------------------- + disp_d_i : in std_logic_vector( 7 downto 0); + disp_p24_n_i : in std_logic; + disp_rd_n_i : in std_logic; + disp_p2_i : in std_logic_vector( 7 downto 5); + disp_reset_clk_o : out std_logic; + disp_photo_int_o : out std_logic; + -- LED Interface -------------------------------------------------------- + led_n_o : out std_logic_vector(39 downto 0) + ); + end component; + +end av_comp_pack; diff --git a/rtl/av_ctrl.vhd b/rtl/av_ctrl.vhd new file mode 100644 index 0000000..a98a6ad --- /dev/null +++ b/rtl/av_ctrl.vhd @@ -0,0 +1,201 @@ +------------------------------------------------------------------------------- +-- +-- FPGA Adventure Vision +-- +-- $Id: av_ctrl.vhd,v 1.7 2006/05/09 21:11:29 arnim Exp $ +-- +-- Controller PCB +-- +------------------------------------------------------------------------------- +-- +-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity av_ctrl is + + port ( + -- Control Interface ------------------------------------------------------ + ctrl_o : out std_logic_vector(7 downto 3); + -- Buttons and Stick Interface -------------------------------------------- + but_1_n_i : in std_logic; + but_2_n_i : in std_logic; + but_3_n_i : in std_logic; + but_4_n_i : in std_logic; + stick_l_n_i : in std_logic; + stick_r_n_i : in std_logic; + stick_u_n_i : in std_logic; + stick_d_n_i : in std_logic; + -- Sound Interface -------------------------------------------------------- + clk_11m_i : in std_logic; + por_n_i : in std_logic; + snd_res_n_i : in std_logic; + snd_p2_i : in std_logic_vector(7 downto 4); + audio_o : out std_logic_vector(1 downto 0) + ); + +end av_ctrl; + + +library ieee; +use ieee.numeric_std.all; + +use work.t400_opt_pack.all; +use work.t400_system_comp_pack.t410_notri; + +architecture rtl of av_ctrl is + + signal io_l_s : std_logic_vector(7 downto 0); + signal io_d_s, + io_g_s : std_logic_vector(3 downto 0); + + signal clk_842k_en_s : std_logic; + signal clk_842k_cnt_q : unsigned(3 downto 0); + + signal gnd4_s : std_logic_vector(3 downto 0); + +begin + + gnd4_s <= (others => '0'); + + ----------------------------------------------------------------------------- + -- COP411L sound controller + ----------------------------------------------------------------------------- + io_l_s(7 downto 4) <= (others => '0'); + io_l_s(3 downto 0) <= snd_p2_i; + -- + cop411_b : t410_notri + generic map ( + opt_ck_div_g => t400_opt_ck_div_16_c + ) + port map ( + ck_i => clk_11m_i, + ck_en_i => clk_842k_en_s, + reset_n_i => snd_res_n_i, + cko_i => gnd4_s(0), + io_l_i => io_l_s, + io_l_o => open, + io_l_en_o => open, + io_d_o => io_d_s, + io_d_en_o => open, + io_g_i => gnd4_s, + io_g_o => io_g_s, + io_g_en_o => open, + si_i => gnd4_s(0), + so_o => open, + so_en_o => open, + sk_o => open, + sk_en_o => open + ); + -- + audio_o(1) <= io_d_s(0); -- 0 = high, 1 = low volume + audio_o(0) <= io_g_s(0); -- digital sound waveform + + + ----------------------------------------------------------------------------- + -- Process clk_842 + -- + -- Purpose: + -- Generates the 842 kHz clock for the COP411L. + -- + clk_842: process (clk_11m_i, por_n_i) + begin + if por_n_i = '0' then + clk_842k_cnt_q <= to_unsigned(12, 4); + elsif clk_11m_i'event and clk_11m_i = '1' then + if clk_842k_en_s = '1' then + clk_842k_cnt_q <= to_unsigned(12, 4); + else + clk_842k_cnt_q <= clk_842k_cnt_q - 1; + end if; + end if; + end process clk_842; + -- + clk_842k_en_s <= '1' + when clk_842k_cnt_q = 0 else + '0'; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process ctrl + -- + -- Purpose: + -- Encodes the button and stick inputs to the control bus. + -- + ctrl: process (but_1_n_i, but_2_n_i, but_3_n_i, but_4_n_i, + stick_l_n_i, stick_r_n_i, stick_u_n_i, stick_d_n_i) + variable ctrl_v : std_logic_vector(7 downto 3); + begin + ctrl_v := (others => '1'); + + if but_1_n_i = '0' then + ctrl_v(5) := '0'; + ctrl_v(4) := '0'; + end if; + if but_2_n_i = '0' then + ctrl_v(6) := '0'; + ctrl_v(4) := '0'; + end if; + if but_3_n_i = '0' then + ctrl_v(3) := '0'; + end if; + if but_4_n_i = '0' then + ctrl_v(7) := '0'; + ctrl_v(4) := '0'; + end if; + + -- priority encoder required here + -- joystick is only 4-way, positions NW, NE, SW and SE do not exist + if stick_l_n_i = '0' then + ctrl_v(7) := '0'; + elsif stick_r_n_i = '0' then + ctrl_v(6) := '0'; + elsif stick_u_n_i = '0' then + ctrl_v(5) := '0'; + elsif stick_d_n_i = '0' then + ctrl_v(4) := '0'; + end if; + + ctrl_o <= ctrl_v; + end process ctrl; + -- + ----------------------------------------------------------------------------- + +end rtl; diff --git a/rtl/av_disp.vhd b/rtl/av_disp.vhd new file mode 100644 index 0000000..2a03633 --- /dev/null +++ b/rtl/av_disp.vhd @@ -0,0 +1,203 @@ +------------------------------------------------------------------------------- +-- +-- FPGA Adventure Vision +-- +-- $Id: av_disp.vhd,v 1.9 2006/04/02 18:37:59 arnim Exp $ +-- +-- Display PCB +-- +------------------------------------------------------------------------------- +-- +-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity av_disp is + + port ( + -- System Interface ------------------------------------------------------- + clk_11m_i : in std_logic; + por_n_i : in std_logic; + -- Display Interface ------------------------------------------------------ + disp_d_i : in std_logic_vector( 7 downto 0); + disp_p24_n_i : in std_logic; + disp_rd_n_i : in std_logic; + disp_p2_i : in std_logic_vector( 7 downto 5); + disp_reset_clk_o : out std_logic; + disp_photo_int_o : out std_logic; + -- LED Interface ---------------------------------------------------------- + led_n_o : out std_logic_vector(39 downto 0) + ); + +end av_disp; + + +library ieee; +use ieee.numeric_std.all; + +architecture rtl of av_disp is + + constant mirror_cnt_width_c : natural := 24; + -- interruptor closed time: 200 us + constant interruptor_reload_c : natural := 2220; + -- mirror rotation time from : 66.67 ms - interruptor closed time + constant mirror_rot_reload_c : natural := 739918 - + interruptor_reload_c; + + signal mirror_cnt_q : unsigned(mirror_cnt_width_c-1 downto 0); + signal interruptor_closed_q : std_logic; + signal disp_photo_int_s : std_logic; + + signal led_pre_n_q, + led_n_q : std_logic_vector(39 downto 0); + + signal p24_n_q : std_logic; + +begin + + ----------------------------------------------------------------------------- + -- Process mirror + -- + -- Purpose: + -- Implements the counter that emulates the rotating mirror. + -- + mirror: process (clk_11m_i, por_n_i) + begin + if por_n_i = '0' then + mirror_cnt_q <= to_unsigned(mirror_rot_reload_c, + mirror_cnt_width_c); + interruptor_closed_q <= '0'; + + elsif clk_11m_i'event and clk_11m_i = '1' then + if mirror_cnt_q = 0 then + if interruptor_closed_q = '0' then + -- mirror moved to position where interruptor will be closed + -- time closing phase + mirror_cnt_q <= to_unsigned(interruptor_reload_c, + mirror_cnt_width_c); + else + -- mirror moved out of interruptor + mirror_cnt_q <= to_unsigned(mirror_rot_reload_c, + mirror_cnt_width_c); + end if; + + -- flip interruptor + interruptor_closed_q <= not interruptor_closed_q; + + else + mirror_cnt_q <= mirror_cnt_q - 1; + end if; + + end if; + end process mirror; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process leds + -- + -- Purpose: + -- Implements the registers for saving the LED data. + -- Data is stored in two steps: + -- a) sequential write to led_pre_q + -- b) full parallel update to led_q + -- + -- Note that the LED signals are active low. I.e. LEDs are lit when control + -- signals are pulled to GND. + -- + leds: process (clk_11m_i, por_n_i) + begin + if por_n_i = '0' then + led_pre_n_q <= (others => '1'); + led_n_q <= (others => '1'); + p24_n_q <= '0'; + + elsif clk_11m_i'event and clk_11m_i = '1' then + p24_n_q <= disp_p24_n_i; + + -- latch while /RD is active + if disp_rd_n_i = '0'then + case disp_p2_i is + when "001" => + led_pre_n_q( 7 downto 0) <= disp_d_i; + when "010" => + led_pre_n_q(15 downto 8) <= disp_d_i; + when "011" => + led_pre_n_q(23 downto 16) <= disp_d_i; + when "100" => + led_pre_n_q(31 downto 24) <= disp_d_i; + when "101" => + led_pre_n_q(39 downto 32) <= disp_d_i; + when others => + null; + end case; + end if; + + if interruptor_closed_q = '0' then + -- detect falling edge on /P2.4 + if disp_p24_n_i = '0' and p24_n_q = '1' then + -- update LEDs + led_n_q <= led_pre_n_q; + end if; + + else + -- clear LEDs + -- required for Super Cobra + led_n_q <= (others => '1'); + end if; + + end if; + end process leds; + -- + disp_photo_int_s <= not interruptor_closed_q; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Output mapping + ----------------------------------------------------------------------------- + disp_photo_int_o <= disp_photo_int_s; + led_n_o <= led_n_q; + -- propagate /RD to reset flip-flop clock when P2 is set to C + disp_reset_clk_o <= disp_rd_n_i + when disp_p2_i = "110" else + '1'; + +end rtl; diff --git a/rtl/av_machine.vhd b/rtl/av_machine.vhd new file mode 100644 index 0000000..7c83885 --- /dev/null +++ b/rtl/av_machine.vhd @@ -0,0 +1,225 @@ +------------------------------------------------------------------------------- +-- +-- FPGA Adventure Vision +-- +-- $Id: av_machine.vhd,v 1.6 2006/05/06 23:40:56 arnim Exp $ +-- +-- Toplevel of the Adventure Vision console +-- +-- References: +-- +-- * AdventureVision.com +-- The comprehensive source of information +-- +-- * Dan Boris' technical resources of the Adventure Vision +-- http://www.atarihq.com/danb/adventurevision.shtml +-- +-- * PCB Schematics, same source +-- http://www.atarihq.com/danb/files/AvSchematic.pdf +-- +-- * Technical manual, same source +-- http://www.atarihq.com/danb/files/AvTechSpecs.pdf +-- +------------------------------------------------------------------------------- +-- +-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity av_machine is + + port ( + -- System Interface ------------------------------------------------------- + clk_11m_i : in std_logic; + reset_n_i : in std_logic; + por_n_o : out std_logic; + -- Cartridge Interface ---------------------------------------------------- + cart_a_o : out std_logic_vector(11 downto 0); + cart_oe_n_o : out std_logic; + cart_d_i : in std_logic_vector( 7 downto 0); + -- Buttons and Stick Interface -------------------------------------------- + but_1_n_i : in std_logic; + but_2_n_i : in std_logic; + but_3_n_i : in std_logic; + but_4_n_i : in std_logic; + stick_l_n_i : in std_logic; + stick_r_n_i : in std_logic; + stick_u_n_i : in std_logic; + stick_d_n_i : in std_logic; + -- Sound Interface -------------------------------------------------------- + audio_o : out std_logic_vector( 1 downto 0); + -- Display Interface ------------------------------------------------------ + led_n_o : out std_logic_vector(39 downto 0); + disp_p24_n_o : out std_logic; + disp_photo_int_o : out std_logic; + -- Expansion Interface ---------------------------------------------------- + exp_t0_i : in std_logic; + exp_t0_o : out std_logic; + exp_t0_dir_o : out std_logic; + exp_rd_n_o : out std_logic; + exp_psen_n_o : out std_logic; + exp_wr_n_o : out std_logic; + exp_ale_o : out std_logic; + exp_d_i : in std_logic_vector( 7 downto 0); + exp_d_o : out std_logic_vector( 7 downto 0); + exp_p1_i : in std_logic_vector( 7 downto 3); + exp_p1_o : out std_logic_vector( 7 downto 3); + exp_p1_low_imp_o : out std_logic; + exp_p2_i : in std_logic_vector( 3 downto 0); + exp_p2_o : out std_logic_vector( 3 downto 0); + exp_p2l_low_imp_o : out std_logic; + exp_p2h_low_imp_o : out std_logic; + exp_prog_n_o : out std_logic + ); + +end av_machine; + + +use work.av_comp_pack.av_main; +use work.av_comp_pack.av_ctrl; +use work.av_comp_pack.av_disp; + +architecture struct of av_machine is + + -- System connections + signal por_n_s : std_logic; + + -- Control connections + signal ctrl_s : std_logic_vector(7 downto 3); + + -- Sound connections + signal snd_res_n_s : std_logic; + signal snd_p2_s : std_logic_vector(7 downto 4); + + -- Display connections + signal disp_d_s : std_logic_vector(7 downto 0); + signal disp_p24_n_s : std_logic; + signal disp_rd_n_s : std_logic; + signal disp_p2_s : std_logic_vector(7 downto 5); + signal disp_reset_clk_s : std_logic; + signal disp_photo_int_s : std_logic; + +begin + + ----------------------------------------------------------------------------- + -- Main PCB + ----------------------------------------------------------------------------- + main_b : av_main + port map ( + clk_11m_i => clk_11m_i, + reset_n_i => reset_n_i, + por_n_o => por_n_s, + cart_a_o => cart_a_o, + cart_oe_n_o => cart_oe_n_o, + cart_d_i => cart_d_i, + ctrl_i => ctrl_s, + snd_res_n_o => snd_res_n_s, + snd_p2_o => snd_p2_s, + disp_d_o => disp_d_s, + disp_p24_n_o => disp_p24_n_s, + disp_rd_n_o => disp_rd_n_s, + disp_p2_o => disp_p2_s, + disp_reset_clk_i => disp_reset_clk_s, + disp_photo_int_i => disp_photo_int_s, + exp_t0_i => exp_t0_i, + exp_t0_o => exp_t0_o, + exp_t0_dir_o => exp_t0_dir_o, + exp_rd_n_o => exp_rd_n_o, + exp_psen_n_o => exp_psen_n_o, + exp_wr_n_o => exp_wr_n_o, + exp_ale_o => exp_ale_o, + exp_d_i => exp_d_i, + exp_d_o => exp_d_o, + exp_p1_i => exp_p1_i, + exp_p1_o => exp_p1_o, + exp_p1_low_imp_o => exp_p1_low_imp_o, + exp_p2_i => exp_p2_i, + exp_p2_o => exp_p2_o, + exp_p2l_low_imp_o => exp_p2l_low_imp_o, + exp_p2h_low_imp_o => exp_p2h_low_imp_o, + exp_prog_n_o => exp_prog_n_o + ); + + + ----------------------------------------------------------------------------- + -- Controller PCB + ----------------------------------------------------------------------------- + ctrl_b : av_ctrl + port map ( + ctrl_o => ctrl_s, + but_1_n_i => but_1_n_i, + but_2_n_i => but_2_n_i, + but_3_n_i => but_3_n_i, + but_4_n_i => but_4_n_i, + stick_l_n_i => stick_l_n_i, + stick_r_n_i => stick_r_n_i, + stick_u_n_i => stick_u_n_i, + stick_d_n_i => stick_d_n_i, + clk_11m_i => clk_11m_i, + por_n_i => por_n_s, + snd_res_n_i => snd_res_n_s, + snd_p2_i => snd_p2_s, + audio_o => audio_o + ); + + + ----------------------------------------------------------------------------- + -- Display PCB + ----------------------------------------------------------------------------- + disp_b : av_disp + port map ( + clk_11m_i => clk_11m_i, + por_n_i => por_n_s, + disp_d_i => disp_d_s, + disp_p24_n_i => disp_p24_n_s, + disp_rd_n_i => disp_rd_n_s, + disp_p2_i => disp_p2_s, + disp_reset_clk_o => disp_reset_clk_s, + disp_photo_int_o => disp_photo_int_s, + led_n_o => led_n_o + ); + + + ----------------------------------------------------------------------------- + -- Output mapping + ----------------------------------------------------------------------------- + por_n_o <= por_n_s; + disp_p24_n_o <= disp_p24_n_s; + disp_photo_int_o <= disp_photo_int_s; + +end struct; diff --git a/rtl/av_machine_comp_pack-p.vhd b/rtl/av_machine_comp_pack-p.vhd new file mode 100644 index 0000000..682dbe2 --- /dev/null +++ b/rtl/av_machine_comp_pack-p.vhd @@ -0,0 +1,64 @@ +------------------------------------------------------------------------------- +-- +-- FPGA Adventure Vision +-- +-- $Id: av_machine_comp_pack-p.vhd,v 1.5 2006/04/02 18:51:11 arnim Exp $ +-- +-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +package av_machine_comp_pack is + + component av_machine + port ( + -- System Interface ----------------------------------------------------- + clk_11m_i : in std_logic; + reset_n_i : in std_logic; + por_n_o : out std_logic; + -- Cartridge Interface -------------------------------------------------- + cart_a_o : out std_logic_vector(11 downto 0); + cart_oe_n_o : out std_logic; + cart_d_i : in std_logic_vector( 7 downto 0); + -- Buttons and Stick Interface ------------------------------------------ + but_1_n_i : in std_logic; + but_2_n_i : in std_logic; + but_3_n_i : in std_logic; + but_4_n_i : in std_logic; + stick_l_n_i : in std_logic; + stick_r_n_i : in std_logic; + stick_u_n_i : in std_logic; + stick_d_n_i : in std_logic; + -- Sound Interface ------------------------------------------------------ + audio_o : out std_logic_vector( 1 downto 0); + -- Display Interface ---------------------------------------------------- + led_n_o : out std_logic_vector(39 downto 0); + disp_p24_n_o : out std_logic; + disp_photo_int_o : out std_logic; + -- Expansion Interface -------------------------------------------------- + exp_t0_i : in std_logic; + exp_t0_o : out std_logic; + exp_t0_dir_o : out std_logic; + exp_rd_n_o : out std_logic; + exp_psen_n_o : out std_logic; + exp_wr_n_o : out std_logic; + exp_ale_o : out std_logic; + exp_d_i : in std_logic_vector( 7 downto 0); + exp_d_o : out std_logic_vector( 7 downto 0); + exp_p1_i : in std_logic_vector( 7 downto 3); + exp_p1_o : out std_logic_vector( 7 downto 3); + exp_p1_low_imp_o : out std_logic; + exp_p2_i : in std_logic_vector( 3 downto 0); + exp_p2_o : out std_logic_vector( 3 downto 0); + exp_p2l_low_imp_o : out std_logic; + exp_p2h_low_imp_o : out std_logic; + exp_prog_n_o : out std_logic + ); + end component; + +end av_machine_comp_pack; diff --git a/rtl/av_main.vhd b/rtl/av_main.vhd new file mode 100644 index 0000000..b20f935 --- /dev/null +++ b/rtl/av_main.vhd @@ -0,0 +1,345 @@ +------------------------------------------------------------------------------- +-- +-- FPGA Adventure Vision +-- +-- $Id: av_main.vhd,v 1.14 2006/05/13 14:54:55 arnim Exp $ +-- +-- Main PCB +-- +------------------------------------------------------------------------------- +-- +-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity av_main is + + port ( + -- System Interface ------------------------------------------------------- + clk_11m_i : in std_logic; + reset_n_i : in std_logic; + por_n_o : out std_logic; + -- Cartridge Interface ---------------------------------------------------- + cart_a_o : out std_logic_vector(11 downto 0); + cart_oe_n_o : out std_logic; + cart_d_i : in std_logic_vector( 7 downto 0); + -- Controller Interface --------------------------------------------------- + ctrl_i : in std_logic_vector( 7 downto 3); + -- Sound Interface -------------------------------------------------------- + snd_res_n_o : out std_logic; + snd_p2_o : out std_logic_vector( 7 downto 4); + -- Display Interface ------------------------------------------------------ + disp_d_o : out std_logic_vector( 7 downto 0); + disp_p24_n_o : out std_logic; + disp_rd_n_o : out std_logic; + disp_p2_o : out std_logic_vector( 7 downto 5); + disp_reset_clk_i : in std_logic; + disp_photo_int_i : in std_logic; + -- Expansion Interface ---------------------------------------------------- + exp_t0_i : in std_logic; + exp_t0_o : out std_logic; + exp_t0_dir_o : out std_logic; + exp_rd_n_o : out std_logic; + exp_psen_n_o : out std_logic; + exp_wr_n_o : out std_logic; + exp_ale_o : out std_logic; + exp_d_i : in std_logic_vector( 7 downto 0); + exp_d_o : out std_logic_vector( 7 downto 0); + exp_p1_i : in std_logic_vector( 7 downto 3); + exp_p1_o : out std_logic_vector( 7 downto 3); + exp_p1_low_imp_o : out std_logic; + exp_p2_i : in std_logic_vector( 3 downto 0); + exp_p2_o : out std_logic_vector( 3 downto 0); + exp_p2l_low_imp_o : out std_logic; + exp_p2h_low_imp_o : out std_logic; + exp_prog_n_o : out std_logic + ); + +end av_main; + + +use work.tech_comp_pack.av_por; +use work.t48_system_comp_pack.t8048_notri; +use work.tech_comp_pack.generic_ram; + +architecture struct of av_main is + + -- System connections + signal por_n_s : std_logic; + signal reset_n_s : std_logic; + signal a_q : std_logic_vector(7 downto 0); + + -- T48 connections + signal ale_s : std_logic; + signal rd_n_s, + wr_n_s : std_logic; + signal psen_n_s : std_logic; + signal db_to_t48_s, + db_from_t48_s : std_logic_vector(7 downto 0); + signal db_dir_s : std_logic; + signal t1_s : std_logic; + signal p1_to_t48_s, + p1_from_t48_s : std_logic_vector(7 downto 0); + signal p2_to_t48_s, + p2_from_t48_s : std_logic_vector(7 downto 0); + + -- RAM connections + signal ram_we_s : std_logic; + signal d_ram_s, + d_from_ram_s : std_logic_vector(7 downto 0); + signal ram_a_s : std_logic_vector(9 downto 0); + + signal d_from_cart_s : std_logic_vector(7 downto 0); + + signal disp_enable_s : std_logic; + + signal db0_q : std_logic; + signal disp_reset_clk_q : std_logic; + signal snd_res_n_q : std_logic; + + signal vdd_s : std_logic; + +begin + + vdd_s <= '1'; + + ----------------------------------------------------------------------------- + -- Power-on reset circuit + -- Reset active for at most 28.5 ms. + -- The power-on reset time is calculated from the RC element present at + -- the reset pin of the 8048: + -- C = 1 uF, R = 20 kOhm (estimated from pin input leakage I_LI2) + -- V_IH = 3.8 V + ----------------------------------------------------------------------------- + por_b : av_por + generic map ( + delay_g => 6315, + cnt_width_g => 19 + ) + port map ( + clk_i => clk_11m_i, + por_n_o => por_n_s + ); + por_n_o <= por_n_s; + reset_n_s <= reset_n_i and por_n_s; + + + ----------------------------------------------------------------------------- + -- T48 uController in 8048 flavour without tri-states + ----------------------------------------------------------------------------- + t8048_notri_b : t8048_notri + generic map ( + gate_port_input_g => 1 + ) + port map ( + xtal_i => clk_11m_i, + reset_n_i => reset_n_s, + t0_i => exp_t0_i, + t0_o => exp_t0_o, + t0_dir_o => exp_t0_dir_o, + int_n_i => vdd_s, + ea_i => p1_from_t48_s(2), + rd_n_o => rd_n_s, + psen_n_o => psen_n_s, + wr_n_o => wr_n_s, + ale_o => ale_s, + db_i => db_to_t48_s, + db_o => db_from_t48_s, + db_dir_o => db_dir_s, + t1_i => t1_s, + p2_i => p2_to_t48_s, + p2_o => p2_from_t48_s, + p2l_low_imp_o => exp_p2l_low_imp_o, + p2h_low_imp_o => exp_p2h_low_imp_o, + p1_i => p1_to_t48_s, + p1_o => p1_from_t48_s, + p1_low_imp_o => exp_p1_low_imp_o, + prog_n_o => exp_prog_n_o + ); + + -- build DB input bus + db_to_t48_s <= d_from_ram_s and + d_from_cart_s and + exp_d_i; + -- set bus from cartridge to inactive when cartridge is not selected + d_from_cart_s <= cart_d_i + when psen_n_s = '0' else + (others => '1'); + + -- build P1 input bus + p1_to_t48_s(2 downto 0) <= (others => '1'); + p1_to_t48_s(7 downto 3) <= ctrl_i and exp_p1_i; + + -- build P2 input bus + p2_to_t48_s(3 downto 0) <= exp_p2_i; + p2_to_t48_s(7 downto 4) <= (others => '1'); + + t1_s <= not disp_photo_int_i; + + + ----------------------------------------------------------------------------- + -- Process alatch + -- + -- Purpose: + -- Implements the address latch. + -- + alatch: process (clk_11m_i, por_n_s) + begin + if por_n_s = '0' then + a_q <= (others => '0'); + elsif clk_11m_i'event and clk_11m_i = '1' then + if ale_s = '1' then + a_q <= db_from_t48_s; + end if; + end if; + end process alatch; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- External RAM + ----------------------------------------------------------------------------- + ram_we_s <= not wr_n_s; + ram_a_s <= p1_from_t48_s(1) & p1_from_t48_s(0) & + a_q; + -- + ext_ram_b : generic_ram + generic map ( + addr_width_g => 10, + data_width_g => 8 + ) + port map ( + clk_i => clk_11m_i, + a_i => ram_a_s, + we_i => ram_we_s, + d_i => db_from_t48_s, + d_o => d_ram_s + ); + -- set bus from RAM to inactive state when RAM is not selected + d_from_ram_s <= d_ram_s + when rd_n_s = '0' else + (others => '1'); + + + ----------------------------------------------------------------------------- + -- Display disabled for at most 240 ms. + -- The disable time is calculated from the RC element present at + -- pin 2 of the 74LS00: + -- C = 47 uF, R = 10 kOhm + -- V_IH = 2 V + ----------------------------------------------------------------------------- + disp_en_b : av_por + generic map ( + delay_g => 3706, + cnt_width_g => 26 + ) + port map ( + clk_i => clk_11m_i, + por_n_o => disp_enable_s + ); + + + ----------------------------------------------------------------------------- + -- Process db_reg + -- + -- Purpose: + -- Saves DB(0) when DB is written to by MOVX. + -- + db_reg: process (clk_11m_i, por_n_s) + begin + if por_n_s = '0' then + db0_q <= '0'; + elsif clk_11m_i'event and clk_11m_i = '1' then + if wr_n_s = '0' then + db0_q <= db_from_t48_s(0); + end if; + end if; + end process db_reg; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process snd_res + -- + -- Purpose: + -- Implements the flip-flop for resetting the COP411L sound controller. + -- + snd_res: process (clk_11m_i, por_n_s) + begin + if por_n_s = '0' then + disp_reset_clk_q <= '0'; + snd_res_n_q <= '0'; + elsif clk_11m_i'event and clk_11m_i = '1' then + disp_reset_clk_q <= disp_reset_clk_i; + if disp_reset_clk_i = '1' and disp_reset_clk_q = '0' then + snd_res_n_q <= db0_q; + end if; + end if; + end process snd_res; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Output mapping + ----------------------------------------------------------------------------- + -- Sound Interface + snd_res_n_o <= snd_res_n_q; + snd_p2_o <= p2_from_t48_s(7 downto 4); + -- Cartridge Interface + cart_a_o <= p2_from_t48_s(3) & p2_from_t48_s(2) & + p2_from_t48_s(1) & p2_from_t48_s(0) & + a_q; + cart_oe_n_o <= psen_n_s; + -- Display Interface + disp_d_o <= db_to_t48_s; + disp_p24_n_o <= disp_enable_s nand p2_from_t48_s(4); + disp_rd_n_o <= rd_n_s; + disp_p2_o <= p2_from_t48_s(7 downto 5); + -- Expansion Interface + exp_rd_n_o <= rd_n_s; + exp_psen_n_o <= psen_n_s; + exp_wr_n_o <= wr_n_s; + exp_ale_o <= ale_s; + exp_d_o <= db_from_t48_s; + exp_p1_o <= p1_from_t48_s(7 downto 3); + exp_p2_o <= p2_from_t48_s(3 downto 0); + +end struct; diff --git a/rtl/pll.qip b/rtl/pll.qip new file mode 100644 index 0000000..acbec3d --- /dev/null +++ b/rtl/pll.qip @@ -0,0 +1,337 @@ +set_global_assignment -entity "pll" -library "pll" -name IP_TOOL_NAME "altera_pll" +set_global_assignment -entity "pll" -library "pll" -name IP_TOOL_VERSION "17.0" +set_global_assignment -entity "pll" -library "pll" -name IP_TOOL_ENV "mwpim" +set_global_assignment -library "pll" -name MISC_FILE [file join $::quartus(qip_path) "pll.cmp"] +set_global_assignment -entity "pll" -library "pll" -name IP_TARGETED_DEVICE_FAMILY "Cyclone V" +set_global_assignment -entity "pll" -library "pll" -name IP_GENERATED_DEVICE_FAMILY "{Cyclone V}" +set_global_assignment -entity "pll" -library "pll" -name IP_QSYS_MODE "UNKNOWN" +set_global_assignment -name SYNTHESIS_ONLY_QIP ON +set_global_assignment -entity "pll" -library "pll" -name IP_COMPONENT_NAME "cGxs" +set_global_assignment -entity "pll" -library "pll" -name IP_COMPONENT_DISPLAY_NAME "QWx0ZXJhIFBMTA==" +set_global_assignment -entity "pll" -library "pll" -name IP_COMPONENT_REPORT_HIERARCHY "Off" +set_global_assignment -entity "pll" -library "pll" -name IP_COMPONENT_INTERNAL "Off" +set_global_assignment -entity "pll" -library "pll" -name IP_COMPONENT_AUTHOR "QWx0ZXJhIENvcnBvcmF0aW9u" +set_global_assignment -entity "pll" -library "pll" -name IP_COMPONENT_VERSION "MTcuMA==" +set_global_assignment -entity "pll" -library "pll" -name IP_COMPONENT_DESCRIPTION "QWx0ZXJhIFBoYXNlLUxvY2tlZCBMb29wIChBTFRFUkFfUExMKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_NAME "cGxsXzAwMDI=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_DISPLAY_NAME "QWx0ZXJhIFBMTA==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_REPORT_HIERARCHY "Off" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_INTERNAL "Off" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_AUTHOR "QWx0ZXJhIENvcnBvcmF0aW9u" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_VERSION "MTcuMA==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_DESCRIPTION "QWx0ZXJhIFBoYXNlLUxvY2tlZCBMb29wIChBTFRFUkFfUExMKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZGVidWdfcHJpbnRfb3V0cHV0::ZmFsc2U=::ZGVidWdfcHJpbnRfb3V0cHV0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZGVidWdfdXNlX3JiY190YWZfbWV0aG9k::ZmFsc2U=::ZGVidWdfdXNlX3JiY190YWZfbWV0aG9k" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZGV2aWNl::NUNFQkEyRjE3QTc=::ZGV2aWNl" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BsbF9tb2Rl::SW50ZWdlci1OIFBMTA==::UExMIE1vZGU=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZnJhY3Rpb25hbF92Y29fbXVsdGlwbGllcg==::ZmFsc2U=::ZnJhY3Rpb25hbF92Y29fbXVsdGlwbGllcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3JlZmVyZW5jZV9jbG9ja19mcmVxdWVuY3k=::NTAuMA==::UmVmZXJlbmNlIENsb2NrIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cmVmZXJlbmNlX2Nsb2NrX2ZyZXF1ZW5jeQ==::NTAuMCBNSHo=::cmVmZXJlbmNlX2Nsb2NrX2ZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2NoYW5uZWxfc3BhY2luZw==::MC4w::Q2hhbm5lbCBTcGFjaW5n" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX29wZXJhdGlvbl9tb2Rl::ZGlyZWN0::T3BlcmF0aW9uIE1vZGU=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2ZlZWRiYWNrX2Nsb2Nr::R2xvYmFsIENsb2Nr::RmVlZGJhY2sgQ2xvY2s=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2ZyYWN0aW9uYWxfY291dA==::MzI=::RnJhY3Rpb25hbCBjYXJyeSBvdXQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RzbV9vdXRfc2Vs::MXN0X29yZGVy::RFNNIE9yZGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3BlcmF0aW9uX21vZGU=::ZGlyZWN0::b3BlcmF0aW9uX21vZGU=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3VzZV9sb2NrZWQ=::dHJ1ZQ==::RW5hYmxlIGxvY2tlZCBvdXRwdXQgcG9ydA==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX2Fkdl9wYXJhbXM=::ZmFsc2U=::RW5hYmxlIHBoeXNpY2FsIG91dHB1dCBjbG9jayBwYXJhbWV0ZXJz" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX251bWJlcl9vZl9jbG9ja3M=::Mg==::TnVtYmVyIE9mIENsb2Nrcw==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "bnVtYmVyX29mX2Nsb2Nrcw==::Mg==::bnVtYmVyX29mX2Nsb2Nrcw==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX211bHRpcGx5X2ZhY3Rvcg==::MQ==::TXVsdGlwbHkgRmFjdG9yIChNLUNvdW50ZXIp" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2ZyYWNfbXVsdGlwbHlfZmFjdG9y::MQ==::RnJhY3Rpb25hbCBNdWx0aXBseSBGYWN0b3IgKEsp" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3Jfbg==::MQ==::RGl2aWRlIEZhY3RvciAoTi1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjA=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kw::MTEuMA==::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzA=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Iw::NDQ=::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjA=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMA==::MjAw::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MA==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMA==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MA==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzA=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDA=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUw::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kx::NDQuMA==::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Ix::NDQ=::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMQ==::NTA=::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MQ==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMQ==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MQ==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE=::LTYwLjA=::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUx::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjI=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3ky::MjAuMA==::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzI=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Iy::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjI=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMg==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Mg==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMg==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Mg==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzI=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDI=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUy::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjM=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kz::MTAuMA==::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzM=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Iz::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjM=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMw==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Mw==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMw==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Mw==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzM=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDM=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUz::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjQ=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k0::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzQ=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I0::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjQ=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNA==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5NA==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNA==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0NA==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzQ=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDQ=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU0::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjU=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k1::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzU=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I1::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjU=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNQ==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5NQ==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNQ==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0NQ==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzU=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDU=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU1::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjY=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k2::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzY=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I2::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjY=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNg==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Ng==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNg==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Ng==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzY=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDY=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU2::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjc=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k3::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzc=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I3::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3Rvcjc=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNw==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Nw==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNw==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Nw==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzc=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDc=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU3::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjg=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k4::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzg=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I4::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3Rvcjg=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yOA==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5OA==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzOA==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0OA==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzg=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDg=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU4::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjk=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k5::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzk=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I5::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3Rvcjk=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yOQ==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5OQ==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzOQ==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0OQ==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzk=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDk=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU5::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEw::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMA==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEw::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMA==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEw::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTA=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTA=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTA=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTA=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEw::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEw::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMA==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEx::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMQ==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEx::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMQ==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEx::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTE=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTE=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTE=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTE=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEx::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEx::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMQ==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEy::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMg==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEy::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMg==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEy::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTI=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTI=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTI=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTI=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEy::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEy::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMg==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEz::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMw==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEz::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMw==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEz::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTM=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTM=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTM=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTM=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEz::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEz::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMw==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE0::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNA==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE0::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNA==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE0::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTQ=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTQ=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTQ=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTQ=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE0::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE0::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNA==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE1::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNQ==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE1::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNQ==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE1::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTU=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTU=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTU=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTU=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE1::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE1::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNQ==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE2::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNg==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE2::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNg==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE2::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTY=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTY=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTY=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTY=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE2::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE2::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNg==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE3::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNw==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE3::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNw==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE3::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTc=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTc=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTc=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTc=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE3::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE3::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNw==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTA=::MTEuMDAwMDAwIE1Ieg==::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTA=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQw::MCBwcw==::cGhhc2Vfc2hpZnQw" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTA=::NTA=::ZHV0eV9jeWNsZTA=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE=::NDQuMDAwMDAwIE1Ieg==::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQx::MCBwcw==::cGhhc2Vfc2hpZnQx" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE=::NTA=::ZHV0eV9jeWNsZTE=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTI=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTI=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQy::MCBwcw==::cGhhc2Vfc2hpZnQy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTI=::NTA=::ZHV0eV9jeWNsZTI=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTM=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQz::MCBwcw==::cGhhc2Vfc2hpZnQz" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTM=::NTA=::ZHV0eV9jeWNsZTM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTQ=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ0::MCBwcw==::cGhhc2Vfc2hpZnQ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTQ=::NTA=::ZHV0eV9jeWNsZTQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTU=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTU=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ1::MCBwcw==::cGhhc2Vfc2hpZnQ1" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTU=::NTA=::ZHV0eV9jeWNsZTU=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTY=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTY=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ2::MCBwcw==::cGhhc2Vfc2hpZnQ2" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTY=::NTA=::ZHV0eV9jeWNsZTY=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTc=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTc=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ3::MCBwcw==::cGhhc2Vfc2hpZnQ3" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTc=::NTA=::ZHV0eV9jeWNsZTc=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTg=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTg=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ4::MCBwcw==::cGhhc2Vfc2hpZnQ4" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTg=::NTA=::ZHV0eV9jeWNsZTg=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTk=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTk=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ5::MCBwcw==::cGhhc2Vfc2hpZnQ5" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTk=::NTA=::ZHV0eV9jeWNsZTk=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEw::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEw" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMA==::MCBwcw==::cGhhc2Vfc2hpZnQxMA==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEw::NTA=::ZHV0eV9jeWNsZTEw" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEx::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEx" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMQ==::MCBwcw==::cGhhc2Vfc2hpZnQxMQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEx::NTA=::ZHV0eV9jeWNsZTEx" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEy::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMg==::MCBwcw==::cGhhc2Vfc2hpZnQxMg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEy::NTA=::ZHV0eV9jeWNsZTEy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEz::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEz" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMw==::MCBwcw==::cGhhc2Vfc2hpZnQxMw==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEz::NTA=::ZHV0eV9jeWNsZTEz" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE0::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNA==::MCBwcw==::cGhhc2Vfc2hpZnQxNA==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE0::NTA=::ZHV0eV9jeWNsZTE0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE1::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE1" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNQ==::MCBwcw==::cGhhc2Vfc2hpZnQxNQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE1::NTA=::ZHV0eV9jeWNsZTE1" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE2::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE2" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNg==::MCBwcw==::cGhhc2Vfc2hpZnQxNg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE2::NTA=::ZHV0eV9jeWNsZTE2" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE3::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE3" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNw==::MCBwcw==::cGhhc2Vfc2hpZnQxNw==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE3::NTA=::ZHV0eV9jeWNsZTE3" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BsbF9hdXRvX3Jlc2V0::T24=::UExMIEF1dG8gUmVzZXQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BsbF9iYW5kd2lkdGhfcHJlc2V0::QXV0bw==::UExMIEJhbmR3aWR0aCBQcmVzZXQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX3JlY29uZg==::ZmFsc2U=::RW5hYmxlIGR5bmFtaWMgcmVjb25maWd1cmF0aW9uIG9mIFBMTA==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX2Rwc19wb3J0cw==::ZmFsc2U=::RW5hYmxlIGFjY2VzcyB0byBkeW5hbWljIHBoYXNlIHNoaWZ0IHBvcnRz" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX3Bob3V0X3BvcnRz::ZmFsc2U=::RW5hYmxlIGFjY2VzcyB0byBQTEwgRFBBIG91dHB1dCBwb3J0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGxsX3R5cGU=::R2VuZXJhbA==::UExMIFRZUEU=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGxsX3N1YnR5cGU=::R2VuZXJhbA==::UExMIFNVQlRZUEU=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BhcmFtZXRlcl9saXN0::TS1Db3VudGVyIEhpIERpdmlkZSxNLUNvdW50ZXIgTG93IERpdmlkZSxOLUNvdW50ZXIgSGkgRGl2aWRlLE4tQ291bnRlciBMb3cgRGl2aWRlLE0tQ291bnRlciBCeXBhc3MgRW5hYmxlLE4tQ291bnRlciBCeXBhc3MgRW5hYmxlLE0tQ291bnRlciBPZGQgRGl2aWRlIEVuYWJsZSxOLUNvdW50ZXIgT2RkIERpdmlkZSBFbmFibGUsQy1Db3VudGVyLTAgSGkgRGl2aWRlLEMtQ291bnRlci0wIExvdyBEaXZpZGUsQy1Db3VudGVyLTAgQ29hcnNlIFBoYXNlIFNoaWZ0LEMtQ291bnRlci0wIFZDTyBQaGFzZSBUYXAsQy1Db3VudGVyLTAgSW5wdXQgU291cmNlLEMtQ291bnRlci0wIEJ5cGFzcyBFbmFibGUsQy1Db3VudGVyLTAgT2RkIERpdmlkZSBFbmFibGUsQy1Db3VudGVyLTEgSGkgRGl2aWRlLEMtQ291bnRlci0xIExvdyBEaXZpZGUsQy1Db3VudGVyLTEgQ29hcnNlIFBoYXNlIFNoaWZ0LEMtQ291bnRlci0xIFZDTyBQaGFzZSBUYXAsQy1Db3VudGVyLTEgSW5wdXQgU291cmNlLEMtQ291bnRlci0xIEJ5cGFzcyBFbmFibGUsQy1Db3VudGVyLTEgT2RkIERpdmlkZSBFbmFibGUsVkNPIFBvc3QgRGl2aWRlIENvdW50ZXIgRW5hYmxlLENoYXJnZSBQdW1wIGN1cnJlbnQgKHVBKSxMb29wIEZpbHRlciBCYW5kd2lkdGggUmVzaXN0b3IgKE9obXMpICxQTEwgT3V0cHV0IFZDTyBGcmVxdWVuY3ksSy1GcmFjdGlvbmFsIERpdmlzaW9uIFZhbHVlIChEU00pLEZlZWRiYWNrIENsb2NrIFR5cGUsRmVlZGJhY2sgQ2xvY2sgTVVYIDEsRmVlZGJhY2sgQ2xvY2sgTVVYIDIsTSBDb3VudGVyIFNvdXJjZSBNVVgsUExMIEF1dG8gUmVzZXQ=::UGFyYW1ldGVyIE5hbWVz" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BhcmFtZXRlcl92YWx1ZXM=::MjIsMjIsMywyLGZhbHNlLGZhbHNlLGZhbHNlLHRydWUsMjAsMjAsMSwwLHBoX211eF9jbGssZmFsc2UsZmFsc2UsNSw1LDEsMCxwaF9tdXhfY2xrLGZhbHNlLGZhbHNlLDIsMjAsMTAwMDAsNDQwLjAgTUh6LDEsbm9uZSxnbGIsbV9jbnQscGhfbXV4X2Nsayx0cnVl::UGFyYW1ldGVyIFZhbHVlcw==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX21pZl9nZW5lcmF0ZQ==::ZmFsc2U=::R2VuZXJhdGUgTUlGIGZpbGU=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9taWZfZHBz::ZmFsc2U=::RW5hYmxlIER5bmFtaWMgUGhhc2UgU2hpZnQgZm9yIE1JRiBzdHJlYW1pbmc=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Rwc19jbnRy::QzA=::RFBTIENvdW50ZXIgU2VsZWN0aW9u" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Rwc19udW0=::MQ==::TnVtYmVyIG9mIER5bmFtaWMgUGhhc2UgU2hpZnRz" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Rwc19kaXI=::UG9zaXRpdmU=::RHluYW1pYyBQaGFzZSBTaGlmdCBEaXJlY3Rpb24=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3JlZmNsa19zd2l0Y2g=::ZmFsc2U=::Q3JlYXRlIGEgc2Vjb25kIGlucHV0IGNsayAncmVmY2xrMSc=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9jYXNjYWRlX291dA==::ZmFsc2U=::Q3JlYXRlIGEgJ2Nhc2NhZGVfb3V0JyBzaWduYWwgdG8gY29ubmVjdCB3aXRoIGEgZG93bnN0cmVhbSBQTEw=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9jYXNjYWRlX2lu::ZmFsc2U=::Q3JlYXRlIGFuIGFkanBsbGluIG9yIGNjbGsgc2lnbmFsIHRvIGNvbm5lY3Qgd2l0aCBhbiB1cHN0cmVhbSBQTEw=" + +set_global_assignment -library "pll" -name VERILOG_FILE [file join $::quartus(qip_path) "pll.v"] +set_global_assignment -library "pll" -name VERILOG_FILE [file join $::quartus(qip_path) "pll/pll_0002.v"] +set_global_assignment -library "pll" -name QIP_FILE [file join $::quartus(qip_path) "pll/pll_0002.qip"] + +set_global_assignment -entity "pll_0002" -library "pll" -name IP_TOOL_NAME "altera_pll" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_TOOL_VERSION "17.0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_TOOL_ENV "mwpim" diff --git a/rtl/pll.v b/rtl/pll.v new file mode 100644 index 0000000..f052e7d --- /dev/null +++ b/rtl/pll.v @@ -0,0 +1,255 @@ +// megafunction wizard: %Altera PLL v17.0% +// GENERATION: XML +// pll.v + +// Generated using ACDS version 17.0 602 + +`timescale 1 ps / 1 ps +module pll ( + input wire refclk, // refclk.clk + input wire rst, // reset.reset + output wire outclk_0, // outclk0.clk + output wire outclk_1, // outclk1.clk + output wire locked // locked.export + ); + + pll_0002 pll_inst ( + .refclk (refclk), // refclk.clk + .rst (rst), // reset.reset + .outclk_0 (outclk_0), // outclk0.clk + .outclk_1 (outclk_1), // outclk1.clk + .locked (locked) // locked.export + ); + +endmodule +// Retrieval info: +// +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// IPFS_FILES : pll.vo +// RELATED_FILES: pll.v, pll_0002.v diff --git a/rtl/pll/pll_0002.qip b/rtl/pll/pll_0002.qip new file mode 100644 index 0000000..aec45eb --- /dev/null +++ b/rtl/pll/pll_0002.qip @@ -0,0 +1,4 @@ +set_instance_assignment -name PLL_COMPENSATION_MODE DIRECT -to "*pll_0002*|altera_pll:altera_pll_i*|*" + +set_instance_assignment -name PLL_AUTO_RESET ON -to "*pll_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_BANDWIDTH_PRESET AUTO -to "*pll_0002*|altera_pll:altera_pll_i*|*" diff --git a/rtl/pll/pll_0002.v b/rtl/pll/pll_0002.v new file mode 100644 index 0000000..11d74e8 --- /dev/null +++ b/rtl/pll/pll_0002.v @@ -0,0 +1,90 @@ +`timescale 1ns/10ps +module pll_0002( + + // interface 'refclk' + input wire refclk, + + // interface 'reset' + input wire rst, + + // interface 'outclk0' + output wire outclk_0, + + // interface 'outclk1' + output wire outclk_1, + + // interface 'locked' + output wire locked +); + + altera_pll #( + .fractional_vco_multiplier("false"), + .reference_clock_frequency("50.0 MHz"), + .operation_mode("direct"), + .number_of_clocks(2), + .output_clock_frequency0("11.000000 MHz"), + .phase_shift0("0 ps"), + .duty_cycle0(50), + .output_clock_frequency1("44.000000 MHz"), + .phase_shift1("0 ps"), + .duty_cycle1(50), + .output_clock_frequency2("0 MHz"), + .phase_shift2("0 ps"), + .duty_cycle2(50), + .output_clock_frequency3("0 MHz"), + .phase_shift3("0 ps"), + .duty_cycle3(50), + .output_clock_frequency4("0 MHz"), + .phase_shift4("0 ps"), + .duty_cycle4(50), + .output_clock_frequency5("0 MHz"), + .phase_shift5("0 ps"), + .duty_cycle5(50), + .output_clock_frequency6("0 MHz"), + .phase_shift6("0 ps"), + .duty_cycle6(50), + .output_clock_frequency7("0 MHz"), + .phase_shift7("0 ps"), + .duty_cycle7(50), + .output_clock_frequency8("0 MHz"), + .phase_shift8("0 ps"), + .duty_cycle8(50), + .output_clock_frequency9("0 MHz"), + .phase_shift9("0 ps"), + .duty_cycle9(50), + .output_clock_frequency10("0 MHz"), + .phase_shift10("0 ps"), + .duty_cycle10(50), + .output_clock_frequency11("0 MHz"), + .phase_shift11("0 ps"), + .duty_cycle11(50), + .output_clock_frequency12("0 MHz"), + .phase_shift12("0 ps"), + .duty_cycle12(50), + .output_clock_frequency13("0 MHz"), + .phase_shift13("0 ps"), + .duty_cycle13(50), + .output_clock_frequency14("0 MHz"), + .phase_shift14("0 ps"), + .duty_cycle14(50), + .output_clock_frequency15("0 MHz"), + .phase_shift15("0 ps"), + .duty_cycle15(50), + .output_clock_frequency16("0 MHz"), + .phase_shift16("0 ps"), + .duty_cycle16(50), + .output_clock_frequency17("0 MHz"), + .phase_shift17("0 ps"), + .duty_cycle17(50), + .pll_type("General"), + .pll_subtype("General") + ) altera_pll_i ( + .rst (rst), + .outclk ({outclk_1, outclk_0}), + .locked (locked), + .fboutclk ( ), + .fbclk (1'b0), + .refclk (refclk) + ); +endmodule + diff --git a/rtl/pll/pll_0002_q13.qip b/rtl/pll/pll_0002_q13.qip new file mode 100644 index 0000000..9f8ded1 --- /dev/null +++ b/rtl/pll/pll_0002_q13.qip @@ -0,0 +1,4 @@ +set_instance_assignment -name PLL_COMPENSATION_MODE DIRECT -to "*pll_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_CHANNEL_SPACING "0.0 KHz" -to "*pll_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_AUTO_RESET ON -to "*pll_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_BANDWIDTH_PRESET AUTO -to "*pll_0002*|altera_pll:altera_pll_i*|*" diff --git a/rtl/t400/CHANGELOG b/rtl/t400/CHANGELOG new file mode 100644 index 0000000..9328358 --- /dev/null +++ b/rtl/t400/CHANGELOG @@ -0,0 +1,19 @@ + +Change log for the T400 uController core +======================================== +Version: $Date: 2006/06/12 18:12:57 $ + + +Release 1.0 +----------- + +* Production test plus related testbench added. + +* Bugfix for + "Timer skipped in T421 configuration" + +* T421 system and testbench added. + +* T410 system and testbench added. + +* Regression test suite environment enhanced for T421 system. diff --git a/rtl/t400/COMPILE_LIST b/rtl/t400/COMPILE_LIST new file mode 100644 index 0000000..5bd6e93 --- /dev/null +++ b/rtl/t400/COMPILE_LIST @@ -0,0 +1,92 @@ +rtl/vhdl/t400_opt_pack-p.vhd +rtl/vhdl/t400_clkgen.vhd +rtl/vhdl/t400_clkgen-c.vhd +rtl/vhdl/t400_reset.vhd +rtl/vhdl/t400_reset-c.vhd +rtl/vhdl/t400_pack-p.vhd +bench/vhdl/tb_pack-p.vhd +rtl/vhdl/t400_pmem_ctrl.vhd +rtl/vhdl/t400_pmem_ctrl-c.vhd +rtl/vhdl/t400_dmem_ctrl.vhd +rtl/vhdl/t400_dmem_ctrl-c.vhd +rtl/vhdl/t400_opc_table.vhd +rtl/vhdl/t400_opc_table-c.vhd +rtl/vhdl/t400_comp_pack-p.vhd +rtl/vhdl/t400_decoder.vhd +rtl/vhdl/t400_decoder-c.vhd +rtl/vhdl/t400_skip.vhd +rtl/vhdl/t400_skip-c.vhd +rtl/vhdl/t400_alu.vhd +rtl/vhdl/t400_alu-c.vhd +rtl/vhdl/t400_stack.vhd +rtl/vhdl/t400_stack-c.vhd +rtl/vhdl/t400_io_pack-p.vhd +rtl/vhdl/t400_io_l.vhd +rtl/vhdl/t400_io_l-c.vhd +rtl/vhdl/t400_io_d.vhd +rtl/vhdl/t400_io_d-c.vhd +rtl/vhdl/t400_io_g.vhd +rtl/vhdl/t400_io_g-c.vhd +rtl/vhdl/t400_io_in.vhd +rtl/vhdl/t400_io_in-c.vhd +rtl/vhdl/t400_sio.vhd +rtl/vhdl/t400_sio-c.vhd +rtl/vhdl/t400_timer.vhd +rtl/vhdl/t400_timer-c.vhd +rtl/vhdl/t400_core.vhd +rtl/vhdl/t400_core-c.vhd +rtl/tech/generic/generic_ram_ena.vhd +rtl/tech/generic/generic_ram_ena-c.vhd +bench/vhdl/lpm_rom.vhd +rtl/vhdl/system/t410_rom-e.vhd +bench/vhdl/t410_rom-lpm-a.vhd +bench/vhdl/t410_rom-lpm-c.vhd +rtl/tech/cyclone/t400_por.vhd +rtl/tech/cyclone/t400_por-c.vhd +rtl/vhdl/t400_core_comp_pack-p.vhd +rtl/tech/t400_tech_comp_pack-p.vhd +rtl/vhdl/system/t410_notri.vhd +rtl/vhdl/system/t410_notri-c.vhd +rtl/vhdl/system/t400_system_comp_pack-p.vhd +rtl/vhdl/system/t410.vhd +rtl/vhdl/system/t410-c.vhd +bench/vhdl/tb_elems.vhd +bench/vhdl/tb_elems-c.vhd +bench/vhdl/tb_t410.vhd +bench/vhdl/tb_t410-c.vhd +Elaborate toplevel tb_t410_behav_c0. + +rtl/vhdl/system/t411.vhd +rtl/vhdl/system/t411-c.vhd +bench/vhdl/tb_t411.vhd +bench/vhdl/tb_t411-c.vhd +Elaborate toplevel tb_t411_behav_c0. + +rtl/vhdl/system/t420_rom-e.vhd +bench/vhdl/t420_rom-lpm-a.vhd +bench/vhdl/t420_rom-lpm-c.vhd +rtl/vhdl/system/t420_notri.vhd +rtl/vhdl/system/t420_notri-c.vhd +rtl/vhdl/system/t420.vhd +rtl/vhdl/system/t420-c.vhd +bench/vhdl/tb_t420.vhd +bench/vhdl/tb_t420-c.vhd +Elaborate toplevel tb_t420_behav_c0. + +rtl/vhdl/system/t421.vhd +rtl/vhdl/system/t421-c.vhd +bench/vhdl/tb_t421.vhd +bench/vhdl/tb_t421-c.vhd +Elaborate toplevel tb_t421_behav_c0. + +bench/vhdl/tb_int.vhd +bench/vhdl/tb_int-c.vhd +Elaborate toplevel tb_int_behav_c0. + +bench/vhdl/tb_microbus.vhd +bench/vhdl/tb_microbus-c.vhd +Elaborate toplevel tb_microbus_behav_c0. + +bench/vhdl/tb_prod.vhd +bench/vhdl/tb_prod-c.vhd +Elaborate toplevel tb_prod_behav_c0. diff --git a/rtl/t400/COPYING b/rtl/t400/COPYING new file mode 100644 index 0000000..60549be --- /dev/null +++ b/rtl/t400/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/rtl/t400/KNOWN_BUGS b/rtl/t400/KNOWN_BUGS new file mode 100644 index 0000000..50f3643 --- /dev/null +++ b/rtl/t400/KNOWN_BUGS @@ -0,0 +1,19 @@ + +Known bugs of the T400 uController core +======================================= +Version: $Date: 2006/06/12 18:12:57 $ + + +Release 0.1 BETA +---------------- + +******************************************************************************* +Timer skipped in T421 configuration + +When the generic opt_type_g is set to t400_opt_type_421_c inside t400_core, +the timer module is not included in the core. This is wrong because the COP421 +chip contains this timer. + +Fixed in: +t400_core.vhd 1.10 +Fix will be included in next release. diff --git a/rtl/t400/README b/rtl/t400/README new file mode 100644 index 0000000..709c098 --- /dev/null +++ b/rtl/t400/README @@ -0,0 +1,325 @@ + +README for the T400 uController project +======================================= +Version: $Date: 2006/06/12 18:12:57 $ + + +Introduction +------------ + +The T400 µController core is an implementation of the COP400 microcontroller +family architecture. + + +Download +-------- + +Download the latest stable release from the project homepage at OpenCores.org: + + http://www.opencores.org/projects.cgi/web/t400/overview/ + +You can get the latest version of the design files from CVS: + + http://www.opencores.org/pdownloads.cgi/list/t400 + +Please keep in mind that this is work in progress and might contain smaller or +bigger problems. +You should also check the Tracker for known bugs and see if they affect your +work. + + +Installation +------------ + +Once the directory structure is generated either by check-out from CVS or by +unpacking the tar-archive, the central project initialization file should be +set up. A template called init_project.template.sh is located in the sw +directory where a copy can be edited. Normally, only the definition for the +variable PROJECT_DIR has to be adjusted to the path where the directory +structure is located. +The commands for setting the necessary variables assume a bash/sh-like +shell. In case you run a different shell like csh or ksh, you should adjust +these commands as well. + +The meaning of the variables is as follows: + + * PROJECT_DIR + Points to the root of the project installation. All further references are + derived from its setting. + + * MAKEFILES + Identifies the global Makefile for compilation of tests. + +These variables must be properly set whenever scripts or makefiles of the T400 +project are executed that are related to verification tasks. Otherwise, you +will most likely encounter error messages. + +NOTE: The concepts of the mentioned shells require that the init_project.sh is + run in the context of the shell. I.e. you should 'source' the script + instead of executing it like a command. This will make sure that the + variable settings are really effective in the calling shell instance. + + +Directory Structure +------------------- + +The project's directory structure follows the proposal of OpenCores.org. + +t400 + | + \--+-- rtl + | | + | +-- vhdl : VHDL code containing the RTL description + | | | of the core. + | | \-- system : RTL VHDL code of sample systems. + | | + | \-- tech : Technology specific files. + | | + | +-- cyclone : Cyclone technology flavor. + | | + | +-- spartan : Spartan technology flavor. + | | + | \-- generic : Generic RTL designs. + | + +-- bench + | | + | \-- vhdl : VHDL testbench code. + | + +-- sim + | | + | \-- rtl_sim : Directory for running simulations. + | + \-- sw : General purpose scripts and files. + | + \-- verif : The verification suite. + | + +-- include : Global includes and makefiles. + | + +-- black_box : Black-box verification tests. + | + +-- int : Interrupt verification tests. + | + \-- system : General system level tests. + + +Compiling the VHDL Code +----------------------- + +VHDL compilation and simulation tasks take place inside in sim/rtl_sim +directory. The project setup supports only the batch mode of certain +simulators. However, there should be no problems to integrate the testbench +and RTL code into arbitrary simulation environments. + +The main file for compilation is Makefile which contains all information +regarding the dependencies of the source files and their compilation +order. + +Compilation is based on the make-utility, thus invocation looks like this: + + $ make + +This will call ghdl to analzye and elaborate the complete design hierarchy. + + Tristan Gingold's GHDL simulator/compiler, a VHDL front-end for gcc. + http://ghdl.free.fr/ + +Make will analyze all VHDL files (RTL and testbench code) and elaborate all +testbench top-levels: + + * tb_t410_behav_c0 + Testbench for the T410 derivative. + It instantiates the T410 system toplevel and is intended to exectue all + verifcation tests tagged with 't41x'. + + * tb_t411_behav_c0 + Testbench for the T411 derivative. + It instantiates the T411 system toplevel and is intended to exectue all + verifcation tests tagged with 't41x'. + + * tb_t420_behav_c0 + The testbench for the T420 derivative. + It instantiates the T420 system toplevel and is intended to execute all + verification tests tagged with 't42x' and 't420'. + + * tb_t421_behav_c0 + The testbench for the T421 derivative. + It instantiates the T421 system toplevel and is intended to execute all + verification tests tagged with 't42x'. + + * tb_int_behav_c0 + The testbench for the interrupt verification suite. + It instantiates the T420 system topevel and is intended to execute all + verification tests tagged with 'int'. + + * tb_microbus_behav_c0 + The testbench for the microbus verification. + It instantiates the T420 system toplevel in microbus configuration and is + intended to execute all verifications tests tagged with 'mb'. + + * tb_prod_behav_c0 + The testbench for the production test. + It instantiates the T420 system toplevel an checks D and P output ports + for the patterns generated by the software as proposed in + "Testing of COP400 Familiy Devices" + National Semiconductor + COP Note 7 + April 1991 + +The Makefile has a 'clean' target to delete all intermediate data: + + $ make clean + +The basic simple sequence list can be found in COMPILE_LIST. This can be +useful to quickly set up the analyze stage of any compiler or +synthesizer. Especially when synthesizing the code, you want to skip the VHDL +configurations in *-c.vhd and everything below the bench/ directory. + + +Preparation of the ROM Files +---------------------------- + +All testbenches listed above load the internal ROM of the controller from a +file in hex-format. Its existance is mandatory as it is referenced in the +VHDL code of the ROM model lpm_rom.vhd. In case it is missing, the +simulation will stop immediately after elaborating the design. + +These files are: + + * rom_41x.hex + Program ROM compiled for the T41x derivatives. Maximum size 512 bytes. + Referenced by the t410_notri system. + Enabled by the 't41x' tag. + + * rom_42x.hex + Program ROM compiled for the T42x derivatives. Maximum size 1024 bytes. + Referenced by the t420_notri system. + Enabled by the 't42x', 't420', 'int', 'mb' and 'prod' tag. + +The verification flow for the T400 project generates these two files +automatically from the assembler source files. Whenever the make process +locates one or more of the above tags, it assembles and links the source code +for the repsective derivative. + +All regression tests and the general purpose software is organized in a cell +structure. Currently, this means that the software for a cell is contained in +a dedicated directory where the assembler run takes place. In the future, +there will be more aspects to a cell. + +Assembling, linking and putting the hex-files in place is under the control of +the make-mechanism. E.g. to assemble the source code of a cell, issue the +following command: + + $ make + +The above mention environment variable MAKEFILES enables execution of the make +process from within any subdirectory in the verification tree. This generates +the linker file (test_41x.p and test_42x.p) and derives hex-files which are +placed into the simulation directory. So most likely, for running a test case +or any other software, you will want to issue: + +The only supported assembler is Alfred Arnold's macroassembler AS. See + + http://john.ccac.rwth-aachen.de:8000/as/ + + +Verification Environment +------------------------ + +The verification environment consists of a number of test programs. They are +all self-checking. I.e. after testing the targeted functionality, they emit a +pass/fail information. This information is detected by the testbench which +stops the simulation and prints out the simulation result. This is the default +mechanism for stopping the VHDL simulation. + +Pass/fail is signalled by a certain sequence of the L port contents: +(R denotes an optional value stored in A when calling the pass or fail +routines) + + 1) L outputs 0x0R + 2) L outputs 0xaR + 3) L outputs 0x5R + 4) L outputs 0x0R -> Pass + L outputs 0xfR -> Fail + +The detection is modelled like a state machine and in case the sequence is of +bytes inside the accumulator does not match, the detection process restarts +from the beginning. This mechanism is part of all verification tests except +for the interrupt testbench. + +The complete regression suite can be executed with the run_regression.pl +script. For each test cell, it steps through the sequence + + 1) Assemble the source code + 2) Run the compiled VHDL design (currently only GHDL) + +It is highly recommended to redirect the output of run_regression.pl into a +file. Otherwise, analyzing the messages related to each test cell is almost +impossible. + + +Clocking System +--------------- + +The main clock is supplied at input ck_i. To ease system integration, ck_i can +accept integer multiples of the target clock frequency. Input ck_en_i is used +to qualify rising edges on ck_i as active clock edges. When ck_i is supplied +with the target frequency, ck_en_i can be kept high constantly. + + +Generic Parameters +------------------ + +Most generic parameters are provided to set the numerous I/O options. Thus +such options are exhibited on the toplevel designs. +All generics are implemented with integer types to enable analysis of the RTL +code without tool restrictions. The related constants are defined in +t400_opt_pack-p.vhd. + + opt_type_g : Derivative type - T420, T421, T410, T411 + opt_ck_div_g : Internal divider on CK + opt_cko_g : Enable CKO as general purpose input + opt_l_out_type_7_g : Output driver type L[7] + opt_l_out_type_6_g : Output driver type L[6] + opt_l_out_type_5_g : Output driver type L[5] + opt_l_out_type_4_g : Output driver type L[4] + opt_l_out_type_3_g : Output driver type L[3] + opt_l_out_type_2_g : Output driver type L[2] + opt_l_out_type_1_g : Output driver type L[1] + opt_l_out_type_0_g : Output driver type L[0] + opt_microbus_g : Enable MICROBUS interface + opt_d_out_type_3_g : Output driver type D[3] + opt_d_out_type_2_g : Output driver type D[2] + opt_d_out_type_1_g : Output driver type D[1] + opt_d_out_type_0_g : Output driver type D[0] + opt_g_out_type_3_g : Output driver type G[3] + opt_g_out_type_2_g : Output driver type G[2] + opt_g_out_type_1_g : Output driver type G[1] + opt_g_out_type_0_g : Output driver type G[0] + opt_so_output_type_g : Output driver type SO + opt_sk_output_type_g : Output driver type SK + + +FPGA Implementation +------------------- + +All of the design files contain pure RTL code. This is true even for the +technology specific power-on reset module. Two flavors exist, each of them +implementing the desired behavior in a way that is understood by the design +tools. The RAM for the data memory is described by generic RTL code as +well. It should be translated automatically by the tool chain to a technology +specific RAM macro. + +There is a generic method for the program memory ROM as well, although this +project uses a flow where hex-files are loaded by lpm_rom.vhd as the default +method. Convert the ROM image to an RTL VHDL file with one of the two +following commands (either from hex or bin format): + + $ hex2rom -b [rom image file] rom_t41x 9l8s > rom_t41x.vhd + $ hex2rom -b [rom image file] rom_t42x 10l8s > rom_t42x.vhd + +The option -b specifies that contains binary data. Skip this +option to process a file in hex format. + +These resulting RTL representations are instantiated by t410_rom-struct-a.vhd +and t420_rom-struct-a.vhd. Altera and Xilinx design tools will detect and +extract the ROM and turn it into a memory macro. diff --git a/rtl/t400/bench/vhdl/tb_pack-p.vhd b/rtl/t400/bench/vhdl/tb_pack-p.vhd new file mode 100644 index 0000000..1b649bd --- /dev/null +++ b/rtl/t400/bench/vhdl/tb_pack-p.vhd @@ -0,0 +1,58 @@ +------------------------------------------------------------------------------- +-- +-- $Id: tb_pack-p.vhd,v 1.1.1.1 2006/06/10 18:06:11 arnim Exp $ +-- +-- Copyright (c) 2006, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.t400_pack.pc_t; + +package tb_pack is + + component tb_elems + generic ( + period_g : time := 4.75 us; + d_width_g : integer := 4; + g_width_g : integer := 4 + ); + port ( + io_l_i : in std_logic_vector(7 downto 0); + io_d_i : in std_logic_vector(d_width_g-1 downto 0); + io_g_i : in std_logic_vector(g_width_g-1 downto 0); + io_in_o : out std_logic_vector(g_width_g-1 downto 0); + so_i : in std_logic; + si_o : out std_logic; + sk_i : in std_logic; + ck_o : out std_logic + ); + end component; + + signal tb_pc_s : pc_t; + signal tb_sa_s : pc_t; + +end tb_pack; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: tb_pack-p.vhd,v $ +-- Revision 1.1.1.1 2006/06/10 18:06:11 arnim +-- copied from opencores.org repository, pre-1.0 release on 10-Jun-2006 +-- +-- Revision 1.3 2006/05/27 19:09:29 arniml +-- add global signals for testbench instrumentation +-- +-- Revision 1.2 2006/05/23 01:17:25 arniml +-- drive IN port +-- +-- Revision 1.1 2006/05/15 21:55:27 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/tech/cyclone/t400_por-c.vhd b/rtl/t400/rtl/tech/cyclone/t400_por-c.vhd new file mode 100644 index 0000000..a5e8ffe --- /dev/null +++ b/rtl/t400/rtl/tech/cyclone/t400_por-c.vhd @@ -0,0 +1,23 @@ +------------------------------------------------------------------------------- +-- $Id: t400_por-c.vhd,v 1.2 2006/05/07 01:49:16 arniml Exp $ +------------------------------------------------------------------------------- + +configuration t400_por_rtl_c0 of t400_por is + + for cyclone + end for; + +end t400_por_rtl_c0; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t400_por-c.vhd,v $ +-- Revision 1.2 2006/05/07 01:49:16 arniml +-- renamed to rtl +-- +-- Revision 1.1.1.1 2006/05/06 01:56:44 arniml +-- import from local CVS repository, LOC_CVS_0_1 +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/tech/cyclone/t400_por.vhd b/rtl/t400/rtl/tech/cyclone/t400_por.vhd new file mode 100644 index 0000000..e3f12c6 --- /dev/null +++ b/rtl/t400/rtl/tech/cyclone/t400_por.vhd @@ -0,0 +1,125 @@ +------------------------------------------------------------------------------- +-- +-- T400 Core +-- +-- $Id: t400_por.vhd,v 1.1.1.1 2006/05/06 01:56:44 arniml Exp $ +-- +-- Wrapper for technology dependent power-on reset circuitry. +-- +-- Altera Cyclone flavor. +-- +-- Generate a reset upon power-on for specified number of clocks. +-- +------------------------------------------------------------------------------- +-- +-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity t400_por is + + generic ( + delay_g : integer := 4; + cnt_width_g : integer := 2 + ); + port ( + clk_i : in std_logic; + por_n_o : out std_logic + ); + +end t400_por; + + +library ieee; +use ieee.numeric_std.all; + +architecture cyclone of t400_por is + + signal por_cnt_q : unsigned(cnt_width_g-1 downto 0) + -- pragma translate_off + -- initialize for simulation only + := (others => '0') + -- pragma translate_on + ; + signal por_n_q : std_logic + -- pragma translate_off + -- initialize for simulation only + := '0' + -- pragma translate_on + ; + + -- Specify power-up level of por counter and por source. + -- Refer to "Quartus II Integrated Synthesis", section "Altera Attribute". + attribute altera_attribute : string; + attribute altera_attribute of por_cnt_q : signal is "-name POWER_UP_LEVEL LOW"; + attribute altera_attribute of por_n_q : signal is "-name POWER_UP_LEVEL LOW"; + +begin + + ----------------------------------------------------------------------------- + -- Process por_cnt + -- + -- Purpose: + -- Generate a power-on reset for the specifiec number of clocks. + -- + por_cnt: process (clk_i) + begin + if clk_i'event and clk_i = '1' then + if por_cnt_q = delay_g-1 then + por_n_q <= '1'; + else + por_cnt_q <= por_cnt_q + 1; + end if; + end if; + end process por_cnt; + -- + ----------------------------------------------------------------------------- + + por_n_o <= por_n_q; + +end cyclone; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t400_por.vhd,v $ +-- Revision 1.1.1.1 2006/05/06 01:56:44 arniml +-- import from local CVS repository, LOC_CVS_0_1 +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/tech/generic/generic_ram-c.vhd b/rtl/t400/rtl/tech/generic/generic_ram-c.vhd new file mode 100644 index 0000000..8a42209 --- /dev/null +++ b/rtl/t400/rtl/tech/generic/generic_ram-c.vhd @@ -0,0 +1,18 @@ +------------------------------------------------------------------------------- +-- +-- Parametrizable, generic RAM. +-- +-- $Id: generic_ram-c.vhd,v 1.1.1.1 2006/05/06 01:56:44 arniml Exp $ +-- +-- Copyright (c) 2006, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +configuration generic_ram_rtl_c0 of generic_ram is + + for rtl + end for; + +end generic_ram_rtl_c0; diff --git a/rtl/t400/rtl/tech/generic/generic_ram.vhd b/rtl/t400/rtl/tech/generic/generic_ram.vhd new file mode 100644 index 0000000..5303995 --- /dev/null +++ b/rtl/t400/rtl/tech/generic/generic_ram.vhd @@ -0,0 +1,94 @@ +------------------------------------------------------------------------------- +-- +-- Parametrizable, generic RAM. +-- +-- $Id: generic_ram.vhd,v 1.1.1.1 2006/05/06 01:56:44 arniml Exp $ +-- +-- Copyright (c) 2006 Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t400/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity generic_ram is + + generic ( + addr_width_g : integer := 10; + data_width_g : integer := 8 + ); + port ( + clk_i : in std_logic; + a_i : in std_logic_vector(addr_width_g-1 downto 0); + we_i : in std_logic; + d_i : in std_logic_vector(data_width_g-1 downto 0); + d_o : out std_logic_vector(data_width_g-1 downto 0) + ); + +end generic_ram; + + +library ieee; +use ieee.numeric_std.all; + +architecture rtl of generic_ram is + + type mem_t is array (natural range 0 to 2**addr_width_g-1) of + std_logic_vector(d_i'range); + signal mem_q : mem_t + -- pragma translate_off + := (others => (others => '0')) + -- pragma translate_on + ; + +begin + + mem: process (clk_i) + begin + + if clk_i'event and clk_i = '1' then + if we_i = '1' then + mem_q(to_integer(unsigned(a_i))) <= d_i; + end if; + + d_o <= mem_q(to_integer(unsigned(a_i))); + end if; + + end process mem; + +end rtl; diff --git a/rtl/t400/rtl/tech/generic/generic_ram_ena-c.vhd b/rtl/t400/rtl/tech/generic/generic_ram_ena-c.vhd new file mode 100644 index 0000000..aeed632 --- /dev/null +++ b/rtl/t400/rtl/tech/generic/generic_ram_ena-c.vhd @@ -0,0 +1,18 @@ +------------------------------------------------------------------------------- +-- +-- Parametrizable, generic RAM with enable. +-- +-- $Id: generic_ram_ena-c.vhd,v 1.1.1.1 2006/06/10 17:50:15 arnim Exp $ +-- +-- Copyright (c) 2006, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +configuration generic_ram_ena_rtl_c0 of generic_ram_ena is + + for rtl + end for; + +end generic_ram_ena_rtl_c0; diff --git a/rtl/t400/rtl/tech/generic/generic_ram_ena.vhd b/rtl/t400/rtl/tech/generic/generic_ram_ena.vhd new file mode 100644 index 0000000..78f6ac2 --- /dev/null +++ b/rtl/t400/rtl/tech/generic/generic_ram_ena.vhd @@ -0,0 +1,97 @@ +------------------------------------------------------------------------------- +-- +-- Parametrizable, generic RAM with enable. +-- +-- $Id: generic_ram_ena.vhd,v 1.1.1.1 2006/06/10 17:50:15 arnim Exp $ +-- +-- Copyright (c) 2006 Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t400/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity generic_ram_ena is + + generic ( + addr_width_g : integer := 10; + data_width_g : integer := 8 + ); + port ( + clk_i : in std_logic; + a_i : in std_logic_vector(addr_width_g-1 downto 0); + we_i : in std_logic; + ena_i : in std_logic; + d_i : in std_logic_vector(data_width_g-1 downto 0); + d_o : out std_logic_vector(data_width_g-1 downto 0) + ); + +end generic_ram_ena; + + +library ieee; +use ieee.numeric_std.all; + +architecture rtl of generic_ram_ena is + + type mem_t is array (natural range 0 to 2**addr_width_g-1) of + std_logic_vector(d_i'range); + signal mem_q : mem_t + -- pragma translate_off + := (others => (others => '0')) + -- pragma translate_on + ; + +begin + + mem: process (clk_i) + begin + + if clk_i'event and clk_i = '1' then + if ena_i = '1' then + if we_i = '1' then + mem_q(to_integer(unsigned(a_i))) <= d_i; + end if; + + d_o <= mem_q(to_integer(unsigned(a_i))); + end if; + + end if; + end process mem; + +end rtl; diff --git a/rtl/t400/rtl/tech/spartan/t400_por-c.vhd b/rtl/t400/rtl/tech/spartan/t400_por-c.vhd new file mode 100644 index 0000000..5bb5490 --- /dev/null +++ b/rtl/t400/rtl/tech/spartan/t400_por-c.vhd @@ -0,0 +1,20 @@ +------------------------------------------------------------------------------- +-- $Id: t400_por-c.vhd,v 1.1 2006/05/07 01:47:51 arniml Exp $ +------------------------------------------------------------------------------- + +configuration t400_por_rtl_c0 of t400_por is + + for spartan + end for; + +end t400_por_rtl_c0; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t400_por-c.vhd,v $ +-- Revision 1.1 2006/05/07 01:47:51 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/tech/spartan/t400_por.vhd b/rtl/t400/rtl/tech/spartan/t400_por.vhd new file mode 100644 index 0000000..b0a6323 --- /dev/null +++ b/rtl/t400/rtl/tech/spartan/t400_por.vhd @@ -0,0 +1,107 @@ +------------------------------------------------------------------------------- +-- +-- T400 Core +-- +-- $Id: t400_por.vhd,v 1.1 2006/05/07 01:47:51 arniml Exp $ +-- +-- Wrapper for technology dependent power-on reset circuitry. +-- +-- Xilinx Spartan3 flavor. +-- +-- Generate a reset upon power-on for specified number of clocks. +-- +------------------------------------------------------------------------------- +-- +-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity t400_por is + + generic ( + delay_g : integer := 4; + cnt_width_g : integer := 2 + ); + port ( + clk_i : in std_logic; + por_n_o : out std_logic + ); + +end t400_por; + + +library ieee; +use ieee.numeric_std.all; + +architecture spartan of t400_por is + + ----------------------------------------------------------------------------- + -- According to + -- "XST User Guide", Chapter 6 "VHDL Language Support", "Initial Values" + -- XST honors the initial value assigned to a flip-flop. Simple :-) + -- + signal por_cnt_q : unsigned(cnt_width_g-1 downto 0) + := to_unsigned(delay_g, cnt_width_g); + signal por_n_q : std_logic := '0'; + -- + ----------------------------------------------------------------------------- + +begin + + ----------------------------------------------------------------------------- + -- Process por_cnt + -- + -- Purpose: + -- Generate a power-on reset for the specified number of clocks. + -- + por_cnt: process (clk_i) + begin + if clk_i'event and clk_i = '1' then + if por_cnt_q = 0 then + por_n_q <= '1'; + else + por_cnt_q <= por_cnt_q - 1; + end if; + end if; + end process por_cnt; + -- + ----------------------------------------------------------------------------- + + por_n_o <= por_n_q; + +end spartan; diff --git a/rtl/t400/rtl/tech/t400_tech_comp_pack-p.vhd b/rtl/t400/rtl/tech/t400_tech_comp_pack-p.vhd new file mode 100644 index 0000000..ba73a06 --- /dev/null +++ b/rtl/t400/rtl/tech/t400_tech_comp_pack-p.vhd @@ -0,0 +1,70 @@ +------------------------------------------------------------------------------- +-- +-- $Id: t400_tech_comp_pack-p.vhd,v 1.2 2006/06/05 20:31:00 arniml Exp $ +-- +-- Copyright (c) 2006, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +package t400_tech_comp_pack is + + component t400_por + generic ( + delay_g : integer := 4; + cnt_width_g : integer := 2 + ); + port ( + clk_i : in std_logic; + por_n_o : out std_logic + ); + end component; + + component generic_ram + generic ( + addr_width_g : integer := 10; + data_width_g : integer := 8 + ); + port ( + clk_i : in std_logic; + a_i : in std_logic_vector(addr_width_g-1 downto 0); + we_i : in std_logic; + d_i : in std_logic_vector(data_width_g-1 downto 0); + d_o : out std_logic_vector(data_width_g-1 downto 0) + ); + end component; + + component generic_ram_ena + generic ( + addr_width_g : integer := 10; + data_width_g : integer := 8 + ); + port ( + clk_i : in std_logic; + a_i : in std_logic_vector(addr_width_g-1 downto 0); + we_i : in std_logic; + ena_i : in std_logic; + d_i : in std_logic_vector(data_width_g-1 downto 0); + d_o : out std_logic_vector(data_width_g-1 downto 0) + ); + end component; + + +end t400_tech_comp_pack; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t400_tech_comp_pack-p.vhd,v $ +-- Revision 1.2 2006/06/05 20:31:00 arniml +-- generic_ram_ena added +-- +-- Revision 1.1.1.1 2006/05/06 01:56:44 arniml +-- import from local CVS repository, LOC_CVS_0_1 +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/system/t400_system_comp_pack-p.vhd b/rtl/t400/rtl/vhdl/system/t400_system_comp_pack-p.vhd new file mode 100644 index 0000000..075fc8a --- /dev/null +++ b/rtl/t400/rtl/vhdl/system/t400_system_comp_pack-p.vhd @@ -0,0 +1,278 @@ +------------------------------------------------------------------------------- +-- +-- $Id: t400_system_comp_pack-p.vhd,v 1.6 2006/06/11 22:18:52 arniml Exp $ +-- +-- Copyright (c) 2006, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.t400_opt_pack.all; + +package t400_system_comp_pack is + + component t410_notri + generic ( + opt_ck_div_g : integer := t400_opt_ck_div_16_c; + opt_cko_g : integer := t400_opt_cko_crystal_c; + opt_l_out_type_7_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_6_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_5_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_4_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_3_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_3_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_3_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_so_output_type_g : integer := t400_opt_out_type_std_c; + opt_sk_output_type_g : integer := t400_opt_out_type_std_c + ); + port ( + ck_i : in std_logic; + ck_en_i : in std_logic; + reset_n_i : in std_logic; + cko_i : in std_logic; + io_l_i : in std_logic_vector(7 downto 0); + io_l_o : out std_logic_vector(7 downto 0); + io_l_en_o : out std_logic_vector(7 downto 0); + io_d_o : out std_logic_vector(3 downto 0); + io_d_en_o : out std_logic_vector(3 downto 0); + io_g_i : in std_logic_vector(3 downto 0); + io_g_o : out std_logic_vector(3 downto 0); + io_g_en_o : out std_logic_vector(3 downto 0); + si_i : in std_logic; + so_o : out std_logic; + so_en_o : out std_logic; + sk_o : out std_logic; + sk_en_o : out std_logic + ); + end component; + + component t410 + generic ( + opt_ck_div_g : integer := t400_opt_ck_div_16_c; + opt_l_out_type_7_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_6_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_5_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_4_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_3_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_3_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_3_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_so_output_type_g : integer := t400_opt_out_type_std_c; + opt_sk_output_type_g : integer := t400_opt_out_type_std_c + ); + port ( + ck_i : in std_logic; + ck_en_i : in std_logic; + reset_n_i : in std_logic; + io_l_b : inout std_logic_vector(7 downto 0); + io_d_o : out std_logic_vector(3 downto 0); + io_g_b : inout std_logic_vector(3 downto 0); + si_i : in std_logic; + so_o : out std_logic; + sk_o : out std_logic + ); + end component; + + component t411 + generic ( + opt_ck_div_g : integer := t400_opt_ck_div_16_c; + opt_l_out_type_7_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_6_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_5_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_4_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_3_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_so_output_type_g : integer := t400_opt_out_type_std_c; + opt_sk_output_type_g : integer := t400_opt_out_type_std_c + ); + port ( + ck_i : in std_logic; + ck_en_i : in std_logic; + reset_n_i : in std_logic; + si_i : in std_logic; + so_o : out std_logic; + sk_o : out std_logic; + io_l_b : inout std_logic_vector(7 downto 0); + io_d_o : out std_logic_vector(1 downto 0); + io_g_b : inout std_logic_vector(2 downto 0) + ); + end component; + + component t420_notri + generic ( + opt_type_g : integer := t400_opt_type_420_c; + opt_ck_div_g : integer := t400_opt_ck_div_16_c; + opt_cko_g : integer := t400_opt_cko_crystal_c; + opt_l_out_type_7_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_6_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_5_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_4_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_3_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_microbus_g : integer := t400_opt_no_microbus_c; + opt_d_out_type_3_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_3_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_so_output_type_g : integer := t400_opt_out_type_std_c; + opt_sk_output_type_g : integer := t400_opt_out_type_std_c + ); + port ( + ck_i : in std_logic; + ck_en_i : in std_logic; + reset_n_i : in std_logic; + cko_i : in std_logic; + io_l_i : in std_logic_vector(7 downto 0); + io_l_o : out std_logic_vector(7 downto 0); + io_l_en_o : out std_logic_vector(7 downto 0); + io_d_o : out std_logic_vector(3 downto 0); + io_d_en_o : out std_logic_vector(3 downto 0); + io_g_i : in std_logic_vector(3 downto 0); + io_g_o : out std_logic_vector(3 downto 0); + io_g_en_o : out std_logic_vector(3 downto 0); + io_in_i : in std_logic_vector(3 downto 0); + si_i : in std_logic; + so_o : out std_logic; + so_en_o : out std_logic; + sk_o : out std_logic; + sk_en_o : out std_logic + ); + end component; + + component t420 + generic ( + opt_ck_div_g : integer := t400_opt_ck_div_16_c; + opt_cko_g : integer := t400_opt_cko_crystal_c; + opt_l_out_type_7_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_6_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_5_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_4_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_3_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_microbus_g : integer := t400_opt_no_microbus_c; + opt_d_out_type_3_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_3_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_so_output_type_g : integer := t400_opt_out_type_std_c; + opt_sk_output_type_g : integer := t400_opt_out_type_std_c + ); + port ( + ck_i : in std_logic; + ck_en_i : in std_logic; + reset_n_i : in std_logic; + cko_i : in std_logic; + io_l_b : inout std_logic_vector(7 downto 0); + io_d_o : out std_logic_vector(3 downto 0); + io_g_b : inout std_logic_vector(3 downto 0); + io_in_i : in std_logic_vector(3 downto 0); + si_i : in std_logic; + so_o : out std_logic; + sk_o : out std_logic + ); + end component; + + component t421 + generic ( + opt_ck_div_g : integer := t400_opt_ck_div_8_c; + opt_cko_g : integer := t400_opt_cko_crystal_c; + opt_l_out_type_7_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_6_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_5_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_4_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_3_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_3_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_3_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_so_output_type_g : integer := t400_opt_out_type_std_c; + opt_sk_output_type_g : integer := t400_opt_out_type_std_c + ); + port ( + ck_i : in std_logic; + ck_en_i : in std_logic; + reset_n_i : in std_logic; + cko_i : in std_logic; + io_l_b : inout std_logic_vector(7 downto 0); + io_d_o : out std_logic_vector(3 downto 0); + io_g_b : inout std_logic_vector(3 downto 0); + si_i : in std_logic; + so_o : out std_logic; + sk_o : out std_logic + ); + end component; + +end t400_system_comp_pack; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t400_system_comp_pack-p.vhd,v $ +-- Revision 1.6 2006/06/11 22:18:52 arniml +-- added t410 +-- +-- Revision 1.5 2006/06/11 13:48:13 arniml +-- * t421 added +-- * fixed generic list for t420 and t420_notri +-- +-- Revision 1.4 2006/06/05 20:02:46 arniml +-- use microbus generic +-- +-- Revision 1.3 2006/05/23 01:16:19 arniml +-- routi CKO to t400_core +-- +-- Revision 1.2 2006/05/14 22:29:33 arniml +-- t420 hierarchies added +-- +-- Revision 1.1.1.1 2006/05/06 01:56:45 arniml +-- import from local CVS repository, LOC_CVS_0_1 +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/system/t410-c.vhd b/rtl/t400/rtl/vhdl/system/t410-c.vhd new file mode 100644 index 0000000..800957e --- /dev/null +++ b/rtl/t400/rtl/vhdl/system/t410-c.vhd @@ -0,0 +1,69 @@ +------------------------------------------------------------------------------- +-- +-- T410 system toplevel. +-- +-- $Id: t410-c.vhd,v 1.1.1.1 2006/06/12 18:12:58 arnim Exp $ +-- +-- Copyright (c) 2006 Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t400/ +-- +------------------------------------------------------------------------------- + +configuration t410_struct_c0 of t410 is + + for struct + + for t410_notri_b: t410_notri + use configuration work.t410_notri_struct_c0; + end for; + + end for; + +end t410_struct_c0; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t410-c.vhd,v $ +-- Revision 1.1.1.1 2006/06/12 18:12:58 arnim +-- copied from opencores.org repository, 1.0 release +-- +-- Revision 1.1 2006/06/11 22:18:28 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/system/t410.vhd b/rtl/t400/rtl/vhdl/system/t410.vhd new file mode 100644 index 0000000..f5e078a --- /dev/null +++ b/rtl/t400/rtl/vhdl/system/t410.vhd @@ -0,0 +1,201 @@ +------------------------------------------------------------------------------- +-- +-- T410 system toplevel. +-- +-- $Id: t410.vhd,v 1.1.1.1 2006/06/12 18:12:58 arnim Exp $ +-- +-- Copyright (c) 2006 Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t400/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.t400_opt_pack.all; + +entity t410 is + + generic ( + opt_ck_div_g : integer := t400_opt_ck_div_16_c; + opt_l_out_type_7_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_6_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_5_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_4_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_3_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_3_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_3_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_so_output_type_g : integer := t400_opt_out_type_std_c; + opt_sk_output_type_g : integer := t400_opt_out_type_std_c + ); + port ( + ck_i : in std_logic; + ck_en_i : in std_logic; + reset_n_i : in std_logic; + io_l_b : inout std_logic_vector(7 downto 0); + io_d_o : out std_logic_vector(3 downto 0); + io_g_b : inout std_logic_vector(3 downto 0); + si_i : in std_logic; + so_o : out std_logic; + sk_o : out std_logic + ); + +end t410; + + +use work.t400_system_comp_pack.t410_notri; + +architecture struct of t410 is + + signal io_l_from_t410_s, + io_l_en_s : std_logic_vector(7 downto 0); + signal io_d_from_t410_s, + io_d_en_s : std_logic_vector(3 downto 0); + signal io_g_to_t410_s, + io_g_from_t410_s, + io_g_en_s : std_logic_vector(3 downto 0); + + signal so_s, + so_en_s : std_logic; + signal sk_s, + sk_en_s : std_logic; + + signal gnd_s : std_logic; + +begin + + gnd_s <= '0'; + + ----------------------------------------------------------------------------- + -- T410 without tri-states + ----------------------------------------------------------------------------- + t410_notri_b : t410_notri + generic map ( + opt_ck_div_g => opt_ck_div_g, + opt_cko_g => t400_opt_cko_crystal_c, + opt_l_out_type_7_g => opt_l_out_type_7_g, + opt_l_out_type_6_g => opt_l_out_type_6_g, + opt_l_out_type_5_g => opt_l_out_type_5_g, + opt_l_out_type_4_g => opt_l_out_type_4_g, + opt_l_out_type_3_g => opt_l_out_type_3_g, + opt_l_out_type_2_g => opt_l_out_type_2_g, + opt_l_out_type_1_g => opt_l_out_type_1_g, + opt_l_out_type_0_g => opt_l_out_type_0_g, + opt_d_out_type_3_g => opt_d_out_type_3_g, + opt_d_out_type_2_g => opt_d_out_type_2_g, + opt_d_out_type_1_g => opt_d_out_type_1_g, + opt_d_out_type_0_g => opt_d_out_type_0_g, + opt_g_out_type_3_g => opt_g_out_type_3_g, + opt_g_out_type_2_g => opt_g_out_type_2_g, + opt_g_out_type_1_g => opt_g_out_type_1_g, + opt_g_out_type_0_g => opt_g_out_type_0_g, + opt_so_output_type_g => opt_so_output_type_g, + opt_sk_output_type_g => opt_sk_output_type_g + ) + port map ( + ck_i => ck_i, + ck_en_i => ck_en_i, + reset_n_i => reset_n_i, + cko_i => gnd_s, + io_l_i => io_l_b, + io_l_o => io_l_from_t410_s, + io_l_en_o => io_l_en_s, + io_d_o => io_d_from_t410_s, + io_d_en_o => io_d_en_s, + io_g_i => io_g_b, + io_g_o => io_g_from_t410_s, + io_g_en_o => io_g_en_s, + si_i => si_i, + so_o => so_s, + so_en_o => so_en_s, + sk_o => sk_s, + sk_en_o => sk_en_s + ); + + + ----------------------------------------------------------------------------- + -- Tri-states for output drivers + ----------------------------------------------------------------------------- + io_l_tri: for idx in 7 downto 0 generate + io_l_b(idx) <= io_l_from_t410_s(idx) + when io_l_en_s(idx) = '1' else + 'Z'; + end generate; + -- + io_d_tri: for idx in 3 downto 0 generate + io_d_o(idx) <= io_d_from_t410_s(idx) + when io_d_en_s(idx) = '1' else + 'Z'; + end generate; + -- + io_g_tri: for idx in 3 downto 0 generate + io_g_b(idx) <= io_g_from_t410_s(idx) + when io_g_en_s(idx) = '1' else + 'Z'; + end generate; + -- + so_o <= so_s + when so_en_s = '1' else + 'Z'; + -- + sk_o <= sk_s + when sk_en_s = '1' else + 'Z'; + +end struct; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t410.vhd,v $ +-- Revision 1.1.1.1 2006/06/12 18:12:58 arnim +-- copied from opencores.org repository, 1.0 release +-- +-- Revision 1.1 2006/06/11 22:18:28 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/system/t410_notri-c.vhd b/rtl/t400/rtl/vhdl/system/t410_notri-c.vhd new file mode 100644 index 0000000..5152d39 --- /dev/null +++ b/rtl/t400/rtl/vhdl/system/t410_notri-c.vhd @@ -0,0 +1,51 @@ +------------------------------------------------------------------------------- +-- +-- T410/411 controller toplevel without tri-states. +-- +-- $Id: t410_notri-c.vhd,v 1.3 2006/06/05 20:03:11 arniml Exp $ +-- +-- Copyright (c) 2006, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +configuration t410_notri_struct_c0 of t410_notri is + + for struct + + for core_b: t400_core + use configuration work.t400_core_struct_c0; + end for; + + for pmem_b: t410_rom + use configuration work.t410_rom_struct_c0; + end for; + + for dmem_b: generic_ram_ena + use configuration work.generic_ram_ena_rtl_c0; + end for; + + for por_b: t400_por + use configuration work.t400_por_rtl_c0; + end for; + + end for; + +end t410_notri_struct_c0; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t410_notri-c.vhd,v $ +-- Revision 1.3 2006/06/05 20:03:11 arniml +-- include generic_ram_ena +-- +-- Revision 1.2 2006/05/07 01:49:03 arniml +-- renamed t400_por configuration to rtl +-- +-- Revision 1.1.1.1 2006/05/06 01:56:45 arniml +-- import from local CVS repository, LOC_CVS_0_1 +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/system/t410_notri.vhd b/rtl/t400/rtl/vhdl/system/t410_notri.vhd new file mode 100644 index 0000000..c1e5846 --- /dev/null +++ b/rtl/t400/rtl/vhdl/system/t410_notri.vhd @@ -0,0 +1,243 @@ +------------------------------------------------------------------------------- +-- +-- T410/411 controller toplevel without tri-states. +-- +-- $Id: t410_notri.vhd,v 1.3 2006/06/05 20:03:11 arniml Exp $ +-- +-- Copyright (c) 2006 Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t400/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.t400_opt_pack.all; + +entity t410_notri is + + generic ( + opt_ck_div_g : integer := t400_opt_ck_div_16_c; + opt_cko_g : integer := t400_opt_cko_crystal_c; + opt_l_out_type_7_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_6_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_5_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_4_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_3_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_3_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_3_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_so_output_type_g : integer := t400_opt_out_type_std_c; + opt_sk_output_type_g : integer := t400_opt_out_type_std_c + ); + port ( + ck_i : in std_logic; + ck_en_i : in std_logic; + reset_n_i : in std_logic; + cko_i : in std_logic; + io_l_i : in std_logic_vector(7 downto 0); + io_l_o : out std_logic_vector(7 downto 0); + io_l_en_o : out std_logic_vector(7 downto 0); + io_d_o : out std_logic_vector(3 downto 0); + io_d_en_o : out std_logic_vector(3 downto 0); + io_g_i : in std_logic_vector(3 downto 0); + io_g_o : out std_logic_vector(3 downto 0); + io_g_en_o : out std_logic_vector(3 downto 0); + si_i : in std_logic; + so_o : out std_logic; + so_en_o : out std_logic; + sk_o : out std_logic; + sk_en_o : out std_logic + ); + +end t410_notri; + + +use work.t400_core_comp_pack.t400_core; +use work.t400_tech_comp_pack.t400_por; +use work.t400_tech_comp_pack.generic_ram_ena; + +architecture struct of t410_notri is + + component t410_rom + port ( + ck_i : in std_logic; + addr_i : in std_logic_vector(8 downto 0); + data_o : out std_logic_vector(7 downto 0) + ); + end component; + + signal por_n_s : std_logic; + + signal pm_addr_s : std_logic_vector(9 downto 0); + signal pm_data_s : std_logic_vector(7 downto 0); + + signal dm_addr_s : std_logic_vector(5 downto 0); + signal dm_we_s : std_logic; + signal dm_data_to_core_s, + dm_data_from_core_s : std_logic_vector(3 downto 0); + + signal gnd4_s : std_logic_vector(3 downto 0); + +begin + + gnd4_s <= (others => '0'); + + ----------------------------------------------------------------------------- + -- T400 core + ----------------------------------------------------------------------------- + core_b : t400_core + generic map ( + opt_type_g => t400_opt_type_410_c, + opt_ck_div_g => opt_ck_div_g, + opt_cko_g => opt_cko_g, + opt_l_out_type_7_g => opt_l_out_type_7_g, + opt_l_out_type_6_g => opt_l_out_type_6_g, + opt_l_out_type_5_g => opt_l_out_type_5_g, + opt_l_out_type_4_g => opt_l_out_type_4_g, + opt_l_out_type_3_g => opt_l_out_type_3_g, + opt_l_out_type_2_g => opt_l_out_type_2_g, + opt_l_out_type_1_g => opt_l_out_type_1_g, + opt_l_out_type_0_g => opt_l_out_type_0_g, + opt_microbus_g => t400_opt_no_microbus_c, + opt_d_out_type_3_g => opt_d_out_type_3_g, + opt_d_out_type_2_g => opt_d_out_type_2_g, + opt_d_out_type_1_g => opt_d_out_type_1_g, + opt_d_out_type_0_g => opt_d_out_type_0_g, + opt_g_out_type_3_g => opt_g_out_type_3_g, + opt_g_out_type_2_g => opt_g_out_type_2_g, + opt_g_out_type_1_g => opt_g_out_type_1_g, + opt_g_out_type_0_g => opt_g_out_type_0_g, + opt_so_output_type_g => opt_so_output_type_g, + opt_sk_output_type_g => opt_sk_output_type_g + ) + port map ( + ck_i => ck_i, + ck_en_i => ck_en_i, + por_n_i => por_n_s, + reset_n_i => reset_n_i, + cko_i => cko_i, + pm_addr_o => pm_addr_s, + pm_data_i => pm_data_s, + dm_addr_o => dm_addr_s, + dm_we_o => dm_we_s, + dm_data_o => dm_data_from_core_s, + dm_data_i => dm_data_to_core_s, + io_l_i => io_l_i, + io_l_o => io_l_o, + io_l_en_o => io_l_en_o, + io_d_o => io_d_o, + io_d_en_o => io_d_en_o, + io_g_i => io_g_i, + io_g_o => io_g_o, + io_g_en_o => io_g_en_o, + io_in_i => gnd4_s, + si_i => si_i, + so_o => so_o, + so_en_o => so_en_o, + sk_o => sk_o, + sk_en_o => sk_en_o + ); + + + ----------------------------------------------------------------------------- + -- Program memory + ----------------------------------------------------------------------------- + pmem_b : t410_rom + port map ( + ck_i => ck_i, + addr_i => pm_addr_s(8 downto 0), + data_o => pm_data_s + ); + + + ----------------------------------------------------------------------------- + -- Data memory + ----------------------------------------------------------------------------- + dmem_b : generic_ram_ena + generic map ( + addr_width_g => 5, + data_width_g => 4 + ) + port map ( + clk_i => ck_i, + a_i => dm_addr_s(4 downto 0), + we_i => dm_we_s, + ena_i => ck_en_i, + d_i => dm_data_from_core_s, + d_o => dm_data_to_core_s + ); + + + ----------------------------------------------------------------------------- + -- Power-on reset circuit + ----------------------------------------------------------------------------- + por_b : t400_por + generic map ( + delay_g => 4, + cnt_width_g => 2 + ) + port map ( + clk_i => ck_i, + por_n_o => por_n_s + ); + +end struct; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t410_notri.vhd,v $ +-- Revision 1.3 2006/06/05 20:03:11 arniml +-- include generic_ram_ena +-- +-- Revision 1.2 2006/05/08 02:36:38 arniml +-- hand-down clock divider option +-- +-- Revision 1.1.1.1 2006/05/06 01:56:45 arniml +-- import from local CVS repository, LOC_CVS_0_1 +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/system/t410_rom-e.vhd b/rtl/t400/rtl/vhdl/system/t410_rom-e.vhd new file mode 100644 index 0000000..186d63f --- /dev/null +++ b/rtl/t400/rtl/vhdl/system/t410_rom-e.vhd @@ -0,0 +1,67 @@ +------------------------------------------------------------------------------- +-- +-- T410/411 ROM. +-- +-- $Id: t410_rom-e.vhd,v 1.1.1.1 2006/05/06 01:56:45 arniml Exp $ +-- +-- Copyright (c) 2006 Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t400/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity t410_rom is + + port ( + ck_i : in std_logic; + addr_i : in std_logic_vector(8 downto 0); + data_o : out std_logic_vector(7 downto 0) + ); + +end t410_rom; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t410_rom-e.vhd,v $ +-- Revision 1.1.1.1 2006/05/06 01:56:45 arniml +-- import from local CVS repository, LOC_CVS_0_1 +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/system/t410_rom-struct-a.vhd b/rtl/t400/rtl/vhdl/system/t410_rom-struct-a.vhd new file mode 100644 index 0000000..11127e8 --- /dev/null +++ b/rtl/t400/rtl/vhdl/system/t410_rom-struct-a.vhd @@ -0,0 +1,78 @@ +------------------------------------------------------------------------------- +-- +-- T410/411 ROM. +-- +-- $Id: t410_rom-struct-a.vhd,v 1.1.1.1 2006/06/10 17:50:15 arnim Exp $ +-- +-- Copyright (c) 2006 Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t400/ +-- +------------------------------------------------------------------------------- + +architecture struct of t410_rom is + + component rom_t41x + port( + Clk : in std_logic; + A : in std_logic_vector(8 downto 0); + D : out std_logic_vector(7 downto 0) + ); + end component; + +begin + + rom_b : rom_t41x + port map ( + Clk => ck_i, + A => addr_i, + D => data_o + ); + +end struct; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t410_rom-struct-a.vhd,v $ +-- Revision 1.1.1.1 2006/06/10 17:50:15 arnim +-- copied from opencores.org repository, pre-1.0 release on 10-Jun-2006 +-- +-- Revision 1.1 2006/06/05 22:44:29 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/system/t411-c.vhd b/rtl/t400/rtl/vhdl/system/t411-c.vhd new file mode 100644 index 0000000..79db93f --- /dev/null +++ b/rtl/t400/rtl/vhdl/system/t411-c.vhd @@ -0,0 +1,66 @@ +------------------------------------------------------------------------------- +-- +-- T411 system toplevel. +-- +-- $Id: t411-c.vhd,v 1.1.1.1 2006/05/06 01:56:45 arniml Exp $ +-- +-- Copyright (c) 2006 Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t400/ +-- +------------------------------------------------------------------------------- + +configuration t411_struct_c0 of t411 is + + for struct + + for t410_notri_b: t410_notri + use configuration work.t410_notri_struct_c0; + end for; + + end for; + +end t411_struct_c0; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t411-c.vhd,v $ +-- Revision 1.1.1.1 2006/05/06 01:56:45 arniml +-- import from local CVS repository, LOC_CVS_0_1 +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/system/t411.vhd b/rtl/t400/rtl/vhdl/system/t411.vhd new file mode 100644 index 0000000..b804d53 --- /dev/null +++ b/rtl/t400/rtl/vhdl/system/t411.vhd @@ -0,0 +1,196 @@ +------------------------------------------------------------------------------- +-- +-- T411 system toplevel. +-- +-- $Id: t411.vhd,v 1.1.1.1 2006/05/06 01:56:45 arniml Exp $ +-- +-- Copyright (c) 2006 Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t400/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.t400_opt_pack.all; + +entity t411 is + + generic ( + opt_ck_div_g : integer := t400_opt_ck_div_16_c; + opt_l_out_type_7_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_6_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_5_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_4_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_3_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_so_output_type_g : integer := t400_opt_out_type_std_c; + opt_sk_output_type_g : integer := t400_opt_out_type_std_c + ); + port ( + ck_i : in std_logic; + ck_en_i : in std_logic; + reset_n_i : in std_logic; + io_l_b : inout std_logic_vector(7 downto 0); + io_d_o : out std_logic_vector(1 downto 0); + io_g_b : inout std_logic_vector(2 downto 0); + si_i : in std_logic; + so_o : out std_logic; + sk_o : out std_logic + ); + +end t411; + + +use work.t400_system_comp_pack.t410_notri; + +architecture struct of t411 is + + signal io_l_from_t410_s, + io_l_en_s : std_logic_vector(7 downto 0); + signal io_d_from_t410_s, + io_d_en_s : std_logic_vector(3 downto 0); + signal io_g_to_t410_s, + io_g_from_t410_s, + io_g_en_s : std_logic_vector(3 downto 0); + + signal so_s, + so_en_s : std_logic; + signal sk_s, + sk_en_s : std_logic; + + signal gnd_s : std_logic; + +begin + + gnd_s <= '0'; + + ----------------------------------------------------------------------------- + -- T411 without tri-states + ----------------------------------------------------------------------------- + t410_notri_b : t410_notri + generic map ( + opt_ck_div_g => opt_ck_div_g, + opt_cko_g => t400_opt_cko_crystal_c, + opt_l_out_type_7_g => opt_l_out_type_7_g, + opt_l_out_type_6_g => opt_l_out_type_6_g, + opt_l_out_type_5_g => opt_l_out_type_5_g, + opt_l_out_type_4_g => opt_l_out_type_4_g, + opt_l_out_type_3_g => opt_l_out_type_3_g, + opt_l_out_type_2_g => opt_l_out_type_2_g, + opt_l_out_type_1_g => opt_l_out_type_1_g, + opt_l_out_type_0_g => opt_l_out_type_0_g, + opt_d_out_type_3_g => t400_opt_out_type_std_c, + opt_d_out_type_2_g => t400_opt_out_type_std_c, + opt_d_out_type_1_g => opt_d_out_type_1_g, + opt_d_out_type_0_g => opt_d_out_type_0_g, + opt_g_out_type_3_g => t400_opt_out_type_std_c, + opt_g_out_type_2_g => opt_g_out_type_2_g, + opt_g_out_type_1_g => opt_g_out_type_1_g, + opt_g_out_type_0_g => opt_g_out_type_0_g, + opt_so_output_type_g => opt_so_output_type_g, + opt_sk_output_type_g => opt_sk_output_type_g + ) + port map ( + ck_i => ck_i, + ck_en_i => ck_en_i, + reset_n_i => reset_n_i, + cko_i => gnd_s, + io_l_i => io_l_b, + io_l_o => io_l_from_t410_s, + io_l_en_o => io_l_en_s, + io_d_o => io_d_from_t410_s, + io_d_en_o => io_d_en_s, + io_g_i => io_g_to_t410_s, + io_g_o => io_g_from_t410_s, + io_g_en_o => io_g_en_s, + si_i => si_i, + so_o => so_s, + so_en_o => so_en_s, + sk_o => sk_s, + sk_en_o => sk_en_s + ); + + + ----------------------------------------------------------------------------- + -- Tri-states for output drivers + ----------------------------------------------------------------------------- + io_l_tri: for idx in 7 downto 0 generate + io_l_b(idx) <= io_l_from_t410_s(idx) + when io_l_en_s(idx) = '1' else + 'Z'; + end generate; + -- + io_d_tri: for idx in 1 downto 0 generate + io_d_o(idx) <= io_d_from_t410_s(idx) + when io_d_en_s(idx) = '1' else + 'Z'; + end generate; + -- + io_g_tri: for idx in 2 downto 0 generate + io_g_b(idx) <= io_g_from_t410_s(idx) + when io_g_en_s(idx) = '1' else + 'Z'; + end generate; + io_g_to_t410_s <= io_g_from_t410_s(3) & io_g_b; + -- + so_o <= so_s + when so_en_s = '1' else + 'Z'; + -- + sk_o <= sk_s + when sk_en_s = '1' else + 'Z'; + +end struct; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t411.vhd,v $ +-- Revision 1.1.1.1 2006/05/06 01:56:45 arniml +-- import from local CVS repository, LOC_CVS_0_1 +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/system/t420-c.vhd b/rtl/t400/rtl/vhdl/system/t420-c.vhd new file mode 100644 index 0000000..fc2bac1 --- /dev/null +++ b/rtl/t400/rtl/vhdl/system/t420-c.vhd @@ -0,0 +1,69 @@ +------------------------------------------------------------------------------- +-- +-- T420 system toplevel. +-- +-- $Id: t420-c.vhd,v 1.1.1.1 2006/06/10 17:50:15 arnim Exp $ +-- +-- Copyright (c) 2006 Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t400/ +-- +------------------------------------------------------------------------------- + +configuration t420_struct_c0 of t420 is + + for struct + + for t420_notri_b: t420_notri + use configuration work.t420_notri_struct_c0; + end for; + + end for; + +end t420_struct_c0; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t420-c.vhd,v $ +-- Revision 1.1.1.1 2006/06/10 17:50:15 arnim +-- copied from opencores.org repository, pre-1.0 release on 10-Jun-2006 +-- +-- Revision 1.1 2006/05/14 22:29:01 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/system/t420.vhd b/rtl/t400/rtl/vhdl/system/t420.vhd new file mode 100644 index 0000000..bff2281 --- /dev/null +++ b/rtl/t400/rtl/vhdl/system/t420.vhd @@ -0,0 +1,219 @@ +------------------------------------------------------------------------------- +-- +-- T420 system toplevel. +-- +-- $Id: t420.vhd,v 1.1.1.2 2006/06/12 18:12:58 arnim Exp $ +-- +-- Copyright (c) 2006 Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t400/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.t400_opt_pack.all; + +entity t420 is + + generic ( + opt_ck_div_g : integer := t400_opt_ck_div_8_c; + opt_cko_g : integer := t400_opt_cko_crystal_c; + opt_l_out_type_7_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_6_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_5_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_4_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_3_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_microbus_g : integer := t400_opt_no_microbus_c; + opt_d_out_type_3_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_3_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_so_output_type_g : integer := t400_opt_out_type_std_c; + opt_sk_output_type_g : integer := t400_opt_out_type_std_c + ); + port ( + ck_i : in std_logic; + ck_en_i : in std_logic; + reset_n_i : in std_logic; + cko_i : in std_logic; + io_l_b : inout std_logic_vector(7 downto 0); + io_d_o : out std_logic_vector(3 downto 0); + io_g_b : inout std_logic_vector(3 downto 0); + io_in_i : in std_logic_vector(3 downto 0); + si_i : in std_logic; + so_o : out std_logic; + sk_o : out std_logic + ); + +end t420; + + +use work.t400_system_comp_pack.t420_notri; + +architecture struct of t420 is + + signal io_l_from_t420_s, + io_l_en_s : std_logic_vector(7 downto 0); + signal io_d_from_t420_s, + io_d_en_s : std_logic_vector(3 downto 0); + signal io_g_from_t420_s, + io_g_en_s : std_logic_vector(3 downto 0); + + signal so_s, + so_en_s : std_logic; + signal sk_s, + sk_en_s : std_logic; + +begin + + ----------------------------------------------------------------------------- + -- T420 without tri-states + ----------------------------------------------------------------------------- + t420_notri_b : t420_notri + generic map ( + opt_type_g => t400_opt_type_420_c, + opt_ck_div_g => opt_ck_div_g, + opt_cko_g => opt_cko_g, + opt_l_out_type_7_g => opt_l_out_type_7_g, + opt_l_out_type_6_g => opt_l_out_type_6_g, + opt_l_out_type_5_g => opt_l_out_type_5_g, + opt_l_out_type_4_g => opt_l_out_type_4_g, + opt_l_out_type_3_g => opt_l_out_type_3_g, + opt_l_out_type_2_g => opt_l_out_type_2_g, + opt_l_out_type_1_g => opt_l_out_type_1_g, + opt_l_out_type_0_g => opt_l_out_type_0_g, + opt_microbus_g => opt_microbus_g, + opt_d_out_type_3_g => opt_d_out_type_3_g, + opt_d_out_type_2_g => opt_d_out_type_2_g, + opt_d_out_type_1_g => opt_d_out_type_1_g, + opt_d_out_type_0_g => opt_d_out_type_0_g, + opt_g_out_type_3_g => opt_g_out_type_3_g, + opt_g_out_type_2_g => opt_g_out_type_2_g, + opt_g_out_type_1_g => opt_g_out_type_1_g, + opt_g_out_type_0_g => opt_g_out_type_0_g, + opt_so_output_type_g => opt_so_output_type_g, + opt_sk_output_type_g => opt_sk_output_type_g + ) + port map ( + ck_i => ck_i, + ck_en_i => ck_en_i, + reset_n_i => reset_n_i, + cko_i => cko_i, + io_l_i => io_l_b, + io_l_o => io_l_from_t420_s, + io_l_en_o => io_l_en_s, + io_d_o => io_d_from_t420_s, + io_d_en_o => io_d_en_s, + io_g_i => io_g_b, + io_g_o => io_g_from_t420_s, + io_g_en_o => io_g_en_s, + io_in_i => io_in_i, + si_i => si_i, + so_o => so_s, + so_en_o => so_en_s, + sk_o => sk_s, + sk_en_o => sk_en_s + ); + + + ----------------------------------------------------------------------------- + -- Tri-states for output drivers + ----------------------------------------------------------------------------- + io_l_tri: for idx in 7 downto 0 generate + io_l_b(idx) <= io_l_from_t420_s(idx) + when io_l_en_s(idx) = '1' else + 'Z'; + end generate; + -- + io_d_tri: for idx in 3 downto 0 generate + io_d_o(idx) <= io_d_from_t420_s(idx) + when io_d_en_s(idx) = '1' else + 'Z'; + end generate; + -- + io_g_tri: for idx in 3 downto 0 generate + io_g_b(idx) <= io_g_from_t420_s(idx) + when io_g_en_s(idx) = '1' else + 'Z'; + end generate; + -- + so_o <= so_s + when so_en_s = '1' else + 'Z'; + -- + sk_o <= sk_s + when sk_en_s = '1' else + 'Z'; + +end struct; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t420.vhd,v $ +-- Revision 1.1.1.2 2006/06/12 18:12:58 arnim +-- copied from opencores.org repository, 1.0 release +-- +-- Revision 1.6 2006/06/11 13:49:18 arniml +-- * hand generic opt_type_g down to t420_notri +-- * full generic list +-- +-- Revision 1.5 2006/06/05 20:04:11 arniml +-- connect microbus generic +-- +-- Revision 1.4 2006/05/23 01:16:05 arniml +-- routi CKO to t400_core +-- +-- Revision 1.3 2006/05/20 02:49:04 arniml +-- select CK divide by 8 +-- +-- Revision 1.2 2006/05/17 00:38:31 arniml +-- connect missing input direction for IO G +-- +-- Revision 1.1 2006/05/14 22:29:01 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/system/t420_notri-c.vhd b/rtl/t400/rtl/vhdl/system/t420_notri-c.vhd new file mode 100644 index 0000000..2c108e1 --- /dev/null +++ b/rtl/t400/rtl/vhdl/system/t420_notri-c.vhd @@ -0,0 +1,51 @@ +------------------------------------------------------------------------------- +-- +-- T420/421 controller toplevel without tri-states. +-- +-- $Id: t420_notri-c.vhd,v 1.1.1.1 2006/06/10 17:50:15 arnim Exp $ +-- +-- Copyright (c) 2006, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +configuration t420_notri_struct_c0 of t420_notri is + + for struct + + for core_b: t400_core + use configuration work.t400_core_struct_c0; + end for; + + for pmem_b: t420_rom + use configuration work.t420_rom_struct_c0; + end for; + + for dmem_b: generic_ram_ena + use configuration work.generic_ram_ena_rtl_c0; + end for; + + for por_b: t400_por + use configuration work.t400_por_rtl_c0; + end for; + + end for; + +end t420_notri_struct_c0; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t420_notri-c.vhd,v $ +-- Revision 1.1.1.1 2006/06/10 17:50:15 arnim +-- copied from opencores.org repository, pre-1.0 release on 10-Jun-2006 +-- +-- Revision 1.2 2006/06/05 20:03:11 arniml +-- include generic_ram_ena +-- +-- Revision 1.1 2006/05/14 22:29:01 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/system/t420_notri.vhd b/rtl/t400/rtl/vhdl/system/t420_notri.vhd new file mode 100644 index 0000000..00324b3 --- /dev/null +++ b/rtl/t400/rtl/vhdl/system/t420_notri.vhd @@ -0,0 +1,245 @@ +------------------------------------------------------------------------------- +-- +-- T420/421 controller toplevel without tri-states. +-- +-- $Id: t420_notri.vhd,v 1.1.1.2 2006/06/12 18:12:58 arnim Exp $ +-- +-- Copyright (c) 2006 Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t400/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.t400_opt_pack.all; + +entity t420_notri is + + generic ( + opt_type_g : integer := t400_opt_type_420_c; + opt_ck_div_g : integer := t400_opt_ck_div_16_c; + opt_cko_g : integer := t400_opt_cko_crystal_c; + opt_l_out_type_7_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_6_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_5_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_4_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_3_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_microbus_g : integer := t400_opt_no_microbus_c; + opt_d_out_type_3_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_3_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_so_output_type_g : integer := t400_opt_out_type_std_c; + opt_sk_output_type_g : integer := t400_opt_out_type_std_c + ); + port ( + ck_i : in std_logic; + ck_en_i : in std_logic; + reset_n_i : in std_logic; + cko_i : in std_logic; + io_l_i : in std_logic_vector(7 downto 0); + io_l_o : out std_logic_vector(7 downto 0); + io_l_en_o : out std_logic_vector(7 downto 0); + io_d_o : out std_logic_vector(3 downto 0); + io_d_en_o : out std_logic_vector(3 downto 0); + io_g_i : in std_logic_vector(3 downto 0); + io_g_o : out std_logic_vector(3 downto 0); + io_g_en_o : out std_logic_vector(3 downto 0); + io_in_i : in std_logic_vector(3 downto 0); + si_i : in std_logic; + so_o : out std_logic; + so_en_o : out std_logic; + sk_o : out std_logic; + sk_en_o : out std_logic + ); + +end t420_notri; + + +use work.t400_core_comp_pack.t400_core; +use work.t400_tech_comp_pack.t400_por; +use work.t400_tech_comp_pack.generic_ram_ena; + +architecture struct of t420_notri is + + component t420_rom + port ( + ck_i : in std_logic; + addr_i : in std_logic_vector(9 downto 0); + data_o : out std_logic_vector(7 downto 0) + ); + end component; + + signal por_n_s : std_logic; + + signal pm_addr_s : std_logic_vector(9 downto 0); + signal pm_data_s : std_logic_vector(7 downto 0); + + signal dm_addr_s : std_logic_vector(5 downto 0); + signal dm_we_s : std_logic; + signal dm_data_to_core_s, + dm_data_from_core_s : std_logic_vector(3 downto 0); + +begin + + ----------------------------------------------------------------------------- + -- T400 core + ----------------------------------------------------------------------------- + core_b : t400_core + generic map ( + opt_type_g => opt_type_g, + opt_ck_div_g => opt_ck_div_g, + opt_cko_g => opt_cko_g, + opt_l_out_type_7_g => opt_l_out_type_7_g, + opt_l_out_type_6_g => opt_l_out_type_6_g, + opt_l_out_type_5_g => opt_l_out_type_5_g, + opt_l_out_type_4_g => opt_l_out_type_4_g, + opt_l_out_type_3_g => opt_l_out_type_3_g, + opt_l_out_type_2_g => opt_l_out_type_2_g, + opt_l_out_type_1_g => opt_l_out_type_1_g, + opt_l_out_type_0_g => opt_l_out_type_0_g, + opt_microbus_g => opt_microbus_g, + opt_d_out_type_3_g => opt_d_out_type_3_g, + opt_d_out_type_2_g => opt_d_out_type_2_g, + opt_d_out_type_1_g => opt_d_out_type_1_g, + opt_d_out_type_0_g => opt_d_out_type_0_g, + opt_g_out_type_3_g => opt_g_out_type_3_g, + opt_g_out_type_2_g => opt_g_out_type_2_g, + opt_g_out_type_1_g => opt_g_out_type_1_g, + opt_g_out_type_0_g => opt_g_out_type_0_g, + opt_so_output_type_g => opt_so_output_type_g, + opt_sk_output_type_g => opt_sk_output_type_g + ) + port map ( + ck_i => ck_i, + ck_en_i => ck_en_i, + por_n_i => por_n_s, + reset_n_i => reset_n_i, + cko_i => cko_i, + pm_addr_o => pm_addr_s, + pm_data_i => pm_data_s, + dm_addr_o => dm_addr_s, + dm_we_o => dm_we_s, + dm_data_o => dm_data_from_core_s, + dm_data_i => dm_data_to_core_s, + io_l_i => io_l_i, + io_l_o => io_l_o, + io_l_en_o => io_l_en_o, + io_d_o => io_d_o, + io_d_en_o => io_d_en_o, + io_g_i => io_g_i, + io_g_o => io_g_o, + io_g_en_o => io_g_en_o, + io_in_i => io_in_i, + si_i => si_i, + so_o => so_o, + so_en_o => so_en_o, + sk_o => sk_o, + sk_en_o => sk_en_o + ); + + + ----------------------------------------------------------------------------- + -- Program memory + ----------------------------------------------------------------------------- + pmem_b : t420_rom + port map ( + ck_i => ck_i, + addr_i => pm_addr_s, + data_o => pm_data_s + ); + + + ----------------------------------------------------------------------------- + -- Data memory + ----------------------------------------------------------------------------- + dmem_b : generic_ram_ena + generic map ( + addr_width_g => 6, + data_width_g => 4 + ) + port map ( + clk_i => ck_i, + a_i => dm_addr_s, + we_i => dm_we_s, + ena_i => ck_en_i, + d_i => dm_data_from_core_s, + d_o => dm_data_to_core_s + ); + + + ----------------------------------------------------------------------------- + -- Power-on reset circuit + ----------------------------------------------------------------------------- + por_b : t400_por + generic map ( + delay_g => 4, + cnt_width_g => 2 + ) + port map ( + clk_i => ck_i, + por_n_o => por_n_s + ); + +end struct; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t420_notri.vhd,v $ +-- Revision 1.1.1.2 2006/06/12 18:12:58 arnim +-- copied from opencores.org repository, 1.0 release +-- +-- Revision 1.3 2006/06/11 13:48:43 arniml +-- hand generic opt_type_g down to t400_core +-- +-- Revision 1.2 2006/06/05 20:03:52 arniml +-- connect microbus generic and include generic_ram_ena +-- +-- Revision 1.1 2006/05/14 22:29:01 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/system/t420_rom-e.vhd b/rtl/t400/rtl/vhdl/system/t420_rom-e.vhd new file mode 100644 index 0000000..10b3157 --- /dev/null +++ b/rtl/t400/rtl/vhdl/system/t420_rom-e.vhd @@ -0,0 +1,70 @@ +------------------------------------------------------------------------------- +-- +-- T420/421 ROM. +-- +-- $Id: t420_rom-e.vhd,v 1.1.1.1 2006/06/10 17:50:15 arnim Exp $ +-- +-- Copyright (c) 2006 Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t400/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity t420_rom is + + port ( + ck_i : in std_logic; + addr_i : in std_logic_vector(9 downto 0); + data_o : out std_logic_vector(7 downto 0) + ); + +end t420_rom; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t420_rom-e.vhd,v $ +-- Revision 1.1.1.1 2006/06/10 17:50:15 arnim +-- copied from opencores.org repository, pre-1.0 release on 10-Jun-2006 +-- +-- Revision 1.1 2006/05/14 22:29:01 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/system/t420_rom-struct-a.vhd b/rtl/t400/rtl/vhdl/system/t420_rom-struct-a.vhd new file mode 100644 index 0000000..104785b --- /dev/null +++ b/rtl/t400/rtl/vhdl/system/t420_rom-struct-a.vhd @@ -0,0 +1,78 @@ +------------------------------------------------------------------------------- +-- +-- T420/421 ROM. +-- +-- $Id: t420_rom-struct-a.vhd,v 1.1.1.1 2006/06/10 17:50:15 arnim Exp $ +-- +-- Copyright (c) 2006 Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t400/ +-- +------------------------------------------------------------------------------- + +architecture struct of t420_rom is + + component rom_t42x + port( + Clk : in std_logic; + A : in std_logic_vector(9 downto 0); + D : out std_logic_vector(7 downto 0) + ); + end component; + +begin + + rom_b : rom_t42x + port map ( + Clk => ck_i, + A => addr_i, + D => data_o + ); + +end struct; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t420_rom-struct-a.vhd,v $ +-- Revision 1.1.1.1 2006/06/10 17:50:15 arnim +-- copied from opencores.org repository, pre-1.0 release on 10-Jun-2006 +-- +-- Revision 1.1 2006/06/05 22:44:29 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/system/t421-c.vhd b/rtl/t400/rtl/vhdl/system/t421-c.vhd new file mode 100644 index 0000000..8601da9 --- /dev/null +++ b/rtl/t400/rtl/vhdl/system/t421-c.vhd @@ -0,0 +1,69 @@ +------------------------------------------------------------------------------- +-- +-- T421 system toplevel. +-- +-- $Id: t421-c.vhd,v 1.1.1.1 2006/06/12 18:12:58 arnim Exp $ +-- +-- Copyright (c) 2006 Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t400/ +-- +------------------------------------------------------------------------------- + +configuration t421_struct_c0 of t421 is + + for struct + + for t420_notri_b: t420_notri + use configuration work.t420_notri_struct_c0; + end for; + + end for; + +end t421_struct_c0; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t421-c.vhd,v $ +-- Revision 1.1.1.1 2006/06/12 18:12:58 arnim +-- copied from opencores.org repository, 1.0 release +-- +-- Revision 1.1 2006/06/11 13:47:24 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/system/t421.vhd b/rtl/t400/rtl/vhdl/system/t421.vhd new file mode 100644 index 0000000..f01db67 --- /dev/null +++ b/rtl/t400/rtl/vhdl/system/t421.vhd @@ -0,0 +1,205 @@ +------------------------------------------------------------------------------- +-- +-- T421 system toplevel. +-- +-- $Id: t421.vhd,v 1.1.1.1 2006/06/12 18:12:58 arnim Exp $ +-- +-- Copyright (c) 2006 Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t400/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.t400_opt_pack.all; + +entity t421 is + + generic ( + opt_ck_div_g : integer := t400_opt_ck_div_8_c; + opt_cko_g : integer := t400_opt_cko_crystal_c; + opt_l_out_type_7_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_6_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_5_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_4_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_3_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_3_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_3_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_so_output_type_g : integer := t400_opt_out_type_std_c; + opt_sk_output_type_g : integer := t400_opt_out_type_std_c + ); + port ( + ck_i : in std_logic; + ck_en_i : in std_logic; + reset_n_i : in std_logic; + cko_i : in std_logic; + io_l_b : inout std_logic_vector(7 downto 0); + io_d_o : out std_logic_vector(3 downto 0); + io_g_b : inout std_logic_vector(3 downto 0); + si_i : in std_logic; + so_o : out std_logic; + sk_o : out std_logic + ); + +end t421; + + +use work.t400_system_comp_pack.t420_notri; + +architecture struct of t421 is + + signal io_l_from_t420_s, + io_l_en_s : std_logic_vector(7 downto 0); + signal io_d_from_t420_s, + io_d_en_s : std_logic_vector(3 downto 0); + signal io_g_from_t420_s, + io_g_en_s : std_logic_vector(3 downto 0); + + signal so_s, + so_en_s : std_logic; + signal sk_s, + sk_en_s : std_logic; + + signal vdd4_s : std_logic_vector(3 downto 0); + +begin + + vdd4_s <= (others => '1'); + + ----------------------------------------------------------------------------- + -- T420 without tri-states in T421 configuration + ----------------------------------------------------------------------------- + t420_notri_b : t420_notri + generic map ( + opt_type_g => t400_opt_type_421_c, + opt_ck_div_g => opt_ck_div_g, + opt_cko_g => opt_cko_g, + opt_l_out_type_7_g => opt_l_out_type_7_g, + opt_l_out_type_6_g => opt_l_out_type_6_g, + opt_l_out_type_5_g => opt_l_out_type_5_g, + opt_l_out_type_4_g => opt_l_out_type_4_g, + opt_l_out_type_3_g => opt_l_out_type_3_g, + opt_l_out_type_2_g => opt_l_out_type_2_g, + opt_l_out_type_1_g => opt_l_out_type_1_g, + opt_l_out_type_0_g => opt_l_out_type_0_g, + opt_microbus_g => t400_opt_no_microbus_c, + opt_d_out_type_3_g => opt_d_out_type_3_g, + opt_d_out_type_2_g => opt_d_out_type_2_g, + opt_d_out_type_1_g => opt_d_out_type_1_g, + opt_d_out_type_0_g => opt_d_out_type_0_g, + opt_g_out_type_3_g => opt_g_out_type_3_g, + opt_g_out_type_2_g => opt_g_out_type_2_g, + opt_g_out_type_1_g => opt_g_out_type_1_g, + opt_g_out_type_0_g => opt_g_out_type_0_g, + opt_so_output_type_g => opt_so_output_type_g, + opt_sk_output_type_g => opt_sk_output_type_g + ) + port map ( + ck_i => ck_i, + ck_en_i => ck_en_i, + reset_n_i => reset_n_i, + cko_i => cko_i, + io_l_i => io_l_b, + io_l_o => io_l_from_t420_s, + io_l_en_o => io_l_en_s, + io_d_o => io_d_from_t420_s, + io_d_en_o => io_d_en_s, + io_g_i => io_g_b, + io_g_o => io_g_from_t420_s, + io_g_en_o => io_g_en_s, + io_in_i => vdd4_s, + si_i => si_i, + so_o => so_s, + so_en_o => so_en_s, + sk_o => sk_s, + sk_en_o => sk_en_s + ); + + + ----------------------------------------------------------------------------- + -- Tri-states for output drivers + ----------------------------------------------------------------------------- + io_l_tri: for idx in 7 downto 0 generate + io_l_b(idx) <= io_l_from_t420_s(idx) + when io_l_en_s(idx) = '1' else + 'Z'; + end generate; + -- + io_d_tri: for idx in 3 downto 0 generate + io_d_o(idx) <= io_d_from_t420_s(idx) + when io_d_en_s(idx) = '1' else + 'Z'; + end generate; + -- + io_g_tri: for idx in 3 downto 0 generate + io_g_b(idx) <= io_g_from_t420_s(idx) + when io_g_en_s(idx) = '1' else + 'Z'; + end generate; + -- + so_o <= so_s + when so_en_s = '1' else + 'Z'; + -- + sk_o <= sk_s + when sk_en_s = '1' else + 'Z'; + +end struct; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t421.vhd,v $ +-- Revision 1.1.1.1 2006/06/12 18:12:58 arnim +-- copied from opencores.org repository, 1.0 release +-- +-- Revision 1.1 2006/06/11 13:47:24 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/t400_alu-c.vhd b/rtl/t400/rtl/vhdl/t400_alu-c.vhd new file mode 100644 index 0000000..5265daa --- /dev/null +++ b/rtl/t400/rtl/vhdl/t400_alu-c.vhd @@ -0,0 +1,29 @@ +------------------------------------------------------------------------------- +-- +-- The Arithmetic Logic Unit (ALU). +-- It contains the accumulator and the C flag. +-- +-- $Id: t400_alu-c.vhd,v 1.1.1.1 2006/05/06 01:56:44 arniml Exp $ +-- +-- Copyright (c) 2006, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +configuration t400_alu_rtl_c0 of t400_alu is + + for rtl + end for; + +end t400_alu_rtl_c0; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t400_alu-c.vhd,v $ +-- Revision 1.1.1.1 2006/05/06 01:56:44 arniml +-- import from local CVS repository, LOC_CVS_0_1 +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/t400_alu.vhd b/rtl/t400/rtl/vhdl/t400_alu.vhd new file mode 100644 index 0000000..afb8628 --- /dev/null +++ b/rtl/t400/rtl/vhdl/t400_alu.vhd @@ -0,0 +1,266 @@ +------------------------------------------------------------------------------- +-- +-- The Arithmetic Logic Unit (ALU). +-- It contains the accumulator and the C flag. +-- +-- $Id: t400_alu.vhd,v 1.3 2006/05/22 00:01:56 arniml Exp $ +-- +-- Copyright (c) 2006 Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t400/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.t400_pack.all; +use work.t400_opt_pack.all; + +entity t400_alu is + + generic ( + opt_cko_g : integer := t400_opt_cko_crystal_c + ); + port ( + -- System Interface ------------------------------------------------------- + ck_i : in std_logic; + ck_en_i : in boolean; + por_i : in boolean; + res_i : in boolean; + cko_i : in std_logic; + -- Control Interface ------------------------------------------------------ + op_i : in alu_op_t; + -- Data Interface --------------------------------------------------------- + m_i : in dw_t; + dec_data_i : in dec_data_t; + q_low_i : in dw_t; + b_i : in b_t; + g_i : in dw_t; + in_i : in dw_t; + sio_i : in dw_t; + a_o : out dw_t; + carry_o : out std_logic; + c_o : out std_logic + ); + +end t400_alu; + + +library ieee; +use ieee.numeric_std.all; + +architecture rtl of t400_alu is + + subtype alu_dw_t is unsigned(dw_t'high+1 downto 0); + signal alu_result_s : alu_dw_t; + + signal a_q : dw_t; + signal c_q : std_logic; + +begin + + ----------------------------------------------------------------------------- + -- Process regs + -- + -- Purpose: + -- Implements the sequential registers of the ALU: + -- * A - accumulator + -- * C - carry flag + -- + regs: process (ck_i, por_i) + begin + if por_i then + a_q <= (others => '0'); + c_q <= '0'; + + elsif ck_i'event and ck_i = '1' then + if res_i then + -- synchronous reset upon external reset event + a_q <= (others => '0'); + c_q <= '0'; + + elsif ck_en_i then + -- update accumulator + case op_i is + when ALU_CLRA | + ALU_ADD | + ALU_ADD_10 | + ALU_ADD_C | + ALU_ADD_DEC | + ALU_COMP | + ALU_XOR => + a_q <= std_logic_vector(alu_result_s(dw_t'range)); + when ALU_LOAD_M => + a_q <= m_i; + when ALU_LOAD_Q => + a_q <= q_low_i; + when ALU_LOAD_G => + a_q <= g_i; + when ALU_LOAD_IN => + a_q <= in_i; + when ALU_LOAD_IL => + a_q(3) <= in_i(3); + if opt_cko_g = t400_opt_cko_gpi_c then + a_q(2) <= cko_i; + else + a_q(2) <= '1'; + end if; + a_q(1) <= '0'; + a_q(0) <= in_i(0); + when ALU_LOAD_BR => + a_q(3 downto 2) <= (others => '0'); + a_q(1 downto 0) <= b_i(br_range_t); + when ALU_LOAD_BD => + a_q <= b_i(bd_range_t); + when ALU_LOAD_SIO => + a_q <= sio_i; + when others => + null; + end case; + + -- update C flag upon the following instructions + case op_i is + -- carry result of addition ----------------------------------------- + when ALU_ADD_C => + c_q <= alu_result_s(alu_dw_t'high); + + -- reset C flag ----------------------------------------------------- + when ALU_RC => + c_q <= '0'; + + -- set C flag ------------------------------------------------------- + when ALU_SC => + c_q <= '1'; + + when others => + null; + end case; + end if; + end if; + end process regs; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process dp + -- + -- Purpose: + -- Implements the ALU's data path. + -- + dp: process (op_i, + a_q, + m_i, + dec_data_i, + c_q) + variable in1_v, + in2_v, + in3_v, + add_v, xor_v : alu_dw_t; + begin + -- prepare adder + in1_v := '0' & unsigned(a_q); + if op_i = ALU_ADD_10 then + in2_v := to_unsigned(10, alu_dw_t'length); + elsif op_i = ALU_ADD_DEC then + in2_v := '0' & unsigned(dec_data_i(dw_t'range)); + else + in2_v := '0' & unsigned(m_i); + end if; + if op_i = ALU_ADD_C then + in3_v := (others => '0'); + in3_v(0) := c_q; + else + in3_v := (others => '0'); + end if; + add_v := in1_v + in2_v + in3_v; + + -- prepare exclusive or + xor_v := in1_v xor in2_v; + + case op_i is + -- ALU operation: Clear accumulator ------------------------------------- + when ALU_CLRA => + alu_result_s <= (others => '0'); + + -- ALU operation: Add to accumulator ------------------------------------ + when ALU_ADD | + ALU_ADD_10 | + ALU_ADD_C | + ALU_ADD_DEC => + alu_result_s <= add_v; + + -- ALU operation: Complement accumulator -------------------------------- + when ALU_COMP => + alu_result_s <= '0' & not unsigned(a_q); + + -- ALU operation: XOR to accumulator ------------------------------------ + when ALU_XOR => + alu_result_s <= xor_v; + + when others => + alu_result_s <= (others => '-'); + end case; + end process dp; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Output mapping + ----------------------------------------------------------------------------- + a_o <= a_q; + carry_o <= alu_result_s(alu_dw_t'high); + c_o <= c_q; + +end rtl; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t400_alu.vhd,v $ +-- Revision 1.3 2006/05/22 00:01:56 arniml +-- simplify ININ/INIL instruction support +-- +-- Revision 1.2 2006/05/21 21:47:40 arniml +-- route cko to ALU for INIL instruction +-- +-- Revision 1.1.1.1 2006/05/06 01:56:44 arniml +-- import from local CVS repository, LOC_CVS_0_1 +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/t400_clkgen-c.vhd b/rtl/t400/rtl/vhdl/t400_clkgen-c.vhd new file mode 100644 index 0000000..19a47a9 --- /dev/null +++ b/rtl/t400/rtl/vhdl/t400_clkgen-c.vhd @@ -0,0 +1,29 @@ +------------------------------------------------------------------------------- +-- +-- The clock generation unit. +-- PHI1 clock and input/output clock enables are generated here. +-- +-- $Id: t400_clkgen-c.vhd,v 1.1.1.1 2006/05/06 01:56:44 arniml Exp $ +-- +-- Copyright (c) 2006, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +configuration t400_clkgen_rtl_c0 of t400_clkgen is + + for rtl + end for; + +end t400_clkgen_rtl_c0; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t400_clkgen-c.vhd,v $ +-- Revision 1.1.1.1 2006/05/06 01:56:44 arniml +-- import from local CVS repository, LOC_CVS_0_1 +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/t400_clkgen.vhd b/rtl/t400/rtl/vhdl/t400_clkgen.vhd new file mode 100644 index 0000000..0543460 --- /dev/null +++ b/rtl/t400/rtl/vhdl/t400_clkgen.vhd @@ -0,0 +1,152 @@ +------------------------------------------------------------------------------- +-- +-- The clock generation unit. +-- PHI1 clock and input/output clock enables are generated here. +-- +-- $Id: t400_clkgen.vhd,v 1.1.1.1 2006/05/06 01:56:44 arniml Exp $ +-- +-- Copyright (c) 2006 Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t400/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.t400_opt_pack.all; + +entity t400_clkgen is + + generic ( + opt_ck_div_g : integer := t400_opt_ck_div_16_c + ); + port ( + -- System Interface ------------------------------------------------------- + ck_i : in std_logic; + ck_en_i : in boolean; + por_i : in boolean; + -- Clock Interface -------------------------------------------------------- + phi1_o : out std_logic; + out_en_o : out boolean; + in_en_o : out boolean; + icyc_en_o : out boolean + ); + +end t400_clkgen; + + +library ieee; +use ieee.numeric_std.all; + +architecture rtl of t400_clkgen is + + subtype ck_div_t is unsigned(5 downto 0); + type ck_div_a_t is array(natural range t400_opt_ck_div_32_c + downto t400_opt_ck_div_4_c) of + ck_div_t; + -- reload values for the CK dividing counter + constant ck_div_a_c : ck_div_a_t := ( + t400_opt_ck_div_32_c => to_unsigned(31, ck_div_t'length), + t400_opt_ck_div_16_c => to_unsigned(15, ck_div_t'length), + t400_opt_ck_div_8_c => to_unsigned( 7, ck_div_t'length), + t400_opt_ck_div_4_c => to_unsigned( 3, ck_div_t'length)); + + signal ck_div_cnt_q : ck_div_t; + signal ck_div_zero_s, + ck_div_half_s : boolean; + signal phi1_q : std_logic; + +begin + + ----------------------------------------------------------------------------- + -- Process ck_div + -- + -- Purpose: + -- Divide the incoming clock on ck_i and generate the derived clock + -- enable for the core. + -- + ck_div: process (ck_i, por_i) + begin + if por_i then + ck_div_cnt_q <= ck_div_a_c(opt_ck_div_g); + phi1_q <= '0'; + + elsif ck_i'event and ck_i = '1' then + if ck_en_i then + if ck_div_zero_s then + ck_div_cnt_q <= ck_div_a_c(opt_ck_div_g); + phi1_q <= '0'; + else + ck_div_cnt_q <= ck_div_cnt_q - 1; + + if ck_div_half_s then + phi1_q <= '1'; + end if; + end if; + end if; + end if; + + end process ck_div; + -- + ck_div_zero_s <= ck_div_cnt_q = 0; + ck_div_half_s <= ck_div_cnt_q = SHIFT_RIGHT(ck_div_a_c(opt_ck_div_g), 1) + 1; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Output mapping + ----------------------------------------------------------------------------- + phi1_o <= phi1_q; + -- Instruction cycle enable + icyc_en_o <= ck_en_i and ck_div_zero_s; + -- Output update enable + out_en_o <= ck_en_i and ck_div_zero_s; + -- Input sample enable + in_en_o <= ck_en_i and ck_div_half_s; + +end rtl; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t400_clkgen.vhd,v $ +-- Revision 1.1.1.1 2006/05/06 01:56:44 arniml +-- import from local CVS repository, LOC_CVS_0_1 +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/t400_comp_pack-p.vhd b/rtl/t400/rtl/vhdl/t400_comp_pack-p.vhd new file mode 100644 index 0000000..e29e569 --- /dev/null +++ b/rtl/t400/rtl/vhdl/t400_comp_pack-p.vhd @@ -0,0 +1,390 @@ +------------------------------------------------------------------------------- +-- +-- $Id: t400_comp_pack-p.vhd,v 1.7 2006/06/05 20:31:56 arniml Exp $ +-- +-- Copyright (c) 2006, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.t400_opt_pack.all; +use work.t400_pack.all; + +package t400_comp_pack is + + component t400_clkgen + generic ( + opt_ck_div_g : integer := t400_opt_ck_div_16_c + ); + port ( + -- System Interface ----------------------------------------------------- + ck_i : in std_logic; + ck_en_i : in boolean; + por_i : in boolean; + -- Clock Interface ------------------------------------------------------ + phi1_o : out std_logic; + out_en_o : out boolean; + in_en_o : out boolean; + icyc_en_o : out boolean + ); + end component; + + component t400_reset + port ( + -- System Interface ----------------------------------------------------- + ck_i : in std_logic; + icyc_en_i : in boolean; + -- Reset Interface ------------------------------------------------------ + por_i : in boolean; + reset_n_i : in std_logic; + res_o : out boolean + ); + end component; + + component t400_stack + generic ( + opt_type_g : integer := t400_opt_type_420_c + ); + port ( + -- System Interface ----------------------------------------------------- + ck_i : in std_logic; + ck_en_i : in boolean; + por_i : in boolean; + -- Stack Control Interface ---------------------------------------------- + op_i : in stack_op_t; + -- Program Counter Interface -------------------------------------------- + pc_i : in pc_t; + pc_o : out pc_t + ); + end component; + + component t400_pmem_ctrl + generic ( + opt_type_g : integer := t400_opt_type_420_c + ); + port ( + -- System Interface ----------------------------------------------------- + ck_i : in std_logic; + ck_en_i : in boolean; + por_i : in boolean; + res_i : in boolean; + a_i : in dw_t; + m_i : in dw_t; + -- Control Interface ---------------------------------------------------- + op_i : in pc_op_t; + dec_data_i : in dec_data_t; + -- Stack Interface ------------------------------------------------------ + pc_o : out pc_t; + pc_i : in pc_t; + -- Program Memory Interface --------------------------------------------- + pm_addr_o : out pc_t + ); + end component; + + component t400_alu + generic ( + opt_cko_g : integer := t400_opt_cko_crystal_c + ); + port ( + -- System Interface ----------------------------------------------------- + ck_i : in std_logic; + ck_en_i : in boolean; + por_i : in boolean; + res_i : in boolean; + cko_i : in std_logic; + -- Control Interface ---------------------------------------------------- + op_i : in alu_op_t; + -- Data Interface ------------------------------------------------------- + m_i : in dw_t; + dec_data_i : in dec_data_t; + q_low_i : in dw_t; + b_i : in b_t; + g_i : in dw_t; + in_i : in dw_t; + sio_i : in dw_t; + a_o : out dw_t; + carry_o : out std_logic; + c_o : out std_logic + ); + end component; + + component t400_dmem_ctrl + generic ( + opt_type_g : integer := t400_opt_type_420_c + ); + port ( + -- System Interface ----------------------------------------------------- + ck_i : in std_logic; + ck_en_i : in boolean; + por_i : in boolean; + res_i : in boolean; + -- Control Interface ---------------------------------------------------- + dmem_op_i : in dmem_op_t; + b_op_i : in b_op_t; + dec_data_i : in dec_data_t; + a_i : in dw_t; + q_high_i : in dw_t; + b_o : out b_t; + -- Data Memory Interface ------------------------------------------------ + dm_addr_o : out dm_addr_t; + dm_data_i : in dw_t; + dm_data_o : out dw_t; + dm_we_o : out std_logic + ); + end component; + + component t400_opc_table + generic ( + opt_type_g : integer := t400_opt_type_420_c + ); + port ( + opcode_i : in byte_t; + mnemonic_o : out mnemonic_t; + multi_byte_o : out boolean + ); + end component; + + component t400_decoder + generic ( + opt_type_g : integer := t400_opt_type_420_c + ); + port ( + -- System Interface ----------------------------------------------------- + ck_i : in std_logic; + ck_en_i : in boolean; + por_i : in boolean; + res_i : in boolean; + out_en_i : in boolean; + in_en_i : in boolean; + icyc_en_i : in boolean; + -- Module Control Interface --------------------------------------------- + pc_op_o : out pc_op_t; + stack_op_o : out stack_op_t; + dmem_op_o : out dmem_op_t; + b_op_o : out b_op_t; + skip_op_o : out skip_op_t; + alu_op_o : out alu_op_t; + io_l_op_o : out io_l_op_t; + io_d_op_o : out io_d_op_t; + io_g_op_o : out io_g_op_t; + io_in_op_o : out io_in_op_t; + sio_op_o : out sio_op_t; + dec_data_o : out dec_data_t; + en_o : out dw_t; + -- Skip Interface ------------------------------------------------------- + skip_i : in boolean; + skip_lbi_i : in boolean; + is_lbi_o : out boolean; + int_i : in boolean; + -- Program Memory Interface --------------------------------------------- + pm_addr_i : in pc_t; + pm_data_i : in byte_t + ); + end component; + + component t400_skip + generic ( + opt_type_g : integer := t400_opt_type_420_c + ); + port ( + -- System Interface ----------------------------------------------------- + ck_i : in std_logic; + ck_en_i : in boolean; + por_i : in boolean; + res_i : in boolean; + -- Control Interface ---------------------------------------------------- + op_i : in skip_op_t; + dec_data_i : in dec_data_t; + carry_i : in std_logic; + c_i : in std_logic; + bd_i : in dw_t; + is_lbi_i : in boolean; + skip_o : out boolean; + skip_lbi_o : out boolean; + -- Data Interface ------------------------------------------------------- + a_i : in dw_t; + m_i : in dw_t; + g_i : in dw_t; + tim_c_i : in boolean + ); + end component; + + component t400_io_l + generic ( + opt_out_type_7_g : integer := t400_opt_out_type_std_c; + opt_out_type_6_g : integer := t400_opt_out_type_std_c; + opt_out_type_5_g : integer := t400_opt_out_type_std_c; + opt_out_type_4_g : integer := t400_opt_out_type_std_c; + opt_out_type_3_g : integer := t400_opt_out_type_std_c; + opt_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_microbus_g : integer := t400_opt_no_microbus_c + ); + port ( + -- System Interface ----------------------------------------------------- + ck_i : in std_logic; + ck_en_i : in boolean; + por_i : in boolean; + in_en_i : in boolean; + -- Control Interface ---------------------------------------------------- + op_i : in io_l_op_t; + en2_i : in std_logic; + m_i : in dw_t; + a_i : in dw_t; + pm_data_i : in byte_t; + q_o : out byte_t; + -- Microbus Interface --------------------------------------------------- + cs_n_i : in std_logic; + rd_n_i : in std_logic; + wr_n_i : in std_logic; + -- Port L Interface ----------------------------------------------------- + io_l_i : in byte_t; + io_l_o : out byte_t; + io_l_en_o : out byte_t + ); + end component; + + component t400_io_d + generic ( + opt_out_type_3_g : integer := t400_opt_out_type_std_c; + opt_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_out_type_0_g : integer := t400_opt_out_type_std_c + ); + port ( + -- System Interface ----------------------------------------------------- + ck_i : in std_logic; + ck_en_i : in boolean; + por_i : in boolean; + res_i : in boolean; + -- Control Interface ---------------------------------------------------- + op_i : in io_d_op_t; + bd_i : in bd_t; + -- Port D Interface ----------------------------------------------------- + io_d_o : out dw_t; + io_d_en_o : out dw_t + ); + end component; + + component t400_io_g + generic ( + opt_out_type_3_g : integer := t400_opt_out_type_std_c; + opt_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_microbus_g : integer := t400_opt_no_microbus_c + ); + port ( + -- System Interface ----------------------------------------------------- + ck_i : in std_logic; + ck_en_i : in boolean; + por_i : in boolean; + res_i : in boolean; + cs_n_i : in std_logic; + wr_n_i : in std_logic; + -- Control Interface ---------------------------------------------------- + op_i : in io_g_op_t; + m_i : in dw_t; + dec_data_i : in dec_data_t; + -- Port G Interface ----------------------------------------------------- + io_g_o : out dw_t; + io_g_en_o : out dw_t + ); + end component; + + component t400_io_in + port ( + -- System Interface ----------------------------------------------------- + ck_i : in std_logic; + ck_en_i : in boolean; + por_i : in boolean; + icyc_en_i : in boolean; + in_en_i : in boolean; + -- Control Interface ---------------------------------------------------- + op_i : in io_in_op_t; + en1_i : in std_logic; + -- Port Interface ------------------------------------------------------- + io_in_i : in dw_t; + in_o : out dw_t; + int_o : out boolean + ); + end component; + + component t400_sio + generic ( + opt_so_output_type_g : integer := t400_opt_out_type_std_c; + opt_sk_output_type_g : integer := t400_opt_out_type_std_c + ); + port ( + -- System Interface ----------------------------------------------------- + ck_i : in std_logic; + ck_en_i : in boolean; + por_i : in boolean; + res_i : in boolean; + phi1_i : in std_logic; + out_en_i : in boolean; + in_en_i : in boolean; + -- Control Interface ---------------------------------------------------- + op_i : in sio_op_t; + en0_i : in std_logic; + en3_i : in std_logic; + -- SIO Interface -------------------------------------------------------- + a_i : in dw_t; + c_i : in std_logic; + sio_o : out dw_t; + -- Pad Interface -------------------------------------------------------- + si_i : in std_logic; + so_o : out std_logic; + so_en_o : out std_logic; + sk_o : out std_logic; + sk_en_o : out std_logic + ); + end component; + + component t400_timer + port ( + -- System Interface ----------------------------------------------------- + ck_i : in std_logic; + ck_en_i : in boolean; + por_i : in boolean; + icyc_en_i : in boolean; + -- Skip Interface ------------------------------------------------------- + op_i : in skip_op_t; + c_o : out boolean + ); + end component; + +end t400_comp_pack; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t400_comp_pack-p.vhd,v $ +-- Revision 1.7 2006/06/05 20:31:56 arniml +-- microbus support for IO G added +-- +-- Revision 1.6 2006/06/05 14:20:34 arniml +-- interface comments added +-- +-- Revision 1.5 2006/05/27 19:11:33 arniml +-- updates for interrupt support +-- +-- Revision 1.4 2006/05/22 00:03:08 arniml +-- io_in added +-- +-- Revision 1.3 2006/05/21 21:47:40 arniml +-- route cko to ALU for INIL instruction +-- +-- Revision 1.2 2006/05/20 02:48:17 arniml +-- timer module included +-- +-- Revision 1.1.1.1 2006/05/06 01:56:44 arniml +-- import from local CVS repository, LOC_CVS_0_1 +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/t400_core-c.vhd b/rtl/t400/rtl/vhdl/t400_core-c.vhd new file mode 100644 index 0000000..5fdb271 --- /dev/null +++ b/rtl/t400/rtl/vhdl/t400_core-c.vhd @@ -0,0 +1,95 @@ +------------------------------------------------------------------------------- +-- +-- T400 Microcontroller Core +-- +-- $Id: t400_core-c.vhd,v 1.3 2006/05/22 00:03:29 arniml Exp $ +-- +-- Copyright (c) 2006, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +configuration t400_core_struct_c0 of t400_core is + + for struct + + for clkgen_b: t400_clkgen + use configuration work.t400_clkgen_rtl_c0; + end for; + + for reset_b: t400_reset + use configuration work.t400_reset_rtl_c0; + end for; + + for pmem_ctrl_b: t400_pmem_ctrl + use configuration work.t400_pmem_ctrl_rtl_c0; + end for; + + for dmem_ctrl_b: t400_dmem_ctrl + use configuration work.t400_dmem_ctrl_rtl_c0; + end for; + + for decoder_b: t400_decoder + use configuration work.t400_decoder_rtl_c0; + end for; + + for skip_b: t400_skip + use configuration work.t400_skip_rtl_c0; + end for; + + for alu_b: t400_alu + use configuration work.t400_alu_rtl_c0; + end for; + + for stack_b: t400_stack + use configuration work.t400_stack_rtl_c0; + end for; + + for io_l_b: t400_io_l + use configuration work.t400_io_l_rtl_c0; + end for; + + for io_d_b: t400_io_d + use configuration work.t400_io_d_rtl_c0; + end for; + + for io_g_b: t400_io_g + use configuration work.t400_io_g_rtl_c0; + end for; + + for use_in + for io_in_b: t400_io_in + use configuration work.t400_io_in_rtl_c0; + end for; + end for; + + for sio_b: t400_sio + use configuration work.t400_sio_rtl_c0; + end for; + + for use_tim + for timer_b: t400_timer + use configuration work.t400_timer_rtl_c0; + end for; + end for; + + end for; + +end t400_core_struct_c0; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t400_core-c.vhd,v $ +-- Revision 1.3 2006/05/22 00:03:29 arniml +-- io_in added +-- +-- Revision 1.2 2006/05/20 02:48:17 arniml +-- timer module included +-- +-- Revision 1.1.1.1 2006/05/06 01:56:44 arniml +-- import from local CVS repository, LOC_CVS_0_1 +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/t400_core.vhd b/rtl/t400/rtl/vhdl/t400_core.vhd new file mode 100644 index 0000000..f56ebf3 --- /dev/null +++ b/rtl/t400/rtl/vhdl/t400_core.vhd @@ -0,0 +1,570 @@ +------------------------------------------------------------------------------- +-- +-- T400 Microcontroller Core +-- +-- $Id: t400_core.vhd,v 1.10 2006/06/11 13:34:39 arniml Exp $ +-- +-- Copyright (c) 2006 Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t400/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.t400_opt_pack.all; + +entity t400_core is + + generic ( + opt_type_g : integer := t400_opt_type_420_c; + opt_ck_div_g : integer := t400_opt_ck_div_16_c; + opt_cko_g : integer := t400_opt_cko_crystal_c; + opt_l_out_type_7_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_6_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_5_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_4_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_3_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_microbus_g : integer := t400_opt_no_microbus_c; + opt_d_out_type_3_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_3_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_so_output_type_g : integer := t400_opt_out_type_std_c; + opt_sk_output_type_g : integer := t400_opt_out_type_std_c + ); + port ( + ck_i : in std_logic; + ck_en_i : in std_logic; + por_n_i : in std_logic; + reset_n_i : in std_logic; + cko_i : in std_logic; + pm_addr_o : out std_logic_vector(9 downto 0); + pm_data_i : in std_logic_vector(7 downto 0); + dm_addr_o : out std_logic_vector(5 downto 0); + dm_we_o : out std_logic; + dm_data_o : out std_logic_vector(3 downto 0); + dm_data_i : in std_logic_vector(3 downto 0); + io_l_i : in std_logic_vector(7 downto 0); + io_l_o : out std_logic_vector(7 downto 0); + io_l_en_o : out std_logic_vector(7 downto 0); + io_d_o : out std_logic_vector(3 downto 0); + io_d_en_o : out std_logic_vector(3 downto 0); + io_g_i : in std_logic_vector(3 downto 0); + io_g_o : out std_logic_vector(3 downto 0); + io_g_en_o : out std_logic_vector(3 downto 0); + io_in_i : in std_logic_vector(3 downto 0); + si_i : in std_logic; + so_o : out std_logic; + so_en_o : out std_logic; + sk_o : out std_logic; + sk_en_o : out std_logic + ); + +end t400_core; + + +use work.t400_pack.all; +use work.t400_comp_pack.all; + +architecture struct of t400_core is + + signal ck_en_s : boolean; + signal por_s : boolean; + signal res_s : boolean; + + signal phi1_s : std_logic; + signal out_en_s : boolean; + signal in_en_s : boolean; + signal icyc_en_s : boolean; + + signal pm_addr_s : pc_t; + + signal a_s : dw_t; + signal dec_data_s : dec_data_t; + + signal pc_to_stack_s, + pc_from_stack_s : pc_t; + + signal q_s : byte_t; + signal b_s : b_t; + + signal c_s, + carry_s : std_logic; + + signal sio_s : dw_t; + + signal pc_op_s : pc_op_t; + signal stack_op_s : stack_op_t; + signal dmem_op_s : dmem_op_t; + signal b_op_s : b_op_t; + signal skip_op_s : skip_op_t; + signal alu_op_s : alu_op_t; + signal io_l_op_s : io_l_op_t; + signal io_d_op_s : io_d_op_t; + signal io_g_op_s : io_g_op_t; + signal io_in_op_s : io_in_op_t; + signal sio_op_s : sio_op_t; + signal is_lbi_s : boolean; + signal en_s : dw_t; + + signal skip_s, + skip_lbi_s : boolean; + signal tim_c_s : boolean; + + signal in_s : dw_t; + signal int_s : boolean; + + signal io_g_s : std_logic_vector(io_g_i'range); + + signal cs_n_s, + rd_n_s, + wr_n_s : std_logic; + + signal vdd_s : std_logic; + signal gnd4_s : dw_t; + +begin + + -- dummies + vdd_s <= '1'; + gnd4_s <= (others => '0'); + + ck_en_s <= ck_en_i = '1'; + por_s <= por_n_i = '0'; + + io_g_s <= to_X01(io_g_i); + + ----------------------------------------------------------------------------- + -- Clock generator + ----------------------------------------------------------------------------- + clkgen_b : t400_clkgen + generic map ( + opt_ck_div_g => opt_ck_div_g + ) + port map ( + ck_i => ck_i, + ck_en_i => ck_en_s, + por_i => por_s, + phi1_o => phi1_s, + out_en_o => out_en_s, + in_en_o => in_en_s, + icyc_en_o => icyc_en_s + ); + + + ----------------------------------------------------------------------------- + -- Reset module + ----------------------------------------------------------------------------- + reset_b : t400_reset + port map ( + ck_i => ck_i, + icyc_en_i => icyc_en_s, + por_i => por_s, + reset_n_i => reset_n_i, + res_o => res_s + ); + + + ----------------------------------------------------------------------------- + -- Program memory controller + ----------------------------------------------------------------------------- + pmem_ctrl_b : t400_pmem_ctrl + generic map ( + opt_type_g => opt_type_g + ) + port map ( + ck_i => ck_i, + ck_en_i => ck_en_s, + por_i => por_s, + res_i => res_s, + a_i => a_s, + m_i => dm_data_i, + op_i => pc_op_s, + dec_data_i => dec_data_s, + pc_o => pc_to_stack_s, + pc_i => pc_from_stack_s, + pm_addr_o => pm_addr_s + ); + -- + pm_addr_o <= std_logic_vector(pm_addr_s); + + + ----------------------------------------------------------------------------- + -- Data memory controller + ----------------------------------------------------------------------------- + dmem_ctrl_b : t400_dmem_ctrl + generic map ( + opt_type_g => opt_type_g + ) + port map ( + ck_i => ck_i, + ck_en_i => ck_en_s, + por_i => por_s, + res_i => res_s, + dmem_op_i => dmem_op_s, + b_op_i => b_op_s, + dec_data_i => dec_data_s, + a_i => a_s, + q_high_i => q_s(7 downto 4), + b_o => b_s, + dm_addr_o => dm_addr_o, + dm_data_i => dm_data_i, + dm_data_o => dm_data_o, + dm_we_o => dm_we_o + ); + + + ----------------------------------------------------------------------------- + -- Decoder + ----------------------------------------------------------------------------- + decoder_b : t400_decoder + generic map ( + opt_type_g => opt_type_g + ) + port map ( + ck_i => ck_i, + ck_en_i => ck_en_s, + por_i => por_s, + res_i => res_s, + out_en_i => out_en_s, + in_en_i => in_en_s, + icyc_en_i => icyc_en_s, + pc_op_o => pc_op_s, + stack_op_o => stack_op_s, + dmem_op_o => dmem_op_s, + b_op_o => b_op_s, + skip_op_o => skip_op_s, + alu_op_o => alu_op_s, + io_l_op_o => io_l_op_s, + io_d_op_o => io_d_op_s, + io_g_op_o => io_g_op_s, + io_in_op_o => io_in_op_s, + sio_op_o => sio_op_s, + dec_data_o => dec_data_s, + en_o => en_s, + skip_i => skip_s, + skip_lbi_i => skip_lbi_s, + is_lbi_o => is_lbi_s, + int_i => int_s, + pm_addr_i => pm_addr_s, + pm_data_i => pm_data_i + ); + + + ----------------------------------------------------------------------------- + -- Skip logic + ----------------------------------------------------------------------------- + skip_b : t400_skip + generic map ( + opt_type_g => opt_type_g + ) + port map ( + ck_i => ck_i, + ck_en_i => ck_en_s, + por_i => por_s, + res_i => res_s, + op_i => skip_op_s, + dec_data_i => dec_data_s, + carry_i => carry_s, + c_i => c_s, + bd_i => b_s(bd_range_t), + is_lbi_i => is_lbi_s, + skip_o => skip_s, + skip_lbi_o => skip_lbi_s, + a_i => a_s, + m_i => dm_data_i, + g_i => io_g_s, + tim_c_i => tim_c_s + ); + + + ----------------------------------------------------------------------------- + -- ALU + ----------------------------------------------------------------------------- + alu_b : t400_alu + generic map ( + opt_cko_g => opt_cko_g + ) + port map ( + ck_i => ck_i, + ck_en_i => ck_en_s, + por_i => por_s, + res_i => res_s, + cko_i => cko_i, + op_i => alu_op_s, + m_i => dm_data_i, + dec_data_i => dec_data_s, + q_low_i => q_s(3 downto 0), + b_i => b_s, + g_i => io_g_s, + in_i => in_s, + sio_i => sio_s, + a_o => a_s, + carry_o => carry_s, + c_o => c_s + ); + + + ----------------------------------------------------------------------------- + -- Stack module + ----------------------------------------------------------------------------- + stack_b : t400_stack + generic map ( + opt_type_g => opt_type_g + ) + port map ( + ck_i => ck_i, + ck_en_i => ck_en_s, + por_i => por_s, + op_i => stack_op_s, + pc_i => pc_to_stack_s, + pc_o => pc_from_stack_s + ); + + + ----------------------------------------------------------------------------- + -- IO L module + ----------------------------------------------------------------------------- + cs_n_s <= io_in_i(2); + rd_n_s <= io_in_i(1); + wr_n_s <= io_in_i(3); + -- + io_l_b : t400_io_l + generic map ( + opt_out_type_7_g => opt_l_out_type_7_g, + opt_out_type_6_g => opt_l_out_type_6_g, + opt_out_type_5_g => opt_l_out_type_5_g, + opt_out_type_4_g => opt_l_out_type_4_g, + opt_out_type_3_g => opt_l_out_type_3_g, + opt_out_type_2_g => opt_l_out_type_2_g, + opt_out_type_1_g => opt_l_out_type_1_g, + opt_out_type_0_g => opt_l_out_type_0_g, + opt_microbus_g => opt_microbus_g + ) + port map ( + ck_i => ck_i, + ck_en_i => ck_en_s, + por_i => por_s, + in_en_i => in_en_s, + op_i => io_l_op_s, + en2_i => en_s(2), + m_i => dm_data_i, + a_i => a_s, + pm_data_i => pm_data_i, + q_o => q_s, + cs_n_i => cs_n_s, + rd_n_i => rd_n_s, + wr_n_i => wr_n_s, + io_l_i => io_l_i, + io_l_o => io_l_o, + io_l_en_o => io_l_en_o + ); + + + ----------------------------------------------------------------------------- + -- IO D module + ----------------------------------------------------------------------------- + io_d_b : t400_io_d + generic map ( + opt_out_type_3_g => opt_d_out_type_3_g, + opt_out_type_2_g => opt_d_out_type_2_g, + opt_out_type_1_g => opt_d_out_type_1_g, + opt_out_type_0_g => opt_d_out_type_0_g + ) + port map ( + ck_i => ck_i, + ck_en_i => ck_en_s, + por_i => por_s, + res_i => res_s, + op_i => io_d_op_s, + bd_i => b_s(bd_range_t), + io_d_o => io_d_o, + io_d_en_o => io_d_en_o + ); + + + ----------------------------------------------------------------------------- + -- IO G module + ----------------------------------------------------------------------------- + io_g_b : t400_io_g + generic map ( + opt_out_type_3_g => opt_g_out_type_3_g, + opt_out_type_2_g => opt_g_out_type_2_g, + opt_out_type_1_g => opt_g_out_type_1_g, + opt_out_type_0_g => opt_g_out_type_0_g, + opt_microbus_g => opt_microbus_g + ) + port map ( + ck_i => ck_i, + ck_en_i => ck_en_s, + por_i => por_s, + res_i => res_s, + cs_n_i => cs_n_s, + wr_n_i => wr_n_s, + op_i => io_g_op_s, + m_i => dm_data_i, + dec_data_i => dec_data_s, + io_g_o => io_g_o, + io_g_en_o => io_g_en_o + ); + + + ----------------------------------------------------------------------------- + -- IO IN module + ----------------------------------------------------------------------------- + use_in: if opt_type_g = t400_opt_type_420_c generate + io_in_b : t400_io_in + port map ( + ck_i => ck_i, + ck_en_i => ck_en_s, + por_i => por_s, + icyc_en_i => icyc_en_s, + in_en_i => in_en_s, + op_i => io_in_op_s, + en1_i => en_s(1), + io_in_i => io_in_i, + in_o => in_s, + int_o => int_s + ); + end generate; + + no_in: if opt_type_g /= t400_opt_type_420_c generate + in_s <= (others => '0'); + int_s <= false; + end generate; + + + ----------------------------------------------------------------------------- + -- SIO module + ----------------------------------------------------------------------------- + sio_b : t400_sio + generic map ( + opt_so_output_type_g => opt_so_output_type_g, + opt_sk_output_type_g => opt_sk_output_type_g + ) + port map ( + ck_i => ck_i, + ck_en_i => ck_en_s, + por_i => por_s, + res_i => res_s, + phi1_i => phi1_s, + out_en_i => out_en_s, + in_en_i => in_en_s, + op_i => sio_op_s, + en0_i => en_s(0), + en3_i => en_s(3), + a_i => a_s, + c_i => c_s, + sio_o => sio_s, + si_i => si_i, + so_o => so_o, + so_en_o => so_en_o, + sk_o => sk_o, + sk_en_o => sk_en_o + ); + + + ----------------------------------------------------------------------------- + -- Timer module + ----------------------------------------------------------------------------- + use_tim: if opt_type_g = t400_opt_type_420_c or + opt_type_g = t400_opt_type_421_c generate + timer_b : t400_timer + port map ( + ck_i => ck_i, + ck_en_i => ck_en_s, + por_i => por_s, + icyc_en_i => icyc_en_s, + op_i => skip_op_s, + c_o => tim_c_s + ); + end generate; + + notim: if opt_type_g /= t400_opt_type_420_c and + opt_type_g /= t400_opt_type_421_c generate + tim_c_s <= false; + end generate; + +end struct; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t400_core.vhd,v $ +-- Revision 1.10 2006/06/11 13:34:39 arniml +-- Fix bug: +-- "Timer skipped in T421 configuration" +-- The generate block that instantiates the timer module considers +-- now t400_opt_type_421_x as well. +-- +-- Revision 1.9 2006/06/06 00:33:56 arniml +-- remove note about limitations +-- +-- Revision 1.8 2006/06/05 20:34:21 arniml +-- use dedicated microbus cs/rd/wr strobes +-- +-- Revision 1.7 2006/06/05 14:19:15 arniml +-- connect microbus control signals to IO L +-- +-- Revision 1.6 2006/05/27 19:11:33 arniml +-- updates for interrupt support +-- +-- Revision 1.5 2006/05/23 01:13:56 arniml +-- use to_X01 for G input +-- +-- Revision 1.4 2006/05/22 00:03:29 arniml +-- io_in added +-- +-- Revision 1.3 2006/05/21 21:47:40 arniml +-- route cko to ALU for INIL instruction +-- +-- Revision 1.2 2006/05/20 02:48:17 arniml +-- timer module included +-- +-- Revision 1.1.1.1 2006/05/06 01:56:44 arniml +-- import from local CVS repository, LOC_CVS_0_1 +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/t400_core_comp_pack-p.vhd b/rtl/t400/rtl/vhdl/t400_core_comp_pack-p.vhd new file mode 100644 index 0000000..7bf84d0 --- /dev/null +++ b/rtl/t400/rtl/vhdl/t400_core_comp_pack-p.vhd @@ -0,0 +1,82 @@ +------------------------------------------------------------------------------- +-- +-- $Id: t400_core_comp_pack-p.vhd,v 1.1.1.1 2006/05/06 01:56:44 arniml Exp $ +-- +-- Copyright (c) 2006, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.t400_opt_pack.all; + +package t400_core_comp_pack is + + component t400_core + generic ( + opt_type_g : integer := t400_opt_type_420_c; + opt_ck_div_g : integer := t400_opt_ck_div_16_c; + opt_cko_g : integer := t400_opt_cko_crystal_c; + opt_l_out_type_7_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_6_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_5_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_4_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_3_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_l_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_microbus_g : integer := t400_opt_no_microbus_c; + opt_d_out_type_3_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_d_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_3_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_g_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_so_output_type_g : integer := t400_opt_out_type_std_c; + opt_sk_output_type_g : integer := t400_opt_out_type_std_c + ); + port ( + ck_i : in std_logic; + ck_en_i : in std_logic; + por_n_i : in std_logic; + reset_n_i : in std_logic; + cko_i : in std_logic; + pm_addr_o : out std_logic_vector(9 downto 0); + pm_data_i : in std_logic_vector(7 downto 0); + dm_addr_o : out std_logic_vector(5 downto 0); + dm_we_o : out std_logic; + dm_data_o : out std_logic_vector(3 downto 0); + dm_data_i : in std_logic_vector(3 downto 0); + io_l_i : in std_logic_vector(7 downto 0); + io_l_o : out std_logic_vector(7 downto 0); + io_l_en_o : out std_logic_vector(7 downto 0); + io_d_o : out std_logic_vector(3 downto 0); + io_d_en_o : out std_logic_vector(3 downto 0); + io_g_i : in std_logic_vector(3 downto 0); + io_g_o : out std_logic_vector(3 downto 0); + io_g_en_o : out std_logic_vector(3 downto 0); + io_in_i : in std_logic_vector(3 downto 0); + si_i : in std_logic; + so_o : out std_logic; + so_en_o : out std_logic; + sk_o : out std_logic; + sk_en_o : out std_logic + ); + end component; + +end t400_core_comp_pack; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t400_core_comp_pack-p.vhd,v $ +-- Revision 1.1.1.1 2006/05/06 01:56:44 arniml +-- import from local CVS repository, LOC_CVS_0_1 +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/t400_decoder-c.vhd b/rtl/t400/rtl/vhdl/t400_decoder-c.vhd new file mode 100644 index 0000000..c3523f5 --- /dev/null +++ b/rtl/t400/rtl/vhdl/t400_decoder-c.vhd @@ -0,0 +1,34 @@ +------------------------------------------------------------------------------- +-- +-- The decoder unit. +-- Implements the instruction opcodes and controls all units of the T400 core. +-- +-- $Id: t400_decoder-c.vhd,v 1.1.1.1 2006/05/06 01:56:44 arniml Exp $ +-- +-- Copyright (c) 2006, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +configuration t400_decoder_rtl_c0 of t400_decoder is + + for rtl + + for opc_table_b: t400_opc_table + use configuration work.t400_opc_table_rtl_c0; + end for; + + end for; + +end t400_decoder_rtl_c0; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t400_decoder-c.vhd,v $ +-- Revision 1.1.1.1 2006/05/06 01:56:44 arniml +-- import from local CVS repository, LOC_CVS_0_1 +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/t400_decoder.vhd b/rtl/t400/rtl/vhdl/t400_decoder.vhd new file mode 100644 index 0000000..d5bf1e5 --- /dev/null +++ b/rtl/t400/rtl/vhdl/t400_decoder.vhd @@ -0,0 +1,884 @@ +------------------------------------------------------------------------------- +-- +-- The decoder unit. +-- Implements the instruction opcodes and controls all units of the T400 core. +-- +-- $Id: t400_decoder.vhd,v 1.6 2006/06/05 14:20:34 arniml Exp $ +-- +-- Copyright (c) 2006 Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t400/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.t400_opt_pack.all; +use work.t400_pack.all; + +entity t400_decoder is + + generic ( + opt_type_g : integer := t400_opt_type_420_c + ); + port ( + -- System Interface ------------------------------------------------------- + ck_i : in std_logic; + ck_en_i : in boolean; + por_i : in boolean; + res_i : in boolean; + out_en_i : in boolean; + in_en_i : in boolean; + icyc_en_i : in boolean; + -- Module Control Interface ----------------------------------------------- + pc_op_o : out pc_op_t; + stack_op_o : out stack_op_t; + dmem_op_o : out dmem_op_t; + b_op_o : out b_op_t; + skip_op_o : out skip_op_t; + alu_op_o : out alu_op_t; + io_l_op_o : out io_l_op_t; + io_d_op_o : out io_d_op_t; + io_g_op_o : out io_g_op_t; + io_in_op_o : out io_in_op_t; + sio_op_o : out sio_op_t; + dec_data_o : out dec_data_t; + en_o : out dw_t; + -- Skip Interface --------------------------------------------------------- + skip_i : in boolean; + skip_lbi_i : in boolean; + is_lbi_o : out boolean; + int_i : in boolean; + -- Program Memory Interface ----------------------------------------------- + pm_addr_i : in pc_t; + pm_data_i : in byte_t + ); + +end t400_decoder; + + +library ieee; +use ieee.numeric_std.all; + +use work.t400_comp_pack.t400_opc_table; + +architecture rtl of t400_decoder is + + signal cyc_cnt_q : unsigned(2 downto 0); + signal ibyte1_q, + ibyte2_q : byte_t; + + signal opcode_s : byte_t; + signal second_cyc_q : boolean; + signal mnemonic_s, + mnemonic_q : mnemonic_t; + signal multi_byte_s, + multi_byte_q : boolean; + signal last_cycle_s : boolean; + signal force_mc_s : boolean; + + signal en_q : dw_t; + signal set_en_s : boolean; + signal ack_int_s : boolean; + +begin + + ----------------------------------------------------------------------------- + -- Theory of operation: + -- + -- a) One instruction cycle lasts at least 4 ck_i cycles. + -- b) PC for instruction/parameter fetch must be valid during cycle 2. + -- => cycle 2 is the opcode fetch cycle + -- c) Cycle 3 is the opcode decode cycle. + -- => opcode_s is valid with cycle 3 + -- d) mnemonic_q is then valid with cycle 0 until end of instruction. + -- So is ibyte1_q. + -- e) PC for is incremented during last instruction cycle. + -- => fetch of either new instruction or second instruction byte + -- f) Second instruction byte is saved in ibyte2_q for cycle 0. + -- Valid until end of instruction. + -- + -- Constraints: + -- + -- a) PC of next instruction must be pushed in cycle 0 or 1. + -- b) PC for next instruction must be poped latest in cycle 1. + -- c) PC for next instruction can only be calculated latest in cycle 1. + -- d) IO output is enabled by out_en_i + -- e) IO inputs are sampled with in_en_i + -- + -- d) and e) are required for proper timing in relation to phi1 + -- (SK clock/sync output). + -- + -- Conventions: + -- + -- a) ALU operations take place in cycle 1. + -- + ----------------------------------------------------------------------------- + + last_cycle_s <= (not multi_byte_q and + not second_cyc_q and not force_mc_s) + or + second_cyc_q; + + + ----------------------------------------------------------------------------- + -- Process seq + -- + -- Purpose: + -- Implements the various sequential elements. + -- Cycle counter: + -- It identifies the execution cycle of the + -- current instruction. + -- Instruction registers: + -- They save the first and second byte of an instruction for + -- further processing. + -- New instruction flag: + -- Indicates when a new instruction is fetched from the program + -- memory. Implemented as a flip-flop to control the multiplexer + -- which saves power by gating the combinational opcode decoder. + -- Mnemonic register: + -- Latches the decoded mnemonic of the current instruction. + -- Multi byte flag: + -- Latches the decoded multi byte status information. + -- + seq: process (ck_i, por_i) + begin + if por_i then + cyc_cnt_q <= to_unsigned(1, cyc_cnt_q'length); + second_cyc_q <= false; + ibyte1_q <= (others => '0'); + ibyte2_q <= (others => '0'); + mnemonic_q <= MN_CLRA; + multi_byte_q <= false; + en_q <= (others => '0'); + + elsif ck_i'event and ck_i = '1' then + if res_i then + -- synchronous reset upon external reset event + mnemonic_q <= MN_CLRA; + multi_byte_q <= false; + cyc_cnt_q <= (others => '0'); + en_q <= (others => '0'); + + elsif ck_en_i then + -- cycle counter ------------------------------------------------------ + if icyc_en_i then + -- new instruction cycle started + cyc_cnt_q <= (others => '0'); + elsif cyc_cnt_q /= 4 then + cyc_cnt_q <= cyc_cnt_q + 1; + end if; + + -- second cycle flag -------------------------------------------------- + if icyc_en_i then + if not last_cycle_s then + second_cyc_q <= true; + else + second_cyc_q <= false; + end if; + end if; + + -- instruction byte 1 and mnemonic info ------------------------------- + if icyc_en_i and last_cycle_s then + if not ack_int_s then + -- update instruction descriptors in normal mode + ibyte1_q <= pm_data_i; + mnemonic_q <= mnemonic_s; + multi_byte_q <= multi_byte_s; + else + -- force NOP instruction when vectoring to interrupt routine + ibyte1_q <= "01000100"; + mnemonic_q <= MN_NOP; + multi_byte_q <= false; + end if; + end if; + + -- instruction byte 2 ------------------------------------------------- + if icyc_en_i and not last_cycle_s then + ibyte2_q <= pm_data_i; + end if; + + -- EN register -------------------------------------------------------- + if set_en_s then + en_q <= ibyte2_q(dw_range_t); + elsif ack_int_s then + -- reset interrupt enable when INT has been acknowledged + en_q(1) <= '0'; + end if; + + end if; + end if; + end process seq; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Opcode multiplexer + ----------------------------------------------------------------------------- + opcode_s <= pm_data_i + when icyc_en_i else + ibyte1_q; + + ----------------------------------------------------------------------------- + -- Opcode decoder table + ----------------------------------------------------------------------------- + opc_table_b : t400_opc_table + generic map ( + opt_type_g => opt_type_g + ) + port map ( + opcode_i => opcode_s, + mnemonic_o => mnemonic_s, + multi_byte_o => multi_byte_s + ); + + + ----------------------------------------------------------------------------- + -- Process decoder_ctrl + -- + -- Purpose: + -- Implements the controlling logic of the decoder module. + -- + decoder_ctrl: process (icyc_en_i, + out_en_i, in_en_i, + cyc_cnt_q, + mnemonic_q, second_cyc_q, last_cycle_s, + ibyte1_q, ibyte2_q, + skip_i, skip_lbi_i, + en_q, int_i, + pm_addr_i, pm_data_i) + variable cyc_v : natural range 0 to 4; + variable t41x_type_v, + t420_type_v : boolean; + variable en_int_v : boolean; + begin + -- default assignments + pc_op_o <= PC_NONE; + stack_op_o <= STACK_NONE; + dmem_op_o <= DMEM_RB; -- default is read via B + b_op_o <= B_NONE; + skip_op_o <= SKIP_NONE; + alu_op_o <= ALU_NONE; + io_l_op_o <= IOL_NONE; + io_d_op_o <= IOD_NONE; + io_g_op_o <= IOG_NONE; + io_in_op_o <= IOIN_NONE; + sio_op_o <= SIO_NONE; + dec_data_o <= (others => '0'); + is_lbi_o <= false; + set_en_s <= false; + force_mc_s <= false; + en_int_v := true; + ack_int_s <= false; + cyc_v := to_integer(cyc_cnt_q); + -- determine type + t41x_type_v := opt_type_g = t400_opt_type_410_c; + t420_type_v := opt_type_g = t400_opt_type_420_c; + + if icyc_en_i then + -- immediately increment program counter + -- this happens at two occasions: + -- a) right before new mnemonic becomes valid + -- b) before the second instruction cycle begins + pc_op_o <= PC_INC_PC; + end if; + + if icyc_en_i and last_cycle_s then + -- update skip state when last instruction cycle ends + skip_op_o <= SKIP_UPDATE; + end if; + + -- skip instruction execution + if not skip_i then + -- implement instruction control + case mnemonic_q is + -- Mnemonic ASC ------------------------------------------------------- + when MN_ASC => + if cyc_v = 1 then + alu_op_o <= ALU_ADD_C; + skip_op_o <= SKIP_CARRY; + end if; + + -- Mnemonic ADD ------------------------------------------------------- + when MN_ADD => + if cyc_v = 1 then + alu_op_o <= ALU_ADD; + end if; + + -- Mnemonic ADT ------------------------------------------------------- + when MN_ADT => + if cyc_v = 1 then + alu_op_o <= ALU_ADD_10; + end if; + + -- Mnemonic AISC ------------------------------------------------------ + when MN_AISC => + dec_data_o(dw_range_t) <= ibyte1_q(dw_range_t); + if cyc_v = 1 then + alu_op_o <= ALU_ADD_DEC; + skip_op_o <= SKIP_CARRY; + end if; + + -- Mnemonic CASC ------------------------------------------------------ + when MN_CASC => + case cyc_v is + when 0 => + alu_op_o <= ALU_COMP; + when 1 => + alu_op_o <= ALU_ADD_C; + skip_op_o <= SKIP_CARRY; + when others => + null; + end case; + + -- Mnemonic CLRA ------------------------------------------------------ + when MN_CLRA => + if cyc_v = 1 then + alu_op_o <= ALU_CLRA; + end if; + + -- Mnemonic COMP ------------------------------------------------------ + when MN_COMP => + if cyc_v = 1 then + alu_op_o <= ALU_COMP; + end if; + + -- Mnemonic NOP ------------------------------------------------------- + when MN_NOP => + -- do nothing + null; + + -- Mnemonic C --------------------------------------------------------- + when MN_C => + if cyc_v = 1 then + if ibyte1_q(4) = '1' then + alu_op_o <= ALU_RC; + else + alu_op_o <= ALU_SC; + end if; + end if; + + -- Mnemonic XOR ------------------------------------------------------- + when MN_XOR => + if cyc_v = 1 then + alu_op_o <= ALU_XOR; + end if; + + -- Mnemonic JID ------------------------------------------------------- + when MN_JID => + force_mc_s <= true; + en_int_v := false; + dec_data_o(byte_t'range) <= pm_data_i; + if cyc_v = 1 then + if not second_cyc_q then + -- first cycle: load PC from A and M + pc_op_o <= PC_LOAD_A_M; + else + -- second cycle: load PC from program memory + pc_op_o <= PC_LOAD_8; + end if; + end if; + + if icyc_en_i and not second_cyc_q then + -- do not increment PC for second instruction cycle + pc_op_o <= PC_NONE; + end if; + + -- Mnemonic JMP ------------------------------------------------------- + when MN_JMP => + en_int_v := false; + dec_data_o <= ibyte1_q(1) & ibyte1_q(0) & ibyte2_q; + if second_cyc_q and cyc_v = 1 then + pc_op_o <= PC_LOAD; + end if; + + -- Mnemonic JP_JSRP --------------------------------------------------- + when MN_JP_JSRP => + en_int_v := false; + -- universal decoder data + dec_data_o <= '0' & "01" & ibyte1_q(6 downto 0); + if cyc_v = 1 then + if pm_addr_i(9 downto 7) = "001" then + -- JP within pages 2 & 3 + pc_op_o <= PC_LOAD_7; + elsif ibyte1_q(6) = '1' then + -- JP outside of pages 2 & 3 + pc_op_o <= PC_LOAD_6; + else + -- JSRP to page 2 + pc_op_o <= PC_LOAD; + stack_op_o <= STACK_PUSH; + end if; + end if; + + -- Mnemonic JSR ------------------------------------------------------- + when MN_JSR => + en_int_v := false; + dec_data_o <= ibyte1_q(1) & ibyte1_q(0) & ibyte2_q; + if second_cyc_q and cyc_v = 1 then + pc_op_o <= PC_LOAD; + stack_op_o <= STACK_PUSH; + end if; + + -- Mnemonic RET ------------------------------------------------------- + when MN_RET => + en_int_v := false; + if cyc_v = 1 then + pc_op_o <= PC_POP; + stack_op_o <= STACK_POP; + + if t420_type_v then + -- always restore skip state in case this was an interrupt + skip_op_o <= SKIP_POP; + end if; + end if; + + -- Mnemonic RETSK ----------------------------------------------------- + when MN_RETSK => + en_int_v := false; + if cyc_v = 1 then + pc_op_o <= PC_POP; + stack_op_o <= STACK_POP; + skip_op_o <= SKIP_NOW; + end if; + + -- Mnemonic LD -------------------------------------------------------- + when MN_LD => + dec_data_o(br_range_t) <= ibyte1_q(br_range_t); + if cyc_v = 1 then + alu_op_o <= ALU_LOAD_M; + b_op_o <= B_XOR_BR; + end if; + + -- Mnemonic LDD_XAD --------------------------------------------------- + when MN_LDD_XAD => + -- preload decoder data + dec_data_o(b_range_t) <= ibyte2_q(b_range_t); + + if second_cyc_q then + case ibyte2_q(7 downto 6) is + -- LDD + when "00" => + if not t41x_type_v then + case cyc_v is + when 1 => + dmem_op_o <= DMEM_RDEC; + when 2 => + alu_op_o <= ALU_LOAD_M; + when others => + null; + end case; + end if; + -- XAD + when "10" => + if not t41x_type_v or + unsigned(ibyte2_q(b_range_t)) = 63 then + case cyc_v is + when 1 => + dmem_op_o <= DMEM_RDEC; + when 2 => + alu_op_o <= ALU_LOAD_M; + dmem_op_o <= DMEM_WDEC_SRC_A; + when others => + null; + end case; + end if; + + when others => + null; + end case; + end if; + + -- Mnemonic LQID ------------------------------------------------------ + when MN_LQID => + force_mc_s <= true; + en_int_v := false; + if not second_cyc_q then + -- first cycle: push PC and set PC from A/M, + -- read IOL from program memory + if cyc_v = 1 then + stack_op_o <= STACK_PUSH; + pc_op_o <= PC_LOAD_A_M; + end if; + + if out_en_i then + io_l_op_o <= IOL_LOAD_PM; + end if; + else + if cyc_v = 1 then + -- second cycle: pop PC + stack_op_o <= STACK_POP; + pc_op_o <= PC_POP; + end if; + end if; + + if icyc_en_i and not second_cyc_q then + -- do not increment PC for second instruction cycle + pc_op_o <= PC_NONE; + end if; + + -- Mnemonic RMB ------------------------------------------------------- + when MN_RMB => + if cyc_v = 1 then + dmem_op_o <= DMEM_WB_RES_BIT; + -- select bit to be reset + case ibyte1_q(dw_range_t) is + when "1100" => + dec_data_o(dw_range_t) <= "0001"; + when "0101" => + dec_data_o(dw_range_t) <= "0010"; + when "0010" => + dec_data_o(dw_range_t) <= "0100"; + when "0011" => + dec_data_o(dw_range_t) <= "1000"; + when others => + null; + end case; + end if; + + -- Mnemonic SMB ------------------------------------------------------- + when MN_SMB => + if cyc_v = 1 then + dmem_op_o <= DMEM_WB_SET_BIT; + -- select bit to be set + case ibyte1_q(dw_range_t) is + when "1101" => + dec_data_o(dw_range_t) <= "0001"; + when "0111" => + dec_data_o(dw_range_t) <= "0010"; + when "0110" => + dec_data_o(dw_range_t) <= "0100"; + when "1011" => + dec_data_o(dw_range_t) <= "1000"; + when others => + null; + end case; + end if; + + -- Mnemonic STII ------------------------------------------------------ + when MN_STII => + dec_data_o(dw_range_t) <= ibyte1_q(dw_range_t); + if cyc_v = 1 then + dmem_op_o <= DMEM_WB_SRC_DEC; + b_op_o <= B_INC_BD; + end if; + + -- Mnemonic X --------------------------------------------------------- + when MN_X => + dec_data_o(br_range_t) <= ibyte1_q(br_range_t); + if cyc_v = 1 then + alu_op_o <= ALU_LOAD_M; + dmem_op_o <= DMEM_WB_SRC_A; + b_op_o <= B_XOR_BR; + end if; + + -- Mnemonic XDS ------------------------------------------------------- + when MN_XDS => + dec_data_o(br_range_t) <= ibyte1_q(br_range_t); + case cyc_v is + when 1 => + alu_op_o <= ALU_LOAD_M; + dmem_op_o <= DMEM_WB_SRC_A; + b_op_o <= B_DEC_BD; + when 2 => + b_op_o <= B_XOR_BR; + skip_op_o <= SKIP_BD_UFLOW; + when others => + null; + end case; + + -- Mnemonic XIS ------------------------------------------------------- + when MN_XIS => + dec_data_o(br_range_t) <= ibyte1_q(br_range_t); + case cyc_v is + when 1 => + alu_op_o <= ALU_LOAD_M; + dmem_op_o <= DMEM_WB_SRC_A; + b_op_o <= B_INC_BD; + when 2 => + b_op_o <= B_XOR_BR; + skip_op_o <= SKIP_BD_OFLOW; + when others => + null; + end case; + + -- Mnemonic CAB ------------------------------------------------------- + when MN_CAB => + if cyc_v = 1 then + b_op_o <= B_SET_BD; + end if; + + -- Mnemonic CBA ------------------------------------------------------- + when MN_CBA => + if cyc_v = 1 then + alu_op_o <= ALU_LOAD_BD; + end if; + + -- Mnemonic LBI ------------------------------------------------------- + when MN_LBI => + is_lbi_o <= true; + en_int_v := false; + dec_data_o(br_range_t) <= ibyte1_q(br_range_t); + dec_data_o(bd_range_t) <= ibyte1_q(bd_range_t); + if cyc_v = 1 and not skip_lbi_i then + -- increment Bd by 1 + b_op_o <= B_SET_B_INC; + skip_op_o <= SKIP_LBI; + end if; + + -- Mnemonic XABR ------------------------------------------------------ + when MN_XABR => + if cyc_v = 1 then + alu_op_o <= ALU_LOAD_BR; + b_op_o <= B_SET_BR; + end if; + + -- Mnemonic SKC ------------------------------------------------------- + when MN_SKC => + if cyc_v = 1 then + skip_op_o <= SKIP_C; + end if; + + -- Mnemonic SKE ------------------------------------------------------- + when MN_SKE => + if cyc_v = 1 then + skip_op_o <= SKIP_A_M; + end if; + + -- Mnemonic SKMBZ ----------------------------------------------------- + when MN_SKMBZ => + if cyc_v = 1 then + skip_op_o <= SKIP_M_BIT; + -- select bit to be checked + case ibyte1_q is + when "00000001" => + dec_data_o(dw_range_t) <= "0001"; + when "00010001" => + dec_data_o(dw_range_t) <= "0010"; + when "00000011" => + dec_data_o(dw_range_t) <= "0100"; + when "00010011" => + dec_data_o(dw_range_t) <= "1000"; + when others => + null; + end case; + end if; + + -- Mnemonic SKT ------------------------------------------------------- + when MN_SKT => + if cyc_v = 1 then + skip_op_o <= SKIP_TIMER; + end if; + + -- Mnemonic XAS ------------------------------------------------------- + when MN_XAS => + if out_en_i then + sio_op_o <= SIO_LOAD; + alu_op_o <= ALU_LOAD_SIO; + end if; + + -- Mnemonic EXT ------------------------------------------------------- + when MN_EXT => + if second_cyc_q then + case ibyte2_q is + -- CAMQ + when "00111100" => + if out_en_i then + io_l_op_o <= IOL_LOAD_AM; + end if; + -- CQMA + when "00101100" => + if not t41x_type_v and in_en_i then + io_l_op_o <= IOL_OUTPUT_Q; + alu_op_o <= ALU_LOAD_Q; + dmem_op_o <= DMEM_WB_SRC_Q; + end if; + -- SKGZ + when "00100001" => + if in_en_i then + skip_op_o <= SKIP_G_ZERO; + end if; + -- SKGBZ + when "00000001" => + if in_en_i then + skip_op_o <= SKIP_G_BIT; + dec_data_o(dw_range_t) <= "0001"; + end if; + when "00010001" => + if in_en_i then + skip_op_o <= SKIP_G_BIT; + dec_data_o(dw_range_t) <= "0010"; + end if; + when "00000011" => + if in_en_i then + skip_op_o <= SKIP_G_BIT; + dec_data_o(dw_range_t) <= "0100"; + end if; + when "00010011" => + if in_en_i then + skip_op_o <= SKIP_G_BIT; + dec_data_o(dw_range_t) <= "1000"; + end if; + -- ING + when "00101010" => + if cyc_v = 1 then + alu_op_o <= ALU_LOAD_G; + end if; + -- INL + when "00101110" => + if in_en_i then + io_l_op_o <= IOL_OUTPUT_L; + alu_op_o <= ALU_LOAD_Q; + dmem_op_o <= DMEM_WB_SRC_Q; + end if; + -- ININ + when "00101000" => + if not t41x_type_v and in_en_i then + alu_op_o <= ALU_LOAD_IN; + end if; + -- INIL + when "00101001" => + if not t41x_type_v and in_en_i then + alu_op_o <= ALU_LOAD_IL; + io_in_op_o <= IOIN_INIL; + end if; + -- OBD + when "00111110" => + if out_en_i then + io_d_op_o <= IOD_LOAD; + end if; + -- OMG + when "00111010" => + if out_en_i then + io_g_op_o <= IOG_LOAD_M; + end if; + -- multiple codes + when others => + -- apply default decoder output, largest required vector + dec_data_o(b_range_t) <= ibyte2_q(b_range_t); + -- LBI + if ibyte2_q(7 downto 6) = "10" and not t41x_type_v then + is_lbi_o <= true; + en_int_v := false; + if cyc_v > 0 and not skip_lbi_i then + b_op_o <= B_SET_B; + skip_op_o <= SKIP_LBI; + end if; + end if; + -- LEI + if ibyte2_q(7 downto 4) = "0110" and in_en_i then + -- dec_data_o applied by default + set_en_s <= true; + + -- acknowledge pending interrupt when EN(1) is not + -- enabled - will clear them until interrupts are + -- enabled with EN(1) = '1' + if en_q(1) = '0' then + io_in_op_o <= IOIN_INTACK; + end if; + end if; + -- OGI + if ibyte2_q(7 downto 4) = "0101" and out_en_i and + not t41x_type_v then + -- dec_data_o applied by default + io_g_op_o <= IOG_LOAD_DEC; + end if; + end case; + end if; + + when others => + null; + end case; + end if; + + + -- Interrupt handling ----------------------------------------------------- + if t420_type_v and + en_q(1) = '1' and int_i and en_int_v then + if last_cycle_s then + if cyc_v = 1 then + stack_op_o <= STACK_PUSH; + end if; + if icyc_en_i then + ack_int_s <= true; + io_in_op_o <= IOIN_INTACK; + pc_op_o <= PC_INT; + -- push skip state that was determined by current instruction + -- and will be valid for the next instruction which is delayed + -- by the interrupt + skip_op_o <= SKIP_PUSH; + end if; + end if; + end if; + + end process decoder_ctrl; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Output mapping + ----------------------------------------------------------------------------- + en_o <= en_q; + +end rtl; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t400_decoder.vhd,v $ +-- Revision 1.6 2006/06/05 14:20:34 arniml +-- interface comments added +-- +-- Revision 1.5 2006/05/28 15:32:14 arniml +-- execute virtual NOP at location 0x0ff when vectoring to interrupt routine +-- +-- Revision 1.4 2006/05/27 19:14:18 arniml +-- interrupt functionality added +-- +-- Revision 1.3 2006/05/22 00:02:36 arniml +-- instructions ININ and INIL implemented +-- +-- Revision 1.2 2006/05/07 02:24:16 arniml +-- fix sensitivity list +-- +-- Revision 1.1.1.1 2006/05/06 01:56:44 arniml +-- import from local CVS repository, LOC_CVS_0_1 +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/t400_dmem_ctrl-c.vhd b/rtl/t400/rtl/vhdl/t400_dmem_ctrl-c.vhd new file mode 100644 index 0000000..cab9537 --- /dev/null +++ b/rtl/t400/rtl/vhdl/t400_dmem_ctrl-c.vhd @@ -0,0 +1,28 @@ +------------------------------------------------------------------------------- +-- +-- The Data memory controller. +-- +-- $Id: t400_dmem_ctrl-c.vhd,v 1.1.1.1 2006/05/06 01:56:44 arniml Exp $ +-- +-- Copyright (c) 2006, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +configuration t400_dmem_ctrl_rtl_c0 of t400_dmem_ctrl is + + for rtl + end for; + +end t400_dmem_ctrl_rtl_c0; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t400_dmem_ctrl-c.vhd,v $ +-- Revision 1.1.1.1 2006/05/06 01:56:44 arniml +-- import from local CVS repository, LOC_CVS_0_1 +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/t400_dmem_ctrl.vhd b/rtl/t400/rtl/vhdl/t400_dmem_ctrl.vhd new file mode 100644 index 0000000..1c4ab34 --- /dev/null +++ b/rtl/t400/rtl/vhdl/t400_dmem_ctrl.vhd @@ -0,0 +1,254 @@ +------------------------------------------------------------------------------- +-- +-- The Data memory controller. +-- +-- $Id: t400_dmem_ctrl.vhd,v 1.1.1.1 2006/05/06 01:56:44 arniml Exp $ +-- +-- Copyright (c) 2006 Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t400/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.t400_opt_pack.all; +use work.t400_pack.all; + +entity t400_dmem_ctrl is + + generic ( + opt_type_g : integer := t400_opt_type_420_c + ); + port ( + -- System Interface ------------------------------------------------------- + ck_i : in std_logic; + ck_en_i : in boolean; + por_i : in boolean; + res_i : in boolean; + -- Control Interface ------------------------------------------------------ + dmem_op_i : in dmem_op_t; + b_op_i : in b_op_t; + dec_data_i : in dec_data_t; + a_i : in dw_t; + q_high_i : in dw_t; + b_o : out b_t; + -- Data Memory Interface -------------------------------------------------- + dm_addr_o : out dm_addr_t; + dm_data_i : in dw_t; + dm_data_o : out dw_t; + dm_we_o : out std_logic + ); + +end t400_dmem_ctrl; + + +library ieee; +use ieee.numeric_std.all; + +architecture rtl of t400_dmem_ctrl is + + signal br_q : unsigned(br_range_t); + signal bd_q : unsigned(bd_range_t); + +begin + + ----------------------------------------------------------------------------- + -- Process b_reg + -- + -- Purpose: + -- Implements the B register. + -- + b_reg: process (ck_i, por_i) + begin + if por_i then + br_q <= (others => '0'); + bd_q <= (others => '0'); + + elsif ck_i'event and ck_i = '1' then + if res_i then + -- synchronous reset upon external reset event + br_q <= (others => '0'); + bd_q <= (others => '0'); + + elsif ck_en_i then + case b_op_i is + -- Set Bd from accumulator ------------------------------------------ + when B_SET_BD => + bd_q <= unsigned(a_i); + + -- Set Br from accumulator ------------------------------------------ + when B_SET_BR => + br_q <= unsigned(a_i(1 downto 0)); + + -- Set Br and Bd from decoder data ---------------------------------- + when B_SET_B => + br_q <= unsigned(dec_data_i(br_range_t)); + bd_q <= unsigned(dec_data_i(bd_range_t)); + + -- Set Br and Bd from decoder data, increment value for Bd ---------- + when B_SET_B_INC => + br_q <= unsigned(dec_data_i(br_range_t)); + bd_q <= unsigned(dec_data_i(bd_range_t)) + 1; + + -- XOR Br with decoder data ----------------------------------------- + when B_XOR_BR => + br_q <= br_q xor unsigned(dec_data_i(br_range_t)); + + -- Increment Bd ----------------------------------------------------- + when B_INC_BD => + bd_q <= bd_q + 1; + + -- Increment Bd ----------------------------------------------------- + when B_DEC_BD => + bd_q <= bd_q - 1; + + when others => + null; + end case; + + end if; + end if; + end process b_reg; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process data_mux + -- + -- Purpose: + -- Multiplexes the data for writing to the memory. + -- + data_mux: process (dmem_op_i, + br_q, bd_q, + a_i, + q_high_i, + dec_data_i, + dm_data_i, + ck_en_i) + variable dm_addr_v : dm_addr_t; + variable dm_data_v : dw_t; + variable dm_we_v : std_logic; + variable bd_v : std_logic_vector(2 downto 0); + begin + -- default assignment + dm_addr_v(br_range_t) := std_logic_vector(br_q); + dm_addr_v(bd_range_t) := std_logic_vector(bd_q); + dm_data_v := (others => '0'); + dm_we_v := '0'; + + case dmem_op_i is + -- Read data memory, indexed by B --------------------------------------- + when DMEM_RB => + null; + + -- Write data memory, indexed by B, source is Q ------------------------- + when DMEM_WB_SRC_Q => + dm_we_v := '1'; + dm_data_v := q_high_i; + + -- Write data memory, indexed by B, source is decoder data -------------- + when DMEM_WB_SRC_DEC => + dm_we_v := '1'; + dm_data_v := dec_data_i(bd_range_t); + + -- Write data memory, indexed by B, source is accumulator --------------- + when DMEM_WB_SRC_A => + dm_we_v := '1'; + dm_data_v := a_i; + + -- Read data memory, indexed by decoder data ---------------------------- + when DMEM_RDEC => + dm_addr_v := dec_data_i(br_range_t'high downto 0); + + -- Write data memory, indexed by decoder data, source is accumulator ---- + when DMEM_WDEC_SRC_A => + dm_we_v := '1'; + dm_addr_v := dec_data_i(br_range_t'high downto 0); + dm_data_v := a_i; + + -- Write data memory, indexed by B, set bit ----------------------------- + when DMEM_WB_SET_BIT => + dm_we_v := '1'; + dm_data_v := dm_data_i or dec_data_i(dw_range_t); + + -- Write data memory, indexed by B, reset bit --------------------------- + when DMEM_WB_RES_BIT => + dm_we_v := '1'; + dm_data_v := dm_data_i and not dec_data_i(dw_range_t); + + when others => + null; + end case; + + -- adjust address vector for 41xL family members + if opt_type_g = t400_opt_type_410_c then + dm_addr_v := '0' & dm_addr_v(br_range_t) & + dm_addr_v(bd_range_t'high-1 downto 0); + end if; + + dm_addr_o <= dm_addr_v; + + if ck_en_i then + dm_we_o <= dm_we_v; + else + dm_we_o <= '0'; + end if; + dm_data_o <= dm_data_v; + end process data_mux; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Output mapping + ----------------------------------------------------------------------------- + b_o(br_range_t) <= std_logic_vector(br_q); + b_o(bd_range_t) <= std_logic_vector(bd_q); + +end rtl; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t400_dmem_ctrl.vhd,v $ +-- Revision 1.1.1.1 2006/05/06 01:56:44 arniml +-- import from local CVS repository, LOC_CVS_0_1 +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/t400_io_d-c.vhd b/rtl/t400/rtl/vhdl/t400_io_d-c.vhd new file mode 100644 index 0000000..b558e5c --- /dev/null +++ b/rtl/t400/rtl/vhdl/t400_io_d-c.vhd @@ -0,0 +1,28 @@ +------------------------------------------------------------------------------- +-- +-- The D port controller. +-- +-- $Id: t400_io_d-c.vhd,v 1.1.1.1 2006/05/06 01:56:44 arniml Exp $ +-- +-- Copyright (c) 2006, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +configuration t400_io_d_rtl_c0 of t400_io_d is + + for rtl + end for; + +end t400_io_d_rtl_c0; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t400_io_d-c.vhd,v $ +-- Revision 1.1.1.1 2006/05/06 01:56:44 arniml +-- import from local CVS repository, LOC_CVS_0_1 +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/t400_io_d.vhd b/rtl/t400/rtl/vhdl/t400_io_d.vhd new file mode 100644 index 0000000..76e9aac --- /dev/null +++ b/rtl/t400/rtl/vhdl/t400_io_d.vhd @@ -0,0 +1,167 @@ +------------------------------------------------------------------------------- +-- +-- The D port controller. +-- +-- $Id: t400_io_d.vhd,v 1.2 2006/05/07 02:24:16 arniml Exp $ +-- +-- Copyright (c) 2006 Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t400/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.t400_opt_pack.all; +use work.t400_pack.all; + +entity t400_io_d is + + generic ( + opt_out_type_3_g : integer := t400_opt_out_type_std_c; + opt_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_out_type_0_g : integer := t400_opt_out_type_std_c + ); + port ( + -- System Interface ------------------------------------------------------- + ck_i : in std_logic; + ck_en_i : in boolean; + por_i : in boolean; + res_i : in boolean; + -- Control Interface ------------------------------------------------------ + op_i : in io_d_op_t; + bd_i : in bd_t; + -- Port D Interface ------------------------------------------------------- + io_d_o : out dw_t; + io_d_en_o : out dw_t + ); + +end t400_io_d; + + +use work.t400_io_pack.all; + +architecture rtl of t400_io_d is + + signal d_q : dw_t; + + signal vdd_s : std_logic; + +begin + + vdd_s <= '1'; + + ----------------------------------------------------------------------------- + -- Process d_reg + -- + -- Purpose: + -- Implements the D output register. + -- + d_reg: process (ck_i, por_i) + begin + if por_i then + d_q <= (others => '0'); + + elsif ck_i'event and ck_i = '1' then + if res_i then + -- synchronous reset upon external reset event + d_q <= (others => '0'); + + elsif ck_en_i then + if op_i = IOD_LOAD then + d_q <= bd_i; + end if; + end if; + + end if; + end process d_reg; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process out_driver + -- + -- Purpose: + -- Implements the output driver data and enable. + -- + out_driver: process (d_q, + vdd_s) + begin + -- bit 3 + io_d_o(3) <= io_out_f(dat => d_q(3), + opt => opt_out_type_3_g); + io_d_en_o(3) <= io_en_f (en => vdd_s, dat => d_q(3), + opt => opt_out_type_3_g); + + -- bit 2 + io_d_o(2) <= io_out_f(dat => d_q(2), + opt => opt_out_type_2_g); + io_d_en_o(2) <= io_en_f (en => vdd_s, dat => d_q(2), + opt => opt_out_type_2_g); + + -- bit 1 + io_d_o(1) <= io_out_f(dat => d_q(1), + opt => opt_out_type_1_g); + io_d_en_o(1) <= io_en_f (en => vdd_s, dat => d_q(1), + opt => opt_out_type_1_g); + + -- bit 0 + io_d_o(0) <= io_out_f(dat => d_q(0), + opt => opt_out_type_0_g); + io_d_en_o(0) <= io_en_f (en => vdd_s, dat => d_q(0), + opt => opt_out_type_0_g); + + end process out_driver; + -- + ----------------------------------------------------------------------------- + +end rtl; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t400_io_d.vhd,v $ +-- Revision 1.2 2006/05/07 02:24:16 arniml +-- fix sensitivity list +-- +-- Revision 1.1.1.1 2006/05/06 01:56:44 arniml +-- import from local CVS repository, LOC_CVS_0_1 +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/t400_io_g-c.vhd b/rtl/t400/rtl/vhdl/t400_io_g-c.vhd new file mode 100644 index 0000000..9ae1bc2 --- /dev/null +++ b/rtl/t400/rtl/vhdl/t400_io_g-c.vhd @@ -0,0 +1,28 @@ +------------------------------------------------------------------------------- +-- +-- The G port controller. +-- +-- $Id: t400_io_g-c.vhd,v 1.1.1.1 2006/05/06 01:56:44 arniml Exp $ +-- +-- Copyright (c) 2006, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +configuration t400_io_g_rtl_c0 of t400_io_g is + + for rtl + end for; + +end t400_io_g_rtl_c0; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t400_io_g-c.vhd,v $ +-- Revision 1.1.1.1 2006/05/06 01:56:44 arniml +-- import from local CVS repository, LOC_CVS_0_1 +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/t400_io_g.vhd b/rtl/t400/rtl/vhdl/t400_io_g.vhd new file mode 100644 index 0000000..3427ea7 --- /dev/null +++ b/rtl/t400/rtl/vhdl/t400_io_g.vhd @@ -0,0 +1,185 @@ +------------------------------------------------------------------------------- +-- +-- The G port controller. +-- +-- $Id: t400_io_g.vhd,v 1.3 2006/06/05 20:32:34 arniml Exp $ +-- +-- Copyright (c) 2006 Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t400/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.t400_opt_pack.all; +use work.t400_pack.all; + +entity t400_io_g is + + generic ( + opt_out_type_3_g : integer := t400_opt_out_type_std_c; + opt_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_microbus_g : integer := t400_opt_no_microbus_c + ); + port ( + -- System Interface ------------------------------------------------------- + ck_i : in std_logic; + ck_en_i : in boolean; + por_i : in boolean; + res_i : in boolean; + -- Control Interface ------------------------------------------------------ + op_i : in io_g_op_t; + m_i : in dw_t; + dec_data_i : in dec_data_t; + cs_n_i : in std_logic; + wr_n_i : in std_logic; + -- Port G Interface ------------------------------------------------------- + io_g_o : out dw_t; + io_g_en_o : out dw_t + ); + +end t400_io_g; + + +use work.t400_io_pack.all; + +architecture rtl of t400_io_g is + + signal g_q : dw_t; + + signal vdd_s : std_logic; + +begin + + vdd_s <= '1'; + + ----------------------------------------------------------------------------- + -- Process g_reg + -- + -- Purpose: + -- Implements the G output register. + -- + g_reg: process (ck_i, por_i) + begin + if por_i then + g_q <= (others => '0'); + + elsif ck_i'event and ck_i = '1' then + if res_i then + -- synchronous reset upon external reset event + g_q <= (others => '0'); + + elsif ck_en_i then + case op_i is + when IOG_LOAD_M => + g_q <= m_i; + when IOG_LOAD_DEC => + g_q <= dec_data_i(dw_range_t); + when others => + null; + end case; + + end if; + + -- reset G(0) in MICROBUS operation upon write + if opt_microbus_g = t400_opt_microbus_c and + cs_n_i = '0' and wr_n_i = '0' then + g_q(0) <= '0'; + end if; + end if; + end process g_reg; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process out_driver + -- + -- Purpose: + -- Implements the output driver data and enable. + -- + out_driver: process (g_q, + vdd_s) + begin + -- bit 3 + io_g_o(3) <= io_out_f(dat => g_q(3), + opt => opt_out_type_3_g); + io_g_en_o(3) <= io_en_f (en => vdd_s, dat => g_q(3), + opt => opt_out_type_3_g); + + -- bit 2 + io_g_o(2) <= io_out_f(dat => g_q(2), + opt => opt_out_type_2_g); + io_g_en_o(2) <= io_en_f (en => vdd_s, dat => g_q(2), + opt => opt_out_type_2_g); + + -- bit 1 + io_g_o(1) <= io_out_f(dat => g_q(1), + opt => opt_out_type_1_g); + io_g_en_o(1) <= io_en_f (en => vdd_s, dat => g_q(1), + opt => opt_out_type_1_g); + + -- bit 0 + io_g_o(0) <= io_out_f(dat => g_q(0), + opt => opt_out_type_0_g); + io_g_en_o(0) <= io_en_f (en => vdd_s, dat => g_q(0), + opt => opt_out_type_0_g); + + end process out_driver; + -- + ----------------------------------------------------------------------------- + +end rtl; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t400_io_g.vhd,v $ +-- Revision 1.3 2006/06/05 20:32:34 arniml +-- reset G(0) upon write access in microbus mode +-- +-- Revision 1.2 2006/05/07 02:24:16 arniml +-- fix sensitivity list +-- +-- Revision 1.1.1.1 2006/05/06 01:56:44 arniml +-- import from local CVS repository, LOC_CVS_0_1 +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/t400_io_in-c.vhd b/rtl/t400/rtl/vhdl/t400_io_in-c.vhd new file mode 100644 index 0000000..074edad --- /dev/null +++ b/rtl/t400/rtl/vhdl/t400_io_in-c.vhd @@ -0,0 +1,31 @@ +------------------------------------------------------------------------------- +-- +-- The IN port controller. +-- +-- $Id: t400_io_in-c.vhd,v 1.1.1.1 2006/06/10 17:50:15 arnim Exp $ +-- +-- Copyright (c) 2006, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +configuration t400_io_in_rtl_c0 of t400_io_in is + + for rtl + end for; + +end t400_io_in_rtl_c0; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t400_io_in-c.vhd,v $ +-- Revision 1.1.1.1 2006/06/10 17:50:15 arnim +-- copied from opencores.org repository, pre-1.0 release on 10-Jun-2006 +-- +-- Revision 1.1 2006/05/22 00:00:55 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/t400_io_in.vhd b/rtl/t400/rtl/vhdl/t400_io_in.vhd new file mode 100644 index 0000000..ffee8ad --- /dev/null +++ b/rtl/t400/rtl/vhdl/t400_io_in.vhd @@ -0,0 +1,187 @@ +------------------------------------------------------------------------------- +-- +-- The IN port controller. +-- +-- $Id: t400_io_in.vhd,v 1.1.1.1 2006/06/10 17:50:15 arnim Exp $ +-- +-- Copyright (c) 2006 Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t400/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.t400_pack.all; + +entity t400_io_in is + + port ( + -- System Interface ------------------------------------------------------- + ck_i : in std_logic; + ck_en_i : in boolean; + por_i : in boolean; + icyc_en_i : in boolean; + in_en_i : in boolean; + -- Control Interface ------------------------------------------------------ + op_i : in io_in_op_t; + en1_i : in std_logic; + -- Port Interface --------------------------------------------------------- + io_in_i : in dw_t; + in_o : out dw_t; + int_o : out boolean + ); + +end t400_io_in; + + +architecture rtl of t400_io_in is + + constant idx_in3_c : natural := 2; + constant idx_in0_c : natural := 1; + constant idx_int_c : natural := 0; + + type neg_edge_t is array (natural range 1 downto 0) of + std_logic_vector(2 downto 0); + signal neg_edge_q : neg_edge_t; + signal neg_edge_s : std_logic_vector(2 downto 0); + + signal il_q : std_logic_vector(1 downto 0); + signal int_q, + int_icyc_q : boolean; + +begin + + ----------------------------------------------------------------------------- + -- Process seq + -- + -- Purpose: + -- Implements the sequential elements. + -- + seq: process (ck_i, por_i) + variable neg_edge_v : std_logic_vector(2 downto 0); + begin + if por_i then + neg_edge_q <= (others => (others => '0')); + il_q <= (others => '0'); + int_q <= false; + int_icyc_q <= false; + + elsif ck_i'event and ck_i = '1' then + -- negative edge detector filp-flops ------------------------------------ + neg_edge_v(idx_in3_c) := to_X01(io_in_i(3)); + neg_edge_v(idx_in0_c) := to_X01(io_in_i(0)); + neg_edge_v(idx_int_c) := to_X01(io_in_i(1)); + + if in_en_i then + neg_edge_q(0) <= neg_edge_v; + neg_edge_q(1) <= neg_edge_q(0) or neg_edge_v; + end if; + + -- IL latches ----------------------------------------------------------- + if in_en_i then + if neg_edge_q(1)(idx_in3_c) = '1' and + ((neg_edge_q(0)(idx_in3_c) or neg_edge_v(idx_in3_c)) = '0') then + il_q(1) <= '1'; + end if; + if neg_edge_q(1)(idx_in0_c) = '1' and + ((neg_edge_q(0)(idx_in0_c) or neg_edge_v(idx_in0_c)) = '0') then + il_q(0) <= '1'; + end if; + end if; + + -- Interrupt trigger ---------------------------------------------------- + if in_en_i then + if neg_edge_q(1)(idx_int_c) = '1' and + ((neg_edge_q(0)(idx_int_c) or neg_edge_v(idx_int_c)) = '0') then + int_q <= true; + end if; + end if; + if icyc_en_i then + -- delay interrupt request until end of current instruction + -- this ensures that the interrupt is valid for a full instruction + -- (i.e. the next one) + int_icyc_q <= int_q; + end if; + + if ck_en_i then + if op_i = IOIN_INIL then + il_q <= (others => '0'); + end if; + + if op_i = IOIN_INTACK then + int_q <= false; + int_icyc_q <= false; + end if; + end if; + + end if; + end process seq; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Output mapping + ----------------------------------------------------------------------------- + in_o <= il_q(1) & "00" & il_q(0) + when op_i = IOIN_INIL else + io_in_i; + int_o <= int_icyc_q; + +end rtl; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t400_io_in.vhd,v $ +-- Revision 1.1.1.1 2006/06/10 17:50:15 arnim +-- copied from opencores.org repository, pre-1.0 release on 10-Jun-2006 +-- +-- Revision 1.3 2006/05/27 19:14:18 arniml +-- interrupt functionality added +-- +-- Revision 1.2 2006/05/23 01:13:28 arniml +-- + reset neg_edge flip-flops to '1' +-- -> after por, a 1-to-0 edge is required to trigger the latches initially +-- + use to_X01 +-- +-- Revision 1.1 2006/05/22 00:00:55 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/t400_io_l-c.vhd b/rtl/t400/rtl/vhdl/t400_io_l-c.vhd new file mode 100644 index 0000000..d26849a --- /dev/null +++ b/rtl/t400/rtl/vhdl/t400_io_l-c.vhd @@ -0,0 +1,28 @@ +------------------------------------------------------------------------------- +-- +-- The L port controller. +-- +-- $Id: t400_io_l-c.vhd,v 1.1.1.1 2006/05/06 01:56:44 arniml Exp $ +-- +-- Copyright (c) 2006, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +configuration t400_io_l_rtl_c0 of t400_io_l is + + for rtl + end for; + +end t400_io_l_rtl_c0; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t400_io_l-c.vhd,v $ +-- Revision 1.1.1.1 2006/05/06 01:56:44 arniml +-- import from local CVS repository, LOC_CVS_0_1 +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/t400_io_l.vhd b/rtl/t400/rtl/vhdl/t400_io_l.vhd new file mode 100644 index 0000000..113fd37 --- /dev/null +++ b/rtl/t400/rtl/vhdl/t400_io_l.vhd @@ -0,0 +1,234 @@ +------------------------------------------------------------------------------- +-- +-- The L port controller. +-- +-- $Id: t400_io_l.vhd,v 1.4 2006/06/05 20:33:24 arniml Exp $ +-- +-- Copyright (c) 2006 Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t400/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.t400_opt_pack.all; +use work.t400_pack.all; + +entity t400_io_l is + + generic ( + opt_out_type_7_g : integer := t400_opt_out_type_std_c; + opt_out_type_6_g : integer := t400_opt_out_type_std_c; + opt_out_type_5_g : integer := t400_opt_out_type_std_c; + opt_out_type_4_g : integer := t400_opt_out_type_std_c; + opt_out_type_3_g : integer := t400_opt_out_type_std_c; + opt_out_type_2_g : integer := t400_opt_out_type_std_c; + opt_out_type_1_g : integer := t400_opt_out_type_std_c; + opt_out_type_0_g : integer := t400_opt_out_type_std_c; + opt_microbus_g : integer := t400_opt_no_microbus_c + ); + port ( + -- System Interface ------------------------------------------------------- + ck_i : in std_logic; + ck_en_i : in boolean; + por_i : in boolean; + in_en_i : in boolean; + -- Control Interface ------------------------------------------------------ + op_i : in io_l_op_t; + en2_i : in std_logic; + m_i : in dw_t; + a_i : in dw_t; + pm_data_i : in byte_t; + q_o : out byte_t; + -- Microbus Interface ----------------------------------------------------- + cs_n_i : in std_logic; + rd_n_i : in std_logic; + wr_n_i : in std_logic; + -- Port L Interface ------------------------------------------------------- + io_l_i : in byte_t; + io_l_o : out byte_t; + io_l_en_o : out byte_t + ); + +end t400_io_l; + + +use work.t400_io_pack.all; + +architecture rtl of t400_io_l is + + signal q_q : byte_t; + + signal en2_s : std_logic; + +begin + + ----------------------------------------------------------------------------- + -- Process q_reg + -- + -- Purpose: + -- Implements the Q register. + -- + q_reg: process (ck_i, por_i) + begin + if por_i then + q_q <= (others => '0'); + elsif ck_i'event and ck_i = '1' then + if ck_en_i then + case op_i is + -- Load Q from accumulator and data memory -------------------------- + when IOL_LOAD_AM => + q_q(7 downto 4) <= a_i; + q_q(3 downto 0) <= m_i; + + -- Load Q from program memory --------------------------------------- + when IOL_LOAD_PM => + q_q <= pm_data_i; + + when others => + null; + end case; + end if; + + -- Microbus functionality + if opt_microbus_g = t400_opt_microbus_c and + cs_n_i = '0' and wr_n_i = '0' then + q_q <= to_X01(io_l_i); + end if; + end if; + end process q_reg; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Multiplexer providing read data to the system. + ----------------------------------------------------------------------------- + q_o <= to_X01(io_l_i) + when op_i = IOL_OUTPUT_L else + q_q; + + + ----------------------------------------------------------------------------- + -- Dedicated output enable when in Microbus mode + ----------------------------------------------------------------------------- + en2_s <= cs_n_i nor rd_n_i + when opt_microbus_g = t400_opt_microbus_c else + en2_i; + + ----------------------------------------------------------------------------- + -- Process out_driver + -- + -- Purpose: + -- Implements the output driver data and enable. + -- + out_driver: process (en2_s, + q_q) + begin + -- bit 7 + io_l_o(7) <= io_out_f(dat => q_q(7), + opt => opt_out_type_7_g); + io_l_en_o(7) <= io_en_f (en => en2_s, dat => q_q(7), + opt => opt_out_type_7_g); + + -- bit 6 + io_l_o(6) <= io_out_f(dat => q_q(6), + opt => opt_out_type_6_g); + io_l_en_o(6) <= io_en_f (en => en2_s, dat => q_q(6), + opt => opt_out_type_6_g); + + -- bit 5 + io_l_o(5) <= io_out_f(dat => q_q(5), + opt => opt_out_type_5_g); + io_l_en_o(5) <= io_en_f (en => en2_s, dat => q_q(5), + opt => opt_out_type_5_g); + + -- bit 4 + io_l_o(4) <= io_out_f(dat => q_q(4), + opt => opt_out_type_4_g); + io_l_en_o(4) <= io_en_f (en => en2_s, dat => q_q(4), + opt => opt_out_type_4_g); + + -- bit 3 + io_l_o(3) <= io_out_f(dat => q_q(3), + opt => opt_out_type_3_g); + io_l_en_o(3) <= io_en_f (en => en2_s, dat => q_q(3), + opt => opt_out_type_3_g); + + -- bit 2 + io_l_o(2) <= io_out_f(dat => q_q(2), + opt => opt_out_type_2_g); + io_l_en_o(2) <= io_en_f (en => en2_s, dat => q_q(2), + opt => opt_out_type_2_g); + + -- bit 1 + io_l_o(1) <= io_out_f(dat => q_q(1), + opt => opt_out_type_1_g); + io_l_en_o(1) <= io_en_f (en => en2_s, dat => q_q(1), + opt => opt_out_type_1_g); + + -- bit 0 + io_l_o(0) <= io_out_f(dat => q_q(0), + opt => opt_out_type_0_g); + io_l_en_o(0) <= io_en_f (en => en2_s, dat => q_q(0), + opt => opt_out_type_0_g); + + end process out_driver; + -- + ----------------------------------------------------------------------------- + +end rtl; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t400_io_l.vhd,v $ +-- Revision 1.4 2006/06/05 20:33:24 arniml +-- latch Q independently of in_en +-- +-- Revision 1.3 2006/06/05 14:21:21 arniml +-- latch io_l_i upon input enable trigger +-- +-- Revision 1.2 2006/05/23 01:14:28 arniml +-- use to_X01 for primary input bus +-- +-- Revision 1.1.1.1 2006/05/06 01:56:44 arniml +-- import from local CVS repository, LOC_CVS_0_1 +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/t400_io_pack-p.vhd b/rtl/t400/rtl/vhdl/t400_io_pack-p.vhd new file mode 100644 index 0000000..0f7f171 --- /dev/null +++ b/rtl/t400/rtl/vhdl/t400_io_pack-p.vhd @@ -0,0 +1,92 @@ +------------------------------------------------------------------------------- +-- +-- $Id: t400_io_pack-p.vhd,v 1.1.1.1 2006/05/06 01:56:44 arniml Exp $ +-- +-- Copyright (c) 2006, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +package t400_io_pack is + + function io_out_f(dat : in std_logic; + opt : in integer) return std_logic; + + function io_en_f (en : in std_logic; + dat : in std_logic; + opt : in integer) return std_logic; + +end t400_io_pack; + + +use work.t400_opt_pack.all; + +package body t400_io_pack is + + function io_out_f(dat : in std_logic; + opt : in integer) return std_logic is + variable result_v : std_logic; + begin + result_v := '-'; + + case opt is + -- Open drain type output drivers --------------------------------------- + when t400_opt_out_type_od_c => + result_v := '0'; + + -- Push/pull type output drivers ---------------------------------------- + when t400_opt_out_type_std_c | + t400_opt_out_type_led_c | + t400_opt_out_type_pp_c => + result_v := dat; + + when others => + null; + end case; + + return result_v; + end io_out_f; + + + function io_en_f (en : in std_logic; + dat : in std_logic; + opt : in integer) return std_logic is + variable result_v : std_logic; + begin + result_v := '0'; + + case opt is + -- Open drain type output drivers --------------------------------------- + when t400_opt_out_type_od_c => + if en = '1' and dat = '0' then + result_v := '1'; + end if; + + -- Push/pull type output drivers ---------------------------------------- + when t400_opt_out_type_std_c | + t400_opt_out_type_led_c | + t400_opt_out_type_pp_c => + result_v := en; + + when others => + null; + end case; + + return result_v; + end io_en_f; + +end t400_io_pack; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t400_io_pack-p.vhd,v $ +-- Revision 1.1.1.1 2006/05/06 01:56:44 arniml +-- import from local CVS repository, LOC_CVS_0_1 +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/t400_opc_table-c.vhd b/rtl/t400/rtl/vhdl/t400_opc_table-c.vhd new file mode 100644 index 0000000..b337e1b --- /dev/null +++ b/rtl/t400/rtl/vhdl/t400_opc_table-c.vhd @@ -0,0 +1,29 @@ +------------------------------------------------------------------------------- +-- +-- The opcode decoder table. +-- Maps the binary opcodes to the mnemonic type. +-- +-- $Id: t400_opc_table-c.vhd,v 1.1.1.1 2006/05/06 01:56:44 arniml Exp $ +-- +-- Copyright (c) 2006, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +configuration t400_opc_table_rtl_c0 of t400_opc_table is + + for rtl + end for; + +end t400_opc_table_rtl_c0; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t400_opc_table-c.vhd,v $ +-- Revision 1.1.1.1 2006/05/06 01:56:44 arniml +-- import from local CVS repository, LOC_CVS_0_1 +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/t400_opc_table.vhd b/rtl/t400/rtl/vhdl/t400_opc_table.vhd new file mode 100644 index 0000000..1a66431 --- /dev/null +++ b/rtl/t400/rtl/vhdl/t400_opc_table.vhd @@ -0,0 +1,302 @@ +------------------------------------------------------------------------------- +-- +-- The opcode decoder table. +-- Maps the binary opcodes to the mnemonic type. +-- +-- $Id: t400_opc_table.vhd,v 1.1.1.1 2006/05/06 01:56:44 arniml Exp $ +-- +-- Copyright (c) 2006 Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t400/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.t400_opt_pack.all; +use work.t400_pack.all; + +entity t400_opc_table is + + generic ( + opt_type_g : integer := t400_opt_type_420_c + ); + port ( + opcode_i : in byte_t; + mnemonic_o : out mnemonic_t; + multi_byte_o : out boolean + ); + +end t400_opc_table; + + +architecture rtl of t400_opc_table is + +begin + + ----------------------------------------------------------------------------- + -- Process opc_decode + -- + -- Purpose: + -- Decodes the opcode to the set of mnemonics. + -- + opc_decode: process (opcode_i) + variable t41x_type_v : boolean; + begin + -- default assignment + mnemonic_o <= MN_NOP; + multi_byte_o <= false; + -- determine type + t41x_type_v := opt_type_g = t400_opt_type_410_c; + + case opcode_i is + -- Mnemonic ASC---------------------------------------------------------- + when "00110000" => + mnemonic_o <= MN_ASC; + + -- Mnemonic ADD --------------------------------------------------------- + when "00110001" => + mnemonic_o <= MN_ADD; + + -- Mnemonic ADT --------------------------------------------------------- + when "01001010" => + if not t41x_type_v then + mnemonic_o <= MN_ADT; + end if; + + -- Mnemonic AISC -------------------------------------------------------- + when "01010001" | "01010010" | "01010011" | + "01010100" | "01010101" | "01010110" | "01010111" | + "01011000" | "01011001" | "01011010" | "01011011" | + "01011100" | "01011101" | "01011110" | "01011111" => + mnemonic_o <= MN_AISC; + + -- Mnemonic CASC -------------------------------------------------------- + when "00010000" => + if not t41x_type_v then + mnemonic_o <= MN_CASC; + end if; + + -- Mnemonic CLRA -------------------------------------------------------- + when "00000000" => + mnemonic_o <= MN_CLRA; + + -- Mnemonic COMP -------------------------------------------------------- + when "01000000" => + mnemonic_o <= MN_COMP; + + -- Mnemonic NOP --------------------------------------------------------- + when "01000100" => + mnemonic_o <= MN_NOP; + + -- Mnemonic C ----------------------------------------------------------- + when "00110010" | -- RC + "00100010" => -- SC + mnemonic_o <= MN_C; + + -- Mnemonic XOR --------------------------------------------------------- + when "00000010" => + mnemonic_o <= MN_XOR; + + -- Mnemonic JID --------------------------------------------------------- + when "11111111" => + mnemonic_o <= MN_JID; + + -- Mnemonic JMP --------------------------------------------------------- + when "01100000" | "01100001" | "01100010" | "01100011" => + mnemonic_o <= MN_JMP; + multi_byte_o <= true; + + -- Mnemonic JP_JSRP ----------------------------------------------------- + when "10000000" | "10000001" | "10000010" | "10000011" | + "10000100" | "10000101" | "10000110" | "10000111" | + "10001000" | "10001001" | "10001010" | "10001011" | + "10001100" | "10001101" | "10001110" | "10001111" | + "10010000" | "10010001" | "10010010" | "10010011" | + "10010100" | "10010101" | "10010110" | "10010111" | + "10011000" | "10011001" | "10011010" | "10011011" | + "10011100" | "10011101" | "10011110" | "10011111" | + "10100000" | "10100001" | "10100010" | "10100011" | + "10100100" | "10100101" | "10100110" | "10100111" | + "10101000" | "10101001" | "10101010" | "10101011" | + "10101100" | "10101101" | "10101110" | "10101111" | + "10110000" | "10110001" | "10110010" | "10110011" | + "10110100" | "10110101" | "10110110" | "10110111" | + "10111000" | "10111001" | "10111010" | "10111011" | + "10111100" | "10111101" | "10111110" | + "11000000" | "11000001" | "11000010" | "11000011" | + "11000100" | "11000101" | "11000110" | "11000111" | + "11001000" | "11001001" | "11001010" | "11001011" | + "11001100" | "11001101" | "11001110" | "11001111" | + "11010000" | "11010001" | "11010010" | "11010011" | + "11010100" | "11010101" | "11010110" | "11010111" | + "11011000" | "11011001" | "11011010" | "11011011" | + "11011100" | "11011101" | "11011110" | "11011111" | + "11100000" | "11100001" | "11100010" | "11100011" | + "11100100" | "11100101" | "11100110" | "11100111" | + "11101000" | "11101001" | "11101010" | "11101011" | + "11101100" | "11101101" | "11101110" | "11101111" | + "11110000" | "11110001" | "11110010" | "11110011" | + "11110100" | "11110101" | "11110110" | "11110111" | + "11111000" | "11111001" | "11111010" | "11111011" | + "11111100" | "11111101" | "11111110" => + mnemonic_o <= MN_JP_JSRP; + + -- Mnemonic JSR --------------------------------------------------------- + when "01101000" | "01101001" | "01101010" | "01101011" => + mnemonic_o <= MN_JSR; + multi_byte_o <= true; + + -- Mnemonic RET --------------------------------------------------------- + when "01001000" => + mnemonic_o <= MN_RET; + + -- Mnemonic RETSK ------------------------------------------------------- + when "01001001" => + mnemonic_o <= MN_RETSK; + + -- Mnemonic LD ---------------------------------------------------------- + when "00000101" | "00010101" | "00100101" | "00110101" => + mnemonic_o <= MN_LD; + + -- Mnemonic LDD_XAD ----------------------------------------------------- + when "00100011" => + mnemonic_o <= MN_LDD_XAD; + multi_byte_o <= true; + + -- Mnemonic LQID -------------------------------------------------------- + when "10111111" => + mnemonic_o <= MN_LQID; + + -- Mnemonic RMB --------------------------------------------------------- + when "01001100" | "01000101" | "01000010" | "01000011" => + mnemonic_o <= MN_RMB; + + -- Mnemonic SMB --------------------------------------------------------- + when "01001101" | "01000111" | "01000110" | "01001011" => + mnemonic_o <= MN_SMB; + + -- Mnemonic STII -------------------------------------------------------- + when "01110000" | "01110001" | "01110010" | "01110011" | + "01110100" | "01110101" | "01110110" | "01110111" | + "01111000" | "01111001" | "01111010" | "01111011" | + "01111100" | "01111101" | "01111110" | "01111111" => + mnemonic_o <= MN_STII; + + -- Mnemonic X ----------------------------------------------------------- + when "00000110" | "00010110" | "00100110" | "00110110" => + mnemonic_o <= MN_X; + + -- Mnemonic XDS --------------------------------------------------------- + when "00000111" | "00010111" | "00100111" | "00110111" => + mnemonic_o <= MN_XDS; + + -- Mnemonic XIS --------------------------------------------------------- + when "00000100" | "00010100" | "00100100" | "00110100" => + mnemonic_o <= MN_XIS; + + -- Mnemonic CAB --------------------------------------------------------- + when "01010000" => + mnemonic_o <= MN_CAB; + + -- Mnemonic CBA --------------------------------------------------------- + when "01001110" => + mnemonic_o <= MN_CBA; + + -- Mnemonic LBI --------------------------------------------------------- + when "00001000" | "00001001" | "00001010" | "00001011" | + "00001100" | "00001101" | "00001110" | "00001111" | + "00011000" | "00011001" | "00011010" | "00011011" | + "00011100" | "00011101" | "00011110" | "00011111" | + "00101000" | "00101001" | "00101010" | "00101011" | + "00101100" | "00101101" | "00101110" | "00101111" | + "00111000" | "00111001" | "00111010" | "00111011" | + "00111100" | "00111101" | "00111110" | "00111111" => + mnemonic_o <= MN_LBI; + + -- Mnemonic XABR -------------------------------------------------------- + when "00010010" => + if not t41x_type_v then + mnemonic_o <= MN_XABR; + end if; + + -- Mnemonic SKC --------------------------------------------------------- + when "00100000" => + mnemonic_o <= MN_SKC; + + -- Mnemonic SKE --------------------------------------------------------- + when "00100001" => + mnemonic_o <= MN_SKE; + + -- Mnemonic SKMBZ ------------------------------------------------------- + when "00000001" | "00010001" | "00000011" | "00010011" => + mnemonic_o <= MN_SKMBZ; + + -- Mnemonic SKT --------------------------------------------------------- + when "01000001" => + if not t41x_type_v then + mnemonic_o <= MN_SKT; + end if; + + -- Mnemonic XAS --------------------------------------------------------- + when "01001111" => + mnemonic_o <= MN_XAS; + + -- Mnemonic EXT --------------------------------------------------------- + when "00110011" => + mnemonic_o <= MN_EXT; + multi_byte_o <= true; + + + when others => + null; + end case; + end process opc_decode; + -- + ----------------------------------------------------------------------------- + +end rtl; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t400_opc_table.vhd,v $ +-- Revision 1.1.1.1 2006/05/06 01:56:44 arniml +-- import from local CVS repository, LOC_CVS_0_1 +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/t400_opt_pack-p.vhd b/rtl/t400/rtl/vhdl/t400_opt_pack-p.vhd new file mode 100644 index 0000000..edb3319 --- /dev/null +++ b/rtl/t400/rtl/vhdl/t400_opt_pack-p.vhd @@ -0,0 +1,48 @@ +------------------------------------------------------------------------------- +-- +-- $Id: t400_opt_pack-p.vhd,v 1.1.1.1 2006/05/06 01:56:45 arniml Exp $ +-- +-- Copyright (c) 2006, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +package t400_opt_pack is + + -- Chip type option --------------------------------------------------------- + constant t400_opt_type_420_c : integer := 0; + constant t400_opt_type_421_c : integer := 1; + constant t400_opt_type_410_c : integer := 2; + + -- Clock divider option ----------------------------------------------------- + constant t400_opt_ck_div_32_c : integer := 3; + constant t400_opt_ck_div_16_c : integer := 2; + constant t400_opt_ck_div_8_c : integer := 1; + constant t400_opt_ck_div_4_c : integer := 0; + + -- CKO pin function option -------------------------------------------------- + constant t400_opt_cko_crystal_c : integer := 0; + constant t400_opt_cko_gpi_c : integer := 1; + + -- Output type option ------------------------------------------------------- + constant t400_opt_out_type_std_c : integer := 0; + constant t400_opt_out_type_od_c : integer := 1; + constant t400_opt_out_type_led_c : integer := 2; + constant t400_opt_out_type_pp_c : integer := 3; + + -- Microbus option ---------------------------------------------------------- + constant t400_opt_no_microbus_c : integer := 0; + constant t400_opt_microbus_c : integer := 1; + +end t400_opt_pack; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t400_opt_pack-p.vhd,v $ +-- Revision 1.1.1.1 2006/05/06 01:56:45 arniml +-- import from local CVS repository, LOC_CVS_0_1 +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/t400_pack-p.vhd b/rtl/t400/rtl/vhdl/t400_pack-p.vhd new file mode 100644 index 0000000..010ecce --- /dev/null +++ b/rtl/t400/rtl/vhdl/t400_pack-p.vhd @@ -0,0 +1,178 @@ +------------------------------------------------------------------------------- +-- +-- $Id: t400_pack-p.vhd,v 1.3 2006/05/27 19:16:52 arniml Exp $ +-- +-- Copyright (c) 2006, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +package t400_pack is + + -- Byte --------------------------------------------------------------------- + subtype byte_t is std_logic_vector(7 downto 0); + + -- Data word ---------------------------------------------------------------- + subtype dw_t is std_logic_vector(3 downto 0); + + -- Misc ranges -------------------------------------------------------------- + subtype dw_range_t is natural range dw_t'range; + subtype b_range_t is natural range 5 downto 0; + subtype br_range_t is natural range 5 downto 4; + subtype bd_range_t is natural range 3 downto 0; + + -- B address ---------------------------------------------------------------- + subtype b_t is std_logic_vector(b_range_t); + subtype br_t is std_logic_vector(br_range_t); + subtype bd_t is std_logic_vector(bd_range_t); + + + -- Program counter ---------------------------------------------------------- + subtype pc_t is unsigned(9 downto 0); + + -- Data memory address vector ----------------------------------------------- + subtype dm_addr_t is std_logic_vector(5 downto 0); + + -- Decoder data ------------------------------------------------------------- + subtype dec_data_t is std_logic_vector(pc_t'range); + + -- Program counter operations ----------------------------------------------- + type pc_op_t is (PC_NONE, + PC_INC_PC, + PC_LOAD_6, PC_LOAD_7, PC_LOAD_8, PC_LOAD, + PC_POP, + PC_LOAD_A_M, + PC_INT); + + -- Data memory controller operations ---------------------------------------- + type dmem_op_t is (DMEM_RB, + DMEM_WB_SRC_Q, DMEM_WB_SRC_DEC, DMEM_WB_SRC_A, + DMEM_RDEC, + DMEM_WB_SET_BIT, DMEM_WB_RES_BIT, + DMEM_WDEC_SRC_A); + type b_op_t is (B_NONE, + B_SET_BD, B_SET_BR, + B_SET_B, B_SET_B_INC, + B_XOR_BR, + B_INC_BD, + B_DEC_BD); + + -- Stack operations --------------------------------------------------------- + type stack_op_t is (STACK_NONE, + STACK_PUSH, + STACK_POP); + + -- ALU operations ----------------------------------------------------------- + type alu_op_t is (ALU_NONE, + ALU_CLRA, + ALU_LOAD_M, + ALU_LOAD_Q, ALU_LOAD_G, ALU_LOAD_IN, ALU_LOAD_IL, + ALU_LOAD_BR, ALU_LOAD_BD, + ALU_LOAD_SIO, + ALU_ADD, ALU_ADD_10, ALU_ADD_C, ALU_ADD_DEC, + ALU_COMP, + ALU_RC, ALU_SC, + ALU_XOR); + + -- Skip operations ---------------------------------------------------------- + type skip_op_t is (SKIP_NONE, + SKIP_UPDATE, + SKIP_NOW, + SKIP_CARRY, SKIP_C, + SKIP_BD_UFLOW, SKIP_BD_OFLOW, + SKIP_LBI, + SKIP_A_M, + SKIP_G_ZERO, SKIP_G_BIT, + SKIP_M_BIT, + SKIP_TIMER, + SKIP_PUSH, SKIP_POP); + + -- IO L port operations ----------------------------------------------------- + type io_l_op_t is (IOL_NONE, + IOL_LOAD_AM, IOL_LOAD_PM, + IOL_OUTPUT_L, + IOL_OUTPUT_Q); + + -- IO D port operations ----------------------------------------------------- + type io_d_op_t is (IOD_NONE, + IOD_LOAD); + + -- IO G port operations ----------------------------------------------------- + type io_g_op_t is (IOG_NONE, + IOG_LOAD_M, + IOG_LOAD_DEC); + + -- IO IN port operations ---------------------------------------------------- + type io_in_op_t is (IOIN_NONE, + IOIN_INIL, + IOIN_INTACK); + + -- SIO operations ----------------------------------------------------------- + type sio_op_t is (SIO_NONE, + SIO_LOAD); + + -- Mnemonics ---------------------------------------------------------------- + type mnemonic_t is (-- Arithmetic instructions + MN_ASC, + MN_ADD, + MN_ADT, + MN_AISC, + MN_CASC, + MN_CLRA, + MN_COMP, + MN_NOP, + MN_C, + MN_XOR, + -- Transfer of control instructions + MN_JID, + MN_JMP, + MN_JP_JSRP, + MN_JSR, + MN_RET, + MN_RETSK, + -- Memory reference instructions + MN_LD, + MN_LDD_XAD, + MN_LQID, + MN_RMB, + MN_SMB, + MN_STII, + MN_X, + MN_XDS, + MN_XIS, + -- Register reference instructions + MN_CAB, + MN_CBA, + MN_LBI, + MN_XABR, + -- Test instructions + MN_SKC, + MN_SKE, + MN_SKMBZ, + MN_SKT, + -- Input/output instructions + MN_EXT, + MN_XAS); + +end t400_pack; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t400_pack-p.vhd,v $ +-- Revision 1.3 2006/05/27 19:16:52 arniml +-- interrupt functionality added +-- +-- Revision 1.2 2006/05/22 00:01:21 arniml +-- operations for IN port added +-- +-- Revision 1.1.1.1 2006/05/06 01:56:45 arniml +-- import from local CVS repository, LOC_CVS_0_1 +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/t400_pmem_ctrl-c.vhd b/rtl/t400/rtl/vhdl/t400_pmem_ctrl-c.vhd new file mode 100644 index 0000000..dd6f1df --- /dev/null +++ b/rtl/t400/rtl/vhdl/t400_pmem_ctrl-c.vhd @@ -0,0 +1,28 @@ +------------------------------------------------------------------------------- +-- +-- The Program memory controller. +-- +-- $Id: t400_pmem_ctrl-c.vhd,v 1.1.1.1 2006/05/06 01:56:45 arniml Exp $ +-- +-- Copyright (c) 2006, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +configuration t400_pmem_ctrl_rtl_c0 of t400_pmem_ctrl is + + for rtl + end for; + +end t400_pmem_ctrl_rtl_c0; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t400_pmem_ctrl-c.vhd,v $ +-- Revision 1.1.1.1 2006/05/06 01:56:45 arniml +-- import from local CVS repository, LOC_CVS_0_1 +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/t400_pmem_ctrl.vhd b/rtl/t400/rtl/vhdl/t400_pmem_ctrl.vhd new file mode 100644 index 0000000..1e61b26 --- /dev/null +++ b/rtl/t400/rtl/vhdl/t400_pmem_ctrl.vhd @@ -0,0 +1,199 @@ +------------------------------------------------------------------------------ +-- +-- The Program memory controller. +-- +-- $Id: t400_pmem_ctrl.vhd,v 1.3 2006/05/28 15:32:40 arniml Exp $ +-- +-- Copyright (c) 2006 Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t400/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.t400_opt_pack.all; +use work.t400_pack.all; + +entity t400_pmem_ctrl is + + generic ( + opt_type_g : integer := t400_opt_type_420_c + ); + port ( + -- System Interface ------------------------------------------------------- + ck_i : in std_logic; + ck_en_i : in boolean; + por_i : in boolean; + res_i : in boolean; + a_i : in dw_t; + m_i : in dw_t; + -- Control Interface ------------------------------------------------------ + op_i : in pc_op_t; + dec_data_i : in dec_data_t; + -- Stack Interface -------------------------------------------------------- + pc_o : out pc_t; + pc_i : in pc_t; + -- Program Memory Interface ----------------------------------------------- + pm_addr_o : out pc_t + ); + +end t400_pmem_ctrl; + + +library ieee; +use ieee.numeric_std.all; + +-- pragma translate_off +use work.tb_pack.tb_pc_s; +-- pragma translate_on + +architecture rtl of t400_pmem_ctrl is + + signal pc_q : pc_t; + signal last_pc_s : pc_t; + +begin + + ----------------------------------------------------------------------------- + -- Determine last program counter address + ----------------------------------------------------------------------------- + last_pc_s <= to_unsigned(16#1ff#, pc_t'length) + when opt_type_g = t400_opt_type_410_c else + to_unsigned(16#3ff#, pc_t'length); + + + ----------------------------------------------------------------------------- + -- Process pc + -- + -- Purpose: + -- Implements the program counter. + -- + pc: process (ck_i, por_i) + begin + if por_i then + pc_q <= (others => '0'); + + elsif ck_i'event and ck_i = '1' then + if res_i then + -- synchronous reset upon external reset event + pc_q <= (others => '0'); + + elsif ck_en_i then + -- determine PC update mode + case op_i is + -- increment program counter ---------------------------------------- + when PC_INC_PC => + if pc_q = last_pc_s then + -- roll over + pc_q <= (others => '0'); + else + pc_q <= pc_q + 1; + end if; + + -- Load lower 6 bits from program memory data ----------------------- + when PC_LOAD_6 => + pc_q(5 downto 0) <= unsigned(dec_data_i(5 downto 0)); + + -- Load lower 7 bits from program memory data ----------------------- + when PC_LOAD_7 => + pc_q(6 downto 0) <= unsigned(dec_data_i(6 downto 0)); + + -- Load lower 8 bits from program memory data ----------------------- + when PC_LOAD_8 => + pc_q(7 downto 0) <= unsigned(dec_data_i(7 downto 0)); + + -- Load all bits from program memory data --------------------------- + when PC_LOAD => + pc_q <= unsigned(dec_data_i); + + -- pop program counter from stack ----------------------------------- + when PC_POP => + pc_q <= pc_i; + + -- update program counter for LQID instruction ---------------------- + when PC_LOAD_A_M => + pc_q(7 downto 4) <= unsigned(a_i); + pc_q(3 downto 0) <= unsigned(m_i); + + -- load interrupt vector -------------------------------------------- + when PC_INT => + if opt_type_g = t400_opt_type_420_c then + -- load address 0x100, i.e. skip first instruction at + -- vector address 0x0ff which has to be a NOP :-) + pc_q <= (8 => '1', others => '0'); + end if; + + when others => + null; + end case; + end if; + end if; + end process pc; + -- + ----------------------------------------------------------------------------- + + + -- pragma translate_off + -- instrument interrupt testbench + tb_pc_s <= pc_q; + -- pragma translate_on + + + ----------------------------------------------------------------------------- + -- Output mapping + ----------------------------------------------------------------------------- + pc_o <= pc_q; + pm_addr_o <= pc_q; + +end rtl; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t400_pmem_ctrl.vhd,v $ +-- Revision 1.3 2006/05/28 15:32:40 arniml +-- load 0x100 upon interrupt +-- +-- Revision 1.2 2006/05/27 19:16:52 arniml +-- interrupt functionality added +-- +-- Revision 1.1.1.1 2006/05/06 01:56:45 arniml +-- import from local CVS repository, LOC_CVS_0_1 +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/t400_reset-c.vhd b/rtl/t400/rtl/vhdl/t400_reset-c.vhd new file mode 100644 index 0000000..233edd6 --- /dev/null +++ b/rtl/t400/rtl/vhdl/t400_reset-c.vhd @@ -0,0 +1,28 @@ +------------------------------------------------------------------------------- +-- +-- The reset generation unit. +-- +-- $Id: t400_reset-c.vhd,v 1.1.1.1 2006/05/06 01:56:45 arniml Exp $ +-- +-- Copyright (c) 2006, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +configuration t400_reset_rtl_c0 of t400_reset is + + for rtl + end for; + +end t400_reset_rtl_c0; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t400_reset-c.vhd,v $ +-- Revision 1.1.1.1 2006/05/06 01:56:45 arniml +-- import from local CVS repository, LOC_CVS_0_1 +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/t400_reset.vhd b/rtl/t400/rtl/vhdl/t400_reset.vhd new file mode 100644 index 0000000..0dbd725 --- /dev/null +++ b/rtl/t400/rtl/vhdl/t400_reset.vhd @@ -0,0 +1,148 @@ +------------------------------------------------------------------------------- +-- +-- The reset generation unit. +-- +-- $Id: t400_reset.vhd,v 1.1.1.1 2006/05/06 01:56:45 arniml Exp $ +-- +-- Copyright (c) 2006 Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t400/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity t400_reset is + + port ( + -- System Interface ------------------------------------------------------- + ck_i : in std_logic; + icyc_en_i : in boolean; + por_i : in boolean; + -- Reset Interface -------------------------------------------------------- + reset_n_i : in std_logic; + res_o : out boolean + ); + +end t400_reset; + + +library ieee; +use ieee.numeric_std.all; + +architecture rtl of t400_reset is + + type res_state_t is (IDLE, + RES1, RES2, + RES_ACTIVE); + signal res_state_q : res_state_t; + signal res_q : boolean; + +begin + + ----------------------------------------------------------------------------- + -- Process res_fsm + -- + -- Purpose: + -- Implements the reset timing/controlling FSM. + -- User's Guide chapter 2.3 requires that reset_n_i has to be low for + -- at least 3 instruction cycle times until it initializes the CPU. + -- + res_fsm: process (ck_i, por_i) + begin + if por_i then + res_state_q <= IDLE; + res_q <= false; + + elsif ck_i'event and ck_i = '1' then + res_q <= false; + if icyc_en_i then + case res_state_q is + when IDLE => + if reset_n_i = '0' then + res_state_q <= RES1; + end if; + + when RES1 => + if reset_n_i = '0' then + res_state_q <= RES2; + else + res_state_q <= IDLE; + end if; + + when RES2 => + if reset_n_i = '0' then + res_state_q <= RES_ACTIVE; + else + res_state_q <= IDLE; + end if; + + when RES_ACTIVE => + res_q <= true; + if reset_n_i = '1' then + res_state_q <= IDLE; + end if; + + when others => + res_state_q <= IDLE; + + end case; + + end if; + + end if; + end process res_fsm; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Output mapping + ----------------------------------------------------------------------------- + res_o <= res_q; + +end rtl; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t400_reset.vhd,v $ +-- Revision 1.1.1.1 2006/05/06 01:56:45 arniml +-- import from local CVS repository, LOC_CVS_0_1 +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/t400_sio-c.vhd b/rtl/t400/rtl/vhdl/t400_sio-c.vhd new file mode 100644 index 0000000..b1692f5 --- /dev/null +++ b/rtl/t400/rtl/vhdl/t400_sio-c.vhd @@ -0,0 +1,28 @@ +------------------------------------------------------------------------------- +-- +-- The serial input/output unit. +-- +-- $Id: t400_sio-c.vhd,v 1.1.1.1 2006/05/06 01:56:45 arniml Exp $ +-- +-- Copyright (c) 2006, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +configuration t400_sio_rtl_c0 of t400_sio is + + for rtl + end for; + +end t400_sio_rtl_c0; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t400_sio-c.vhd,v $ +-- Revision 1.1.1.1 2006/05/06 01:56:45 arniml +-- import from local CVS repository, LOC_CVS_0_1 +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/t400_sio.vhd b/rtl/t400/rtl/vhdl/t400_sio.vhd new file mode 100644 index 0000000..e51ecc5 --- /dev/null +++ b/rtl/t400/rtl/vhdl/t400_sio.vhd @@ -0,0 +1,305 @@ +------------------------------------------------------------------------------- +-- +-- The serial input/output unit. +-- +-- $Id: t400_sio.vhd,v 1.3 2006/05/07 02:24:16 arniml Exp $ +-- +-- Copyright (c) 2006 Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t400/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.t400_pack.all; +use work.t400_opt_pack.all; + +entity t400_sio is + + generic ( + opt_so_output_type_g : integer := t400_opt_out_type_std_c; + opt_sk_output_type_g : integer := t400_opt_out_type_std_c + ); + port ( + -- System Interface ------------------------------------------------------- + ck_i : in std_logic; + ck_en_i : in boolean; + por_i : in boolean; + res_i : in boolean; + phi1_i : in std_logic; + out_en_i : in boolean; + in_en_i : in boolean; + -- Control Interface ------------------------------------------------------ + op_i : in sio_op_t; + en0_i : in std_logic; + en3_i : in std_logic; + -- SIO Interface ---------------------------------------------------------- + a_i : in dw_t; + c_i : in std_logic; + sio_o : out dw_t; + -- Pad Interface ---------------------------------------------------------- + si_i : in std_logic; + so_o : out std_logic; + so_en_o : out std_logic; + sk_o : out std_logic; + sk_en_o : out std_logic + ); + +end t400_sio; + + +library ieee; +use ieee.numeric_std.all; + +use work.t400_io_pack.all; + +architecture rtl of t400_sio is + + signal si_q : std_logic; + type si_flt_t is (SI_LOW_0, SI_LOW_1, + SI_HIGH_0, SI_HIGH_1); + signal si_flt_s, + si_flt_q : si_flt_t; + signal si_0_ok_s, + si_1_ok_s : boolean; + signal si_0_ok_q, + si_1_ok_q : boolean; + signal dec_sio_s : boolean; + + signal new_sio_s, + sio_q : unsigned(dw_range_t); + signal skl_q : std_logic; + signal phi1_en_q : std_logic; + + signal so_s, + sk_s : std_logic; + + signal vdd_s : std_logic; + +begin + + vdd_s <= '1'; + + ----------------------------------------------------------------------------- + -- Process seq + -- + -- Purpose: + -- Implements the sequential elements. + -- + seq: process (ck_i, por_i) + begin + if por_i then + sio_q <= (others => '0'); + skl_q <= '1'; + phi1_en_q <= '1'; + si_q <= '1'; + si_flt_q <= SI_LOW_0; + si_0_ok_q <= false; + si_1_ok_q <= false; + + elsif ck_i'event and ck_i = '1' then + if res_i then + -- synchronous reset upon external reset event + skl_q <= '1'; + phi1_en_q <= '1'; + else + if in_en_i then + -- sample asynchronous SI input + si_q <= si_i; + end if; + + if out_en_i then + -- SI filter FSM + si_flt_q <= si_flt_s; + -- SI low/high markers + si_0_ok_q <= si_0_ok_s; + si_1_ok_q <= si_1_ok_s; + end if; + + -- SIO shift register / counter + if op_i = SIO_LOAD and ck_en_i then + -- parallel update has priority + sio_q <= unsigned(a_i); + skl_q <= c_i; + + else + sio_q <= new_sio_s; + end if; + + if ck_en_i then + -- delay enable of PHI1 by one clock cycle + -- this prevents glitches on sk_o when enabling/disabling + -- sk_o as a clock output + phi1_en_q <= skl_q; + end if; + + end if; + end if; + end process seq; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process new_sio + -- + -- Purpose: + -- Calculates the new value of SIO. + -- Splitting this from the sequential process is required to deliver + -- the transient new value of SIO to sio_o upon reading SIO. + -- + new_sio: process (out_en_i, + en0_i, + sio_q, + si_q, + dec_sio_s) + begin + -- default value + new_sio_s <= sio_q; + + if out_en_i then + if en0_i = '0' then + -- shift register mode + new_sio_s(3 downto 1) <= sio_q(2 downto 0); + new_sio_s(0) <= si_q; + + else + -- counter mode + if dec_sio_s then + new_sio_s <= sio_q - 1; + end if; + + end if; + end if; + end process new_sio; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process si_sample + -- + -- Purpose: + -- Implements the low pass filter on SI for low and high levels. + -- + si_sample: process (si_q, + si_flt_q, + si_0_ok_q, si_1_ok_q) + begin + -- default assignments + si_flt_s <= si_flt_q; + si_0_ok_s <= si_0_ok_q; + si_1_ok_s <= si_1_ok_q; + dec_sio_s <= false; + + case si_flt_q is + when SI_LOW_0 => + if si_q = '0' then + si_flt_s <= SI_LOW_1; + else + si_flt_s <= SI_HIGH_0; + end if; + + when SI_LOW_1 => + if si_q = '0' then + si_0_ok_s <= true; -- enough '0' on SI + + if not si_0_ok_q and si_1_ok_q then + -- decrement counter if durations of high and low phases + -- were long enough + dec_sio_s <= true; + end if; + else + si_flt_s <= SI_HIGH_0; + si_1_ok_s <= false; -- restart measuring + end if; + + when SI_HIGH_0 => + si_1_ok_s <= false; -- restart marker + if si_q = '1' then + si_flt_s <= SI_HIGH_1; + else + si_flt_s <= SI_LOW_0; + end if; + + when SI_HIGH_1 => + if si_q = '1' then + si_1_ok_s <= true; -- enough '1' on SI + else + si_flt_s <= SI_LOW_0; + si_0_ok_s <= false; -- restart measuring + end if; + + when others => + null; + end case; + end process si_sample; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Output mapping + ----------------------------------------------------------------------------- + sio_o <= std_logic_vector(new_sio_s); + so_s <= en3_i and (en0_i or sio_q(3)); + sk_s <= phi1_en_q and (en0_i or phi1_i); + so_o <= io_out_f(dat => so_s, opt => opt_so_output_type_g); + so_en_o <= io_en_f (en => vdd_s, + dat => so_s, opt => opt_so_output_type_g); + sk_o <= io_out_f(dat => sk_s, opt => opt_sk_output_type_g); + sk_en_o <= io_en_f (en => vdd_s, + dat => sk_s, opt => opt_sk_output_type_g); + +end rtl; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t400_sio.vhd,v $ +-- Revision 1.3 2006/05/07 02:24:16 arniml +-- fix sensitivity list +-- +-- Revision 1.2 2006/05/06 13:34:58 arniml +-- phi1_en_q is dedicated enable for PHI1 clock to suppress glitches on sk_o +-- +-- Revision 1.1.1.1 2006/05/06 01:56:45 arniml +-- import from local CVS repository, LOC_CVS_0_1 +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/t400_skip-c.vhd b/rtl/t400/rtl/vhdl/t400_skip-c.vhd new file mode 100644 index 0000000..b4d901f --- /dev/null +++ b/rtl/t400/rtl/vhdl/t400_skip-c.vhd @@ -0,0 +1,29 @@ +------------------------------------------------------------------------------- +-- +-- The skip unit. +-- Skip conditions are checked here and communicated to the decoder unit. +-- +-- $Id: t400_skip-c.vhd,v 1.1.1.1 2006/05/06 01:56:45 arniml Exp $ +-- +-- Copyright (c) 2006, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +configuration t400_skip_rtl_c0 of t400_skip is + + for rtl + end for; + +end t400_skip_rtl_c0; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t400_skip-c.vhd,v $ +-- Revision 1.1.1.1 2006/05/06 01:56:45 arniml +-- import from local CVS repository, LOC_CVS_0_1 +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/t400_skip.vhd b/rtl/t400/rtl/vhdl/t400_skip.vhd new file mode 100644 index 0000000..0313e01 --- /dev/null +++ b/rtl/t400/rtl/vhdl/t400_skip.vhd @@ -0,0 +1,239 @@ +------------------------------------------------------------------------------- +-- +-- The skip unit. +-- Skip conditions are checked here and communicated to the decoder unit. +-- +-- $Id: t400_skip.vhd,v 1.5 2006/06/05 14:20:34 arniml Exp $ +-- +-- Copyright (c) 2006 Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t400/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.t400_opt_pack.all; +use work.t400_pack.all; + +entity t400_skip is + + generic ( + opt_type_g : integer := t400_opt_type_420_c + ); + port ( + -- System Interface ------------------------------------------------------- + ck_i : in std_logic; + ck_en_i : in boolean; + por_i : in boolean; + res_i : in boolean; + -- Control Interface ------------------------------------------------------ + op_i : in skip_op_t; + dec_data_i : in dec_data_t; + carry_i : in std_logic; + c_i : in std_logic; + bd_i : in dw_t; + is_lbi_i : in boolean; + skip_o : out boolean; + skip_lbi_o : out boolean; + -- Data Interface --------------------------------------------------------- + a_i : in dw_t; + m_i : in dw_t; + g_i : in dw_t; + tim_c_i : in boolean + ); + +end t400_skip; + + +library ieee; +use ieee.numeric_std.all; + +architecture rtl of t400_skip is + + signal skip_q, + skip_next_q : boolean; + signal skip_lbi_q : boolean; + + signal skip_int_q : boolean; + +begin + + ----------------------------------------------------------------------------- + -- Process skip + -- + -- Purpose: + -- Implements the skip logic. + -- + skip: process (ck_i, por_i) + variable t420_type_v : boolean; + begin + if por_i then + skip_next_q <= false; + skip_q <= false; + skip_lbi_q <= false; + skip_int_q <= false; + + elsif ck_i'event and ck_i = '1' then + if res_i then + -- synchronous reset upon external reset event + skip_next_q <= false; + skip_q <= false; + skip_lbi_q <= false; + skip_int_q <= false; + + elsif ck_en_i then + t420_type_v := opt_type_g = t400_opt_type_420_c; + + if ck_en_i then + case op_i is + -- update skip information ---------------------------------------- + when SKIP_UPDATE => + skip_q <= skip_next_q; + -- also reset skip_next flag + skip_next_q <= false; + + -- reset skip-on-lbi flag when this was not an LBI + if not is_lbi_i then + skip_lbi_q <= false; + end if; + + -- skip always ---------------------------------------------------- + when SKIP_NOW => + skip_next_q <= true; + + -- skip on carry -------------------------------------------------- + when SKIP_CARRY => + skip_next_q <= carry_i = '1'; + + -- skip on C ------------------------------------------------------ + when SKIP_C => + skip_next_q <= c_i = '1'; + + -- skip on BD underflow ------------------------------------------ + when SKIP_BD_UFLOW => + skip_next_q <= unsigned(bd_i) = 15; + + -- skip on BD overflow ------------------------------------------- + when SKIP_BD_OFLOW => + skip_next_q <= unsigned(bd_i) = 0; + + -- skip on LBI instruction ---------------------------------------- + when SKIP_LBI => + skip_lbi_q <= true; + + -- skip on A and M equal ------------------------------------------ + when SKIP_A_M => + skip_next_q <= unsigned(a_i) = unsigned(m_i); + + -- skip on G zero ------------------------------------------------- + when SKIP_G_ZERO => + skip_next_q <= unsigned(g_i) = 0; + + -- skip on G bit -------------------------------------------------- + when SKIP_G_BIT => + skip_next_q <= unsigned(g_i and dec_data_i(dw_range_t)) = 0; + + -- skip on M bit -------------------------------------------------- + when SKIP_M_BIT => + skip_next_q <= unsigned(m_i and dec_data_i(dw_range_t)) = 0; + + -- skip on timer carry -------------------------------------------- + when SKIP_TIMER => + skip_next_q <= tim_c_i; + null; + + -- push skip state when vectoring to interrupt routine ------------ + when SKIP_PUSH => + if t420_type_v then + -- save next skip flag + skip_int_q <= skip_next_q; + skip_next_q <= false; + -- never skip first instruction of interrupt routine + skip_q <= false; + end if; + + -- pop skip state for RET from interrupt routine ------------------ + when SKIP_POP => + if t420_type_v then + -- push'ed info must be pop'ed to skip_next_q as pop'ing + -- happens during RET of interrupt routine + -- skip info is valid for next instruction + skip_next_q <= skip_int_q; + skip_int_q <= false; + end if; + + when others => + null; + end case; + end if; + end if; + end if; + end process skip; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Output mapping + ----------------------------------------------------------------------------- + skip_o <= skip_q; + skip_lbi_o <= skip_lbi_q; + +end rtl; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t400_skip.vhd,v $ +-- Revision 1.5 2006/06/05 14:20:34 arniml +-- interface comments added +-- +-- Revision 1.4 2006/05/28 15:35:33 arniml +-- fix pop'ing of skip flag +-- +-- Revision 1.3 2006/05/27 19:16:52 arniml +-- interrupt functionality added +-- +-- Revision 1.2 2006/05/20 02:47:52 arniml +-- skip-on-timer implemented +-- +-- Revision 1.1.1.1 2006/05/06 01:56:45 arniml +-- import from local CVS repository, LOC_CVS_0_1 +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/t400_stack-c.vhd b/rtl/t400/rtl/vhdl/t400_stack-c.vhd new file mode 100644 index 0000000..49cdeed --- /dev/null +++ b/rtl/t400/rtl/vhdl/t400_stack-c.vhd @@ -0,0 +1,28 @@ +------------------------------------------------------------------------------- +-- +-- The stack unit. +-- +-- $Id: t400_stack-c.vhd,v 1.1.1.1 2006/05/06 01:56:45 arniml Exp $ +-- +-- Copyright (c) 2006, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +configuration t400_stack_rtl_c0 of t400_stack is + + for rtl + end for; + +end t400_stack_rtl_c0; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t400_stack-c.vhd,v $ +-- Revision 1.1.1.1 2006/05/06 01:56:45 arniml +-- import from local CVS repository, LOC_CVS_0_1 +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/t400_stack.vhd b/rtl/t400/rtl/vhdl/t400_stack.vhd new file mode 100644 index 0000000..b81875a --- /dev/null +++ b/rtl/t400/rtl/vhdl/t400_stack.vhd @@ -0,0 +1,159 @@ +------------------------------------------------------------------------------- +-- +-- The stack unit. +-- +-- $Id: t400_stack.vhd,v 1.3 2006/06/11 02:12:11 arniml Exp $ +-- +-- Copyright (c) 2006 Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t400/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.t400_opt_pack.all; +use work.t400_pack.all; + +entity t400_stack is + + generic ( + opt_type_g : integer := t400_opt_type_420_c + ); + port ( + -- System Interface ------------------------------------------------------- + ck_i : in std_logic; + ck_en_i : in boolean; + por_i : in boolean; + -- Stack Control Interface ------------------------------------------------ + op_i : in stack_op_t; + -- Program Counter Interface ---------------------------------------------- + pc_i : in pc_t; + pc_o : out pc_t + ); + +end t400_stack; + + +-- pragma translate_off +use work.tb_pack.tb_sa_s; +-- pragma translate_on + +architecture rtl of t400_stack is + + signal sa_q, + sb_q, + sc_q : pc_t; + +begin + + ----------------------------------------------------------------------------- + -- Process stack + -- + -- Purpose: + -- Implements the stack consisting of SA, SB, SC. + -- SC is skipped when it's a 41xL. + -- + stack: process (ck_i, por_i) + variable t41x_type_v : boolean; + begin + if por_i then + sa_q <= (others => '0'); + sb_q <= (others => '0'); + sc_q <= (others => '0'); + + elsif ck_i'event and ck_i = '1' then + -- determine type + t41x_type_v := opt_type_g = t400_opt_type_410_c; + + if ck_en_i then + case op_i is + when STACK_PUSH => + sa_q <= pc_i; + sb_q <= sa_q; + if not t41x_type_v then + sc_q <= sb_q; + else + sc_q <= (others => '0'); + end if; + + when STACK_POP => + sa_q <= sb_q; + if not t41x_type_v then + sb_q <= sc_q; + end if; + + when others => + null; + + end case; + end if; + end if; + end process stack; + -- + ----------------------------------------------------------------------------- + + + -- pragma translate_off + -- instrument interrupt testbench + tb_sa_s <= sa_q; + -- pragma translate_on + + + ----------------------------------------------------------------------------- + -- Output mapping + ----------------------------------------------------------------------------- + pc_o <= sa_q; + +end rtl; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t400_stack.vhd,v $ +-- Revision 1.3 2006/06/11 02:12:11 arniml +-- assign sc_q with 0 for t41x derivatives +-- this prevents a dummy warning about inferring latches for sc_q +-- +-- Revision 1.2 2006/05/27 19:15:59 arniml +-- instrument testbench +-- +-- Revision 1.1.1.1 2006/05/06 01:56:45 arniml +-- import from local CVS repository, LOC_CVS_0_1 +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/t400_timer-c.vhd b/rtl/t400/rtl/vhdl/t400_timer-c.vhd new file mode 100644 index 0000000..3194662 --- /dev/null +++ b/rtl/t400/rtl/vhdl/t400_timer-c.vhd @@ -0,0 +1,31 @@ +------------------------------------------------------------------------------- +-- +-- The timer unit. +-- +-- $Id: t400_timer-c.vhd,v 1.1.1.1 2006/06/10 17:50:15 arnim Exp $ +-- +-- Copyright (c) 2006, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +configuration t400_timer_rtl_c0 of t400_timer is + + for rtl + end for; + +end t400_timer_rtl_c0; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t400_timer-c.vhd,v $ +-- Revision 1.1.1.1 2006/06/10 17:50:15 arnim +-- copied from opencores.org repository, pre-1.0 release on 10-Jun-2006 +-- +-- Revision 1.1 2006/05/20 02:47:12 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t400/rtl/vhdl/t400_timer.vhd b/rtl/t400/rtl/vhdl/t400_timer.vhd new file mode 100644 index 0000000..cb690f5 --- /dev/null +++ b/rtl/t400/rtl/vhdl/t400_timer.vhd @@ -0,0 +1,128 @@ +------------------------------------------------------------------------------- +-- +-- The timer unit. +-- +-- $Id: t400_timer.vhd,v 1.1.1.1 2006/06/10 17:50:15 arnim Exp $ +-- +-- Copyright (c) 2006 Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t400/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.t400_pack.all; + +entity t400_timer is + + port ( + -- System Interface ------------------------------------------------------- + ck_i : in std_logic; + ck_en_i : in boolean; + por_i : in boolean; + icyc_en_i : in boolean; + -- Skip Interface --------------------------------------------------------- + op_i : in skip_op_t; + c_o : out boolean + ); + +end t400_timer; + + +library ieee; +use ieee.numeric_std.all; + +architecture rtl of t400_timer is + + signal cnt_q : unsigned(9 downto 0); + signal c_q : boolean; + +begin + + ----------------------------------------------------------------------------- + -- Process seq + -- + -- Purpose: + -- Implements the sequential elements: + -- * timer counter + -- * carry (underflow) marker flag + -- + seq: process (ck_i, por_i) + begin + if por_i then + cnt_q <= (others => '1'); + c_q <= false; + + elsif ck_i'event and ck_i = '1' then + if icyc_en_i then + if cnt_q = 0 then + -- counter underflow: + -- * reload counter + -- * set marker flag + cnt_q <= (others => '1'); + c_q <= true; + else + cnt_q <= cnt_q - 1; + end if; + end if; + + if ck_en_i and op_i = SKIP_TIMER then + c_q <= false; + end if; + end if; + end process seq; + -- + ----------------------------------------------------------------------------- + + + c_o <= c_q; + +end rtl; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t400_timer.vhd,v $ +-- Revision 1.1.1.1 2006/06/10 17:50:15 arnim +-- copied from opencores.org repository, pre-1.0 release on 10-Jun-2006 +-- +-- Revision 1.1 2006/05/20 02:47:12 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t48/COPYING b/rtl/t48/COPYING new file mode 100644 index 0000000..60549be --- /dev/null +++ b/rtl/t48/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/rtl/t48/README b/rtl/t48/README new file mode 100644 index 0000000..532e363 --- /dev/null +++ b/rtl/t48/README @@ -0,0 +1,232 @@ + +README for the T48 uController project +====================================== +Version: $Date: 2005/06/19 15:59:48 $ + + +Introduction +------------ + +The T48 µController core is an implementation of the MCS-48 microcontroller +family architecture. While being a controller core for SoC, it also aims for +code-compatability and cycle-accuracy so that it can be used as a drop-in +replacement for any MCS-48 controller. +It can be configured to better suit the requirements and characteristics of +the integrating system. On the other hand, nearly the full functionality of a +stock 8048/8049 is available. + + +Download +-------- + +Download the latest stable release from the project homepage at OpenCores.org: + + http://www.opencores.org/projects.cgi/web/t48/overview/ + +You can get the latest version of the design files from CVS: + + http://www.opencores.org/pdownloads.cgi/list/t48 + +Please keep in mind that this is work in progress and might contain smaller or +bigger problems. +You should also check the Tracker for known bugs and see if they affect your +work. + + +Installation +------------ + +Once the directory structure is generated either by check-out from CVS or by +unpacking the tar-archive, the central project initialization file should be +set up. A template called init_project.template.sh is located in the sw +directory where a copy can be edited. Normally, only the definition for the +variable PROJECT_DIR has to be adjusted to the path where the directory +structure is located. +The commands for setting the necessary variables assume a bash/sh-like +shell. In case you run a different shell like csh or ksh, you should adjust +these commands as well. + +The meaning of the variables is as follows: + + * PROJECT_DIR + Points to the root of the project installation. All further references are + derived from its setting. + + * VERIF_DIR + Location of the verification suite. + + * SIM_DIR + Directory for running simulations. + +These variables must be properly set whenever scripts or makefiles of the T48 +project are executed. Otherwise, you will most likely encounter error +messages. + +NOTE: The concepts of the mentioned shells require that the init_project.sh is + run in the context of the shell. I.e. you should 'source' the script + instead of executing it like a command. This will make sure that the + variable settings are really effective in the calling shell instance. + + +Directory Structure +------------------- + +The project's directory structure follows the proposal of OpenCores.org. + +t48 + | + \--+-- rtl + | | + | \-- vhdl : VHDL code containing the RTL description + | | of the core. + | \-- system : RTL VHDL code of sample systems. + | + +-- bench + | | + | \-- vhdl : VHDL testbench code. + | + +-- sim + | | + | \-- rtl_sim : Directory for running simulations. + | + \-- sw : General purpose scripts and files. + | + +-- i8039emu : An MCS-48 emulator written in C. + | + \-- verif : The verification suite. + | + +-- include : Global includes and makefiles. + | + +-- black_box : Black-box verification tests. + | + +-- white_box : White-box verification tests. + | + \-- gp_sw : General purpose software. + + +Compiling the VHDL Code +----------------------- + +VHDL compilation and simulation tasks take place inside in sim/rtl_sim +directory. The project setup supports only the batch mode of certain +simulators. However, there should be no problems to integrate the testbench +and RTL code into arbitrary simulation environments. + +The main file for compilation is Makefile.hier which contains all information +regarding the dependencies of the source files and their compilation +order. There is a dedicated file for each supported simulator that maps the +generic information of Makefile.hier to object files specific to the given +simulator. + +Compilation is based on the make-utility, thus invocation looks like this: + +$ make -f Makefile. + +where denotes one of the supported simulators: + + * Makefile.ghdl + Tristan Gingold's GHDL simulator/compiler, a VHDL front-end for gcc. + http://ghdl.free.fr/ + + * Makefile.simili + VHDL Simili, a VHDL simulator by Symphony EDA + http://www.symphonyeda.com/ + +Make will analyze all VHDL files (RTL and testbench code) and elaborate all +three testbench top-levels if appropriate for the chosen simulator: + + * tb_behav_c0 + The main testbench for regression testing. + Instantiates the plain t48_core and provides internal RAM (256 bytes) and + ROM (2k bytes) plus 2k bytes of external ROM. + + * tb_t8048_behav_c0 + The testbench for the t8048 sample system. + + * tb_t8039_behav_c0 + The testbench for the 8039 sample system. + +Each Makefile has a 'clean' target to delete all intermediate data: + +$ make -f Makefile. clean + +The basic simple sequence list can be found in COMPILE_LIST. This can be +useful to quickly set up the analyze stage of any compiler or +synthesizer. Especially when synthesizing the code, you want to skip the VHDL +configurations in *-c.vhd and everything below the bench/ directory. + +Preparation of the ROM Files +---------------------------- + +All testbenches listed above need two files in hex-format. They contain the +program for the T48 core and are loaded into internal and external ROM at +simulation startup. Their existance is mandatory as they are referenced in the +VHDL code of the ROM model lpm_rom.vhd. In case they are missing, the +simulation will stop immediately after elaborating the design. + +These files are: + + * t48_rom.hex + Internal ROM contents at address range 000H to 7FFH. + Intel hex format, starting at address 000H. + + * t48_ext_rom.hex + External ROM contents at address range 800H to FFFH. + Intel hex format, starting at address 000H. + +The verification flow for the T48 project generates these two files +automatically from the assembler source files. + +All regression tests and the general purpose software is organized in a cell +structure. Currently, this means that the software for a cell is contained in +a dedicated directory where the assembler run takes place. In the future, +there will be more aspects to a cell. + +Assembling, linking and putting the hex-files in place is under the control of +the make-mechanism. E.g. to assemble the source code of a cell, issue the +following command: + +$ make -f $VERIF_DIR/include/Makefile.cell + +This generates the linker file (test.p) and distributes its contents to the +required ROM files for internal and external program ROM. The target 'simu' +copies these files automatically to the simulation directory. So most likely, +for running a test case or any other software, you will want to issue: + +$ make -f VERIF_DIR/include/Makefile.cell simu clean + +The only supported assembler is Alfred Arnold's macroassembler AS. See + + http://john.ccac.rwth-aachen.de:8000/as/ + + +Verification Environment +------------------------ + +The verification environment consists of a number of test programs. They are +all self-checking. I.e. after testing the targeted functionality, they emit a +pass/fail information. This information is detected by the testbench which +stops the simulation and prints out the simulation result. This is the default +mechanism for stopping the VHDL simulation. + +Pass/fail is signalled by a certain sequence of the accumulator contents: + + 1) Accumulator contains AAH + 2) Accumulator contains 55H + 3) Accumulator contains 01H -> Pass + Accumulator contains 00H -> Fail + +The detection is modelled like a state machine and in case the sequence is of +bytes inside the accumulator does not match, the detection process restarts +from the beginning. This mechanism is part of all verification tests. + +The complete regression suite can be executed with the run_regression.pl +script. For each test cell, it steps through the sequence + + 1) Assemble the source code + 2) Run the compiled VHDL design (currently only GHDL) + 3) Optionally perform a dump compare against the C-model + +It is highly recommended to redirect the output of run_regression.pl into a +file. Otherwise, analyzing the messages related to each test cell is almost +impossible. diff --git a/rtl/t48/rtl/vhdl/alu-c.vhd b/rtl/t48/rtl/vhdl/alu-c.vhd new file mode 100644 index 0000000..93fe852 --- /dev/null +++ b/rtl/t48/rtl/vhdl/alu-c.vhd @@ -0,0 +1,19 @@ +------------------------------------------------------------------------------- +-- +-- The Arithmetic Logic Unit (ALU). +-- It contains the ALU core plus the Accumulator and the Temp Reg. +-- +-- $Id: alu-c.vhd,v 1.2 2005/06/11 10:08:43 arniml Exp $ +-- +-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +configuration t48_alu_rtl_c0 of t48_alu is + + for rtl + end for; + +end t48_alu_rtl_c0; diff --git a/rtl/t48/rtl/vhdl/alu.vhd b/rtl/t48/rtl/vhdl/alu.vhd new file mode 100644 index 0000000..140bd4c --- /dev/null +++ b/rtl/t48/rtl/vhdl/alu.vhd @@ -0,0 +1,449 @@ +------------------------------------------------------------------------------- +-- +-- The Arithmetic Logic Unit (ALU). +-- It contains the ALU core plus the Accumulator and the Temp Reg. +-- +-- $Id: alu.vhd,v 1.9 2005/06/11 10:08:43 arniml Exp $ +-- +-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t48/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.t48_pack.word_t; +use work.t48_alu_pack.alu_op_t; + +entity t48_alu is + + port ( + -- Global Interface ------------------------------------------------------- + clk_i : in std_logic; + res_i : in std_logic; + en_clk_i : in boolean; + -- T48 Bus Interface ------------------------------------------------------ + data_i : in word_t; + data_o : out word_t; + write_accu_i : in boolean; + write_shadow_i : in boolean; + write_temp_reg_i : in boolean; + read_alu_i : in boolean; + -- Decoder Interface ------------------------------------------------------ + carry_i : in std_logic; + carry_o : out std_logic; + aux_carry_o : out std_logic; + alu_op_i : in alu_op_t; + use_carry_i : in boolean; + da_high_i : in boolean; + da_overflow_o : out boolean; + accu_low_i : in boolean; + p06_temp_reg_i : in boolean; + p60_temp_reg_i : in boolean + ); + +end t48_alu; + + +library ieee; +use ieee.numeric_std.all; + +use work.t48_pack.clk_active_c; +use work.t48_pack.res_active_c; +use work.t48_pack.bus_idle_level_c; +use work.t48_pack.nibble_t; +use work.t48_alu_pack.all; + +-- pragma translate_off +use work.t48_tb_pack.tb_accu_s; +-- pragma translate_on + +architecture rtl of t48_alu is + + -- the Accumulator and Temp Reg + signal accumulator_q, + accu_shadow_q, + temp_req_q : word_t; + -- inputs to the ALU core + signal in_a_s, + in_b_s : word_t; + -- output of the ALU core + signal data_s : word_t; + + signal add_result_s : alu_operand_t; + +begin + + ----------------------------------------------------------------------------- + -- Process working_regs + -- + -- Purpose: + -- Implements the working registers: + -- + Accumulator + -- + Temp Reg + -- + working_regs: process (res_i, clk_i) + begin + if res_i = res_active_c then + accumulator_q <= (others => '0'); + accu_shadow_q <= (others => '0'); + temp_req_q <= (others => '0'); + + elsif clk_i'event and clk_i = clk_active_c then + if en_clk_i then + + if write_accu_i then + if accu_low_i then + accumulator_q(nibble_t'range) <= data_i(nibble_t'range); + else + accumulator_q <= data_i; + end if; + end if; + + if write_shadow_i then + -- write shadow directly from t48 data bus + accu_shadow_q <= data_i; + else + -- default: update shadow Accumulator from real Accumulator + accu_shadow_q <= accumulator_q; + end if; + + if p06_temp_reg_i then + -- low nibble of DA sequence + temp_req_q <= "00000110"; + elsif p60_temp_reg_i then + -- high nibble of DA sequence + temp_req_q <= "01100000"; + elsif write_temp_reg_i then + -- normal load from T48 bus + temp_req_q <= data_i; + end if; + + end if; + + end if; + + end process working_regs; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Build the inputs to the ALU core. + -- Input A: + -- Unary operators use only Input A. + -- Is always fed from the shadow Accumulator. + -- Assumption: It never happens that the Accumulator is written and then + -- read for an ALU operation in the next cycle. + -- Its contents can thus be staged through the shadow Accu. + -- Input B: + -- Is always fed from the Temp Reg. + ----------------------------------------------------------------------------- + in_a_s <= accu_shadow_q; + in_b_s <= temp_req_q; + + + ----------------------------------------------------------------------------- + -- Process alu_core + -- + -- Purpose: + -- Implements the ALU core. + -- All operations defined in alu_op_t are handled here. + -- + alu_core: process (in_a_s, + in_b_s, + alu_op_i, + carry_i, + use_carry_i, + add_result_s) + + begin + -- default assigments + data_s <= (others => '0'); + carry_o <= '0'; + + case alu_op_i is + -- Operation: AND ------------------------------------------------------- + when ALU_AND => + data_s <= in_a_s and in_b_s; + + -- Operation: OR -------------------------------------------------------- + when ALU_OR => + data_s <= in_a_s or in_b_s; + + -- Operation: XOR ------------------------------------------------------- + when ALU_XOR => + data_s <= in_a_s xor in_b_s; + + -- Operation: Add ------------------------------------------------------- + when ALU_ADD => + data_s <= add_result_s(data_s'range); + carry_o <= add_result_s(add_result_s'high); + + -- Operation: CPL ------------------------------------------------------- + when ALU_CPL => + data_s <= not in_a_s; + + -- Operation: CLR ------------------------------------------------------- + when ALU_CLR => + data_s <= (others => '0'); + + -- Operation: RL -------------------------------------------------------- + when ALU_RL => + data_s(7 downto 1) <= in_a_s(6 downto 0); + carry_o <= in_a_s(7); + + if use_carry_i then + data_s(0) <= carry_i; + else + data_s(0) <= in_a_s(7); + end if; + + -- Operation: RR -------------------------------------------------------- + when ALU_RR => + data_s(6 downto 0) <= in_a_s(7 downto 1); + carry_o <= in_a_s(0); + + if use_carry_i then + data_s(7) <= carry_i; + else + data_s(7) <= in_a_s(0); + end if; + + -- Operation: Swap ------------------------------------------------------ + when ALU_SWAP => + data_s(3 downto 0) <= in_a_s(7 downto 4); + data_s(7 downto 4) <= in_a_s(3 downto 0); + + -- Operation: DEC ------------------------------------------------------- + when ALU_DEC => + data_s <= add_result_s(data_s'range); + + -- Operation: INC ------------------------------------------------------- + when ALU_INC => + data_s <= add_result_s(data_s'range); + + -- Operation CONCAT ----------------------------------------------------- + when ALU_CONCAT => + data_s <= in_b_s(7 downto 4) & in_a_s(3 downto 0); + + -- Operation: NOP ------------------------------------------------------- + when ALU_NOP => + data_s <= in_a_s; + + when others => + -- pragma translate_off + assert false + report "Unknown ALU operation selected!" + severity error; + -- pragma translate_on + + end case; + + end process alu_core; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process adder + -- + -- Purpose: + -- Implements the adder used by several instructions. + -- This way of modelling the adder forces resource sharing of: + -- * ADD + -- * INC + -- * DEC + -- + adder: process (in_a_s, + in_b_s, + alu_op_i, + carry_i, + use_carry_i) + + variable add_a_v, add_b_v : alu_operand_t; + variable c_v : alu_operand_t; + variable result_v : UNSIGNED(alu_operand_t'range); + variable aux_c_v : std_logic_vector(1 downto 0); + + begin + -- Carry Selection -------------------------------------------------------- + c_v := (others => '0'); + if use_carry_i and carry_i = '1' then + c_v(0) := '1'; + end if; + + -- Operand Selection ------------------------------------------------------ + -- defaults for ADD + add_a_v := '0' & in_a_s; + add_b_v := '0' & in_b_s; + + case alu_op_i is + when ALU_INC => + add_b_v := (others => '0'); + add_b_v(0) := '1'; + when ALU_DEC => + add_b_v := (others => '1'); + when others => + null; + end case; + + -- The Adder -------------------------------------------------------------- + result_v := UNSIGNED(add_a_v) + + UNSIGNED(add_b_v) + + UNSIGNED(c_v); + + add_result_s <= std_logic_vector(result_v); + + -- Auxiliary Carry -------------------------------------------------------- + aux_c_v := in_a_s(4) & in_b_s(4); + + aux_carry_o <= '0'; + case aux_c_v is + when "00" | "11" => + if result_v(4) = '1' then + aux_carry_o <= '1'; + end if; + + when "01" | "10" => + if result_v(4) = '0' then + aux_carry_o <= '1'; + end if; + + when others => + null; + + end case; + + end process adder; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process da_overflow + -- + -- Purpose: + -- Detect overflow situation during DA sequence. + -- + da_overflow: process (accu_shadow_q, + da_high_i) + + variable da_nibble_v : nibble_t; + + function da_overflow_f(data : in nibble_t) return boolean is + variable overflow_v : boolean; + begin + case data is + when "1010" | + "1011" | + "1100" | + "1101" | + "1110" | + "1111" => + overflow_v := true; + when others => + overflow_v := false; + end case; + + return(overflow_v); + end; + + begin + if da_high_i then + da_nibble_v := accu_shadow_q(7 downto 4); + else + da_nibble_v := accu_shadow_q(3 downto 0); + end if; + + da_overflow_o <= da_overflow_f(da_nibble_v); + + end process da_overflow; + -- + ----------------------------------------------------------------------------- + + + -- pragma translate_off + ----------------------------------------------------------------------------- + -- Testbench support. + ----------------------------------------------------------------------------- + tb_accu_s <= accumulator_q; + -- pragma translate_on + + ----------------------------------------------------------------------------- + -- Output Multiplexer. + ----------------------------------------------------------------------------- + data_o <= data_s + when read_alu_i else + (others => bus_idle_level_c); + +end rtl; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: alu.vhd,v $ +-- Revision 1.9 2005/06/11 10:08:43 arniml +-- introduce prefix 't48_' for all packages, entities and configurations +-- +-- Revision 1.8 2004/04/24 23:43:56 arniml +-- move from std_logic_arith to numeric_std +-- +-- Revision 1.7 2004/04/07 22:09:03 arniml +-- remove unused signals +-- +-- Revision 1.6 2004/04/07 20:56:23 arniml +-- default assignment for aux_carry_o +-- +-- Revision 1.5 2004/04/06 20:21:53 arniml +-- fix sensitivity list +-- +-- Revision 1.4 2004/04/06 18:10:41 arniml +-- rework adder and force resource sharing between ADD, INC and DEC +-- +-- Revision 1.3 2004/04/04 14:18:52 arniml +-- add measures to implement XCHD +-- +-- Revision 1.2 2004/03/28 21:08:51 arniml +-- support for DA instruction +-- +-- Revision 1.1 2004/03/23 21:31:52 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t48/rtl/vhdl/alu_pack-p.vhd b/rtl/t48/rtl/vhdl/alu_pack-p.vhd new file mode 100644 index 0000000..71c1e4b --- /dev/null +++ b/rtl/t48/rtl/vhdl/alu_pack-p.vhd @@ -0,0 +1,51 @@ +------------------------------------------------------------------------------- +-- +-- $Id: alu_pack-p.vhd,v 1.3 2005/06/11 10:08:43 arniml Exp $ +-- +-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.t48_pack.word_width_c; + +package t48_alu_pack is + + ----------------------------------------------------------------------------- + -- The ALU operations + ----------------------------------------------------------------------------- + type alu_op_t is (ALU_AND, ALU_OR, ALU_XOR, + ALU_CPL, ALU_CLR, + ALU_RL, ALU_RR, + ALU_SWAP, + ALU_DEC, ALU_INC, + ALU_ADD, + ALU_CONCAT, + ALU_NOP); + + ----------------------------------------------------------------------------- + -- The dedicated ALU arithmetic types. + ----------------------------------------------------------------------------- + subtype alu_operand_t is std_logic_vector(word_width_c downto 0); + +end t48_alu_pack; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: alu_pack-p.vhd,v $ +-- Revision 1.3 2005/06/11 10:08:43 arniml +-- introduce prefix 't48_' for all packages, entities and configurations +-- +-- Revision 1.2 2004/04/04 14:18:53 arniml +-- add measures to implement XCHD +-- +-- Revision 1.1 2004/03/23 21:31:52 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t48/rtl/vhdl/bus_mux-c.vhd b/rtl/t48/rtl/vhdl/bus_mux-c.vhd new file mode 100644 index 0000000..ccec86a --- /dev/null +++ b/rtl/t48/rtl/vhdl/bus_mux-c.vhd @@ -0,0 +1,19 @@ +------------------------------------------------------------------------------- +-- +-- The T48 Bus Connector. +-- Multiplexes all drivers of the T48 bus. +-- +-- $Id: bus_mux-c.vhd,v 1.2 2005/06/11 10:08:43 arniml Exp $ +-- +-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +configuration t48_bus_mux_rtl_c0 of t48_bus_mux is + + for rtl + end for; + +end t48_bus_mux_rtl_c0; diff --git a/rtl/t48/rtl/vhdl/bus_mux.vhd b/rtl/t48/rtl/vhdl/bus_mux.vhd new file mode 100644 index 0000000..8d09b33 --- /dev/null +++ b/rtl/t48/rtl/vhdl/bus_mux.vhd @@ -0,0 +1,113 @@ +------------------------------------------------------------------------------- +-- +-- The T48 Bus Connector. +-- Multiplexes all drivers of the T48 bus. +-- +-- $Id: bus_mux.vhd,v 1.2 2005/06/11 10:08:43 arniml Exp $ +-- +-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t48/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.t48_pack.word_t; + +entity t48_bus_mux is + + port ( + alu_data_i : in word_t; + bus_data_i : in word_t; + dec_data_i : in word_t; + dm_data_i : in word_t; + pm_data_i : in word_t; + p1_data_i : in word_t; + p2_data_i : in word_t; + psw_data_i : in word_t; + tim_data_i : in word_t; + data_o : out word_t + ); + +end t48_bus_mux; + + +use work.t48_pack.bus_idle_level_c; + +architecture rtl of t48_bus_mux is + +begin + + or_tree: if bus_idle_level_c = '0' generate + data_o <= alu_data_i or + bus_data_i or + dec_data_i or + dm_data_i or + pm_data_i or + p1_data_i or + p2_data_i or + psw_data_i or + tim_data_i; + end generate; + + and_tree: if bus_idle_level_c = '1' generate + data_o <= alu_data_i and + bus_data_i and + dec_data_i and + dm_data_i and + pm_data_i and + p1_data_i and + p2_data_i and + psw_data_i and + tim_data_i; + end generate; + +end rtl; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: bus_mux.vhd,v $ +-- Revision 1.2 2005/06/11 10:08:43 arniml +-- introduce prefix 't48_' for all packages, entities and configurations +-- +-- Revision 1.1 2004/03/23 21:31:52 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t48/rtl/vhdl/clock_ctrl-c.vhd b/rtl/t48/rtl/vhdl/clock_ctrl-c.vhd new file mode 100644 index 0000000..b36b70e --- /dev/null +++ b/rtl/t48/rtl/vhdl/clock_ctrl-c.vhd @@ -0,0 +1,14 @@ +------------------------------------------------------------------------------- +-- +-- $Id: clock_ctrl-c.vhd,v 1.2 2005/06/11 10:08:43 arniml Exp $ +-- +-- The clock control unit. +-- +------------------------------------------------------------------------------- + +configuration t48_clock_ctrl_rtl_c0 of t48_clock_ctrl is + + for rtl + end for; + +end t48_clock_ctrl_rtl_c0; diff --git a/rtl/t48/rtl/vhdl/clock_ctrl.vhd b/rtl/t48/rtl/vhdl/clock_ctrl.vhd new file mode 100644 index 0000000..0b6aa59 --- /dev/null +++ b/rtl/t48/rtl/vhdl/clock_ctrl.vhd @@ -0,0 +1,440 @@ +------------------------------------------------------------------------------- +-- +-- The Clock Control unit. +-- Clock States and Machine Cycles are generated here. +-- +-- $Id: clock_ctrl.vhd,v 1.10 2005/11/01 21:24:21 arniml Exp $ +-- +-- Copyright (c) 2004, 2005, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t48/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.t48_pack.all; + +entity t48_clock_ctrl is + + generic ( + -- divide XTAL1 by 3 to derive Clock States + xtal_div_3_g : integer := 1 + ); + + port ( + clk_i : in std_logic; + xtal_i : in std_logic; + res_i : in std_logic; + en_clk_i : in boolean; + xtal3_o : out boolean; + t0_o : out std_logic; + multi_cycle_i : in boolean; + assert_psen_i : in boolean; + assert_prog_i : in boolean; + assert_rd_i : in boolean; + assert_wr_i : in boolean; + mstate_o : out mstate_t; + second_cycle_o : out boolean; + ale_o : out boolean; + psen_o : out boolean; + prog_o : out boolean; + rd_o : out boolean; + wr_o : out boolean + ); + +end t48_clock_ctrl; + + +library ieee; +use ieee.numeric_std.all; + +architecture rtl of t48_clock_ctrl is + + -- The three XTAL1 cycles. + signal xtal_q : unsigned(1 downto 0); + signal xtal1_s, + xtal2_s, + xtal3_s : boolean; + signal x1_s, + x2_s, + x3_s : std_logic; + + signal t0_q : std_logic; + + + -- The five clock states. + signal mstate_q : mstate_t; + + signal ale_q : boolean; + signal psen_q : boolean; + signal prog_q : boolean; + signal rd_q : boolean; + signal wr_q : boolean; + + + -- The Machine Cycle marker. + signal second_cycle_q : boolean; + signal multi_cycle_q : boolean; + +begin + + ----------------------------------------------------------------------------- + -- Verify the generics + ----------------------------------------------------------------------------- + + -- pragma translate_off + + -- XTAL1 divide by 3 -------------------------------------------------------- + assert (xtal_div_3_g = 1) or (xtal_div_3_g = 0) + report "xtal_div_3_g must be either 1 or 0!" + severity failure; + + -- pragma translate_on + + + ----------------------------------------------------------------------------- + -- Divide XTAL1 by 3 to derive Clock States. + ----------------------------------------------------------------------------- + use_xtal_div: if xtal_div_3_g = 1 generate + xtal: process (res_i, xtal_i) + begin + if res_i = res_active_c then + xtal_q <= TO_UNSIGNED(0, 2); + t0_q <= '0'; + + elsif xtal_i'event and xtal_i = clk_active_c then + if xtal_q < 2 then + xtal_q <= xtal_q + 1; + else + xtal_q <= TO_UNSIGNED(0, 2); + end if; + + if xtal3_s then + t0_q <= '1'; + else + t0_q <= '0'; + end if; + + end if; + + end process xtal; + + x1_s <= '1' + when xtal_q = 0 else + '0'; + x2_s <= '1' + when xtal_q = 1 else + '0'; + x3_s <= '1' + when xtal_q = 2 else + '0'; + t0_o <= t0_q; + + end generate; + + ----------------------------------------------------------------------------- + -- XTAL1 is used directly for Clock States. + ----------------------------------------------------------------------------- + no_xtal_div: if xtal_div_3_g = 0 generate + xtal_q <= TO_UNSIGNED(0, 2); + + x1_s <= '1'; + x2_s <= '1'; + x3_s <= '1' + when en_clk_i else + '0'; + t0_o <= xtal_i; + + end generate; + + -- And finally the boolean flags -------------------------------------------- + xtal1_s <= to_boolean(x1_s); + xtal2_s <= to_boolean(x2_s); + xtal3_s <= to_boolean(x3_s); + + + ----------------------------------------------------------------------------- + -- Process external_signal + -- + -- Purpose: + -- Control signals ALE, PSEN, PROG and RD/WR are generated here. + -- + external_signals: process (res_i, xtal_i) + begin + if res_i = res_active_c then + ale_q <= false; + psen_q <= false; + prog_q <= false; + rd_q <= false; + wr_q <= false; + + elsif xtal_i'event and xtal_i = clk_active_c then + + case mstate_q is + when MSTATE5 => + -- RD, WR are set at the end of XTAL2 of first machine cycle + if xtal2_s and not second_cycle_q then + if assert_rd_i then + rd_q <= true; + end if; + if assert_wr_i then + wr_q <= true; + end if; + end if; + + when MSTATE1 => + if xtal3_s then + psen_q <= false; + end if; + + when MSTATE2 => + if xtal2_s then + -- PROG is removed at the end of XTAL2 of second machine cycle + -- according to the user manual, PROG should be removed at the + -- end of XTAL3 but this would raise the need to change P2 at + -- XTAL1 or XTAL2 -> introduction of inter-xtal timing in + -- the rest of the core. + prog_q <= false; + end if; + if xtal3_s then + -- RD, WR are removed at the end of XTAL3 of second machine cycle + rd_q <= false; + wr_q <= false; + end if; + + when MSTATE3 => + -- ALE is set at the end of XTAL3 of every machine cycle + if xtal3_s then + ale_q <= true; + end if; + + when MSTATE4 => + if xtal3_s then + -- PSEN is set at the end of XTAL3 + if assert_psen_i then + psen_q <= true; + end if; + + end if; + + -- PROG is set at the end of XTAL3 + if xtal3_s and + multi_cycle_q and not second_cycle_q and assert_prog_i then + prog_q <= true; + end if; + + -- ALE is removed at the end of XTAL2 of every machine cycle + if xtal2_s then + ale_q <= false; + end if; + + when others => + -- recover when states are out of sync + ale_q <= false; + psen_q <= false; + prog_q <= false; + rd_q <= false; + wr_q <= false; + + end case; + + end if; + + end process external_signals; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process states + -- + -- Purpose: + -- The Clock State controller. + -- + states: process (res_i, clk_i) + begin + if res_i = res_active_c then + -- Reset machine state to MSTATE3 + -- This allows a proper instruction fetch for the first real instruction + -- after reset. + -- The MSTATE3 is part of a virtual NOP that has no MSTATE1 and MSTATE2. + mstate_q <= MSTATE3; + + elsif clk_i'event and clk_i = clk_active_c then + if en_clk_i then + + case mstate_q is + when MSTATE5 => + mstate_q <= MSTATE1; + + when MSTATE1 => + mstate_q <= MSTATE2; + + when MSTATE2 => + mstate_q <= MSTATE3; + + when MSTATE3 => + mstate_q <= MSTATE4; + + when MSTATE4 => + mstate_q <= MSTATE5; + + when others => + -- recover when states are out of sync + mstate_q <= MSTATE1; + + -- pragma translate_off + assert false + report "Encoding of Clock States failed!" + severity error; + -- pragma translate_on + + end case; + + end if; + + end if; + + end process states; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process machine_cycle + -- + -- Purpose: + -- Keep track of machine cycles. + -- Basically, this means to differ between first and second cycle. + -- + machine_cycle: process (res_i, clk_i) + variable state2_v, state5_v : boolean; + begin + if res_i = res_active_c then + multi_cycle_q <= false; + second_cycle_q <= false; + + elsif clk_i'event and clk_i = clk_active_c then + if en_clk_i then + + state2_v := mstate_q = MSTATE2; + state5_v := mstate_q = MSTATE5; + + -- multi cycle information is delivered in State 2 from the decoder + if state2_v and multi_cycle_i then + multi_cycle_q <= true; + end if; + + -- mark second machine cycle + if multi_cycle_q and state5_v then + second_cycle_q <= true; + end if; + + -- reset at end of second machine cycle + if state5_v and + (multi_cycle_q and second_cycle_q) then + multi_cycle_q <= false; + second_cycle_q <= false; + end if; + + end if; + + end if; + + end process machine_cycle; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Output assignments + ----------------------------------------------------------------------------- + xtal3_o <= xtal3_s; + mstate_o <= mstate_q; + second_cycle_o <= second_cycle_q; + ale_o <= ale_q; + psen_o <= psen_q; + prog_o <= prog_q; + rd_o <= rd_q; + wr_o <= wr_q; + +end rtl; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: clock_ctrl.vhd,v $ +-- Revision 1.10 2005/11/01 21:24:21 arniml +-- * shift assertion of ALE and PROG to xtal3 +-- * correct change of revision 1.8 +-- +-- Revision 1.9 2005/06/11 10:08:43 arniml +-- introduce prefix 't48_' for all packages, entities and configurations +-- +-- Revision 1.8 2005/06/09 22:15:10 arniml +-- Use en_clk_i instead of xtal3_s for generation of external signals. +-- This is required when the core runs with full xtal clock instead +-- of xtal/3 (xtal_div_3_g = 0). +-- +-- Revision 1.7 2005/05/04 20:12:36 arniml +-- Fix bug report: +-- "Wrong clock applied to T0" +-- t0_o is generated inside clock_ctrl with a separate flip-flop running +-- with xtal_i +-- +-- Revision 1.6 2004/10/25 20:31:12 arniml +-- remove PROG and end of XTAL2, see comment for details +-- +-- Revision 1.5 2004/10/25 19:35:41 arniml +-- deassert rd_q, wr_q and prog_q at end of XTAL3 +-- +-- Revision 1.4 2004/04/24 23:44:25 arniml +-- move from std_logic_arith to numeric_std +-- +-- Revision 1.3 2004/04/18 18:56:23 arniml +-- reset machine state to MSTATE3 to allow proper instruction fetch +-- after reset +-- +-- Revision 1.2 2004/03/28 12:55:06 arniml +-- move code for PROG out of if-branch for xtal3_s +-- +-- Revision 1.1 2004/03/23 21:31:52 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t48/rtl/vhdl/cond_branch-c.vhd b/rtl/t48/rtl/vhdl/cond_branch-c.vhd new file mode 100644 index 0000000..15a0b7e --- /dev/null +++ b/rtl/t48/rtl/vhdl/cond_branch-c.vhd @@ -0,0 +1,19 @@ +------------------------------------------------------------------------------- +-- +-- The Conditional Branch Logic unit. +-- Decisions whether to take a jump or not are made here. +-- +-- $Id: cond_branch-c.vhd,v 1.2 2005/06/11 10:08:43 arniml Exp $ +-- +-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +configuration t48_cond_branch_rtl_c0 of t48_cond_branch is + + for rtl + end for; + +end t48_cond_branch_rtl_c0; diff --git a/rtl/t48/rtl/vhdl/cond_branch.vhd b/rtl/t48/rtl/vhdl/cond_branch.vhd new file mode 100644 index 0000000..a97f871 --- /dev/null +++ b/rtl/t48/rtl/vhdl/cond_branch.vhd @@ -0,0 +1,217 @@ +------------------------------------------------------------------------------- +-- +-- The Conditional Branch Logic unit. +-- Decisions whether to take a jump or not are made here. +-- +-- $Id: cond_branch.vhd,v 1.3 2005/06/11 10:08:43 arniml Exp $ +-- +-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t48/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.t48_pack.word_t; + +use work.t48_cond_branch_pack.all; + +entity t48_cond_branch is + + port ( + -- Global Interface ------------------------------------------------------- + clk_i : in std_logic; + res_i : in std_logic; + en_clk_i : in boolean; + -- Decoder Interface ------------------------------------------------------ + compute_take_i : in boolean; + branch_cond_i : in branch_conditions_t; + take_branch_o : out boolean; + accu_i : in word_t; + t0_i : in std_logic; + t1_i : in std_logic; + int_n_i : in std_logic; + f0_i : in std_logic; + f1_i : in std_logic; + tf_i : in std_logic; + carry_i : in std_logic; + comp_value_i : in comp_value_t + ); + +end t48_cond_branch; + + +library ieee; +use ieee.numeric_std.all; + +use work.t48_pack.res_active_c; +use work.t48_pack.clk_active_c; + +architecture rtl of t48_cond_branch is + + -- marker for branch taken + signal take_branch_s, + take_branch_q : boolean; + +begin + + ----------------------------------------------------------------------------- + -- Process decide_take + -- + -- Purpose: + -- Decides whether a branch has to be taken or not. + -- + decide_take: process (accu_i, + branch_cond_i, + t0_i, t1_i, + int_n_i, + f0_i, f1_i, + tf_i, + carry_i, + comp_value_i) + variable or_v : std_logic; + begin + -- default assignment + take_branch_s <= false; + or_v := '0'; + + case branch_cond_i is + -- Branch On: Accumulator Bit ------------------------------------------- + when COND_ON_BIT => + if accu_i(TO_INTEGER(UNSIGNED(comp_value_i))) = '1' then + take_branch_s <= true; + end if; + + -- Branch On: Accumulator Zero ------------------------------------------ + when COND_Z => + for i in accu_i'range loop + or_v := or_v or accu_i(i); + end loop; + take_branch_s <= or_v = not comp_value_i(0); + + -- Branch On: Carry ----------------------------------------------------- + when COND_C => + take_branch_s <= carry_i = comp_value_i(0); + + -- Branch On: Flag 0 ---------------------------------------------------- + when COND_F0 => + take_branch_s <= f0_i = '1'; + + -- Branch On: Flag 1 ---------------------------------------------------- + when COND_F1 => + take_branch_s <= f1_i = '1'; + + -- Branch On: Interrupt ------------------------------------------------- + when COND_INT => + take_branch_s <= int_n_i = '0'; + + -- Branch On: Test 0 ---------------------------------------------------- + when COND_T0 => + take_branch_s <= t0_i = comp_value_i(0); + + -- Branch On: Test 1 ---------------------------------------------------- + when COND_T1 => + take_branch_s <= t1_i = comp_value_i(0); + + -- Branch On: Timer Flag ------------------------------------------------ + when COND_TF => + take_branch_s <= tf_i = '1'; + + when others => + -- pragma translate_off + assert false + report "Unknown branch condition specified!" + severity error; + -- pragma translate_on + + end case; + + end process decide_take; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process reg + -- + -- Purpose: + -- Implement the marker register. + -- + reg: process (res_i, clk_i) + begin + if res_i = res_active_c then + take_branch_q <= false; + + elsif clk_i'event and clk_i = clk_active_c then + if en_clk_i then + + if compute_take_i then + take_branch_q <= take_branch_s; + end if; + + end if; + + end if; + + end process reg; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Output Mapping. + ----------------------------------------------------------------------------- + take_branch_o <= take_branch_q; + +end rtl; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: cond_branch.vhd,v $ +-- Revision 1.3 2005/06/11 10:08:43 arniml +-- introduce prefix 't48_' for all packages, entities and configurations +-- +-- Revision 1.2 2004/04/24 23:44:25 arniml +-- move from std_logic_arith to numeric_std +-- +-- Revision 1.1 2004/03/23 21:31:52 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t48/rtl/vhdl/cond_branch_pack-p.vhd b/rtl/t48/rtl/vhdl/cond_branch_pack-p.vhd new file mode 100644 index 0000000..e6a029f --- /dev/null +++ b/rtl/t48/rtl/vhdl/cond_branch_pack-p.vhd @@ -0,0 +1,41 @@ +------------------------------------------------------------------------------- +-- +-- $Id: cond_branch_pack-p.vhd,v 1.2 2005/06/11 10:08:43 arniml Exp $ +-- +-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +package t48_cond_branch_pack is + + ----------------------------------------------------------------------------- + -- The branch conditions. + ----------------------------------------------------------------------------- + type branch_conditions_t is (COND_ON_BIT, COND_Z, + COND_C, + COND_F0, COND_F1, + COND_INT, + COND_T0, COND_T1, + COND_TF); + + subtype comp_value_t is std_logic_vector(2 downto 0); + +end t48_cond_branch_pack; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: cond_branch_pack-p.vhd,v $ +-- Revision 1.2 2005/06/11 10:08:43 arniml +-- introduce prefix 't48_' for all packages, entities and configurations +-- +-- Revision 1.1 2004/03/23 21:31:52 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t48/rtl/vhdl/db_bus-c.vhd b/rtl/t48/rtl/vhdl/db_bus-c.vhd new file mode 100644 index 0000000..2047eb9 --- /dev/null +++ b/rtl/t48/rtl/vhdl/db_bus-c.vhd @@ -0,0 +1,19 @@ +------------------------------------------------------------------------------- +-- +-- The BUS unit. +-- Implements the BUS port logic. +-- +-- $Id: db_bus-c.vhd,v 1.2 2005/06/11 10:08:43 arniml Exp $ +-- +-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +configuration t48_db_bus_rtl_c0 of t48_db_bus is + + for rtl + end for; + +end t48_db_bus_rtl_c0; diff --git a/rtl/t48/rtl/vhdl/db_bus.vhd b/rtl/t48/rtl/vhdl/db_bus.vhd new file mode 100644 index 0000000..54e6b19 --- /dev/null +++ b/rtl/t48/rtl/vhdl/db_bus.vhd @@ -0,0 +1,169 @@ +------------------------------------------------------------------------------- +-- +-- The BUS unit. +-- Implements the BUS port logic. +-- +-- $Id: db_bus.vhd,v 1.5 2005/06/11 10:08:43 arniml Exp $ +-- +-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t48/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.t48_pack.word_t; + +entity t48_db_bus is + + port ( + -- Global Interface ------------------------------------------------------- + clk_i : in std_logic; + res_i : in std_logic; + en_clk_i : in boolean; + ea_i : in std_logic; + -- T48 Bus Interface ------------------------------------------------------ + data_i : in word_t; + data_o : out word_t; + write_bus_i : in boolean; + read_bus_i : in boolean; + -- BUS Interface ---------------------------------------------------------- + output_pcl_i : in boolean; + bidir_bus_i : in boolean; + pcl_i : in word_t; + db_i : in word_t; + db_o : out word_t; + db_dir_o : out std_logic + ); + +end t48_db_bus; + + +use work.t48_pack.clk_active_c; +use work.t48_pack.res_active_c; +use work.t48_pack.bus_idle_level_c; +use work.t48_pack.to_stdLogic; + +architecture rtl of t48_db_bus is + + -- the BUS output register + signal bus_q : word_t; + + -- BUS direction marker + signal db_dir_q, + db_dir_qq : std_logic; + +begin + + ----------------------------------------------------------------------------- + -- Process bus_regs + -- + -- Purpose: + -- Implements the BUS output register. + -- + bus_regs: process (res_i, clk_i) + begin + if res_i = res_active_c then + bus_q <= (others => '0'); + db_dir_q <= '0'; + db_dir_qq <= '0'; + + elsif clk_i'event and clk_i = clk_active_c then + if en_clk_i then + if write_bus_i then + db_dir_qq <= '1'; + else + -- extend bus direction by one machine cycle + db_dir_qq <= db_dir_q; + end if; + + if write_bus_i then + bus_q <= data_i; + + db_dir_q <= '1'; + + elsif ea_i = '1' or bidir_bus_i then + db_dir_q <= '0'; + + end if; + + end if; + + end if; + + end process bus_regs; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Output Mapping. + ----------------------------------------------------------------------------- + db_o <= pcl_i + when output_pcl_i else + bus_q; + db_dir_o <= db_dir_qq or + to_stdLogic(output_pcl_i); + data_o <= (others => bus_idle_level_c) + when not read_bus_i else + db_i; + +end rtl; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: db_bus.vhd,v $ +-- Revision 1.5 2005/06/11 10:08:43 arniml +-- introduce prefix 't48_' for all packages, entities and configurations +-- +-- Revision 1.4 2005/06/09 22:16:26 arniml +-- Implement db_dir_o glitch-safe +-- +-- Revision 1.3 2004/10/25 20:30:18 arniml +-- delay db_dir_o by one machine cycle +-- this fixes the timing relation between BUS data and WR' +-- +-- Revision 1.2 2004/04/04 14:15:45 arniml +-- add dump_compare support +-- +-- Revision 1.1 2004/03/23 21:31:52 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t48/rtl/vhdl/decoder-c.vhd b/rtl/t48/rtl/vhdl/decoder-c.vhd new file mode 100644 index 0000000..efcebaf --- /dev/null +++ b/rtl/t48/rtl/vhdl/decoder-c.vhd @@ -0,0 +1,28 @@ +------------------------------------------------------------------------------- +-- +-- The Decoder unit. +-- It decodes the instruction opcodes and executes them. +-- +-- $Id: decoder-c.vhd,v 1.2 2005/06/11 10:08:43 arniml Exp $ +-- +-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +configuration t48_decoder_rtl_c0 of t48_decoder is + + for rtl + + for opc_decoder_b: t48_opc_decoder + use configuration work.t48_opc_decoder_rtl_c0; + end for; + + for int_b: t48_int + use configuration work.t48_int_rtl_c0; + end for; + + end for; + +end t48_decoder_rtl_c0; diff --git a/rtl/t48/rtl/vhdl/decoder.vhd b/rtl/t48/rtl/vhdl/decoder.vhd new file mode 100644 index 0000000..f0d6519 --- /dev/null +++ b/rtl/t48/rtl/vhdl/decoder.vhd @@ -0,0 +1,2069 @@ +------------------------------------------------------------------------------- +-- +-- The Decoder unit. +-- It decodes the instruction opcodes and executes them. +-- +-- $Id: decoder.vhd,v 1.24 2005/11/14 21:12:29 arniml Exp $ +-- +-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t48/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.t48_pack.word_t; +use work.t48_pack.mstate_t; +use work.t48_alu_pack.alu_op_t; +use work.t48_cond_branch_pack.all; +use work.t48_dmem_ctrl_pack.all; +use work.t48_pmem_ctrl_pack.all; + +entity t48_decoder is + + generic ( + -- store mnemonic in flip-flops (registered-out) + register_mnemonic_g : integer := 1 + ); + + port ( + -- Global Interface ------------------------------------------------------- + clk_i : in std_logic; + res_i : in std_logic; + en_clk_i : in boolean; + xtal_i : in std_logic; + ea_i : in std_logic; + ale_i : in boolean; + int_n_i : in std_logic; + t0_dir_o : out std_logic; + -- T48 Bus Interface ------------------------------------------------------ + data_i : in word_t; + data_o : out word_t; + alu_write_accu_o : out boolean; + alu_write_shadow_o : out boolean; + alu_write_temp_reg_o : out boolean; + alu_read_alu_o : out boolean; + bus_write_bus_o : out boolean; + bus_read_bus_o : out boolean; + dm_write_dmem_addr_o : out boolean; + dm_write_dmem_o : out boolean; + dm_read_dmem_o : out boolean; + p1_write_p1_o : out boolean; + p1_read_p1_o : out boolean; + p2_write_p2_o : out boolean; + p2_write_exp_o : out boolean; + p2_read_p2_o : out boolean; + p2_read_exp_o : out boolean; + pm_write_pcl_o : out boolean; + pm_read_pcl_o : out boolean; + pm_write_pch_o : out boolean; + pm_read_pch_o : out boolean; + pm_read_pmem_o : out boolean; + psw_read_psw_o : out boolean; + psw_read_sp_o : out boolean; + psw_write_psw_o : out boolean; + psw_write_sp_o : out boolean; + -- ALU Interface ---------------------------------------------------------- + alu_carry_i : in std_logic; + alu_op_o : out alu_op_t; + alu_use_carry_o : out boolean; + alu_da_high_o : out boolean; + alu_accu_low_o : out boolean; + alu_p06_temp_reg_o : out boolean; + alu_p60_temp_reg_o : out boolean; + alu_da_overflow_i : in boolean; + -- BUS Interface ---------------------------------------------------------- + bus_output_pcl_o : out boolean; + bus_bidir_bus_o : out boolean; + -- Clock Controller Interface --------------------------------------------- + clk_multi_cycle_o : out boolean; + clk_assert_psen_o : out boolean; + clk_assert_prog_o : out boolean; + clk_assert_rd_o : out boolean; + clk_assert_wr_o : out boolean; + clk_mstate_i : in mstate_t; + clk_second_cycle_i : in boolean; + -- Conditional Branch Logic Interface ------------------------------------- + cnd_compute_take_o : out boolean; + cnd_branch_cond_o : out branch_conditions_t; + cnd_take_branch_i : in boolean; + cnd_comp_value_o : out comp_value_t; + cnd_f1_o : out std_logic; + cnd_tf_o : out std_logic; + -- Data Memory Controller Interface --------------------------------------- + dm_addr_type_o : out dmem_addr_ident_t; + -- Port 1 Interface ------------------------------------------------------- + p1_read_reg_o : out boolean; + -- Port 2 Interface ------------------------------------------------------- + p2_read_reg_o : out boolean; + p2_output_pch_o : out boolean; + -- Program Memory Controller Interface ------------------------------------ + pm_inc_pc_o : out boolean; + pm_write_pmem_addr_o : out boolean; + pm_addr_type_o : out pmem_addr_ident_t; + -- Program Status Word Interface ------------------------------------------ + psw_special_data_o : out std_logic; + psw_carry_i : in std_logic; + psw_aux_carry_i : in std_logic; + psw_f0_i : in std_logic; + psw_inc_stackp_o : out boolean; + psw_dec_stackp_o : out boolean; + psw_write_carry_o : out boolean; + psw_write_aux_carry_o : out boolean; + psw_write_f0_o : out boolean; + psw_write_bs_o : out boolean; + -- Timer Interface -------------------------------------------------------- + tim_read_timer_o : out boolean; + tim_write_timer_o : out boolean; + tim_start_t_o : out boolean; + tim_start_cnt_o : out boolean; + tim_stop_tcnt_o : out boolean; + tim_overflow_i : in boolean + ); + +end t48_decoder; + + +use work.t48_pack.all; +use work.t48_alu_pack.all; +use work.t48_decoder_pack.all; + +use work.t48_comp_pack.t48_opc_decoder; +use work.t48_comp_pack.t48_int; + +-- pragma translate_off +use work.t48_tb_pack.tb_istrobe_s; +-- pragma translate_on + +architecture rtl of t48_decoder is + + -- Enable fixing a bug of Quartus II 4.0 + constant enable_quartus_bugfix_c : boolean := true; + + -- Opcode Decoder + signal opc_multi_cycle_s : boolean; + signal opc_read_bus_s : boolean; + signal opc_inj_int_s : boolean; + signal opc_opcode_s : word_t; + signal opc_mnemonic_s : mnemonic_t; + signal last_cycle_s : boolean; + + -- state translators + signal assert_psen_s : boolean; + + -- branch taken handshake + signal branch_taken_s, + branch_taken_q : boolean; + signal pm_inc_pc_s : boolean; + signal pm_write_pmem_addr_s : boolean; + -- additional signal to increment PC during CALL + signal add_inc_pc_s : boolean; + -- addtional signal to set PC during RET(R) + signal add_write_pmem_addr_s : boolean; + + -- Flag 1 + signal clear_f1_s, + cpl_f1_s : boolean; + signal f1_q : std_logic; + -- memory bank select + signal clear_mb_s, + set_mb_s : boolean; + signal mb_q : std_logic; + + -- T0 direction selection + signal ent0_clk_s : boolean; + signal t0_dir_q : std_logic; + + signal data_s : word_t; + signal read_dec_s : boolean; + + signal tf_s : std_logic; + + signal bus_read_bus_s : boolean; + signal add_read_bus_s : boolean; + + signal dm_write_dmem_s : boolean; + + signal p2_output_exp_s : boolean; + + signal movx_first_cycle_s : boolean; + + -- interrupt handling + signal jtf_executed_s : boolean; + signal en_tcnti_s : boolean; + signal dis_tcnti_s : boolean; + signal en_i_s : boolean; + signal dis_i_s : boolean; + signal tim_int_s : boolean; + signal retr_executed_s : boolean; + signal int_executed_s : boolean; + signal int_pending_s : boolean; + signal int_in_progress_s : boolean; + + -- pragma translate_off + signal istrobe_res_q : std_logic; + signal istrobe_q : std_logic; + signal injected_int_q : std_logic; + -- pragma translate_on + +begin + + ----------------------------------------------------------------------------- + -- Opcode Decoder + ----------------------------------------------------------------------------- + opc_decoder_b : t48_opc_decoder + generic map ( + register_mnemonic_g => register_mnemonic_g + ) + port map ( + clk_i => clk_i, + res_i => res_i, + en_clk_i => en_clk_i, + data_i => data_i, + read_bus_i => opc_read_bus_s, + inj_int_i => opc_inj_int_s, + opcode_o => opc_opcode_s, + mnemonic_o => opc_mnemonic_s, + multi_cycle_o => opc_multi_cycle_s + ); + + + ----------------------------------------------------------------------------- + -- Interrupt Controller. + ----------------------------------------------------------------------------- + int_b : t48_int + port map ( + clk_i => clk_i, + res_i => res_i, + en_clk_i => en_clk_i, + xtal_i => xtal_i, + clk_mstate_i => clk_mstate_i, + jtf_executed_i => jtf_executed_s, + tim_overflow_i => tim_overflow_i, + tf_o => tf_s, + en_tcnti_i => en_tcnti_s, + dis_tcnti_i => dis_tcnti_s, + int_n_i => int_n_i, + ale_i => ale_i, + last_cycle_i => last_cycle_s, + en_i_i => en_i_s, + dis_i_i => dis_i_s, + ext_int_o => open, + tim_int_o => tim_int_s, + retr_executed_i => retr_executed_s, + int_executed_i => int_executed_s, + int_pending_o => int_pending_s, + int_in_progress_o => int_in_progress_s + ); + + last_cycle_s <= not opc_multi_cycle_s or + (opc_multi_cycle_s and clk_second_cycle_i); + + ----------------------------------------------------------------------------- + -- Process machine_cycle + -- + -- Purpose: + -- Generates the control signals that are basically needed for the + -- handling of a machine cycle. + -- + machine_cycle: process (clk_mstate_i, + clk_second_cycle_i, + last_cycle_s, + ea_i, + assert_psen_s, + branch_taken_q, + int_pending_s, + p2_output_exp_s, + movx_first_cycle_s) + + variable need_address_v : boolean; + + begin + -- default assignments + clk_assert_psen_o <= false; + pm_inc_pc_s <= false; + pm_write_pmem_addr_s <= false; + pm_read_pmem_o <= false; + bus_output_pcl_o <= false; + p2_output_pch_o <= false; + opc_read_bus_s <= false; + opc_inj_int_s <= false; + bus_read_bus_s <= false; + + need_address_v := not clk_second_cycle_i or + (clk_second_cycle_i and assert_psen_s); + + case clk_mstate_i is + when MSTATE1 => + if need_address_v then + if ea_i = '0' then + if not int_pending_s then + pm_read_pmem_o <= true; + end if; + + else + if not int_pending_s then + bus_read_bus_s <= true; + end if; + p2_output_pch_o <= true; + end if; + + end if; + + if not clk_second_cycle_i then + if not int_pending_s then + opc_read_bus_s <= true; + else + opc_inj_int_s <= true; -- inject interrupt call + end if; + end if; + + when MSTATE2 => + if need_address_v and not branch_taken_q and + not int_pending_s then + pm_inc_pc_s <= true; + end if; + + when MSTATE3 => + if need_address_v then + -- Theory of operation: + -- Program Memory address is updated at end of State 3 (or end of + -- State 2 in case of a RET). Address information is thus available + -- latest with State 4. + -- This is the time where we need information about access target + -- (internal or external = EA). EA information needs to be stable + -- until end of State 1. + pm_write_pmem_addr_s <= true; + end if; + + when MSTATE4 => + if ea_i = '1' and + ((not clk_second_cycle_i and assert_psen_s) + or last_cycle_s) then + clk_assert_psen_o <= true; + p2_output_pch_o <= true; + bus_output_pcl_o <= true; + end if; + + when MSTATE5 => + if ea_i = '1' and + (need_address_v or last_cycle_s) and + -- Suppress output of PCH when either + -- a) expander port is driven on P2, has priority + not p2_output_exp_s and + -- b) first cycle of MOVX, don't disturb external access + not movx_first_cycle_s then + p2_output_pch_o <= true; + end if; + + when others => + -- pragma translate_off + assert false + report "Unkown machine state!" + severity error; + -- pragma translate_on + + end case; + + end process machine_cycle; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process decode + -- + -- Purpose: + -- Indentifies each single instruction and steps through the related + -- execution sequence. + -- + decode: process (alu_carry_i, + psw_aux_carry_i, + alu_da_overflow_i, + clk_mstate_i, + clk_second_cycle_i, + cnd_take_branch_i, + opc_opcode_s, + opc_mnemonic_s, + psw_carry_i, + psw_f0_i, + f1_q, + mb_q, + tim_int_s, + int_pending_s, + int_in_progress_s) + + procedure address_indirect_3_f is + begin + -- apply dmem address from selected register for indirect mode + if opc_opcode_s(3) = '0' or enable_quartus_bugfix_c then + dm_read_dmem_o <= true; + dm_write_dmem_addr_o <= true; + dm_addr_type_o <= DM_PLAIN; + end if; + end; + + procedure and_or_xor_add_4_f is + begin + -- write dmem contents to Temp Reg + dm_read_dmem_o <= true; + alu_write_temp_reg_o <= true; + end; + + procedure and_or_xor_add_5_f (alu_op : alu_op_t) is + begin + -- perform ALU operation and store in Accumulator + alu_op_o <= alu_op; + alu_read_alu_o <= true; + alu_write_accu_o <= true; + end; + + procedure cond_jump_c2_m1_f is + begin + -- store address in Program Counter low byte if branch has to + -- be taken +-- if clk_mstate_i = MSTATE1 and cnd_take_branch_i then + pm_write_pcl_o <= true; + branch_taken_s <= true; +-- end if; + end; + + -- intermediate value of the Program Memory Bank Flag + variable mb_v : std_logic; + + begin + -- default assignments + data_s <= (others => '-'); + read_dec_s <= false; + branch_taken_s <= false; + clear_f1_s <= false; + cpl_f1_s <= false; + clear_mb_s <= false; + set_mb_s <= false; + add_inc_pc_s <= false; + assert_psen_s <= false; + alu_write_accu_o <= false; + alu_write_shadow_o <= false; + alu_write_temp_reg_o <= false; + alu_p06_temp_reg_o <= false; + alu_p60_temp_reg_o <= false; + alu_read_alu_o <= false; + bus_write_bus_o <= false; + bus_bidir_bus_o <= false; + dm_write_dmem_addr_o <= false; + dm_write_dmem_s <= false; + dm_read_dmem_o <= false; + pm_write_pcl_o <= false; + pm_read_pcl_o <= false; + pm_write_pch_o <= false; + pm_read_pch_o <= false; + pm_addr_type_o <= PM_PC; + psw_read_psw_o <= false; + psw_read_sp_o <= false; + psw_write_psw_o <= false; + psw_write_sp_o <= false; + alu_op_o <= ALU_NOP; + alu_use_carry_o <= false; + alu_da_high_o <= false; + alu_accu_low_o <= false; + clk_assert_prog_o <= false; + clk_assert_rd_o <= false; + clk_assert_wr_o <= false; + cnd_branch_cond_o <= COND_ON_BIT; + cnd_compute_take_o <= false; + cnd_comp_value_o <= opc_opcode_s(7 downto 5); + dm_addr_type_o <= DM_REG; + tim_read_timer_o <= false; + tim_write_timer_o <= false; + tim_start_t_o <= false; + tim_start_cnt_o <= false; + tim_stop_tcnt_o <= false; + p1_write_p1_o <= false; + p1_read_p1_o <= false; + p1_read_reg_o <= false; + p2_write_p2_o <= false; + p2_write_exp_o <= false; + p2_read_p2_o <= false; + p2_read_reg_o <= false; + p2_read_exp_o <= false; + p2_output_exp_s <= false; + psw_special_data_o <= '0'; + psw_inc_stackp_o <= false; + psw_dec_stackp_o <= false; + psw_write_carry_o <= false; + psw_write_aux_carry_o <= false; + psw_write_f0_o <= false; + psw_write_bs_o <= false; + jtf_executed_s <= false; + en_tcnti_s <= false; + dis_tcnti_s <= false; + en_i_s <= false; + dis_i_s <= false; + retr_executed_s <= false; + int_executed_s <= false; + add_write_pmem_addr_s <= false; + ent0_clk_s <= false; + add_read_bus_s <= false; + movx_first_cycle_s <= false; + + -- the Program Memory Bank Flag is held low when interrupts are in progress + -- according to the MCS-48 User's Manual + if int_in_progress_s then + mb_v := '0'; + else + mb_v := mb_q; + end if; + + -- prepare potential register indirect address mode + if not clk_second_cycle_i and clk_mstate_i = MSTATE2 then + data_s <= (others => '0'); + if opc_opcode_s(3) = '1' then + data_s(2 downto 0) <= opc_opcode_s(2 downto 0); + else + data_s(2 downto 0) <= "00" & opc_opcode_s(0); + end if; + + read_dec_s <= true; + dm_write_dmem_addr_o <= true; + dm_addr_type_o <= DM_REG; + end if; + + case opc_mnemonic_s is + + -- Mnemonic ADD --------------------------------------------------------- + when MN_ADD => + case clk_mstate_i is + -- read RAM once for indirect address mode + when MSTATE3 => + if not enable_quartus_bugfix_c or + opc_opcode_s(3) = '0' then + address_indirect_3_f; + end if; + + -- store data from RAM to Temp Reg + when MSTATE4 => + and_or_xor_add_4_f; + + -- perform ADD and store in Accumulator + when MSTATE5 => + and_or_xor_add_5_f(alu_op => ALU_ADD); + + if opc_opcode_s(4) = '1' then + alu_use_carry_o <= true; + end if; + + psw_special_data_o <= alu_carry_i; + psw_write_carry_o <= true; + psw_write_aux_carry_o <= true; + + when others => + null; + + end case; + + -- Mnemonic ADD_A_DATA -------------------------------------------------- + when MN_ADD_A_DATA => + assert_psen_s <= true; + + if clk_second_cycle_i then + case clk_mstate_i is + -- write Temp Reg when contents of Program Memory is on bus + when MSTATE1 => + alu_write_temp_reg_o <= true; + + -- perform ADD and store in Accumulator + when MSTATE3 => + and_or_xor_add_5_f(alu_op => ALU_ADD); + + if opc_opcode_s(4) = '1' then + alu_use_carry_o <= true; + end if; + + psw_special_data_o <= alu_carry_i; + psw_write_carry_o <= true; + psw_write_aux_carry_o <= true; + + when others => + null; + + end case; + + end if; + + -- Mnemonic ANL --------------------------------------------------------- + when MN_ANL => + case clk_mstate_i is + -- read RAM once for indirect address mode + when MSTATE3 => + if not enable_quartus_bugfix_c or + opc_opcode_s(3) = '0' then + address_indirect_3_f; + end if; + + -- store data from RAM to Temp Reg + when MSTATE4 => + and_or_xor_add_4_f; + + -- perform AND and store in Accumulator + when MSTATE5 => + and_or_xor_add_5_f(alu_op => ALU_AND); + + when others => + null; + + end case; + + -- Mnemonic ANL_A_DATA -------------------------------------------------- + when MN_ANL_A_DATA => + assert_psen_s <= true; + + if clk_second_cycle_i then + case clk_mstate_i is + -- write Temp Reg when contents of Program Memory is on bus + when MSTATE1 => + alu_write_temp_reg_o <= true; + + -- perform AND and store in Accumulator + when MSTATE3 => + and_or_xor_add_5_f(alu_op => ALU_AND); + + when others => + null; + + end case; + + end if; + + -- Mnemonic ANL_EXT ----------------------------------------------------- + when MN_ANL_EXT => + assert_psen_s <= true; + + if not clk_second_cycle_i then + -- read port to Temp Reg + if clk_mstate_i = MSTATE5 then + if opc_opcode_s(1 downto 0) = "00" then + add_read_bus_s <= true; + elsif opc_opcode_s(1) = '0' then + p1_read_p1_o <= true; + p1_read_reg_o <= true; + else + p2_read_p2_o <= true; + p2_read_reg_o <= true; + end if; + + alu_write_temp_reg_o <= true; + end if; + + else + case clk_mstate_i is + -- write shadow Accumulator when contents of Program Memory is + -- on bus + when MSTATE1 => + alu_write_shadow_o <= true; + + -- loop shadow Accumulator through ALU to prevent update from + -- real Accumulator + when MSTATE2 => + alu_read_alu_o <= true; + alu_write_shadow_o <= true; + + -- write result of AND operation back to port + when MSTATE3 => + alu_op_o <= ALU_AND; + alu_read_alu_o <= true; + + if opc_opcode_s(1 downto 0) = "00" then + bus_write_bus_o <= true; + elsif opc_opcode_s(1) = '0' then + p1_write_p1_o <= true; + else + p2_write_p2_o <= true; + end if; + + when others => + null; + + end case; + + end if; + + -- Mnemonic CALL -------------------------------------------------------- + when MN_CALL => + assert_psen_s <= true; + + if not clk_second_cycle_i then + case clk_mstate_i is + -- read Stack Pointer and address Data Memory for low byte + -- also increment Program Counter to point to next instruction + when MSTATE3 => + psw_read_sp_o <= true; + dm_write_dmem_addr_o <= true; + dm_addr_type_o <= DM_STACK; + + -- only increment PC if this is not an injected CALL + -- injected CALLS are not located in Program Memory, + -- the PC points already to the instruction to be executed + -- after the interrupt + if not int_pending_s then + add_inc_pc_s <= true; + end if; + + -- store Program Counter low byte on stack + when MSTATE4 => + pm_read_pcl_o <= true; + dm_write_dmem_s <= true; + + -- store Program Counter high byte and PSW on stack + -- increment Stack pointer + when MSTATE5 => + psw_read_psw_o <= true; + pm_read_pch_o <= true; + dm_write_dmem_addr_o <= true; + dm_addr_type_o <= DM_STACK_HIGH; + dm_write_dmem_s <= true; + psw_inc_stackp_o <= true; + + when others => + null; + + end case; + + else + case clk_mstate_i is + -- store address in Program Counter low byte + when MSTATE1 => + pm_write_pcl_o <= true; + branch_taken_s <= true; + if int_pending_s then + -- apply low part of vector address manually + data_s <= (others => '0'); + data_s(1 downto 0) <= "11"; + if tim_int_s then + data_s(2) <= '1'; + end if; + read_dec_s <= true; + end if; + + when MSTATE2 => + pm_write_pch_o <= true; + read_dec_s <= true; + if not int_pending_s then + -- store high part of target address in Program Counter + data_s <= "0000" & mb_v & opc_opcode_s(7 downto 5); + else + -- apply high part of vector address manually + data_s <= (others => '0'); + int_executed_s <= true; + end if; + + when others => + null; + + end case; + + end if; + + -- Mnemonic CLR_A ------------------------------------------------------- + when MN_CLR_A => + -- write CLR output of ALU to Accumulator + if clk_mstate_i = MSTATE3 then + alu_op_o <= ALU_CLR; + alu_read_alu_o <= true; + alu_write_accu_o <= true; + end if; + + -- Mnemonic CLR_C ------------------------------------------------------- + when MN_CLR_C => + -- store 0 to Carry + if clk_mstate_i = MSTATE3 then + psw_special_data_o <= '0'; + psw_write_carry_o <= true; + end if; + + -- Mnemonic CLR_F ------------------------------------------------------- + when MN_CLR_F => + -- store 0 to selected flag + if clk_mstate_i = MSTATE3 then + if opc_opcode_s(5) = '0' then + psw_special_data_o <= '0'; + psw_write_f0_o <= true; + else + clear_f1_s <= true; + end if; + + end if; + + -- Mnemonic CPL_A ------------------------------------------------------- + when MN_CPL_A => + -- write CPL output of ALU to Accumulator + if clk_mstate_i = MSTATE3 then + alu_op_o <= ALU_CPL; + alu_read_alu_o <= true; + alu_write_accu_o <= true; + end if; + + -- Mnemnonic CPL_C ------------------------------------------------------ + when MN_CPL_C => + -- write inverse of Carry to PSW + if clk_mstate_i = MSTATE3 then + psw_special_data_o <= not psw_carry_i; + psw_write_carry_o <= true; + end if; + + -- Mnemonic CPL_F ------------------------------------------------------- + when MN_CPL_f => + -- write inverse of selected flag back to flag + if clk_mstate_i = MSTATE3 then + if opc_opcode_s(5) = '0' then + psw_special_data_o <= not psw_f0_i; + psw_write_f0_o <= true; + else + cpl_f1_s <= true; + end if; + + end if; + + -- Mnemonic DA ---------------------------------------------------------- + when MN_DA => + alu_op_o <= ALU_ADD; + + case clk_mstate_i is + -- Step 1: Preload Temp Reg with 0x06 + when MSTATE3 => + alu_p06_temp_reg_o <= true; + + -- Step 2: Check Auxiliary Carry and overflow on low nibble + -- Add 0x06 to shadow Accumulator if one is true + when MSTATE4 => + if psw_aux_carry_i = '1' or alu_da_overflow_i then + alu_read_alu_o <= true; + alu_write_shadow_o <= true; + end if; + + -- preload Temp Reg with 0x60 + alu_p60_temp_reg_o <= true; + + -- Step 3: Check overflow on high nibble + -- Add 0x60 to shadow Accumulator if true and store result + -- in Accumulator and PSW (only Carry) + when MSTATE5 => + alu_da_high_o <= true; + + if alu_da_overflow_i then + psw_special_data_o <= alu_carry_i; + else + alu_op_o <= ALU_NOP; + psw_special_data_o <= '0'; + end if; + alu_read_alu_o <= true; + alu_write_accu_o <= true; + psw_write_carry_o <= true; + + when others => + null; + + end case; + + -- Mnemonic DEC --------------------------------------------------------- + when MN_DEC => + case clk_mstate_i is + when MSTATE4 => + -- DEC Rr: store data from RAM to shadow Accumulator + if opc_opcode_s(6) = '1' then + dm_read_dmem_o <= true; + alu_write_shadow_o <= true; + end if; + + when MSTATE5 => + alu_op_o <= ALU_DEC; + alu_read_alu_o <= true; + + if opc_opcode_s(6) = '0' then + -- write DEC of Accumulator to Accumulator + alu_write_accu_o <= true; + else + -- store DEC of shadow Accumulator back to dmem + dm_write_dmem_s <= true; + end if; + + when others => + null; + + end case; + + -- Mnemonic DIS_EN_I ---------------------------------------------------- + when MN_DIS_EN_I => + if clk_mstate_i = MSTATE3 then + if opc_opcode_s(4) = '1' then + dis_i_s <= true; + else + en_i_s <= true; + end if; + end if; + + -- Mnemonic DIS_EN_TCNTI ------------------------------------------------ + when MN_DIS_EN_TCNTI => + if clk_mstate_i = MSTATE3 then + if opc_opcode_s(4) = '1' then + dis_tcnti_s <= true; + else + en_tcnti_s <= true; + end if; + end if; + + -- Mnemonic DJNZ -------------------------------------------------------- + when MN_DJNZ => + assert_psen_s <= true; + + if not clk_second_cycle_i then + case clk_mstate_i is + -- store data from RAM to shadow Accumulator + when MSTATE4 => + dm_read_dmem_o <= true; + alu_write_shadow_o <= true; + + -- write DEC result of shadow Accumulator back to dmem and + -- conditional branch logic + when MSTATE5 => + alu_op_o <= ALU_DEC; + alu_read_alu_o <= true; + dm_write_dmem_s <= true; + + cnd_compute_take_o <= true; + cnd_branch_cond_o <= COND_Z; + cnd_comp_value_o(0) <= '0'; + + when others => + null; + + end case; + + else + -- store address in Program Counter low byte if branch has to + -- be taken + if clk_mstate_i = MSTATE1 and cnd_take_branch_i then + cond_jump_c2_m1_f; + end if; + + end if; + + -- Mnemonic ENT0_CLK ---------------------------------------------------- + when MN_ENT0_CLK => + if clk_mstate_i = MSTATE3 then + ent0_clk_s <= true; + end if; + + -- Mnemonic IN ---------------------------------------------------------- + when MN_IN => + -- read Port and store in Accumulator + if clk_second_cycle_i and clk_mstate_i = MSTATE2 then + alu_write_accu_o <= true; + + if opc_opcode_s(1) = '0' then + p1_read_p1_o <= true; + else + p2_read_p2_o <= true; + end if; + end if; + + -- Mnemonic INS --------------------------------------------------------- + when MN_INS => + clk_assert_rd_o <= true; + + -- read BUS and store in Accumulator + if clk_second_cycle_i and clk_mstate_i = MSTATE2 then + alu_write_accu_o <= true; + + add_read_bus_s <= true; + end if; + + -- Mnemonic INC --------------------------------------------------------- + when MN_INC => + case clk_mstate_i is + -- read RAM once for indirect address mode + when MSTATE3 => + if not enable_quartus_bugfix_c or + opc_opcode_s(3) = '0' then + address_indirect_3_f; + end if; + + when MSTATE4 => + -- INC Rr; INC @ Rr: store data from RAM to shadow Accumulator + if opc_opcode_s(3 downto 2) /= "01" then + dm_read_dmem_o <= true; + alu_write_shadow_o <= true; + end if; + + when MSTATE5 => + alu_op_o <= ALU_INC; + alu_read_alu_o <= true; + + if opc_opcode_s(3 downto 2) = "01" then + -- write INC output of ALU to Accumulator + alu_write_accu_o <= true; + else + -- store INC of shadow Accumulator back to dmem + dm_write_dmem_s <= true; + end if; + + when others => + null; + + end case; + + -- Mnemonic JBB --------------------------------------------------------- + when MN_JBB => + assert_psen_s <= true; + cnd_branch_cond_o <= COND_ON_BIT; + + if not clk_second_cycle_i then + -- read Accumulator and start branch calculation + if clk_mstate_i = MSTATE3 then + alu_read_alu_o <= true; + cnd_compute_take_o <= true; + -- cnd_comp_value_o is ok by default assignment + end if; + + else + -- store address in Program Counter low byte if branch has to + -- be taken + if clk_mstate_i = MSTATE1 and cnd_take_branch_i then + cond_jump_c2_m1_f; + end if; + + end if; + + -- Mnemonic JC ---------------------------------------------------------- + when MN_JC => + assert_psen_s <= true; + cnd_branch_cond_o <= COND_C; + + if not clk_second_cycle_i then + -- start branch calculation + if clk_mstate_i = MSTATE3 then + cnd_compute_take_o <= true; + cnd_comp_value_o(0) <= opc_opcode_s(4); + end if; + + else + -- store address in Program Counter low byte if branch has to + -- be taken + if clk_mstate_i = MSTATE1 and cnd_take_branch_i then + cond_jump_c2_m1_f; + end if; + + end if; + + -- Mnemonic JF ---------------------------------------------------------- + when MN_JF => + assert_psen_s <= true; + + if not clk_second_cycle_i then + -- start branch calculation + if clk_mstate_i = MSTATE3 then + cnd_compute_take_o <= true; + if opc_opcode_s(7) = '1' then + -- JF0 + cnd_branch_cond_o <= COND_F0; + else + -- JF1 + cnd_branch_cond_o <= COND_F1; + end if; + + end if; + + else + -- store address in Program Counter low byte if branch has to + -- be taken + if clk_mstate_i = MSTATE1 and cnd_take_branch_i then + cond_jump_c2_m1_f; + end if; + + end if; + + + -- Mnemonic JMP --------------------------------------------------------- + when MN_JMP => + assert_psen_s <= true; + + if clk_second_cycle_i then + case clk_mstate_i is + -- store address in Program Counter low byte + when MSTATE1 => + pm_write_pcl_o <= true; + branch_taken_s <= true; + + -- store high part of target address in Program Counter + when MSTATE2 => + data_s <= "0000" & mb_v & opc_opcode_s(7 downto 5); + read_dec_s <= true; + pm_write_pch_o <= true; + + when others => + null; + + end case; + + end if; + + -- Mnemonic JMPP -------------------------------------------------------- + when MN_JMPP => + assert_psen_s <= true; + + if not clk_second_cycle_i then + -- write Accumulator to Program Memory address + -- (skip page offset update from Program Counter) + if clk_mstate_i = MSTATE3 then + alu_read_alu_o <= true; + pm_addr_type_o <= PM_PAGE; + end if; + + else + if clk_mstate_i = MSTATE1 then + -- store address in Program Counter low byte + pm_write_pcl_o <= true; + branch_taken_s <= true; + end if; + + end if; + + -- Mnemonic JNI --------------------------------------------------------- + when MN_JNI => + assert_psen_s <= true; + cnd_branch_cond_o <= COND_INT; + + if not clk_second_cycle_i then + -- start branch calculation + if clk_mstate_i = MSTATE3 then + cnd_compute_take_o <= true; + end if; + + else + -- store address in Program Counter low byte if branch has to + -- be taken + if clk_mstate_i = MSTATE1 and cnd_take_branch_i then + cond_jump_c2_m1_f; + end if; + + end if; + + -- Mnemonic JT ---------------------------------------------------------- + when MN_JT => + assert_psen_s <= true; + if opc_opcode_s(6) = '0' then + cnd_branch_cond_o <= COND_T0; + else + cnd_branch_cond_o <= COND_T1; + end if; + + if not clk_second_cycle_i then + -- start branch calculation + if clk_mstate_i = MSTATE3 then + cnd_compute_take_o <= true; + cnd_comp_value_o(0) <= opc_opcode_s(4); + end if; + + else + -- store address in Program Counter low byte if branch has to + -- be taken + if clk_mstate_i = MSTATE1 and cnd_take_branch_i then + cond_jump_c2_m1_f; + end if; + + end if; + + -- Mnemonic JTF --------------------------------------------------------- + when MN_JTF => + assert_psen_s <= true; + cnd_branch_cond_o <= COND_TF; + + if not clk_second_cycle_i then + -- start branch calculation + if clk_mstate_i = MSTATE3 then + cnd_compute_take_o <= true; + jtf_executed_s <= true; + end if; + + else + -- store address in Program Counter low byte if branch has to + -- be taken + if clk_mstate_i = MSTATE1 and cnd_take_branch_i then + cond_jump_c2_m1_f; + end if; + + end if; + + -- Mnemonic JZ ---------------------------------------------------------- + when MN_JZ => + assert_psen_s <= true; + cnd_branch_cond_o <= COND_Z; + + if not clk_second_cycle_i then + -- read Accumulator and start branch calculation + if clk_mstate_i = MSTATE3 then + alu_read_alu_o <= true; + cnd_compute_take_o <= true; + cnd_comp_value_o(0) <= opc_opcode_s(6); + end if; + + else + -- store address in Program Counter low byte if branch has to + -- be taken + if clk_mstate_i = MSTATE1 and cnd_take_branch_i then + cond_jump_c2_m1_f; + end if; + + end if; + + -- Mnemonic MOV_A_DATA -------------------------------------------------- + when MN_MOV_A_DATA => + assert_psen_s <= true; + + -- Write Accumulator when contents of Program Memory is on bus + -- during machine state 1 of second cycle. + if clk_second_cycle_i and clk_mstate_i = MSTATE1 then + alu_write_accu_o <= true; + end if; + + -- Mnemonic MOV_A_RR ---------------------------------------------------- + when MN_MOV_A_RR => + case clk_mstate_i is + -- read RAM once for indirect address mode + when MSTATE3 => + if not enable_quartus_bugfix_c or + opc_opcode_s(3) = '0' then + address_indirect_3_f; + end if; + + -- read data from RAM and store in Accumulator + when MSTATE4 => + and_or_xor_add_4_f; + alu_write_accu_o <= true; + + when others => + null; + + end case; + + -- Mnemonic MOV_A_PSW --------------------------------------------------- + when MN_MOV_A_PSW => + if clk_mstate_i = MSTATE3 then + psw_read_psw_o <= true; + psw_read_sp_o <= true; + alu_write_accu_o <= true; + end if; + + -- Mnemoniv MOV_PSW_A --------------------------------------------------- + when MN_MOV_PSW_A => + if clk_mstate_i = MSTATE3 then + alu_read_alu_o <= true; + psw_write_psw_o <= true; + psw_write_sp_o <= true; + end if; + + -- Mnemonic MOV_RR ------------------------------------------------------ + when MN_MOV_RR => + case clk_mstate_i is + -- read RAM once for indirect address mode + when MSTATE3 => + if not enable_quartus_bugfix_c or + opc_opcode_s(3) = '0' then + address_indirect_3_f; + end if; + + -- write Accumulator to dmem + when MSTATE5 => + alu_read_alu_o <= true; + dm_write_dmem_s <= true; + + when others => + null; + + end case; + + -- Mnemonic MOV_RR_DATA ------------------------------------------------- + when MN_MOV_RR_DATA => + assert_psen_s <= true; + + -- read RAM once for indirect address mode + if not clk_second_cycle_i and clk_mstate_i = MSTATE3 then + if not enable_quartus_bugfix_c or + opc_opcode_s(3) = '0' then + address_indirect_3_f; + end if; + end if; + + -- Write Data Memory when contents of Program Memory is on bus + -- during machine state 1 of second cycle. + if clk_second_cycle_i and clk_mstate_i = MSTATE1 then + dm_write_dmem_s <= true; + end if; + + -- Mnemonic MOV_T ------------------------------------------------------- + when MN_MOV_T => + if clk_mstate_i = MSTATE3 then + if opc_opcode_s(5) = '1' then + alu_read_alu_o <= true; -- MOV T, A + tim_write_timer_o <= true; + else + tim_read_timer_o <= true; -- MOV A, T + alu_write_accu_o <= true; + end if; + end if; + + -- Mnemonic OUTD_PP_A --------------------------------------------------- + when MN_OUTD_PP_A => + clk_assert_prog_o <= true; + + if not clk_second_cycle_i then + case clk_mstate_i is + -- propagate expander port number to Port 2 + when MSTATE3 => + + data_s(7 downto 4) <= (others => '0'); + data_s(1 downto 0) <= opc_opcode_s(1 downto 0); + -- decide which 8243 command to use + case opc_opcode_s(7 downto 4) is + when "1001" => + data_s(3 downto 2) <= "11"; -- ANLD command + when "1000" => + data_s(3 downto 2) <= "10"; -- ORLD command + when "0011" => + data_s(3 downto 2) <= "01"; -- MOVD command + when others => + null; + end case; + + read_dec_s <= true; + p2_write_exp_o <= true; + + -- output expander port number on Port 2 while active edge of PROG + -- write Accumulator to expander port + when MSTATE4 => + p2_output_exp_s <= true; + + alu_read_alu_o <= true; + p2_write_exp_o <= true; + + when MSTATE5 => + p2_output_exp_s <= true; + + when others => + null; + + end case; + + else + -- hold expander port until inactive edge of PROG + if clk_mstate_i = MSTATE1 or clk_mstate_i = MSTATE2 then + p2_output_exp_s <= true; + end if; + + end if; + + -- Mnemonic MOVD_A_PP --------------------------------------------------- + when MN_MOVD_A_PP => + clk_assert_prog_o <= true; + + if not clk_second_cycle_i then + case clk_mstate_i is + -- propagate expander port number to Port 2 + when MSTATE3 => + data_s <= "0000" & + "00" & -- 8243 command: read + opc_opcode_s(1 downto 0); + read_dec_s <= true; + p2_write_exp_o <= true; + + -- output expander port number on Port 2 while active edge of PROG + -- write 1's to expander port to set lower nibble of Port 2 to input + when MSTATE4 => + p2_output_exp_s <= true; + + data_s(nibble_t'range) <= (others => '1'); + read_dec_s <= true; + p2_write_exp_o <= true; + + when MSTATE5 => + p2_output_exp_s <= true; + + when others => + null; + + end case; + + else + case clk_mstate_i is + -- hold expander port until inactive edge of PROG + when MSTATE1 => + p2_output_exp_s <= true; + + -- hold expander port until inactive edge of PROG + -- write Accumulator with nibble of expander port + when MSTATE2 => + p2_read_p2_o <= true; + p2_output_exp_s <= true; + p2_read_exp_o <= true; + alu_write_accu_o <= true; + + when others => + null; + + end case; + + end if; + + -- Mnemonic MOVP -------------------------------------------------------- + when MN_MOVP => + assert_psen_s <= true; + + if not clk_second_cycle_i then + -- write Accumulator to Program Memory address + -- (skip page offset update from Program Counter) + if clk_mstate_i = MSTATE3 then + alu_read_alu_o <= true; + if opc_opcode_s(6) = '0' then + pm_addr_type_o <= PM_PAGE; + else + pm_addr_type_o <= PM_PAGE3; + end if; + end if; + + else + if clk_mstate_i = MSTATE1 then + -- store data from Program Memory in Accumulator + alu_write_accu_o <= true; + -- trick & treat to prevent additional PC increment + -- our branch target is the previously incremented PC! + branch_taken_s <= true; + end if; + + end if; + + -- Mnemonic MOVX -------------------------------------------------------- + when MN_MOVX => + bus_bidir_bus_o <= true; + + if opc_opcode_s(4) = '0' then + clk_assert_rd_o <= true; + else + clk_assert_wr_o <= true; + end if; + + if not clk_second_cycle_i then + movx_first_cycle_s <= true; + case clk_mstate_i is + -- read dmem and put contents on BUS as external address + when MSTATE3 => + dm_read_dmem_o <= true; + bus_write_bus_o <= true; + + -- store contents of Accumulator to BUS + when MSTATE5 => + if opc_opcode_s(4) = '1' then + alu_read_alu_o <= true; + bus_write_bus_o <= true; + end if; + + when others => + null; + end case; + + else + if clk_mstate_i = MSTATE2 then + if opc_opcode_s(4) = '0' then + -- store contents of BUS in Accumulator + add_read_bus_s <= true; + alu_write_accu_o <= true; + else + -- store contents of Accumulator to BUS + -- to this to keep bus in output direction + alu_read_alu_o <= true; + bus_write_bus_o <= true; + end if; + end if; + + end if; + + -- Mnemonic NOP --------------------------------------------------------- + when MN_NOP => + -- nothing to do + + -- Mnemonic ORL --------------------------------------------------------- + when MN_ORL => + case clk_mstate_i is + -- read RAM once for indirect address mode + when MSTATE3 => + if not enable_quartus_bugfix_c or + opc_opcode_s(3) = '0' then + address_indirect_3_f; + end if; + + -- store data from RAM to Temp Reg + when MSTATE4 => + and_or_xor_add_4_f; + + -- perform OR and store in Accumulator + when MSTATE5 => + and_or_xor_add_5_f(alu_op => ALU_OR); + + when others => + null; + + end case; + + -- Mnemonic ORL_A_DATA -------------------------------------------------- + when MN_ORL_A_DATA => + assert_psen_s <= true; + + if clk_second_cycle_i then + case clk_mstate_i is + -- write Temp Reg when contents of Program Memory is on bus + when MSTATE1 => + alu_write_temp_reg_o <= true; + + -- perform OR and store in Accumulator + when MSTATE3 => + and_or_xor_add_5_f(alu_op => ALU_OR); + + when others => + null; + + end case; + + end if; + + -- Mnemonic ORL_EXT ----------------------------------------------------- + when MN_ORL_EXT => + assert_psen_s <= true; + + if not clk_second_cycle_i then + -- read port to Temp Reg + if clk_mstate_i = MSTATE5 then + if opc_opcode_s(1 downto 0) = "00" then + add_read_bus_s <= true; + elsif opc_opcode_s(1) = '0' then + p1_read_p1_o <= true; + p1_read_reg_o <= true; + else + p2_read_p2_o <= true; + p2_read_reg_o <= true; + end if; + + alu_write_temp_reg_o <= true; + end if; + + else + case clk_mstate_i is + -- write shadow Accumulator when contents of Program Memory is + -- on bus + when MSTATE1 => + alu_write_shadow_o <= true; + + -- loop shadow Accumulator through ALU to prevent update from + -- real Accumulator + when MSTATE2 => + alu_read_alu_o <= true; + alu_write_shadow_o <= true; + + -- write result of OR operation back to port + when MSTATE3 => + alu_op_o <= ALU_OR; + alu_read_alu_o <= true; + + if opc_opcode_s(1 downto 0) = "00" then + bus_write_bus_o <= true; + elsif opc_opcode_s(1) = '0' then + p1_write_p1_o <= true; + else + p2_write_p2_o <= true; + end if; + + when others => + null; + + end case; + + end if; + + -- Mnemonic OUTL_EXT ---------------------------------------------------- + when MN_OUTL_EXT => + if opc_opcode_s(4) = '0' then + clk_assert_wr_o <= true; + end if; + + -- read Accumulator and store in Port/BUS output register + if not clk_second_cycle_i and clk_mstate_i = MSTATE4 then + alu_read_alu_o <= true; + + if opc_opcode_s(4) = '1' then + if opc_opcode_s(1) = '0' then + p1_write_p1_o <= true; + else + p2_write_p2_o <= true; + end if; + + else + bus_write_bus_o <= true; + + end if; + + end if; + + -- Mnemonic RET --------------------------------------------------------- + when MN_RET => + if not clk_second_cycle_i then + case clk_mstate_i is + -- decrement Stack Pointer + when MSTATE3 => + psw_dec_stackp_o <= true; + + -- read Stack Pointer and address Data Memory for low byte + when MSTATE4 => + psw_read_sp_o <= true; + dm_write_dmem_addr_o <= true; + dm_addr_type_o <= DM_STACK; + + -- read Data Memory and store to Program Counter low + -- prepare address to Data memory for high byte + when MSTATE5 => + dm_read_dmem_o <= true; + pm_write_pcl_o <= true; + dm_write_dmem_addr_o <= true; + dm_addr_type_o <= DM_STACK_HIGH; + + when others => + null; + + end case; + + else + case clk_mstate_i is + -- read Data Memory and store to Program Counter high and PSW + when MSTATE1 => + dm_read_dmem_o <= true; + pm_write_pch_o <= true; + if opc_opcode_s(4) = '1' then + psw_write_psw_o <= true; + retr_executed_s <= true; + end if; + + when MSTATE2 => + add_write_pmem_addr_s <= true; + + when others => + null; + + end case; + + end if; + + -- Mnemonic RL ---------------------------------------------------------- + when MN_RL => + if clk_mstate_i = MSTATE3 then + alu_op_o <= ALU_RL; + alu_read_alu_o <= true; + alu_write_accu_o <= true; + + if opc_opcode_s(4) = '1' then + psw_special_data_o <= alu_carry_i; + psw_write_carry_o <= true; + alu_use_carry_o <= true; + end if; + end if; + + -- Mnemonic RR ---------------------------------------------------------- + when MN_RR => + if clk_mstate_i = MSTATE3 then + alu_op_o <= ALU_RR; + alu_read_alu_o <= true; + alu_write_accu_o <= true; + + if opc_opcode_s(4) = '0' then + psw_special_data_o <= alu_carry_i; + psw_write_carry_o <= true; + alu_use_carry_o <= true; + end if; + end if; + + -- Mnemonic SEL_MB ------------------------------------------------------ + when MN_SEL_MB => + if clk_mstate_i = MSTATE3 then + if opc_opcode_s(4) = '1' then + set_mb_s <= true; + else + clear_mb_s <= true; + end if; + end if; + + -- Mnemonic SEL_RB ------------------------------------------------------ + when MN_SEL_RB => + if clk_mstate_i = MSTATE3 then + psw_special_data_o <= opc_opcode_s(4); + psw_write_bs_o <= true; + end if; + + -- Mnemonic STOP_TCNT --------------------------------------------------- + when MN_STOP_TCNT => + if clk_mstate_i = MSTATE3 then + tim_stop_tcnt_o <= true; + end if; + + -- Mnemonic STRT -------------------------------------------------------- + when MN_STRT => + if clk_mstate_i = MSTATE3 then + if opc_opcode_s(4) = '1' then + tim_start_t_o <= true; + else + tim_start_cnt_o <= true; + end if; + end if; + + -- Mnemonic SWAP -------------------------------------------------------- + when MN_SWAP => + alu_op_o <= ALU_SWAP; + + if clk_mstate_i = MSTATE3 then + alu_read_alu_o <= true; + alu_write_accu_o <= true; + end if; + + -- Mnemonic XCH --------------------------------------------------------- + when MN_XCH => + case clk_mstate_i is + -- read RAM once for indirect address mode + when MSTATE3 => + if not enable_quartus_bugfix_c or + opc_opcode_s(3) = '0' then + address_indirect_3_f; + end if; + + -- store data from RAM in Accumulator and Temp Reg + -- Accumulator is already shadowed! + when MSTATE4 => + dm_read_dmem_o <= true; + alu_write_accu_o <= true; + alu_write_temp_reg_o <= true; + if opc_opcode_s(4) = '1' then + -- XCHD + -- only write lower nibble of Accumulator + alu_accu_low_o <= true; + end if; + + -- store data from shadow (previous) Accumulator to dmem + when MSTATE5 => + dm_write_dmem_s <= true; + alu_read_alu_o <= true; + if opc_opcode_s(4) = '1' then + -- XCHD + -- concatenate shadow Accumulator and Temp Reg + alu_op_o <= ALU_CONCAT; + end if; + + when others => + null; + + end case; + + -- Mnemonic XRL --------------------------------------------------------- + when MN_XRL => + case clk_mstate_i is + -- read RAM once for indirect address mode + when MSTATE3 => + if not enable_quartus_bugfix_c or + opc_opcode_s(3) = '0' then + address_indirect_3_f; + end if; + + -- store data from RAM to Temp Reg + when MSTATE4 => + and_or_xor_add_4_f; + + -- perform XOR and store in Accumulator + when MSTATE5 => + and_or_xor_add_5_f(alu_op => ALU_XOR); + + when others => + null; + + end case; + + -- Mnemonic XRL_A_DATA -------------------------------------------------- + when MN_XRL_A_DATA => + assert_psen_s <= true; + + if clk_second_cycle_i then + case clk_mstate_i is + -- write Temp Reg when contents of Program Memory is on bus + when MSTATE1 => + alu_write_temp_reg_o <= true; + + -- perform XOR and store in Accumulator + when MSTATE3 => + and_or_xor_add_5_f(alu_op => ALU_XOR); + + when others => + null; + + end case; + + end if; + + -- Unimplemented mnemonic ----------------------------------------------- + when others => + -- this will behave like a NOP + + -- pragma translate_off + assert false + report "Mnemonic not yet implemented." + severity warning; + -- pragma translate_on + + end case; + + end process decode; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process regs + -- + -- Purpose: + -- Implements the various registes. + -- + regs: process (res_i, clk_i) + begin + if res_i = res_active_c then + branch_taken_q <= false; + f1_q <= '0'; + mb_q <= '0'; + t0_dir_q <= '0'; + -- pragma translate_off + istrobe_res_q <= '1'; + istrobe_q <= '0'; + injected_int_q <= '0'; + -- pragma translate_on + + elsif clk_i'event and clk_i = clk_active_c then + if en_clk_i then + + -- branch taken flag + if branch_taken_s then + branch_taken_q <= true; + elsif clk_mstate_i = MSTATE5 then + -- release flag when new instruction starts + branch_taken_q <= false; + end if; + + -- Flag 1 + if clear_f1_s then + f1_q <= '0'; + elsif cpl_f1_s then + f1_q <= not f1_q; + end if; + + -- Memory Bank select + if clear_mb_s then + mb_q <= '0'; + elsif set_mb_s then + mb_q <= '1'; + end if; + + -- T0 direction selection + if ent0_clk_s then + t0_dir_q <= '1'; + end if; + + -- pragma translate_off + -- Marker for injected instruction ------------------------------------ + if opc_inj_int_s then + injected_int_q <= '1'; + elsif clk_mstate_i = MSTATE5 and last_cycle_s then + injected_int_q <= '0'; + end if; + + -- Remove istrobe after reset suppression ----------------------------- + if clk_mstate_i = MSTATE5 and last_cycle_s then + istrobe_res_q <= '0'; + end if; + -- pragma translate_on + + end if; + + -- pragma translate_off + -- Instruction Strobe --------------------------------------------------- + if clk_mstate_i = MSTATE5 and last_cycle_s and + injected_int_q = '0' then + if istrobe_res_q = '0' then + istrobe_q <= '1'; + end if; + else + istrobe_q <= '0'; + end if; + -- pragma translate_on + + end if; + + end process regs; + -- + ----------------------------------------------------------------------------- + + -- pragma translate_off + -- assign to global signal for testbench + tb_istrobe_s <= istrobe_q; + -- pragma translate_on + + + ----------------------------------------------------------------------------- + -- Output Mapping. + ----------------------------------------------------------------------------- + clk_multi_cycle_o <= opc_multi_cycle_s; + cnd_f1_o <= f1_q; + cnd_tf_o <= tf_s; + data_o <= data_s + when read_dec_s else + (others => bus_idle_level_c); + dm_write_dmem_o <= dm_write_dmem_s and en_clk_i; + pm_inc_pc_o <= pm_inc_pc_s or add_inc_pc_s; + pm_write_pmem_addr_o <= pm_write_pmem_addr_s or add_write_pmem_addr_s; + t0_dir_o <= t0_dir_q; + bus_read_bus_o <= bus_read_bus_s or add_read_bus_s; + +end rtl; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: decoder.vhd,v $ +-- Revision 1.24 2005/11/14 21:12:29 arniml +-- suppress p2_output_pch_o when MOVX operation is accessing the +-- external memory +-- +-- Revision 1.23 2005/11/07 19:25:01 arniml +-- fix sensitivity list +-- +-- Revision 1.22 2005/11/01 21:25:37 arniml +-- * suppress p2_output_pch_o when p2_output_exp is active +-- * wire xtal_i to interrupt module +-- +-- Revision 1.21 2005/10/31 10:08:33 arniml +-- Suppress assertion of bus_read_bus_s when interrupt is pending. +-- This should fix bug report +-- "PROBLEM WHEN INT AND JMP" +-- +-- Revision 1.20 2005/09/13 21:08:34 arniml +-- move check for int_pending_s into ea_i_='0' branch +-- this fixes a glitch on PCH when an interrutp occurs +-- during external program memory fetch +-- +-- Revision 1.19 2005/06/11 10:08:43 arniml +-- introduce prefix 't48_' for all packages, entities and configurations +-- +-- Revision 1.18 2005/06/09 22:18:28 arniml +-- Move latching of BUS to MSTATE2 +-- -> sample BUS at the end of RD' +-- +-- Revision 1.17 2005/05/09 22:26:08 arniml +-- remove obsolete output stack_high_o +-- +-- Revision 1.16 2004/10/25 19:39:24 arniml +-- Fix bug report: +-- "RD' and WR' not asserted for INS A, BUS and OUTL BUS, A" +-- rd is asserted for INS A, BUS +-- wr is asserted for OUTL BUS, A +-- P1, P2 and BUS are written in first instruction cycle +-- +-- Revision 1.15 2004/09/12 00:35:44 arniml +-- Fix bug report: +-- "PSENn Timing" +-- PSEN is now only asserted for the second cycle if explicitely +-- requested by assert_psen_s. +-- The previous implementation asserted PSEN together with RD or WR. +-- +-- Revision 1.14 2004/06/30 21:18:28 arniml +-- Fix bug report: +-- "Program Memory bank can be switched during interrupt" +-- int module emits int_in_progress signal that is used inside the decoder +-- to hold mb low for JMP and CALL during interrupts +-- +-- Revision 1.13 2004/05/20 21:51:40 arniml +-- clean-up use of ea_i +-- +-- Revision 1.12 2004/05/17 14:40:09 arniml +-- assert p2_read_p2_o when expander port is read +-- +-- Revision 1.11 2004/05/16 15:33:39 arniml +-- work around bug in Quartus II 4.0 +-- +-- Revision 1.10 2004/04/25 16:22:03 arniml +-- adjust external timing of BUS +-- +-- Revision 1.9 2004/04/24 11:22:55 arniml +-- removed superfluous signal from sensitivity list +-- +-- Revision 1.8 2004/04/18 18:57:43 arniml +-- + enhance instruction strobe generation +-- + rework address output under EA=1 conditions +-- +-- Revision 1.7 2004/04/15 22:06:05 arniml +-- + add marker for injected calls +-- + suppress intstruction strobes for injected calls +-- +-- Revision 1.6 2004/04/14 20:53:33 arniml +-- make istrobe visible through testbench package +-- +-- Revision 1.5 2004/04/07 22:09:03 arniml +-- remove unused signals +-- +-- Revision 1.4 2004/04/04 14:18:53 arniml +-- add measures to implement XCHD +-- +-- Revision 1.3 2004/03/28 21:15:48 arniml +-- implemented mnemonic DA +-- +-- Revision 1.2 2004/03/28 13:06:32 arniml +-- implement mnemonics: +-- + MOVD_A_PP +-- + OUTD_PP_A -> ANLD PP, A; MOVD PP, A; ORLD PP, A +-- +-- Revision 1.1 2004/03/23 21:31:52 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t48/rtl/vhdl/decoder_pack-p.vhd b/rtl/t48/rtl/vhdl/decoder_pack-p.vhd new file mode 100644 index 0000000..5051e3d --- /dev/null +++ b/rtl/t48/rtl/vhdl/decoder_pack-p.vhd @@ -0,0 +1,90 @@ +------------------------------------------------------------------------------- +-- +-- $Id: decoder_pack-p.vhd,v 1.3 2005/06/11 10:08:43 arniml Exp $ +-- +-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +package t48_decoder_pack is + + ----------------------------------------------------------------------------- + -- The Mnemonics. + ----------------------------------------------------------------------------- + type mnemonic_t is (MN_ADD, + MN_ADD_A_DATA, + MN_ANL, + MN_ANL_A_DATA, + MN_ANL_EXT, + MN_CALL, + MN_CLR_A, + MN_CLR_C, + MN_CLR_F, + MN_CPL_A, + MN_CPL_C, + MN_CPL_F, + MN_DA, + MN_DEC, + MN_DIS_EN_I, + MN_DIS_EN_TCNTI, + MN_DJNZ, + MN_ENT0_CLK, + MN_IN, + MN_INC, + MN_INS, + MN_JBB, + MN_JC, + MN_JF, + MN_JMP, + MN_JMPP, + MN_JNI, + MN_JT, + MN_JTF, + MN_JZ, + MN_MOV_A_DATA, + MN_MOV_A_PSW, + MN_MOV_A_RR, + MN_MOV_PSW_A, + MN_MOV_RR, + MN_MOV_RR_DATA, + MN_MOV_T, + MN_MOVD_A_PP, + MN_MOVP, + MN_MOVX, + MN_NOP, + MN_ORL, + MN_ORL_A_DATA, + MN_ORL_EXT, + MN_OUTD_PP_A, + MN_OUTL_EXT, + MN_RET, + MN_RL, + MN_RR, + MN_SEL_MB, + MN_SEL_RB, + MN_STOP_TCNT, + MN_STRT, + MN_SWAP, + MN_XCH, + MN_XRL, + MN_XRL_A_DATA); + +end t48_decoder_pack; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: decoder_pack-p.vhd,v $ +-- Revision 1.3 2005/06/11 10:08:43 arniml +-- introduce prefix 't48_' for all packages, entities and configurations +-- +-- Revision 1.2 2004/03/28 13:09:53 arniml +-- merge MN_ANLD, MN_MOVD_PP_A and MN_ORLD_PP_A to OUTLD_PP_A +-- +-- Revision 1.1 2004/03/23 21:31:52 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t48/rtl/vhdl/dmem_ctrl-c.vhd b/rtl/t48/rtl/vhdl/dmem_ctrl-c.vhd new file mode 100644 index 0000000..c82948c --- /dev/null +++ b/rtl/t48/rtl/vhdl/dmem_ctrl-c.vhd @@ -0,0 +1,19 @@ +------------------------------------------------------------------------------- +-- +-- The Data Memory control unit. +-- All accesses to the Data Memory are managed here. +-- +-- $Id: dmem_ctrl-c.vhd,v 1.2 2005/06/11 10:08:43 arniml Exp $ +-- +-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +configuration t48_dmem_ctrl_rtl_c0 of t48_dmem_ctrl is + + for rtl + end for; + +end t48_dmem_ctrl_rtl_c0; diff --git a/rtl/t48/rtl/vhdl/dmem_ctrl.vhd b/rtl/t48/rtl/vhdl/dmem_ctrl.vhd new file mode 100644 index 0000000..0420c76 --- /dev/null +++ b/rtl/t48/rtl/vhdl/dmem_ctrl.vhd @@ -0,0 +1,219 @@ +------------------------------------------------------------------------------- +-- +-- The Data Memory control unit. +-- All accesses to the Data Memory are managed here. +-- +-- $Id: dmem_ctrl.vhd,v 1.4 2005/06/11 10:08:43 arniml Exp $ +-- +-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t48/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.t48_pack.dmem_addr_t; +use work.t48_pack.word_t; +use work.t48_dmem_ctrl_pack.dmem_addr_ident_t; + +entity t48_dmem_ctrl is + + port ( + -- Global Interface ------------------------------------------------------- + clk_i : in std_logic; + res_i : in std_logic; + en_clk_i : in boolean; + -- Control Interface ------------------------------------------------------ + data_i : in word_t; + write_dmem_addr_i : in boolean; + write_dmem_i : in boolean; + read_dmem_i : in boolean; + addr_type_i : in dmem_addr_ident_t; + bank_select_i : in std_logic; + data_o : out word_t; + -- Data Memory Interface -------------------------------------------------- + dmem_data_i : in word_t; + dmem_addr_o : out dmem_addr_t; + dmem_we_o : out std_logic; + dmem_data_o : out word_t + ); + +end t48_dmem_ctrl; + + +library ieee; +use ieee.numeric_std.all; + +use work.t48_pack.clk_active_c; +use work.t48_pack.res_active_c; +use work.t48_pack.bus_idle_level_c; +use work.t48_pack.to_stdLogic; + +use work.t48_dmem_ctrl_pack.all; + +architecture rtl of t48_dmem_ctrl is + + signal dmem_addr_s, + dmem_addr_q : dmem_addr_t; +begin + + ----------------------------------------------------------------------------- + -- Process addr_decode + -- + -- Purpose: + -- Decode/multiplex the address information for the Data Memory. + -- + addr_decode: process (data_i, + addr_type_i, + bank_select_i, + dmem_addr_q) + variable stack_addr_v : unsigned(5 downto 0); + begin + -- default assignment + dmem_addr_s <= dmem_addr_q; + stack_addr_v := (others => '0'); + + case addr_type_i is + when DM_PLAIN => + dmem_addr_s <= data_i; + + when DM_REG => + dmem_addr_s <= (others => '0'); + dmem_addr_s(2 downto 0) <= data_i(2 downto 0); + -- implement bank switching + if bank_select_i = '1' then + -- dmem address 24 - 31: access proper set + dmem_addr_s(4 downto 3) <= "11"; + end if; + + when DM_STACK => + -- build address from stack pointer + stack_addr_v(3 downto 1) := unsigned(data_i(2 downto 0)); + -- dmem address 8 - 23 + stack_addr_v := stack_addr_v + 8; + + dmem_addr_s <= (others => '0'); + dmem_addr_s(5 downto 0) <= std_logic_vector(stack_addr_v); + + when DM_STACK_HIGH => + dmem_addr_s(0) <= '1'; + + when others => + -- do nothing + + -- pragma translate_off + assert false + report "Unknown address type identification for Data Memory controller!" + severity error; + -- pragma translate_on + + end case; + + end process addr_decode; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process dmem_addr_reg + -- + -- Purpose: + -- Implements the Data Memory Address Register. + -- This register is necessary to hold the address during a write operation + -- as we cannot hold the address in the input register of the + -- synchronous RAM (no clock suppression/gating). + -- + dmem_addr_reg: process (res_i, clk_i) + begin + if res_i = res_active_c then + dmem_addr_q <= (others => '0'); + + elsif clk_i'event and clk_i = clk_active_c then + if en_clk_i then + + if write_dmem_addr_i then + dmem_addr_q <= dmem_addr_s; + end if; + + end if; + + end if; + + end process dmem_addr_reg; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Output mapping. + ----------------------------------------------------------------------------- + dmem_addr_o <= dmem_addr_s + when write_dmem_addr_i and en_clk_i else + dmem_addr_q; + + -- data from bus is fed through + dmem_data_o <= data_i; + + -- data to bus is enabled upon read request + data_o <= dmem_data_i + when read_dmem_i else + (others => bus_idle_level_c); + + -- write enable to Data Memory is fed through + dmem_we_o <= to_stdLogic(write_dmem_i); + +end rtl; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: dmem_ctrl.vhd,v $ +-- Revision 1.4 2005/06/11 10:08:43 arniml +-- introduce prefix 't48_' for all packages, entities and configurations +-- +-- Revision 1.3 2004/04/24 23:44:25 arniml +-- move from std_logic_arith to numeric_std +-- +-- Revision 1.2 2004/04/18 18:58:29 arniml +-- clean up sensitivity list +-- +-- Revision 1.1 2004/03/23 21:31:52 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t48/rtl/vhdl/dmem_ctrl_pack-p.vhd b/rtl/t48/rtl/vhdl/dmem_ctrl_pack-p.vhd new file mode 100644 index 0000000..3bde1b7 --- /dev/null +++ b/rtl/t48/rtl/vhdl/dmem_ctrl_pack-p.vhd @@ -0,0 +1,34 @@ +------------------------------------------------------------------------------- +-- +-- $Id: dmem_ctrl_pack-p.vhd,v 1.2 2005/06/11 10:08:43 arniml Exp $ +-- +-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +package t48_dmem_ctrl_pack is + + ----------------------------------------------------------------------------- + -- Address Type Identifier + ----------------------------------------------------------------------------- + type dmem_addr_ident_t is (DM_PLAIN, + DM_REG, + DM_STACK, + DM_STACK_HIGH); + +end t48_dmem_ctrl_pack; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: dmem_ctrl_pack-p.vhd,v $ +-- Revision 1.2 2005/06/11 10:08:43 arniml +-- introduce prefix 't48_' for all packages, entities and configurations +-- +-- Revision 1.1 2004/03/23 21:31:52 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t48/rtl/vhdl/int-c.vhd b/rtl/t48/rtl/vhdl/int-c.vhd new file mode 100644 index 0000000..6f7d4d8 --- /dev/null +++ b/rtl/t48/rtl/vhdl/int-c.vhd @@ -0,0 +1,17 @@ +------------------------------------------------------------------------------- +-- +-- The Interrupt Controller. +-- It collects the interrupt sources and notifies the decoder. +-- +-- $Id: int-c.vhd,v 1.2 2005/06/11 10:08:43 arniml Exp $ +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +configuration t48_int_rtl_c0 of t48_int is + + for rtl + end for; + +end t48_int_rtl_c0; diff --git a/rtl/t48/rtl/vhdl/int.vhd b/rtl/t48/rtl/vhdl/int.vhd new file mode 100644 index 0000000..bb5c2d7 --- /dev/null +++ b/rtl/t48/rtl/vhdl/int.vhd @@ -0,0 +1,284 @@ +------------------------------------------------------------------------------- +-- +-- The Interrupt Controller. +-- It collects the interrupt sources and notifies the decoder. +-- +-- $Id: int.vhd,v 1.6 2005/11/01 21:26:24 arniml Exp $ +-- +-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t48/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.t48_pack.mstate_t; + +entity t48_int is + + port ( + clk_i : in std_logic; + res_i : in std_logic; + en_clk_i : in boolean; + xtal_i : in std_logic; + clk_mstate_i : in mstate_t; + jtf_executed_i : in boolean; + tim_overflow_i : in boolean; + tf_o : out std_logic; + en_tcnti_i : in boolean; + dis_tcnti_i : in boolean; + int_n_i : in std_logic; + ale_i : in boolean; + last_cycle_i : in boolean; + en_i_i : in boolean; + dis_i_i : in boolean; + ext_int_o : out boolean; + tim_int_o : out boolean; + retr_executed_i : in boolean; + int_executed_i : in boolean; + int_pending_o : out boolean; + int_in_progress_o : out boolean + ); + +end t48_int; + + +use work.t48_pack.all; + +architecture rtl of t48_int is + + constant tim_int_c : std_logic := '0'; + constant ext_int_c : std_logic := '1'; + + type int_state_t is (IDLE, PENDING, INT); + + signal int_state_s, + int_state_q : int_state_t; + + signal timer_flag_q : boolean; + signal timer_overflow_q : boolean; + signal timer_int_enable_q : boolean; + signal int_q : boolean; + signal int_enable_q : boolean; + signal ale_q : boolean; + signal int_type_q : std_logic; + signal int_in_progress_q : boolean; + +begin + + ----------------------------------------------------------------------------- + -- Process nstate + -- + -- Purpose: + -- Determines the next state of the Interrupt controller FSM. + -- + nstate: process (int_state_q, + int_type_q, + int_in_progress_q, + int_executed_i, + retr_executed_i, + clk_mstate_i, + last_cycle_i) + begin + int_state_s <= int_state_q; + + case int_state_q is + when IDLE => + if int_in_progress_q and + last_cycle_i and clk_mstate_i = MSTATE5 then + int_state_s <= PENDING; + end if; + + when PENDING => + if int_executed_i then + int_state_s <= INT; + end if; + + when INT => + if retr_executed_i then + int_state_s <= IDLE; + end if; + + when others => + int_state_s <= IDLE; + + end case; + + end process nstate; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process regs + -- + -- Purpose: + -- Implement the various registers. + -- They are designed according Figure "Interrupt Logic" of + -- "The Single Component MCS-48 System". + -- + regs: process (res_i, clk_i) + begin + if res_i = res_active_c then + timer_flag_q <= false; + timer_overflow_q <= false; + timer_int_enable_q <= false; + int_enable_q <= false; + int_type_q <= '0'; + int_state_q <= IDLE; + int_in_progress_q <= false; + + elsif clk_i'event and clk_i = clk_active_c then + if en_clk_i then + + int_state_q <= int_state_s; + + if jtf_executed_i then + timer_flag_q <= false; + elsif tim_overflow_i then + timer_flag_q <= true; + end if; + + if (int_type_q = tim_int_c and int_executed_i) or + not timer_int_enable_q then + timer_overflow_q <= false; + elsif tim_overflow_i then + timer_overflow_q <= true; + end if; + + if dis_tcnti_i then + timer_int_enable_q <= false; + elsif en_tcnti_i then + timer_int_enable_q <= true; + end if; + + if dis_i_i then + int_enable_q <= false; + elsif en_i_i then + int_enable_q <= true; + end if; + + if retr_executed_i then + int_in_progress_q <= false; + elsif (int_q and int_enable_q) or + timer_overflow_q then + int_in_progress_q <= true; + if not int_in_progress_q then + int_type_q <= to_stdLogic(int_q and int_enable_q); + end if; + end if; + + end if; + + end if; + + end process regs; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process xtal_regs + -- + -- Purpose: + -- Implements the sequential registers clocked with XTAL. + -- + xtal_regs: process (res_i, xtal_i) + begin + if res_i = res_active_c then + int_q <= false; + ale_q <= false; + + elsif xtal_i'event and xtal_i = clk_active_c then + ale_q <= ale_i; + + if last_cycle_i and + ale_q and not ale_i then + int_q <= not to_boolean(int_n_i); + end if; + + + end if; + end process xtal_regs; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Output Mapping. + ----------------------------------------------------------------------------- + tf_o <= to_stdLogic(timer_flag_q); + ext_int_o <= int_type_q = ext_int_c; + tim_int_o <= int_type_q = tim_int_c; + int_pending_o <= int_state_q = PENDING; + int_in_progress_o <= int_in_progress_q and int_state_q /= IDLE; + +end rtl; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: int.vhd,v $ +-- Revision 1.6 2005/11/01 21:26:24 arniml +-- operate ale_q and int_q with xtal_i after shift of ALE assertion to XTAL3 +-- +-- Revision 1.5 2005/09/13 21:00:16 arniml +-- Fix bug reports: +-- "Target address of JMP to Program Memory Bank 1 corrupted by interrupt" +-- "Return address of CALL to Program Memory Bank 1 corrupted by interrupt" +-- int_in_progress_o was active one cycle before int_pending_o is +-- asserted. this confused the mb multiplexer which determines the state of +-- the memory bank selection flag +-- +-- Revision 1.4 2005/06/11 10:08:43 arniml +-- introduce prefix 't48_' for all packages, entities and configurations +-- +-- Revision 1.3 2004/07/11 16:51:33 arniml +-- cleanup copyright notice +-- +-- Revision 1.2 2004/06/30 21:18:28 arniml +-- Fix bug report: +-- "Program Memory bank can be switched during interrupt" +-- int module emits int_in_progress signal that is used inside the decoder +-- to hold mb low for JMP and CALL during interrupts +-- +-- Revision 1.1 2004/03/23 21:31:52 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t48/rtl/vhdl/opc_decoder-c.vhd b/rtl/t48/rtl/vhdl/opc_decoder-c.vhd new file mode 100644 index 0000000..d888898 --- /dev/null +++ b/rtl/t48/rtl/vhdl/opc_decoder-c.vhd @@ -0,0 +1,23 @@ +------------------------------------------------------------------------------- +-- +-- The Opcode Decoder. +-- Derives instruction mnemonics and multicycle information +-- using the OPC table unit. +-- +-- $Id: opc_decoder-c.vhd,v 1.2 2005/06/11 10:08:43 arniml Exp $ +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +configuration t48_opc_decoder_rtl_c0 of t48_opc_decoder is + + for rtl + + for opc_table_b: t48_opc_table + use configuration work.t48_opc_table_rtl_c0; + end for; + + end for; + +end t48_opc_decoder_rtl_c0; diff --git a/rtl/t48/rtl/vhdl/opc_decoder.vhd b/rtl/t48/rtl/vhdl/opc_decoder.vhd new file mode 100644 index 0000000..c002232 --- /dev/null +++ b/rtl/t48/rtl/vhdl/opc_decoder.vhd @@ -0,0 +1,182 @@ +------------------------------------------------------------------------------- +-- +-- The Opcode Decoder. +-- Derives instruction mnemonics and multicycle information +-- using the OPC table unit. +-- +-- $Id: opc_decoder.vhd,v 1.3 2005/06/11 10:08:43 arniml Exp $ +-- +-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t48/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.t48_pack.word_t; +use work.t48_decoder_pack.mnemonic_t; + +entity t48_opc_decoder is + + generic ( + -- store mnemonic in flip-flops (registered-out) + register_mnemonic_g : integer := 1 + ); + + port ( + -- Global Interface ------------------------------------------------------- + clk_i : in std_logic; + res_i : in std_logic; + en_clk_i : in boolean; + -- T48 Bus Interface ------------------------------------------------------ + data_i : in word_t; + read_bus_i : in boolean; + -- Decoder Interface ------------------------------------------------------ + inj_int_i : in boolean; + opcode_o : out word_t; + mnemonic_o : out mnemonic_t; + multi_cycle_o : out boolean + ); + +end t48_opc_decoder; + + +use work.t48_pack.clk_active_c; +use work.t48_pack.res_active_c; +use work.t48_pack.to_boolean; +--use work.decoder_pack.MN_NOP; +use work.t48_decoder_pack.all; + +use work.t48_comp_pack.t48_opc_table; + +architecture rtl of t48_opc_decoder is + + -- the opcode register + signal opcode_q : word_t; + + -- the mnemonic + signal mnemonic_s, + mnemonic_q : mnemonic_t; + + signal multi_cycle_s : std_logic; + +begin + + ----------------------------------------------------------------------------- + -- Verify the generics + ----------------------------------------------------------------------------- + + -- pragma translate_off + + -- Register Mnemonic -------------------------------------------------------- + assert (register_mnemonic_g = 1) or (register_mnemonic_g = 0) + report "register_mnemonic_g must be either 1 or 0!" + severity failure; + + -- pragma translate_on + + + ----------------------------------------------------------------------------- + -- Opcode Decoder Table + ----------------------------------------------------------------------------- + opc_table_b : t48_opc_table + port map ( + opcode_i => opcode_q, + multi_cycle_o => multi_cycle_s, + mnemonic_o => mnemonic_s + ); + + + ----------------------------------------------------------------------------- + -- Process regs + -- + -- Purpose: + -- Implements the opcode and mnemonic registers. + -- + regs: process (res_i, clk_i) + begin + if res_i = res_active_c then + opcode_q <= (others => '0'); -- NOP + mnemonic_q <= MN_NOP; + + elsif clk_i'event and clk_i = clk_active_c then + if en_clk_i then + + if read_bus_i then + opcode_q <= data_i; + elsif inj_int_i then + opcode_q <= "00010100"; + else + mnemonic_q <= mnemonic_s; + end if; + + end if; + + end if; + + end process regs; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Output Mapping. + ----------------------------------------------------------------------------- + opcode_o <= opcode_q; + multi_cycle_o <= to_boolean(multi_cycle_s); + mnemonic_o <= mnemonic_q + when register_mnemonic_g = 1 else + mnemonic_s; + +end rtl; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: opc_decoder.vhd,v $ +-- Revision 1.3 2005/06/11 10:08:43 arniml +-- introduce prefix 't48_' for all packages, entities and configurations +-- +-- Revision 1.2 2004/07/11 16:51:33 arniml +-- cleanup copyright notice +-- +-- Revision 1.1 2004/03/23 21:31:52 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t48/rtl/vhdl/opc_table-c.vhd b/rtl/t48/rtl/vhdl/opc_table-c.vhd new file mode 100644 index 0000000..96c1de9 --- /dev/null +++ b/rtl/t48/rtl/vhdl/opc_table-c.vhd @@ -0,0 +1,18 @@ +------------------------------------------------------------------------------- +-- +-- The Opcode Decoder Table. +-- Decodes the given opcode to instruction mnemonics. +-- Also derives the multicycle information. +-- +-- $Id: opc_table-c.vhd,v 1.2 2005/06/11 10:08:43 arniml Exp $ +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +configuration t48_opc_table_rtl_c0 of t48_opc_table is + + for rtl + end for; + +end t48_opc_table_rtl_c0; diff --git a/rtl/t48/rtl/vhdl/opc_table.vhd b/rtl/t48/rtl/vhdl/opc_table.vhd new file mode 100644 index 0000000..883f488 --- /dev/null +++ b/rtl/t48/rtl/vhdl/opc_table.vhd @@ -0,0 +1,425 @@ +------------------------------------------------------------------------------- +-- +-- The Opcode Decoder Table. +-- Decodes the given opcode to instruction mnemonics. +-- Also derives the multicycle information. +-- +-- $Id: opc_table.vhd,v 1.4 2005/06/11 10:08:43 arniml Exp $ +-- +-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t48/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.t48_pack.word_t; +use work.t48_decoder_pack.mnemonic_t; + +entity t48_opc_table is + + port ( + opcode_i : in word_t; + multi_cycle_o : out std_logic; + mnemonic_o : out mnemonic_t + ); + +end t48_opc_table; + + +use work.t48_decoder_pack.all; + +architecture rtl of t48_opc_table is + +begin + + ----------------------------------------------------------------------------- + -- Process opc_decode + -- + -- Purpose: + -- Decode the opcode to the set of mnemonics. + -- + opc_decode: process (opcode_i) + begin + -- default assignment + mnemonic_o <= MN_NOP; + multi_cycle_o <= '0'; + + case opcode_i is + -- Mnemonic ADD --------------------------------------------------------- + when "01101000" | "01101001" | "01101010" | "01101011" | -- ADD A, Rr + "01101100" | "01101101" | "01101110" | "01101111" | -- + "01100000" | "01100001" | -- ADD A, @ Rr + "01111000" | "01111001" | "01111010" | "01111011" | -- ADDC A, Rr + "01111100" | "01111101" | "01111110" | "01111111" | -- + "01110000" | "01110001" => -- ADDC A, @ Rr + mnemonic_o <= MN_ADD; + + -- Mnemonic ADD_A_DATA -------------------------------------------------- + when "00000011" | -- ADD A, data + "00010011" => -- ADDC A, data + mnemonic_o <= MN_ADD_A_DATA; + multi_cycle_o <= '1'; + + -- Mnemonic ANL --------------------------------------------------------- + when "01011000" | "01011001" | "01011010" | "01011011" | -- ANL A, Rr + "01011100" | "01011101" | "01011110" | "01011111" | -- + "01010000" | "01010001" => -- ANL A, @ Rr + mnemonic_o <= MN_ANL; + + -- Mnemonic ANL_A_DATA -------------------------------------------------- + when "01010011" => -- ANL A, data + mnemonic_o <= MN_ANL_A_DATA; + multi_cycle_o <= '1'; + + -- Mnemonic ANL_EXT ----------------------------------------------------- + when "10011000" | -- ANL BUS, data + "10011001" | "10011010" => -- ANL PP, data + mnemonic_o <= MN_ANL_EXT; + multi_cycle_o <= '1'; + + -- Mnemonic CALL -------------------------------------------------------- + when "00010100" | "00110100" | "01010100" | "01110100" | -- CALL addr + "10010100" | "10110100" | "11010100" | "11110100" => -- + mnemonic_o <= MN_CALL; + multi_cycle_o <= '1'; + + -- Mnemonic CLR_A ------------------------------------------------------- + when "00100111" => -- CLR A + mnemonic_o <= MN_CLR_A; + + -- Mnemonic CLR_C ------------------------------------------------------- + when "10010111" => -- CLR C + mnemonic_o <= MN_CLR_C; + + -- Mnemonic CLR_F ------------------------------------------------------- + when "10000101" | -- CLR F0 + "10100101" => + mnemonic_o <= MN_CLR_F; + + -- Mnemonic CPL_A ------------------------------------------------------- + when "00110111" => -- CPL A + mnemonic_o <= MN_CPL_A; + + -- Mnemonic CPL_C ------------------------------------------------------- + when "10100111" => -- CPL C + mnemonic_o <= MN_CPL_C; + + -- Mnemonic CPL_F ------------------------------------------------------- + when "10010101" | -- CPL F0 + "10110101" => -- CPL F1 + mnemonic_o <= MN_CPL_F; + + -- Mnemonic DA ---------------------------------------------------------- + when "01010111" => -- DA D + mnemonic_o <= MN_DA; + + -- Mnemonic DEC --------------------------------------------------------- + when "11001000" | "11001001" | "11001010" | "11001011" | -- DEC Rr + "11001100" | "11001101" | "11001110" | "11001111" | -- + "00000111" => -- DEC A + mnemonic_o <= MN_DEC; + + -- Mnemonic DIS_EN_I ---------------------------------------------------- + when "00010101" | -- DIS I + "00000101" => -- EN I + mnemonic_o <= MN_DIS_EN_I; + + -- Mnemonic DIS_EN_TCNTI ------------------------------------------------ + when "00110101" | -- DIS TCNTI + "00100101" => -- EN TCNTI + mnemonic_o <= MN_DIS_EN_TCNTI; + + -- Mnemonic DJNZ -------------------------------------------------------- + when "11101000" | "11101001" | "11101010" | "11101011" | -- DJNZ Rr, addr + "11101100" | "11101101" | "11101110" | "11101111" => -- + mnemonic_o <= MN_DJNZ; + multi_cycle_o <= '1'; + + -- Mnemonic ENT0_CLK ---------------------------------------------------- + when "01110101" => -- ENT0 CLK + mnemonic_o <= MN_ENT0_CLK; + + -- Mnemonic IN ---------------------------------------------------------- + when "00001001" | "00001010" => -- IN A, Pp + mnemonic_o <= MN_IN; + multi_cycle_o <= '1'; + + -- Mnemonic INC --------------------------------------------------------- + when "00010111" | -- INC A + "00011000" | "00011001" | "00011010" | "00011011" | -- INC Rr + "00011100" | "00011101" | "00011110" | "00011111" | -- + "00010000" | "00010001" => -- INC @ Rr + mnemonic_o <= MN_INC; + + -- Mnemonic INS --------------------------------------------------------- + when "00001000" => -- INS A, BUS + mnemonic_o <= MN_INS; + multi_cycle_o <= '1'; + + -- Mnemonic JBB --------------------------------------------------------- + when "00010010" | "00110010" | "01010010" | "01110010" | -- JBb addr + "10010010" | "10110010" | "11010010" | "11110010" => -- + mnemonic_o <= MN_JBB; + multi_cycle_o <= '1'; + + -- Mnemonic JC ---------------------------------------------------------- + when "11110110" | -- JC addr + "11100110" => -- JNC addr + mnemonic_o <= MN_JC; + multi_cycle_o <= '1'; + + -- Mnemonic JF ---------------------------------------------------------- + when "10110110" | -- JF0 addr + "01110110" => -- JF1 addr + mnemonic_o <= MN_JF; + multi_cycle_o <= '1'; + + -- Mnemonic JMP --------------------------------------------------------- + when "00000100" | "00100100" | "01000100" | "01100100" | -- JMP addr + "10000100" | "10100100" | "11000100" | "11100100" => -- + mnemonic_o <= MN_JMP; + multi_cycle_o <= '1'; + + -- Mnemonic JMPP -------------------------------------------------------- + when "10110011" => -- JMPP @ A + mnemonic_o <= MN_JMPP; + multi_cycle_o <= '1'; + + -- Mnemonic JNI --------------------------------------------------------- + when "10000110" => -- JNI addr + mnemonic_o <= MN_JNI; + multi_cycle_o <= '1'; + + -- Mnemonic JT ---------------------------------------------------------- + when "00100110" | -- JNT0 addr + "01000110" | -- JNT1 addr + "00110110" | -- JT0 addr + "01010110" => -- JT1 addr + mnemonic_o <= MN_JT; + multi_cycle_o <= '1'; + + -- Mnemonic JTF --------------------------------------------------------- + when "00010110" => -- JTF addr + mnemonic_o <= MN_JTF; + multi_cycle_o <= '1'; + + -- Mnemonic JZ ---------------------------------------------------------- + when "10010110" | -- JNZ addr + "11000110" => -- JZ addr + mnemonic_o <= MN_JZ; + multi_cycle_o <= '1'; + + -- Mnemonic MOV_A_DATA -------------------------------------------------- + when "00100011" => -- MOV A, data + mnemonic_o <= MN_MOV_A_DATA; + multi_cycle_o <= '1'; + + -- Mnemonic MOV_A_PSW --------------------------------------------------- + when "11000111" => -- MOV A, PSW + mnemonic_o <= MN_MOV_A_PSW; + + -- Mnemonic MOV_A_RR ---------------------------------------------------- + when "11111000" | "11111001" | "11111010" | "11111011" | -- MOV A, Rr + "11111100" | "11111101" | "11111110" | "11111111" | -- + "11110000" | "11110001" => -- MOV A, @ Rr + mnemonic_o <= MN_MOV_A_RR; + + -- Mnemonic MOV_PSW_A --------------------------------------------------- + when "11010111" => -- MOV PSW, A + mnemonic_o <= MN_MOV_PSW_A; + + -- Mnemonic MOV_RR ------------------------------------------------------ + when "10101000" | "10101001" | "10101010" | "10101011" | -- MOV Rr, A + "10101100" | "10101101" | "10101110" | "10101111" | -- + "10100000" | "10100001" => -- MOV @ Rr, A + mnemonic_o <= MN_MOV_RR; + + -- Mnemonic MOV_RR_DATA ------------------------------------------------- + when "10111000" | "10111001" | "10111010" | "10111011" | -- MOV Rr, data + "10111100" | "10111101" | "10111110" | "10111111" | -- + "10110000" | "10110001" => -- MOV @ Rr, data + mnemonic_o <= MN_MOV_RR_DATA; + multi_cycle_o <= '1'; + + -- Mnemonic MOV_T ------------------------------------------------------- + when "01100010" | -- MOV T, A + "01000010" => -- MOV A, T + mnemonic_o <= MN_MOV_T; + + -- Mnemonic MOVD_A_PP --------------------------------------------------- + when "00001100" | "00001101" | "00001110" | "00001111" => -- MOVD A, Pp + mnemonic_o <= MN_MOVD_A_PP; + multi_cycle_o <= '1'; + + -- Mnemonic MOVP -------------------------------------------------------- + when "10100011" | -- MOVP A, @ A + "11100011" => -- MOVP3 A, @ A + mnemonic_o <= MN_MOVP; + multi_cycle_o <= '1'; + + -- Mnemonic MOVX -------------------------------------------------------- + when "10000000" | "10000001" | -- MOVX A, @ Rr + "10010000" | "10010001" => -- MOVX @ Rr, A + mnemonic_o <= MN_MOVX; + multi_cycle_o <= '1'; + + -- Mnemonic NOP --------------------------------------------------------- + when "00000000" => -- NOP + mnemonic_o <= MN_NOP; + + -- Mnemonic ORL --------------------------------------------------------- + when "01001000" | "01001001" | "01001010" | "01001011" | -- ORL A, Rr + "01001100" | "01001101" | "01001110" | "01001111" | -- + "01000000" | "01000001" => -- ORL A, @ Rr + mnemonic_o <= MN_ORL; + + -- Mnemonic ORL_A_DATA -------------------------------------------------- + when "01000011" => -- ORL A, data + mnemonic_o <= MN_ORL_A_DATA; + multi_cycle_o <= '1'; + + -- Mnemonic ORL_EXT ----------------------------------------------------- + when "10001000" | -- ORL BUS, data + "10001001" | "10001010" => -- ORL Pp, data + mnemonic_o <= MN_ORL_EXT; + multi_cycle_o <= '1'; + + -- Mnemonic OUTD_PP_A --------------------------------------------------- + when "00111100" | "00111101" | "00111110" | "00111111" | -- MOVD Pp, A + "10011100" | "10011101" | "10011110" | "10011111" | -- ANLD PP, A + "10001100" | "10001101" | "10001110" | "10001111" => -- ORLD Pp, A + mnemonic_o <= MN_OUTD_PP_A; + multi_cycle_o <= '1'; + + -- Mnemonic OUTL_EXT ---------------------------------------------------- + when "00111001" | "00111010" | -- OUTL Pp, A + "00000010" => -- OUTL BUS, A + mnemonic_o <= MN_OUTL_EXT; + multi_cycle_o <= '1'; + + -- Mnemonic RET --------------------------------------------------------- + when "10000011" | -- RET + "10010011" => -- RETR + mnemonic_o <= MN_RET; + multi_cycle_o <= '1'; + + -- Mnemonic RL ---------------------------------------------------------- + when "11100111" | -- RL A + "11110111" => -- RLC A + mnemonic_o <= MN_RL; + + -- Mnemonic RR ---------------------------------------------------------- + when "01110111" | -- RR A + "01100111" => -- RRC A + mnemonic_o <= MN_RR; + + -- Mnemonic SEL_MB ------------------------------------------------------ + when "11100101" | -- SEL MB0 + "11110101" => -- SEL MB1 + mnemonic_o <= MN_SEL_MB; + + -- Mnemonic SEL_RB ------------------------------------------------------ + when "11000101" | -- SEL RB0 + "11010101" => -- SEL RB1 + mnemonic_o <= MN_SEL_RB; + + -- Mnemonic STOP_TCNT --------------------------------------------------- + when "01100101" => -- STOP TCNT + mnemonic_o <= MN_STOP_TCNT; + + -- Mnemonic START ------------------------------------------------------- + when "01000101" | -- STRT CNT + "01010101" => -- STRT T + mnemonic_o <= MN_STRT; + + -- Mnemonic SWAP -------------------------------------------------------- + when "01000111" => -- SWAP A + mnemonic_o <= MN_SWAP; + + -- Mnemonic XCH --------------------------------------------------------- + when "00101000" | "00101001" | "00101010" | "00101011" | -- XCH A, Rr + "00101100" | "00101101" | "00101110" | "00101111" | -- + "00100000" | "00100001" | -- XCH A, @ Rr + "00110000" | "00110001" => -- XCHD A, @ Rr + mnemonic_o <= MN_XCH; + + -- Mnemonic XRL --------------------------------------------------------- + when "11011000" | "11011001" | "11011010" | "11011011" | -- XRL A, Rr + "11011100" | "11011101" | "11011110" | "11011111" | -- + "11010000" | "11010001" => -- XRL A, @ Rr + mnemonic_o <= MN_XRL; + + -- Mnemonic XRL_A_DATA -------------------------------------------------- + when "11010011" => -- XRL A, data + mnemonic_o <= MN_XRL_A_DATA; + multi_cycle_o <= '1'; + + when others => + -- pragma translate_off + assert now = 0 ns + report "Unknown opcode." + severity warning; + -- pragma translate_on + + end case; + + end process opc_decode; + -- + ----------------------------------------------------------------------------- + +end rtl; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: opc_table.vhd,v $ +-- Revision 1.4 2005/06/11 10:08:43 arniml +-- introduce prefix 't48_' for all packages, entities and configurations +-- +-- Revision 1.3 2004/07/11 16:51:33 arniml +-- cleanup copyright notice +-- +-- Revision 1.2 2004/03/28 13:10:48 arniml +-- merge MN_ANLD, MN_MOVD_PP_A and MN_ORLD_PP_A to OUTLD_PP_A +-- +-- Revision 1.1 2004/03/23 21:31:52 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t48/rtl/vhdl/p1-c.vhd b/rtl/t48/rtl/vhdl/p1-c.vhd new file mode 100644 index 0000000..246a296 --- /dev/null +++ b/rtl/t48/rtl/vhdl/p1-c.vhd @@ -0,0 +1,17 @@ +------------------------------------------------------------------------------- +-- +-- The Port 1 unit. +-- Implements the Port 1 logic. +-- +-- $Id: p1-c.vhd,v 1.2 2005/06/11 10:08:43 arniml Exp $ +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +configuration t48_p1_rtl_c0 of t48_p1 is + + for rtl + end for; + +end t48_p1_rtl_c0; diff --git a/rtl/t48/rtl/vhdl/p1.vhd b/rtl/t48/rtl/vhdl/p1.vhd new file mode 100644 index 0000000..694846a --- /dev/null +++ b/rtl/t48/rtl/vhdl/p1.vhd @@ -0,0 +1,173 @@ +------------------------------------------------------------------------------- +-- +-- The Port 1 unit. +-- Implements the Port 1 logic. +-- +-- $Id: p1.vhd,v 1.5 2005/06/11 10:08:43 arniml Exp $ +-- +-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t48/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.t48_pack.word_t; + +entity t48_p1 is + + port ( + -- Global Interface ------------------------------------------------------- + clk_i : in std_logic; + res_i : in std_logic; + en_clk_i : in boolean; + -- T48 Bus Interface ------------------------------------------------------ + data_i : in word_t; + data_o : out word_t; + write_p1_i : in boolean; + read_p1_i : in boolean; + read_reg_i : in boolean; + -- Port 1 Interface ------------------------------------------------------- + p1_i : in word_t; + p1_o : out word_t; + p1_low_imp_o : out std_logic + ); + +end t48_p1; + + +use work.t48_pack.clk_active_c; +use work.t48_pack.res_active_c; +use work.t48_pack.bus_idle_level_c; + +architecture rtl of t48_p1 is + + -- the port output register + signal p1_q : word_t; + + -- the low impedance marker + signal low_imp_q : std_logic; + +begin + + ----------------------------------------------------------------------------- + -- Process p1_reg + -- + -- Purpose: + -- Implements the port output register. + -- + p1_reg: process (res_i, clk_i) + begin + if res_i = res_active_c then + p1_q <= (others => '1'); + low_imp_q <= '0'; + + elsif clk_i'event and clk_i = clk_active_c then + if en_clk_i then + + if write_p1_i then + p1_q <= data_i; + low_imp_q <= '1'; + else + low_imp_q <= '0'; + end if; + + end if; + + end if; + + end process p1_reg; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process p1_data + -- + -- Purpose: + -- Generates the T48 bus data. + -- + p1_data: process (read_p1_i, + p1_i, + read_reg_i, + p1_q) + begin + data_o <= (others => bus_idle_level_c); + + if read_p1_i then + if read_reg_i then + data_o <= p1_q; + else + data_o <= p1_i; + end if; + end if; + + end process p1_data; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Output Mapping. + ----------------------------------------------------------------------------- + p1_o <= p1_q; + p1_low_imp_o <= low_imp_q; + +end rtl; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: p1.vhd,v $ +-- Revision 1.5 2005/06/11 10:08:43 arniml +-- introduce prefix 't48_' for all packages, entities and configurations +-- +-- Revision 1.4 2004/07/11 16:51:33 arniml +-- cleanup copyright notice +-- +-- Revision 1.3 2004/05/17 14:37:53 arniml +-- reorder data_o generation +-- +-- Revision 1.2 2004/03/29 19:39:58 arniml +-- rename pX_limp to pX_low_imp +-- +-- Revision 1.1 2004/03/23 21:31:52 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t48/rtl/vhdl/p2-c.vhd b/rtl/t48/rtl/vhdl/p2-c.vhd new file mode 100644 index 0000000..dff1c4c --- /dev/null +++ b/rtl/t48/rtl/vhdl/p2-c.vhd @@ -0,0 +1,17 @@ +------------------------------------------------------------------------------- +-- +-- The Port 2 unit. +-- Implements the Port 2 logic. +-- +-- $Id: p2-c.vhd,v 1.2 2005/06/11 10:08:43 arniml Exp $ +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +configuration t48_p2_rtl_c0 of t48_p2 is + + for rtl + end for; + +end t48_p2_rtl_c0; diff --git a/rtl/t48/rtl/vhdl/p2.vhd b/rtl/t48/rtl/vhdl/p2.vhd new file mode 100644 index 0000000..8134e4c --- /dev/null +++ b/rtl/t48/rtl/vhdl/p2.vhd @@ -0,0 +1,270 @@ +------------------------------------------------------------------------------- +-- +-- The Port 2 unit. +-- Implements the Port 2 logic. +-- +-- $Id: p2.vhd,v 1.8 2005/11/01 21:27:55 arniml Exp $ +-- +-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t48/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.t48_pack.word_t; +use work.t48_pack.nibble_t; + +entity t48_p2 is + + port ( + -- Global Interface ------------------------------------------------------- + clk_i : in std_logic; + res_i : in std_logic; + en_clk_i : in boolean; + xtal_i : in std_logic; + -- T48 Bus Interface ------------------------------------------------------ + data_i : in word_t; + data_o : out word_t; + write_p2_i : in boolean; + write_exp_i : in boolean; + read_p2_i : in boolean; + read_reg_i : in boolean; + read_exp_i : in boolean; + -- Port 2 Interface ------------------------------------------------------- + output_pch_i : in boolean; + pch_i : in nibble_t; + p2_i : in word_t; + p2_o : out word_t; + p2l_low_imp_o : out std_logic; + p2h_low_imp_o : out std_logic + ); + +end t48_p2; + + +use work.t48_pack.clk_active_c; +use work.t48_pack.res_active_c; +use work.t48_pack.bus_idle_level_c; + +architecture rtl of t48_p2 is + + -- the port output register + signal p2_q : word_t; + + -- the low impedance markers + signal l_low_imp_q, + h_low_imp_q : std_logic; + + signal en_clk_q : boolean; + signal l_low_imp_del_q, + h_low_imp_del_q : std_logic; + signal output_pch_q : boolean; + +begin + + ----------------------------------------------------------------------------- + -- Process p2_regs + -- + -- Purpose: + -- Implements the port output and expander registers. + -- + p2_regs: process (res_i, clk_i) + begin + if res_i = res_active_c then + p2_q <= (others => '1'); + l_low_imp_q <= '0'; + h_low_imp_q <= '0'; + + elsif clk_i'event and clk_i = clk_active_c then + if en_clk_i then + -- default: reset low impedance marker + l_low_imp_q <= '0'; + h_low_imp_q <= '0'; + + if write_p2_i then + -- write whole P2 + p2_q <= data_i; + l_low_imp_q <= '1'; + h_low_imp_q <= '1'; + + elsif write_exp_i then + -- write lower nibble of P2 + p2_q(nibble_t'range) <= data_i(nibble_t'range); + l_low_imp_q <= '1'; + + end if; + + end if; + + end if; + + end process p2_regs; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process p2_port + -- + -- Purpose: + -- Generates the output byte vector for Port 2. + -- It is a synchronous process clocked with XTAL. This ensures that + -- P2 data and low impedance markers are free of glitches and stabilize + -- during the same clock/machine state. + -- On the other hand, P2 is delayed by 1 XTAL cycle. + -- + p2_port: process (res_i, xtal_i) + begin + if res_i = res_active_c then + p2_o <= (others => '1'); + l_low_imp_del_q <= '0'; + h_low_imp_del_q <= '0'; + output_pch_q <= false; + en_clk_q <= false; + + elsif xtal_i'event and xtal_i = clk_active_c then + -- delay clock enable by one XTAL period + en_clk_q <= en_clk_i; + + p2_o <= p2_q; + output_pch_q <= output_pch_i; + + if output_pch_i then + p2_o(nibble_t'range) <= pch_i; + end if; + + -- generate low impedance trigger for one XTAL clock period after + -- global clock enable when + -- a) switching to or from PCH + -- b) l_low_imp_q is active + if en_clk_q and + ((output_pch_q xor output_pch_i) or + l_low_imp_q = '1') then + l_low_imp_del_q <= '1'; + else + l_low_imp_del_q <= '0'; + end if; + + -- generate low impedance trigger for on XTAL clock period after + -- global clock enable when + -- h_low_imp_q is active + if en_clk_q and + h_low_imp_q = '1' then + h_low_imp_del_q <= '1'; + else + h_low_imp_del_q <= '0'; + end if; + + end if; + + end process p2_port; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process p2_data + -- + -- Purpose: + -- Generates the T48 bus data. + -- + p2_data: process (read_p2_i, + p2_i, + read_reg_i, + p2_q, + read_exp_i) + begin + data_o <= (others => bus_idle_level_c); + + if read_p2_i then + if read_reg_i then + data_o <= p2_q; + elsif read_exp_i then + data_o <= "0000" & p2_i(nibble_t'range); + else + data_o <= p2_i; + end if; + end if; + + end process p2_data; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Output Mapping. + ----------------------------------------------------------------------------- + p2l_low_imp_o <= l_low_imp_del_q; + p2h_low_imp_o <= h_low_imp_del_q; + +end rtl; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: p2.vhd,v $ +-- Revision 1.8 2005/11/01 21:27:55 arniml +-- * change low impedance markers for P2 +-- separate marker for low and high part +-- * p2_o output is also registered to prevent combinational +-- output to pads +-- +-- Revision 1.7 2005/06/11 10:08:43 arniml +-- introduce prefix 't48_' for all packages, entities and configurations +-- +-- Revision 1.6 2004/07/11 16:51:33 arniml +-- cleanup copyright notice +-- +-- Revision 1.5 2004/05/17 13:52:46 arniml +-- Fix bug "ANL and ORL to P1/P2 read port status instead of port output register" +-- +-- Revision 1.4 2004/04/24 23:44:25 arniml +-- move from std_logic_arith to numeric_std +-- +-- Revision 1.3 2004/03/29 19:39:58 arniml +-- rename pX_limp to pX_low_imp +-- +-- Revision 1.2 2004/03/28 13:11:43 arniml +-- rework Port 2 expander handling +-- +-- Revision 1.1 2004/03/23 21:31:53 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t48/rtl/vhdl/pmem_ctrl-c.vhd b/rtl/t48/rtl/vhdl/pmem_ctrl-c.vhd new file mode 100644 index 0000000..8cadaaa --- /dev/null +++ b/rtl/t48/rtl/vhdl/pmem_ctrl-c.vhd @@ -0,0 +1,17 @@ +------------------------------------------------------------------------------- +-- +-- The Program Memory control unit. +-- All operations related to the Program Memory are managed here. +-- +-- $Id: pmem_ctrl-c.vhd,v 1.2 2005/06/11 10:08:43 arniml Exp $ +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +configuration t48_pmem_ctrl_rtl_c0 of t48_pmem_ctrl is + + for rtl + end for; + +end t48_pmem_ctrl_rtl_c0; diff --git a/rtl/t48/rtl/vhdl/pmem_ctrl.vhd b/rtl/t48/rtl/vhdl/pmem_ctrl.vhd new file mode 100644 index 0000000..51c801f --- /dev/null +++ b/rtl/t48/rtl/vhdl/pmem_ctrl.vhd @@ -0,0 +1,245 @@ +------------------------------------------------------------------------------- +-- +-- The Program Memory control unit. +-- All operations related to the Program Memory are managed here. +-- +-- $Id: pmem_ctrl.vhd,v 1.5 2005/06/11 10:08:43 arniml Exp $ +-- +-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t48/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.t48_pack.pmem_addr_t; +use work.t48_pack.word_t; +use work.t48_pmem_ctrl_pack.pmem_addr_ident_t; + +entity t48_pmem_ctrl is + + port ( + -- Global Interface ------------------------------------------------------- + clk_i : in std_logic; + res_i : in std_logic; + en_clk_i : in boolean; + -- T48 Bus Interface ------------------------------------------------------ + data_i : in word_t; + data_o : out word_t; + write_pcl_i : in boolean; + read_pcl_i : in boolean; + write_pch_i : in boolean; + read_pch_i : in boolean; + inc_pc_i : in boolean; + write_pmem_addr_i : in boolean; + addr_type_i : in pmem_addr_ident_t; + read_pmem_i : in boolean; + -- Porgram Memroy Interface ----------------------------------------------- + pmem_addr_o : out pmem_addr_t; + pmem_data_i : in word_t + ); + +end t48_pmem_ctrl; + + +library ieee; +use ieee.numeric_std.all; + +use work.t48_pmem_ctrl_pack.all; +use work.t48_pack.res_active_c; +use work.t48_pack.clk_active_c; +use work.t48_pack.bus_idle_level_c; +use work.t48_pack.pmem_addr_width_c; +use work.t48_pack.dmem_addr_width_c; +use work.t48_pack.page_t; + +architecture rtl of t48_pmem_ctrl is + + -- implemented counter width of Program Counter + -- the upper bit is only altered by JMP, CALL and RET(R) + subtype pc_count_range_t is natural range pmem_addr_width_c-2 downto 0; + + -- the Program Counter + signal program_counter_q : unsigned(pmem_addr_t'range); + + + -- the Program Memory address + signal pmem_addr_s, + pmem_addr_q : std_logic_vector(pmem_addr_t'range); + +begin + + ----------------------------------------------------------------------------- + -- Process program_counter + -- + -- Purpose: + -- Implements the Program Counter. + -- + program_counter: process (res_i, clk_i) + begin + if res_i = res_active_c then + program_counter_q <= (others => '0'); + pmem_addr_q <= (others => '0'); + + elsif clk_i'event and clk_i = clk_active_c then + if en_clk_i then + + -- parallel load mode + if write_pcl_i then + program_counter_q(data_i'range) <= UNSIGNED(data_i); + elsif write_pch_i then + program_counter_q(pmem_addr_width_c-1 downto data_i'high+1) <= + UNSIGNED(data_i(pmem_addr_width_c - dmem_addr_width_c - 1 downto 0)); + elsif inc_pc_i then + -- increment mode + -- the MSB is not modified by linear increments + -- it can only be altered by JMP, CALL or RET(R) + program_counter_q(pc_count_range_t) <= + program_counter_q(pc_count_range_t) + 1; + end if; + + -- set pmem address + if write_pmem_addr_i then + pmem_addr_q <= pmem_addr_s; + end if; + + end if; + + end if; + + end process program_counter; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process pmem_addr + -- + -- Purpose: + -- Multiplex the Program Memory address. + -- + pmem_addr: process (program_counter_q, + addr_type_i, + pmem_addr_q, + data_i) + begin + -- default assignment + pmem_addr_s <= STD_LOGIC_VECTOR(program_counter_q); + + case addr_type_i is + when PM_PC => + -- default is ok + null; + + when PM_PAGE => + pmem_addr_s(word_t'range) <= data_i; + -- take page address from program counter + -- => important for JMPP, MOVP! + -- they must wrap to next page when at FF! + + when PM_PAGE3 => + pmem_addr_s(word_t'range) <= data_i; + -- page address is explicitely specified + pmem_addr_s(page_t'range) <= "0011"; + + when others => + null; + + end case; + + end process pmem_addr; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process data_output + -- + -- Purpose: + -- Multiplex the data bus output. + -- + data_output: process (read_pmem_i, + read_pcl_i, + read_pch_i, + pmem_data_i, + program_counter_q) + begin + data_o <= (others => bus_idle_level_c); + + if read_pmem_i then + data_o <= pmem_data_i; + elsif read_pcl_i then + data_o <= STD_LOGIC_VECTOR(program_counter_q(data_o'range)); + elsif read_pch_i then + data_o(3 downto 0) <= STD_LOGIC_VECTOR(program_counter_q(pmem_addr_width_c-1 downto data_o'high+1)); + end if; + + end process data_output; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Output Mapping. + ----------------------------------------------------------------------------- + pmem_addr_o <= pmem_addr_q; + +end rtl; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: pmem_ctrl.vhd,v $ +-- Revision 1.5 2005/06/11 10:08:43 arniml +-- introduce prefix 't48_' for all packages, entities and configurations +-- +-- Revision 1.4 2005/06/08 19:13:53 arniml +-- fix bug report +-- "MSB of Program Counter changed upon PC increment" +-- +-- Revision 1.3 2004/07/11 16:51:33 arniml +-- cleanup copyright notice +-- +-- Revision 1.2 2004/04/24 23:44:25 arniml +-- move from std_logic_arith to numeric_std +-- +-- Revision 1.1 2004/03/23 21:31:53 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t48/rtl/vhdl/pmem_ctrl_pack-p.vhd b/rtl/t48/rtl/vhdl/pmem_ctrl_pack-p.vhd new file mode 100644 index 0000000..c1d45d6 --- /dev/null +++ b/rtl/t48/rtl/vhdl/pmem_ctrl_pack-p.vhd @@ -0,0 +1,33 @@ +------------------------------------------------------------------------------- +-- +-- $Id: pmem_ctrl_pack-p.vhd,v 1.2 2005/06/11 10:08:43 arniml Exp $ +-- +-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +package t48_pmem_ctrl_pack is + + ----------------------------------------------------------------------------- + -- Address Type Identifier + ----------------------------------------------------------------------------- + type pmem_addr_ident_t is (PM_PC, + PM_PAGE, + PM_PAGE3); + +end t48_pmem_ctrl_pack; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: pmem_ctrl_pack-p.vhd,v $ +-- Revision 1.2 2005/06/11 10:08:43 arniml +-- introduce prefix 't48_' for all packages, entities and configurations +-- +-- Revision 1.1 2004/03/23 21:31:53 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t48/rtl/vhdl/psw-c.vhd b/rtl/t48/rtl/vhdl/psw-c.vhd new file mode 100644 index 0000000..049e8f5 --- /dev/null +++ b/rtl/t48/rtl/vhdl/psw-c.vhd @@ -0,0 +1,17 @@ +------------------------------------------------------------------------------- +-- +-- The Program Status Word (PSW). +-- Implements the PSW with its special bits. +-- +-- $Id: psw-c.vhd,v 1.2 2005/06/11 10:08:43 arniml Exp $ +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +configuration t48_psw_rtl_c0 of t48_psw is + + for rtl + end for; + +end t48_psw_rtl_c0; diff --git a/rtl/t48/rtl/vhdl/psw.vhd b/rtl/t48/rtl/vhdl/psw.vhd new file mode 100644 index 0000000..87664f8 --- /dev/null +++ b/rtl/t48/rtl/vhdl/psw.vhd @@ -0,0 +1,243 @@ +------------------------------------------------------------------------------- +-- +-- The Program Status Word (PSW). +-- Implements the PSW with its special bits. +-- +-- $Id: psw.vhd,v 1.8 2005/06/11 10:08:43 arniml Exp $ +-- +-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t48/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.t48_pack.word_t; + +entity t48_psw is + + port ( + -- Global Interface ------------------------------------------------------- + clk_i : in std_logic; + res_i : in std_logic; + en_clk_i : in boolean; + -- T48 Bus Interface ------------------------------------------------------ + data_i : in word_t; + data_o : out word_t; + read_psw_i : in boolean; + read_sp_i : in boolean; + write_psw_i : in boolean; + write_sp_i : in boolean; + -- Decoder Interface ------------------------------------------------------ + special_data_i : in std_logic; + inc_stackp_i : in boolean; + dec_stackp_i : in boolean; + write_carry_i : in boolean; + write_aux_carry_i : in boolean; + write_f0_i : in boolean; + write_bs_i : in boolean; + carry_o : out std_logic; + aux_carry_i : in std_logic; + aux_carry_o : out std_logic; + f0_o : out std_logic; + bs_o : out std_logic + ); + +end t48_psw; + + +library ieee; +use ieee.numeric_std.all; + +use work.t48_pack.clk_active_c; +use work.t48_pack.res_active_c; +use work.t48_pack.bus_idle_level_c; +use work.t48_pack.nibble_t; + +architecture rtl of t48_psw is + + -- special bit positions in PSW + constant carry_c : natural := 3; + constant aux_carry_c : natural := 2; + constant f0_c : natural := 1; + constant bs_c : natural := 0; + + -- the PSW register + signal psw_q : nibble_t; + -- the Stack Pointer + signal sp_q : unsigned(2 downto 0); + + -- pragma translate_off + signal psw_s : word_t; + -- pragma translate_on + +begin + + ----------------------------------------------------------------------------- + -- Process psw_reg + -- + -- Purpose: + -- Implements the PSW register. + -- + psw_reg: process (res_i, clk_i) + begin + if res_i = res_active_c then + psw_q <= (others => '0'); + sp_q <= (others => '0'); + + elsif clk_i'event and clk_i = clk_active_c then + if en_clk_i then + + -- T48 bus access + if write_psw_i then + psw_q <= data_i(7 downto 4); + end if; + if write_sp_i then + sp_q <= unsigned(data_i(2 downto 0)); + end if; + + -- increment Stack Pointer + if inc_stackp_i then + sp_q <= sp_q + 1; + end if; + -- decrement Stack Pointer + if dec_stackp_i then + sp_q <= sp_q - 1; + end if; + + -- access to special bits + if write_carry_i then + psw_q(carry_c) <= special_data_i; + end if; + -- + if write_aux_carry_i then + psw_q(aux_carry_c) <= aux_carry_i; + end if; + -- + if write_f0_i then + psw_q(f0_c) <= special_data_i; + end if; + -- + if write_bs_i then + psw_q(bs_c) <= special_data_i; + end if; + + end if; + + end if; + + end process psw_reg; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process data_out + -- + -- Purpose: + -- Output multiplexer for T48 Data Bus. + -- + data_out: process (read_psw_i, + read_sp_i, + psw_q, + sp_q) + begin + data_o <= (others => bus_idle_level_c); + + if read_psw_i then + data_o(7 downto 4) <= psw_q; + end if; + + if read_sp_i then + data_o(3 downto 0) <= '1' & std_logic_vector(sp_q); + end if; + + end process data_out; + -- + ----------------------------------------------------------------------------- + + + -- pragma translate_off + tb: process (psw_q, sp_q) + begin + psw_s(7 downto 4) <= psw_q; + psw_s(3) <= '1'; + psw_s(2 downto 0) <= std_logic_vector(sp_q); + end process tb; + -- pragma translate_on + + ----------------------------------------------------------------------------- + -- Output mapping. + ----------------------------------------------------------------------------- + carry_o <= psw_q(carry_c); + aux_carry_o <= psw_q(aux_carry_c); + f0_o <= psw_q(f0_c); + bs_o <= psw_q(bs_c); + +end rtl; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: psw.vhd,v $ +-- Revision 1.8 2005/06/11 10:08:43 arniml +-- introduce prefix 't48_' for all packages, entities and configurations +-- +-- Revision 1.7 2004/07/11 16:51:33 arniml +-- cleanup copyright notice +-- +-- Revision 1.6 2004/04/24 23:44:25 arniml +-- move from std_logic_arith to numeric_std +-- +-- Revision 1.5 2004/04/24 11:25:39 arniml +-- removed dummy_s - workaround not longer needed for GHDL 0.11.1 +-- +-- Revision 1.4 2004/04/18 18:59:01 arniml +-- add temporary workaround for GHDL 0.11 +-- +-- Revision 1.3 2004/04/04 14:15:45 arniml +-- add dump_compare support +-- +-- Revision 1.2 2004/03/28 21:28:13 arniml +-- take auxiliary carry from direct ALU connection +-- +-- Revision 1.1 2004/03/23 21:31:53 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t48/rtl/vhdl/system/lpm_ram_dq.vhd b/rtl/t48/rtl/vhdl/system/lpm_ram_dq.vhd new file mode 100644 index 0000000..8b2a30b --- /dev/null +++ b/rtl/t48/rtl/vhdl/system/lpm_ram_dq.vhd @@ -0,0 +1,439 @@ +-------------------------------------------------------------------------- +-- This VHDL file was developed by Altera Corporation. It may be +-- freely copied and/or distributed at no cost. Any persons using this +-- file for any purpose do so at their own risk, and are responsible for +-- the results of such use. Altera Corporation does not guarantee that +-- this file is complete, correct, or fit for any particular purpose. +-- NO WARRANTY OF ANY KIND IS EXPRESSED OR IMPLIED. This notice must +-- accompany any copy of this file. +-- +-------------------------------------------------------------------------- +-- LPM Synthesizable Models (Support string type generic) +-------------------------------------------------------------------------- +-- Version 2.0 (lpm 220) Date 01/04/00 +-- +-- 1. Fixed LPM_RAM_DQ, LPM_RAM_DP, LPM_RAM_IO and LPM_ROM to correctly +-- read in values from LPM_FILE (*.hex) when the DATA width is greater +-- than 16 bits. +-- 2. Explicit sign conversions are added to standard logic vector +-- comparisons in LPM_RAM_DQ, LPM_RAM_DP, LPM_RAM_IO, LPM_ROM, and +-- LPM_COMPARE. +-- 3. LPM_FIFO_DC is rewritten to have correct outputs. +-- 4. LPM_FIFO outputs zeros when nothing has been read from it, and +-- outputs LPM_NUMWORDS mod exp(2, LPM_WIDTHU) when it is full. +-- 5. Fixed LPM_DIVIDE to divide correctly. +-------------------------------------------------------------------------- +-- Version 1.9 (lpm 220) Date 11/30/99 +-- +-- 1. Fixed UNUSED file not found problem and initialization problem +-- with LPM_RAM_DP, LPM_RAM_DQ, and LPM_RAM_IO. +-- 2. Fixed LPM_MULT when SUM port is not used. +-- 3. Fixed LPM_FIFO_DC to enable read when rdclock and wrclock rise +-- at the same time. +-- 4. Fixed LPM_COUNTER comparison problem when signed library is loaded +-- and counter is incrementing. +-- 5. Got rid of "Illegal Character" error message at time = 0 ns when +-- simulating LPM_COUNTER. +-------------------------------------------------------------------------- +-- Version 1.8 (lpm 220) Date 10/25/99 +-- +-- 1. Some LPM_PVALUE implementations were missing, and now implemented. +-- 2. Fixed LPM_COUNTER to count correctly without conversion overflow, +-- that is, when LPM_MODULUS = 2 ** LPM_WIDTH. +-- 3. Fixed LPM_RAM_DP sync process sensitivity list to detect wraddress +-- changes. +-------------------------------------------------------------------------- +-- Version 1.7 (lpm 220) Date 07/13/99 +-- +-- Changed LPM_RAM_IO so that it can be used to simulate both MP2 and +-- Quartus behaviour and LPM220-compliant behaviour. +-------------------------------------------------------------------------- +-- Version 1.6 (lpm 220) Date 06/15/99 +-- +-- 1. Fixed LPM_ADD_SUB sign extension problem and subtraction bug. +-- 2. Fixed LPM_COUNTER to use LPM_MODULUS value. +-- 3. Added CIN and COUT port, and discarded EQ port in LPM_COUNTER to +-- comply with the specfication. +-- 4. Included LPM_RAM_DP, LPM_RAM_DQ, LPM_RAM_IO, LPM_ROM, LPM_FIFO, and +-- LPM_FIFO_DC; they are all initialized to 0's. +-------------------------------------------------------------------------- +-- Version 1.5 (lpm 220) Date 05/10/99 +-- +-- Changed LPM_MODULUS from string type to integer. +-------------------------------------------------------------------------- +-- Version 1.4 (lpm 220) Date 02/05/99 +-- +-- 1. Added LPM_DIVIDE module. +-- 2. Added CLKEN port to LPM_MUX, LPM_DECODE, LPM_ADD_SUB, LPM_MULT +-- and LPM_COMPARE +-- 3. Replaced the constants holding string with the actual string. +-------------------------------------------------------------------------- +-- Version 1.3 Date 07/30/96 +-- +-- Modification History +-- +-- 1. Changed the DEFAULT value to "UNUSED" for LPM_SVALUE, LPM_AVALUE, +-- LPM_MODULUS, and LPM_NUMWORDS, LPM_HINT,LPM_STRENGTH, LPM_DIRECTION, +-- and LPM_PVALUE +-- +-- 2. Added the two dimentional port components (AND, OR, XOR, and MUX). +-------------------------------------------------------------------------- +-- Excluded Functions: +-- +-- LPM_FSM and LPM_TTABLE +-- +-------------------------------------------------------------------------- +-- Assumptions: +-- +-- 1. All ports and signal types are std_logic or std_logic_vector +-- from IEEE 1164 package. +-- 2. Synopsys std_logic_arith, std_logic_unsigned, and std_logic_signed +-- package are assumed to be accessible from IEEE library. +-- 3. lpm_component_package must be accessible from library work. +-- 4. The default value of LPM_SVALUE, LPM_AVALUE, LPM_MODULUS, LPM_HINT, +-- LPM_NUMWORDS, LPM_STRENGTH, LPM_DIRECTION, and LPM_PVALUE is +-- string "UNUSED". +-------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; +--use IEEE.std_logic_unsigned.all; +use std.textio.all; + +entity LPM_RAM_DQ is + generic (LPM_WIDTH : positive; + LPM_WIDTHAD : positive; + LPM_NUMWORDS : natural := 0; + LPM_INDATA : string := "REGISTERED"; + LPM_ADDRESS_CONTROL: string := "REGISTERED"; + LPM_OUTDATA : string := "REGISTERED"; + LPM_FILE : string := "UNUSED"; + LPM_TYPE : string := "LPM_RAM_DQ"; + LPM_HINT : string := "UNUSED"); + port (DATA : in std_logic_vector(LPM_WIDTH-1 downto 0); + ADDRESS : in std_logic_vector(LPM_WIDTHAD-1 downto 0); + INCLOCK : in std_logic := '0'; + OUTCLOCK : in std_logic := '0'; + WE : in std_logic; + Q : out std_logic_vector(LPM_WIDTH-1 downto 0)); + + function int_to_str( value : integer ) return string is + variable ivalue,index : integer; + variable digit : integer; + variable line_no: string(8 downto 1) := " "; + begin + ivalue := value; + index := 1; + while (ivalue > 0) loop + digit := ivalue MOD 10; + ivalue := ivalue/10; + case digit is + when 0 => + line_no(index) := '0'; + when 1 => + line_no(index) := '1'; + when 2 => + line_no(index) := '2'; + when 3 => + line_no(index) := '3'; + when 4 => + line_no(index) := '4'; + when 5 => + line_no(index) := '5'; + when 6 => + line_no(index) := '6'; + when 7 => + line_no(index) := '7'; + when 8 => + line_no(index) := '8'; + when 9 => + line_no(index) := '9'; + when others => + ASSERT FALSE + REPORT "Illegal number!" + SEVERITY ERROR; + end case; + index := index + 1; + end loop; + return line_no; + end; + + function hex_str_to_int( str : string ) return integer is + variable len : integer := str'length; + variable ivalue : integer := 0; + variable digit : integer; + begin + for i in len downto 1 loop + case str(i) is + when '0' => + digit := 0; + when '1' => + digit := 1; + when '2' => + digit := 2; + when '3' => + digit := 3; + when '4' => + digit := 4; + when '5' => + digit := 5; + when '6' => + digit := 6; + when '7' => + digit := 7; + when '8' => + digit := 8; + when '9' => + digit := 9; + when 'A' => + digit := 10; + when 'a' => + digit := 10; + when 'B' => + digit := 11; + when 'b' => + digit := 11; + when 'C' => + digit := 12; + when 'c' => + digit := 12; + when 'D' => + digit := 13; + when 'd' => + digit := 13; + when 'E' => + digit := 14; + when 'e' => + digit := 14; + when 'F' => + digit := 15; + when 'f' => + digit := 15; + when others => + ASSERT FALSE + REPORT "Illegal character "& str(i) & "in Intel Hex File! " + SEVERITY ERROR; + end case; + ivalue := ivalue * 16 + digit; + end loop; + return ivalue; + end; + + procedure Shrink_line(L : inout LINE; pos : in integer) is + subtype nstring is string(1 to pos); + variable stmp : nstring; + begin + if pos >= 1 then + read(l, stmp); + end if; + end; + +end LPM_RAM_DQ; + +architecture LPM_SYN of lpm_ram_dq is + +--type lpm_memory is array(lpm_numwords-1 downto 0) of std_logic_vector(lpm_width-1 downto 0); +type lpm_memory is array(integer range (2**lpm_widthad)-1 downto 0) of std_logic_vector(lpm_width-1 downto 0); + +signal data_tmp, data_reg : std_logic_vector(lpm_width-1 downto 0); +signal q_tmp, q_reg : std_logic_vector(lpm_width-1 downto 0) := (others => '0'); +signal address_tmp, address_reg : std_logic_vector(lpm_widthad-1 downto 0); +signal we_tmp, we_reg : std_logic; + +begin + + sync: process(data, data_reg, address, address_reg, + we, we_reg, q_tmp, q_reg) + begin + if (lpm_address_control = "REGISTERED") then + address_tmp <= address_reg; + we_tmp <= we_reg; + else + address_tmp <= address; + we_tmp <= we; + end if; + if (lpm_indata = "REGISTERED") then + data_tmp <= data_reg; + else + data_tmp <= data; + end if; + if (lpm_outdata = "REGISTERED") then + q <= q_reg; + else + q <= q_tmp; + end if; + end process; + + input_reg: process (inclock) + begin + if inclock'event and inclock = '1' then + data_reg <= data; + address_reg <= address; + we_reg <= we; + end if; + end process; + + output_reg: process (outclock) + begin + if outclock'event and outclock = '1' then + q_reg <= q_tmp; + end if; + end process; + + memory: process(data_tmp, we_tmp, address_tmp) + variable mem_data : lpm_memory; + variable mem_data_tmp : integer := 0; + variable mem_init: boolean := false; + variable i,j,k,lineno: integer := 0; + variable buf: line ; + variable booval: boolean ; + FILE unused_file: TEXT IS OUT "UNUSED"; + FILE mem_data_file: TEXT IS IN LPM_FILE; + variable base, byte, rec_type, datain, addr, checksum: string(2 downto 1); + variable startadd: string(4 downto 1); + variable ibase: integer := 0; + variable ibyte: integer := 0; + variable istartadd: integer := 0; + variable check_sum_vec, check_sum_vec_tmp: unsigned(7 downto 0); + begin + -- INITIALIZE -- + if NOT(mem_init) then + -- INITIALIZE TO 0 -- + for i in mem_data'LOW to mem_data'HIGH loop + mem_data(i) := (OTHERS => '0'); + end loop; + + if (LPM_FILE = "UNUSED") then + ASSERT FALSE + REPORT "Initialization file not found!" + SEVERITY WARNING; + else + WHILE NOT ENDFILE(mem_data_file) loop + booval := true; + READLINE(mem_data_file, buf); + lineno := lineno + 1; + check_sum_vec := (OTHERS => '0'); + if (buf(buf'LOW) = ':') then + i := 1; + shrink_line(buf, i); + READ(L=>buf, VALUE=>byte, good=>booval); + if not (booval) then + ASSERT FALSE + REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format!" + SEVERITY ERROR; + end if; + ibyte := hex_str_to_int(byte); + check_sum_vec := unsigned(check_sum_vec) + to_unsigned(ibyte, check_sum_vec'length); + READ(L=>buf, VALUE=>startadd, good=>booval); + if not (booval) then + ASSERT FALSE + REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format! " + SEVERITY ERROR; + end if; + istartadd := hex_str_to_int(startadd); + addr(2) := startadd(4); + addr(1) := startadd(3); + check_sum_vec := unsigned(check_sum_vec) + to_unsigned(hex_str_to_int(addr), check_sum_vec'length); + addr(2) := startadd(2); + addr(1) := startadd(1); + check_sum_vec := unsigned(check_sum_vec) + to_unsigned(hex_str_to_int(addr), check_sum_vec'length); + READ(L=>buf, VALUE=>rec_type, good=>booval); + if not (booval) then + ASSERT FALSE + REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format! " + SEVERITY ERROR; + end if; + check_sum_vec := unsigned(check_sum_vec) + to_unsigned(hex_str_to_int(rec_type), check_sum_vec'length); + else + ASSERT FALSE + REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format! " + SEVERITY ERROR; + end if; + case rec_type is + when "00"=> -- Data record + i := 0; + k := lpm_width / 8; + if ((lpm_width MOD 8) /= 0) then + k := k + 1; + end if; + -- k = no. of bytes per CAM entry. + while (i < ibyte) loop + mem_data_tmp := 0; + for j in 1 to k loop + READ(L=>buf, VALUE=>datain,good=>booval); -- read in data a byte (2 hex chars) at a time. + if not (booval) then + ASSERT FALSE + REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format! " + SEVERITY ERROR; + end if; + check_sum_vec := unsigned(check_sum_vec) + to_unsigned(hex_str_to_int(datain), check_sum_vec'length); + mem_data_tmp := mem_data_tmp * 256 + hex_str_to_int(datain); + end loop; + i := i + k; + mem_data(ibase + istartadd) := STD_LOGIC_VECTOR(to_unsigned(mem_data_tmp, lpm_width)); + istartadd := istartadd + 1; + end loop; + when "01"=> + exit; + when "02"=> + ibase := 0; + if (ibyte /= 2) then + ASSERT FALSE + REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format for record type 02! " + SEVERITY ERROR; + end if; + for i in 0 to (ibyte-1) loop + READ(L=>buf, VALUE=>base,good=>booval); + ibase := ibase * 256 + hex_str_to_int(base); + if not (booval) then + ASSERT FALSE + REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format! " + SEVERITY ERROR; + end if; + check_sum_vec := unsigned(check_sum_vec) + to_unsigned(hex_str_to_int(base), check_sum_vec'length); + end loop; + ibase := ibase * 16; + when OTHERS => + ASSERT FALSE + REPORT "[Line "& int_to_str(lineno) & "]:Illegal record type in Intel Hex File! " + SEVERITY ERROR; + end case; + READ(L=>buf, VALUE=>checksum,good=>booval); + if not (booval) then + ASSERT FALSE + REPORT "[Line "& int_to_str(lineno) & "]:Checksum is missing! " + SEVERITY ERROR; + end if; + + check_sum_vec := unsigned(not (check_sum_vec)) + 1 ; + check_sum_vec_tmp := to_unsigned(hex_str_to_int(checksum), check_sum_vec_tmp'length); + + if (unsigned(check_sum_vec) /= unsigned(check_sum_vec_tmp)) then + ASSERT FALSE + REPORT "[Line "& int_to_str(lineno) & "]:Incorrect checksum!" + SEVERITY ERROR; + end if; + end loop; + end if; + mem_init := TRUE; + end if; + + -- MEMORY FUNCTION -- + if we_tmp = '1' then + mem_data (to_integer(unsigned(address_tmp))) := data_tmp; + end if; + q_tmp <= mem_data(to_integer(unsigned(address_tmp))); + end process; + +end LPM_SYN; + + +-- pragma translate_off +configuration lpm_ram_dq_c0 of lpm_ram_dq is + + for lpm_syn + end for; + +end lpm_ram_dq_c0; +-- pragma translate_on diff --git a/rtl/t48/rtl/vhdl/system/lpm_rom.vhd b/rtl/t48/rtl/vhdl/system/lpm_rom.vhd new file mode 100644 index 0000000..b9450d6 --- /dev/null +++ b/rtl/t48/rtl/vhdl/system/lpm_rom.vhd @@ -0,0 +1,437 @@ +-------------------------------------------------------------------------- +-- This VHDL file was developed by Altera Corporation. It may be +-- freely copied and/or distributed at no cost. Any persons using this +-- file for any purpose do so at their own risk, and are responsible for +-- the results of such use. Altera Corporation does not guarantee that +-- this file is complete, correct, or fit for any particular purpose. +-- NO WARRANTY OF ANY KIND IS EXPRESSED OR IMPLIED. This notice must +-- accompany any copy of this file. +-- +-------------------------------------------------------------------------- +-- LPM Synthesizable Models (Support string type generic) +-------------------------------------------------------------------------- +-- Version 2.0 (lpm 220) Date 01/04/00 +-- +-- 1. Fixed LPM_RAM_DQ, LPM_RAM_DP, LPM_RAM_IO and LPM_ROM to correctly +-- read in values from LPM_FILE (*.hex) when the DATA width is greater +-- than 16 bits. +-- 2. Explicit sign conversions are added to standard logic vector +-- comparisons in LPM_RAM_DQ, LPM_RAM_DP, LPM_RAM_IO, LPM_ROM, and +-- LPM_COMPARE. +-- 3. LPM_FIFO_DC is rewritten to have correct outputs. +-- 4. LPM_FIFO outputs zeros when nothing has been read from it, and +-- outputs LPM_NUMWORDS mod exp(2, LPM_WIDTHU) when it is full. +-- 5. Fixed LPM_DIVIDE to divide correctly. +-------------------------------------------------------------------------- +-- Version 1.9 (lpm 220) Date 11/30/99 +-- +-- 1. Fixed UNUSED file not found problem and initialization problem +-- with LPM_RAM_DP, LPM_RAM_DQ, and LPM_RAM_IO. +-- 2. Fixed LPM_MULT when SUM port is not used. +-- 3. Fixed LPM_FIFO_DC to enable read when rdclock and wrclock rise +-- at the same time. +-- 4. Fixed LPM_COUNTER comparison problem when signed library is loaded +-- and counter is incrementing. +-- 5. Got rid of "Illegal Character" error message at time = 0 ns when +-- simulating LPM_COUNTER. +-------------------------------------------------------------------------- +-- Version 1.8 (lpm 220) Date 10/25/99 +-- +-- 1. Some LPM_PVALUE implementations were missing, and now implemented. +-- 2. Fixed LPM_COUNTER to count correctly without conversion overflow, +-- that is, when LPM_MODULUS = 2 ** LPM_WIDTH. +-- 3. Fixed LPM_RAM_DP sync process sensitivity list to detect wraddress +-- changes. +-------------------------------------------------------------------------- +-- Version 1.7 (lpm 220) Date 07/13/99 +-- +-- Changed LPM_RAM_IO so that it can be used to simulate both MP2 and +-- Quartus behaviour and LPM220-compliant behaviour. +-------------------------------------------------------------------------- +-- Version 1.6 (lpm 220) Date 06/15/99 +-- +-- 1. Fixed LPM_ADD_SUB sign extension problem and subtraction bug. +-- 2. Fixed LPM_COUNTER to use LPM_MODULUS value. +-- 3. Added CIN and COUT port, and discarded EQ port in LPM_COUNTER to +-- comply with the specfication. +-- 4. Included LPM_RAM_DP, LPM_RAM_DQ, LPM_RAM_IO, LPM_ROM, LPM_FIFO, and +-- LPM_FIFO_DC; they are all initialized to 0's. +-------------------------------------------------------------------------- +-- Version 1.5 (lpm 220) Date 05/10/99 +-- +-- Changed LPM_MODULUS from string type to integer. +-------------------------------------------------------------------------- +-- Version 1.4 (lpm 220) Date 02/05/99 +-- +-- 1. Added LPM_DIVIDE module. +-- 2. Added CLKEN port to LPM_MUX, LPM_DECODE, LPM_ADD_SUB, LPM_MULT +-- and LPM_COMPARE +-- 3. Replaced the constants holding string with the actual string. +-------------------------------------------------------------------------- +-- Version 1.3 Date 07/30/96 +-- +-- Modification History +-- +-- 1. Changed the DEFAULT value to "UNUSED" for LPM_SVALUE, LPM_AVALUE, +-- LPM_MODULUS, and LPM_NUMWORDS, LPM_HINT,LPM_STRENGTH, LPM_DIRECTION, +-- and LPM_PVALUE +-- +-- 2. Added the two dimentional port components (AND, OR, XOR, and MUX). +-------------------------------------------------------------------------- +-- Excluded Functions: +-- +-- LPM_FSM and LPM_TTABLE +-- +-------------------------------------------------------------------------- +-- Assumptions: +-- +-- 1. All ports and signal types are std_logic or std_logic_vector +-- from IEEE 1164 package. +-- 2. Synopsys std_logic_arith, std_logic_unsigned, and std_logic_signed +-- package are assumed to be accessible from IEEE library. +-- 3. lpm_component_package must be accessible from library work. +-- 4. The default value of LPM_SVALUE, LPM_AVALUE, LPM_MODULUS, LPM_HINT, +-- LPM_NUMWORDS, LPM_STRENGTH, LPM_DIRECTION, and LPM_PVALUE is +-- string "UNUSED". +-------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; +--use work.LPM_COMPONENTS.all; +use std.textio.all; + +entity LPM_ROM is + generic (LPM_WIDTH : positive; + LPM_WIDTHAD : positive; + LPM_NUMWORDS : natural := 0; + LPM_ADDRESS_CONTROL : string := "REGISTERED"; + LPM_OUTDATA : string := "REGISTERED"; + LPM_FILE : string; + LPM_TYPE : string := "LPM_ROM"; + LPM_HINT : string := "UNUSED"); + port (ADDRESS : in STD_LOGIC_VECTOR(LPM_WIDTHAD-1 downto 0); + INCLOCK : in STD_LOGIC := '0'; + OUTCLOCK : in STD_LOGIC := '0'; + MEMENAB : in STD_LOGIC := '1'; + Q : out STD_LOGIC_VECTOR(LPM_WIDTH-1 downto 0)); + + function int_to_str( value : integer ) return string is + variable ivalue,index : integer; + variable digit : integer; + variable line_no: string(8 downto 1) := " "; + begin + ivalue := value; + index := 1; + while (ivalue > 0 ) loop + digit := ivalue MOD 10; + ivalue := ivalue/10; + case digit is + when 0 => + line_no(index) := '0'; + when 1 => + line_no(index) := '1'; + when 2 => + line_no(index) := '2'; + when 3 => + line_no(index) := '3'; + when 4 => + line_no(index) := '4'; + when 5 => + line_no(index) := '5'; + when 6 => + line_no(index) := '6'; + when 7 => + line_no(index) := '7'; + when 8 => + line_no(index) := '8'; + when 9 => + line_no(index) := '9'; + when others => + ASSERT FALSE + REPORT "Illegal number!" + SEVERITY ERROR; + end case; + index := index + 1; + end loop; + return line_no; + end; + + function hex_str_to_int( str : string ) return integer is + variable len : integer := str'length; + variable ivalue : integer := 0; + variable digit : integer; + begin + for i in len downto 1 loop + case str(i) is + when '0' => + digit := 0; + when '1' => + digit := 1; + when '2' => + digit := 2; + when '3' => + digit := 3; + when '4' => + digit := 4; + when '5' => + digit := 5; + when '6' => + digit := 6; + when '7' => + digit := 7; + when '8' => + digit := 8; + when '9' => + digit := 9; + when 'A' => + digit := 10; + when 'a' => + digit := 10; + when 'B' => + digit := 11; + when 'b' => + digit := 11; + when 'C' => + digit := 12; + when 'c' => + digit := 12; + when 'D' => + digit := 13; + when 'd' => + digit := 13; + when 'E' => + digit := 14; + when 'e' => + digit := 14; + when 'F' => + digit := 15; + when 'f' => + digit := 15; + when others => + ASSERT FALSE + REPORT "Illegal character "& str(i) & "in Intel Hex File! " + SEVERITY ERROR; + end case; + ivalue := ivalue * 16 + digit; + end loop; + return ivalue; + end; + + procedure Shrink_line(L : inout LINE; pos : in integer) is + subtype nstring is string(1 to pos); + variable stmp : nstring; + begin + if pos >= 1 then + read(l, stmp); + end if; + end; + +end LPM_ROM; + +architecture LPM_SYN of lpm_rom is + +--type lpm_memory is array(lpm_numwords-1 downto 0) of std_logic_vector(lpm_width-1 downto 0); +type lpm_memory is array(integer range (2**lpm_widthad)-1 downto 0) of std_logic_vector(lpm_width-1 downto 0); + +signal q2, q_tmp, q_reg : std_logic_vector(lpm_width-1 downto 0); +signal address_tmp, address_reg : std_logic_vector(lpm_widthad-1 downto 0); + +begin + + enable_mem: process(memenab, q2) + begin + if (memenab = '1') then + q <= q2; + else + q <= (OTHERS => 'Z'); + end if; + end process; + + sync: process(address, address_reg, q_tmp, q_reg) + begin + if (lpm_address_control = "REGISTERED") then + address_tmp <= address_reg; + else + address_tmp <= address; + end if; + if (lpm_outdata = "REGISTERED") then + q2 <= q_reg; + else + q2 <= q_tmp; + end if; + end process; + + input_reg: process (inclock) + begin + if inclock'event and inclock = '1' then + address_reg <= address; + end if; + end process; + + output_reg: process (outclock) + begin + if outclock'event and outclock = '1' then + q_reg <= q_tmp; + end if; + end process; + + memory: process(memenab, address_tmp) + variable mem_data : lpm_memory; + variable mem_data_tmp : integer := 0; + variable mem_init: boolean := false; + variable i, j, k, lineno : integer := 0; + variable buf: line ; + variable booval: boolean ; + FILE mem_data_file: TEXT IS IN LPM_FILE; + variable base, byte, rec_type, datain, addr, checksum: string(2 downto 1); + variable startadd: string(4 downto 1); + variable ibase: integer := 0; + variable ibyte: integer := 0; + variable istartadd: integer := 0; + variable check_sum_vec, check_sum_vec_tmp: unsigned(7 downto 0); + begin + -- INITIALIZE -- + if NOT(mem_init) then + -- INITIALIZE TO 0 -- + for i in mem_data'LOW to mem_data'HIGH loop + mem_data(i) := (OTHERS => '0'); + end loop; + + if (LPM_FILE = "UNUSED") then + ASSERT FALSE + REPORT "Initialization file not found!" + SEVERITY ERROR; + else + WHILE NOT ENDFILE(mem_data_file) loop + booval := true; + READLINE(mem_data_file, buf); + lineno := lineno + 1; + check_sum_vec := (OTHERS => '0'); + if (buf(buf'LOW) = ':') then + i := 1; + shrink_line(buf, i); + READ(L=>buf, VALUE=>byte, good=>booval); + if not (booval) then + ASSERT FALSE + REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format!" + SEVERITY ERROR; + end if; + ibyte := hex_str_to_int(byte); + check_sum_vec := unsigned(check_sum_vec) + to_unsigned(ibyte, 8); + READ(L=>buf, VALUE=>startadd, good=>booval); + if not (booval) then + ASSERT FALSE + REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format! " + SEVERITY ERROR; + end if; + istartadd := hex_str_to_int(startadd); + addr(2) := startadd(4); + addr(1) := startadd(3); + check_sum_vec := unsigned(check_sum_vec) + to_unsigned(hex_str_to_int(addr), check_sum_vec'length); + addr(2) := startadd(2); + addr(1) := startadd(1); + check_sum_vec := unsigned(check_sum_vec) + to_unsigned(hex_str_to_int(addr), check_sum_vec'length); + READ(L=>buf, VALUE=>rec_type, good=>booval); + if not (booval) then + ASSERT FALSE + REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format! " + SEVERITY ERROR; + end if; + check_sum_vec := unsigned(check_sum_vec) + to_unsigned(hex_str_to_int(rec_type), check_sum_vec'length); + else + ASSERT FALSE + REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format! " + SEVERITY ERROR; + end if; + case rec_type is + when "00"=> -- Data record + i := 0; + k := lpm_width / 8; + if ((lpm_width MOD 8) /= 0) then + k := k + 1; + end if; + -- k = no. of bytes per CAM entry. + while (i < ibyte) loop + mem_data_tmp := 0; + for j in 1 to k loop + READ(L=>buf, VALUE=>datain,good=>booval); -- read in data a byte (2 hex chars) at a time. + if not (booval) then + ASSERT FALSE + REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format! " + SEVERITY ERROR; + end if; + check_sum_vec := unsigned(check_sum_vec) + to_unsigned(hex_str_to_int(datain), check_sum_vec'length); + mem_data_tmp := mem_data_tmp * 256 + hex_str_to_int(datain); + end loop; + i := i + k; + mem_data(ibase + istartadd) := STD_LOGIC_VECTOR(to_unsigned(mem_data_tmp, lpm_width)); + istartadd := istartadd + 1; + end loop; + when "01"=> + exit; + when "02"=> + ibase := 0; + if (ibyte /= 2) then + ASSERT FALSE + REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format for record type 02! " + SEVERITY ERROR; + end if; + for i in 0 to (ibyte-1) loop + READ(L=>buf, VALUE=>base,good=>booval); + ibase := ibase * 256 + hex_str_to_int(base); + if not (booval) then + ASSERT FALSE + REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format! " + SEVERITY ERROR; + end if; + check_sum_vec := unsigned(check_sum_vec) + to_unsigned(hex_str_to_int(base), check_sum_vec'length); + end loop; + ibase := ibase * 16; + when OTHERS => + ASSERT FALSE + REPORT "[Line "& int_to_str(lineno) & "]:Illegal record type in Intel Hex File! " + SEVERITY ERROR; + end case; + READ(L=>buf, VALUE=>checksum,good=>booval); + if not (booval) then + ASSERT FALSE + REPORT "[Line "& int_to_str(lineno) & "]:Checksum is missing! " + SEVERITY ERROR; + end if; + + check_sum_vec := unsigned(not (check_sum_vec)) + 1 ; + check_sum_vec_tmp := to_unsigned(hex_str_to_int(checksum),8); + + if (unsigned(check_sum_vec) /= unsigned(check_sum_vec_tmp)) then + ASSERT FALSE + REPORT "[Line "& int_to_str(lineno) & "]:Incorrect checksum!" + SEVERITY ERROR; + end if; + end loop; + end if; + mem_init := TRUE; + end if; + + -- MEMORY FUNCTION -- + --if memenab = '1' then + q_tmp <= mem_data(to_integer(UNSIGNED(address_tmp))); + --else + -- q_tmp <= (OTHERS => 'Z'); + --end if; + end process; + +end LPM_SYN; + + +--------------------------------------------------------------------------- + + +-- pragma translate_off +configuration lpm_rom_c0 of lpm_rom is + + for lpm_syn + end for; + +end lpm_rom_c0; +-- pragma translate_on diff --git a/rtl/t48/rtl/vhdl/system/syn_ram-e.vhd b/rtl/t48/rtl/vhdl/system/syn_ram-e.vhd new file mode 100644 index 0000000..4505949 --- /dev/null +++ b/rtl/t48/rtl/vhdl/system/syn_ram-e.vhd @@ -0,0 +1,73 @@ +------------------------------------------------------------------------------- +-- +-- A synchronous parametrizable RAM. +-- +-- $Id: syn_ram-e.vhd,v 1.1 2004/03/24 21:32:27 arniml Exp $ +-- +-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t48/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity syn_ram is + + generic ( + address_width_g : positive := 8 + ); + port ( + clk_i : in std_logic; + res_i : in std_logic; + ram_addr_i : in std_logic_vector(address_width_g-1 downto 0); + ram_data_i : in std_logic_vector(7 downto 0); + ram_we_i : in std_logic; + ram_data_o : out std_logic_vector(7 downto 0) + ); + +end syn_ram; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: syn_ram-e.vhd,v $ +-- Revision 1.1 2004/03/24 21:32:27 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t48/rtl/vhdl/system/syn_ram-lpm-a.vhd b/rtl/t48/rtl/vhdl/system/syn_ram-lpm-a.vhd new file mode 100644 index 0000000..47df03d --- /dev/null +++ b/rtl/t48/rtl/vhdl/system/syn_ram-lpm-a.vhd @@ -0,0 +1,120 @@ +------------------------------------------------------------------------------- +-- +-- A synchronous parametrizable RAM instantiating a standard RAM from +-- the Altera LPM. +-- +-- $Id: syn_ram-lpm-a.vhd,v 1.4 2005/11/14 21:12:57 arniml Exp $ +-- +-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t48/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +architecture lpm of syn_ram is + + component lpm_ram_dq + generic ( + LPM_WIDTH : positive; + LPM_TYPE : string := "LPM_RAM_DQ"; + LPM_WIDTHAD : positive; + LPM_NUMWORDS : natural := 0; + LPM_FILE : string := "UNUSED"; + LPM_INDATA : string := "REGISTERED"; + LPM_ADDRESS_CONTROL : string := "REGISTERED"; + LPM_OUTDATA : string := "UNREGISTERED"; + LPM_HINT : string := "UNUSED" + ); + port ( + data : in std_logic_vector(LPM_WIDTH-1 downto 0); + address : in std_logic_vector(LPM_WIDTHAD-1 downto 0); + we : in std_logic; + inclock : in std_logic; + outclock : in std_logic; + q : out std_logic_vector(LPM_WIDTH-1 downto 0) + ); + end component; + + signal zero_s : std_logic; + +begin + + zero_s <= '0'; + + ram_b : lpm_ram_dq + generic map ( + LPM_WIDTH => 8, + LPM_TYPE => "LPM_RAM_DQ", + LPM_WIDTHAD => address_width_g, + LPM_NUMWORDS => 2 ** address_width_g, + LPM_FILE => "UNUSED", + LPM_INDATA => "REGISTERED", + LPM_ADDRESS_CONTROL => "REGISTERED", + LPM_OUTDATA => "UNREGISTERED", + LPM_HINT => "UNUSED" + ) + port map ( + data => ram_data_i, + address => ram_addr_i, + we => ram_we_i, + inclock => clk_i, + outclock => clk_i, + q => ram_data_o + ); + +end lpm; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: syn_ram-lpm-a.vhd,v $ +-- Revision 1.4 2005/11/14 21:12:57 arniml +-- assign clk_i to outclock +-- +-- Revision 1.3 2005/09/07 17:39:34 arniml +-- fix missing assignment to outclock +-- +-- Revision 1.2 2004/04/07 22:09:08 arniml +-- remove unused signals +-- +-- Revision 1.1 2004/03/24 21:32:27 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t48/rtl/vhdl/system/syn_ram-lpm-c.vhd b/rtl/t48/rtl/vhdl/system/syn_ram-lpm-c.vhd new file mode 100644 index 0000000..448b456 --- /dev/null +++ b/rtl/t48/rtl/vhdl/system/syn_ram-lpm-c.vhd @@ -0,0 +1,34 @@ +------------------------------------------------------------------------------- +-- +-- A synchronous parametrizable RAM instantiating a standard RAM from +-- the Altera LPM. +-- +-- $Id: syn_ram-lpm-c.vhd,v 1.1 2004/03/24 21:32:27 arniml Exp $ +-- +-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +configuration syn_ram_lpm_c0 of syn_ram is + + for lpm + + for ram_b : lpm_ram_dq + use configuration work.lpm_ram_dq_c0; + end for; + + end for; + +end syn_ram_lpm_c0; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: syn_ram-lpm-c.vhd,v $ +-- Revision 1.1 2004/03/24 21:32:27 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t48/rtl/vhdl/system/syn_rom-e.vhd b/rtl/t48/rtl/vhdl/system/syn_rom-e.vhd new file mode 100644 index 0000000..5cc9447 --- /dev/null +++ b/rtl/t48/rtl/vhdl/system/syn_rom-e.vhd @@ -0,0 +1,60 @@ +------------------------------------------------------------------------------- +-- +-- A synchronous parametrizable ROM. +-- +-- $Id: syn_rom-e.vhd,v 1.1 2004/03/24 21:32:27 arniml Exp $ +-- +-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t48/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity syn_rom is + + generic ( + address_width_g : positive := 10 + ); + port ( + clk_i : in std_logic; + rom_addr_i : in std_logic_vector(address_width_g-1 downto 0); + rom_data_o : out std_logic_vector(7 downto 0) + ); + +end syn_rom; diff --git a/rtl/t48/rtl/vhdl/system/syn_rom-lpm-a.vhd b/rtl/t48/rtl/vhdl/system/syn_rom-lpm-a.vhd new file mode 100644 index 0000000..6747db8 --- /dev/null +++ b/rtl/t48/rtl/vhdl/system/syn_rom-lpm-a.vhd @@ -0,0 +1,115 @@ +------------------------------------------------------------------------------- +-- +-- A synchronous parametrizable ROM instantiating a standard ROM from +-- the Altera LPM. +-- +-- $Id: syn_rom-lpm-a.vhd,v 1.3 2005/11/14 21:13:05 arniml Exp $ +-- +-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t48/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +architecture lpm of syn_rom is + + component lpm_rom + generic ( + LPM_WIDTH : positive; + LPM_TYPE : string := "LPM_ROM"; + LPM_WIDTHAD : positive; + LPM_NUMWORDS : natural := 0; + LPM_FILE : string; + LPM_ADDRESS_CONTROL : string := "REGISTERED"; + LPM_OUTDATA : string := "REGISTERED"; + LPM_HINT : string := "UNUSED" + ); + port ( + address : in std_logic_vector(LPM_WIDTHAD-1 downto 0); + inclock : in std_logic; + outclock : in std_logic; + memenab : in std_logic; + q : out std_logic_vector(LPM_WIDTH-1 downto 0) + ); + end component; + + signal one_s, + zero_s : std_logic; + +begin + + one_s <= '1'; + zero_s <= '0'; + + rom_b : lpm_rom + generic map ( + LPM_WIDTH => 8, + LPM_TYPE => "LPM_ROM", + LPM_WIDTHAD => address_width_g, + LPM_NUMWORDS => 2 ** address_width_g, + LPM_FILE => "t48_rom.hex", + LPM_ADDRESS_CONTROL => "REGISTERED", + LPM_OUTDATA => "UNREGISTERED", + LPM_HINT => "UNUSED" + ) + port map ( + address => rom_addr_i, + inclock => clk_i, + outclock => clk_i, + memenab => one_s, + q => rom_data_o + ); + +end lpm; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: syn_rom-lpm-a.vhd,v $ +-- Revision 1.3 2005/11/14 21:13:05 arniml +-- assign clk_i to outclock +-- +-- Revision 1.2 2005/09/07 17:39:34 arniml +-- fix missing assignment to outclock +-- +-- Revision 1.1 2004/03/24 21:32:27 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t48/rtl/vhdl/system/syn_rom-lpm-c.vhd b/rtl/t48/rtl/vhdl/system/syn_rom-lpm-c.vhd new file mode 100644 index 0000000..6706e6d --- /dev/null +++ b/rtl/t48/rtl/vhdl/system/syn_rom-lpm-c.vhd @@ -0,0 +1,34 @@ +------------------------------------------------------------------------------- +-- +-- A synchronous parametrizable ROM instantiating a standard ROM from +-- the Altera LPM. +-- +-- $Id: syn_rom-lpm-c.vhd,v 1.1 2004/03/24 21:32:27 arniml Exp $ +-- +-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +configuration syn_rom_lpm_c0 of syn_rom is + + for lpm + + for rom_b : lpm_rom + use configuration work.lpm_rom_c0; + end for; + + end for; + +end syn_rom_lpm_c0; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: syn_rom-lpm-c.vhd,v $ +-- Revision 1.1 2004/03/24 21:32:27 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t48/rtl/vhdl/system/t48_system_comp_pack-p.vhd b/rtl/t48/rtl/vhdl/system/t48_system_comp_pack-p.vhd new file mode 100644 index 0000000..e465f55 --- /dev/null +++ b/rtl/t48/rtl/vhdl/system/t48_system_comp_pack-p.vhd @@ -0,0 +1,175 @@ +------------------------------------------------------------------------------- +-- +-- $Id: t48_system_comp_pack-p.vhd,v 1.7 2005/11/01 21:37:10 arniml Exp $ +-- +-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +package t48_system_comp_pack is + + component t48_wb_master + port ( + xtal_i : in std_logic; + res_i : in std_logic; + en_clk_o : out std_logic; + ale_i : in std_logic; + rd_n_i : in std_logic; + wr_n_i : in std_logic; + adr_i : in std_logic; + db_bus_i : in std_logic_vector( 7 downto 0); + db_bus_o : out std_logic_vector( 7 downto 0); + wb_cyc_o : out std_logic; + wb_stb_o : out std_logic; + wb_we_o : out std_logic; + wb_adr_o : out std_logic_vector(23 downto 0); + wb_ack_i : in std_logic; + wb_dat_i : in std_logic_vector( 7 downto 0); + wb_dat_o : out std_logic_vector( 7 downto 0) + ); + end component; + + component t8048_notri + generic ( + gate_port_input_g : integer := 1 + ); + + port ( + xtal_i : in std_logic; + reset_n_i : in std_logic; + t0_i : in std_logic; + t0_o : out std_logic; + t0_dir_o : out std_logic; + int_n_i : in std_logic; + ea_i : in std_logic; + rd_n_o : out std_logic; + psen_n_o : out std_logic; + wr_n_o : out std_logic; + ale_o : out std_logic; + db_i : in std_logic_vector( 7 downto 0); + db_o : out std_logic_vector( 7 downto 0); + db_dir_o : out std_logic; + t1_i : in std_logic; + p2_i : in std_logic_vector( 7 downto 0); + p2_o : out std_logic_vector( 7 downto 0); + p2l_low_imp_o : out std_logic; + p2h_low_imp_o : out std_logic; + p1_i : in std_logic_vector( 7 downto 0); + p1_o : out std_logic_vector( 7 downto 0); + p1_low_imp_o : out std_logic; + prog_n_o : out std_logic + ); + end component; + + component t8039_notri + generic ( + gate_port_input_g : integer := 1 + ); + + port ( + xtal_i : in std_logic; + reset_n_i : in std_logic; + t0_i : in std_logic; + t0_o : out std_logic; + t0_dir_o : out std_logic; + int_n_i : in std_logic; + ea_i : in std_logic; + rd_n_o : out std_logic; + psen_n_o : out std_logic; + wr_n_o : out std_logic; + ale_o : out std_logic; + db_i : in std_logic_vector( 7 downto 0); + db_o : out std_logic_vector( 7 downto 0); + db_dir_o : out std_logic; + t1_i : in std_logic; + p2_i : in std_logic_vector( 7 downto 0); + p2_o : out std_logic_vector( 7 downto 0); + p2l_low_imp_o : out std_logic; + p2h_low_imp_o : out std_logic; + p1_i : in std_logic_vector( 7 downto 0); + p1_o : out std_logic_vector( 7 downto 0); + p1_low_imp_o : out std_logic; + prog_n_o : out std_logic + ); + end component; + + component t8050_wb + generic ( + gate_port_input_g : integer := 1 + ); + + port ( + xtal_i : in std_logic; + reset_n_i : in std_logic; + t0_i : in std_logic; + t0_o : out std_logic; + t0_dir_o : out std_logic; + int_n_i : in std_logic; + ea_i : in std_logic; + rd_n_o : out std_logic; + psen_n_o : out std_logic; + wr_n_o : out std_logic; + ale_o : out std_logic; + t1_i : in std_logic; + p2_i : in std_logic_vector( 7 downto 0); + p2_o : out std_logic_vector( 7 downto 0); + p2l_low_imp_o : out std_logic; + p2h_low_imp_o : out std_logic; + p1_i : in std_logic_vector( 7 downto 0); + p1_o : out std_logic_vector( 7 downto 0); + p1_low_imp_o : out std_logic; + prog_n_o : out std_logic; + wb_cyc_o : out std_logic; + wb_stb_o : out std_logic; + wb_we_o : out std_logic; + wb_adr_o : out std_logic_vector(23 downto 0); + wb_ack_i : in std_logic; + wb_dat_i : in std_logic_vector( 7 downto 0); + wb_dat_o : out std_logic_vector( 7 downto 0) + ); + end component; + + component t8048 + port ( + xtal_i : in std_logic; + reset_n_i : in std_logic; + t0_b : inout std_logic; + int_n_i : in std_logic; + ea_i : in std_logic; + rd_n_o : out std_logic; + psen_n_o : out std_logic; + wr_n_o : out std_logic; + ale_o : out std_logic; + db_b : inout std_logic_vector( 7 downto 0); + t1_i : in std_logic; + p2_b : inout std_logic_vector( 7 downto 0); + p1_b : inout std_logic_vector( 7 downto 0); + prog_n_o : out std_logic + ); + end component; + + component t8039 + port ( + xtal_i : in std_logic; + reset_n_i : in std_logic; + t0_b : inout std_logic; + int_n_i : in std_logic; + ea_i : in std_logic; + rd_n_o : out std_logic; + psen_n_o : out std_logic; + wr_n_o : out std_logic; + ale_o : out std_logic; + db_b : inout std_logic_vector( 7 downto 0); + t1_i : in std_logic; + p2_b : inout std_logic_vector( 7 downto 0); + p1_b : inout std_logic_vector( 7 downto 0); + prog_n_o : out std_logic + ); + end component; + +end t48_system_comp_pack; diff --git a/rtl/t48/rtl/vhdl/system/t8039-c.vhd b/rtl/t48/rtl/vhdl/system/t8039-c.vhd new file mode 100644 index 0000000..1daac1a --- /dev/null +++ b/rtl/t48/rtl/vhdl/system/t8039-c.vhd @@ -0,0 +1,23 @@ +------------------------------------------------------------------------------- +-- +-- T8039 Microcontroller System +-- +-- $Id: t8039-c.vhd,v 1.2 2004/12/03 19:43:12 arniml Exp $ +-- +-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +configuration t8039_struct_c0 of t8039 is + + for struct + + for t8039_notri_b : t8039_notri + use configuration work.t8039_notri_struct_c0; + end for; + + end for; + +end t8039_struct_c0; diff --git a/rtl/t48/rtl/vhdl/system/t8039.vhd b/rtl/t48/rtl/vhdl/system/t8039.vhd new file mode 100644 index 0000000..5b3481c --- /dev/null +++ b/rtl/t48/rtl/vhdl/system/t8039.vhd @@ -0,0 +1,193 @@ +------------------------------------------------------------------------------- +-- +-- T8039 Microcontroller System +-- +-- $Id: t8039.vhd,v 1.5 2005/11/02 23:41:43 arniml Exp $ +-- +-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t48/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity t8039 is + + port ( + xtal_i : in std_logic; + reset_n_i : in std_logic; + t0_b : inout std_logic; + int_n_i : in std_logic; + ea_i : in std_logic; + rd_n_o : out std_logic; + psen_n_o : out std_logic; + wr_n_o : out std_logic; + ale_o : out std_logic; + db_b : inout std_logic_vector( 7 downto 0); + t1_i : in std_logic; + p2_b : inout std_logic_vector( 7 downto 0); + p1_b : inout std_logic_vector( 7 downto 0); + prog_n_o : out std_logic + ); + +end t8039; + + +use work.t48_system_comp_pack.t8039_notri; + +architecture struct of t8039 is + + signal t0_s : std_logic; + signal t0_dir_s : std_logic; + signal db_s : std_logic_vector( 7 downto 0); + signal db_dir_s : std_logic; + signal p2_s : std_logic_vector( 7 downto 0); + signal p2l_low_imp_s : std_logic; + signal p2h_low_imp_s : std_logic; + signal p1_s : std_logic_vector( 7 downto 0); + signal p1_low_imp_s : std_logic; + +begin + + t8039_notri_b : t8039_notri + generic map ( + -- we don't need explicit gating of input ports + -- this is done implicitely by the bidirectional pads + gate_port_input_g => 0 + ) + + port map ( + xtal_i => xtal_i, + reset_n_i => reset_n_i, + t0_i => t0_b, + t0_o => t0_s, + t0_dir_o => t0_dir_s, + int_n_i => int_n_i, + ea_i => ea_i, + rd_n_o => rd_n_o, + psen_n_o => psen_n_o, + wr_n_o => wr_n_o, + ale_o => ale_o, + db_i => db_b, + db_o => db_s, + db_dir_o => db_dir_s, + t1_i => t1_i, + p2_i => p2_b, + p2_o => p2_s, + p2l_low_imp_o => p2l_low_imp_s, + p2h_low_imp_o => p2h_low_imp_s, + p1_i => p1_b, + p1_o => p1_s, + p1_low_imp_o => p1_low_imp_s, + prog_n_o => prog_n_o + ); + + ----------------------------------------------------------------------------- + -- Process bidirs + -- + -- Purpose: + -- Assign bidirectional signals. + -- + bidirs: process (t0_b, t0_s, t0_dir_s, + db_b, db_s, db_dir_s, + p1_b, p1_s, p1_low_imp_s, + p2_b, p2_s, p2l_low_imp_s, p2h_low_imp_s) + + function port_bidir_f(port_value : in std_logic_vector; + low_imp : in std_logic) return std_logic_vector is + variable result_v : std_logic_vector(port_value'range); + begin + for idx in port_value'high downto port_value'low loop + if low_imp = '1' then + result_v(idx) := port_value(idx); + elsif port_value(idx) = '0' then + result_v(idx) := '0'; + else + result_v(idx) := 'Z'; + end if; + end loop; + + return result_v; + end; + + begin + -- Test 0 ----------------------------------------------------------------- + if t0_dir_s = '1' then + t0_b <= t0_s; + else + t0_b <= 'Z'; + end if; + + -- Data Bus --------------------------------------------------------------- + if db_dir_s = '1' then + db_b <= db_s; + else + db_b <= (others => 'Z'); + end if; + + -- Port 1 ----------------------------------------------------------------- + p1_b <= port_bidir_f(port_value => p1_s, + low_imp => p1_low_imp_s); + + -- Port 2 ----------------------------------------------------------------- + p2_b(3 downto 0) <= port_bidir_f(port_value => p2_s(3 downto 0), + low_imp => p2l_low_imp_s); + p2_b(7 downto 4) <= port_bidir_f(port_value => p2_s(7 downto 4), + low_imp => p2h_low_imp_s); + + end process bidirs; + -- + ----------------------------------------------------------------------------- + +end struct; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t8039.vhd,v $ +-- Revision 1.5 2005/11/02 23:41:43 arniml +-- properly drive P1 and P2 with low impedance markers +-- +-- Revision 1.4 2005/11/01 21:37:45 arniml +-- wire signals for P2 low impedance marker issue +-- +-- Revision 1.3 2004/12/03 19:43:12 arniml +-- added hierarchy t8039_notri +-- +------------------------------------------------------------------------------- diff --git a/rtl/t48/rtl/vhdl/system/t8039_notri-c.vhd b/rtl/t48/rtl/vhdl/system/t8039_notri-c.vhd new file mode 100644 index 0000000..53904f6 --- /dev/null +++ b/rtl/t48/rtl/vhdl/system/t8039_notri-c.vhd @@ -0,0 +1,28 @@ +------------------------------------------------------------------------------- +-- +-- T8039 Microcontroller System +-- 8039 toplevel without tri-states +-- +-- $Id: t8039_notri-c.vhd,v 1.1 2004/12/03 19:42:34 arniml Exp $ +-- +-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +configuration t8039_notri_struct_c0 of t8039_notri is + + for struct + + for ram_128_b : syn_ram + use configuration work.syn_ram_lpm_c0; + end for; + + for t48_core_b : t48_core + use configuration work.t48_core_struct_c0; + end for; + + end for; + +end t8039_notri_struct_c0; diff --git a/rtl/t48/rtl/vhdl/system/t8039_notri.vhd b/rtl/t48/rtl/vhdl/system/t8039_notri.vhd new file mode 100644 index 0000000..75f1d14 --- /dev/null +++ b/rtl/t48/rtl/vhdl/system/t8039_notri.vhd @@ -0,0 +1,211 @@ +------------------------------------------------------------------------------- +-- +-- T8039 Microcontroller System +-- 8039 toplevel without tri-states +-- +-- $Id: t8039_notri.vhd,v 1.2 2005/11/01 21:38:10 arniml Exp $ +-- +-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t48/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity t8039_notri is + + generic ( + gate_port_input_g : integer := 1 + ); + + port ( + xtal_i : in std_logic; + reset_n_i : in std_logic; + t0_i : in std_logic; + t0_o : out std_logic; + t0_dir_o : out std_logic; + int_n_i : in std_logic; + ea_i : in std_logic; + rd_n_o : out std_logic; + psen_n_o : out std_logic; + wr_n_o : out std_logic; + ale_o : out std_logic; + db_i : in std_logic_vector( 7 downto 0); + db_o : out std_logic_vector( 7 downto 0); + db_dir_o : out std_logic; + t1_i : in std_logic; + p2_i : in std_logic_vector( 7 downto 0); + p2_o : out std_logic_vector( 7 downto 0); + p2l_low_imp_o : out std_logic; + p2h_low_imp_o : out std_logic; + p1_i : in std_logic_vector( 7 downto 0); + p1_o : out std_logic_vector( 7 downto 0); + p1_low_imp_o : out std_logic; + prog_n_o : out std_logic + ); + +end t8039_notri; + + +library ieee; +use ieee.numeric_std.all; + +use work.t48_core_comp_pack.t48_core; +use work.t48_core_comp_pack.syn_rom; +use work.t48_core_comp_pack.syn_ram; + +architecture struct of t8039_notri is + + signal xtal3_s : std_logic; + signal dmem_addr_s : std_logic_vector( 7 downto 0); + signal dmem_we_s : std_logic; + signal dmem_data_from_s : std_logic_vector( 7 downto 0); + signal dmem_data_to_s : std_logic_vector( 7 downto 0); + signal pmem_data_s : std_logic_vector( 7 downto 0); + + signal p1_in_s, + p1_out_s : std_logic_vector( 7 downto 0); + signal p2_in_s, + p2_out_s : std_logic_vector( 7 downto 0); + +begin + + ----------------------------------------------------------------------------- + -- Check generics for valid values. + ----------------------------------------------------------------------------- + -- pragma translate_off + assert gate_port_input_g = 0 or gate_port_input_g = 1 + report "gate_port_input_g must be either 1 or 0!" + severity failure; + -- pragma translate_on + + + -- no Program memory available + pmem_data_s <= (others => '0'); + + + t48_core_b : t48_core + generic map ( + xtal_div_3_g => 1, + register_mnemonic_g => 1, + include_port1_g => 1, + include_port2_g => 1, + include_bus_g => 1, + include_timer_g => 1, + sample_t1_state_g => 4 + ) + port map ( + xtal_i => xtal_i, + reset_i => reset_n_i, + t0_i => t0_i, + t0_o => t0_o, + t0_dir_o => t0_dir_o, + int_n_i => int_n_i, + ea_i => ea_i, + rd_n_o => rd_n_o, + psen_n_o => psen_n_o, + wr_n_o => wr_n_o, + ale_o => ale_o, + db_i => db_i, + db_o => db_o, + db_dir_o => db_dir_o, + t1_i => t1_i, + p2_i => p2_in_s, + p2_o => p2_out_s, + p2l_low_imp_o => p2l_low_imp_o, + p2h_low_imp_o => p2h_low_imp_o, + p1_i => p1_in_s, + p1_o => p1_out_s, + p1_low_imp_o => p1_low_imp_o, + prog_n_o => prog_n_o, + clk_i => xtal_i, + en_clk_i => xtal3_s, + xtal3_o => xtal3_s, + dmem_addr_o => dmem_addr_s, + dmem_we_o => dmem_we_s, + dmem_data_i => dmem_data_from_s, + dmem_data_o => dmem_data_to_s, + pmem_addr_o => open, + pmem_data_i => pmem_data_s + ); + + + ----------------------------------------------------------------------------- + -- Gate port 1 and 2 input bus with respetive output value + ----------------------------------------------------------------------------- + gate_ports: if gate_port_input_g = 1 generate + p1_in_s <= p1_i and p1_out_s; + p2_in_s <= p2_i and p2_out_s; + end generate; + + pass_ports: if gate_port_input_g = 0 generate + p1_in_s <= p1_i; + p2_in_s <= p2_i; + end generate; + + p1_o <= p1_out_s; + p2_o <= p2_out_s; + + + ram_128_b : syn_ram + generic map ( + address_width_g => 7 + ) + port map ( + clk_i => xtal_i, + res_i => reset_n_i, + ram_addr_i => dmem_addr_s(6 downto 0), + ram_data_i => dmem_data_to_s, + ram_we_i => dmem_we_s, + ram_data_o => dmem_data_from_s + ); + +end struct; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t8039_notri.vhd,v $ +-- Revision 1.2 2005/11/01 21:38:10 arniml +-- wire signals for P2 low impedance marker issue +-- +-- Revision 1.1 2004/12/03 19:42:34 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t48/rtl/vhdl/system/t8048-c.vhd b/rtl/t48/rtl/vhdl/system/t8048-c.vhd new file mode 100644 index 0000000..b3d7d0a --- /dev/null +++ b/rtl/t48/rtl/vhdl/system/t8048-c.vhd @@ -0,0 +1,23 @@ +------------------------------------------------------------------------------- +-- +-- T8048 Microcontroller System +-- +-- $Id: t8048-c.vhd,v 1.2 2004/12/01 23:09:47 arniml Exp $ +-- +-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +configuration t8048_struct_c0 of t8048 is + + for struct + + for t8048_notri_b : t8048_notri + use configuration work.t8048_notri_struct_c0; + end for; + + end for; + +end t8048_struct_c0; diff --git a/rtl/t48/rtl/vhdl/system/t8048.vhd b/rtl/t48/rtl/vhdl/system/t8048.vhd new file mode 100644 index 0000000..03b5206 --- /dev/null +++ b/rtl/t48/rtl/vhdl/system/t8048.vhd @@ -0,0 +1,219 @@ +------------------------------------------------------------------------------- +-- +-- T8048 Microcontroller System +-- +-- $Id: t8048.vhd,v 1.9 2005/11/02 23:41:43 arniml Exp $ +-- +-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t48/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity t8048 is + + port ( + xtal_i : in std_logic; + reset_n_i : in std_logic; + t0_b : inout std_logic; + int_n_i : in std_logic; + ea_i : in std_logic; + rd_n_o : out std_logic; + psen_n_o : out std_logic; + wr_n_o : out std_logic; + ale_o : out std_logic; + db_b : inout std_logic_vector( 7 downto 0); + t1_i : in std_logic; + p2_b : inout std_logic_vector( 7 downto 0); + p1_b : inout std_logic_vector( 7 downto 0); + prog_n_o : out std_logic + ); + +end t8048; + + +library ieee; +use ieee.numeric_std.all; + +use work.t48_system_comp_pack.t8048_notri; + +architecture struct of t8048 is + + signal t0_s : std_logic; + signal t0_dir_s : std_logic; + signal db_s : std_logic_vector( 7 downto 0); + signal db_dir_s : std_logic; + signal p2_s : std_logic_vector( 7 downto 0); + signal p2l_low_imp_s : std_logic; + signal p2h_low_imp_s : std_logic; + signal p1_s : std_logic_vector( 7 downto 0); + signal p1_low_imp_s : std_logic; + +begin + + t8048_notri_b : t8048_notri + generic map ( + -- we don't need explicit gating of input ports + -- this is done implicitely by the bidirectional pads + gate_port_input_g => 0 + ) + + port map ( + xtal_i => xtal_i, + reset_n_i => reset_n_i, + t0_i => t0_b, + t0_o => t0_s, + t0_dir_o => t0_dir_s, + int_n_i => int_n_i, + ea_i => ea_i, + rd_n_o => rd_n_o, + psen_n_o => psen_n_o, + wr_n_o => wr_n_o, + ale_o => ale_o, + db_i => db_b, + db_o => db_s, + db_dir_o => db_dir_s, + t1_i => t1_i, + p2_i => p2_b, + p2_o => p2_s, + p2l_low_imp_o => p2l_low_imp_s, + p2h_low_imp_o => p2h_low_imp_s, + p1_i => p1_b, + p1_o => p1_s, + p1_low_imp_o => p1_low_imp_s, + prog_n_o => prog_n_o + ); + + ----------------------------------------------------------------------------- + -- Process bidirs + -- + -- Purpose: + -- Assign bidirectional signals. + -- + bidirs: process (t0_b, t0_s, t0_dir_s, + db_b, db_s, db_dir_s, + p1_b, p1_s, p1_low_imp_s, + p2_b, p2_s, p2l_low_imp_s, p2h_low_imp_s) + + function port_bidir_f(port_value : in std_logic_vector; + low_imp : in std_logic) return std_logic_vector is + variable result_v : std_logic_vector(port_value'range); + begin + for idx in port_value'high downto port_value'low loop + if low_imp = '1' then + result_v(idx) := port_value(idx); + elsif port_value(idx) = '0' then + result_v(idx) := '0'; + else + result_v(idx) := 'Z'; + end if; + end loop; + + return result_v; + end; + + begin + -- Test 0 ----------------------------------------------------------------- + if t0_dir_s = '1' then + t0_b <= t0_s; + else + t0_b <= 'Z'; + end if; + + -- Data Bus --------------------------------------------------------------- + if db_dir_s = '1' then + db_b <= db_s; + else + db_b <= (others => 'Z'); + end if; + + -- Port 1 ----------------------------------------------------------------- + p1_b <= port_bidir_f(port_value => p1_s, + low_imp => p1_low_imp_s); + + -- Port 2 ----------------------------------------------------------------- + p2_b(3 downto 0) <= port_bidir_f(port_value => p2_s(3 downto 0), + low_imp => p2l_low_imp_s); + p2_b(7 downto 4) <= port_bidir_f(port_value => p2_s(7 downto 4), + low_imp => p2h_low_imp_s); + + end process bidirs; + -- + ----------------------------------------------------------------------------- + + +end struct; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t8048.vhd,v $ +-- Revision 1.9 2005/11/02 23:41:43 arniml +-- properly drive P1 and P2 with low impedance markers +-- +-- Revision 1.8 2005/11/01 21:38:31 arniml +-- wire signals for P2 low impedance marker issue +-- +-- Revision 1.7 2004/12/03 19:44:36 arniml +-- removed obsolete constant +-- +-- Revision 1.6 2004/12/02 22:08:42 arniml +-- introduced generic gate_port_input_g +-- forces masking of P1 and P2 input bus +-- +-- Revision 1.5 2004/12/01 23:09:47 arniml +-- intruduced hierarchy t8048_notri where all system functionality +-- except bidirectional ports is handled +-- +-- Revision 1.4 2004/10/24 09:10:16 arniml +-- Fix for: +-- P1 constantly in push-pull mode in t8048 +-- +-- Revision 1.3 2004/05/20 21:58:26 arniml +-- Fix for: +-- External Program Memory ignored when EA = 0 +-- +-- Revision 1.2 2004/03/29 19:40:14 arniml +-- rename pX_limp to pX_low_imp +-- +-- Revision 1.1 2004/03/24 21:32:27 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t48/rtl/vhdl/system/t8048_notri-c.vhd b/rtl/t48/rtl/vhdl/system/t8048_notri-c.vhd new file mode 100644 index 0000000..df5b1d5 --- /dev/null +++ b/rtl/t48/rtl/vhdl/system/t8048_notri-c.vhd @@ -0,0 +1,31 @@ +------------------------------------------------------------------------------- +-- +-- T8048 Microcontroller System +-- +-- $Id: t8048_notri-c.vhd,v 1.1 2004/12/01 23:07:21 arniml Exp $ +-- +-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +configuration t8048_notri_struct_c0 of t8048_notri is + + for struct + + for rom_1k_b : syn_rom + use configuration work.syn_rom_lpm_c0; + end for; + + for ram_64_b : syn_ram + use configuration work.syn_ram_lpm_c0; + end for; + + for t48_core_b : t48_core + use configuration work.t48_core_struct_c0; + end for; + + end for; + +end t8048_notri_struct_c0; diff --git a/rtl/t48/rtl/vhdl/system/t8048_notri.vhd b/rtl/t48/rtl/vhdl/system/t8048_notri.vhd new file mode 100644 index 0000000..8dbd352 --- /dev/null +++ b/rtl/t48/rtl/vhdl/system/t8048_notri.vhd @@ -0,0 +1,257 @@ +------------------------------------------------------------------------------- +-- +-- T8048 Microcontroller System +-- 8048 toplevel without tri-states +-- +-- $Id: t8048_notri.vhd,v 1.4 2005/11/01 21:38:48 arniml Exp $ +-- +-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t48/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity t8048_notri is + + generic ( + gate_port_input_g : integer := 1 + ); + + port ( + xtal_i : in std_logic; + reset_n_i : in std_logic; + t0_i : in std_logic; + t0_o : out std_logic; + t0_dir_o : out std_logic; + int_n_i : in std_logic; + ea_i : in std_logic; + rd_n_o : out std_logic; + psen_n_o : out std_logic; + wr_n_o : out std_logic; + ale_o : out std_logic; + db_i : in std_logic_vector( 7 downto 0); + db_o : out std_logic_vector( 7 downto 0); + db_dir_o : out std_logic; + t1_i : in std_logic; + p2_i : in std_logic_vector( 7 downto 0); + p2_o : out std_logic_vector( 7 downto 0); + p2l_low_imp_o : out std_logic; + p2h_low_imp_o : out std_logic; + p1_i : in std_logic_vector( 7 downto 0); + p1_o : out std_logic_vector( 7 downto 0); + p1_low_imp_o : out std_logic; + prog_n_o : out std_logic + ); + +end t8048_notri; + + +library ieee; +use ieee.numeric_std.all; + +use work.t48_core_comp_pack.t48_core; +use work.t48_core_comp_pack.syn_rom; +use work.t48_core_comp_pack.syn_ram; + +architecture struct of t8048_notri is + + -- Address width of internal ROM + constant rom_addr_width_c : natural := 10; + + signal xtal3_s : std_logic; + signal dmem_addr_s : std_logic_vector( 7 downto 0); + signal dmem_we_s : std_logic; + signal dmem_data_from_s : std_logic_vector( 7 downto 0); + signal dmem_data_to_s : std_logic_vector( 7 downto 0); + signal pmem_addr_s : std_logic_vector(11 downto 0); + signal pmem_data_s : std_logic_vector( 7 downto 0); + + signal ea_s : std_logic; + + signal p1_in_s, + p1_out_s : std_logic_vector( 7 downto 0); + signal p2_in_s, + p2_out_s : std_logic_vector( 7 downto 0); + +begin + + ----------------------------------------------------------------------------- + -- Check generics for valid values. + ----------------------------------------------------------------------------- + -- pragma translate_off + assert gate_port_input_g = 0 or gate_port_input_g = 1 + report "gate_port_input_g must be either 1 or 0!" + severity failure; + -- pragma translate_on + + + t48_core_b : t48_core + generic map ( + xtal_div_3_g => 1, + register_mnemonic_g => 1, + include_port1_g => 1, + include_port2_g => 1, + include_bus_g => 1, + include_timer_g => 1, + sample_t1_state_g => 4 + ) + port map ( + xtal_i => xtal_i, + reset_i => reset_n_i, + t0_i => t0_i, + t0_o => t0_o, + t0_dir_o => t0_dir_o, + int_n_i => int_n_i, + ea_i => ea_s, + rd_n_o => rd_n_o, + psen_n_o => psen_n_o, + wr_n_o => wr_n_o, + ale_o => ale_o, + db_i => db_i, + db_o => db_o, + db_dir_o => db_dir_o, + t1_i => t1_i, + p2_i => p2_in_s, + p2_o => p2_out_s, + p2l_low_imp_o => p2l_low_imp_o, + p2h_low_imp_o => p2h_low_imp_o, + p1_i => p1_in_s, + p1_o => p1_out_s, + p1_low_imp_o => p1_low_imp_o, + prog_n_o => prog_n_o, + clk_i => xtal_i, + en_clk_i => xtal3_s, + xtal3_o => xtal3_s, + dmem_addr_o => dmem_addr_s, + dmem_we_o => dmem_we_s, + dmem_data_i => dmem_data_from_s, + dmem_data_o => dmem_data_to_s, + pmem_addr_o => pmem_addr_s, + pmem_data_i => pmem_data_s + ); + + + ----------------------------------------------------------------------------- + -- Gate port 1 and 2 input bus with respetive output value + ----------------------------------------------------------------------------- + gate_ports: if gate_port_input_g = 1 generate + p1_in_s <= p1_i and p1_out_s; + p2_in_s <= p2_i and p2_out_s; + end generate; + + pass_ports: if gate_port_input_g = 0 generate + p1_in_s <= p1_i; + p2_in_s <= p2_i; + end generate; + + p1_o <= p1_out_s; + p2_o <= p2_out_s; + + + ----------------------------------------------------------------------------- + -- Process ea + -- + -- Purpose: + -- Detects access to external program memory. + -- Either by ea_i = '1' or when program memory address leaves address + -- range of internal ROM. + -- + ea: process (ea_i, + pmem_addr_s) + begin + if ea_i = '1' then + -- Forced external access + ea_s <= '1'; + + elsif unsigned(pmem_addr_s(11 downto rom_addr_width_c)) = 0 then + -- Internal access + ea_s <= '0'; + + else + -- Access to program memory out of internal range + ea_s <= '1'; + + end if; + + end process ea; + -- + ----------------------------------------------------------------------------- + + + rom_1k_b : syn_rom + generic map ( + address_width_g => rom_addr_width_c + ) + port map ( + clk_i => xtal_i, + rom_addr_i => pmem_addr_s(rom_addr_width_c-1 downto 0), + rom_data_o => pmem_data_s + ); + + ram_64_b : syn_ram + generic map ( + address_width_g => 6 + ) + port map ( + clk_i => xtal_i, + res_i => reset_n_i, + ram_addr_i => dmem_addr_s(5 downto 0), + ram_data_i => dmem_data_to_s, + ram_we_i => dmem_we_s, + ram_data_o => dmem_data_from_s + ); + +end struct; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t8048_notri.vhd,v $ +-- Revision 1.4 2005/11/01 21:38:48 arniml +-- wire signals for P2 low impedance marker issue +-- +-- Revision 1.3 2004/12/02 22:08:42 arniml +-- introduced generic gate_port_input_g +-- forces masking of P1 and P2 input bus +-- +-- Revision 1.2 2004/12/01 23:08:08 arniml +-- update +-- +------------------------------------------------------------------------------- diff --git a/rtl/t48/rtl/vhdl/system/t8050_wb-c.vhd b/rtl/t48/rtl/vhdl/system/t8050_wb-c.vhd new file mode 100644 index 0000000..1fe1ccc --- /dev/null +++ b/rtl/t48/rtl/vhdl/system/t8050_wb-c.vhd @@ -0,0 +1,35 @@ +------------------------------------------------------------------------------- +-- +-- T8048 Microcontroller System +-- +-- $Id: t8050_wb-c.vhd,v 1.2 2005/06/11 10:19:14 arniml Exp $ +-- +-- Copyright (c) 2005, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +configuration t8050_wb_struct_c0 of t8050_wb is + + for struct + + for rom_4k_b : syn_rom + use configuration work.syn_rom_lpm_c0; + end for; + + for ram_256_b : syn_ram + use configuration work.syn_ram_lpm_c0; + end for; + + for wb_master_b : t48_wb_master + use configuration work.t48_wb_master_rtl_c0; + end for; + + for t48_core_b : t48_core + use configuration work.t48_core_struct_c0; + end for; + + end for; + +end t8050_wb_struct_c0; diff --git a/rtl/t48/rtl/vhdl/system/t8050_wb.vhd b/rtl/t48/rtl/vhdl/system/t8050_wb.vhd new file mode 100644 index 0000000..32d513b --- /dev/null +++ b/rtl/t48/rtl/vhdl/system/t8050_wb.vhd @@ -0,0 +1,305 @@ +------------------------------------------------------------------------------- +-- +-- T8048 Microcontroller System +-- 8050 toplevel with Wishbone interface +-- +-- $Id: t8050_wb.vhd,v 1.3 2005/11/01 21:39:14 arniml Exp $ +-- +-- Copyright (c) 2005, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t48/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity t8050_wb is + + generic ( + gate_port_input_g : integer := 1 + ); + + port ( + -- T48 Interface ---------------------------------------------------------- + xtal_i : in std_logic; + reset_n_i : in std_logic; + t0_i : in std_logic; + t0_o : out std_logic; + t0_dir_o : out std_logic; + int_n_i : in std_logic; + ea_i : in std_logic; + rd_n_o : out std_logic; + psen_n_o : out std_logic; + wr_n_o : out std_logic; + ale_o : out std_logic; + t1_i : in std_logic; + p2_i : in std_logic_vector( 7 downto 0); + p2_o : out std_logic_vector( 7 downto 0); + p2l_low_imp_o : out std_logic; + p2h_low_imp_o : out std_logic; + p1_i : in std_logic_vector( 7 downto 0); + p1_o : out std_logic_vector( 7 downto 0); + p1_low_imp_o : out std_logic; + prog_n_o : out std_logic; + -- Wishbone Interface ----------------------------------------------------- + wb_cyc_o : out std_logic; + wb_stb_o : out std_logic; + wb_we_o : out std_logic; + wb_adr_o : out std_logic_vector(23 downto 0); + wb_ack_i : in std_logic; + wb_dat_i : in std_logic_vector( 7 downto 0); + wb_dat_o : out std_logic_vector( 7 downto 0) + + ); + +end t8050_wb; + + +library ieee; +use ieee.numeric_std.all; + +use work.t48_core_comp_pack.t48_core; +use work.t48_core_comp_pack.syn_rom; +use work.t48_core_comp_pack.syn_ram; +use work.t48_system_comp_pack.t48_wb_master; + +architecture struct of t8050_wb is + + -- Address width of internal ROM + constant rom_addr_width_c : natural := 12; + + signal xtal3_s : std_logic; + signal dmem_addr_s : std_logic_vector( 7 downto 0); + signal dmem_we_s : std_logic; + signal dmem_data_from_s : std_logic_vector( 7 downto 0); + signal dmem_data_to_s : std_logic_vector( 7 downto 0); + signal pmem_addr_s : std_logic_vector(11 downto 0); + signal pmem_data_s : std_logic_vector( 7 downto 0); + + signal ea_s : std_logic; + + signal ale_s : std_logic; + signal wr_n_s : std_logic; + signal rd_n_s : std_logic; + signal db_bus_to_t48, + db_bus_from_t48 : std_logic_vector( 7 downto 0); + + signal wb_en_clk_s : std_logic; + signal en_clk_s : std_logic; + + signal p1_in_s, + p1_out_s : std_logic_vector( 7 downto 0); + signal p2_in_s, + p2_out_s : std_logic_vector( 7 downto 0); + +begin + + ----------------------------------------------------------------------------- + -- Check generics for valid values. + ----------------------------------------------------------------------------- + -- pragma translate_off + assert gate_port_input_g = 0 or gate_port_input_g = 1 + report "gate_port_input_g must be either 1 or 0!" + severity failure; + -- pragma translate_on + + + t48_core_b : t48_core + generic map ( + xtal_div_3_g => 1, + register_mnemonic_g => 1, + include_port1_g => 1, + include_port2_g => 1, + include_bus_g => 1, + include_timer_g => 1, + sample_t1_state_g => 4 + ) + port map ( + xtal_i => xtal_i, + reset_i => reset_n_i, + t0_i => t0_i, + t0_o => t0_o, + t0_dir_o => t0_dir_o, + int_n_i => int_n_i, + ea_i => ea_s, + rd_n_o => rd_n_s, + psen_n_o => psen_n_o, + wr_n_o => wr_n_s, + ale_o => ale_s, + db_i => db_bus_to_t48, + db_o => db_bus_from_t48, + db_dir_o => open, + t1_i => t1_i, + p2_i => p2_in_s, + p2_o => p2_out_s, + p2l_low_imp_o => p2l_low_imp_o, + p2h_low_imp_o => p2h_low_imp_o, + p1_i => p1_in_s, + p1_o => p1_out_s, + p1_low_imp_o => p1_low_imp_o, + prog_n_o => prog_n_o, + clk_i => xtal_i, + en_clk_i => en_clk_s, + xtal3_o => xtal3_s, + dmem_addr_o => dmem_addr_s, + dmem_we_o => dmem_we_s, + dmem_data_i => dmem_data_from_s, + dmem_data_o => dmem_data_to_s, + pmem_addr_o => pmem_addr_s, + pmem_data_i => pmem_data_s + ); + + + ----------------------------------------------------------------------------- + -- Gate port 1 and 2 input bus with respetive output value + ----------------------------------------------------------------------------- + gate_ports: if gate_port_input_g = 1 generate + p1_in_s <= p1_i and p1_out_s; + p2_in_s <= p2_i and p2_out_s; + end generate; + + pass_ports: if gate_port_input_g = 0 generate + p1_in_s <= p1_i; + p2_in_s <= p2_i; + end generate; + + p1_o <= p1_out_s; + p2_o <= p2_out_s; + + ale_o <= ale_s; + wr_n_o <= wr_n_s; + rd_n_o <= rd_n_s; + + + ----------------------------------------------------------------------------- + -- Generate clock enable + ----------------------------------------------------------------------------- + en_clk_s <= xtal3_s and wb_en_clk_s; + + + ----------------------------------------------------------------------------- + -- Process ea + -- + -- Purpose: + -- Detects access to external program memory. + -- Either by ea_i = '1' or when program memory address leaves address + -- range of internal ROM. + -- + ea: process (ea_i, + pmem_addr_s) + begin + if ea_i = '1' then + -- Forced external access + ea_s <= '1'; + +-- elsif unsigned(pmem_addr_s(11 downto rom_addr_width_c)) = 0 then + else + -- Internal access + ea_s <= '0'; + +-- else +-- -- Access to program memory out of internal range +-- ea_s <= '1'; + + end if; + + end process ea; + -- + ----------------------------------------------------------------------------- + + + wb_master_b : t48_wb_master + port map ( + xtal_i => xtal_i, + res_i => reset_n_i, + en_clk_o => wb_en_clk_s, + ale_i => ale_s, + rd_n_i => rd_n_s, + wr_n_i => wr_n_s, + adr_i => p2_out_s(4), + db_bus_i => db_bus_from_t48, + db_bus_o => db_bus_to_t48, + wb_cyc_o => wb_cyc_o, + wb_stb_o => wb_stb_o, + wb_we_o => wb_we_o, + wb_adr_o => wb_adr_o, + wb_ack_i => wb_ack_i, + wb_dat_i => wb_dat_i, + wb_dat_o => wb_dat_o + ); + + + rom_4k_b : syn_rom + generic map ( + address_width_g => rom_addr_width_c + ) + port map ( + clk_i => xtal_i, + rom_addr_i => pmem_addr_s(rom_addr_width_c-1 downto 0), + rom_data_o => pmem_data_s + ); + + ram_256_b : syn_ram + generic map ( + address_width_g => 8 + ) + port map ( + clk_i => xtal_i, + res_i => reset_n_i, + ram_addr_i => dmem_addr_s(7 downto 0), + ram_data_i => dmem_data_to_s, + ram_we_i => dmem_we_s, + ram_data_o => dmem_data_from_s + ); + +end struct; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t8050_wb.vhd,v $ +-- Revision 1.3 2005/11/01 21:39:14 arniml +-- wire signals for P2 low impedance marker issue +-- +-- Revision 1.2 2005/06/11 10:16:05 arniml +-- introduce prefix 't48_' for wb_master entity and configuration +-- +-- Revision 1.1 2005/05/08 10:36:59 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t48/rtl/vhdl/system/wb_master-c.vhd b/rtl/t48/rtl/vhdl/system/wb_master-c.vhd new file mode 100644 index 0000000..89673ec --- /dev/null +++ b/rtl/t48/rtl/vhdl/system/wb_master-c.vhd @@ -0,0 +1,18 @@ +------------------------------------------------------------------------------- +-- +-- The Wishbone master module. +-- +-- $Id: wb_master-c.vhd,v 1.2 2005/06/11 10:16:05 arniml Exp $ +-- +-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +configuration t48_wb_master_rtl_c0 of t48_wb_master is + + for rtl + end for; + +end t48_wb_master_rtl_c0; diff --git a/rtl/t48/rtl/vhdl/system/wb_master.vhd b/rtl/t48/rtl/vhdl/system/wb_master.vhd new file mode 100644 index 0000000..f1f6993 --- /dev/null +++ b/rtl/t48/rtl/vhdl/system/wb_master.vhd @@ -0,0 +1,274 @@ +------------------------------------------------------------------------------- +-- +-- The Wishbone master module. +-- +-- $Id: wb_master.vhd,v 1.5 2005/06/11 10:16:05 arniml Exp $ +-- +-- Copyright (c) 2005, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t48/ +-- +-- +-- Short description: +-- This design implements a simple Wishbone bus master. It connects to the +-- BUS interface of the T48 uController core. +-- +-- The CPU clock is suppressed with en_clk_o to stall the CPU until the +-- acknowledge signal from the peripheral is detected. +-- +-- The adr_i input selects between configuration and Wishbone address range: +-- 1 - configuration range +-- 0 - Wishbone range +-- +-- When configuration range is selected, two address register are accessible. +-- 000h -> adr1 +-- 001h -> adr2 +-- These registers can be read and written with movx to their addresses. +-- +-- When Wishbone range is selected, all movx generate Wishbone bus cycles +-- (either read or write) at following address: +-- Wishbone address = adr2 & adr1 & address of movx +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.t48_pack.all; + +entity t48_wb_master is + + port ( + xtal_i : in std_logic; + res_i : in std_logic; + en_clk_o : out std_logic; + -- T48 Interface ---------------------------------------------------------- + ale_i : in std_logic; + rd_n_i : in std_logic; + wr_n_i : in std_logic; + adr_i : in std_logic; + db_bus_i : in std_logic_vector( 7 downto 0); + db_bus_o : out std_logic_vector( 7 downto 0); + -- Wishbone Interface ----------------------------------------------------- + wb_cyc_o : out std_logic; + wb_stb_o : out std_logic; + wb_we_o : out std_logic; + wb_adr_o : out std_logic_vector(23 downto 0); + wb_ack_i : in std_logic; + wb_dat_i : in std_logic_vector( 7 downto 0); + wb_dat_o : out std_logic_vector( 7 downto 0) + ); + +end t48_wb_master; + + +architecture rtl of t48_wb_master is + + ----------------------------------------------------------------------------- + -- Controller FSM + ----------------------------------------------------------------------------- + type state_t is (IDLE, CYC, WAIT_INACT); + signal state_s, + state_q : state_t; + + ----------------------------------------------------------------------------- + -- Select signals for each range + ----------------------------------------------------------------------------- + signal sel_adr1_s, + sel_adr2_s, + sel_wb_s : boolean; + + signal wr_s, + rd_s : boolean; + + signal adr_q : std_logic_vector(23 downto 0); + signal wb_dat_q : std_logic_vector( 7 downto 0); + +begin + + ----------------------------------------------------------------------------- + -- Select signal generation + ----------------------------------------------------------------------------- + sel_adr1_s <= adr_i = '1' and adr_q(word_t'range) = "00000000"; + sel_adr2_s <= adr_i = '1' and adr_q(word_t'range) = "00000001"; + sel_wb_s <= adr_i = '0'; + + wr_s <= wr_n_i = '0'; + rd_s <= rd_n_i = '0'; + + + ----------------------------------------------------------------------------- + -- Process seq + -- + -- Purpose: + -- Implements the sequential elements. + -- + seq: process (res_i, xtal_i) + begin + if res_i = res_active_c then + adr_q <= (others => '0'); + wb_dat_q <= (others => '0'); + state_q <= IDLE; + + elsif xtal_i'event and xtal_i = clk_active_c then + -- Address register ----------------------------------------------------- + -- update lowest address byte + if ale_i = '1' then + adr_q(word_t'range) <= db_bus_i; + end if; + -- set adr1 part + if wr_s and sel_adr1_s then + adr_q(word_t'length*2 - 1 downto word_t'length) <= db_bus_i; + end if; + -- set adr2 part + if wr_s and sel_adr2_s then + adr_q(word_t'length*3 - 1 downto word_t'length*2) <= db_bus_i; + end if; + + -- Data from peripheral has to be saved --------------------------------- + if wb_ack_i = '1' then + wb_dat_q <= wb_dat_i; + end if; + + -- FSM state ------------------------------------------------------------ + state_q <= state_s; + + end if; + end process seq; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process fsm + -- + -- Purpose: + -- Implements the state transitions of the controller FSM. + -- + fsm: process (state_q, + wr_s, + rd_s, + sel_wb_s, + wb_ack_i) + begin + -- default assignments + wb_cyc_o <= '0'; + wb_stb_o <= '0'; + en_clk_o <= '1'; + state_s <= IDLE; + + case state_q is + -- Idle State: Wait for read or write access ---------------------------- + when IDLE => + if sel_wb_s and (wr_s or rd_s) then + state_s <= CYC; + end if; + + -- WB Cycle State: Start Wishbone cycle and wait for ack ---------------- + when CYC => + wb_cyc_o <= '1'; + wb_stb_o <= '1'; + en_clk_o <= '0'; + + if wb_ack_i = '1' then + state_s <= WAIT_INACT; + else + state_s <= CYC; + end if; + + -- Wait inact State: Wait for end of T48 access ------------------------- + when WAIT_INACT => + if not wr_s and not rd_s then + state_s <= IDLE; + else + state_s <= WAIT_INACT; + end if; + + when others => + null; + + end case; + + end process fsm; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Output multiplexer + ----------------------------------------------------------------------------- + db_bus_o <= adr_q(word_t'length*2 - 1 downto word_t'length) + when sel_adr1_s else + adr_q(word_t'length*3 - 1 downto word_t'length*2) + when sel_adr2_s else + wb_dat_q; + + + ----------------------------------------------------------------------------- + -- Output mapping + ----------------------------------------------------------------------------- + wb_adr_o <= adr_q; + wb_dat_o <= db_bus_i; + wb_we_o <= '1' + when wr_s and sel_wb_s else + '0'; + +end rtl; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: wb_master.vhd,v $ +-- Revision 1.5 2005/06/11 10:16:05 arniml +-- introduce prefix 't48_' for wb_master entity and configuration +-- +-- Revision 1.4 2005/05/10 22:36:23 arniml +-- save data from wishbone bus in register bank with wb_ack +-- necessary to hold data from peripheral/memory until it is read by T48 +-- +-- Revision 1.3 2005/05/08 10:36:07 arniml +-- simplify address range: +-- - configuration range +-- - Wishbone range +-- +-- Revision 1.2 2005/05/06 18:54:03 arniml +-- assign default for state_s +-- +-- Revision 1.1 2005/05/05 19:49:03 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t48/rtl/vhdl/t48_comp_pack-p.vhd b/rtl/t48/rtl/vhdl/t48_comp_pack-p.vhd new file mode 100644 index 0000000..e51e629 --- /dev/null +++ b/rtl/t48/rtl/vhdl/t48_comp_pack-p.vhd @@ -0,0 +1,395 @@ +------------------------------------------------------------------------------- +-- +-- $Id: t48_comp_pack-p.vhd,v 1.10 2005/11/01 21:29:00 arniml Exp $ +-- +-- Copyright (c) 2004, 2005, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.t48_alu_pack.alu_op_t; +use work.t48_cond_branch_pack.branch_conditions_t; +use work.t48_cond_branch_pack.comp_value_t; +use work.t48_decoder_pack.mnemonic_t; +use work.t48_dmem_ctrl_pack.dmem_addr_ident_t; +use work.t48_pmem_ctrl_pack.pmem_addr_ident_t; +use work.t48_pack.dmem_addr_t; +use work.t48_pack.pmem_addr_t; +use work.t48_pack.mstate_t; +use work.t48_pack.word_t; +use work.t48_pack.nibble_t; + +package t48_comp_pack is + + component t48_alu + port ( + clk_i : in std_logic; + res_i : in std_logic; + en_clk_i : in boolean; + data_i : in word_t; + data_o : out word_t; + write_accu_i : in boolean; + write_shadow_i : in boolean; + write_temp_reg_i : in boolean; + read_alu_i : in boolean; + carry_i : in std_logic; + carry_o : out std_logic; + aux_carry_o : out std_logic; + alu_op_i : in alu_op_t; + use_carry_i : in boolean; + da_high_i : in boolean; + da_overflow_o : out boolean; + accu_low_i : in boolean; + p06_temp_reg_i : in boolean; + p60_temp_reg_i : in boolean + ); + end component; + + component t48_bus_mux + port ( + alu_data_i : in word_t; + bus_data_i : in word_t; + dec_data_i : in word_t; + dm_data_i : in word_t; + pm_data_i : in word_t; + p1_data_i : in word_t; + p2_data_i : in word_t; + psw_data_i : in word_t; + tim_data_i : in word_t; + data_o : out word_t + ); + end component; + + component t48_clock_ctrl + generic ( + xtal_div_3_g : integer := 1 + ); + port ( + clk_i : in std_logic; + xtal_i : in std_logic; + res_i : in std_logic; + en_clk_i : in boolean; + xtal3_o : out boolean; + t0_o : out std_logic; + multi_cycle_i : in boolean; + assert_psen_i : in boolean; + assert_prog_i : in boolean; + assert_rd_i : in boolean; + assert_wr_i : in boolean; + mstate_o : out mstate_t; + second_cycle_o : out boolean; + ale_o : out boolean; + psen_o : out boolean; + prog_o : out boolean; + rd_o : out boolean; + wr_o : out boolean + ); + end component; + + component t48_cond_branch + port ( + clk_i : in std_logic; + res_i : in std_logic; + en_clk_i : in boolean; + compute_take_i : in boolean; + branch_cond_i : in branch_conditions_t; + take_branch_o : out boolean; + accu_i : in word_t; + t0_i : in std_logic; + t1_i : in std_logic; + int_n_i : in std_logic; + f0_i : in std_logic; + f1_i : in std_logic; + tf_i : in std_logic; + carry_i : in std_logic; + comp_value_i : in comp_value_t + ); + end component; + + component t48_db_bus + port ( + clk_i : in std_logic; + res_i : in std_logic; + en_clk_i : in boolean; + ea_i : in std_logic; + data_i : in word_t; + data_o : out word_t; + write_bus_i : in boolean; + read_bus_i : in boolean; + output_pcl_i : in boolean; + bidir_bus_i : in boolean; + pcl_i : in word_t; + db_i : in word_t; + db_o : out word_t; + db_dir_o : out std_logic + ); + end component; + + component t48_decoder + generic ( + register_mnemonic_g : integer := 1 + ); + port ( + clk_i : in std_logic; + res_i : in std_logic; + en_clk_i : in boolean; + xtal_i : in std_logic; + ea_i : in std_logic; + ale_i : in boolean; + int_n_i : in std_logic; + t0_dir_o : out std_logic; + data_i : in word_t; + data_o : out word_t; + alu_write_accu_o : out boolean; + alu_write_shadow_o : out boolean; + alu_write_temp_reg_o : out boolean; + alu_read_alu_o : out boolean; + bus_write_bus_o : out boolean; + bus_read_bus_o : out boolean; + dm_write_dmem_addr_o : out boolean; + dm_write_dmem_o : out boolean; + dm_read_dmem_o : out boolean; + p1_write_p1_o : out boolean; + p1_read_p1_o : out boolean; + p2_write_p2_o : out boolean; + p2_write_exp_o : out boolean; + p2_read_p2_o : out boolean; + pm_write_pcl_o : out boolean; + pm_read_pcl_o : out boolean; + pm_write_pch_o : out boolean; + pm_read_pch_o : out boolean; + pm_read_pmem_o : out boolean; + psw_read_psw_o : out boolean; + psw_read_sp_o : out boolean; + psw_write_psw_o : out boolean; + psw_write_sp_o : out boolean; + alu_carry_i : in std_logic; + alu_op_o : out alu_op_t; + alu_da_high_o : out boolean; + alu_accu_low_o : out boolean; + alu_da_overflow_i : in boolean; + alu_p06_temp_reg_o : out boolean; + alu_p60_temp_reg_o : out boolean; + alu_use_carry_o : out boolean; + bus_output_pcl_o : out boolean; + bus_bidir_bus_o : out boolean; + clk_multi_cycle_o : out boolean; + clk_assert_psen_o : out boolean; + clk_assert_prog_o : out boolean; + clk_assert_rd_o : out boolean; + clk_assert_wr_o : out boolean; + clk_mstate_i : in mstate_t; + clk_second_cycle_i : in boolean; + cnd_compute_take_o : out boolean; + cnd_branch_cond_o : out branch_conditions_t; + cnd_take_branch_i : in boolean; + cnd_comp_value_o : out comp_value_t; + cnd_f1_o : out std_logic; + cnd_tf_o : out std_logic; + dm_addr_type_o : out dmem_addr_ident_t; + tim_read_timer_o : out boolean; + tim_write_timer_o : out boolean; + tim_start_t_o : out boolean; + tim_start_cnt_o : out boolean; + tim_stop_tcnt_o : out boolean; + p1_read_reg_o : out boolean; + p2_read_reg_o : out boolean; + p2_read_exp_o : out boolean; + p2_output_pch_o : out boolean; + pm_inc_pc_o : out boolean; + pm_write_pmem_addr_o : out boolean; + pm_addr_type_o : out pmem_addr_ident_t; + psw_special_data_o : out std_logic; + psw_carry_i : in std_logic; + psw_aux_carry_i : in std_logic; + psw_f0_i : in std_logic; + psw_inc_stackp_o : out boolean; + psw_dec_stackp_o : out boolean; + psw_write_carry_o : out boolean; + psw_write_aux_carry_o : out boolean; + psw_write_f0_o : out boolean; + psw_write_bs_o : out boolean; + tim_overflow_i : in boolean + ); + end component; + + component t48_dmem_ctrl + port ( + clk_i : in std_logic; + res_i : in std_logic; + en_clk_i : in boolean; + data_i : in word_t; + write_dmem_addr_i : in boolean; + write_dmem_i : in boolean; + read_dmem_i : in boolean; + addr_type_i : in dmem_addr_ident_t; + bank_select_i : in std_logic; + data_o : out word_t; + dmem_data_i : in word_t; + dmem_addr_o : out dmem_addr_t; + dmem_we_o : out std_logic; + dmem_data_o : out word_t + ); + end component; + + component t48_int + port ( + clk_i : in std_logic; + res_i : in std_logic; + en_clk_i : in boolean; + xtal_i : in std_logic; + clk_mstate_i : in mstate_t; + jtf_executed_i : in boolean; + tim_overflow_i : in boolean; + tf_o : out std_logic; + en_tcnti_i : in boolean; + dis_tcnti_i : in boolean; + int_n_i : in std_logic; + ale_i : in boolean; + last_cycle_i : in boolean; + en_i_i : in boolean; + dis_i_i : in boolean; + ext_int_o : out boolean; + tim_int_o : out boolean; + retr_executed_i : in boolean; + int_executed_i : in boolean; + int_pending_o : out boolean; + int_in_progress_o : out boolean + ); + end component; + + component t48_opc_table + port ( + opcode_i : in word_t; + multi_cycle_o : out std_logic; + mnemonic_o : out mnemonic_t + ); + end component; + + component t48_opc_decoder + generic ( + register_mnemonic_g : integer := 1 + ); + port ( + clk_i : in std_logic; + res_i : in std_logic; + en_clk_i : in boolean; + data_i : in word_t; + read_bus_i : in boolean; + inj_int_i : in boolean; + opcode_o : out word_t; + mnemonic_o : out mnemonic_t; + multi_cycle_o : out boolean + ); + end component; + + component t48_timer + generic ( + sample_t1_state_g : integer := 4 + ); + port ( + clk_i : in std_logic; + res_i : in std_logic; + en_clk_i : in boolean; + t1_i : in std_logic; + clk_mstate_i : in mstate_t; + data_i : in word_t; + data_o : out word_t; + read_timer_i : in boolean; + write_timer_i : in boolean; + start_t_i : in boolean; + start_cnt_i : in boolean; + stop_tcnt_i : in boolean; + overflow_o : out std_logic + ); + end component; + + component t48_p1 + port ( + clk_i : in std_logic; + res_i : in std_logic; + en_clk_i : in boolean; + data_i : in word_t; + data_o : out word_t; + write_p1_i : in boolean; + read_p1_i : in boolean; + read_reg_i : in boolean; + p1_i : in word_t; + p1_o : out word_t; + p1_low_imp_o : out std_logic + ); + end component; + + component t48_p2 + port ( + clk_i : in std_logic; + res_i : in std_logic; + en_clk_i : in boolean; + xtal_i : in std_logic; + data_i : in word_t; + data_o : out word_t; + write_p2_i : in boolean; + write_exp_i : in boolean; + read_p2_i : in boolean; + read_reg_i : in boolean; + read_exp_i : in boolean; + output_pch_i : in boolean; + pch_i : in nibble_t; + p2_i : in word_t; + p2_o : out word_t; + p2l_low_imp_o : out std_logic; + p2h_low_imp_o : out std_logic + ); + end component; + + component t48_pmem_ctrl + port ( + clk_i : in std_logic; + res_i : in std_logic; + en_clk_i : in boolean; + data_i : in word_t; + data_o : out word_t; + write_pcl_i : in boolean; + read_pcl_i : in boolean; + write_pch_i : in boolean; + read_pch_i : in boolean; + inc_pc_i : in boolean; + write_pmem_addr_i : in boolean; + addr_type_i : in pmem_addr_ident_t; + read_pmem_i : in boolean; + pmem_addr_o : out pmem_addr_t; + pmem_data_i : in word_t + ); + end component; + + component t48_psw + port ( + clk_i : in std_logic; + res_i : in std_logic; + en_clk_i : in boolean; + data_i : in word_t; + data_o : out word_t; + read_psw_i : in boolean; + read_sp_i : in boolean; + write_psw_i : in boolean; + write_sp_i : in boolean; + special_data_i : in std_logic; + inc_stackp_i : in boolean; + dec_stackp_i : in boolean; + write_carry_i : in boolean; + write_aux_carry_i : in boolean; + write_f0_i : in boolean; + write_bs_i : in boolean; + carry_o : out std_logic; + aux_carry_i : in std_logic; + aux_carry_o : out std_logic; + f0_o : out std_logic; + bs_o : out std_logic + ); + end component; + +end t48_comp_pack; diff --git a/rtl/t48/rtl/vhdl/t48_core-c.vhd b/rtl/t48/rtl/vhdl/t48_core-c.vhd new file mode 100644 index 0000000..8f0d359 --- /dev/null +++ b/rtl/t48/rtl/vhdl/t48_core-c.vhd @@ -0,0 +1,71 @@ +------------------------------------------------------------------------------- +-- +-- T48 Microcontroller Core +-- +-- $Id: t48_core-c.vhd,v 1.2 2005/06/11 10:08:43 arniml Exp $ +-- +------------------------------------------------------------------------------- + +configuration t48_core_struct_c0 of t48_core is + + for struct + + for alu_b : t48_alu + use configuration work.t48_alu_rtl_c0; + end for; + + for bus_mux_b : t48_bus_mux + use configuration work.t48_bus_mux_rtl_c0; + end for; + + for clock_ctrl_b : t48_clock_ctrl + use configuration work.t48_clock_ctrl_rtl_c0; + end for; + + for cond_branch_b : t48_cond_branch + use configuration work.t48_cond_branch_rtl_c0; + end for; + + for use_db_bus + for db_bus_b : t48_db_bus + use configuration work.t48_db_bus_rtl_c0; + end for; + end for; + + for decoder_b : t48_decoder + use configuration work.t48_decoder_rtl_c0; + end for; + + for dmem_ctrl_b : t48_dmem_ctrl + use configuration work.t48_dmem_ctrl_rtl_c0; + end for; + + for use_timer + for timer_b : t48_timer + use configuration work.t48_timer_rtl_c0; + end for; + end for; + + for use_p1 + for p1_b : t48_p1 + use configuration work.t48_p1_rtl_c0; + end for; + end for; + + for use_p2 + for p2_b : t48_p2 + use configuration work.t48_p2_rtl_c0; + end for; + end for; + + for pmem_ctrl_b : t48_pmem_ctrl + use configuration work.t48_pmem_ctrl_rtl_c0; + end for; + + for psw_b : t48_psw + use configuration work.t48_psw_rtl_c0; + end for; + + end for; + +end t48_core_struct_c0; diff --git a/rtl/t48/rtl/vhdl/t48_core.vhd b/rtl/t48/rtl/vhdl/t48_core.vhd new file mode 100644 index 0000000..15dac11 --- /dev/null +++ b/rtl/t48/rtl/vhdl/t48_core.vhd @@ -0,0 +1,669 @@ +------------------------------------------------------------------------------- +-- +-- T48 Microcontroller Core +-- +-- $Id: t48_core.vhd,v 1.10 2005/11/01 21:32:58 arniml Exp $ +-- +-- Copyright (c) 2004, 2005, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t48/ +-- +-- Limitations : +-- ============= +-- +-- Compared to the original MCS-48 architecture, the following limitations +-- apply: +-- +-- * Nibble-wide instructions addressing expander port implemented but +-- not verified in detail. +-- +-- * Single-step mode not implemented. +-- Not selected for future implementation. +-- +-- * Reading of internal Program Memory not implemented. +-- Not selected for future implementation. +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity t48_core is + + generic ( + -- divide XTAL1 by 3 to derive Clock States + xtal_div_3_g : integer := 1; + -- store mnemonic in flip-flops (registered-out) + register_mnemonic_g : integer := 1; + -- include the port 1 module + include_port1_g : integer := 1; + -- include the port 2 module + include_port2_g : integer := 1; + -- include the BUS module + include_bus_g : integer := 1; + -- include the timer module + include_timer_g : integer := 1; + -- state in which T1 is sampled (3 or 4) + sample_t1_state_g : integer := 4 + ); + + port ( + -- T48 Interface ---------------------------------------------------------- + xtal_i : in std_logic; + reset_i : in std_logic; + t0_i : in std_logic; + t0_o : out std_logic; + t0_dir_o : out std_logic; + int_n_i : in std_logic; + ea_i : in std_logic; + rd_n_o : out std_logic; + psen_n_o : out std_logic; + wr_n_o : out std_logic; + ale_o : out std_logic; + db_i : in std_logic_vector( 7 downto 0); + db_o : out std_logic_vector( 7 downto 0); + db_dir_o : out std_logic; + t1_i : in std_logic; + p2_i : in std_logic_vector( 7 downto 0); + p2_o : out std_logic_vector( 7 downto 0); + p2l_low_imp_o : out std_logic; + p2h_low_imp_o : out std_logic; + p1_i : in std_logic_vector( 7 downto 0); + p1_o : out std_logic_vector( 7 downto 0); + p1_low_imp_o : out std_logic; + prog_n_o : out std_logic; + -- Core Interface --------------------------------------------------------- + clk_i : in std_logic; + en_clk_i : in std_logic; + xtal3_o : out std_logic; + dmem_addr_o : out std_logic_vector( 7 downto 0); + dmem_we_o : out std_logic; + dmem_data_i : in std_logic_vector( 7 downto 0); + dmem_data_o : out std_logic_vector( 7 downto 0); + pmem_addr_o : out std_logic_vector(11 downto 0); + pmem_data_i : in std_logic_vector( 7 downto 0) + ); + +end t48_core; + + +use work.t48_alu_pack.alu_op_t; +use work.t48_cond_branch_pack.branch_conditions_t; +use work.t48_cond_branch_pack.comp_value_t; +use work.t48_dmem_ctrl_pack.dmem_addr_ident_t; +use work.t48_pmem_ctrl_pack.pmem_addr_ident_t; +use work.t48_comp_pack.all; +use work.t48_pack.bus_idle_level_c; +use work.t48_pack.word_t; +use work.t48_pack.pmem_addr_t; +use work.t48_pack.mstate_t; +use work.t48_pack.to_stdLogic; +use work.t48_pack.to_boolean; + +architecture struct of t48_core is + + signal t48_data_s : word_t; + + signal en_clk_s : boolean; + + -- ALU signals + signal alu_data_s : word_t; + signal alu_write_accu_s : boolean; + signal alu_write_shadow_s : boolean; + signal alu_write_temp_reg_s : boolean; + signal alu_read_alu_s : boolean; + signal alu_carry_s : std_logic; + signal alu_aux_carry_s : std_logic; + signal alu_op_s : alu_op_t; + signal alu_use_carry_s : boolean; + signal alu_da_high_s : boolean; + signal alu_da_overflow_s : boolean; + signal alu_accu_low_s : boolean; + signal alu_p06_temp_reg_s : boolean; + signal alu_p60_temp_reg_s : boolean; + + -- BUS signals + signal bus_write_bus_s : boolean; + signal bus_read_bus_s : boolean; + signal bus_output_pcl_s : boolean; + signal bus_bidir_bus_s : boolean; + signal bus_data_s : word_t; + + -- Clock Controller signals + signal clk_multi_cycle_s : boolean; + signal clk_assert_psen_s : boolean; + signal clk_assert_prog_s : boolean; + signal clk_assert_rd_s : boolean; + signal clk_assert_wr_s : boolean; + signal clk_mstate_s : mstate_t; + signal clk_second_cycle_s : boolean; + signal psen_s : boolean; + signal prog_s : boolean; + signal rd_s : boolean; + signal wr_s : boolean; + signal ale_s : boolean; + signal xtal3_s : boolean; + + -- Conditional Branch Logic signals + signal cnd_compute_take_s : boolean; + signal cnd_branch_cond_s : branch_conditions_t; + signal cnd_take_branch_s : boolean; + signal cnd_comp_value_s : comp_value_t; + signal cnd_f1_s : std_logic; + signal cnd_tf_s : std_logic; + + -- Data Memory Controller signals + signal dm_write_dmem_addr_s : boolean; + signal dm_write_dmem_s : boolean; + signal dm_read_dmem_s : boolean; + signal dm_addr_type_s : dmem_addr_ident_t; + signal dm_data_s : word_t; + + -- Decoder signals + signal dec_data_s : word_t; + + -- Port 1 signals + signal p1_write_p1_s : boolean; + signal p1_read_p1_s : boolean; + signal p1_read_reg_s : boolean; + signal p1_data_s : word_t; + + -- Port 2 signals + signal p2_write_p2_s : boolean; + signal p2_write_exp_s : boolean; + signal p2_read_p2_s : boolean; + signal p2_read_reg_s : boolean; + signal p2_read_exp_s : boolean; + signal p2_output_pch_s : boolean; + signal p2_data_s : word_t; + + -- Program Memory Controller signals + signal pm_write_pcl_s : boolean; + signal pm_read_pcl_s : boolean; + signal pm_write_pch_s : boolean; + signal pm_read_pch_s : boolean; + signal pm_read_pmem_s : boolean; + signal pm_inc_pc_s : boolean; + signal pm_write_pmem_addr_s : boolean; + signal pm_data_s : word_t; + signal pm_addr_type_s : pmem_addr_ident_t; + signal pmem_addr_s : pmem_addr_t; + + -- PSW signals + signal psw_read_psw_s : boolean; + signal psw_read_sp_s : boolean; + signal psw_write_psw_s : boolean; + signal psw_write_sp_s : boolean; + signal psw_carry_s : std_logic; + signal psw_aux_carry_s : std_logic; + signal psw_f0_s : std_logic; + signal psw_bs_s : std_logic; + signal psw_special_data_s : std_logic; + signal psw_inc_stackp_s : boolean; + signal psw_dec_stackp_s : boolean; + signal psw_write_carry_s : boolean; + signal psw_write_aux_carry_s : boolean; + signal psw_write_f0_s : boolean; + signal psw_write_bs_s : boolean; + signal psw_data_s : word_t; + + -- Timer signals + signal tim_overflow_s : boolean; + signal tim_of_s : std_logic; + signal tim_read_timer_s : boolean; + signal tim_write_timer_s : boolean; + signal tim_start_t_s : boolean; + signal tim_start_cnt_s : boolean; + signal tim_stop_tcnt_s : boolean; + signal tim_data_s : word_t; + +begin + + ----------------------------------------------------------------------------- + -- Check generics for valid values. + ----------------------------------------------------------------------------- + -- pragma translate_off + assert include_timer_g = 0 or include_timer_g = 1 + report "include_timer_g must be either 1 or 0!" + severity failure; + + assert include_port1_g = 0 or include_port1_g = 1 + report "include_port1_g must be either 1 or 0!" + severity failure; + + assert include_port2_g = 0 or include_port2_g = 1 + report "include_port2_g must be either 1 or 0!" + severity failure; + + assert include_bus_g = 0 or include_bus_g = 1 + report "include_bus_g must be either 1 or 0!" + severity failure; + -- pragma translate_on + + + en_clk_s <= to_boolean(en_clk_i); + + alu_b : t48_alu + port map ( + clk_i => clk_i, + res_i => reset_i, + en_clk_i => en_clk_s, + data_i => t48_data_s, + data_o => alu_data_s, + write_accu_i => alu_write_accu_s, + write_shadow_i => alu_write_shadow_s, + write_temp_reg_i => alu_write_temp_reg_s, + read_alu_i => alu_read_alu_s, + carry_i => psw_carry_s, + carry_o => alu_carry_s, + aux_carry_o => alu_aux_carry_s, + alu_op_i => alu_op_s, + use_carry_i => alu_use_carry_s, + da_high_i => alu_da_high_s, + da_overflow_o => alu_da_overflow_s, + accu_low_i => alu_accu_low_s, + p06_temp_reg_i => alu_p06_temp_reg_s, + p60_temp_reg_i => alu_p60_temp_reg_s + ); + + bus_mux_b : t48_bus_mux + port map ( + alu_data_i => alu_data_s, + bus_data_i => bus_data_s, + dec_data_i => dec_data_s, + dm_data_i => dm_data_s, + pm_data_i => pm_data_s, + p1_data_i => p1_data_s, + p2_data_i => p2_data_s, + psw_data_i => psw_data_s, + tim_data_i => tim_data_s, + data_o => t48_data_s + ); + + clock_ctrl_b : t48_clock_ctrl + generic map ( + xtal_div_3_g => xtal_div_3_g + ) + port map ( + clk_i => clk_i, + xtal_i => xtal_i, + res_i => reset_i, + en_clk_i => en_clk_s, + xtal3_o => xtal3_s, + t0_o => t0_o, + multi_cycle_i => clk_multi_cycle_s, + assert_psen_i => clk_assert_psen_s, + assert_prog_i => clk_assert_prog_s, + assert_rd_i => clk_assert_rd_s, + assert_wr_i => clk_assert_wr_s, + mstate_o => clk_mstate_s, + second_cycle_o => clk_second_cycle_s, + ale_o => ale_s, + psen_o => psen_s, + prog_o => prog_s, + rd_o => rd_s, + wr_o => wr_s + ); + + cond_branch_b : t48_cond_branch + port map ( + clk_i => clk_i, + res_i => reset_i, + en_clk_i => en_clk_s, + compute_take_i => cnd_compute_take_s, + branch_cond_i => cnd_branch_cond_s, + take_branch_o => cnd_take_branch_s, + accu_i => alu_data_s, + t0_i => To_X01Z(t0_i), + t1_i => To_X01Z(t1_i), + int_n_i => int_n_i, + f0_i => psw_f0_s, + f1_i => cnd_f1_s, + tf_i => cnd_tf_s, + carry_i => psw_carry_s, + comp_value_i => cnd_comp_value_s + ); + + use_db_bus: if include_bus_g = 1 generate + db_bus_b : t48_db_bus + port map ( + clk_i => clk_i, + res_i => reset_i, + en_clk_i => en_clk_s, + ea_i => ea_i, + data_i => t48_data_s, + data_o => bus_data_s, + write_bus_i => bus_write_bus_s, + read_bus_i => bus_read_bus_s, + output_pcl_i => bus_output_pcl_s, + bidir_bus_i => bus_bidir_bus_s, + pcl_i => pmem_addr_s(word_t'range), + db_i => db_i, + db_o => db_o, + db_dir_o => db_dir_o + ); + end generate; + + skip_db_bus: if include_bus_g = 0 generate + bus_data_s <= (others => bus_idle_level_c); + db_o <= (others => '0'); + db_dir_o <= '0'; + end generate; + + decoder_b : t48_decoder + generic map ( + register_mnemonic_g => register_mnemonic_g + ) + port map ( + clk_i => clk_i, + res_i => reset_i, + en_clk_i => en_clk_s, + xtal_i => xtal_i, + ea_i => ea_i, + ale_i => ale_s, + int_n_i => int_n_i, + t0_dir_o => t0_dir_o, + data_i => t48_data_s, + data_o => dec_data_s, + alu_write_accu_o => alu_write_accu_s, + alu_write_shadow_o => alu_write_shadow_s, + alu_write_temp_reg_o => alu_write_temp_reg_s, + alu_read_alu_o => alu_read_alu_s, + bus_write_bus_o => bus_write_bus_s, + bus_read_bus_o => bus_read_bus_s, + dm_write_dmem_addr_o => dm_write_dmem_addr_s, + dm_write_dmem_o => dm_write_dmem_s, + dm_read_dmem_o => dm_read_dmem_s, + p1_write_p1_o => p1_write_p1_s, + p1_read_p1_o => p1_read_p1_s, + pm_write_pcl_o => pm_write_pcl_s, + p2_write_p2_o => p2_write_p2_s, + p2_write_exp_o => p2_write_exp_s, + p2_read_p2_o => p2_read_p2_s, + pm_read_pcl_o => pm_read_pcl_s, + pm_write_pch_o => pm_write_pch_s, + pm_read_pch_o => pm_read_pch_s, + pm_read_pmem_o => pm_read_pmem_s, + psw_read_psw_o => psw_read_psw_s, + psw_read_sp_o => psw_read_sp_s, + psw_write_psw_o => psw_write_psw_s, + psw_write_sp_o => psw_write_sp_s, + alu_carry_i => alu_carry_s, + alu_op_o => alu_op_s, + alu_use_carry_o => alu_use_carry_s, + alu_da_high_o => alu_da_high_s, + alu_da_overflow_i => alu_da_overflow_s, + alu_accu_low_o => alu_accu_low_s, + alu_p06_temp_reg_o => alu_p06_temp_reg_s, + alu_p60_temp_reg_o => alu_p60_temp_reg_s, + bus_output_pcl_o => bus_output_pcl_s, + bus_bidir_bus_o => bus_bidir_bus_s, + clk_multi_cycle_o => clk_multi_cycle_s, + clk_assert_psen_o => clk_assert_psen_s, + clk_assert_prog_o => clk_assert_prog_s, + clk_assert_rd_o => clk_assert_rd_s, + clk_assert_wr_o => clk_assert_wr_s, + clk_mstate_i => clk_mstate_s, + clk_second_cycle_i => clk_second_cycle_s, + cnd_compute_take_o => cnd_compute_take_s, + cnd_branch_cond_o => cnd_branch_cond_s, + cnd_take_branch_i => cnd_take_branch_s, + cnd_comp_value_o => cnd_comp_value_s, + cnd_f1_o => cnd_f1_s, + cnd_tf_o => cnd_tf_s, + dm_addr_type_o => dm_addr_type_s, + tim_read_timer_o => tim_read_timer_s, + tim_write_timer_o => tim_write_timer_s, + tim_start_t_o => tim_start_t_s, + tim_start_cnt_o => tim_start_cnt_s, + tim_stop_tcnt_o => tim_stop_tcnt_s, + p1_read_reg_o => p1_read_reg_s, + p2_read_reg_o => p2_read_reg_s, + p2_read_exp_o => p2_read_exp_s, + p2_output_pch_o => p2_output_pch_s, + pm_inc_pc_o => pm_inc_pc_s, + pm_write_pmem_addr_o => pm_write_pmem_addr_s, + pm_addr_type_o => pm_addr_type_s, + psw_special_data_o => psw_special_data_s, + psw_carry_i => psw_carry_s, + psw_aux_carry_i => psw_aux_carry_s, + psw_f0_i => psw_f0_s, + psw_inc_stackp_o => psw_inc_stackp_s, + psw_dec_stackp_o => psw_dec_stackp_s, + psw_write_carry_o => psw_write_carry_s, + psw_write_aux_carry_o => psw_write_aux_carry_s, + psw_write_f0_o => psw_write_f0_s, + psw_write_bs_o => psw_write_bs_s, + tim_overflow_i => tim_overflow_s + ); + + dmem_ctrl_b : t48_dmem_ctrl + port map ( + clk_i => clk_i, + res_i => reset_i, + en_clk_i => en_clk_s, + data_i => t48_data_s, + write_dmem_addr_i => dm_write_dmem_addr_s, + write_dmem_i => dm_write_dmem_s, + read_dmem_i => dm_read_dmem_s, + addr_type_i => dm_addr_type_s, + bank_select_i => psw_bs_s, + data_o => dm_data_s, + dmem_data_i => dmem_data_i, + dmem_addr_o => dmem_addr_o, + dmem_we_o => dmem_we_o, + dmem_data_o => dmem_data_o + ); + + use_timer: if include_timer_g = 1 generate + timer_b : t48_timer + generic map ( + sample_t1_state_g => sample_t1_state_g + ) + port map ( + clk_i => clk_i, + res_i => reset_i, + en_clk_i => en_clk_s, + t1_i => To_X01Z(t1_i), + clk_mstate_i => clk_mstate_s, + data_i => t48_data_s, + data_o => tim_data_s, + read_timer_i => tim_read_timer_s, + write_timer_i => tim_write_timer_s, + start_t_i => tim_start_t_s, + start_cnt_i => tim_start_cnt_s, + stop_tcnt_i => tim_stop_tcnt_s, + overflow_o => tim_of_s + ); + end generate; + + skip_timer: if include_timer_g = 0 generate + tim_data_s <= (others => bus_idle_level_c); + tim_of_s <= '0'; + end generate; + + tim_overflow_s <= to_boolean(tim_of_s); + + use_p1: if include_port1_g = 1 generate + p1_b : t48_p1 + port map ( + clk_i => clk_i, + res_i => reset_i, + en_clk_i => en_clk_s, + data_i => t48_data_s, + data_o => p1_data_s, + write_p1_i => p1_write_p1_s, + read_p1_i => p1_read_p1_s, + read_reg_i => p1_read_reg_s, + p1_i => p1_i, + p1_o => p1_o, + p1_low_imp_o => p1_low_imp_o + ); + end generate; + + skip_p1: if include_port1_g = 0 generate + p1_data_s <= (others => bus_idle_level_c); + p1_o <= (others => '0'); + p1_low_imp_o <= '0'; + end generate; + + use_p2: if include_port2_g = 1 generate + p2_b : t48_p2 + port map ( + clk_i => clk_i, + res_i => reset_i, + en_clk_i => en_clk_s, + xtal_i => xtal_i, + data_i => t48_data_s, + data_o => p2_data_s, + write_p2_i => p2_write_p2_s, + write_exp_i => p2_write_exp_s, + read_p2_i => p2_read_p2_s, + read_reg_i => p2_read_reg_s, + read_exp_i => p2_read_exp_s, + output_pch_i => p2_output_pch_s, + pch_i => pmem_addr_s(11 downto 8), + p2_i => p2_i, + p2_o => p2_o, + p2l_low_imp_o => p2l_low_imp_o, + p2h_low_imp_o => p2h_low_imp_o + ); + end generate; + + skip_p2: if include_port2_g = 0 generate + p2_data_s <= (others => bus_idle_level_c); + p2_o <= (others => '0'); + p2l_low_imp_o <= '0'; + p2h_low_imp_o <= '0'; + end generate; + + pmem_ctrl_b : t48_pmem_ctrl + port map ( + clk_i => clk_i, + res_i => reset_i, + en_clk_i => en_clk_s, + data_i => t48_data_s, + data_o => pm_data_s, + write_pcl_i => pm_write_pcl_s, + read_pcl_i => pm_read_pcl_s, + write_pch_i => pm_write_pch_s, + read_pch_i => pm_read_pch_s, + inc_pc_i => pm_inc_pc_s, + write_pmem_addr_i => pm_write_pmem_addr_s, + addr_type_i => pm_addr_type_s, + read_pmem_i => pm_read_pmem_s, + pmem_addr_o => pmem_addr_s, + pmem_data_i => pmem_data_i + ); + + psw_b : t48_psw + port map ( + clk_i => clk_i, + res_i => reset_i, + en_clk_i => en_clk_s, + data_i => t48_data_s, + data_o => psw_data_s, + read_psw_i => psw_read_psw_s, + read_sp_i => psw_read_sp_s, + write_psw_i => psw_write_psw_s, + write_sp_i => psw_write_sp_s, + special_data_i => psw_special_data_s, + inc_stackp_i => psw_inc_stackp_s, + dec_stackp_i => psw_dec_stackp_s, + write_carry_i => psw_write_carry_s, + write_aux_carry_i => psw_write_aux_carry_s, + write_f0_i => psw_write_f0_s, + write_bs_i => psw_write_bs_s, + carry_o => psw_carry_s, + aux_carry_i => alu_aux_carry_s, + aux_carry_o => psw_aux_carry_s, + f0_o => psw_f0_s, + bs_o => psw_bs_s + ); + + + ----------------------------------------------------------------------------- + -- Output Mapping. + ----------------------------------------------------------------------------- + ale_o <= to_stdLogic(ale_s); + psen_n_o <= to_stdLogic(not psen_s); + prog_n_o <= to_stdLogic(not prog_s); + rd_n_o <= to_stdLogic(not rd_s); + wr_n_o <= to_stdLogic(not wr_s); + xtal3_o <= to_stdLogic(xtal3_s); + pmem_addr_o <= pmem_addr_s; + +end struct; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t48_core.vhd,v $ +-- Revision 1.10 2005/11/01 21:32:58 arniml +-- wire signals for P2 low impeddance marker issue +-- +-- Revision 1.9 2005/06/11 10:08:43 arniml +-- introduce prefix 't48_' for all packages, entities and configurations +-- +-- Revision 1.8 2005/05/04 20:12:37 arniml +-- Fix bug report: +-- "Wrong clock applied to T0" +-- t0_o is generated inside clock_ctrl with a separate flip-flop running +-- with xtal_i +-- +-- Revision 1.7 2004/05/01 11:58:04 arniml +-- update notice about expander port instructions +-- +-- Revision 1.6 2004/04/07 22:09:03 arniml +-- remove unused signals +-- +-- Revision 1.5 2004/04/04 14:18:53 arniml +-- add measures to implement XCHD +-- +-- Revision 1.4 2004/03/29 19:39:58 arniml +-- rename pX_limp to pX_low_imp +-- +-- Revision 1.3 2004/03/28 21:27:50 arniml +-- update wiring for DA support +-- +-- Revision 1.2 2004/03/28 13:13:20 arniml +-- connect control signal for Port 2 expander +-- +-- Revision 1.1 2004/03/23 21:31:53 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/t48/rtl/vhdl/t48_core_comp_pack-p.vhd b/rtl/t48/rtl/vhdl/t48_core_comp_pack-p.vhd new file mode 100644 index 0000000..de9b79b --- /dev/null +++ b/rtl/t48/rtl/vhdl/t48_core_comp_pack-p.vhd @@ -0,0 +1,88 @@ +------------------------------------------------------------------------------- +-- +-- $Id: t48_core_comp_pack-p.vhd,v 1.3 2005/11/01 21:33:41 arniml Exp $ +-- +-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +package t48_core_comp_pack is + + component t48_core + generic ( + xtal_div_3_g : integer := 1; + register_mnemonic_g : integer := 1; + include_port1_g : integer := 1; + include_port2_g : integer := 1; + include_bus_g : integer := 1; + include_timer_g : integer := 1; + sample_t1_state_g : integer := 4 + ); + + port ( + xtal_i : in std_logic; + reset_i : in std_logic; + t0_i : in std_logic; + t0_o : out std_logic; + t0_dir_o : out std_logic; + int_n_i : in std_logic; + ea_i : in std_logic; + rd_n_o : out std_logic; + psen_n_o : out std_logic; + wr_n_o : out std_logic; + ale_o : out std_logic; + db_i : in std_logic_vector( 7 downto 0); + db_o : out std_logic_vector( 7 downto 0); + db_dir_o : out std_logic; + t1_i : in std_logic; + p2_i : in std_logic_vector( 7 downto 0); + p2_o : out std_logic_vector( 7 downto 0); + p2l_low_imp_o : out std_logic; + p2h_low_imp_o : out std_logic; + p1_i : in std_logic_vector( 7 downto 0); + p1_o : out std_logic_vector( 7 downto 0); + p1_low_imp_o : out std_logic; + prog_n_o : out std_logic; + clk_i : in std_logic; + en_clk_i : in std_logic; + xtal3_o : out std_logic; + dmem_addr_o : out std_logic_vector( 7 downto 0); + dmem_we_o : out std_logic; + dmem_data_i : in std_logic_vector( 7 downto 0); + dmem_data_o : out std_logic_vector( 7 downto 0); + pmem_addr_o : out std_logic_vector(11 downto 0); + pmem_data_i : in std_logic_vector( 7 downto 0) + ); + end component; + + component syn_rom + generic ( + address_width_g : positive := 10 + ); + port ( + clk_i : in std_logic; + rom_addr_i : in std_logic_vector(address_width_g-1 downto 0); + rom_data_o : out std_logic_vector(7 downto 0) + ); + end component; + + component syn_ram + generic ( + address_width_g : positive := 8 + ); + port ( + clk_i : in std_logic; + res_i : in std_logic; + ram_addr_i : in std_logic_vector(address_width_g-1 downto 0); + ram_data_i : in std_logic_vector(7 downto 0); + ram_we_i : in std_logic; + ram_data_o : out std_logic_vector(7 downto 0) + ); + end component; + +end t48_core_comp_pack; diff --git a/rtl/t48/rtl/vhdl/t48_pack-p.vhd b/rtl/t48/rtl/vhdl/t48_pack-p.vhd new file mode 100644 index 0000000..f95fa75 --- /dev/null +++ b/rtl/t48/rtl/vhdl/t48_pack-p.vhd @@ -0,0 +1,82 @@ +------------------------------------------------------------------------------- +-- +-- $Id: t48_pack-p.vhd,v 1.1 2004/03/23 21:31:53 arniml Exp $ +-- +-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +package t48_pack is + + ----------------------------------------------------------------------------- + -- Global constants + ----------------------------------------------------------------------------- + + -- clock active level + constant clk_active_c : std_logic := '1'; + -- reset active level + constant res_active_c : std_logic := '0'; + -- idle level on internal data bus + constant bus_idle_level_c : std_logic := '1'; + + -- global data word width + constant word_width_c : natural := 8; + + -- data memory address width + constant dmem_addr_width_c : natural := 8; + -- program memory address width + constant pmem_addr_width_c : natural := 12; + + + ----------------------------------------------------------------------------- + -- Global data types + ----------------------------------------------------------------------------- + + -- the global data word width type + subtype word_t is std_logic_vector(word_width_c-1 downto 0); + subtype nibble_t is std_logic_vector(word_width_c/2-1 downto 0); + -- the global data memory address type + subtype dmem_addr_t is std_logic_vector(dmem_addr_width_c-1 downto 0); + -- the global program memory address type + subtype pmem_addr_t is std_logic_vector(pmem_addr_width_c-1 downto 0); + subtype page_t is std_logic_vector(pmem_addr_width_c-1 downto word_width_c); + + -- the machine states + type mstate_t is (MSTATE1, MSTATE2, MSTATE3, MSTATE4, MSTATE5); + + + ----------------------------------------------------------------------------- + -- Global functions + ----------------------------------------------------------------------------- + + function to_stdLogic(input: boolean) return std_logic; + function to_boolean(input: std_logic) return boolean; + +end t48_pack; + +package body t48_pack is + + function to_stdLogic(input: boolean) return std_logic is + begin + if input then + return '1'; + else + return '0'; + end if; + end to_stdLogic; + + function to_boolean(input: std_logic) return boolean is + begin + if input = '1' then + return true; + else + return false; + end if; + end to_boolean; + +end t48_pack; diff --git a/rtl/t48/rtl/vhdl/t48_tb_pack-p.vhd b/rtl/t48/rtl/vhdl/t48_tb_pack-p.vhd new file mode 100644 index 0000000..3b0d3a1 --- /dev/null +++ b/rtl/t48/rtl/vhdl/t48_tb_pack-p.vhd @@ -0,0 +1,22 @@ +------------------------------------------------------------------------------- +-- +-- $Id: t48_tb_pack-p.vhd,v 1.2 2004/04/14 20:53:54 arniml Exp $ +-- +-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +package t48_tb_pack is + + -- Instruction strobe visibility + signal tb_istrobe_s : std_logic; + + -- Accumulator visibilty + signal tb_accu_s : std_logic_vector(7 downto 0); + +end t48_tb_pack; diff --git a/rtl/t48/rtl/vhdl/timer-c.vhd b/rtl/t48/rtl/vhdl/timer-c.vhd new file mode 100644 index 0000000..8304089 --- /dev/null +++ b/rtl/t48/rtl/vhdl/timer-c.vhd @@ -0,0 +1,16 @@ +------------------------------------------------------------------------------- +-- +-- The Timer/Counter unit. +-- +-- $Id: timer-c.vhd,v 1.2 2005/06/11 10:08:43 arniml Exp $ +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +configuration t48_timer_rtl_c0 of t48_timer is + + for rtl + end for; + +end t48_timer_rtl_c0; diff --git a/rtl/t48/rtl/vhdl/timer.vhd b/rtl/t48/rtl/vhdl/timer.vhd new file mode 100644 index 0000000..724579c --- /dev/null +++ b/rtl/t48/rtl/vhdl/timer.vhd @@ -0,0 +1,280 @@ +------------------------------------------------------------------------------- +-- +-- The Timer/Counter unit. +-- +-- $Id: timer.vhd,v 1.6 2005/06/11 10:08:43 arniml Exp $ +-- +-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t48/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.t48_pack.word_t; +use work.t48_pack.mstate_t; + +entity t48_timer is + + generic ( + -- state in which T1 is sampled (3 or 4) + sample_t1_state_g : integer := 4 + ); + + port ( + -- Global Interface ------------------------------------------------------- + clk_i : in std_logic; + res_i : in std_logic; + en_clk_i : in boolean; + t1_i : in std_logic; + clk_mstate_i : in mstate_t; + -- T48 Bus Interface ------------------------------------------------------ + data_i : in word_t; + data_o : out word_t; + read_timer_i : in boolean; + write_timer_i : in boolean; + -- Decoder Interface ------------------------------------------------------ + start_t_i : in boolean; + start_cnt_i : in boolean; + stop_tcnt_i : in boolean; + overflow_o : out std_logic + ); + +end t48_timer; + + +library ieee; +use ieee.numeric_std.all; + +use work.t48_pack.all; + +architecture rtl of t48_timer is + + -- the 8 bit counter core + signal counter_q : unsigned(word_t'range); + signal overflow_q : boolean; + + -- increment signal for the counter core + type inc_type_t is (NONE, TIMER, COUNTER); + signal increment_s : boolean; + signal inc_sel_q : inc_type_t; + + -- T1 edge detector + signal t1_q : std_logic; + signal t1_inc_s : boolean; + + -- timer prescaler + signal prescaler_q : unsigned(4 downto 0); + signal pre_inc_s : boolean; + +begin + + ----------------------------------------------------------------------------- + -- Verify the generics + ----------------------------------------------------------------------------- + + -- pragma translate_off + assert (sample_t1_state_g = 3) or (sample_t1_state_g = 4) + report "sample_t1_state_g must be either 3 or 4!" + severity failure; + -- pragma translate_on + + + ----------------------------------------------------------------------------- + -- Process t1_edge + -- + -- Purpose: + -- Implements the edge detector for T1. + -- + t1_edge: process (t1_i, + t1_q, + clk_mstate_i) + begin + t1_inc_s <= false; + + -- sample in state according to generic + -- Old devices: sample at the beginning of state 3 + -- New devices: sample in state 4 + if (sample_t1_state_g = 3 and clk_mstate_i = MSTATE3) or + (sample_t1_state_g = 4 and clk_mstate_i = MSTATE4) then + -- detect falling edge + if t1_q = '1' and t1_i = '0' then + t1_inc_s <= true; + end if; + end if; + + end process t1_edge; + -- + ----------------------------------------------------------------------------- + + + pre_inc_s <= clk_mstate_i = MSTATE4 and prescaler_q = 31; + + + ----------------------------------------------------------------------------- + -- Process inc_sel + -- + -- Purpose: + -- Select increment source (timer, counter or none). + -- + inc_sel: process (inc_sel_q, + pre_inc_s, + t1_inc_s) + begin + -- default assignment + increment_s <= false; + + case inc_sel_q is + when NONE => + increment_s <= false; + when TIMER => + increment_s <= pre_inc_s; + when COUNTER => + increment_s <= t1_inc_s; + when others => + null; + end case; + + end process inc_sel; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process regs + -- + -- Purpose: + -- Implements the counter, the prescaler and other registers. + -- + regs: process (res_i, clk_i) + begin + if res_i = res_active_c then + overflow_q <= false; + t1_q <= '0'; + prescaler_q <= (others => '0'); + inc_sel_q <= NONE; + + elsif clk_i'event and clk_i = clk_active_c then + if en_clk_i then + + -- Counter Core and overflow ------------------------------------------ + overflow_q <= false; + + if write_timer_i then + counter_q <= unsigned(data_i); + + elsif increment_s then + counter_q <= counter_q + 1; + + if counter_q = 255 then + overflow_q <= true; + end if; + + end if; + + -- T1 edge detector --------------------------------------------------- + if (sample_t1_state_g = 3 and clk_mstate_i = MSTATE3) or + (sample_t1_state_g = 4 and clk_mstate_i = MSTATE4) then + t1_q <= t1_i; + end if; + + -- Prescaler ---------------------------------------------------------- + if start_t_i then + prescaler_q <= (others => '0'); + + elsif clk_mstate_i = MSTATE3 then + prescaler_q <= prescaler_q + 1; + + end if; + + -- Increment Selector ------------------------------------------------- + if start_t_i then + inc_sel_q <= TIMER; + elsif start_cnt_i then + inc_sel_q <= COUNTER; + elsif stop_tcnt_i then + inc_sel_q <= NONE; + end if; + + end if; + + end if; + + end process regs; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Output Mapping. + ----------------------------------------------------------------------------- + data_o <= std_logic_vector(counter_q) + when read_timer_i else + (others => bus_idle_level_c); + overflow_o <= to_stdLogic(overflow_q); + +end rtl; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: timer.vhd,v $ +-- Revision 1.6 2005/06/11 10:08:43 arniml +-- introduce prefix 't48_' for all packages, entities and configurations +-- +-- Revision 1.5 2004/07/11 16:51:33 arniml +-- cleanup copyright notice +-- +-- Revision 1.4 2004/07/04 13:06:45 arniml +-- counter_q is not cleared during reset +-- this would match all different descriptions of the Counter as +-- a) if the software assumes that the Counter is modified during reset, it +-- will initialize the Counter anyhow +-- b) the special case 'Counter not modified during reset' is covered +-- +-- Revision 1.3 2004/05/16 15:32:57 arniml +-- fix edge detector bug for counter +-- +-- Revision 1.2 2004/04/15 22:05:13 arniml +-- increment prescaler with MSTATE4 +-- +-- Revision 1.1 2004/03/23 21:31:53 arniml +-- initial check-in +-- +------------------------------------------------------------------------------- diff --git a/rtl/tech/cyclone/av_por.vhd b/rtl/tech/cyclone/av_por.vhd new file mode 100644 index 0000000..e00bb01 --- /dev/null +++ b/rtl/tech/cyclone/av_por.vhd @@ -0,0 +1,115 @@ +------------------------------------------------------------------------------- +-- +-- FPGA Adventure Vision +-- +-- $Id: av_por.vhd,v 1.1 2006/03/26 10:42:47 arnim Exp $ +-- +-- Wrapper for technology dependent power-on reset circuitry. +-- +-- Altera Cyclone flavor. +-- +-- Generate a reset upon power-on for specified number of clocks. +-- +------------------------------------------------------------------------------- +-- +-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity av_por is + + generic ( + delay_g : integer := 4; + cnt_width_g : integer := 2 + ); + port ( + clk_i : in std_logic; + por_n_o : out std_logic + ); + +end av_por; + + +library ieee; +use ieee.numeric_std.all; + +architecture cyclone of av_por is + + signal por_cnt_q : unsigned(cnt_width_g-1 downto 0) + -- pragma translate_off + -- initialize for simulation only + := (others => '0') + -- pragma translate_on + ; + signal por_n_q : std_logic + -- pragma translate_off + -- initialize for simulation only + := '0' + -- pragma translate_on + ; + + -- Specify power-up level of por counter and por source. + -- Refer to "Quartus II Integrated Synthesis", section "Altera Attribute". + attribute altera_attribute : string; + attribute altera_attribute of por_cnt_q : signal is "-name POWER_UP_LEVEL LOW"; + attribute altera_attribute of por_n_q : signal is "-name POWER_UP_LEVEL LOW"; + +begin + + ----------------------------------------------------------------------------- + -- Process por_cnt + -- + -- Purpose: + -- Generate a power-on reset for the specifiec number of clocks. + -- + por_cnt: process (clk_i) + begin + if clk_i'event and clk_i = '1' then + if por_cnt_q = delay_g then + por_n_q <= '1'; + else + por_cnt_q <= por_cnt_q + 1; + end if; + end if; + end process por_cnt; + -- + ----------------------------------------------------------------------------- + + por_n_o <= por_n_q; + +end cyclone; diff --git a/rtl/tech/generic/dpram.vhd b/rtl/tech/generic/dpram.vhd new file mode 100644 index 0000000..879867a --- /dev/null +++ b/rtl/tech/generic/dpram.vhd @@ -0,0 +1,104 @@ +------------------------------------------------------------------------------- +-- +-- FPGA Adventure Vision +-- +-- $Id: dpram.vhd,v 1.2 2006/04/02 18:50:23 arnim Exp $ +-- +-- Generic dual port RAM. +-- +------------------------------------------------------------------------------- +-- +-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity dpram is + + generic ( + addr_width_g : integer := 8; + data_width_g : integer := 8 + ); + port ( + clk_a_i : in std_logic; + we_i : in std_logic; + addr_a_i : in std_logic_vector(addr_width_g-1 downto 0); + data_a_i : in std_logic_vector(data_width_g-1 downto 0); + data_a_o : out std_logic_vector(data_width_g-1 downto 0); + clk_b_i : in std_logic; + addr_b_i : in std_logic_vector(addr_width_g-1 downto 0); + data_b_o : out std_logic_vector(data_width_g-1 downto 0) + ); + +end dpram; + + +library ieee; +use ieee.numeric_std.all; + +architecture rtl of dpram is + + type ram_t is array (natural range 2**addr_width_g-1 downto 0) of + std_logic_vector(data_width_g-1 downto 0); + signal ram_q : ram_t; + signal read_addr_a_q, + read_addr_b_q : unsigned(addr_width_g-1 downto 0); + +begin + + mem_a: process (clk_a_i) + begin + if clk_a_i'event and clk_a_i = '1' then + if we_i = '1' then + ram_q(to_integer(unsigned(addr_a_i))) <= data_a_i; + end if; + + read_addr_a_q <= unsigned(addr_a_i); + end if; + end process mem_a; + + mem_b: process (clk_b_i) + begin + if clk_b_i'event and clk_b_i = '1' then + read_addr_b_q <= unsigned(addr_b_i); + end if; + end process mem_b; + + data_a_o <= ram_q(to_integer(read_addr_a_q)); + data_b_o <= ram_q(to_integer(read_addr_b_q)); + +end rtl; diff --git a/rtl/tech/generic/generic_ram.vhd b/rtl/tech/generic/generic_ram.vhd new file mode 100644 index 0000000..c8b70ba --- /dev/null +++ b/rtl/tech/generic/generic_ram.vhd @@ -0,0 +1,99 @@ +------------------------------------------------------------------------------- +-- +-- FPGA Adventure Vision +-- +-- $Id: generic_ram.vhd,v 1.1 2006/03/18 11:28:17 arnim Exp $ +-- +-- Generic RTL flavour. +-- +-- Characteristics of the synchronous RAM: +-- - memory is updated with rising clock edge +-- - no read-through-write capability +-- +------------------------------------------------------------------------------- +-- +-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity generic_ram is + + generic ( + addr_width_g : integer := 10; + data_width_g : integer := 8 + ); + port ( + clk_i : in std_logic; + a_i : in std_logic_vector(addr_width_g-1 downto 0); + we_i : in std_logic; + d_i : in std_logic_vector(data_width_g-1 downto 0); + d_o : out std_logic_vector(data_width_g-1 downto 0) + ); + +end generic_ram; + + +library ieee; +use ieee.numeric_std.all; + +architecture rtl of generic_ram is + + type mem_t is array (natural range 0 to 2**addr_width_g-1) of + std_logic_vector(d_i'range); + signal mem_q : mem_t + -- pragma translate_off + := (others => (others => '0')) + -- pragma translate_on + ; + +begin + + mem: process (clk_i) + begin + + if clk_i'event and clk_i = '1' then + if we_i = '1' then + mem_q(to_integer(unsigned(a_i))) <= d_i; + end if; + + d_o <= mem_q(to_integer(unsigned(a_i))); + end if; + + end process mem; + +end rtl; diff --git a/rtl/tech/generic/syn_ram-generic_tech-a.vhd b/rtl/tech/generic/syn_ram-generic_tech-a.vhd new file mode 100644 index 0000000..57198c5 --- /dev/null +++ b/rtl/tech/generic/syn_ram-generic_tech-a.vhd @@ -0,0 +1,65 @@ +------------------------------------------------------------------------------- +-- +-- A synchronous parametrizable RAM instantiating a standard generic RAM. +-- +-- $Id: syn_ram-generic_tech-a.vhd,v 1.1 2006/03/18 11:28:17 arnim Exp $ +-- +-- Copyright (c) 2006, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.tech_comp_pack.generic_ram; + +architecture generic_tech of syn_ram is + +begin + + ram_b : generic_ram + generic map ( + addr_width_g => address_width_g, + data_width_g => 8 + ) + port map ( + clk_i => clk_i, + a_i => ram_addr_i, + we_i => ram_we_i, + d_i => ram_data_i, + d_o => ram_data_o + ); + +end generic_tech; diff --git a/rtl/tech/generic/syn_rom-av_bios-a.vhd b/rtl/tech/generic/syn_rom-av_bios-a.vhd new file mode 100644 index 0000000..f67b0fd --- /dev/null +++ b/rtl/tech/generic/syn_rom-av_bios-a.vhd @@ -0,0 +1,66 @@ +------------------------------------------------------------------------------- +-- +-- A synchronous parametrizable ROM instantiating a standard generic ROM +-- preloaded with the Adventure Vision BIOS. +-- +-- $Id: syn_rom-av_bios-a.vhd,v 1.1 2006/03/18 11:49:56 arnim Exp $ +-- +-- Copyright (c) 2006, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +architecture av_bios of syn_rom is + + component adventurevision_bios + port ( + Clk : in std_logic; + A : in std_logic_vector(9 downto 0); + D : out std_logic_vector(7 downto 0) + ); + end component; + +begin + + rom_b : adventurevision_bios + port map ( + Clk => clk_i, + A => rom_addr_i, + D => rom_data_o + ); + +end av_bios; diff --git a/rtl/tech/generic/t410_rom-struct-a.vhd b/rtl/tech/generic/t410_rom-struct-a.vhd new file mode 100644 index 0000000..6647d5b --- /dev/null +++ b/rtl/tech/generic/t410_rom-struct-a.vhd @@ -0,0 +1,24 @@ +------------------------------------------------------------------------------- +-- $Id: t410_rom-struct-a.vhd,v 1.1 2006/05/07 23:53:30 arnim Exp $ +------------------------------------------------------------------------------- + +architecture struct of t410_rom is + + component rom_t41x + port( + Clk : in std_logic; + A : in std_logic_vector(8 downto 0); + D : out std_logic_vector(7 downto 0) + ); + end component; + +begin + + rom_b : rom_t41x + port map ( + Clk => ck_i, + A => addr_i, + D => data_o + ); + +end struct; diff --git a/rtl/tech/spartan/av_por.vhd b/rtl/tech/spartan/av_por.vhd new file mode 100644 index 0000000..91bc0b3 --- /dev/null +++ b/rtl/tech/spartan/av_por.vhd @@ -0,0 +1,107 @@ +------------------------------------------------------------------------------- +-- +-- FPGA Adventure Vision +-- +-- $Id: av_por.vhd,v 1.4 2006/03/26 10:30:01 arnim Exp $ +-- +-- Wrapper for technology dependent power-on reset circuitry. +-- +-- Xilinx Spartan3 flavor. +-- +-- Generate a reset upon power-on for specified number of clocks. +-- +------------------------------------------------------------------------------- +-- +-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity av_por is + + generic ( + delay_g : integer := 4; + cnt_width_g : integer := 2 + ); + port ( + clk_i : in std_logic; + por_n_o : out std_logic + ); + +end av_por; + + +library ieee; +use ieee.numeric_std.all; + +architecture spartan of av_por is + + ----------------------------------------------------------------------------- + -- According to + -- "XST User Guide", Chapter 6 "VHDL Language Support", "Initial Values" + -- XST honors the initial value assigned to a flip-flop. Simple :-) + -- + signal por_cnt_q : unsigned(cnt_width_g-1 downto 0) + := to_unsigned(delay_g, cnt_width_g); + signal por_n_q : std_logic := '0'; + -- + ----------------------------------------------------------------------------- + +begin + + ----------------------------------------------------------------------------- + -- Process por_cnt + -- + -- Purpose: + -- Generate a power-on reset for the specified number of clocks. + -- + por_cnt: process (clk_i) + begin + if clk_i'event and clk_i = '1' then + if por_cnt_q = 0 then + por_n_q <= '1'; + else + por_cnt_q <= por_cnt_q - 1; + end if; + end if; + end process por_cnt; + -- + ----------------------------------------------------------------------------- + + por_n_o <= por_n_q; + +end spartan; diff --git a/rtl/tech/tech_comp_pack-p.vhd b/rtl/tech/tech_comp_pack-p.vhd new file mode 100644 index 0000000..0a1caf9 --- /dev/null +++ b/rtl/tech/tech_comp_pack-p.vhd @@ -0,0 +1,85 @@ +------------------------------------------------------------------------------- +-- +-- FPGA Adventure Vision +-- +-- $Id: tech_comp_pack-p.vhd,v 1.5 2006/04/02 18:48:29 arnim Exp $ +-- +-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +package tech_comp_pack is + + component av_por + generic ( + delay_g : integer := 4; + cnt_width_g : integer := 2 + ); + port ( + clk_i : in std_logic; + por_n_o : out std_logic + ); + end component; + + component generic_ram + generic ( + addr_width_g : integer := 10; + data_width_g : integer := 8 + ); + port ( + clk_i : in std_logic; + a_i : in std_logic_vector(addr_width_g-1 downto 0); + we_i : in std_logic; + d_i : in std_logic_vector(data_width_g-1 downto 0); + d_o : out std_logic_vector(data_width_g-1 downto 0) + ); + end component; + + component dpram + generic ( + addr_width_g : integer := 8; + data_width_g : integer := 8 + ); + port ( + clk_a_i : in std_logic; + we_i : in std_logic; + addr_a_i : in std_logic_vector(addr_width_g-1 downto 0); + data_a_i : in std_logic_vector(data_width_g-1 downto 0); + data_a_o : out std_logic_vector(data_width_g-1 downto 0); + clk_b_i : in std_logic; + addr_b_i : in std_logic_vector(addr_width_g-1 downto 0); + data_b_o : out std_logic_vector(data_width_g-1 downto 0) + ); + end component; + + component syn_ram + generic ( + address_width_g : positive := 8 + ); + port ( + clk_i : in std_logic; + res_i : in std_logic; + ram_addr_i : in std_logic_vector(address_width_g-1 downto 0); + ram_data_i : in std_logic_vector(7 downto 0); + ram_we_i : in std_logic; + ram_data_o : out std_logic_vector(7 downto 0) + ); + end component; + + component syn_rom + generic ( + address_width_g : positive := 9 + ); + port ( + clk_i : in std_logic; + rom_addr_i : in std_logic_vector(address_width_g-1 downto 0); + rom_data_o : out std_logic_vector(7 downto 0) + ); + end component; + +end tech_comp_pack; diff --git a/rtl/video/av_frame_buffer.vhd b/rtl/video/av_frame_buffer.vhd new file mode 100644 index 0000000..df435bc --- /dev/null +++ b/rtl/video/av_frame_buffer.vhd @@ -0,0 +1,298 @@ +------------------------------------------------------------------------------- +-- +-- FPGA Adventure Vision +-- +-- $Id: av_frame_buffer.vhd,v 1.6 2006/04/02 18:53:04 arnim Exp $ +-- +-- Framebuffer module +-- +------------------------------------------------------------------------------- +-- +-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity av_frame_buffer is + + port ( + -- System Interface ------------------------------------------------------- + clk_11m_i : in std_logic; + por_n_i : in std_logic; + -- Display Interface ------------------------------------------------------ + disp_photo_int_i : in std_logic; + led_n_i : in std_logic_vector(39 downto 0); + -- Framebuffer Interface -------------------------------------------------- + fb_a_i : in std_logic_vector(12 downto 0); + fb_d_o : out std_logic; + fb_sync_o : out std_logic + ); + +end av_frame_buffer; + + +library ieee; +use ieee.numeric_std.all; + +use work.tech_comp_pack.generic_ram; + +architecture rtl of av_frame_buffer is + + constant y_off_c : natural := 150; + type y_offset_t is array (natural range 39 downto 0) of natural; + constant y_offset_c : y_offset_t := ( + 00 * y_off_c, 01 * y_off_c, 02 * y_off_c, 03 * y_off_c, 04 * y_off_c, + 05 * y_off_c, 06 * y_off_c, 07 * y_off_c, 08 * y_off_c, 09 * y_off_c, + 10 * y_off_c, 11 * y_off_c, 12 * y_off_c, 13 * y_off_c, 14 * y_off_c, + 15 * y_off_c, 16 * y_off_c, 17 * y_off_c, 18 * y_off_c, 19 * y_off_c, + 20 * y_off_c, 21 * y_off_c, 22 * y_off_c, 23 * y_off_c, 24 * y_off_c, + 25 * y_off_c, 26 * y_off_c, 27 * y_off_c, 28 * y_off_c, 29 * y_off_c, + 30 * y_off_c, 31 * y_off_c, 32 * y_off_c, 33 * y_off_c, 34 * y_off_c, + 35 * y_off_c, 36 * y_off_c, 37 * y_off_c, 38 * y_off_c, 39 * y_off_c); + + signal cnt_x_q : unsigned(7 downto 0); + signal cnt_y_q : unsigned(5 downto 0); + + subtype cnt_capt_t is unsigned(9 downto 0); + signal cnt_capt_q : cnt_capt_t; + -- times the first capture after photo interruptor trigger + constant cnt_capt_photo_int_c : cnt_capt_t := + to_unsigned(798, cnt_capt_t'length); + -- times each x position in a way that the slots 50 and 150 + -- do not result in a desynchronization + -- slots 50 and 150 are 83us long instead of 60us, presumably due to + -- switching the memory regions in the BIOS routine + constant cnt_capt_scan_c : cnt_capt_t := + to_unsigned(664, cnt_capt_t'length); + + signal photo_int_q : std_logic; + + signal frame_q : std_logic; + + type scan_state_t is (IDLE, SCANNING); + signal scan_state_q : scan_state_t; + + type fb_a_t is array (natural range 1 downto 0) of + std_logic_vector(12 downto 0); + signal fb_a_s : fb_a_t; + signal fb_w_s : std_logic_vector(1 downto 0); + subtype fb_dbit_t is std_logic_vector(0 downto 0); + type fb_d_t is array (natural range 1 downto 0) of fb_dbit_t; + signal fb_din_s : fb_dbit_t; + signal fb_dout_s : fb_d_t; + + signal fb_sync_q : std_logic_vector( 1 downto 0); + +begin + + ----------------------------------------------------------------------------- + -- Process seq + -- + -- Purpose: + -- Implements the sequential control elements. + -- + seq: process (clk_11m_i, por_n_i) + variable photo_int_fall_v : boolean; + variable cnt_x_at_150_v : boolean; + variable cnt_y_at_39_v : boolean; + variable cnt_capt_zero_v : boolean; + begin + if por_n_i = '0' then + cnt_x_q <= (others => '0'); + cnt_y_q <= (others => '0'); + photo_int_q <= '1'; + frame_q <= '0'; + scan_state_q <= IDLE; + fb_sync_q <= (others => '0'); + cnt_capt_q <= cnt_capt_photo_int_c; + + elsif clk_11m_i'event and clk_11m_i = '1' then + cnt_x_at_150_v := cnt_x_q = 150; + cnt_y_at_39_v := cnt_y_q = 39; + cnt_capt_zero_v := cnt_capt_q = 0; + -- edge detector + photo_int_fall_v := disp_photo_int_i = '0' and photo_int_q = '1'; + + photo_int_q <= disp_photo_int_i; + + -- scan FSM + case scan_state_q is + when IDLE => + if cnt_capt_zero_v and not cnt_x_at_150_v then + scan_state_q <= SCANNING; + end if; + + when SCANNING => + -- stop scanning when last led is being saved + -- or upon new sync + if cnt_y_at_39_v or photo_int_fall_v then + scan_state_q <= IDLE; + end if; + + when others => + null; + end case; + + -- x counter + if photo_int_fall_v then + cnt_x_q <= (others => '0'); + elsif cnt_y_at_39_v and not cnt_x_at_150_v then + cnt_x_q <= cnt_x_q + 1; + end if; + + -- edge detection for frame sync + if cnt_x_at_150_v then + fb_sync_q(0) <= '1'; + + if fb_sync_q(0) = '0' then + fb_sync_q(1) <= '1'; + else + fb_sync_q(1) <= '0'; + end if; + + else + fb_sync_q(0) <= '0'; + fb_sync_q(1) <= '0'; + end if; + + -- y counter + if scan_state_q = SCANNING and + not cnt_y_at_39_v then + cnt_y_q <= cnt_y_q + 1; + else + cnt_y_q <= (others => '0'); + end if; + + -- frame selector + if fb_sync_q(1) = '1' then + frame_q <= not frame_q; + end if; + + -- capture counter + if disp_photo_int_i = '0' then + cnt_capt_q <= cnt_capt_photo_int_c; + elsif cnt_capt_zero_v then + cnt_capt_q <= cnt_capt_scan_c; + else + cnt_capt_q <= cnt_capt_q - 1; + end if; + + end if; + end process seq; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process fb_ctrl + -- + -- Purpose: + -- Control logic for the framebuffers. + -- + fb_ctrl: process (scan_state_q, + frame_q, + cnt_x_q, cnt_y_q, + fb_a_i, + fb_dout_s, + led_n_i) + variable a_v : unsigned(12 downto 0); + variable w_v : std_logic; + begin + -- calculate address for write + a_v := "0" & "0000" & cnt_x_q + y_offset_c(to_integer(cnt_y_q)); + + -- write whenever scan FSM is in state SCANNING + if scan_state_q = SCANNING then + w_v := '1'; + else + w_v := '0'; + end if; + + -- MUX address, write enable and write data + if frame_q = '0' then + fb_a_s(0) <= std_logic_vector(a_v); + fb_w_s(0) <= w_v; + -- + fb_a_s(1) <= fb_a_i; + fb_w_s(1) <= '0'; + -- + fb_d_o <= fb_dout_s(1)(0); + + else + fb_a_s(0) <= fb_a_i; + fb_w_s(0) <= '0'; + -- + fb_a_s(1) <= std_logic_vector(a_v); + fb_w_s(1) <= w_v; + -- + fb_d_o <= fb_dout_s(0)(0); + + end if; + + -- select framebuffer write data + fb_din_s(0) <= not led_n_i(to_integer(cnt_y_q)); + + end process fb_ctrl; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Framebuffer RAMs + ----------------------------------------------------------------------------- + fbs: for idx in 0 to 1 generate + fb_b : generic_ram + generic map ( + addr_width_g => 13, + data_width_g => 1 + ) + port map ( + clk_i => clk_11m_i, + a_i => fb_a_s(idx), + we_i => fb_w_s(idx), + d_i => fb_din_s, + d_o => fb_dout_s(idx) + ); + end generate; + + + ----------------------------------------------------------------------------- + -- Output mapping + ----------------------------------------------------------------------------- + fb_sync_o <= fb_sync_q(1); + +end rtl; diff --git a/rtl/video/av_raster.vhd b/rtl/video/av_raster.vhd new file mode 100644 index 0000000..5eab774 --- /dev/null +++ b/rtl/video/av_raster.vhd @@ -0,0 +1,443 @@ +------------------------------------------------------------------------------- +-- +-- FPGA Adventure Vision +-- +-- $Id: av_raster.vhd,v 1.5 2006/04/02 18:53:04 arnim Exp $ +-- +-- Rasterizer module +-- +------------------------------------------------------------------------------- +-- +-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity av_raster is + + generic ( + is_pal_g : integer := 0 + ); + port ( + -- System Interface ------------------------------------------------------- + clk_11m_i : in std_logic; + por_n_i : in std_logic; + -- Framebuffer Interface -------------------------------------------------- + fb_a_o : out std_logic_vector(12 downto 0); + fb_d_i : in std_logic; + fb_sync_i : in std_logic; + -- RGB Video Interface ---------------------------------------------------- + rgb_r_o : out std_logic_vector( 2 downto 0); + rgb_hsync_n_o : out std_logic; + rgb_vsync_n_o : out std_logic; + rgb_csync_n_o : out std_logic; + vblank : out std_logic; + hblank : out std_logic; + -- Core Options ----------------------------------------------------------- + fixed_intensity: in std_logic + ); + +end av_raster; + + +library ieee; +use ieee.numeric_std.all; + +architecture rtl of av_raster is + + -- horizontal prescaler + subtype hprescal_t is unsigned(1 downto 0); + constant hprescal_reload_c : hprescal_t := to_unsigned(2, hprescal_t'length); + signal hprescal_q : hprescal_t; + signal hprescal_zero_s : boolean; + + -- vertical prescaler + subtype vprescal_t is unsigned(1 downto 0); + constant vprescal_reload_c : vprescal_t := to_unsigned(2, vprescal_t'length); + signal vprescal_q : vprescal_t; + signal vprescal_zero_s : boolean; + + -- Horizontal video timing -------------------------------------------------- + -- + subtype hcnt_t is signed(7+1 downto 0); + signal hcnt_q : hcnt_t; + signal hcnt_at_start_q : boolean; + -- + -- start value for horizontal counter + signal hstart_s : hcnt_t; + -- end of horizontal sync + signal hsync_end_s : hcnt_t; + -- start of active area + signal hstart_active_s : hcnt_t; + -- last pixel of active area + signal hlast_active_s : hcnt_t; + -- last pixel of front porch + signal hlast_pixel_s : hcnt_t; + + -- Vertical video timing ---------------------------------------------------- + -- + subtype vcnt_t is signed(6+1 downto 0); + signal vcnt_q : vcnt_t; + signal vcnt_pix_q : unsigned(12 downto 0); + -- + -- start value for vertical counter + signal vstart_s : vcnt_t; + -- end of vertical sync + signal vsync_end_s : vcnt_t; + -- start of active area + signal vstart_active_s : vcnt_t; + -- last display line of active area + signal vlast_active_s : vcnt_t; + -- last display line of front porch + signal vlast_line_s : vcnt_t; + + signal hsync_n_q, + vsync_n_q : std_logic; + signal active_display_q : boolean; + + signal vblank_en : std_logic; + signal hblank_en : std_logic; + + signal frame_cnt_q : unsigned(2 downto 0); + signal frame_sync_q : boolean; + + signal rgb_r_q : unsigned(2 downto 0); + +begin + + ----------------------------------------------------------------------------- + -- Timing values for NTSC (525/60) + -- + -- 525 scanlines, 483 visible + ----------------------------------------------------------------------------- + ntsc: if is_pal_g = 0 generate + -- start value for horizontal counter: + -- 10.5 us + 20 pixels + hstart_s <= to_signed(-58, hcnt_t'length); + -- end of horizontal sync: + -- 4.7 us after hsync start + hsync_end_s <= to_signed(-41, hcnt_t'length); + -- start of active area + hstart_active_s <= to_signed( 0, hcnt_t'length); + -- last pixel of active area + hlast_active_s <= to_signed(149, hcnt_t'length); + -- last pixel of front porch: + -- 1.5 us + 20 pixels after active area + hlast_pixel_s <= to_signed(174, hcnt_t'length); + + -- start value for vertical counter: + -- 60 scanlines before active display + vstart_s <= to_signed(-28, vcnt_t'length); + -- end of vertical sync + vsync_end_s <= to_signed(-25, vcnt_t'length); + -- start of active area + vstart_active_s <= to_signed( 0, vcnt_t'length); + -- last display line of active area + vlast_active_s <= to_signed( 39, vcnt_t'length); + -- last display line of front porch: + -- 22 scanlines after active area + vlast_line_s <= to_signed( 58, vcnt_t'length); + end generate; + + + ----------------------------------------------------------------------------- + -- Timing values for PAL (625/50) + -- + -- 625 scanlines, 575 visible + ----------------------------------------------------------------------------- + pal: if is_pal_g /= 0 generate + -- start value for horizontal counter: + -- 10.5 us + 20 pixels + hstart_s <= to_signed(-58, hcnt_t'length); + -- end of horizontal sync: + -- 4.7 us after hsync start + hsync_end_s <= to_signed(-41, hcnt_t'length); + -- start of active area + hstart_active_s <= to_signed( 0, hcnt_t'length); + -- last pixel of active area + hlast_active_s <= to_signed(149, hcnt_t'length); + -- last pixel of front porch: + -- 1.5 us + 20 pixels after active area + hlast_pixel_s <= to_signed(175, hcnt_t'length); + + -- start value for vertical counter: + -- 96 scanlines before active display + vstart_s <= to_signed(-32, vcnt_t'length); + -- end of vertical sync + vsync_end_s <= to_signed(-27, vcnt_t'length); + -- start of active area + vstart_active_s <= to_signed( 0, vcnt_t'length); + -- last display line of active area + vlast_active_s <= to_signed( 39, vcnt_t'length); + -- last display line of front porch: + -- 96 scanlines after active area + vlast_line_s <= to_signed( 71, vcnt_t'length); + end generate; + + + ----------------------------------------------------------------------------- + -- Process htiming + -- + -- Purpose: + -- Implements the counters for horizontal timing. + -- + htiming: process (clk_11m_i, por_n_i, + hstart_s) + begin + if por_n_i = '0' then + hprescal_q <= hprescal_reload_c; + hcnt_q <= hstart_s; + hsync_n_q <= '1'; + + elsif clk_11m_i'event and clk_11m_i = '1' then + -- horizontal prescaler + if hprescal_zero_s then + hprescal_q <= hprescal_reload_c; + else + hprescal_q <= hprescal_q - 1; + end if; + + if hprescal_zero_s then + -- horizontal pixel counter + if hcnt_q = hlast_pixel_s then + hcnt_q <= hstart_s; + else + hcnt_q <= hcnt_q + 1; + end if; + + -- horizontal sync + if hcnt_q < hsync_end_s then + hsync_n_q <= '0'; + else + hsync_n_q <= '1'; + end if; + end if; + + end if; + end process htiming; + -- + hprescal_zero_s <= hprescal_q = 0; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process vtiming + -- + -- Purpose: + -- Implements the counters for vertical timing. + -- + vtiming: process (clk_11m_i, por_n_i, + vstart_s) + variable hcnt_at_start_v : boolean; + begin + if por_n_i = '0' then + vprescal_q <= vprescal_reload_c; + vcnt_q <= vstart_s; + vsync_n_q <= '1'; + hcnt_at_start_q <= false; + + elsif clk_11m_i'event and clk_11m_i = '1' then + hcnt_at_start_v := hcnt_q = hstart_s; + + hcnt_at_start_q <= hcnt_at_start_v; + + -- horizontal counter just reached hstart_c + if hcnt_at_start_v and not hcnt_at_start_q then + -- vertical prescaler + if vprescal_zero_s then + vprescal_q <= vprescal_reload_c; + else + vprescal_q <= vprescal_q - 1; + end if; + + if vprescal_zero_s then + -- vertical line counter + if vcnt_q = vlast_line_s then + vcnt_q <= vstart_s; + else + vcnt_q <= vcnt_q + 1; + end if; + + -- vertical sync + if vcnt_q < vsync_end_s then + vsync_n_q <= '0'; + else + vsync_n_q <= '1'; + end if; + end if; + + end if; + + end if; + end process vtiming; + -- + vprescal_zero_s <= vprescal_q = 0; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process ctrl + -- + -- Purpose: + -- Implements various control registers. + -- + ctrl: process (clk_11m_i, por_n_i) + variable r_offset_v : natural; + begin + if por_n_i = '0' then + active_display_q <= false; + frame_cnt_q <= (others => '0'); + frame_sync_q <= false; + rgb_r_q <= (others => '0'); + vcnt_pix_q <= (others => '0'); + vblank_en <= '0'; + hblank_en <= '0'; + + elsif clk_11m_i'event and clk_11m_i = '1' then + -- catch framebuffer sync event + if fb_sync_i = '1' then + frame_sync_q <= true; + end if; + + if hprescal_zero_s then + -- determine active display area + if vcnt_q >= 0 and + vcnt_q <= vlast_active_s then + vblank_en <= '0'; + if hcnt_q = -1 then + active_display_q <= true; + hblank_en <= '0'; + elsif hcnt_q = hlast_active_s then + active_display_q <= false; + hblank_en <= '1'; + end if; + + else + active_display_q <= false; + if (vcnt_q >= 49) or (vcnt_q <= -10) then + vblank_en <= '1'; + else + vblank_en <= '0'; + end if; + if hcnt_q = -1 then + hblank_en <= '0'; + elsif hcnt_q = hlast_active_s then + hblank_en <= '1'; + end if; + end if; + + -- frame counter + if vcnt_q = vlast_line_s and + hcnt_q = hlast_pixel_s and + vprescal_zero_s then + if frame_sync_q then + frame_cnt_q <= (others => '0'); + frame_sync_q <= false; + else + frame_cnt_q <= frame_cnt_q + 1; + end if; + end if; + + -- Red channel intensity calculation + -- Theorie of operation: + -- With every new h/v scan, the intensity of the screen decays. + -- This is implemented by subtracting the frame counter from the + -- maximum intensity. + -- The inner scanline is drawn with this intensity, while the + -- outer scanlines are drawn with reduced intensity. + -- + if fb_d_i = '1' and active_display_q then + -- determine intensity upon vertical prescaler + if fixed_intensity = '1' then + case vprescal_q is + when "00" | + "01" => + r_offset_v := 7; + when "10" => + r_offset_v := 0; + when others => + r_offset_v := 7; + end case; + rgb_r_q <= to_unsigned(r_offset_v, 3); + else + case vprescal_q is + when "10" | + "00" => + r_offset_v := 4; + when "01" => + r_offset_v := 7; + when others => + r_offset_v := 7; + end case; + rgb_r_q <= r_offset_v - frame_cnt_q; + end if; + else + rgb_r_q <= (others => '0'); + end if; + + -- vertical pixel/line counter + if hcnt_q = hlast_active_s and + vprescal_zero_s then + if active_display_q then + vcnt_pix_q <= vcnt_pix_q + 150; + else + -- clear counter if display left active are + vcnt_pix_q <= (others => '0'); + end if; + end if; + + end if; + end if; + end process ctrl; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Output mapping + ----------------------------------------------------------------------------- + fb_a_o <= std_logic_vector(unsigned(hcnt_q(7 downto 0)) + vcnt_pix_q); + rgb_r_o <= std_logic_vector(rgb_r_q); + rgb_hsync_n_o <= hsync_n_q; + rgb_vsync_n_o <= vsync_n_q; + rgb_csync_n_o <= hsync_n_q and vsync_n_q; + hblank <= hblank_en; + vblank <= vblank_en; + +end rtl; diff --git a/rtl/video/av_video.vhd b/rtl/video/av_video.vhd new file mode 100644 index 0000000..575bfea --- /dev/null +++ b/rtl/video/av_video.vhd @@ -0,0 +1,123 @@ +------------------------------------------------------------------------------- +-- +-- FPGA Adventure Vision +-- +-- $Id: av_video.vhd,v 1.4 2006/04/02 18:53:04 arnim Exp $ +-- +-- Video supplement hierarchy +-- +------------------------------------------------------------------------------- +-- +-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity av_video is + + generic ( + is_pal_g : integer := 0 + ); + port ( + -- System Interface ------------------------------------------------------- + clk_11m_i : in std_logic; + por_n_i : in std_logic; + -- Display Interface ------------------------------------------------------ + disp_photo_int_i : in std_logic; + led_n_i : in std_logic_vector(39 downto 0); + -- RGB Video Interface ---------------------------------------------------- + rgb_r_o : out std_logic_vector( 2 downto 0); + rgb_hsync_n_o : out std_logic; + rgb_vsync_n_o : out std_logic; + rgb_csync_n_o : out std_logic; + vblank : out std_logic; + hblank : out std_logic; + fixed_intensity : in std_logic + ); + +end av_video; + + +use work.av_video_comp_pack.av_frame_buffer; +use work.av_video_comp_pack.av_raster; + +architecture struct of av_video is + + signal fb_a_s : std_logic_vector(12 downto 0); + signal fb_d_s : std_logic; + signal fb_sync_s : std_logic; + +begin + + ----------------------------------------------------------------------------- + -- Framebuffer + ----------------------------------------------------------------------------- + frame_buf_b : av_frame_buffer + port map ( + clk_11m_i => clk_11m_i, + por_n_i => por_n_i, + disp_photo_int_i => disp_photo_int_i, + led_n_i => led_n_i, + fb_a_i => fb_a_s, + fb_d_o => fb_d_s, + fb_sync_o => fb_sync_s + ); + + + ----------------------------------------------------------------------------- + -- Rasterizer + ----------------------------------------------------------------------------- + raster_b : av_raster + generic map ( + is_pal_g => is_pal_g + ) + port map ( + clk_11m_i => clk_11m_i, + por_n_i => por_n_i, + fb_a_o => fb_a_s, + fb_d_i => fb_d_s, + fb_sync_i => fb_sync_s, + rgb_r_o => rgb_r_o, + rgb_hsync_n_o => rgb_hsync_n_o, + rgb_vsync_n_o => rgb_vsync_n_o, + rgb_csync_n_o => rgb_csync_n_o, + vblank => vblank, + hblank => hblank, + fixed_intensity => fixed_intensity + ); + +end struct; diff --git a/rtl/video/av_video_comp_pack-p.vhd b/rtl/video/av_video_comp_pack-p.vhd new file mode 100644 index 0000000..b11c767 --- /dev/null +++ b/rtl/video/av_video_comp_pack-p.vhd @@ -0,0 +1,78 @@ +------------------------------------------------------------------------------- +-- +-- FPGA Adventure Vision +-- +-- $Id: av_video_comp_pack-p.vhd,v 1.4 2006/04/02 18:53:04 arnim Exp $ +-- +-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +package av_video_comp_pack is + + component av_video + generic ( + is_pal_g : integer := 0 + ); + port ( + -- System Interface ----------------------------------------------------- + clk_11m_i : in std_logic; + por_n_i : in std_logic; + -- Display Interface ---------------------------------------------------- + disp_photo_int_i : in std_logic; + led_n_i : in std_logic_vector(39 downto 0); + -- RGB Video Interface -------------------------------------------------- + rgb_r_o : out std_logic_vector( 2 downto 0); + rgb_hsync_n_o : out std_logic; + rgb_vsync_n_o : out std_logic; + rgb_csync_n_o : out std_logic; + vblank : out std_logic; + hblank : out std_logic; + fixed_intensity : in std_logic + ); + end component; + + component av_frame_buffer + port ( + -- System Interface ----------------------------------------------------- + clk_11m_i : in std_logic; + por_n_i : in std_logic; + -- Display Interface ---------------------------------------------------- + disp_photo_int_i : in std_logic; + led_n_i : in std_logic_vector(39 downto 0); + -- Framebuffer Interface ------------------------------------------------ + fb_a_i : in std_logic_vector(12 downto 0); + fb_d_o : out std_logic; + fb_sync_o : out std_logic + ); + end component; + + component av_raster + generic ( + is_pal_g : integer := 0 + ); + port ( + -- System Interface ----------------------------------------------------- + clk_11m_i : in std_logic; + por_n_i : in std_logic; + -- Framebuffer Interface ------------------------------------------------ + fb_a_o : out std_logic_vector(12 downto 0); + fb_d_i : in std_logic; + fb_sync_i : in std_logic; + -- RGB Video Interface -------------------------------------------------- + rgb_r_o : out std_logic_vector( 2 downto 0); + rgb_hsync_n_o : out std_logic; + rgb_vsync_n_o : out std_logic; + rgb_csync_n_o : out std_logic; + vblank : out std_logic; + hblank : out std_logic; + fixed_intensity: in std_logic + ); + end component; + +end av_video_comp_pack; diff --git a/sys/alsa.sv b/sys/alsa.sv new file mode 100644 index 0000000..9034389 --- /dev/null +++ b/sys/alsa.sv @@ -0,0 +1,157 @@ +//============================================================================ +// +// ALSA sound support for MiSTer +// (c)2019,2020 Alexey Melnikov +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +//============================================================================ + +module alsa +#( + parameter CLK_RATE = 24576000 +) +( + input reset, + input clk, + + output reg [31:3] ram_address, + input [63:0] ram_data, + output reg ram_req = 0, + input ram_ready, + + input spi_ss, + input spi_sck, + input spi_mosi, + output spi_miso, + + output reg [15:0] pcm_l, + output reg [15:0] pcm_r +); + +reg [60:0] buf_info; +reg [6:0] spicnt = 0; +always @(posedge spi_sck, posedge spi_ss) begin + reg [95:0] spi_data; + + if(spi_ss) spicnt <= 0; + else begin + spi_data[{spicnt[6:3],~spicnt[2:0]}] <= spi_mosi; + if(&spicnt) buf_info <= {spi_data[82:67],spi_data[50:35],spi_data[31:3]}; + spicnt <= spicnt + 1'd1; + end +end + +assign spi_miso = spi_out[{spicnt[4:3],~spicnt[2:0]}]; + +reg [31:0] spi_out = 0; +always @(posedge clk) if(spi_ss) spi_out <= {buf_rptr, hurryup, 8'h00}; + + +reg [31:3] buf_addr; +reg [18:3] buf_len; +reg [18:3] buf_wptr = 0; + +always @(posedge clk) begin + reg [60:0] data1,data2; + + data1 <= buf_info; + data2 <= data1; + if(data2 == data1) {buf_wptr,buf_len,buf_addr} <= data2; +end + +reg [2:0] hurryup = 0; +reg [18:3] buf_rptr = 0; + +always @(posedge clk) begin + reg [18:3] len = 0; + reg [1:0] ready = 0; + reg [63:0] readdata; + reg got_first = 0; + reg [7:0] ce_cnt = 0; + reg [1:0] state = 0; + + if(reset) begin + ready <= 0; + ce_cnt <= 0; + state <= 0; + got_first <= 0; + len <= 0; + end + else begin + + //ramp up + if(len[18:14] && (hurryup < 1)) hurryup <= 1; + if(len[18:16] && (hurryup < 2)) hurryup <= 2; + if(len[18:17] && (hurryup < 4)) hurryup <= 4; + + //ramp down + if(!len[18:15] && (hurryup > 2)) hurryup <= 2; + if(!len[18:13] && (hurryup > 1)) hurryup <= 1; + if(!len[18:10]) hurryup <= 0; + + if(ce_sample && ~&ce_cnt) ce_cnt <= ce_cnt + 1'd1; + + case(state) + 0: if(!ce_sample) begin + if(ready) begin + if(ce_cnt) begin + {readdata[31:0],pcm_r,pcm_l} <= readdata; + ready <= ready - 1'd1; + ce_cnt <= ce_cnt - 1'd1; + end + end + else if(buf_rptr != buf_wptr) begin + if(~got_first) begin + buf_rptr <= buf_wptr; + got_first <= 1; + end + else begin + ram_address <= buf_addr + buf_rptr; + ram_req <= ~ram_req; + buf_rptr <= buf_rptr + 1'd1; + len <= (buf_wptr < buf_rptr) ? (buf_len + buf_wptr - buf_rptr) : (buf_wptr - buf_rptr); + state <= 1; + end + end + else begin + len <= 0; + ce_cnt <= 0; + hurryup <= 0; + end + end + 1: if(ram_ready) begin + ready <= 2; + readdata <= ram_data; + if(buf_rptr >= buf_len) buf_rptr <= buf_rptr - buf_len; + state <= 0; + end + endcase + end +end + +reg ce_sample; +always @(posedge clk) begin + reg [31:0] acc = 0; + + ce_sample <= 0; + acc <= acc + 48000 + {hurryup,6'd0}; + if(acc >= CLK_RATE) begin + acc <= acc - CLK_RATE; + ce_sample <= 1; + end +end + +endmodule diff --git a/sys/arcade_video.v b/sys/arcade_video.v new file mode 100644 index 0000000..2838f26 --- /dev/null +++ b/sys/arcade_video.v @@ -0,0 +1,324 @@ +//============================================================================ +// +// Copyright (C) 2017-2020 Sorgelig +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +//============================================================================ + +////////////////////////////////////////////////////////// +// DW: +// 6 : 2R 2G 2B +// 8 : 3R 3G 2B +// 9 : 3R 3G 3B +// 12 : 4R 4G 4B +// 24 : 8R 8G 8B + +module arcade_video #(parameter WIDTH=320, DW=8, GAMMA=1) +( + input clk_video, + input ce_pix, + + input[DW-1:0] RGB_in, + input HBlank, + input VBlank, + input HSync, + input VSync, + + output CLK_VIDEO, + output CE_PIXEL, + output [7:0] VGA_R, + output [7:0] VGA_G, + output [7:0] VGA_B, + output VGA_HS, + output VGA_VS, + output VGA_DE, + output [1:0] VGA_SL, + + input [2:0] fx, + input forced_scandoubler, + inout [21:0] gamma_bus +); + +assign CLK_VIDEO = clk_video; + +wire hs_fix,vs_fix; +sync_fix sync_v(CLK_VIDEO, HSync, hs_fix); +sync_fix sync_h(CLK_VIDEO, VSync, vs_fix); + +reg [DW-1:0] RGB_fix; + +reg CE,HS,VS,HBL,VBL; +always @(posedge CLK_VIDEO) begin + reg old_ce; + old_ce <= ce_pix; + CE <= 0; + if(~old_ce & ce_pix) begin + CE <= 1; + HS <= hs_fix; + if(~HS & hs_fix) VS <= vs_fix; + + RGB_fix <= RGB_in; + HBL <= HBlank; + if(HBL & ~HBlank) VBL <= VBlank; + end +end + +wire [7:0] R,G,B; + +generate + if(DW == 6) begin + assign R = {RGB_fix[5:4],RGB_fix[5:4],RGB_fix[5:4],RGB_fix[5:4]}; + assign G = {RGB_fix[3:2],RGB_fix[3:2],RGB_fix[3:2],RGB_fix[3:2]}; + assign B = {RGB_fix[1:0],RGB_fix[1:0],RGB_fix[1:0],RGB_fix[1:0]}; + end + else if(DW == 8) begin + assign R = {RGB_fix[7:5],RGB_fix[7:5],RGB_fix[7:6]}; + assign G = {RGB_fix[4:2],RGB_fix[4:2],RGB_fix[4:3]}; + assign B = {RGB_fix[1:0],RGB_fix[1:0],RGB_fix[1:0],RGB_fix[1:0]}; + end + else if(DW == 9) begin + assign R = {RGB_fix[8:6],RGB_fix[8:6],RGB_fix[8:7]}; + assign G = {RGB_fix[5:3],RGB_fix[5:3],RGB_fix[5:4]}; + assign B = {RGB_fix[2:0],RGB_fix[2:0],RGB_fix[2:1]}; + end + else if(DW == 12) begin + assign R = {RGB_fix[11:8],RGB_fix[11:8]}; + assign G = {RGB_fix[7:4],RGB_fix[7:4]}; + assign B = {RGB_fix[3:0],RGB_fix[3:0]}; + end + else begin // 24 + assign R = RGB_fix[23:16]; + assign G = RGB_fix[15:8]; + assign B = RGB_fix[7:0]; + end +endgenerate + +assign VGA_SL = sl[1:0]; +wire [2:0] sl = fx ? fx - 1'd1 : 3'd0; +wire scandoubler = fx || forced_scandoubler; + +video_mixer #(.LINE_LENGTH(WIDTH+4), .HALF_DEPTH(DW!=24), .GAMMA(GAMMA)) video_mixer +( + .CLK_VIDEO(CLK_VIDEO), + .ce_pix(CE), + .CE_PIXEL(CE_PIXEL), + + .scandoubler(scandoubler), + .hq2x(fx==1), + .gamma_bus(gamma_bus), + + .R((DW!=24) ? R[7:4] : R), + .G((DW!=24) ? G[7:4] : G), + .B((DW!=24) ? B[7:4] : B), + + .HSync (HS), + .VSync (VS), + .HBlank(HBL), + .VBlank(VBL), + + .VGA_R(VGA_R), + .VGA_G(VGA_G), + .VGA_B(VGA_B), + .VGA_VS(VGA_VS), + .VGA_HS(VGA_HS), + .VGA_DE(VGA_DE) +); + +endmodule + +//============================================================================ +// +// Screen +90/-90 deg. rotation +// Copyright (C) 2020 Sorgelig +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +//============================================================================ + +module screen_rotate +( + input CLK_VIDEO, + input CE_PIXEL, + + input [7:0] VGA_R, + input [7:0] VGA_G, + input [7:0] VGA_B, + input VGA_HS, + input VGA_VS, + input VGA_DE, + + input rotate_ccw, + input no_rotate, + input flip, + output video_rotated, + + output FB_EN, + output [4:0] FB_FORMAT, + output reg [11:0] FB_WIDTH, + output reg [11:0] FB_HEIGHT, + output [31:0] FB_BASE, + output [13:0] FB_STRIDE, + input FB_VBL, + input FB_LL, + + output DDRAM_CLK, + input DDRAM_BUSY, + output [7:0] DDRAM_BURSTCNT, + output [28:0] DDRAM_ADDR, + output [63:0] DDRAM_DIN, + output [7:0] DDRAM_BE, + output DDRAM_WE, + output DDRAM_RD +); + +parameter MEM_BASE = 7'b0010010; // buffer at 0x24000000, 3x8MB + +reg do_flip; + +assign DDRAM_CLK = CLK_VIDEO; +assign DDRAM_BURSTCNT = 1; +assign DDRAM_ADDR = {MEM_BASE, i_fb, ram_addr[22:3]}; +assign DDRAM_BE = ram_addr[2] ? 8'hF0 : 8'h0F; +assign DDRAM_DIN = {ram_data,ram_data}; +assign DDRAM_WE = ram_wr; +assign DDRAM_RD = 0; + +assign FB_EN = fb_en[2]; +assign FB_FORMAT = 5'b00110; +assign FB_BASE = {MEM_BASE,o_fb,23'd0}; +assign FB_STRIDE = stride; + +function [1:0] buf_next; + input [1:0] a,b; + begin + buf_next = 1; + if ((a==0 && b==1) || (a==1 && b==0)) buf_next = 2; + if ((a==1 && b==2) || (a==2 && b==1)) buf_next = 0; + end +endfunction + +assign video_rotated = ~no_rotate; + +always @(posedge CLK_VIDEO) begin + do_flip <= no_rotate && flip; + if( do_flip ) begin + FB_WIDTH <= hsz; + FB_HEIGHT <= vsz; + end else begin + FB_WIDTH <= vsz; + FB_HEIGHT <= hsz; + end +end + +reg [1:0] i_fb,o_fb; +always @(posedge CLK_VIDEO) begin + reg old_vbl,old_vs; + old_vbl <= FB_VBL; + old_vs <= VGA_VS; + + if(FB_LL) begin + if(~old_vbl & FB_VBL) o_fb<={1'b0,~i_fb[0]}; + if(~old_vs & VGA_VS) i_fb<={1'b0,~i_fb[0]}; + end + else begin + if(~old_vbl & FB_VBL) o_fb<=buf_next(o_fb,i_fb); + if(~old_vs & VGA_VS) i_fb<=buf_next(i_fb,o_fb); + end +end + +initial begin + fb_en = 0; +end + +reg [2:0] fb_en = 0; +reg [11:0] hsz = 320, vsz = 240; +reg [11:0] bwidth; +reg [22:0] bufsize; +always @(posedge CLK_VIDEO) begin + reg [11:0] hcnt = 0, vcnt = 0; + reg old_vs, old_de; + + if(CE_PIXEL) begin + old_vs <= VGA_VS; + old_de <= VGA_DE; + + hcnt <= hcnt + 1'd1; + if(~old_de & VGA_DE) begin + hcnt <= 1; + vcnt <= vcnt + 1'd1; + end + if(old_de & ~VGA_DE) begin + hsz <= hcnt; + if( do_flip ) bwidth <= hcnt + 2'd3; + end + if(~old_vs & VGA_VS) begin + vsz <= vcnt; + if( !do_flip ) bwidth <= vcnt + 2'd3; + vcnt <= 0; + fb_en <= {fb_en[1:0], ~no_rotate | flip}; + end + if(old_vs & ~VGA_VS) bufsize <= (do_flip ? vsz : hsz ) * stride; + end +end + +wire [13:0] stride = {bwidth[11:2], 4'd0}; + +reg [22:0] ram_addr, next_addr; +reg [31:0] ram_data; +reg ram_wr; +always @(posedge CLK_VIDEO) begin + reg [13:0] hcnt = 0; + reg old_vs, old_de; + + ram_wr <= 0; + if(CE_PIXEL && FB_EN) begin + old_vs <= VGA_VS; + old_de <= VGA_DE; + + if(~old_vs & VGA_VS) begin + next_addr <= + do_flip ? bufsize-3'd4 : + rotate_ccw ? (bufsize - stride) : {vsz-1'd1, 2'b00}; + hcnt <= rotate_ccw ? 3'd4 : {vsz-2'd2, 2'b00}; + end + if(VGA_DE) begin + ram_wr <= 1; + ram_data <= {8'd0,VGA_B,VGA_G,VGA_R}; + ram_addr <= next_addr; + next_addr <= + do_flip ? next_addr-3'd4 : + rotate_ccw ? (next_addr - stride) : (next_addr + stride); + end + if(old_de & ~VGA_DE & ~do_flip) begin + next_addr <= rotate_ccw ? (bufsize - stride + hcnt) : hcnt; + hcnt <= rotate_ccw ? (hcnt + 3'd4) : (hcnt - 3'd4); + end + end +end + +endmodule diff --git a/sys/ascal.vhd b/sys/ascal.vhd new file mode 100644 index 0000000..aa2af61 --- /dev/null +++ b/sys/ascal.vhd @@ -0,0 +1,2871 @@ +-------------------------------------------------------------------------------- +-- AVALON SCALER +-------------------------------------------------------------------------------- +-- TEMLIB 2018 - 2020 +-------------------------------------------------------------------------------- +-- This code can be freely distributed and used for any purpose, but, if you +-- find any bug, or want to suggest an enhancement, you ought to send a mail +-- to info@temlib.org. +-------------------------------------------------------------------------------- + +-- Features +-- - Arbitrary output video format +-- - Autodetect input image size or fixed window +-- - Progressive and interlaced input +-- - Interpolation +-- Upscaling : Nearest, Bilinear, Sharp Bilinear, Bicubic, Polyphase +-- Downscaling : Nearest, Bilinear +-- - Avalon bus interface with 128 or 64 bits DATA +-- - Optional triple buffering +-- - Support for external low lag syntonization + +-------------------------------------------- +-- Downscaling +-- - Horizontal and vertical up-/down-scaling are independant. +-- - Downscaling, H and/or V, supports only nearest-neighbour and bilinear +-- filtering. +-- - For interlaced video, when the vertical size is lower than a deinterlaced +-- frame size (2x half-frame), the scaler processes only half-frames +-- and upscales (when the output size is between 1x an 2x) or downscales (size +-- below 1x) them. + +-------------------------------------------- +-- 5 clock domains +-- i_xxx : Input video +-- o_xxx : Output video +-- avl_xxx : Avalon memory bus +-- poly_xxx : Polyphase filters memory +-- pal_xxx : Framebuffer mode 8bpp palette. + +-------------------------------------------- +-- O_FB_FORMAT : Framebuffer format +-- [2:0] : 011=8bpp(palette) 100=16bpp 101=24bpp 110=32bpp +-- [3] : 0=16bits 565 1=16bits 1555 +-- [4] : 0=RGB 1=BGR (for 16/24/32 modes) +-- [5] : TBD + +-------------------------------------------- +-- Image header. When HEADER = TRUE +-- Header Address = RAMBASE +-- Image Address = RAMBASE + HEADER_SIZE + +-- Header (Bytes. Big Endian.) +-- 0 : Type = 1 +-- 1 : Pixel format +-- 0 : 16 bits/pixel, RGB : RRRRRGGGGGGBBBBB +-- 1 : 24 bits/pixel, RGB +-- 2 : 32 bits/pixel, RGB0 + +-- 3:2 : Header size : Offset to start of picture (= N_BURST). 12 bits +-- 5:4 : Attributes +-- b0 ; Interlaced +-- b1 : Field number +-- b2 : Horizontal downscaled +-- b3 : Vertical downscaled +-- b4 : Triple buffered +-- b7-5 : Frame counter +-- 7:6 : Image width. Pixels. 12 bits +-- 9:8 : Image height. Pixels. 12 bits +-- 11:10 : Line length. Bytes. +-- 13:12 : Output width. Pixels. 12 bits +-- 15:14 : Output height. Pixels. 12 bits +-------------------------------------------- + +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; +USE ieee.numeric_std.ALL; + +-- MODE[2:0] +-- 000 : Nearest +-- 001 : Bilinear +-- 010 : Sharp Bilinear +-- 011 : Bicubic +-- 100 : Polyphase +-- 101 : TBD +-- 110 : TBD +-- 111 : TBD + +-- MODE[3] +-- 0 : Direct. Single framebuffer. +-- 1 : Triple buffering + +-- MODE[4] : TBD + +-- MASK : Enable / Disable selected interpoler +-- 0:Nearest 1:Bilinear 2:SharpBilinear 3:Bicubic 4:Polyphase +-- RAMBASE : RAM base address for framebuffer +-- RAMSIZE : RAM allocated for one framebuffer (needs x3 if triple-buffering) +-- Must be a power of two +-- INTER : True=Autodetect interlaced video False=Force progressive scan +-- HEADER : True=Add image properties header +-- PALETTE : Enable palette for framebuffer 8bpp mode +-- PALETTE2 : Enable palette for framebuffer 8bpp mode supplied by core +-- DOWNSCALE : True=Support downscaling False=Downscaling disabled +-- BYTESWAP : Little/Big endian byte swap +-- FRAC : Fractional bits, subpixel resolution +-- OHRES : Max. output horizontal resolution. Must be a power of two. +-- (Used for sizing line buffers) +-- IHRES : Max. input horizontal resolution. Must be a power of two. +-- (Used for sizing line buffers) +-- N_DW : Avalon data bus width. 64 or 128 bits +-- N_AW : Avalon address bus width +-- N_BURST : Burst size in bytes. Power of two. + +ENTITY ascal IS + GENERIC ( + MASK : unsigned(7 DOWNTO 0) :=x"FF"; + RAMBASE : unsigned(31 DOWNTO 0); + RAMSIZE : unsigned(31 DOWNTO 0) := x"0080_0000"; -- =8MB + INTER : boolean := true; + HEADER : boolean := true; + DOWNSCALE : boolean := true; + BYTESWAP : boolean := true; + PALETTE : boolean := true; + PALETTE2 : boolean := true; + ADAPTIVE : boolean := true; + DOWNSCALE_NN : boolean := false; + FRAC : natural RANGE 4 TO 8 :=4; + OHRES : natural RANGE 1 TO 4096 :=2048; + IHRES : natural RANGE 1 TO 2048 :=2048; + N_DW : natural RANGE 64 TO 128 := 128; + N_AW : natural RANGE 8 TO 32 := 32; + N_BURST : natural := 256 -- 256 bytes per burst + ); + PORT ( + ------------------------------------ + -- Input video + i_r : IN unsigned(7 DOWNTO 0); + i_g : IN unsigned(7 DOWNTO 0); + i_b : IN unsigned(7 DOWNTO 0); + i_hs : IN std_logic; -- H sync + i_vs : IN std_logic; -- V sync + i_fl : IN std_logic; -- Interlaced field + i_de : IN std_logic; -- Display Enable + i_ce : IN std_logic; -- Clock Enable + i_clk : IN std_logic; -- Input clock + + ------------------------------------ + -- Output video + o_r : OUT unsigned(7 DOWNTO 0); + o_g : OUT unsigned(7 DOWNTO 0); + o_b : OUT unsigned(7 DOWNTO 0); + o_hs : OUT std_logic; -- H sync + o_vs : OUT std_logic; -- V sync + o_de : OUT std_logic; -- Display Enable + o_vbl : OUT std_logic; -- V blank + o_brd : OUT std_logic; -- border enable + o_ce : IN std_logic; -- Clock Enable + o_clk : IN std_logic; -- Output clock + + -- Border colour R G B + o_border : IN unsigned(23 DOWNTO 0) := x"000000"; + + ------------------------------------ + -- Framebuffer mode + o_fb_ena : IN std_logic :='0'; -- Enable Framebuffer Mode + o_fb_hsize : IN natural RANGE 0 TO 4095 :=0; + o_fb_vsize : IN natural RANGE 0 TO 4095 :=0; + o_fb_format : IN unsigned(5 DOWNTO 0) :="000100"; + o_fb_base : IN unsigned(31 DOWNTO 0) :=x"0000_0000"; + o_fb_stride : IN unsigned(13 DOWNTO 0) :=(OTHERS =>'0'); + + -- Framebuffer palette in 8bpp mode + pal1_clk : IN std_logic :='0'; + pal1_dw : IN unsigned(47 DOWNTO 0) :=x"000000000000"; -- R1 G1 B1 R0 G0 B0 + pal1_dr : OUT unsigned(47 DOWNTO 0) :=x"000000000000"; + pal1_a : IN unsigned(6 DOWNTO 0) :="0000000"; -- Colour index/2 + pal1_wr : IN std_logic :='0'; + + pal_n : IN std_logic :='0'; + + pal2_clk : IN std_logic :='0'; + pal2_dw : IN unsigned(23 DOWNTO 0) :=x"000000"; -- R G B + pal2_dr : OUT unsigned(23 DOWNTO 0) :=x"000000"; + pal2_a : IN unsigned(7 DOWNTO 0) :="00000000"; -- Colour index + pal2_wr : IN std_logic :='0'; + + ------------------------------------ + -- Low lag PLL tuning + o_lltune : OUT unsigned(15 DOWNTO 0); + + ------------------------------------ + -- Input video parameters + iauto : IN std_logic :='1'; -- 1=Autodetect image size 0=Choose window + himin : IN natural RANGE 0 TO 4095 :=0; -- MIN < MAX, MIN >=0, MAX < DISP + himax : IN natural RANGE 0 TO 4095 :=0; + vimin : IN natural RANGE 0 TO 4095 :=0; + vimax : IN natural RANGE 0 TO 4095 :=0; + + -- Detected input image size + i_hdmax : OUT natural RANGE 0 TO 4095; + i_vdmax : OUT natural RANGE 0 TO 4095; + + -- Output video parameters + run : IN std_logic :='1'; -- 1=Enable output image. 0=No image + freeze : IN std_logic :='0'; -- 1=Disable framebuffer writes + mode : IN unsigned(4 DOWNTO 0); + -- SYNC |_________________________/"""""""""\_______| + -- DE |""""""""""""""""""\________________________| + -- RGB | <#IMAGE#> ^HDISP | + -- ^HMIN ^HMAX ^HSSTART ^HSEND ^HTOTAL + htotal : IN natural RANGE 0 TO 4095; + hsstart : IN natural RANGE 0 TO 4095; + hsend : IN natural RANGE 0 TO 4095; + hdisp : IN natural RANGE 0 TO 4095; + hmin : IN natural RANGE 0 TO 4095; + hmax : IN natural RANGE 0 TO 4095; -- 0 <= hmin < hmax < hdisp + vtotal : IN natural RANGE 0 TO 4095; + vsstart : IN natural RANGE 0 TO 4095; + vsend : IN natural RANGE 0 TO 4095; + vdisp : IN natural RANGE 0 TO 4095; + vmin : IN natural RANGE 0 TO 4095; + vmax : IN natural RANGE 0 TO 4095; -- 0 <= vmin < vmax < vdisp + + -- Scaler format. 00=16bpp 565, 01=24bpp 10=32bpp + format : IN unsigned(1 DOWNTO 0) :="01"; + + ------------------------------------ + -- Polyphase filter coefficients + -- Order : + -- [Horizontal] [Vertical] [Horizontal2] [Vertical2] + -- [0]...[2**FRAC-1] + -- [-1][0][1][2] + poly_clk : IN std_logic; + poly_dw : IN unsigned(9 DOWNTO 0); + poly_a : IN unsigned(FRAC+3 DOWNTO 0); + poly_wr : IN std_logic; + + ------------------------------------ + -- Avalon + avl_clk : IN std_logic; -- Avalon clock + avl_waitrequest : IN std_logic; + avl_readdata : IN std_logic_vector(N_DW-1 DOWNTO 0); + avl_readdatavalid : IN std_logic; + avl_burstcount : OUT std_logic_vector(7 DOWNTO 0); + avl_writedata : OUT std_logic_vector(N_DW-1 DOWNTO 0); + avl_address : OUT std_logic_vector(N_AW-1 DOWNTO 0); + avl_write : OUT std_logic; + avl_read : OUT std_logic; + avl_byteenable : OUT std_logic_vector(N_DW/8-1 DOWNTO 0); + + ------------------------------------ + reset_na : IN std_logic + ); + +BEGIN + ASSERT N_DW=64 OR N_DW=128 REPORT "DW" SEVERITY failure; + +END ENTITY ascal; + +--############################################################################## + +ARCHITECTURE rtl OF ascal IS + + CONSTANT MASK_NEAREST : natural :=0; + CONSTANT MASK_BILINEAR : natural :=1; + CONSTANT MASK_SHARP_BILINEAR : natural :=2; + CONSTANT MASK_BICUBIC : natural :=3; + CONSTANT MASK_POLY : natural :=4; + + ---------------------------------------------------------- + FUNCTION ilog2 (CONSTANT v : natural) RETURN natural IS + VARIABLE r : natural := 1; + VARIABLE n : natural := 0; + BEGIN + WHILE v>r LOOP + n:=n+1; + r:=r*2; + END LOOP; + RETURN n; + END FUNCTION ilog2; + FUNCTION to_std_logic (a : boolean) RETURN std_logic IS + BEGIN + IF a THEN RETURN '1'; + ELSE RETURN '0'; + END IF; + END FUNCTION to_std_logic; + + ---------------------------------------------------------- + CONSTANT NB_BURST : natural :=ilog2(N_BURST); + CONSTANT NB_LA : natural :=ilog2(N_DW/8); -- Low address bits + CONSTANT BLEN : natural :=N_BURST / N_DW * 8; -- Burst length + + ---------------------------------------------------------- + TYPE arr_dw IS ARRAY (natural RANGE <>) OF unsigned(N_DW-1 DOWNTO 0); + + TYPE type_pix IS RECORD + r,g,b : unsigned(7 DOWNTO 0); -- 0.8 + END RECORD; + TYPE arr_pix IS ARRAY (natural RANGE <>) OF type_pix; + TYPE arr_pixq IS ARRAY(natural RANGE <>) OF arr_pix(0 TO 3); + ATTRIBUTE ramstyle : string; + + SUBTYPE uint12 IS natural RANGE 0 TO 4095; + SUBTYPE uint13 IS natural RANGE 0 TO 8191; + + TYPE arr_uv48 IS ARRAY (natural RANGE <>) OF unsigned(47 DOWNTO 0); + TYPE arr_uv24 IS ARRAY (natural RANGE <>) OF unsigned(23 DOWNTO 0); + TYPE arr_uv40 IS ARRAY (natural RANGE <>) OF unsigned(39 DOWNTO 0); + TYPE arr_int9 IS ARRAY (natural RANGE <>) OF integer RANGE -256 TO 255; + TYPE arr_uint12 IS ARRAY (natural RANGE <>) OF uint12; + TYPE arr_frac IS ARRAY (natural RANGE <>) OF unsigned(11 DOWNTO 0); + TYPE arr_div IS ARRAY (natural RANGE <>) OF unsigned(20 DOWNTO 0); + + ---------------------------------------------------------- + -- Input image + SIGNAL i_pvs,i_pfl,i_pde,i_pce : std_logic; + SIGNAL i_ppix : type_pix; + SIGNAL i_freeze : std_logic; + SIGNAL i_count : unsigned(2 DOWNTO 0); + SIGNAL i_hsize,i_hmin,i_hmax,i_hcpt : uint12; + SIGNAL i_hrsize,i_vrsize : uint12; + SIGNAL i_himax,i_vimax : uint12; + SIGNAL i_vsize,i_vmaxmin,i_vmin,i_vmax,i_vcpt : uint12; + SIGNAL i_iauto : std_logic; + SIGNAL i_mode : unsigned(4 DOWNTO 0); + SIGNAL i_format : unsigned(1 DOWNTO 0); + SIGNAL i_ven,i_sof : std_logic; + SIGNAL i_wr : std_logic; + SIGNAL i_divstart,i_divrun : std_logic; + SIGNAL i_de_pre,i_vs_pre,i_fl_pre : std_logic; + SIGNAL i_de_delay : natural RANGE 0 TO 31; + SIGNAL i_intercnt : natural RANGE 0 TO 3; + SIGNAL i_inter,i_half,i_flm : std_logic; + SIGNAL i_write,i_wreq,i_alt,i_line,i_wline,i_wline_mem : std_logic; + SIGNAL i_walt,i_walt_mem,i_wreq_mem : std_logic; + SIGNAL i_wdelay : natural RANGE 0 TO 7; + SIGNAL i_push,i_pushend,i_pushend2 : std_logic; + SIGNAL i_eol : std_logic; + SIGNAL i_pushhead,i_pushhead2,i_pushhead3 : std_logic; + SIGNAL i_hburst,i_hbcpt : natural RANGE 0 TO 31; + SIGNAL i_shift : unsigned(0 TO 119) := (OTHERS =>'0'); + SIGNAL i_head : unsigned(127 DOWNTO 0); + SIGNAL i_acpt : natural RANGE 0 TO 15; + SIGNAL i_dpram : arr_dw(0 TO BLEN*2-1); + ATTRIBUTE ramstyle OF i_dpram : SIGNAL IS "no_rw_check"; + SIGNAL i_endframe0,i_endframe1,i_vss : std_logic; + SIGNAL i_wad : natural RANGE 0 TO BLEN*2-1; + SIGNAL i_dw : unsigned(N_DW-1 DOWNTO 0); + SIGNAL i_adrs,i_adrsi,i_wadrs,i_wadrs_mem : unsigned(31 DOWNTO 0); + SIGNAL i_reset_na : std_logic; + SIGNAL i_hnp,i_vnp : std_logic; + SIGNAL i_mem : arr_pix(0 TO IHRES-1); -- Downscale line buffer + ATTRIBUTE ramstyle OF i_mem : SIGNAL IS "no_rw_check"; + SIGNAL i_ohsize,i_ovsize : uint12; + SIGNAL i_vdivi : unsigned(12 DOWNTO 0); + SIGNAL i_vdivr : unsigned(24 DOWNTO 0); + SIGNAL i_div : unsigned(16 DOWNTO 0); + SIGNAL i_dir : unsigned(11 DOWNTO 0); + SIGNAL i_h_frac,i_v_frac : unsigned(11 DOWNTO 0); + SIGNAL i_hacc,i_vacc : uint13; + SIGNAL i_hdown,i_vdown : std_logic; + SIGNAL i_divcpt : natural RANGE 0 TO 36; + SIGNAL i_lwad,i_lrad : natural RANGE 0 TO OHRES-1; + SIGNAL i_lwr,i_bil : std_logic; + SIGNAL i_ldw,i_ldrm : type_pix; + SIGNAL i_hpixp,i_hpix0,i_hpix1,i_hpix2,i_hpix3,i_hpix4 : type_pix; + SIGNAL i_hpix,i_pix : type_pix; + SIGNAL i_hnp1,i_hnp2,i_hnp3,i_hnp4 : std_logic; + SIGNAL i_ven1,i_ven2,i_ven3,i_ven4,i_ven5,i_ven6 : std_logic; + + ---------------------------------------------------------- + -- Avalon + TYPE type_avl_state IS (sIDLE,sWRITE,sREAD); + SIGNAL avl_state : type_avl_state; + SIGNAL avl_write_i,avl_write_sync,avl_write_sync2 : std_logic; + SIGNAL avl_read_i,avl_read_sync,avl_read_sync2 : std_logic; + SIGNAL avl_read_pulse,avl_write_pulse : std_logic; + SIGNAL avl_read_sr,avl_write_sr,avl_read_clr,avl_write_clr : std_logic; + SIGNAL avl_rad,avl_rad_c,avl_wad : natural RANGE 0 TO 2*BLEN-1; + SIGNAL avl_walt,avl_wline,avl_rline : std_logic; + SIGNAL avl_dw,avl_dr : unsigned(N_DW-1 DOWNTO 0); + SIGNAL avl_wr : std_logic; + SIGNAL avl_readdataack,avl_readack : std_logic; + SIGNAL avl_radrs,avl_wadrs : unsigned(31 DOWNTO 0); + SIGNAL avl_i_offset0,avl_o_offset0 : unsigned(31 DOWNTO 0); + SIGNAL avl_i_offset1,avl_o_offset1 : unsigned(31 DOWNTO 0); + SIGNAL avl_reset_na : std_logic; + SIGNAL avl_o_vs_sync,avl_o_vs : std_logic; + SIGNAL avl_fb_ena : std_logic; + + FUNCTION buf_next(a,b : natural RANGE 0 TO 2; freeze : std_logic := '0') RETURN natural IS + BEGIN + IF (freeze='1') THEN RETURN a; END IF; + IF (a=0 AND b=1) OR (a=1 AND b=0) THEN RETURN 2; END IF; + IF (a=1 AND b=2) OR (a=2 AND b=1) THEN RETURN 0; END IF; + RETURN 1; + END FUNCTION; + FUNCTION buf_offset(b : natural RANGE 0 TO 2; + base : unsigned(31 DOWNTO 0); + size : unsigned(31 DOWNTO 0)) RETURN unsigned IS + BEGIN + IF b=1 THEN RETURN base+size; END IF; + IF b=2 THEN RETURN base+(size(30 DOWNTO 0) & '0'); END IF; + RETURN base; + END FUNCTION; + + ---------------------------------------------------------- + -- Output + SIGNAL o_run : std_logic; + SIGNAL o_freeze : std_logic; + SIGNAL o_mode,o_hmode,o_vmode : unsigned(4 DOWNTO 0); + SIGNAL o_format : unsigned(5 DOWNTO 0); + SIGNAL o_fb_pal_dr : unsigned(23 DOWNTO 0); + SIGNAL o_fb_pal_dr2 : unsigned(23 DOWNTO 0); + SIGNAL o_fb_pal_dr_x2 : unsigned(47 DOWNTO 0); + SIGNAL pal_idx: unsigned(7 DOWNTO 0); + SIGNAL pal_idx_lsb: std_logic; + SIGNAL pal1_mem : arr_uv48(0 TO 127); + SIGNAL pal2_mem : arr_uv24(0 TO 255); + ATTRIBUTE ramstyle of pal1_mem : signal is "no_rw_check"; + ATTRIBUTE ramstyle of pal2_mem : signal is "no_rw_check"; + SIGNAL o_htotal,o_hsstart,o_hsend : uint12; + SIGNAL o_hmin,o_hmax,o_hdisp,o_v_hmin_adj : uint12; + SIGNAL o_hsize,o_vsize : uint12; + SIGNAL o_vtotal,o_vsstart,o_vsend : uint12; + SIGNAL o_vmin,o_vmax,o_vdisp : uint12; + SIGNAL o_divcpt : natural RANGE 0 TO 36; + SIGNAL o_iendframe0,o_iendframe02,o_iendframe1,o_iendframe12 : std_logic; + SIGNAL o_bufup0,o_bufup1,o_inter : std_logic; + SIGNAL o_ibuf0,o_ibuf1,o_obuf0,o_obuf1 : natural RANGE 0 TO 2; + TYPE enum_o_state IS (sDISP,sHSYNC,sREAD,sWAITREAD); + SIGNAL o_state : enum_o_state; + TYPE enum_o_copy IS (sWAIT,sSHIFT,sCOPY); + SIGNAL o_copy : enum_o_copy; + SIGNAL o_pshift : natural RANGE 0 TO 15; + SIGNAL o_readack,o_readack_sync,o_readack_sync2 : std_logic; + SIGNAL o_readdataack,o_readdataack_sync,o_readdataack_sync2 : std_logic; + SIGNAL o_copyv : unsigned(0 TO 12); + SIGNAL o_adrs : unsigned(31 DOWNTO 0); -- Avalon address + SIGNAL o_adrs_pre : natural RANGE 0 TO 2**24-1; + SIGNAL o_stride : unsigned(13 DOWNTO 0); + SIGNAL o_adrsa,o_adrsb,o_rline : std_logic; + SIGNAL o_ad,o_ad1,o_ad2,o_ad3 : natural RANGE 0 TO 2*BLEN-1; + SIGNAL o_adturn : std_logic; + SIGNAL o_dr : unsigned(N_DW-1 DOWNTO 0); + SIGNAL o_shift : unsigned(0 TO N_DW+15); + SIGNAL o_sh,o_sh1,o_sh2,o_sh3,o_sh4 : std_logic; + SIGNAL o_reset_na : std_logic; + SIGNAL o_dpram : arr_dw(0 TO BLEN*2-1); + ATTRIBUTE ramstyle OF o_dpram : SIGNAL IS "no_rw_check"; + SIGNAL o_line0,o_line1,o_line2,o_line3 : arr_pix(0 TO OHRES-1); + ATTRIBUTE ramstyle OF o_line0 : SIGNAL IS "no_rw_check"; + ATTRIBUTE ramstyle OF o_line1 : SIGNAL IS "no_rw_check"; + ATTRIBUTE ramstyle OF o_line2 : SIGNAL IS "no_rw_check"; + ATTRIBUTE ramstyle OF o_line3 : SIGNAL IS "no_rw_check"; + SIGNAL o_wadl,o_radl0,o_radl1,o_radl2,o_radl3 : natural RANGE 0 TO OHRES-1; + SIGNAL o_ldw,o_ldr0,o_ldr1,o_ldr2,o_ldr3 : type_pix; + SIGNAL o_wr : unsigned(3 DOWNTO 0); + SIGNAL o_hcpt,o_vcpt,o_vcpt_pre,o_vcpt_pre2,o_vcpt_pre3 : uint12; + SIGNAL o_ihsize,o_ihsizem,o_ivsize : uint12; + SIGNAL o_ihsize_temp, o_ihsize_temp2 : natural RANGE 0 TO 32767; + + SIGNAL o_vfrac : unsigned(11 DOWNTO 0); + SIGNAL o_hfrac : arr_frac(0 TO 8); + ATTRIBUTE ramstyle OF o_hfrac : SIGNAL IS "logic"; -- avoid blockram shift register + + SIGNAL o_hacc,o_hacc_ini,o_hacc_next,o_vacc,o_vacc_next,o_vacc_ini : natural RANGE 0 TO 4*OHRES-1; + SIGNAL o_hsv,o_vsv,o_dev,o_pev,o_end : unsigned(0 TO 9); + SIGNAL o_hsp,o_vss : std_logic; + SIGNAL o_vcarrym,o_prim : boolean; + SIGNAL o_read,o_read_pre : std_logic; + SIGNAL o_readlev,o_copylev : natural RANGE 0 TO 2; + SIGNAL o_hburst,o_hbcpt : natural RANGE 0 TO 31; + SIGNAL o_fload : natural RANGE 0 TO 3; + SIGNAL o_acpt,o_acpt1,o_acpt2,o_acpt3,o_acpt4 : natural RANGE 0 TO 15; -- Alternance pixels FIFO + SIGNAL o_dshi : natural RANGE 0 TO 3; + SIGNAL o_first,o_last,o_last1,o_last2 : std_logic; + SIGNAL o_lastt1,o_lastt2,o_lastt3,o_lastt4 : std_logic; + SIGNAL o_alt,o_altx : unsigned(3 DOWNTO 0); + SIGNAL o_hdown,o_vdown : std_logic; + SIGNAL o_primv,o_lastv,o_bibv : unsigned(0 TO 2); + TYPE arr_uint4 IS ARRAY (natural RANGE <>) OF natural RANGE 0 TO 15; + SIGNAL o_off : arr_uint4(0 TO 2); + SIGNAL o_bibu : std_logic :='0'; + SIGNAL o_dcptv : arr_uint12(1 TO 12); + SIGNAL o_dcpt : uint12; + SIGNAL o_hpixs,o_hpix0,o_hpix1,o_hpix2,o_hpix3 : type_pix; + SIGNAL o_hpixq : arr_pixq(2 TO 6); + ATTRIBUTE ramstyle OF o_hpixq : SIGNAL IS "logic"; -- avoid blockram shift register + SIGNAL o_vpixq : arr_pix(0 TO 3); + SIGNAL o_vpix_outer : arr_pix(0 TO 2); + SIGNAL o_vpix_inner : arr_pix(0 TO 5); + + -- ATTRIBUTE ramstyle OF o_hpixq : SIGNAL IS "logic"; + + + SIGNAL o_vpe : std_logic; + SIGNAL o_div : arr_div(0 TO 2); --uint12; + SIGNAL o_dir : arr_frac(0 TO 2); + ATTRIBUTE ramstyle OF o_div, o_dir : SIGNAL IS "logic"; -- avoid blockram shift register + SIGNAL o_vdivi : unsigned(12 DOWNTO 0); + SIGNAL o_vdivr : unsigned(24 DOWNTO 0); + SIGNAL o_divstart : std_logic; + SIGNAL o_divrun : std_logic; + SIGNAL o_hacpt,o_vacpt : unsigned(11 DOWNTO 0); + SIGNAL o_vacptl : unsigned(1 DOWNTO 0); + + ----------------------------------------------------------------------------- + FUNCTION shift_ishift(shift : unsigned(0 TO 119); + pix : type_pix; + format : unsigned(1 DOWNTO 0)) RETURN unsigned IS + BEGIN + CASE format IS + WHEN "01" => -- 24bpp + RETURN shift(24 TO 119) & pix.r & pix.g & pix.b; + WHEN "10" => -- 32bpp + RETURN shift(32 TO 119) & pix.r & pix.g & pix.b & x"00"; + WHEN OTHERS => -- 16bpp 565 + RETURN shift(16 TO 119) & + pix.g(4 DOWNTO 2) & pix.r(7 DOWNTO 3) & + pix.b(7 DOWNTO 3) & pix.g(7 DOWNTO 5); + END CASE; + END FUNCTION; + + FUNCTION shift_ipack(i_dw : unsigned(N_DW-1 DOWNTO 0); + acpt : natural RANGE 0 TO 15; + shift : unsigned(0 TO 119); + pix : type_pix; + format : unsigned(1 DOWNTO 0)) RETURN unsigned IS + VARIABLE dw : unsigned(N_DW-1 DOWNTO 0); + BEGIN + dw:=i_dw; + CASE format IS + WHEN "01" => -- 24bpp + IF N_DW=128 THEN + IF acpt=5 THEN dw:=shift(0 TO 119) & pix.r; + ELSIF acpt=10 THEN dw:=shift(8 TO 119) & pix.r & pix.g; + ELSIF acpt=15 THEN dw:=shift(16 TO 119) & pix.r & pix.g & pix.b; + END IF; + ELSE -- N_DW=64 + IF (acpt MOD 8)=2 THEN dw:=shift(72 TO 119) & pix.r & pix.g; + ELSIF (acpt MOD 8)=5 THEN dw:=shift(64 TO 119) & pix.r; + ELSIF (acpt MOD 8)=7 THEN dw:=shift(80 TO 119) & pix.r & pix.g & pix.b; + END IF; + END IF; + WHEN "10" => -- 32bpp + IF (N_DW=128 AND (acpt MOD 4)=3) OR (N_DW=64 AND (acpt MOD 8)=7) THEN + dw:=shift(128-N_DW+24 TO 119) & pix.r & pix.g & pix.b & x"00"; + END IF; + WHEN OTHERS => -- 16bpp 565 + IF (N_DW=128 AND (acpt MOD 8)=7) OR (N_DW=64 AND (acpt MOD 4)=3) THEN + dw:=shift(128-N_DW+8 TO 119) & pix.g(4 DOWNTO 2) & pix.r(7 DOWNTO 3) & + pix.b(7 DOWNTO 3) & pix.g(7 DOWNTO 5); + END IF; + END CASE; + RETURN dw; + END FUNCTION; + + FUNCTION shift_inext (acpt : natural RANGE 0 TO 15; + format : unsigned(1 DOWNTO 0)) RETURN boolean IS + BEGIN + CASE format IS + WHEN "01" => -- 24bpp + RETURN (N_DW=128 AND (acpt=5 OR acpt=10 OR acpt=15)) OR + (N_DW=64 AND ((acpt MOD 8)=2 OR (acpt MOD 8)=5 OR (acpt MOD 8)=7)); + WHEN "10" => -- 32bpp + RETURN (N_DW=128 AND ((acpt MOD 4)=3)) OR + (N_DW=64 AND ((acpt MOD 2)=1)); + WHEN OTHERS => -- 16bpp + RETURN (N_DW=128 AND ((acpt MOD 8)=7)) OR + (N_DW=64 AND ((acpt MOD 4)=3)); + END CASE; + END FUNCTION; + + FUNCTION shift_opack(acpt : natural RANGE 0 TO 15; + shift : unsigned(0 TO N_DW+15); + dr : unsigned(N_DW-1 DOWNTO 0); + format : unsigned(5 DOWNTO 0)) RETURN unsigned IS + VARIABLE shift_v : unsigned(0 TO N_DW+15); + BEGIN + CASE format(2 DOWNTO 0) IS + WHEN "011" => -- 8bpp + IF (N_DW=128 AND acpt=0) OR (N_DW=64 AND (acpt MOD 8)=0) THEN + shift_v:=dr & dr(15 DOWNTO 0); + ELSE + shift_v:=shift(8 TO N_DW+15) & dr(7 DOWNTO 0); + END IF; + + WHEN "100" => -- 16bpp + IF (N_DW=128 AND (acpt MOD 8)=0) OR (N_DW=64 AND (acpt MOD 4)=0) THEN + shift_v:=dr & dr(15 DOWNTO 0); + ELSE + shift_v:=shift(16 TO N_DW+15) & dr(15 DOWNTO 0); + END IF; + + WHEN "101" => -- 24bpp + IF N_DW=128 THEN + IF acpt=0 THEN + shift_v:=dr & dr(15 DOWNTO 0); + ELSIF acpt=5 THEN + shift_v:=shift(24 TO 31) & dr & dr(7 DOWNTO 0); + ELSIF acpt=10 THEN + shift_v:=shift(24 TO 39) & dr; + ELSE + shift_v:=shift(24 TO N_DW+15) & dr(23 DOWNTO 0); + END IF; + ELSE -- N_DW=64 + IF (acpt MOD 8)=0 THEN + shift_v:=dr & dr(15 DOWNTO 0); + ELSIF (acpt MOD 8)=2 THEN + shift_v:=shift(24 TO 39) & dr; + ELSIF (acpt MOD 8)=5 THEN + shift_v:=shift(24 TO 31) & dr & dr(7 DOWNTO 0); + ELSE + shift_v:=shift(24 TO N_DW+15) & dr(23 DOWNTO 0); + END IF; + END IF; + WHEN OTHERS => -- 32bpp + IF (N_DW=128 AND (acpt MOD 4)=0) OR (N_DW=64 AND (acpt MOD 2)=0) THEN + shift_v:=dr & dr(15 DOWNTO 0); + ELSE + shift_v:=shift(32 TO N_DW+15) & dr(31 DOWNTO 0); + END IF; + END CASE; + RETURN shift_v; + END FUNCTION; + + FUNCTION shift_onext (acpt : natural RANGE 0 TO 15; + format : unsigned(5 DOWNTO 0)) RETURN boolean IS + BEGIN + CASE format(2 DOWNTO 0) IS + WHEN "011" => -- 8bpp + RETURN (N_DW=128 AND acpt=0) OR + (N_DW=64 AND ((acpt MOD 8)=0)); + WHEN "100" => -- 16bpp + RETURN (N_DW=128 AND ((acpt MOD 8)=0)) OR + (N_DW=64 AND ((acpt MOD 4)=0)); + WHEN "101" => -- 24bpp + RETURN (N_DW=128 AND (acpt=0 OR acpt=5 OR acpt=10)) OR + (N_DW=64 AND ((acpt MOD 8)=0 OR (acpt MOD 8)=2 OR (acpt MOD 8)=5)); + WHEN OTHERS => -- 32bpp + RETURN (N_DW=128 AND ((acpt MOD 4)=0)) OR + (N_DW=64 AND ((acpt MOD 2)=0)); + END CASE; + END FUNCTION; + + FUNCTION shift_opix (shift : unsigned(0 TO N_DW+15); + format : unsigned(5 DOWNTO 0)) RETURN type_pix IS + BEGIN + CASE format(3 DOWNTO 0) IS + WHEN "0100" => -- 16bpp 565 + RETURN (b=>shift(8 TO 12) & shift(8 TO 10), + g=>shift(13 TO 15) & shift(0 TO 2) & shift(13 TO 14), + r=>shift(3 TO 7) & shift(3 TO 5)); + WHEN "1100" => -- 16bpp 1555 + RETURN (b=>shift(9 TO 13) & shift(9 TO 11), + g=>shift(14 TO 15) & shift(0 TO 2) & shift(14 TO 15) & shift(0), + r=>shift(3 TO 7) & shift(3 TO 5)); + WHEN "0101" | "0110" => -- 24bpp / 32bpp + RETURN (r=>shift(0 TO 7),g=>shift(8 TO 15),b=>shift(16 TO 23)); + + WHEN OTHERS => + RETURN (r=>shift(0 TO 7),g=>shift(8 TO 15),b=>shift(16 TO 23)); + + END CASE; + END FUNCTION; + + FUNCTION pixoffset(adrs : unsigned(31 DOWNTO 0); + format : unsigned (5 DOWNTO 0)) RETURN natural IS + BEGIN + CASE format(2 DOWNTO 0) IS + WHEN "011" => -- 8bbp + RETURN to_integer(adrs(NB_LA-1 DOWNTO 0)); + WHEN "100" => -- 16bpp 565 + RETURN to_integer(adrs(NB_LA-1 DOWNTO 1)); + WHEN OTHERS => -- 32bpp + RETURN to_integer(adrs(NB_LA-1 DOWNTO 2)); + END CASE; + END FUNCTION; + + FUNCTION swap(d : unsigned(N_DW-1 DOWNTO 0)) RETURN unsigned IS + VARIABLE e : unsigned(N_DW-1 DOWNTO 0); + BEGIN + IF BYTESWAP THEN + FOR i IN 0 TO N_DW/8-1 LOOP + e(i*8+7 DOWNTO i*8):=d(N_DW-i*8-1 DOWNTO N_DW-i*8-8); + END LOOP; + RETURN e; + ELSE + RETURN d; + END IF; + END FUNCTION swap; + + ----------------------------------------------------------------------------- + FUNCTION altx (a : unsigned(1 DOWNTO 0)) RETURN unsigned IS + BEGIN + CASE a IS + WHEN "00" => RETURN "0001"; + WHEN "01" => RETURN "0010"; + WHEN "10" => RETURN "0100"; + WHEN OTHERS => RETURN "1000"; + END CASE; + END FUNCTION; + + ----------------------------------------------------------------------------- + FUNCTION bound(a : unsigned; + s : natural) RETURN unsigned IS + BEGIN + IF a(a'left)='1' THEN + RETURN x"00"; + ELSIF a(a'left DOWNTO s)/=0 THEN + RETURN x"FF"; + ELSE + RETURN a(s-1 DOWNTO s-8); + END IF; + END FUNCTION bound; + + ----------------------------------------------------------------------------- + -- Nearest + FUNCTION near_frac(f : unsigned) RETURN unsigned IS + VARIABLE x : unsigned(FRAC-1 DOWNTO 0); + BEGIN + x:=(OTHERS =>f(f'left)); + RETURN x; + END FUNCTION; + + SIGNAL o_h_near_frac,o_v_near_frac : unsigned(FRAC-1 DOWNTO 0); + SIGNAL o_h_bil_frac,o_v_bil_frac : unsigned(FRAC-1 DOWNTO 0); + SIGNAL o_h_bil_pix,o_v_bil_pix : type_pix; + + ----------------------------------------------------------------------------- + -- Nearest + Bilinear + Sharp Bilinear + FUNCTION bil_frac(f : unsigned) RETURN unsigned IS + BEGIN + RETURN f(f'left DOWNTO f'left+1-FRAC); + END FUNCTION; + + TYPE type_bil_t IS RECORD + r,g,b : unsigned(8+FRAC DOWNTO 0); + END RECORD; + + FUNCTION bil_calc(f : unsigned(FRAC-1 DOWNTO 0); + p : arr_pix(0 TO 3)) RETURN type_bil_t IS + VARIABLE fp,fn : unsigned(FRAC DOWNTO 0); + VARIABLE u : unsigned(8+FRAC DOWNTO 0); + VARIABLE x : type_bil_t; + CONSTANT Z : unsigned(FRAC-1 DOWNTO 0):=(OTHERS =>'0'); + BEGIN + fp:=('0' & f) + (Z & f(FRAC-1)); + fn:=('1' & Z) - fp; + u:=p(2).r * fp + p(1).r * fn; + x.r:=u; + u:=p(2).g * fp + p(1).g * fn; + x.g:=u; + u:=p(2).b * fp + p(1).b * fn; + x.b:=u; + RETURN x; + END FUNCTION; + + FUNCTION near_calc(f : unsigned(FRAC-1 DOWNTO 0); + p : arr_pix(0 TO 3)) RETURN type_bil_t IS + VARIABLE fp,fn : unsigned(FRAC DOWNTO 0); + VARIABLE u : unsigned(8+FRAC DOWNTO 0); + VARIABLE x : type_bil_t; + CONSTANT Z : unsigned(FRAC-1 DOWNTO 0):=(OTHERS =>'0'); + BEGIN + IF f(FRAC-1)='0' THEN + x.r := '0' & p(1).r & Z; + x.g := '0' & p(1).g & Z; + x.b := '0' & p(1).b & Z; + ELSE + x.r := '0' & p(2).r & Z; + x.g := '0' & p(2).g & Z; + x.b := '0' & p(2).b & Z; + END IF; + RETURN x; + END FUNCTION; + + SIGNAL o_h_bil_t,o_v_bil_t : type_bil_t; + SIGNAL o_h_near_t,o_v_near_t : type_bil_t; + SIGNAL i_h_bil_t : type_bil_t; + + ----------------------------------------------------------------------------- + -- Sharp Bilinear + -- <0.5 : x*x*x*4 + -- >0.5 : 1 - (1-x)*(1-x)*(1-x)*4 + + TYPE type_sbil_tt IS RECORD + f : unsigned(FRAC-1 DOWNTO 0); + s : unsigned(FRAC-1 DOWNTO 0); + END RECORD; + + SIGNAL o_h_sbil_t,o_v_sbil_t : type_sbil_tt; + + FUNCTION sbil_frac1(f : unsigned(11 DOWNTO 0)) RETURN type_sbil_tt IS + VARIABLE u : unsigned(FRAC-1 DOWNTO 0); + VARIABLE v : unsigned(2*FRAC-1 DOWNTO 0); + VARIABLE x : type_sbil_tt; + BEGIN + IF f(11)='0' THEN + u:=f(11 DOWNTO 12-FRAC); + ELSE + u:=NOT f(11 DOWNTO 12-FRAC); + END IF; + v:=u*u; + x.f:=u; + x.s:=v(2*FRAC-2 DOWNTO FRAC-1); + RETURN x; + END FUNCTION; + + FUNCTION sbil_frac2(f : unsigned(11 DOWNTO 0); + t : type_sbil_tt) RETURN unsigned IS + VARIABLE v : unsigned(2*FRAC-1 DOWNTO 0); + BEGIN + v:=t.f*t.s; + IF f(11)='0' THEN + RETURN v(2*FRAC-2 DOWNTO FRAC-1); + ELSE + RETURN NOT v(2*FRAC-2 DOWNTO FRAC-1); + END IF; + END FUNCTION; + + ----------------------------------------------------------------------------- + -- Bicubic + TYPE type_bic_abcd IS RECORD + a : unsigned(7 DOWNTO 0); -- 0.8 + b : signed(8 DOWNTO 0); -- 0.9 + c : signed(11 DOWNTO 0); -- 3.9 + d : signed(10 DOWNTO 0); -- 2.9 + xx : signed(8 DOWNTO 0); -- X.X 1.8 + END RECORD; + TYPE type_bic_pix_abcd IS RECORD + r,g,b : type_bic_abcd; + END RECORD; + TYPE type_bic_tt1 IS RECORD -- Intermediate result + r_bx,g_bx,b_bx : signed(8 DOWNTO 0); -- B.X 1.8 + r_cxx,g_cxx,b_cxx : signed(11 DOWNTO 0); -- C.XX 3.9 + r_dxx,g_dxx,b_dxx : signed(10 DOWNTO 0); -- D.XX 2.9 + END RECORD; + TYPE type_bic_tt2 IS RECORD -- Intermediate result + r_abxcxx,g_abxcxx,b_abxcxx : signed(9 DOWNTO 0); -- A + B.X + C.XX 2.8 + r_dxxx,g_dxxx,b_dxxx : signed(9 DOWNTO 0); -- D.X.X.X 2.8 + END RECORD; + + ---------------------------------------------------------- + -- Y = A + B.X + C.X.X + D.X.X.X = A + X.(B + X.(C + X.D)) + -- A = Y(0) 0 .. 1 unsigned + -- B = Y(1)/2 - Y(-1)/2 -1/2 .. +1/2 signed + -- C = Y(-1) - 5*Y(0)/2 + 2*Y(1) - Y(2)/2 -3 .. +3 signed + -- D = -Y(-1)/2 + 3*Y(0)/2 - 3*Y(1)/2 + Y(2)/2 -2 .. +2 signed + + FUNCTION bic_calc0(f : unsigned(11 DOWNTO 0); + pm,p0,p1,p2 : unsigned(7 DOWNTO 0)) RETURN type_bic_abcd IS + VARIABLE xx : signed(2*FRAC+1 DOWNTO 0); -- 2.(2*FRAC) + BEGIN + xx := signed('0' & f(11 DOWNTO 12-FRAC)) * + signed('0' & f(11 DOWNTO 12-FRAC)); -- 2.(2*FRAC) + RETURN type_bic_abcd'( + a=>p0,-- 0.8 + b=>signed(('0' & p1) - ('0' & pm)), -- 0.9 + c=>signed(("000" & pm & '0') - ("00" & p0 & "00") - ("0000" & p0) + + ("00" & p1 & "00") - ("0000" & p2)), -- 3.9 + d=>signed(("00" & p0 & '0') - ("00" & p1 & '0') - ("000" & p1) + + ("000" & p0) + ("000" & p2) - ("000" & pm)), -- 2.9 + xx=>xx(2*FRAC DOWNTO 2*FRAC-8)); -- 1.8 + END FUNCTION; + FUNCTION bic_calc0(f : unsigned(11 DOWNTO 0); + p : arr_pix(0 TO 3)) RETURN type_bic_pix_abcd IS + BEGIN + RETURN type_bic_pix_abcd'(r=>bic_calc0(f,p(0).r,p(1).r,p(2).r,p(3).r), + g=>bic_calc0(f,p(0).g,p(1).g,p(2).g,p(3).g), + b=>bic_calc0(f,p(0).b,p(1).b,p(2).b,p(3).b)); + END FUNCTION; + + ---------------------------------------------------------- + -- Calc : B.X, C.XX, D.XX + FUNCTION bic_calc1(f : unsigned(11 DOWNTO 0); + abcd : type_bic_pix_abcd) RETURN type_bic_tt1 IS + VARIABLE t : type_bic_tt1; + VARIABLE bx : signed(9+FRAC DOWNTO 0); -- 1.(FRAC+9) + VARIABLE cxx : signed(20 DOWNTO 0); -- 4.17 + VARIABLE dxx : signed(19 DOWNTO 0); -- 3.17 + BEGIN + bx := abcd.r.b * signed('0' & f(11 DOWNTO 12-FRAC)); -- 1.(FRAC+9) + t.r_bx:=bx(9+FRAC DOWNTO 9+FRAC-8); -- 1.8 + cxx:= abcd.r.c * abcd.r.xx; -- 3.9 * 1.8 = 4.17 + t.r_cxx:=cxx(19 DOWNTO 8); -- 3.9 + dxx:= abcd.r.d * abcd.r.xx; -- 2.9 * 1.8 = 3.17 + t.r_dxx:=dxx(18 DOWNTO 8); -- 2.9 + bx := abcd.g.b * signed('0' & f(11 DOWNTO 12-FRAC)); -- 1.(FRAC+9) + t.g_bx:=bx(9+FRAC DOWNTO 9+FRAC-8); -- 1.8 + cxx:= abcd.g.c * abcd.g.xx; -- 3.9 * 1.8 = 4.17 + t.g_cxx:=cxx(19 DOWNTO 8); -- 3.9 + dxx:= abcd.g.d * abcd.g.xx; -- 2.9 * 1.8 = 3.17 + t.g_dxx:=dxx(18 DOWNTO 8); -- 2.9 + bx := abcd.b.b * signed('0' & f(11 DOWNTO 12-FRAC)); -- 1.(FRAC+9) + t.b_bx:=bx(9+FRAC DOWNTO 9+FRAC-8); -- 1.8 + cxx:= abcd.b.c * abcd.b.xx; -- 3.9 * 1.8 = 4.17 + t.b_cxx:=cxx(19 DOWNTO 8); -- 3.9 + dxx:= abcd.b.d * abcd.b.xx; -- 2.9 * 1.8 = 3.17 + t.b_dxx:=dxx(18 DOWNTO 8); -- 2.9 + RETURN t; + END FUNCTION; + + ---------------------------------------------------------- + -- Calc A + BX + CXX , X.DXX + FUNCTION bic_calc2(f : unsigned(11 DOWNTO 0); + t : type_bic_tt1; + abcd : type_bic_pix_abcd) RETURN type_bic_tt2 IS + VARIABLE u : type_bic_tt2; + VARIABLE x : signed(11+FRAC DOWNTO 0); -- 3.(9+FRAC) + BEGIN + u.r_abxcxx:=(t.r_bx(8) & t.r_bx) + ("00" & signed(abcd.r.a)) + t.r_cxx(10 DOWNTO 1); -- 2.8 + u.g_abxcxx:=(t.g_bx(8) & t.g_bx) + ("00" & signed(abcd.g.a)) + t.g_cxx(10 DOWNTO 1); -- 2.8 + u.b_abxcxx:=(t.b_bx(8) & t.b_bx) + ("00" & signed(abcd.b.a)) + t.b_cxx(10 DOWNTO 1); -- 2.8 + + x:=t.r_dxx * signed('0' & f(11 DOWNTO 12-FRAC)); --2.9 * 1.FRAC =3.(9+FRAC) + u.r_dxxx:=x(10+FRAC DOWNTO 9+FRAC-8); -- 2.8 + x:=t.g_dxx * signed('0' & f(11 DOWNTO 12-FRAC)); --2.9 * 1.FRAC =3.(9+FRAC) + u.g_dxxx:=x(10+FRAC DOWNTO 9+FRAC-8); -- 2.8 + x:=t.b_dxx * signed('0' & f(11 DOWNTO 12-FRAC)); --2.9 * 1.FRAC =3.(9+FRAC) + u.b_dxxx:=x(10+FRAC DOWNTO 9+FRAC-8); -- 2.8 + RETURN u; + END FUNCTION; + + ---------------------------------------------------------- + -- Calc (A + BX + CXX) + (DXXX) + FUNCTION bic_calc3(f : unsigned(11 DOWNTO 0); + t : type_bic_tt2; + abcd : type_bic_pix_abcd) RETURN type_pix IS + VARIABLE x : type_pix; + VARIABLE v : signed(9 DOWNTO 0); -- 2.8 + BEGIN + v:=t.r_abxcxx + t.r_dxxx; + x.r:=bound(unsigned(v),8); + v:=t.g_abxcxx + t.g_dxxx; + x.g:=bound(unsigned(v),8); + v:=t.b_abxcxx + t.b_dxxx; + x.b:=bound(unsigned(v),8); + RETURN x; + END FUNCTION; + + ----------------------------------------------------------------------------- + SIGNAL o_h_bic_pix,o_v_bic_pix : type_pix; + SIGNAL o_h_bic_abcd1,o_h_bic_abcd2 : type_bic_pix_abcd; + SIGNAL o_v_bic_abcd1,o_v_bic_abcd2 : type_bic_pix_abcd; + SIGNAL o_h_bic_tt1,o_v_bic_tt1 : type_bic_tt1; + SIGNAL o_h_bic_tt2,o_v_bic_tt2 : type_bic_tt2; + + ----------------------------------------------------------------------------- + -- Polyphase + -- 2.7 + TYPE poly_phase_t IS RECORD + t0, t1, t2, t3 : signed(9 DOWNTO 0); + END RECORD; + + -- 4.14 + TYPE poly_phase_interp_t IS RECORD + t0, t1, t2, t3 : signed(17 DOWNTO 0); + END RECORD; + + -- 5.22 + TYPE type_poly_t IS RECORD + r0,r1,b0,b1,g0,g1 : signed(26 DOWNTO 0); + END RECORD; + + + SIGNAL o_h_poly_mem : arr_uv40(0 TO 2**FRAC-1); + SIGNAL o_v_poly_mem : arr_uv40(0 TO 2**FRAC-1); + SIGNAL o_a_poly_mem : arr_uv40(0 TO 2**FRAC-1); + ATTRIBUTE ramstyle OF o_h_poly_mem : SIGNAL IS "no_rw_check"; + ATTRIBUTE ramstyle OF o_v_poly_mem : SIGNAL IS "no_rw_check"; + ATTRIBUTE ramstyle OF o_a_poly_mem : SIGNAL IS "no_rw_check"; + SIGNAL o_a_poly_addr, o_v_poly_addr, o_h_poly_addr : integer RANGE 0 TO 2**FRAC-1; + SIGNAL o_h_poly_phase_a,o_h_poly_phase_a2,o_h_poly_phase_a3 : poly_phase_t; + SIGNAL o_v_poly_phase_a,o_v_poly_phase_a2,o_v_poly_phase_a3 : poly_phase_t; + SIGNAL o_poly_phase_a, o_poly_phase_a2, o_poly_phase_a3 : poly_phase_t; + SIGNAL o_poly_phase_b,o_poly_phase_b2,o_poly_phase_b3 : poly_phase_t; + SIGNAL o_v_poly_phase, o_v_poly_phase2, o_h_poly_phase, o_poly_phase : poly_phase_interp_t; + SIGNAL o_v_poly_pix, o_h_poly_pix : type_pix; + SIGNAL o_v_poly_lum, o_h_poly_lum, o_poly_lum : unsigned(7 DOWNTO 0); + SIGNAL o_poly_lerp_ta, o_poly_lerp_tb, o_poly_lerp_tb3 : signed(9 DOWNTO 0); + SIGNAL o_h_poly_t,o_h_poly_t2,o_v_poly_t : type_poly_t; + + SIGNAL o_v_poly_adaptive, o_h_poly_adaptive, o_v_poly_use_adaptive, o_h_poly_use_adaptive : std_logic; + SIGNAL poly_wr_mode : std_logic_vector(2 DOWNTO 0); + SIGNAL poly_tdw : unsigned(39 DOWNTO 0); + SIGNAL poly_a2 : unsigned(FRAC-1 DOWNTO 0); + + + FUNCTION poly_unpack(a : unsigned(39 DOWNTO 0)) RETURN poly_phase_t IS + VARIABLE v : poly_phase_t; + BEGIN + v.t0 := signed(a(39 DOWNTO 30)); + v.t1 := signed(a(29 DOWNTO 20)); + v.t2 := signed(a(19 DOWNTO 10)); + v.t3 := signed(a( 9 DOWNTO 0)); + + RETURN v; + END FUNCTION; + + -- 6 DSP 18*18 + 18*18 + FUNCTION poly_calc(fi : poly_phase_interp_t; + p : arr_pix(0 TO 3)) RETURN type_poly_t IS + VARIABLE t : type_poly_t; + BEGIN + -- 3.15 * 1.8 = 4.23 + t.r0:=(fi.t0 * signed('0' & p(0).r) + + fi.t1 * signed('0' & p(1).r)); + t.r1:=(fi.t2 * signed('0' & p(2).r) + + fi.t3 * signed('0' & p(3).r)); + t.g0:=(fi.t0 * signed('0' & p(0).g) + + fi.t1 * signed('0' & p(1).g)); + t.g1:=(fi.t2 * signed('0' & p(2).g) + + fi.t3 * signed('0' & p(3).g)); + t.b0:=(fi.t0 * signed('0' & p(0).b) + + fi.t1 * signed('0' & p(1).b)); + t.b1:=(fi.t2 * signed('0' & p(2).b) + + fi.t3 * signed('0' & p(3).b)); + RETURN t; + END FUNCTION; + + FUNCTION poly_final(t : type_poly_t) RETURN type_pix IS + VARIABLE p : type_pix; + BEGIN + p.r:=bound(unsigned(t.r0(26 DOWNTO 8)+t.r1(26 DOWNTO 8)),15); + p.g:=bound(unsigned(t.g0(26 DOWNTO 8)+t.g1(26 DOWNTO 8)),15); + p.b:=bound(unsigned(t.b0(26 DOWNTO 8)+t.b1(26 DOWNTO 8)),15); + RETURN p; + END FUNCTION; + + -- 4 DSP 18*18 + 18*18 + FUNCTION poly_lerp(a : poly_phase_t; + b : poly_phase_t; + ta : SIGNED(9 DOWNTO 0); + tb : SIGNED(9 DOWNTO 0)) RETURN poly_phase_interp_t IS + VARIABLE v : poly_phase_interp_t; + VARIABLE t0,t1,t2,t3 : signed(19 DOWNTO 0); + BEGIN + -- 2.8 * 2.8 = 4.16 + t0 := (a.t0 * ta) + (b.t0 * tb); + t1 := (a.t1 * ta) + (b.t1 * tb); + t2 := (a.t2 * ta) + (b.t2 * tb); + t3 := (a.t3 * ta) + (b.t3 * tb); + + -- 4.16 -> 3.15 + v.t0 := t0(18 DOWNTO 1); + v.t1 := t1(18 DOWNTO 1); + v.t2 := t2(18 DOWNTO 1); + v.t3 := t3(18 DOWNTO 1); + + RETURN v; + END FUNCTION; + + FUNCTION poly_cvt(a : poly_phase_t) RETURN poly_phase_interp_t IS + VARIABLE v : poly_phase_interp_t; + BEGIN + v.t0 := resize(signed( a.t0 & "0000000" ), v.t0'length); + v.t1 := resize(signed( a.t1 & "0000000" ), v.t1'length); + v.t2 := resize(signed( a.t2 & "0000000" ), v.t2'length); + v.t3 := resize(signed( a.t3 & "0000000" ), v.t3'length); + RETURN v; + END FUNCTION; + + -- Nearest neighbor polyphase ceoffs + FUNCTION poly_nn(frac : unsigned(FRAC-1 DOWNTO 0)) RETURN poly_phase_t IS + VARIABLE v : poly_phase_t; + BEGIN + IF frac(frac'left)='0' THEN + v := (t1=>to_signed(256, 10), OTHERS=>to_signed(0, 10)); + ELSE + v := (t2=>to_signed(256, 10), OTHERS=>to_signed(0, 10)); + END IF; + RETURN v; + END FUNCTION; + + + FUNCTION poly_lum(p : type_pix) RETURN unsigned IS + VARIABLE v : UNSIGNED(7 DOWNTO 0); + BEGIN + -- 0.375 R + 0.5 G + 0.125 B + --v := ("00" & p.r(7 DOWNTO 2)) + ("000" & p.r(7 DOWNTO 3)) + ("0" & p.g(7 DOWNTO 1)) + ("000" & p.b(7 DOWNTO 3)); + + -- 0.25 R + 0.5 G + 0.25 B + -- v := ( ("00" & p.r(7 DOWNTO 2)) + ("0" & p.g(7 DOWNTO 1)) + ("00" & p.b(7 DOWNTO 2)) ); + + -- Just OR them all together + --v := (p.r OR p.g OR p.b); + + -- Maximum + IF p.r > p.g THEN + v := p.r; + ELSE + v := p.g; + END IF; + + IF p.b > v THEN + v := p.b; + END IF; + + -- 100% + -- v := "1111111"; + + RETURN v; + END FUNCTION; +BEGIN + + ----------------------------------------------------------------------------- + i_reset_na<='0' WHEN reset_na='0' ELSE '1' WHEN rising_edge(i_clk); + o_reset_na<='0' WHEN reset_na='0' ELSE '1' WHEN rising_edge(o_clk); + avl_reset_na<='0' WHEN reset_na='0' ELSE '1' WHEN rising_edge(avl_clk); + + ----------------------------------------------------------------------------- + -- Input pixels FIFO and shreg + InAT:PROCESS(i_clk,i_reset_na) IS + CONSTANT Z : unsigned(FRAC-1 DOWNTO 0):=(OTHERS =>'0'); + VARIABLE frac_v : unsigned(FRAC-1 DOWNTO 0); + VARIABLE div_v : unsigned(16 DOWNTO 0); + VARIABLE dir_v : unsigned(11 DOWNTO 0); + VARIABLE bil_t_v : type_bil_t; + BEGIN + IF i_reset_na='0' THEN + i_write<='0'; + + ELSIF rising_edge(i_clk) THEN + i_push<='0'; + i_pushhead<='0'; + i_eol<='0'; -- End Of Line + i_freeze <=freeze; -- + i_iauto<=iauto; -- + i_wreq<='0'; + i_wr<='0'; + + ------------------------------------------------------ + i_head(127 DOWNTO 120)<=x"01"; -- Header type + i_head(119 DOWNTO 112)<="000000" & i_format; -- Header format + i_head(111 DOWNTO 96)<="0000" & to_unsigned(N_BURST,12); -- Header size + i_head(95 DOWNTO 80)<=x"0000"; -- Attributes. TBD + i_head(80)<=i_inter; + i_head(81)<=i_flm; + i_head(82)<=i_hdown; + i_head(83)<=i_vdown; + i_head(84)<=i_mode(3); + i_head(87 DOWNTO 85)<=i_count; + i_head(79 DOWNTO 64)<="0000" & to_unsigned(i_hrsize,12); -- Image width + i_head(63 DOWNTO 48)<="0000" & to_unsigned(i_vrsize,12); -- Image height + i_head(47 DOWNTO 32)<= + to_unsigned(N_BURST * i_hburst,16); -- Line Length. Bytes + i_head(31 DOWNTO 16)<="0000" & to_unsigned(i_ohsize,12); + i_head(15 DOWNTO 0) <="0000" & to_unsigned(i_ovsize,12); + + ------------------------------------------------------ + i_ppix<=(i_r,i_g,i_b); + i_pvs<=i_vs; + i_pfl<=i_fl; + i_pde<=i_de; + i_pce<=i_ce; + + ------------------------------------------------------ + IF i_pce='1' THEN + ---------------------------------------------------- + i_vs_pre<=i_pvs; + i_de_pre<=i_pde; + i_fl_pre<=i_pfl; + + ---------------------------------------------------- + -- Detect interlaced video + IF NOT INTER THEN + i_intercnt<=0; + ELSIF i_pfl/=i_fl_pre THEN + i_intercnt<=3; + ELSIF i_pvs='1' AND i_vs_pre='0' AND i_intercnt>0 THEN + i_intercnt<=i_intercnt-1; + END IF; + i_inter<=to_std_logic(i_intercnt>0); + + ---------------------------------------------------- + IF i_pvs='1' AND i_vs_pre='0' THEN + i_sof<='1'; + END IF; + + IF i_pde='1' AND i_de_pre='0' THEN + i_flm<=i_pfl; + END IF; + + IF i_pde='1' AND i_sof='1' THEN + i_sof<='0'; + i_vcpt<=0; + IF i_inter='1' AND i_flm='0' AND i_half='0' AND INTER THEN + i_line<='1'; + i_adrsi<=to_unsigned(N_BURST * i_hburst,32) + + to_unsigned(N_BURST * to_integer( + unsigned'("00") & to_std_logic(HEADER)),32); + ELSE + i_line<='0'; + i_adrsi<=to_unsigned(N_BURST * to_integer( + unsigned'("00") & to_std_logic(HEADER)),32); + END IF; + END IF; + + i_ven<=to_std_logic(i_hcpt>=i_hmin AND i_hcpt<=i_hmax AND + i_vcpt>=i_vmin AND i_vcpt<=i_vmax); + + -- Detects end of frame for triple buffering. + i_endframe0<=i_vs AND (NOT i_inter OR i_flm); + i_endframe1<=i_vs AND (NOT i_inter OR NOT i_flm); + + i_vss<=to_std_logic(i_vcpt>=i_vmin AND i_vcpt<=i_vmax); + + ---------------------------------------------------- + IF i_pde='1' AND i_de_pre='0' THEN + i_vimax<=i_vcpt; + i_hcpt<=0; + ELSE + i_hcpt<=(i_hcpt+1) MOD 4096; + END IF; + + IF i_pde='0' AND i_de_pre='1' THEN + i_himax<=i_hcpt; + END IF; + + IF i_iauto='1' THEN + -- Auto-size + i_hmin<=0; + i_hmax<=i_himax; + i_vmin<=0; + IF i_pvs='1' AND i_vs_pre='0' AND (i_inter='0' OR i_pfl='0') THEN + i_vmax<=i_vimax; + END IF; + ELSE + -- Forced image + i_hmin<=himin; -- + i_hmax<=himax; -- + i_vmin<=vimin; -- + IF i_pvs='1' AND i_vs_pre='0' AND (i_inter='0' OR i_pfl='0') THEN + i_vmax<=vimax; -- + END IF; + END IF; + + IF i_pvs='1' AND i_vs_pre='0' AND (i_inter='0' OR i_pfl='0') THEN + i_vdmax<=i_vimax; + END IF; + i_hdmax<=i_himax; + + IF i_format="00" OR i_format="11" THEN -- 16bpp + i_hburst<=(i_hrsize*2 + N_BURST - 1) / N_BURST; + ELSIF i_format="01" THEN -- 24bpp + i_hburst<=(i_hrsize*3 + N_BURST - 1) / N_BURST; + ELSE -- 32bpp + i_hburst<=(i_hrsize*4 + N_BURST - 1) / N_BURST; + END IF; + ---------------------------------------------------- + i_mode<=mode; -- + i_format<=format; -- + + -- Downscaling : Nearest or bilinear + i_bil<=to_std_logic(i_mode(2 DOWNTO 0)/="000" AND NOT DOWNSCALE_NN); + + i_hdown<=to_std_logic(i_hsize>i_ohsize AND DOWNSCALE); --H downscale + i_vdown<=to_std_logic(i_vsize>i_ovsize AND DOWNSCALE); --V downscale + + ---------------------------------------------------- + i_hsize <=(4096+i_hmax-i_hmin+1) MOD 4096; + i_vmaxmin<=(4096+i_vmax-i_vmin+1) MOD 4096; + + IF i_inter='0' THEN + -- Non interlaced + i_vsize<=i_vmaxmin; + i_half <='0'; + ELSIF i_ovsize<2*i_vmaxmin THEN + -- Interlaced, but downscaling, use only half frames + i_vsize<=i_vmaxmin; + i_half <='1'; + ELSE + -- Interlaced : Double image height + i_vsize<=2*i_vmaxmin; + i_half <='0'; + END IF; + + i_ohsize<=o_hsize; -- + i_ovsize<=o_vsize; -- + + ---------------------------------------------------- + -- Downscaling vertical + i_divstart<='0'; + IF i_de_delay=16 THEN + IF (i_vacc + 2*i_ovsize) < 2*i_vsize THEN + i_vacc<=(i_vacc + 2*i_ovsize) MOD 8192; + i_vnp<='0'; + ELSE + i_vacc<=(i_vacc + 2*i_ovsize - 2*i_vsize + 8192) MOD 8192; + i_vnp<='1'; + END IF; + i_divstart<='1'; + + IF i_vcpt=i_vmin THEN + i_vacc<=(i_vsize - i_ovsize + 8192) MOD 8192; + i_vnp<='1'; -- + END IF; + END IF; + + IF i_vdown='0' THEN + i_vnp<='1'; + END IF; + + -- Downscaling horizontal + IF i_ven='1' THEN + IF i_hacc + 2*i_ohsize < 2*i_hsize THEN + i_hacc<=(i_hacc + 2*i_ohsize) MOD 8192; + i_hnp<='0'; -- Skip. pix. + ELSE + i_hacc<=(i_hacc + 2*i_ohsize - 2*i_hsize + 8192) MOD 8192; + i_hnp<='1'; + END IF; + END IF; + IF i_hdown='0' THEN + i_hnp<='1'; + END IF; + + ---------------------------------------------------- + -- Downscaling interpolation + i_hpixp<=i_ppix; + i_hpix0<=i_hpixp; + i_hpix1<=i_hpix0; + i_hpix2<=i_hpix1; + i_hpix3<=i_hpix2; + i_hpix4<=i_hpix3; + + i_hnp1<=i_hnp; i_hnp2<=i_hnp1; i_hnp3<=i_hnp2; i_hnp4<=i_hnp3; + i_ven1<=i_ven; i_ven2<=i_ven1; i_ven3<=i_ven2; i_ven4<=i_ven3; + i_ven5<=i_ven4; i_ven6<=i_ven5; + + -- C1 : DIV 1. Pipelined 4 bits non-restoring divider + dir_v:=x"000"; + div_v:=to_unsigned(i_hacc * 16,17); + + div_v:=div_v-to_unsigned(i_hsize*16,17); + dir_v(11):=NOT div_v(16); + IF div_v(16)='0' THEN + div_v:=div_v-to_unsigned(i_hsize*8,17); + ELSE + div_v:=div_v+to_unsigned(i_hsize*8,17); + END IF; + dir_v(10):=NOT div_v(16); + i_div<=div_v; + i_dir<=dir_v; + + -- C2 : DIV 2. + div_v:=i_div; + dir_v:=i_dir; + IF div_v(16)='0' THEN + div_v:=div_v-to_unsigned(i_hsize*4,17); + ELSE + div_v:=div_v+to_unsigned(i_hsize*4,17); + END IF; + dir_v(9):=NOT div_v(16); + + IF div_v(16)='0' THEN + div_v:=div_v-to_unsigned(i_hsize*2,17); + ELSE + div_v:=div_v+to_unsigned(i_hsize*2,17); + END IF; + dir_v(8):=NOT div_v(16); + i_h_frac<=dir_v; + + -- C4 : Horizontal Bilinear + IF i_bil='0' THEN + frac_v:=near_frac(i_h_frac); + i_h_bil_t<=near_calc(frac_v,(i_hpix2,i_hpix2,i_hpix3,i_hpix3)); + ELSE + frac_v:=bil_frac(i_h_frac); + i_h_bil_t<=bil_calc(frac_v,(i_hpix2,i_hpix2,i_hpix3,i_hpix3)); + END IF; + + i_hpix.r<=bound(i_h_bil_t.r,8+FRAC); + i_hpix.g<=bound(i_h_bil_t.g,8+FRAC); + i_hpix.b<=bound(i_h_bil_t.b,8+FRAC); + + IF i_hdown='0' THEN + i_hpix<=i_hpix4; + END IF; + + -- C5 : Vertical Bilinear + IF i_bil='0' THEN + frac_v:=near_frac(i_v_frac(11 DOWNTO 0)); + bil_t_v:=near_calc(frac_v,(i_hpix,i_hpix,i_ldrm,i_ldrm)); + ELSE + frac_v:=bil_frac(i_v_frac(11 DOWNTO 0)); + bil_t_v:=bil_calc(frac_v,(i_hpix,i_hpix,i_ldrm,i_ldrm)); + END IF; + + i_pix.r<=bound(bil_t_v.r,8+FRAC); + i_pix.g<=bound(bil_t_v.g,8+FRAC); + i_pix.b<=bound(bil_t_v.b,8+FRAC); + + IF i_vdown='0' THEN + i_pix<=i_hpix; + END IF; + + ---------------------------------------------------- + -- VNP : Vert. downscaling line enable + -- HNP : Horiz. downscaling pix. enable + -- VEN : Enable pixel within displayed window + + IF (i_hnp4='1' AND i_ven6='1') OR i_pushend='1' THEN + i_shift<=shift_ishift(i_shift,i_pix,i_format); + i_dw<=shift_ipack(i_dw,i_acpt,i_shift,i_pix,i_format); + + IF shift_inext(i_acpt,i_format) AND i_vnp='1' THEN + i_push<='1'; + i_pushend<='0'; + END IF; + i_acpt<=(i_acpt+1) MOD 16; + END IF; + + IF i_ven6='1' AND i_ven5='0' AND i_vnp='1' THEN + i_pushend<='1'; + END IF; + i_pushend2<=i_pushend; + + IF i_pushend2='1' AND i_pushend='0' THEN + i_eol<='1'; + END IF; + + IF i_pde='0' AND i_de_pre='1' THEN + i_de_delay<=0; + ELSIF i_de_delay<18 THEN + i_de_delay<=i_de_delay+1; + END IF; + + IF i_de_delay=16 THEN + i_lwad<=0; + i_lrad<=0; + i_vcpt<=i_vcpt+1; + i_hacc<=(i_hsize - i_ohsize + 8192) MOD 8192; + i_hbcpt<=0; + END IF; + IF i_de_delay=17 THEN + i_acpt<=0; + i_wad<=2*BLEN-1; + END IF; + + IF i_pvs='0' AND i_vs_pre='1' THEN + -- Push header + i_pushhead<=to_std_logic(HEADER); + END IF; + + END IF; -- IF i_pce='1' + + ------------------------------------------------------ + -- Push pixels to downscaling line buffer + i_lwr<=i_hnp4 AND i_ven5 AND i_pce; + IF i_lwr='1' THEN + i_lwad<=(i_lwad+1) MOD OHRES; + END IF; + i_ldw<=i_hpix; + + IF i_hnp3='1' AND i_ven4='1' AND i_pce='1' THEN + i_lrad<=(i_lrad+1) MOD OHRES; + END IF; + + ------------------------------------------------------ + -- Write image properties header + i_pushhead2<=i_pushhead; i_pushhead3<=i_pushhead2; + + IF i_pushhead='1' AND i_freeze='0' THEN + i_dw<=i_head(127 DOWNTO 128-N_DW); + i_count<=i_count+1; + i_wr<='1'; + i_wad<=0; + IF N_DW=128 THEN + i_alt<='0'; + i_wreq<=NOT i_freeze; + i_adrs<=(OTHERS =>'0'); + END IF; + END IF; + + IF i_pushhead2='1' AND i_freeze='0' AND N_DW=64 THEN + i_dw<=i_head(N_DW-1 DOWNTO 0); + i_wr<='1'; + i_wad<=1; + i_wreq<=NOT i_freeze; + i_alt<='0'; + i_adrs<=(OTHERS =>'0'); + END IF; + IF i_pushhead3='1' THEN + i_wad<=BLEN-1; + END IF; + + ------------------------------------------------------ + -- Push pixels to DPRAM + IF i_push='1' AND i_freeze='0' THEN + i_wr<='1'; + i_wad<=(i_wad+1) MOD (BLEN*2); + IF (i_wad+1) MOD BLEN=BLEN-1 AND i_hbcpt 12 + IDividers:PROCESS (i_clk,i_reset_na) IS + BEGIN + IF i_reset_na='0' THEN +--pragma synthesis_off + i_v_frac<=x"000"; +--pragma synthesis_on + NULL; + ELSIF rising_edge(i_clk) THEN + i_vdivi<=to_unsigned(2*i_vsize,13); + i_vdivr<=to_unsigned(i_vacc*4096,25); + + ------------------------------------------------------ + IF i_divstart='1' THEN + i_divcpt<=0; + i_divrun<='1'; + + ELSIF i_divrun='1' THEN + ---------------------------------------------------- + IF i_divcpt=6 THEN + i_divrun<='0'; + i_v_frac<=i_vdivr(4 DOWNTO 0) & NOT i_vdivr(24) & "000000"; + ELSE + i_divcpt<=i_divcpt+1; + END IF; + + IF i_vdivr(24)='0' THEN + i_vdivr(24 DOWNTO 12)<=i_vdivr(23 DOWNTO 11) - i_vdivi; + ELSE + i_vdivr(24 DOWNTO 12)<=i_vdivr(23 DOWNTO 11) + i_vdivi; + END IF; + i_vdivr(11 DOWNTO 0)<=i_vdivr(10 DOWNTO 0) & NOT i_vdivr(24); + + ---------------------------------------------------- + END IF; + END IF; + END PROCESS IDividers; + + ----------------------------------------------------------------------------- + -- DPRAM Input. Double buffer for RAM bursts. + PROCESS (i_clk) IS + BEGIN + IF rising_edge(i_clk) THEN + IF i_wr='1' THEN + i_dpram(i_wad)<=i_dw; + END IF; + END IF; + END PROCESS; + + avl_dr<=i_dpram(avl_rad_c) WHEN rising_edge(avl_clk); + + -- Line buffer for downscaling with interpolation + DownLine:IF DOWNSCALE GENERATE + ILBUF:PROCESS(i_clk) IS + BEGIN + IF rising_edge(i_clk) THEN + IF i_lwr='1' THEN + i_mem(i_lwad MOD IHRES)<=i_ldw; + END IF; + IF i_pce='1' THEN + i_ldrm<=i_mem(i_lrad MOD IHRES); + END IF; + END IF; + END PROCESS ILBUF; + END GENERATE DownLine; + + ----------------------------------------------------------------------------- + -- AVALON interface + Avaloir:PROCESS(avl_clk,avl_reset_na) IS + VARIABLE adr_v : unsigned(31 DOWNTO 0); + BEGIN + IF avl_reset_na='0' THEN + avl_state<=sIDLE; + avl_write_sr<='0'; + avl_read_sr<='0'; + avl_readdataack<='0'; + avl_readack<='0'; + + ELSIF rising_edge(avl_clk) THEN + ---------------------------------- + avl_write_sync<=i_write; -- + avl_write_sync2<=avl_write_sync; + avl_write_pulse<=avl_write_sync XOR avl_write_sync2; + IF avl_write_pulse='1' THEN + avl_wadrs <=i_wadrs AND (RAMSIZE - 1); -- + avl_wline <=i_wline; -- + avl_walt <=i_walt; -- + END IF; + + ---------------------------------- + avl_read_sync<=o_read; -- + avl_read_sync2<=avl_read_sync; + avl_read_pulse<=avl_read_sync XOR avl_read_sync2; + avl_radrs <=o_adrs; -- + avl_rline <=o_rline; -- + + -------------------------------------------- + avl_o_vs_sync<=o_vsv(0); -- + avl_o_vs<=avl_o_vs_sync; + + avl_fb_ena<=o_fb_ena; -- + IF avl_fb_ena='0' THEN + IF HEADER THEN + avl_o_offset0<=buf_offset(o_obuf0,RAMBASE,RAMSIZE) + N_BURST; -- + avl_o_offset1<=buf_offset(o_obuf1,RAMBASE,RAMSIZE) + N_BURST; -- + ELSE + avl_o_offset0<=buf_offset(o_obuf0,RAMBASE,RAMSIZE); -- + avl_o_offset1<=buf_offset(o_obuf1,RAMBASE,RAMSIZE); -- + END IF; + ELSIF avl_o_vs_sync='0' AND avl_o_vs='1' THEN + -- Copy framebuffer base address at VS falling edge + avl_o_offset0<=o_fb_base; -- + avl_o_offset1<=o_fb_base; -- + END IF; + + avl_i_offset0<=buf_offset(o_ibuf0,RAMBASE,RAMSIZE); -- + avl_i_offset1<=buf_offset(o_ibuf1,RAMBASE,RAMSIZE); -- + + -------------------------------------------- + avl_dw<=swap(unsigned(avl_readdata)); + avl_read_i<='0'; + avl_write_i<='0'; + + avl_write_sr<=(avl_write_sr OR avl_write_pulse) AND NOT avl_write_clr; + avl_read_sr <=(avl_read_sr OR avl_read_pulse) AND NOT avl_read_clr; + avl_write_clr<='0'; + avl_read_clr <='0'; + + avl_rad<=avl_rad_c; + + -------------------------------------------- + CASE avl_state IS + WHEN sIDLE => + IF avl_write_sr='1' THEN + avl_state<=sWRITE; + avl_write_clr<='1'; + IF avl_walt='0' THEN + avl_rad<=0; + ELSE + avl_rad<=BLEN; + END IF; + IF avl_wline='0' THEN + avl_address<=std_logic_vector( + avl_wadrs(N_AW+NB_LA-1 DOWNTO NB_LA) + + avl_i_offset0(N_AW+NB_LA-1 DOWNTO NB_LA)); + ELSE + avl_address<=std_logic_vector( + avl_wadrs(N_AW+NB_LA-1 DOWNTO NB_LA) + + avl_i_offset1(N_AW+NB_LA-1 DOWNTO NB_LA)); + END IF; + ELSIF avl_read_sr='1' THEN + avl_state<=sREAD; + avl_read_clr<='1'; + END IF; + + WHEN sWRITE => + avl_write_i<='1'; + IF avl_write_i='1' AND avl_waitrequest='0' THEN + IF (avl_rad MOD BLEN)=BLEN-1 THEN + avl_write_i<='0'; + avl_state<=sIDLE; + END IF; + END IF; + + WHEN sREAD => + IF avl_rline='0' THEN + adr_v:=avl_radrs + avl_o_offset0; + ELSE + adr_v:=avl_radrs + avl_o_offset1; + END IF; + avl_address<=std_logic_vector(adr_v(N_AW+NB_LA-1 DOWNTO NB_LA)); + + avl_read_i<='1'; + IF avl_read_i='1' AND avl_waitrequest='0' THEN + avl_state<=sIDLE; + avl_read_i<='0'; + avl_readack<=NOT avl_readack; + END IF; + END CASE; + + -------------------------------------------- + -- Pipelined data read + avl_wr<='0'; + IF avl_readdatavalid='1' THEN + avl_wr<='1'; + avl_wad<=(avl_wad+1) MOD (2*BLEN); + IF (avl_wad MOD BLEN)=BLEN-2 THEN + avl_readdataack<=NOT avl_readdataack; + END IF; + END IF; + + IF avl_o_vs_sync='0' AND avl_o_vs='1' THEN + avl_wad<=2*BLEN-1; + END IF; + + -------------------------------------------- + END IF; + END PROCESS Avaloir; + + avl_read<=avl_read_i; + avl_write<=avl_write_i; + avl_writedata<=std_logic_vector(swap(avl_dr)); + avl_burstcount<=std_logic_vector(to_unsigned(BLEN,8)); + avl_byteenable<=(OTHERS =>'1'); + + avl_rad_c<=(avl_rad+1) MOD (2*BLEN) + WHEN avl_write_i='1' AND avl_waitrequest='0' ELSE avl_rad; + + ----------------------------------------------------------------------------- + -- DPRAM Output. Double buffer for RAM bursts. + PROCESS (avl_clk) IS + BEGIN + IF rising_edge(avl_clk) THEN + IF avl_wr='1' THEN + o_dpram(avl_wad)<=avl_dw; + END IF; + END IF; + END PROCESS; + + o_dr<=o_dpram(o_ad3) WHEN rising_edge(o_clk); + + ----------------------------------------------------------------------------- + -- Output Vertical Divider + -- Vfrac = Vacc / Vsize + ODivider:PROCESS (o_clk,o_reset_na) IS + BEGIN + IF o_reset_na='0' THEN +--pragma synthesis_off + o_vfrac<=x"000"; +--pragma synthesis_on + ELSIF rising_edge(o_clk) THEN + o_vdivi<=to_unsigned(2*o_vsize,13); + o_vdivr<=to_unsigned(o_vacc*4096,25); + ------------------------------------------------------ + IF o_divstart='1' THEN + o_divcpt<=0; + o_divrun<='1'; + + ELSIF o_divrun='1' THEN + ---------------------------------------------------- + IF o_divcpt=12 THEN + o_divrun<='0'; + o_vfrac<=o_vdivr(10 DOWNTO 0) & NOT o_vdivr(24); + ELSE + o_divcpt<=o_divcpt+1; + END IF; + + IF o_vdivr(24)='0' THEN + o_vdivr(24 DOWNTO 12)<=o_vdivr(23 DOWNTO 11) - o_vdivi; + ELSE + o_vdivr(24 DOWNTO 12)<=o_vdivr(23 DOWNTO 11) + o_vdivi; + END IF; + o_vdivr(11 DOWNTO 0)<=o_vdivr(10 DOWNTO 0) & NOT o_vdivr(24); + ---------------------------------------------------- + END IF; + END IF; + END PROCESS ODivider; + + ----------------------------------------------------------------------------- + Scalaire:PROCESS (o_clk,o_reset_na) IS + VARIABLE lev_inc_v,lev_dec_v : std_logic; + VARIABLE prim_v,last_v,bib_v : std_logic; + VARIABLE shift_v : unsigned(0 TO N_DW+15); + VARIABLE hpix_v : type_pix; + VARIABLE hcarry_v,vcarry_v : boolean; + VARIABLE dif_v : natural RANGE 0 TO 8*OHRES-1; + VARIABLE off_v : natural RANGE 0 TO 15; + BEGIN + IF o_reset_na='0' THEN + o_copy<=sWAIT; + o_state<=sDISP; + o_read_pre<='0'; + o_readlev<=0; + o_copylev<=0; + o_hsp<='0'; + + ELSIF rising_edge(o_clk) THEN + ------------------------------------------------------ + o_mode <=mode; -- ? + o_format <="0001" & format; -- ? + + o_run <=run; -- ? + + o_htotal <=htotal; -- ? + o_hsstart<=hsstart; -- ? + o_hsend <=hsend; -- ? + o_hdisp <=hdisp; -- ? + o_hmin <=hmin; -- ? + o_hmax <=hmax; -- ? + + o_vtotal <=vtotal; -- ? + o_vsstart<=vsstart; -- ? + o_vsend <=vsend; -- ? + o_vdisp <=vdisp; -- ? + o_vmin <=vmin; -- ? + o_vmax <=vmax; -- ? + + o_hsize <=o_hmax - o_hmin + 1; + o_vsize <=o_vmax - o_vmin + 1; + + -------------------------------------------- + -- Triple buffering. + -- For intelaced video, half frames are updated independently + -- Input : Toggle buffer at end of input frame + o_freeze <= freeze; + o_inter <=i_inter; -- + o_iendframe0<=i_endframe0; -- + o_iendframe02<=o_iendframe0; + IF o_iendframe0='1' AND o_iendframe02='0' THEN + o_ibuf0<=buf_next(o_ibuf0,o_obuf0,o_freeze); + o_bufup0<='1'; + END IF; + o_iendframe1<=i_endframe1; -- + o_iendframe12<=o_iendframe1; + IF o_iendframe1='1' AND o_iendframe12='0' THEN + o_ibuf1<=buf_next(o_ibuf1,o_obuf1,o_freeze); + o_bufup1<='1'; + END IF; + + -- Output : Change framebuffer, and image properties, at VS falling edge + IF o_vsv(1)='1' AND o_vsv(0)='0' AND o_bufup0='1' THEN + o_obuf0<=buf_next(o_obuf0,o_ibuf0,o_freeze); + o_bufup0<='0'; + END IF; + IF o_vsv(1)='1' AND o_vsv(0)='0' AND o_bufup1='1' THEN + o_obuf1<=buf_next(o_obuf1,o_ibuf1,o_freeze); + o_bufup1<='0'; + o_ihsize<=i_hrsize; -- + o_ivsize<=i_vrsize; -- + o_hdown<=i_hdown; -- + o_vdown<=i_vdown; -- + END IF; + + -- Simultaneous change of input and output framebuffers + IF o_vsv(1)='1' AND o_vsv(0)='0' AND + o_iendframe0='1' AND o_iendframe02='0' THEN + o_bufup0<='0'; + o_obuf0<=o_ibuf0; + END IF; + IF o_vsv(1)='1' AND o_vsv(0)='0' AND + o_iendframe1='1' AND o_iendframe12='0' THEN + o_bufup1<='0'; + o_obuf1<=o_ibuf1; + END IF; + + -- Non-interlaced, use same buffer for even and odd lines + IF o_inter='0' THEN + o_ibuf1<=o_ibuf0; + o_obuf1<=o_obuf0; + END IF; + + -- Triple buffer disabled + IF o_mode(3)='0' THEN + o_obuf0<=0; + o_obuf1<=0; + o_ibuf0<=0; + o_ibuf1<=0; + END IF; + + -- Framebuffer mode. + IF o_fb_ena='1' THEN + o_ihsize<=o_fb_hsize; + o_ivsize<=o_fb_vsize; + o_format<=o_fb_format; + o_hdown<='0'; + o_vdown<='0'; + END IF; + + -- 011=8bpp(palette) 100=16bpp 101=24bpp 110=32bpp + CASE o_format(2 DOWNTO 0) IS + WHEN "011" => o_ihsize_temp <= o_ihsize; + WHEN "100" => o_ihsize_temp <= o_ihsize * 2; + WHEN "110" => o_ihsize_temp <= o_ihsize * 4; + WHEN OTHERS => o_ihsize_temp <= o_ihsize * 3; + END CASE; + + o_ihsize_temp2 <= (o_ihsize_temp + N_BURST - 1); + o_hburst <= o_ihsize_temp2 / N_BURST; + + IF o_fb_ena='1' AND o_fb_stride /= 0 THEN + o_stride<=o_fb_stride; + ELSE + o_stride<=to_unsigned(o_ihsize_temp2,14); + o_stride(NB_BURST-1 DOWNTO 0)<=(OTHERS =>'0'); + END IF; + ------------------------------------------------------ + o_hmode<=o_mode; + IF o_hdown='1' AND DOWNSCALE THEN + -- Force nearest if downscaling : Downscaled framebuffer + o_hmode(2 DOWNTO 0)<="000"; + END IF; + + o_vmode<=o_mode; + IF o_vdown='1' AND DOWNSCALE THEN + -- Force nearest if downscaling : Downscaled framebuffer + o_vmode(2 DOWNTO 0)<="000"; + END IF; + + ------------------------------------------------------ + -- End DRAM READ + o_readack_sync<=avl_readack; -- + o_readack_sync2<=o_readack_sync; + o_readack<=o_readack_sync XOR o_readack_sync2; + + o_readdataack_sync<=avl_readdataack; -- + o_readdataack_sync2<=o_readdataack_sync; + o_readdataack<=o_readdataack_sync XOR o_readdataack_sync2; + + ------------------------------------------------------ + lev_inc_v:='0'; + lev_dec_v:='0'; + + -- acpt : Pixel position within current data word + -- dcpt : Destination image position + + -- Force preload 2 lines at top of screen + IF o_hsv(0)='1' AND o_hsv(1)='0' THEN + IF o_vcpt_pre3=o_vmin THEN + o_fload<=2; + o_bibu<='0'; + END IF; + o_hsp<='1'; + END IF; + + o_vpe<=to_std_logic(o_vcpt_pre=o_vmin); + o_divstart<='0'; + o_adrsa<='0'; + o_adrsb<=o_adrsa; + + o_vacc_ini<=(o_vsize - o_ivsize + 8192) MOD 8192; + o_hacc_ini<=(o_hsize + o_ihsize + 8192) MOD 8192; + + --Alternate phase + --o_vacc_ini<=o_ivsize; + --o_hacc_ini<=(2*o_hsize - o_ihsize + 8192) MOD 8192; + + CASE o_state IS + -------------------------------------------------- + WHEN sDISP => + IF o_hsp='1' THEN + o_state<=sHSYNC; + o_hsp<='0'; + END IF; + o_prim<=true; + o_vcarrym<=false; + + -------------------------------------------------- + WHEN sHSYNC => + dif_v :=(o_vacc_next - 2*o_vsize + 16384) MOD 16384; + IF o_prim THEN + IF dif_v>=8192 THEN + o_vacc <=o_vacc_next; + ELSE + o_vacc <=dif_v; + END IF; + END IF; + IF dif_v>=8192 THEN + o_vacc_next<=(o_vacc_next + 2*o_ivsize) MOD 8192; + vcarry_v:=false; + ELSE + o_vacc_next<=dif_v; + vcarry_v:=true; + END IF; + + IF o_vcpt_pre2=o_vmin THEN + o_vacc <=o_vacc_ini; + o_vacc_next<=o_vacc_ini + 2*o_ivsize; + o_vacpt <=x"001"; + o_vacptl<="01"; + vcarry_v:=false; + END IF; + + IF vcarry_v THEN + o_vacpt<=o_vacpt+1; + END IF; + IF vcarry_v AND o_prim THEN + o_vacptl<=o_vacptl+1; + END IF; + o_vcarrym <= o_vcarrym OR vcarry_v; + o_prim <= false; + o_hbcpt<=0; -- Clear burst counter on line + o_divstart<=to_std_logic(NOT vcarry_v); + IF NOT vcarry_v OR o_fload>0 THEN + IF (o_vpe='1' AND o_vcarrym) OR o_fload>0 THEN + o_state<=sREAD; + ELSE + o_state<=sDISP; + END IF; + END IF; + + WHEN sREAD => + -- Read a block + IF o_readlev<2 AND o_adrsb='1' THEN + lev_inc_v:='1'; + o_read_pre<=NOT o_read_pre; + o_state <=sWAITREAD; + o_bibu<=NOT o_bibu; + END IF; + prim_v:=to_std_logic(o_hbcpt=0); + last_v:=to_std_logic(o_hbcpt=o_hburst-1); + bib_v :=o_bibu; + off_v :=pixoffset(o_adrs + o_fb_base(NB_LA-1 DOWNTO 0),o_fb_format); + IF o_fb_ena='0' THEN + off_v:=0; + END IF; + o_adrsa<='1'; + + WHEN sWAITREAD => + IF o_readack='1' THEN + o_hbcpt<=o_hbcpt+1; + IF o_hbcpt=1 THEN + o_fload<=o_fload-1; + END IF; + END IF; + END IF; + + -------------------------------------------------- + END CASE; + + o_read<=o_read_pre AND o_run; + o_rline<=o_vacpt(0); -- Even/Odd line for interlaced video + + o_adrs_pre<=to_integer(o_vacpt) * to_integer(o_stride); + IF o_adrsa='1' THEN + IF o_fload=2 THEN + o_adrs<=to_unsigned(o_hbcpt * N_BURST,32); + o_alt<="1111"; + ELSIF o_fload=1 THEN + o_adrs<=to_unsigned(o_hbcpt * N_BURST,32) + o_stride; + o_alt<="0100"; + ELSE + o_adrs<=to_unsigned(o_adrs_pre + (o_hbcpt * N_BURST),32); + o_alt<=altx(o_vacptl + 1); + END IF; + END IF; + + ------------------------------------------------------ + -- Copy from buffered memory to pixel lines + o_sh<='0'; + CASE o_copy IS + WHEN sWAIT => + o_copyv(0)<='0'; + IF o_copylev>0 AND o_copyv(0)='0' THEN + o_copy<=sCOPY; + IF o_off(0)>0 AND o_primv(0)='1' THEN + o_copy<=sSHIFT; + END IF; + o_altx<=o_alt; + END IF; + o_adturn<='0'; + o_pshift<=o_off(0) -1; + IF o_primv(0)='1' THEN + -- First memcopy of a horizontal line, carriage return ! + o_ihsizem<=o_ihsize + o_off(0) - 2; + o_hacc <=o_hacc_ini; + o_hacc_next<=o_hacc_ini + 2*o_ihsize; + o_hacpt <=x"000"; + o_dcpt<=0; + o_dshi<=2; + o_acpt<=0; + o_first<='1'; + o_last<='0'; + END IF; + + IF o_bibv(0)='0' THEN + o_ad<=0; + ELSE + o_ad<=BLEN; + END IF; + + WHEN sSHIFT => + o_hacpt<=o_hacpt+1; + o_sh<='1'; + o_acpt<=(o_acpt+1) MOD 16; + IF shift_onext(o_acpt,o_format) THEN + o_ad<=(o_ad+1) MOD (2*BLEN); + END IF; + o_pshift<=o_pshift-1; + IF o_pshift=0 THEN + o_copy<=sCOPY; + END IF; + + WHEN sCOPY => + -- dshi : Force shift first two or three pixels of each line + IF o_dshi=0 THEN + dif_v:=(o_hacc_next - 2*o_hsize + (8*OHRES)) MOD (8*OHRES); + IF dif_v>=4*OHRES THEN + o_hacc<=o_hacc_next; + o_hacc_next<=o_hacc_next + 2*o_ihsize; + hcarry_v:=false; + ELSE + o_hacc<=dif_v; + o_hacc_next<=(dif_v + 2*o_ihsize + (4*OHRES)) MOD (4*OHRES); + hcarry_v:=true; + END IF; + o_dcpt<=(o_dcpt+1) MOD 4096; + ELSE + o_dshi<=o_dshi-1; + hcarry_v:=false; + END IF; + IF o_dshi<=1 THEN + o_copyv(0)<='1'; + END IF; + IF hcarry_v THEN + o_hacpt<=o_hacpt+1; + o_last <=to_std_logic(o_hacpt>=o_ihsizem); + END IF; + + IF hcarry_v OR o_dshi>0 THEN + o_sh<='1'; + o_acpt<=(o_acpt+1) MOD 16; + + -- Shift two more pixels to the right before ending line. + o_last1<=o_last; + o_last2<=o_last1; + + IF shift_onext(o_acpt,o_format) THEN + o_ad<=(o_ad+1) MOD (2*BLEN); + END IF; + + IF o_adturn='1' AND (shift_onext((o_acpt+1) MOD 16,o_format)) AND + (((o_ad MOD BLEN=0) AND o_lastv(0)='0') OR o_last2='1') THEN + o_copy<=sWAIT; + lev_dec_v:='1'; + END IF; + + IF o_ad MOD BLEN=4 THEN + o_adturn<='1'; + END IF; + END IF; + END CASE; + + o_acpt1<=o_acpt; o_acpt2<=o_acpt1; o_acpt3<=o_acpt2; o_acpt4<=o_acpt3; + o_ad1<=o_ad; o_ad2<=o_ad1; o_ad3<=o_ad2; + o_sh1<=o_sh; o_sh2<=o_sh1; o_sh3<=o_sh2; o_sh4<=o_sh3; + o_lastt1<=o_last; o_lastt2<=o_lastt1; + o_lastt3<=o_lastt2; o_lastt4<=o_lastt3; + + ------------------------------------------------------ + IF o_sh3='1' THEN + shift_v:=shift_opack(o_acpt4,o_shift,o_dr,o_format); + o_shift<=shift_v; + o_hpixs<=shift_opix(shift_v,o_format); + END IF; + + IF o_sh4='1' THEN + hpix_v:=o_hpixs; + IF o_format(4)='1' THEN -- Swap B <-> R + hpix_v:=(r=>o_hpixs.b,g=>o_hpixs.g,b=>o_hpixs.r); + END IF; + IF o_format(2 DOWNTO 0)="011" THEN + -- 8bpp indexed colour mode + hpix_v:=(r=>o_fb_pal_dr(23 DOWNTO 16),g=>o_fb_pal_dr(15 DOWNTO 8), + b=>o_fb_pal_dr(7 DOWNTO 0)); + END IF; + o_hpix0<=hpix_v; + o_hpix1<=o_hpix0; + o_hpix2<=o_hpix1; + o_hpix3<=o_hpix2; + + IF o_first='1' THEN + -- Left edge. Duplicate first pixel + o_hpix1<=hpix_v; + o_hpix2<=hpix_v; + o_first<='0'; + END IF; + IF o_lastt4='1' THEN + -- Right edge. Keep last pixel. + o_hpix0<=o_hpix0; + END IF; + END IF; + + ------------------------------------------------------ + -- lev_inc : read start + -- lev_dec : end of copy + -- READLEV : Number of ongoing Avalon Reads + IF lev_dec_v='0' AND lev_inc_v='1' THEN + o_readlev<=o_readlev+1; + ELSIF lev_dec_v='1' AND lev_inc_v='0' THEN + o_readlev<=o_readlev-1; + END IF; + + -- COPYLEV : Number of ongoing copies to line buffers + IF lev_dec_v='1' AND o_readdataack='0' THEN + o_copylev<=o_copylev-1; + ELSIF lev_dec_v='0' AND o_readdataack='1' THEN + o_copylev<=o_copylev+1; + END IF; + + -- FIFOs + IF lev_dec_v='1' THEN + o_primv(0 TO 1)<=o_primv(1 TO 2); -- First buffer of line + o_lastv(0 TO 1)<=o_lastv(1 TO 2); -- Last buffer of line + o_bibv (0 TO 1)<=o_bibv (1 TO 2); -- Double buffer select + o_off (0 TO 1)<=o_off (1 TO 2); -- Start offset + END IF; + + IF lev_inc_v='1' THEN + IF o_readlev=0 OR (o_readlev=1 AND lev_dec_v='1') THEN + o_primv(0)<=prim_v; + o_lastv(0)<=last_v; + o_bibv (0)<=bib_v; + o_off (0)<=off_v; + ELSIF (o_readlev=1 AND lev_dec_v='0') OR + (o_readlev=2 AND lev_dec_v='1') THEN + o_primv(1)<=prim_v; + o_lastv(1)<=last_v; + o_bibv (1)<=bib_v; + o_off (1)<=off_v; + END IF; + o_primv(2)<=prim_v; + o_lastv(2)<=last_v; + o_bibv (2)<=bib_v; + o_off (2)<=off_v; + END IF; + + ------------------------------------------------------ + END IF; + END PROCESS Scalaire; + + -- Fetch polyphase coefficients + PolyFetch:PROCESS (o_clk) IS + VARIABLE hfrac2_v, hfrac3_v, vfrac_v : unsigned(FRAC-1 DOWNTO 0); + VARIABLE o_poly_phase_v : poly_phase_interp_t; + BEGIN + IF rising_edge(o_clk) THEN + hfrac2_v:=o_hfrac(2)(11 DOWNTO 12-FRAC); + hfrac3_v:=o_hfrac(3)(11 DOWNTO 12-FRAC); + vfrac_v:=o_vfrac(11 DOWNTO 12-FRAC); + + o_v_poly_use_adaptive <= to_std_logic((o_vmode(2 DOWNTO 0)/="000") AND (o_v_poly_adaptive = '1')); + o_h_poly_use_adaptive <= to_std_logic((o_hmode(2 DOWNTO 0)/="000") AND (o_h_poly_adaptive = '1')); + + -- C2 / HC2 / VC3 + o_v_poly_addr<=to_integer(vfrac_v); + o_h_poly_addr<=to_integer(hfrac2_v); + IF o_v_poly_use_adaptive = '1' THEN + o_a_poly_addr<=to_integer(vfrac_v); + ELSIF o_h_poly_use_adaptive = '1' THEN + o_a_poly_addr<=to_integer(hfrac2_v); + END IF; + + -- C3 / HC3 / VC4 + IF o_vmode(2 DOWNTO 0)/="000" THEN + o_v_poly_phase_a<=poly_unpack(o_v_poly_mem(o_v_poly_addr)); + ELSE + o_v_poly_phase_a<=poly_nn(vfrac_v); + END IF; + + IF o_hmode(2 DOWNTO 0)/="000" THEN + o_h_poly_phase_a<=poly_unpack(o_h_poly_mem(o_h_poly_addr)); + ELSE + o_h_poly_phase_a<=poly_nn(hfrac3_v); + END IF; + + IF o_v_poly_use_adaptive='1' THEN + o_poly_lum<=o_v_poly_lum; + ELSIF o_h_poly_use_adaptive='1' THEN + o_poly_lum<=o_h_poly_lum; + END IF; + + o_poly_phase_b<=poly_unpack(o_a_poly_mem(o_a_poly_addr)); + + -- C4 / HC4 / VC5 + o_poly_lerp_ta<=signed(to_unsigned(256,10) - resize(o_poly_lum,10)); + o_poly_lerp_tb<=signed(resize(o_poly_lum,10)); + + IF o_v_poly_use_adaptive='1' THEN + o_poly_phase_a<=o_v_poly_phase_a; + ELSIF o_h_poly_use_adaptive = '1' THEN + o_poly_phase_a<=o_h_poly_phase_a; + END IF; + + o_h_poly_phase_a2<=o_h_poly_phase_a; + o_v_poly_phase_a2<=o_v_poly_phase_a; + o_poly_phase_b2<=o_poly_phase_b; + + -- C5 / HC5 / VC6 + o_poly_phase<=poly_lerp(o_poly_phase_a, o_poly_phase_b2, o_poly_lerp_ta, o_poly_lerp_tb); + o_h_poly_phase_a3<=o_h_poly_phase_a2; + o_v_poly_phase_a3<=o_v_poly_phase_a2; + + -- C6 / HC6 / VC7 + o_v_poly_phase<=poly_cvt(o_v_poly_phase_a3); + o_h_poly_phase<=poly_cvt(o_h_poly_phase_a3); + + IF o_v_poly_use_adaptive = '1' THEN + o_v_poly_phase<=o_poly_phase; + ELSIF o_h_poly_use_adaptive = '1' THEN + o_h_poly_phase<=o_poly_phase; + END IF; + + END IF; + END PROCESS PolyFetch; + + + -- Framebuffer palette + GenPal1:IF PALETTE GENERATE + Tempera1:PROCESS(pal1_clk) IS + BEGIN + IF rising_edge(pal1_clk) THEN + IF pal1_wr='1' THEN + pal1_mem(to_integer(pal1_a))<=pal1_dw; + END IF; + pal1_dr<=pal1_mem(to_integer(pal1_a)); + END IF; + END PROCESS; + + pal_idx <= shift_opack(o_acpt4,o_shift,o_dr,o_format)(0 TO 7); + pal_idx_lsb <= pal_idx(0) WHEN rising_edge(o_clk); + o_fb_pal_dr_x2 <= pal1_mem(to_integer(pal_idx(7 DOWNTO 1))) WHEN rising_edge(o_clk); + END GENERATE GenPal1; + + GenPal2:IF PALETTE and PALETTE2 GENERATE + Tempera2:PROCESS(pal2_clk) IS + BEGIN + IF rising_edge(pal2_clk) THEN + IF pal2_wr='1' THEN + pal2_mem(to_integer(pal2_a))<=pal2_dw; + END IF; + pal2_dr<=pal2_mem(to_integer(pal2_a)); + END IF; + END PROCESS; + + o_fb_pal_dr2 <= pal2_mem(to_integer(pal_idx(7 DOWNTO 0))) WHEN rising_edge(o_clk); + o_fb_pal_dr <= o_fb_pal_dr2 when pal_n = '1' else o_fb_pal_dr_x2(47 DOWNTO 24) WHEN pal_idx_lsb = '1' ELSE o_fb_pal_dr_x2(23 DOWNTO 0); + END GENERATE GenPal2; + + GenPal1not2:IF PALETTE and not PALETTE2 GENERATE + o_fb_pal_dr <= o_fb_pal_dr_x2(47 DOWNTO 24) WHEN pal_idx_lsb = '1' ELSE o_fb_pal_dr_x2(23 DOWNTO 0); + END GENERATE GenPal1not2; + + GenNoPal:IF NOT PALETTE GENERATE + o_fb_pal_dr<=x"000000"; + END GENERATE GenNoPal; + + ----------------------------------------------------------------------------- + -- Polyphase ROMs + Polikarpov:PROCESS(poly_clk) IS + BEGIN + IF rising_edge(poly_clk) THEN + IF poly_wr='1' THEN + poly_tdw(9+10*(3-to_integer(poly_a(1 DOWNTO 0))) DOWNTO + 10*(3-to_integer(poly_a(1 DOWNTO 0))))<=poly_dw; + END IF; + + poly_wr_mode(0)<=poly_wr AND NOT poly_a(FRAC+2); + poly_wr_mode(1)<=poly_wr AND poly_a(FRAC+2); + poly_wr_mode(2)<=poly_wr AND poly_a(FRAC+3) AND to_std_logic(ADAPTIVE); + poly_a2<=poly_a(FRAC+1 DOWNTO 2); + + CASE poly_wr_mode IS + WHEN "001" => -- horiz + o_h_poly_mem(to_integer(poly_a2))<=poly_tdw; + o_h_poly_adaptive<='0'; + WHEN "010" => -- vert + o_v_poly_mem(to_integer(poly_a2))<=poly_tdw; + o_v_poly_adaptive<='0'; + WHEN "101" => -- horiz adaptive + o_a_poly_mem(to_integer(poly_a2))<=poly_tdw; + o_h_poly_adaptive<='1'; + WHEN "110" => -- vert adaptive + o_a_poly_mem(to_integer(poly_a2))<=poly_tdw; + o_v_poly_adaptive<='1'; + WHEN OTHERS => NULL; + END CASE; + END IF; + END PROCESS Polikarpov; + + ----------------------------------------------------------------------------- + -- Horizontal Scaler + HSCAL:PROCESS(o_clk) IS + VARIABLE div_v : unsigned(20 DOWNTO 0); + VARIABLE dir_v : unsigned(11 DOWNTO 0); + BEGIN + IF rising_edge(o_clk) THEN + -- Pipeline signals + ----------------------------------- + -- Pipelined 8 bits non-restoring divider. Cycle 1 + dir_v:=x"000"; + div_v:=to_unsigned(o_hacc * 256,21); + + div_v:=div_v-to_unsigned(o_hsize*256,21); + dir_v(11):=NOT div_v(20); + IF div_v(20)='0' THEN + div_v:=div_v-to_unsigned(o_hsize*128,21); + ELSE + div_v:=div_v+to_unsigned(o_hsize*128,21); + END IF; + dir_v(10):=NOT div_v(20); + + o_div(0)<=div_v; + o_dir(0)<=dir_v; + + -- Cycle 2 + div_v:=o_div(0); + dir_v:=o_dir(0); + IF div_v(20)='0' THEN + div_v:=div_v-to_unsigned(o_hsize*64,21); + ELSE + div_v:=div_v+to_unsigned(o_hsize*64,21); + END IF; + dir_v( 9):=NOT div_v(20); + + IF div_v(20)='0' THEN + div_v:=div_v-to_unsigned(o_hsize*32,21); + ELSE + div_v:=div_v+to_unsigned(o_hsize*32,21); + END IF; + dir_v( 8):=NOT div_v(20); + + o_div(1)<=div_v; + o_dir(1)<=dir_v; + + -- Cycle 3 + div_v:=o_div(1); + dir_v:=o_dir(1); + IF FRAC>4 THEN + IF div_v(20)='0' THEN + div_v:=div_v-to_unsigned(o_hsize*16,21); + ELSE + div_v:=div_v+to_unsigned(o_hsize*16,21); + END IF; + dir_v(7):=NOT div_v(20); + + IF div_v(20)='0' THEN + div_v:=div_v-to_unsigned(o_hsize*8,21); + ELSE + div_v:=div_v+to_unsigned(o_hsize*8,21); + END IF; + dir_v(6):=NOT div_v(20); + END IF; + o_div(2)<=div_v; + o_dir(2)<=dir_v; + + div_v:=o_div(2); + dir_v:=o_dir(2); + IF FRAC>6 THEN + IF div_v(20)='0' THEN + div_v:=div_v-to_unsigned(o_hsize*4,21); + ELSE + div_v:=div_v+to_unsigned(o_hsize*4,21); + END IF; + dir_v(5):=NOT div_v(20); + + IF div_v(20)='0' THEN + div_v:=div_v-to_unsigned(o_hsize*2,21); + ELSE + div_v:=div_v+to_unsigned(o_hsize*2,21); + END IF; + dir_v(4):=NOT div_v(20); + END IF; + + ----------------------------------- + o_hfrac(1)<=dir_v; + o_hfrac(2 TO 6) <= o_hfrac(1 TO 5); + + o_copyv(1 TO 12)<=o_copyv(0 TO 11); + + o_dcptv(1)<=o_dcpt; + IF o_dcptv(1)>=o_hsize THEN + o_copyv(2)<='0'; + END IF; + o_dcptv(2)<=o_dcptv(1) MOD OHRES; + o_dcptv(3 TO 12)<=o_dcptv(2 TO 11); + + -- C2 + o_hpixq(2)<=(o_hpix3,o_hpix2,o_hpix1,o_hpix0); + o_hpixq(3 TO 6)<=o_hpixq(2 TO 5); + + -- BILINEAR / SHARP BILINEAR --------------- + -- C4 : Pre-calc Sharp Bilinear + o_h_sbil_t<=sbil_frac1(o_hfrac(3)); + + -- C5 : Select + o_h_bil_frac<=(OTHERS =>'0'); + IF o_hmode(0)='1' THEN -- Bilinear + IF MASK(MASK_BILINEAR)='1' THEN + o_h_bil_frac<=bil_frac(o_hfrac(4)); + END IF; + ELSE -- Sharp Bilinear + IF MASK(MASK_SHARP_BILINEAR)='1' THEN + o_h_bil_frac<=sbil_frac2(o_hfrac(4),o_h_sbil_t); + END IF; + END IF; + + -- C6 : Opposite frac + o_h_bil_t<=bil_calc(o_h_bil_frac,o_hpixq(5)); + + -- C7 : Bilinear / Sharp Bilinear + o_h_bil_pix.r<=bound(o_h_bil_t.r,8+FRAC); + o_h_bil_pix.g<=bound(o_h_bil_t.g,8+FRAC); + o_h_bil_pix.b<=bound(o_h_bil_t.b,8+FRAC); + + -- BICUBIC ------------------------------------------- + -- C5 : Bicubic coefficients A,B,C,D + -- C5 : Bicubic calc T1 = X.D + C + o_h_bic_abcd1<=bic_calc0(o_hfrac(4),o_hpixq(4)); + o_h_bic_tt1<=bic_calc1(o_hfrac(4), + bic_calc0(o_hfrac(4),o_hpixq(4))); + + -- C6 : Bicubic calc T2 = X.T1 + B + o_h_bic_abcd2<=o_h_bic_abcd1; + o_h_bic_tt2<=bic_calc2(o_hfrac(5),o_h_bic_tt1,o_h_bic_abcd1); + + -- C7 : Bicubic final Y = X.T2 + A + o_h_bic_pix<=bic_calc3(o_hfrac(6),o_h_bic_tt2,o_h_bic_abcd2); + + -- POLYPHASE ----------------------------------------- + -- C2 + IF o_hfrac(2)(o_hfrac(2)'left)='0' THEN + o_h_poly_lum<=poly_lum(o_hpix2); + ELSE + o_h_poly_lum<=poly_lum(o_hpix1); + END IF; + -- C3-C6 in PolyFetch + + -- C7 : Apply Polyphase + o_h_poly_t<=poly_calc(o_h_poly_phase,o_hpixq(6)); + + -- C8 : Sum and bound + o_h_poly_pix<=poly_final(o_h_poly_t); + + -- C9 : Select interpoler ---------------------------- + o_wadl<=o_dcptv(12); + o_wr<=o_altx AND (o_copyv(12) & o_copyv(12) & o_copyv(12) & o_copyv(12)); + o_ldw<=(x"00",x"00",x"00"); + + CASE o_hmode(2 DOWNTO 0) IS + WHEN "000" => -- Nearest + IF MASK(MASK_NEAREST)='1' THEN + o_ldw<=o_h_poly_pix; + END IF; + WHEN "001" | "010" => -- Bilinear | Sharp Bilinear + IF MASK(MASK_BILINEAR)='1' OR + MASK(MASK_SHARP_BILINEAR)='1' THEN + o_ldw<=o_h_bil_pix; + END IF; + WHEN "011" => -- BiCubic + IF MASK(MASK_BICUBIC)='1' THEN + o_ldw<=o_h_bic_pix; + END IF; + WHEN OTHERS => -- PolyPhase + IF MASK(MASK_POLY)='1' THEN + o_ldw<=o_h_poly_pix; + END IF; + END CASE; + ------------------------------------------------------ + END IF; + END PROCESS HSCAL; + + ----------------------------------------------------------------------------- + -- Line buffers 4 x OHRES x (R+G+B) + OLBUF:PROCESS(o_clk) IS + BEGIN + IF rising_edge(o_clk) THEN + -- WRITES + IF o_wr(0)='1' THEN o_line0(o_wadl)<=o_ldw; END IF; + IF o_wr(1)='1' THEN o_line1(o_wadl)<=o_ldw; END IF; + IF o_wr(2)='1' THEN o_line2(o_wadl)<=o_ldw; END IF; + IF o_wr(3)='1' THEN o_line3(o_wadl)<=o_ldw; END IF; + + -- READS + o_ldr0<=o_line0(o_radl0); + o_ldr1<=o_line1(o_radl1); + o_ldr2<=o_line2(o_radl2); + o_ldr3<=o_line3(o_radl3); + END IF; + END PROCESS OLBUF; + + ----------------------------------------------------------------------------- + -- Output video sweep + OSWEEP:PROCESS(o_clk) IS + BEGIN + IF rising_edge(o_clk) THEN + IF o_ce='1' THEN + -- Output pixels count + IF o_hcpt+1=o_vtotal THEN + o_vcpt_pre3<=0; + ELSE + o_vcpt_pre3<=(o_vcpt_pre3+1) MOD 4096; + END IF; + o_vcpt_pre2<=o_vcpt_pre3; + o_vcpt_pre<=o_vcpt_pre2; + o_vcpt<=o_vcpt_pre; + END IF; + + o_end(0)<=to_std_logic(o_vcpt>=o_vdisp); + o_dev(0)<=to_std_logic(o_hcpt=o_hmin AND o_hcpt<=o_hmax AND + o_vcpt>=o_vmin AND o_vcpt<=o_vmax); + o_hsv(0)<=to_std_logic(o_hcpt>=o_hsstart AND o_hcpt=o_hsstart) OR + (o_vcpt>o_vsstart AND o_vcpt=o_vmin AND o_vcpt_pre2<=o_vmax); + o_hsv(1 TO 9)<=o_hsv(0 TO 8); + o_vsv(1 TO 9)<=o_vsv(0 TO 8); + o_dev(1 TO 9)<=o_dev(0 TO 8); + o_pev(1 TO 9)<=o_pev(0 TO 8); + o_end(1 TO 9)<=o_end(0 TO 8); + + IF o_run='0' THEN + o_hsv(2)<='0'; + o_vsv(2)<='0'; + o_dev(2)<='0'; + o_pev(2)<='0'; + o_end(2)<='0'; + END IF; + + END IF; + END IF; + + END PROCESS OSWEEP; + + ----------------------------------------------------------------------------- + -- Vertical Scaler + VSCAL:PROCESS(o_clk) IS + VARIABLE pixq_v : arr_pix(0 TO 3); + VARIABLE vlumpix_v : type_pix; + VARIABLE r1_v, r2_v : natural RANGE 0 TO OHRES-1; + VARIABLE fracnn_v : std_logic; + BEGIN + IF rising_edge(o_clk) THEN + IF o_ce='1' THEN + o_v_hmin_adj<=o_hmin + 4; + + fracnn_v := o_vfrac(o_vfrac'left); + r1_v := (o_hcpt - o_v_hmin_adj + OHRES) MOD OHRES; + r2_v := (o_hcpt - o_hmin + OHRES) MOD OHRES; + + -- CYCLE 1 ----------------------------------------- + -- Read mem + o_radl0<=r1_v; + o_radl1<=r1_v; + o_radl2<=r1_v; + o_radl3<=r1_v; + + IF fracnn_v = '0' THEN + CASE o_vacptl IS + WHEN "10" => o_radl1<=r2_v; + WHEN "11" => o_radl2<=r2_v; + WHEN "00" => o_radl3<=r2_v; + WHEN OTHERS => o_radl0<=r2_v; + END CASE; + ELSE + CASE o_vacptl IS + WHEN "10" => o_radl2<=r2_v; + WHEN "11" => o_radl3<=r2_v; + WHEN "00" => o_radl0<=r2_v; + WHEN OTHERS => o_radl1<=r2_v; + END CASE; + END IF; + + -- CYCLE 2 ----------------------------------------- + -- Lines reordering + CASE o_vacptl IS + WHEN "10" => pixq_v:=(o_ldr0,o_ldr1,o_ldr2,o_ldr3); + WHEN "11" => pixq_v:=(o_ldr1,o_ldr2,o_ldr3,o_ldr0); + WHEN "00" => pixq_v:=(o_ldr2,o_ldr3,o_ldr0,o_ldr1); + WHEN OTHERS => pixq_v:=(o_ldr3,o_ldr0,o_ldr1,o_ldr2); + END CASE; + + IF fracnn_v = '0' THEN + o_vpix_outer<=(pixq_v(0), pixq_v(2), pixq_v(3)); + o_vpix_inner(0)<=pixq_v(1); + ELSE + o_vpix_outer<=(pixq_v(0), pixq_v(1), pixq_v(3)); + o_vpix_inner(0)<=pixq_v(2); + END IF; + + -- CYCLE 3-6 + o_vpix_inner(1 TO 4)<=o_vpix_inner(0 TO 3); + + -- CYCLE 7 + IF to_integer(o_vacpt)>o_ivsize THEN + IF fracnn_v = '0' THEN + o_vpixq<=(o_vpix_outer(0), o_vpix_inner(4), o_vpix_inner(4), o_vpix_inner(4)); + ELSE + o_vpixq<=(o_vpix_outer(0), o_vpix_outer(1), o_vpix_outer(1), o_vpix_outer(1)); + END IF; + ELSIF to_integer(o_vacpt)=o_ivsize THEN + IF fracnn_v = '0' THEN + o_vpixq<=(o_vpix_outer(0), o_vpix_inner(4), o_vpix_outer(1), o_vpix_outer(1)); + ELSE + o_vpixq<=(o_vpix_outer(0), o_vpix_outer(1), o_vpix_inner(4), o_vpix_inner(4)); + END IF; + ELSE + IF fracnn_v = '0' THEN + o_vpixq<=(o_vpix_outer(0), o_vpix_inner(4), o_vpix_outer(1), o_vpix_outer(2)); + ELSE + o_vpixq<=(o_vpix_outer(0), o_vpix_outer(1), o_vpix_inner(4), o_vpix_outer(2)); + END IF; + END IF; + + -- BILINEAR / SHARP BILINEAR ----------------------- + -- C6 : Pre-calc Sharp Bilinear + o_v_sbil_t<=sbil_frac1(o_vfrac); + + -- C7 : Select + o_v_bil_frac<=(OTHERS =>'0'); + IF o_vmode(0)='1' THEN -- Bilinear + IF MASK(MASK_BILINEAR)='1' THEN + o_v_bil_frac<=bil_frac(o_vfrac); + END IF; + ELSE -- Sharp Bilinear + IF MASK(MASK_SHARP_BILINEAR)='1' THEN + o_v_bil_frac<=sbil_frac2(o_vfrac,o_v_sbil_t); + END IF; + END IF; + + -- C8 : + o_v_bil_t<=bil_calc(o_v_bil_frac,o_vpixq); + + -- C9 : Nearest / Bilinear / Sharp Bilinear + o_v_bil_pix.r<=bound(o_v_bil_t.r,8+FRAC); + o_v_bil_pix.g<=bound(o_v_bil_t.g,8+FRAC); + o_v_bil_pix.b<=bound(o_v_bil_t.b,8+FRAC); + + -- BICUBIC ----------------------------------------- + -- C7 : Bicubic coefficients A,B,C,D + -- C7 : Bicubic calc T1 = X.D + C + o_v_bic_abcd1<=bic_calc0(o_vfrac,o_vpixq); + o_v_bic_tt1<=bic_calc1(o_vfrac,bic_calc0(o_vfrac,o_vpixq)); + + -- C8 : Bicubic calc T2 = X.T1 + B + o_v_bic_abcd2<=o_v_bic_abcd1; + o_v_bic_tt2<=bic_calc2(o_vfrac,o_v_bic_tt1,o_v_bic_abcd1); + + -- C9 : Bicubic final Y = X.T2 + A + o_v_bic_pix<=bic_calc3(o_vfrac,o_v_bic_tt2,o_v_bic_abcd2); + + -- POLYPHASE --------------------------------------- + -- C3 : Calculate Luminance + o_v_poly_lum<=poly_lum(o_vpix_inner(0)); + + -- C4-C7 in PolyFetch + + -- C8 : Apply polyphase + o_v_poly_t<=poly_calc(o_v_poly_phase,o_vpixq); + + -- C9 : Bound + o_v_poly_pix<=poly_final(o_v_poly_t); + + -- CYCLE 10 ----------------------------------------- + o_hs<=o_hsv(9); + o_vs<=o_vsv(9); + o_de<=o_dev(9); + o_vbl<=o_end(9); + o_r<=x"00"; + o_g<=x"00"; + o_b<=x"00"; + o_brd<= not o_pev(9); + + CASE o_vmode(2 DOWNTO 0) IS + WHEN "000" => -- Nearest + IF MASK(MASK_NEAREST)='1' THEN + o_r<=o_v_poly_pix.r; + o_g<=o_v_poly_pix.g; + o_b<=o_v_poly_pix.b; + END IF; + WHEN "001" | "010" => -- Bilinear | Sharp Bilinear + IF MASK(MASK_BILINEAR)='1' OR + MASK(MASK_SHARP_BILINEAR)='1' THEN + o_r<=o_v_bil_pix.r; + o_g<=o_v_bil_pix.g; + o_b<=o_v_bil_pix.b; + END IF; + WHEN "011" => -- BiCubic + IF MASK(MASK_BICUBIC)='1' THEN + o_r<=o_v_bic_pix.r; + o_g<=o_v_bic_pix.g; + o_b<=o_v_bic_pix.b; + END IF; + + WHEN OTHERS => -- Polyphase + IF MASK(MASK_POLY)='1' THEN + o_r<=o_v_poly_pix.r; + o_g<=o_v_poly_pix.g; + o_b<=o_v_poly_pix.b; + END IF; + END CASE; + + IF o_pev(9)='0' THEN + o_r<=o_border(23 DOWNTO 16); -- Copy border colour + o_g<=o_border(15 DOWNTO 8); + o_b<=o_border(7 DOWNTO 0); + END IF; + + ---------------------------------------------------- + END IF; + END IF; + + END PROCESS VSCAL; + + ----------------------------------------------------------------------------- + -- Low Lag syntoniser interface + o_lltune<=(0 => i_vss, + 1 => i_pde, + 2 => i_inter, + 3 => i_flm, + 4 => o_vss, + 5 => i_pce, + 6 => i_clk, + 7 => o_clk, + OTHERS =>'0'); + + ---------------------------------------------------------------------------- +END ARCHITECTURE rtl; diff --git a/sys/audio_out.v b/sys/audio_out.v new file mode 100644 index 0000000..0f748e0 --- /dev/null +++ b/sys/audio_out.v @@ -0,0 +1,296 @@ + +module audio_out +#( + parameter CLK_RATE = 24576000 +) +( + input reset, + input clk, + + //0 - 48KHz, 1 - 96KHz + input sample_rate, + + input [31:0] flt_rate, + input [39:0] cx, + input [7:0] cx0, + input [7:0] cx1, + input [7:0] cx2, + input [23:0] cy0, + input [23:0] cy1, + input [23:0] cy2, + + input [4:0] att, + input [1:0] mix, + + input is_signed, + input [15:0] core_l, + input [15:0] core_r, + + input [15:0] alsa_l, + input [15:0] alsa_r, + + // I2S + output i2s_bclk, + output i2s_lrclk, + output i2s_data, + + // SPDIF + output spdif, + + // Sigma-Delta DAC + output dac_l, + output dac_r +); + +localparam AUDIO_RATE = 48000; +localparam AUDIO_DW = 16; + +localparam CE_RATE = AUDIO_RATE*AUDIO_DW*8; +localparam FILTER_DIV = (CE_RATE/(AUDIO_RATE*32))-1; + +wire [31:0] real_ce = sample_rate ? {CE_RATE[30:0],1'b0} : CE_RATE[31:0]; + +reg mclk_ce; +always @(posedge clk) begin + reg [31:0] cnt; + + mclk_ce = 0; + cnt = cnt + real_ce; + if(cnt >= CLK_RATE) begin + cnt = cnt - CLK_RATE; + mclk_ce = 1; + end +end + +reg i2s_ce; +always @(posedge clk) begin + reg div; + i2s_ce <= 0; + if(mclk_ce) begin + div <= ~div; + i2s_ce <= div; + end +end + +i2s i2s +( + .reset(reset), + + .clk(clk), + .ce(i2s_ce), + + .sclk(i2s_bclk), + .lrclk(i2s_lrclk), + .sdata(i2s_data), + + .left_chan(al), + .right_chan(ar) +); + +spdif toslink +( + .rst_i(reset), + + .clk_i(clk), + .bit_out_en_i(mclk_ce), + + .sample_i({ar,al}), + .spdif_o(spdif) +); + +sigma_delta_dac #(15) sd_l +( + .CLK(clk), + .RESET(reset), + .DACin({~al[15], al[14:0]}), + .DACout(dac_l) +); + +sigma_delta_dac #(15) sd_r +( + .CLK(clk), + .RESET(reset), + .DACin({~ar[15], ar[14:0]}), + .DACout(dac_r) +); + +reg sample_ce; +always @(posedge clk) begin + reg [8:0] div = 0; + reg [1:0] add = 0; + + div <= div + add; + if(!div) begin + div <= 2'd1 << sample_rate; + add <= 2'd1 << sample_rate; + end + + sample_ce <= !div; +end + +reg flt_ce; +always @(posedge clk) begin + reg [31:0] cnt = 0; + + flt_ce = 0; + cnt = cnt + {flt_rate[30:0],1'b0}; + if(cnt >= CLK_RATE) begin + cnt = cnt - CLK_RATE; + flt_ce = 1; + end +end + +reg [15:0] cl,cr; +always @(posedge clk) begin + reg [15:0] cl1,cl2; + reg [15:0] cr1,cr2; + + cl1 <= core_l; cl2 <= cl1; + if(cl2 == cl1) cl <= cl2; + + cr1 <= core_r; cr2 <= cr1; + if(cr2 == cr1) cr <= cr2; +end + +reg a_en1 = 0, a_en2 = 0; +always @(posedge clk, posedge reset) begin + reg [1:0] dly1 = 0; + reg [14:0] dly2 = 0; + + if(reset) begin + dly1 <= 0; + dly2 <= 0; + a_en1 <= 0; + a_en2 <= 0; + end + else begin + if(flt_ce) begin + if(~&dly1) dly1 <= dly1 + 1'd1; + else a_en1 <= 1; + end + + if(sample_ce) begin + if(!dly2[13+sample_rate]) dly2 <= dly2 + 1'd1; + else a_en2 <= 1; + end + end +end + +wire [15:0] acl, acr; +IIR_filter #(.use_params(0)) IIR_filter +( + .clk(clk), + .reset(reset), + + .ce(flt_ce & a_en1), + .sample_ce(sample_ce), + + .cx(cx), + .cx0(cx0), + .cx1(cx1), + .cx2(cx2), + .cy0(cy0), + .cy1(cy1), + .cy2(cy2), + + .input_l({~is_signed ^ cl[15], cl[14:0]}), + .input_r({~is_signed ^ cr[15], cr[14:0]}), + .output_l(acl), + .output_r(acr) +); + +wire [15:0] adl; +DC_blocker dcb_l +( + .clk(clk), + .ce(sample_ce), + .sample_rate(sample_rate), + .mute(~a_en2), + .din(acl), + .dout(adl) +); + +wire [15:0] adr; +DC_blocker dcb_r +( + .clk(clk), + .ce(sample_ce), + .sample_rate(sample_rate), + .mute(~a_en2), + .din(acr), + .dout(adr) +); + +wire [15:0] al, audio_l_pre; +aud_mix_top audmix_l +( + .clk(clk), + .ce(sample_ce), + .att(att), + .mix(mix), + + .core_audio(adl), + .pre_in(audio_r_pre), + .linux_audio(alsa_l), + + .pre_out(audio_l_pre), + .out(al) +); + +wire [15:0] ar, audio_r_pre; +aud_mix_top audmix_r +( + .clk(clk), + .ce(sample_ce), + .att(att), + .mix(mix), + + .core_audio(adr), + .pre_in(audio_l_pre), + .linux_audio(alsa_r), + + .pre_out(audio_r_pre), + .out(ar) +); + +endmodule + +module aud_mix_top +( + input clk, + input ce, + + input [4:0] att, + input [1:0] mix, + + input [15:0] core_audio, + input [15:0] linux_audio, + input [15:0] pre_in, + + output reg [15:0] pre_out = 0, + output reg [15:0] out = 0 +); + +reg signed [16:0] a1, a2, a3, a4; +always @(posedge clk) if (ce) begin + + a1 <= {core_audio[15],core_audio}; + a2 <= a1 + {linux_audio[15],linux_audio}; + + pre_out <= a2[16:1]; + + case(mix) + 0: a3 <= a2; + 1: a3 <= $signed(a2) - $signed(a2[16:3]) + $signed(pre_in[15:2]); + 2: a3 <= $signed(a2) - $signed(a2[16:2]) + $signed(pre_in[15:1]); + 3: a3 <= {a2[16],a2[16:1]} + {pre_in[15],pre_in}; + endcase + + if(att[4]) a4 <= 0; + else a4 <= a3 >>> att[3:0]; + + //clamping + out <= ^a4[16:15] ? {a4[16],{15{a4[15]}}} : a4[15:0]; +end + +endmodule diff --git a/sys/build_id.tcl b/sys/build_id.tcl new file mode 100644 index 0000000..bb2dc67 --- /dev/null +++ b/sys/build_id.tcl @@ -0,0 +1,73 @@ + +# Build TimeStamp Verilog Module +# Jeff Wiencrot - 8/1/2011 +# Sorgelig - 02/11/2019 +proc generateBuildID_Verilog {} { + + # Get the timestamp (see: http://www.altera.com/support/examples/tcl/tcl-date-time-stamp.html) + set buildDate "`define BUILD_DATE \"[clock format [ clock seconds ] -format %y%m%d]\"" + + # Create a Verilog file for output + set outputFileName "build_id.v" + + set fileData "" + if { [file exists $outputFileName]} { + set outputFile [open $outputFileName "r"] + set fileData [read $outputFile] + close $outputFile + } + + if {$buildDate ne $fileData} { + set outputFile [open $outputFileName "w"] + puts -nonewline $outputFile $buildDate + close $outputFile + # Send confirmation message to the Messages window + post_message "Generated: [pwd]/$outputFileName: $buildDate" + } +} + +# Build CDF file +# Sorgelig - 17/2/2018 +proc generateCDF {revision device outpath} { + + set outputFileName "jtag.cdf" + set outputFile [open $outputFileName "w"] + + puts $outputFile "JedecChain;" + puts $outputFile " FileRevision(JESD32A);" + puts $outputFile " DefaultMfr(6E);" + puts $outputFile "" + puts $outputFile " P ActionCode(Ign)" + puts $outputFile " Device PartName(SOCVHPS) MfrSpec(OpMask(0));" + puts $outputFile " P ActionCode(Cfg)" + puts $outputFile " Device PartName($device) Path(\"$outpath/\") File(\"$revision.sof\") MfrSpec(OpMask(1));" + puts $outputFile "ChainEnd;" + puts $outputFile "" + puts $outputFile "AlteraBegin;" + puts $outputFile " ChainType(JTAG);" + puts $outputFile "AlteraEnd;" +} + +set project_name [lindex $quartus(args) 1] +set revision [lindex $quartus(args) 2] + +if {[project_exists $project_name]} { + if {[string equal "" $revision]} { + project_open $project_name -revision [get_current_revision $project_name] + } else { + project_open $project_name -revision $revision + } +} else { + post_message -type error "Project $project_name does not exist" + exit +} + +set device [get_global_assignment -name DEVICE] +set outpath [get_global_assignment -name PROJECT_OUTPUT_DIRECTORY] + +if [is_project_open] { + project_close +} + +generateBuildID_Verilog +generateCDF $revision $device $outpath diff --git a/sys/ddr_svc.sv b/sys/ddr_svc.sv new file mode 100644 index 0000000..abcd4fa --- /dev/null +++ b/sys/ddr_svc.sv @@ -0,0 +1,108 @@ +// +// Copyright (c) 2020 Alexey Melnikov +// +// +// This source file is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This source file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// ------------------------------------------ +// + +// 16-bit version + +module ddr_svc +( + input clk, + + input ram_waitrequest, + output [7:0] ram_burstcnt, + output [28:0] ram_addr, + input [63:0] ram_readdata, + input ram_read_ready, + output reg ram_read, + output [63:0] ram_writedata, + output [7:0] ram_byteenable, + output reg ram_write, + + output [7:0] ram_bcnt, + + input [31:3] ch0_addr, + input [7:0] ch0_burst, + output [63:0] ch0_data, + input ch0_req, + output ch0_ready, + + input [31:3] ch1_addr, + input [7:0] ch1_burst, + output [63:0] ch1_data, + input ch1_req, + output ch1_ready +); + +assign ram_burstcnt = ram_burst; +assign ram_byteenable = 8'hFF; +assign ram_addr = ram_address; +assign ram_writedata = 0; + +assign ch0_data = ram_q[0]; +assign ch1_data = ram_q[1]; +assign ch0_ready = ready[0]; +assign ch1_ready = ready[1]; + +reg [7:0] ram_burst; +reg [63:0] ram_q[2]; +reg [31:3] ram_address; +reg [1:0] ack = 0; +reg [1:0] ready; +reg state = 0; +reg ch = 0; + +always @(posedge clk) begin + ready <= 0; + + if(!ram_waitrequest) begin + ram_read <= 0; + ram_write <= 0; + + case(state) + 0: if(ch0_req != ack[0]) begin + ack[0] <= ch0_req; + ram_address <= ch0_addr; + ram_burst <= ch0_burst; + ram_read <= 1; + ch <= 0; + ram_bcnt <= 8'hFF; + state <= 1; + end + else if(ch1_req != ack[1]) begin + ack[1] <= ch1_req; + ram_address <= ch1_addr; + ram_burst <= ch1_burst; + ram_read <= 1; + ch <= 1; + ram_bcnt <= 8'hFF; + state <= 1; + end + 1: begin + if(ram_read_ready) begin + ram_bcnt <= ram_bcnt + 1'd1; + ram_q[ch] <= ram_readdata; + ready[ch] <= 1; + if ((ram_bcnt+2'd2) == ram_burst) state <= 0; + end + end + endcase + end +end + +endmodule diff --git a/sys/f2sdram_safe_terminator.sv b/sys/f2sdram_safe_terminator.sv new file mode 100644 index 0000000..07085d7 --- /dev/null +++ b/sys/f2sdram_safe_terminator.sv @@ -0,0 +1,250 @@ +// ============================================================================ +// +// f2sdram_safe_terminator for MiSTer platform +// +// ============================================================================ +// Copyright (c) 2021 bellwood420 +// +// Background: +// +// Terminating a transaction of burst writing(/reading) in its midstream +// seems to cause an illegal state to f2sdram interface. +// +// Forced reset request that occurs when loading other core is inevitable. +// +// So if it happens exactly within the transaction period, +// unexpected issues with accessing to f2sdram interface will be caused +// in next loaded core. +// +// It seems that only way to reset broken f2sdram interface is to reset +// whole SDRAM Controller Subsystem from HPS via permodrst register +// in Reset Manager. +// But it cannot be done safely while Linux is running. +// It is usually done when cold or warm reset is issued in HPS. +// +// Main_MiSTer is issuing reset for FPGA <> HPS bridges +// via brgmodrst register in Reset Manager when loading rbf. +// But it has no effect on f2sdram interface. +// f2sdram interface seems to belong to SDRAM Controller Subsystem +// rather than FPGA-to-HPS bridge. +// +// Main_MiSTer is also trying to issuing reset for f2sdram ports +// via fpgaportrst register in SDRAM Controller Subsystem when loading rbf. +// But according to the Intel's document, fpgaportrst register can be +// used to stretch the port reset. +// It seems that it cannot be used to assert the port reset. +// +// According to the Intel's document, there seems to be a reset port on +// Avalon-MM slave interface, but it cannot be found in Qsys generated HDL. +// +// To conclude, the only thing FPGA can do is not to break the transaction. +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// +// Purpose: +// To prevent the issue, this module completes ongoing transaction +// on behalf of user logic, when reset is asserted. +// +// Usage: +// Insert this module into the bus line between +// f2sdram (Avalon-MM slave) and user logic (Avalon-MM master). +// +// Notice: +// Asynchronous reset request is not supported. +// Please feed reset request synchronized to clock. +// +module f2sdram_safe_terminator #( + parameter DATA_WIDTH = 64, + parameter BURSTCOUNT_WIDTH = 8 +) ( + // clk should be the same as one provided to f2sdram port + // clk should not be stop when reset is asserted + input clk, + // rst_req_sync should be synchronized to clk + // Asynchronous reset request is not supported + input rst_req_sync, + + // Master port: connecting to Alavon-MM slave(f2sdram) + input waitrequest_master, + output [BURSTCOUNT_WIDTH-1:0] burstcount_master, + output [ADDRESS_WITDH-1:0] address_master, + input [DATA_WIDTH-1:0] readdata_master, + input readdatavalid_master, + output read_master, + output [DATA_WIDTH-1:0] writedata_master, + output [BYTEENABLE_WIDTH-1:0] byteenable_master, + output write_master, + + // Slave port: connecting to Alavon-MM master(user logic) + output waitrequest_slave, + input [BURSTCOUNT_WIDTH-1:0] burstcount_slave, + input [ADDRESS_WITDH-1:0] address_slave, + output [DATA_WIDTH-1:0] readdata_slave, + output readdatavalid_slave, + input read_slave, + input [DATA_WIDTH-1:0] writedata_slave, + input [BYTEENABLE_WIDTH-1:0] byteenable_slave, + input write_slave +); + +localparam BYTEENABLE_WIDTH = DATA_WIDTH/8; +localparam ADDRESS_WITDH = 32-$clog2(BYTEENABLE_WIDTH); + +/* +* Capture init reset deaseert +*/ +reg init_reset_deasserted = 1'b0; + +always_ff @(posedge clk) begin + if (!rst_req_sync) begin + init_reset_deasserted <= 1'b1; + end +end + +/* +* Lock stage +*/ +reg lock_stage = 1'b0; + +always_ff @(posedge clk) begin + if (rst_req_sync) begin + // Reset assert + if (init_reset_deasserted) begin + lock_stage <= 1'b1; + end + end + else begin + // Reset deassert + lock_stage <= 1'b0; + end +end + +/* +* Write burst transaction observer +*/ +reg state_write = 1'b0; +wire next_state_write; + +wire burst_write_start = !state_write && next_state_write; +wire valid_write_data = state_write && !waitrequest_master; +wire burst_write_end = state_write && (write_burstcounter == write_burstcount_latch - 1'd1); +wire valid_non_burst_write = !state_write && write_slave && (burstcount_slave == 1) && !waitrequest_master; + +reg [BURSTCOUNT_WIDTH-1:0] write_burstcounter = 0; +reg [BURSTCOUNT_WIDTH-1:0] write_burstcount_latch = 0; +reg [ADDRESS_WITDH-1:0] write_address_latch = 0; + +always_ff @(posedge clk) begin + state_write <= next_state_write; + + if (burst_write_start) begin + write_burstcounter <= waitrequest_master ? 1'd0 : 1'd1; + write_burstcount_latch <= burstcount_slave; + write_address_latch <= address_slave; + end + else if (valid_write_data) begin + write_burstcounter <= write_burstcounter + 1'd1; + end +end + +always_comb begin + if (!state_write) begin + if (valid_non_burst_write) + next_state_write = 1'b0; + else if (write_slave) + next_state_write = 1'b1; + else + next_state_write = 1'b0; + end + else begin + if (burst_write_end) + next_state_write = 1'b0; + else + next_state_write = 1'b1; + end +end + +reg [BURSTCOUNT_WIDTH-1:0] write_terminate_counter = 0; +reg [BURSTCOUNT_WIDTH-1:0] burstcount_latch = 0; +reg [ADDRESS_WITDH-1:0] address_latch = 0; + +reg terminating = 0; +reg read_terminating = 0; +reg write_terminating = 0; + +wire on_write_transaction = state_write && next_state_write; +wire on_start_write_transaction = !state_write && next_state_write; + +always_ff @(posedge clk) begin + if (rst_req_sync) begin + // Reset assert + if (init_reset_deasserted) begin + if (!lock_stage) begin + // Even not knowing reading is in progress or not, + // if it is in progress, it will finish at some point, and no need to do anything. + // Assume that reading is in progress when we are not on write transaction. + burstcount_latch <= burstcount_slave; + address_latch <= address_slave; + terminating <= 1; + + if (on_write_transaction) begin + write_terminating <= 1; + burstcount_latch <= write_burstcount_latch; + address_latch <= write_address_latch; + write_terminate_counter <= waitrequest_master ? write_burstcounter : write_burstcounter + 1'd1; + end + else if (on_start_write_transaction) begin + if (!valid_non_burst_write) begin + write_terminating <= 1; + write_terminate_counter <= waitrequest_master ? 1'd0 : 1'd1; + end + end + else if (read_slave && waitrequest_master) begin + // Need to keep read signal, burstcount and address until waitrequest_master deasserted + read_terminating <= 1; + end + end + else if (!waitrequest_master) begin + read_terminating <= 0; + end + end + end + else begin + // Reset deassert + if (!write_terminating) terminating <= 0; + read_terminating <= 0; + end + + if (write_terminating) begin + // Continue write transaction until the end + if (!waitrequest_master) write_terminate_counter <= write_terminate_counter + 1'd1; + if (write_terminate_counter == burstcount_latch - 1'd1) write_terminating <= 0; + end +end + +/* +* Bus mux depending on the stage. +*/ +always_comb begin + if (terminating) begin + burstcount_master = burstcount_latch; + address_master = address_latch; + read_master = read_terminating; + write_master = write_terminating; + byteenable_master = 0; + end + else begin + burstcount_master = burstcount_slave; + address_master = address_slave; + read_master = read_slave; + byteenable_master = byteenable_slave; + write_master = write_slave; + end +end + +// Just passing master <-> slave +assign writedata_master = writedata_slave; +assign readdata_slave = readdata_master; +assign readdatavalid_slave = readdatavalid_master; +assign waitrequest_slave = waitrequest_master; + +endmodule diff --git a/sys/gamma_corr.sv b/sys/gamma_corr.sv new file mode 100644 index 0000000..321b83f --- /dev/null +++ b/sys/gamma_corr.sv @@ -0,0 +1,124 @@ +module gamma_corr +( + input clk_sys, + input clk_vid, + input ce_pix, + input gamma_en, + input gamma_wr, + input [9:0] gamma_wr_addr, + input [7:0] gamma_value, + input HSync, + input VSync, + input HBlank, + input VBlank, + input [23:0] RGB_in, + output reg HSync_out, + output reg VSync_out, + output reg HBlank_out, + output reg VBlank_out, + output reg [23:0] RGB_out +); + +(* ramstyle="no_rw_check" *) reg [7:0] gamma_curve[768]; + +always @(posedge clk_sys) if (gamma_wr) gamma_curve[gamma_wr_addr] <= gamma_value; +always @(posedge clk_vid) gamma <= gamma_curve[gamma_index]; + +reg [9:0] gamma_index; +reg [7:0] gamma; + +always @(posedge clk_vid) begin + reg [7:0] R_in, G_in, B_in; + reg [7:0] R_gamma, G_gamma; + reg hs,vs,hb,vb; + reg [1:0] ctr = 0; + reg old_ce; + + old_ce <= ce_pix; + if(~old_ce & ce_pix) begin + {R_in,G_in,B_in} <= RGB_in; + hs <= HSync; vs <= VSync; + hb <= HBlank; vb <= VBlank; + + RGB_out <= gamma_en ? {R_gamma,G_gamma,gamma} : {R_in,G_in,B_in}; + HSync_out <= hs; VSync_out <= vs; + HBlank_out <= hb; VBlank_out <= vb; + + ctr <= 1; + gamma_index <= {2'b00,RGB_in[23:16]}; + end + + if (|ctr) ctr <= ctr + 1'd1; + + case(ctr) + 1: begin gamma_index <= {2'b01,G_in}; end + 2: begin R_gamma <= gamma; gamma_index <= {2'b10,B_in}; end + 3: begin G_gamma <= gamma; end + endcase +end + +endmodule + +module gamma_fast +( + input clk_vid, + input ce_pix, + + inout [21:0] gamma_bus, + + input HSync, + input VSync, + input HBlank, + input VBlank, + input DE, + input [23:0] RGB_in, + + output reg HSync_out, + output reg VSync_out, + output reg HBlank_out, + output reg VBlank_out, + output reg DE_out, + output reg [23:0] RGB_out +); + +(* ramstyle="no_rw_check" *) reg [7:0] gamma_curve_r[256]; +(* ramstyle="no_rw_check" *) reg [7:0] gamma_curve_g[256]; +(* ramstyle="no_rw_check" *) reg [7:0] gamma_curve_b[256]; + +assign gamma_bus[21] = 1; +wire clk_sys = gamma_bus[20]; +wire gamma_en = gamma_bus[19]; +wire gamma_wr = gamma_bus[18]; +wire [9:0] gamma_wr_addr = gamma_bus[17:8]; +wire [7:0] gamma_value = gamma_bus[7:0]; + +always @(posedge clk_sys) if (gamma_wr) begin + case(gamma_wr_addr[9:8]) + 0: gamma_curve_r[gamma_wr_addr[7:0]] <= gamma_value; + 1: gamma_curve_g[gamma_wr_addr[7:0]] <= gamma_value; + 2: gamma_curve_b[gamma_wr_addr[7:0]] <= gamma_value; + endcase +end + +reg [7:0] gamma_index_r,gamma_index_g,gamma_index_b; + +always @(posedge clk_vid) begin + reg [7:0] R_in, G_in, B_in; + reg [7:0] R_gamma, G_gamma; + reg hs,vs,hb,vb,de; + + if(ce_pix) begin + {gamma_index_r,gamma_index_g,gamma_index_b} <= RGB_in; + hs <= HSync; vs <= VSync; + hb <= HBlank; vb <= VBlank; + de <= DE; + + RGB_out <= gamma_en ? {gamma_curve_r[gamma_index_r],gamma_curve_g[gamma_index_g],gamma_curve_b[gamma_index_b]} + : {gamma_index_r,gamma_index_g,gamma_index_b}; + HSync_out <= hs; VSync_out <= vs; + HBlank_out <= hb; VBlank_out <= vb; + DE_out <= de; + end +end + +endmodule diff --git a/sys/hdmi_config.sv b/sys/hdmi_config.sv new file mode 100644 index 0000000..4a0a13d --- /dev/null +++ b/sys/hdmi_config.sv @@ -0,0 +1,239 @@ + +module hdmi_config +( + // Host Side + input iCLK, + input iRST_N, + + input dvi_mode, + input audio_96k, + input [1:0] limited, + input ypbpr, + + output reg done, + + // I2C Side + output I2C_SCL, + inout I2C_SDA +); + +// Internal Registers/Wires +reg mI2C_GO = 0; +wire mI2C_END; +wire mI2C_ACK; +reg [15:0] LUT_DATA; +reg [7:0] LUT_INDEX = 0; + +i2c #(50_000_000, 20_000) i2c_av +( + .CLK(iCLK), + + .I2C_SCL(I2C_SCL), // I2C CLOCK + .I2C_SDA(I2C_SDA), // I2C DATA + + .I2C_ADDR('h39), // 0x39 is the Slave Address of the ADV7513 chip! + .I2C_WLEN(1), + .I2C_WDATA1(init_data[LUT_INDEX][15:8]), // SUB_ADDR + .I2C_WDATA2(init_data[LUT_INDEX][7:0]), // DATA + .START(mI2C_GO), // START transfer + .READ(0), + .END(mI2C_END), // END transfer + .ACK(mI2C_ACK) // ACK +); + +////////////////////// Config Control //////////////////////////// +always@(posedge iCLK or negedge iRST_N) begin + reg [1:0] mSetup_ST = 0; + + if(!iRST_N) begin + LUT_INDEX <= 0; + mSetup_ST <= 0; + mI2C_GO <= 0; + done <= 0; + end else begin + if(init_data[LUT_INDEX] != 16'hFFFF) begin + case(mSetup_ST) + 0: begin + mI2C_GO <= 1; + mSetup_ST <= 1; + end + 1: if(~mI2C_END) mSetup_ST <= 2; + 2: begin + mI2C_GO <= 0; + if(mI2C_END) begin + mSetup_ST <= 0; + if(!mI2C_ACK) LUT_INDEX <= LUT_INDEX + 8'd1; + end + end + endcase + end + else done <= 1; + end +end + +//////////////////////////////////////////////////////////////////// +///////////////////// Config Data LUT ////////////////////////// + +wire [15:0] init_data[82] = +'{ + 16'h9803, // ADI required Write. + + {8'hD6, 8'b1100_0000}, // [7:6] HPD Control... + // 00 = HPD is from both HPD pin or CDC HPD + // 01 = HPD is from CDC HPD + // 10 = HPD is from HPD pin + // 11 = HPD is always high + + 16'h4110, // Power Down control + 16'h9A70, // ADI required Write. + 16'h9C30, // ADI required Write. + {8'h9D, 8'b0110_0001}, // [7:4] must be b0110!. + // [3:2] b00 = Input clock not divided. b01 = Clk divided by 2. b10 = Clk divided by 4. b11 = invalid! + // [1:0] must be b01! + 16'hA2A4, // ADI required Write. + 16'hA3A4, // ADI required Write. + 16'hE0D0, // ADI required Write. + + + 16'h35_40, + 16'h36_D9, + 16'h37_0A, + 16'h38_00, + 16'h39_2D, + 16'h3A_00, + + {8'h16, 8'b0011_1000}, // Output Format 444 [7]=0. + // [6] must be 0! + // Colour Depth for Input Video data [5:4] b11 = 8-bit. + // Input Style [3:2] b10 = Style 1 (ignored when using 444 input). + // DDR Input Edge falling [1]=0 (not using DDR atm). + // Output Colour Space RGB [0]=0. + + {8'h17, 8'b01100010}, // Aspect ratio 16:9 [1]=1, 4:3 [1]=0 + + {8'h18, ypbpr ? 8'h86 : limited[0] ? 8'h8D : limited[1] ? 8'h8E : 8'h00}, // CSC Scaling Factors and Coefficients for RGB Full->Limited. + {8'h19, ypbpr ? 8'hDF : limited[0] ? 8'hBC : 8'hFE}, // Taken from table in ADV7513 Programming Guide. + {8'h1A, ypbpr ? 8'h1A : 8'h00}, // CSC Channel A. + {8'h1B, ypbpr ? 8'h3F : 8'h00}, + {8'h1C, ypbpr ? 8'h1E : 8'h00}, + {8'h1D, ypbpr ? 8'hE2 : 8'h00}, + {8'h1E, ypbpr ? 8'h07 : 8'h01}, + {8'h1F, ypbpr ? 8'hE7 : 8'h00}, + + {8'h20, ypbpr ? 8'h04 : 8'h00}, // CSC Channel B. + {8'h21, ypbpr ? 8'h1C : 8'h00}, + {8'h22, ypbpr ? 8'h08 : limited[0] ? 8'h0D : 8'h0E}, + {8'h23, ypbpr ? 8'h11 : limited[0] ? 8'hBC : 8'hFE}, + {8'h24, ypbpr ? 8'h01 : 8'h00}, + {8'h25, ypbpr ? 8'h91 : 8'h00}, + {8'h26, ypbpr ? 8'h01 : 8'h01}, + {8'h27, 8'h00}, + + {8'h28, ypbpr ? 8'h1D : 8'h00}, // CSC Channel C. + {8'h29, ypbpr ? 8'hAE : 8'h00}, + {8'h2A, ypbpr ? 8'h1B : 8'h00}, + {8'h2B, ypbpr ? 8'h73 : 8'h00}, + {8'h2C, ypbpr ? 8'h06 : limited[0] ? 8'h0D : 8'h0E}, + {8'h2D, ypbpr ? 8'hDF : limited[0] ? 8'hBC : 8'hFE}, + {8'h2E, ypbpr ? 8'h07 : 8'h01}, + {8'h2F, ypbpr ? 8'hE7 : 8'h00}, + + {8'h3B, 8'b0000_0000}, // Pixel repetition [6:5] b00 AUTO. [4:3] b00 x1 mult of input clock. [2:1] b00 x1 pixel rep to send to HDMI Rx. + + 16'h4000, // General Control Packet Enable + + {8'h48, 8'b0000_1000}, // [6]=0 Normal bus order! + // [5] DDR Alignment. + // [4:3] b01 Data right justified (for YCbCr 422 input modes). + + 16'h49A8, // ADI required Write. + 16'h4C00, // ADI required Write. + + {8'h55, 8'b0001_0000}, // [7] must be 0!. Set RGB444 in AVinfo Frame [6:5], Set active format [4]. + // AVI InfoFrame Valid [4]. + // Bar Info [3:2] b00 Bars invalid. b01 Bars vertical. b10 Bars horizontal. b11 Bars both. + // Scan Info [1:0] b00 (No data). b01 TV. b10 PC. b11 None. + + {8'h57, 1'b0, // [7] IT Content. 0 - No. 1 - Yes (type set in register h59). + 3'b000, // [6:4] Color space (ignored for RGB) + (ypbpr | limited) ? 2'b01 : 2'b10, // [3:2] RGB Quantization range + 2'b00}, // [1:0] Non-Uniform Scaled: 00 - None. 01 - Horiz. 10 - Vert. 11 - Both. + + 16'h7301, + + {8'h94, 8'b1000_0000}, // [7]=1 HPD Interrupt ENabled. + + 16'h9902, // ADI required Write. + 16'h9B18, // ADI required Write. + + 16'h9F00, // ADI required Write. + + {8'hA1, 8'b0000_0000}, // [6]=1 Monitor Sense Power Down DISabled. + + 16'hA408, // ADI required Write. + 16'hA504, // ADI required Write. + 16'hA600, // ADI required Write. + 16'hA700, // ADI required Write. + 16'hA800, // ADI required Write. + 16'hA900, // ADI required Write. + 16'hAA00, // ADI required Write. + 16'hAB40, // ADI required Write. + + {8'hAF, 6'b0000_01,~dvi_mode,1'b0}, // [7]=0 HDCP Disabled. + // [6:5] must be b00! + // [4]=0 Current frame is unencrypted + // [3:2] must be b01! + // [1]=1 HDMI Mode. + // [0] must be b0! + + 16'hB900, // ADI required Write. + + {8'hBA, 8'b0110_0000}, // [7:5] Input Clock delay... + // b000 = -1.2ns. + // b001 = -0.8ns. + // b010 = -0.4ns. + // b011 = No delay. + // b100 = 0.4ns. + // b101 = 0.8ns. + // b110 = 1.2ns. + // b111 = 1.6ns. + + 16'hBB00, // ADI required Write. + + 16'hDE9C, // ADI required Write. + 16'hE460, // ADI required Write. + 16'hFA7D, // Nbr of times to search for good phase + + + // (Audio stuff on Programming Guide, Page 66)... + + {8'h0A, 8'b0000_0000}, // [6:4] Audio Select. b000 = I2S. + // [3:2] Audio Mode. (HBR stuff, leave at 00!). + + {8'h0B, 8'b0000_1110}, // + + {8'h0C, 8'b0000_0100}, // [7] 0 = Use sampling rate from I2S stream. 1 = Use samp rate from I2C Register. + // [6] 0 = Use Channel Status bits from stream. 1 = Use Channel Status bits from I2C register. + // [2] 1 = I2S0 Enable. + // [1:0] I2S Format: 00 = Standard. 01 = Right Justified. 10 = Left Justified. 11 = AES. + + {8'h0D, 8'b0001_0000}, // [4:0] I2S Bit (Word) Width for Right-Justified. + {8'h14, 8'b0000_0010}, // [3:0] Audio Word Length. b0010 = 16 bits. + {8'h15, audio_96k, 7'b010_0000}, // I2S Sampling Rate [7:4]. b0000 = (44.1KHz). b0010 = 48KHz. + // Input ID [3:1] b000 (0) = 24-bit RGB 444 or YCrCb 444 with Separate Syncs. + + // Audio Clock Config + 16'h0100, // + audio_96k ? 16'h0230 : 16'h0218, // Set N Value 12288/6144 + 16'h0300, // + + 16'h0701, // + 16'h0822, // Set CTS Value 74250 + 16'h090A, // + + 16'hFFFF // END +}; + +//////////////////////////////////////////////////////////////////// + +endmodule \ No newline at end of file diff --git a/sys/hps_io.sv b/sys/hps_io.sv new file mode 100644 index 0000000..864f1bd --- /dev/null +++ b/sys/hps_io.sv @@ -0,0 +1,999 @@ +// +// hps_io.v +// +// Copyright (c) 2014 Till Harbaum +// Copyright (c) 2017-2020 Alexey Melnikov +// +// This source file is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This source file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////// +// altera message_off 10665 + +// +// Use buffer to access SD card. It's time-critical part. +// +// WIDE=1 for 16 bit file I/O +// VDNUM 1..10 +// BLKSZ 0..7: 0 = 128, 1 = 256, 2 = 512(default), .. 7 = 16384 +// +module hps_io #(parameter CONF_STR, CONF_STR_BRAM=1, PS2DIV=0, WIDE=0, VDNUM=1, BLKSZ=2, PS2WE=0) +( + input clk_sys, + inout [48:0] HPS_BUS, + + // buttons up to 32 + output reg [31:0] joystick_0, + output reg [31:0] joystick_1, + output reg [31:0] joystick_2, + output reg [31:0] joystick_3, + output reg [31:0] joystick_4, + output reg [31:0] joystick_5, + + // analog -127..+127, Y: [15:8], X: [7:0] + output reg [15:0] joystick_l_analog_0, + output reg [15:0] joystick_l_analog_1, + output reg [15:0] joystick_l_analog_2, + output reg [15:0] joystick_l_analog_3, + output reg [15:0] joystick_l_analog_4, + output reg [15:0] joystick_l_analog_5, + + output reg [15:0] joystick_r_analog_0, + output reg [15:0] joystick_r_analog_1, + output reg [15:0] joystick_r_analog_2, + output reg [15:0] joystick_r_analog_3, + output reg [15:0] joystick_r_analog_4, + output reg [15:0] joystick_r_analog_5, + + input [15:0] joystick_0_rumble, // 15:8 - 'large' rumble motor magnitude, 7:0 'small' rumble motor magnitude + input [15:0] joystick_1_rumble, + input [15:0] joystick_2_rumble, + input [15:0] joystick_3_rumble, + input [15:0] joystick_4_rumble, + input [15:0] joystick_5_rumble, + + // paddle 0..255 + output reg [7:0] paddle_0, + output reg [7:0] paddle_1, + output reg [7:0] paddle_2, + output reg [7:0] paddle_3, + output reg [7:0] paddle_4, + output reg [7:0] paddle_5, + + // spinner [7:0] -128..+127, [8] - toggle with every update + output reg [8:0] spinner_0, + output reg [8:0] spinner_1, + output reg [8:0] spinner_2, + output reg [8:0] spinner_3, + output reg [8:0] spinner_4, + output reg [8:0] spinner_5, + + // ps2 keyboard emulation + output ps2_kbd_clk_out, + output ps2_kbd_data_out, + input ps2_kbd_clk_in, + input ps2_kbd_data_in, + + input [2:0] ps2_kbd_led_status, + input [2:0] ps2_kbd_led_use, + + output ps2_mouse_clk_out, + output ps2_mouse_data_out, + input ps2_mouse_clk_in, + input ps2_mouse_data_in, + + // ps2 alternative interface. + + // [8] - extended, [9] - pressed, [10] - toggles with every press/release + output reg [10:0] ps2_key = 0, + + // [24] - toggles with every event + output reg [24:0] ps2_mouse = 0, + output reg [15:0] ps2_mouse_ext = 0, // 15:8 - reserved(additional buttons), 7:0 - wheel movements + + output [1:0] buttons, + output forced_scandoubler, + output direct_video, + input video_rotated, + + //toggle to force notify of video mode change + input new_vmode, + + inout [21:0] gamma_bus, + + output reg [63:0] status, + input [63:0] status_in, + input status_set, + input [15:0] status_menumask, + + input info_req, + input [7:0] info, + + // SD config + output reg [VD:0] img_mounted, // signaling that new image has been mounted + output reg img_readonly, // mounted as read only. valid only for active bit in img_mounted + output reg [63:0] img_size, // size of image in bytes. valid only for active bit in img_mounted + + // SD block level access + input [31:0] sd_lba[VDNUM], + input [5:0] sd_blk_cnt[VDNUM], // number of blocks-1, total size ((sd_blk_cnt+1)*(1<<(BLKSZ+7))) must be <= 16384! + input [VD:0] sd_rd, + input [VD:0] sd_wr, + output reg [VD:0] sd_ack, + + // SD byte level access. Signals for 2-PORT altsyncram. + output reg [AW:0] sd_buff_addr, + output reg [DW:0] sd_buff_dout, + input [DW:0] sd_buff_din[VDNUM], + output reg sd_buff_wr, + + // ARM -> FPGA download + output reg ioctl_download = 0, // signal indicating an active download + output reg [15:0] ioctl_index, // menu index used to upload the file + output reg ioctl_wr, + output reg [26:0] ioctl_addr, // in WIDE mode address will be incremented by 2 + output reg [DW:0] ioctl_dout, + output reg ioctl_upload = 0, // signal indicating an active upload + input ioctl_upload_req, // request to save (must be supported on HPS side for specific core) + input [7:0] ioctl_upload_index, + input [DW:0] ioctl_din, + output reg ioctl_rd, + output reg [31:0] ioctl_file_ext, + input ioctl_wait, + + // [15]: 0 - unset, 1 - set. [1:0]: 0 - none, 1 - 32MB, 2 - 64MB, 3 - 128MB + // [14]: debug mode: [8]: 1 - phase up, 0 - phase down. [7:0]: amount of shift. + output reg [15:0] sdram_sz, + + // RTC MSM6242B layout + output reg [64:0] RTC, + + // Seconds since 1970-01-01 00:00:00 + output reg [32:0] TIMESTAMP, + + // UART flags + output reg [7:0] uart_mode, + output reg [31:0] uart_speed, + + // for core-specific extensions + inout [35:0] EXT_BUS +); + +assign EXT_BUS[31:16] = HPS_BUS[31:16]; +assign EXT_BUS[35:33] = HPS_BUS[35:33]; + +localparam DW = (WIDE) ? 15 : 7; +localparam AW = (WIDE) ? 12 : 13; +localparam VD = VDNUM-1; + +wire io_strobe= HPS_BUS[33]; +wire io_enable= HPS_BUS[34]; +wire fp_enable= HPS_BUS[35]; +wire io_wide = (WIDE) ? 1'b1 : 1'b0; +wire [15:0] io_din = HPS_BUS[31:16]; +reg [15:0] io_dout; + +assign HPS_BUS[37] = ioctl_wait; +assign HPS_BUS[36] = clk_sys; +assign HPS_BUS[32] = io_wide; +assign HPS_BUS[15:0] = EXT_BUS[32] ? EXT_BUS[15:0] : fp_enable ? fp_dout : io_dout; + +reg [15:0] cfg; +assign buttons = cfg[1:0]; +//cfg[2] - vga_scaler handled in sys_top +//cfg[3] - csync handled in sys_top +assign forced_scandoubler = cfg[4]; +//cfg[5] - ypbpr handled in sys_top +assign direct_video = cfg[10]; + +reg [3:0] sdn; +reg [3:0] sd_rrb = 0; +always_comb begin + int n, i; + + sdn = 0; + for(i = VDNUM - 1; i >= 0; i = i - 1) begin + n = i + sd_rrb; + if(n >= VDNUM) n = n - VDNUM; + if(sd_wr[n] | sd_rd[n]) sdn = n[3:0]; + end +end + +///////////////////////////////////////////////////////// + +wire [15:0] vc_dout; +video_calc video_calc +( + .clk_100(HPS_BUS[43]), + .clk_vid(HPS_BUS[42]), + .clk_sys(clk_sys), + .ce_pix(HPS_BUS[41]), + .de(HPS_BUS[40]), + .hs(HPS_BUS[39]), + .vs(HPS_BUS[38]), + .vs_hdmi(HPS_BUS[44]), + .f1(HPS_BUS[45]), + .new_vmode(new_vmode), + .video_rotated(video_rotated), + + .par_num(byte_cnt[3:0]), + .dout(vc_dout) +); + +///////////////////////////////////////////////////////// + +localparam STRLEN = $size(CONF_STR)>>3; +localparam MAX_W = $clog2((32 > (STRLEN+2)) ? 32 : (STRLEN+2))-1; + +wire [7:0] conf_byte; +generate + if(CONF_STR_BRAM) begin + confstr_rom #(CONF_STR, STRLEN) confstr_rom(.*, .conf_addr(byte_cnt - 1'd1)); + end + else begin + assign conf_byte = CONF_STR[{(STRLEN - byte_cnt),3'b000} +:8]; + end +endgenerate + +assign gamma_bus[20:0] = {clk_sys, gamma_en, gamma_wr, gamma_wr_addr, gamma_value}; +reg gamma_en; +reg gamma_wr; +reg [9:0] gamma_wr_addr; +reg [7:0] gamma_value; + +reg [31:0] ps2_key_raw = 0; +wire pressed = (ps2_key_raw[15:8] != 8'hf0); +wire extended = (~pressed ? (ps2_key_raw[23:16] == 8'he0) : (ps2_key_raw[15:8] == 8'he0)); + +reg [MAX_W:0] byte_cnt; +reg [3:0] sdn_ack; +wire [15:0] disk = 16'd1 << io_din[11:8]; + +always@(posedge clk_sys) begin : uio_block + reg [15:0] cmd; + reg [2:0] b_wr; + reg [3:0] stick_idx; + reg [3:0] pdsp_idx; + reg ps2skip = 0; + reg [3:0] stflg = 0; + reg [63:0] status_req; + reg old_status_set = 0; + reg old_upload_req = 0; + reg upload_req = 0; + reg old_info = 0; + reg [7:0] info_n = 0; + reg [15:0] tmp1; + reg [7:0] tmp2; + reg [3:0] sdn_r; + + old_status_set <= status_set; + if(~old_status_set & status_set) begin + stflg <= stflg + 1'd1; + status_req <= status_in; + end + + old_upload_req <= ioctl_upload_req; + if(~old_upload_req & ioctl_upload_req) upload_req <= 1; + + old_info <= info_req; + if(~old_info & info_req) info_n <= info; + + sd_buff_wr <= b_wr[0]; + if(b_wr[2] && (~&sd_buff_addr)) sd_buff_addr <= sd_buff_addr + 1'b1; + b_wr <= (b_wr<<1); + + if(PS2DIV) {kbd_rd,kbd_we,mouse_rd,mouse_we} <= 0; + + gamma_wr <= 0; + + if(~io_enable) begin + if(cmd == 4 && !ps2skip) ps2_mouse[24] <= ~ps2_mouse[24]; + if(cmd == 5 && !ps2skip) begin + ps2_key <= {~ps2_key[10], pressed, extended, ps2_key_raw[7:0]}; + if(ps2_key_raw == 'hE012E07C) ps2_key[9:0] <= 'h37C; // prnscr pressed + if(ps2_key_raw == 'h7CE0F012) ps2_key[9:0] <= 'h17C; // prnscr released + if(ps2_key_raw == 'hF014F077) ps2_key[9:0] <= 'h377; // pause pressed + end + if(cmd == 'h22) RTC[64] <= ~RTC[64]; + if(cmd == 'h24) TIMESTAMP[32] <= ~TIMESTAMP[32]; + cmd <= 0; + byte_cnt <= 0; + sd_ack <= 0; + io_dout <= 0; + ps2skip <= 0; + img_mounted <= 0; + end + else if(io_strobe) begin + + io_dout <= 0; + if(~&byte_cnt) byte_cnt <= byte_cnt + 1'd1; + + if(byte_cnt == 0) begin + cmd <= io_din; + + casex(io_din) + 'h16: begin io_dout <= {1'b1, sd_blk_cnt[sdn], BLKSZ[2:0], sdn, sd_wr[sdn], sd_rd[sdn]}; sdn_r <= sdn; end + 'h0X17, + 'h0X18: begin sd_ack <= disk[VD:0]; sdn_ack <= io_din[11:8]; end + 'h29: io_dout <= {4'hA, stflg}; +`ifdef MISTER_DISABLE_ADAPTIVE + 'h2B: io_dout <= {HPS_BUS[48:46],4'b0110}; +`else + 'h2B: io_dout <= {HPS_BUS[48:46],4'b0111}; +`endif + 'h2F: io_dout <= 1; + 'h32: io_dout <= gamma_bus[21]; + 'h36: begin io_dout <= info_n; info_n <= 0; end + 'h39: io_dout <= 1; + 'h3C: if(upload_req) begin io_dout <= {ioctl_upload_index, 8'd1}; upload_req <= 0; end + 'h3E: io_dout <= 1; // shadow mask + 'h003F: io_dout <= joystick_0_rumble; + 'h013F: io_dout <= joystick_1_rumble; + 'h023F: io_dout <= joystick_2_rumble; + 'h033F: io_dout <= joystick_3_rumble; + 'h043F: io_dout <= joystick_4_rumble; + 'h053F: io_dout <= joystick_5_rumble; + endcase + + sd_buff_addr <= 0; + if(io_din == 5) ps2_key_raw <= 0; + end else begin + + casex(cmd) + // buttons and switches + 'h01: cfg <= io_din; + 'h02: if(byte_cnt==1) joystick_0[15:0] <= io_din; else joystick_0[31:16] <= io_din; + 'h03: if(byte_cnt==1) joystick_1[15:0] <= io_din; else joystick_1[31:16] <= io_din; + 'h10: if(byte_cnt==1) joystick_2[15:0] <= io_din; else joystick_2[31:16] <= io_din; + 'h11: if(byte_cnt==1) joystick_3[15:0] <= io_din; else joystick_3[31:16] <= io_din; + 'h12: if(byte_cnt==1) joystick_4[15:0] <= io_din; else joystick_4[31:16] <= io_din; + 'h13: if(byte_cnt==1) joystick_5[15:0] <= io_din; else joystick_5[31:16] <= io_din; + + // store incoming ps2 mouse bytes + 'h04: begin + if(PS2DIV) begin + mouse_data <= io_din[7:0]; + mouse_we <= 1; + end + if(&io_din[15:8]) ps2skip <= 1; + if(~&io_din[15:8] && ~ps2skip && !byte_cnt[MAX_W:2]) begin + case(byte_cnt[1:0]) + 1: ps2_mouse[7:0] <= io_din[7:0]; + 2: ps2_mouse[15:8] <= io_din[7:0]; + 3: ps2_mouse[23:16] <= io_din[7:0]; + endcase + case(byte_cnt[1:0]) + 1: ps2_mouse_ext[7:0] <= {io_din[14], io_din[14:8]}; + 2: ps2_mouse_ext[11:8] <= io_din[11:8]; + 3: ps2_mouse_ext[15:12]<= io_din[11:8]; + endcase + end + end + + // store incoming ps2 keyboard bytes + 'h05: begin + if(&io_din[15:8]) ps2skip <= 1; + if(~&io_din[15:8] & ~ps2skip) ps2_key_raw[31:0] <= {ps2_key_raw[23:0], io_din[7:0]}; + if(PS2DIV) begin + kbd_data <= io_din[7:0]; + kbd_we <= 1; + end + end + + // reading config string, returning a byte from string + 'h14: if(byte_cnt <= STRLEN) io_dout[7:0] <= conf_byte; + + // reading sd card status + 'h16: if(!byte_cnt[MAX_W:2]) begin + case(byte_cnt[1:0]) + 1: sd_rrb <= (sd_rrb == VD) ? 4'd0 : (sd_rrb + 1'd1); + 2: io_dout <= sd_lba[sdn_r][15:0]; + 3: io_dout <= sd_lba[sdn_r][31:16]; + endcase + end + + // send sector IO -> FPGA + // flag that download begins + 'h0X17: begin + sd_buff_dout <= io_din[DW:0]; + b_wr <= 1; + end + + // reading sd card write data + 'h0X18: begin + if(~&sd_buff_addr) sd_buff_addr <= sd_buff_addr + 1'b1; + io_dout <= sd_buff_din[sdn_ack]; + end + + // joystick left analog + 'h1a: if(!byte_cnt[MAX_W:2]) begin + case(byte_cnt[1:0]) + 1: {pdsp_idx,stick_idx} <= io_din[7:0]; // first byte is joystick index + 2: case(stick_idx) + 0: joystick_l_analog_0 <= io_din; + 1: joystick_l_analog_1 <= io_din; + 2: joystick_l_analog_2 <= io_din; + 3: joystick_l_analog_3 <= io_din; + 4: joystick_l_analog_4 <= io_din; + 5: joystick_l_analog_5 <= io_din; + 15: case(pdsp_idx) + 0: paddle_0 <= io_din[7:0]; + 1: paddle_1 <= io_din[7:0]; + 2: paddle_2 <= io_din[7:0]; + 3: paddle_3 <= io_din[7:0]; + 4: paddle_4 <= io_din[7:0]; + 5: paddle_5 <= io_din[7:0]; + 8: spinner_0 <= {~spinner_0[8],io_din[7:0]}; + 9: spinner_1 <= {~spinner_1[8],io_din[7:0]}; + 10: spinner_2 <= {~spinner_2[8],io_din[7:0]}; + 11: spinner_3 <= {~spinner_3[8],io_din[7:0]}; + 12: spinner_4 <= {~spinner_4[8],io_din[7:0]}; + 13: spinner_5 <= {~spinner_5[8],io_din[7:0]}; + endcase + endcase + endcase + end + + // joystick right analog + 'h3d: if(!byte_cnt[MAX_W:2]) begin + case(byte_cnt[1:0]) + 1: stick_idx <= io_din[3:0]; // first byte is joystick index + 2: case(stick_idx) + 0: joystick_r_analog_0 <= io_din; + 1: joystick_r_analog_1 <= io_din; + 2: joystick_r_analog_2 <= io_din; + 3: joystick_r_analog_3 <= io_din; + 4: joystick_r_analog_4 <= io_din; + 5: joystick_r_analog_5 <= io_din; + endcase + endcase + end + + // notify image selection + 'h1c: begin + img_mounted <= io_din[VD:0] ? io_din[VD:0] : 1'b1; + img_readonly <= io_din[7]; + end + + // send image info + 'h1d: if(byte_cnt<5) img_size[{byte_cnt-1'b1, 4'b0000} +:16] <= io_din; + + // status, 64bit version + 'h1e: if(!byte_cnt[MAX_W:3]) begin + case(byte_cnt[2:0]) + 1: status[15:00] <= io_din; + 2: status[31:16] <= io_din; + 3: status[47:32] <= io_din; + 4: status[63:48] <= io_din; + endcase + end + + // reading keyboard LED status + 'h1f: io_dout <= {|PS2WE, 2'b01, ps2_kbd_led_status[2], ps2_kbd_led_use[2], ps2_kbd_led_status[1], ps2_kbd_led_use[1], ps2_kbd_led_status[0], ps2_kbd_led_use[0]}; + + // reading ps2 keyboard/mouse control + 'h21: if(PS2DIV) begin + if(byte_cnt == 1) begin + io_dout <= kbd_data_host; + kbd_rd <= 1; + end + else + if(byte_cnt == 2) begin + io_dout <= mouse_data_host; + mouse_rd <= 1; + end + end + + //RTC + 'h22: RTC[(byte_cnt-6'd1)<<4 +:16] <= io_din; + + //Video res. + 'h23: if(!byte_cnt[MAX_W:4]) io_dout <= vc_dout; + + //RTC + 'h24: TIMESTAMP[(byte_cnt-6'd1)<<4 +:16] <= io_din; + + //status set + 'h29: if(!byte_cnt[MAX_W:3]) begin + case(byte_cnt[2:0]) + 1: io_dout <= status_req[15:00]; + 2: io_dout <= status_req[31:16]; + 3: io_dout <= status_req[47:32]; + 4: io_dout <= status_req[63:48]; + endcase + end + + //menu mask + 'h2E: if(byte_cnt == 1) io_dout <= status_menumask; + + //sdram size set + 'h31: if(byte_cnt == 1) sdram_sz <= io_din; + + // Gamma + 'h32: gamma_en <= io_din[0]; + 'h33: begin + gamma_wr_addr <= {(byte_cnt[1:0]-1'b1),io_din[15:8]}; + {gamma_wr, gamma_value} <= {1'b1,io_din[7:0]}; + if (byte_cnt[1:0] == 3) byte_cnt <= 1; + end + + // UART + 'h3b: if(!byte_cnt[MAX_W:2]) begin + case(byte_cnt[1:0]) + 1: tmp2 <= io_din[7:0]; + 2: tmp1 <= io_din; + 3: {uart_speed, uart_mode} <= {io_din, tmp1, tmp2}; + endcase + end + endcase + end + end +end + + +/////////////////////////////// PS2 /////////////////////////////// +generate + if(PS2DIV) begin + reg clk_ps2; + always @(posedge clk_sys) begin + integer cnt; + cnt <= cnt + 1'd1; + if(cnt == PS2DIV) begin + clk_ps2 <= ~clk_ps2; + cnt <= 0; + end + end + + reg [7:0] kbd_data; + reg kbd_we; + wire [8:0] kbd_data_host; + reg kbd_rd; + + ps2_device keyboard + ( + .clk_sys(clk_sys), + + .wdata(kbd_data), + .we(kbd_we), + + .ps2_clk(clk_ps2), + .ps2_clk_out(ps2_kbd_clk_out), + .ps2_dat_out(ps2_kbd_data_out), + + .ps2_clk_in(ps2_kbd_clk_in || !PS2WE), + .ps2_dat_in(ps2_kbd_data_in || !PS2WE), + + .rdata(kbd_data_host), + .rd(kbd_rd) + ); + + reg [7:0] mouse_data; + reg mouse_we; + wire [8:0] mouse_data_host; + reg mouse_rd; + + ps2_device mouse + ( + .clk_sys(clk_sys), + + .wdata(mouse_data), + .we(mouse_we), + + .ps2_clk(clk_ps2), + .ps2_clk_out(ps2_mouse_clk_out), + .ps2_dat_out(ps2_mouse_data_out), + + .ps2_clk_in(ps2_mouse_clk_in || !PS2WE), + .ps2_dat_in(ps2_mouse_data_in || !PS2WE), + + .rdata(mouse_data_host), + .rd(mouse_rd) + ); + end + else begin + assign ps2_kbd_clk_out = 0; + assign ps2_kbd_data_out = 0; + assign ps2_mouse_clk_out = 0; + assign ps2_mouse_data_out = 0; + end +endgenerate + +/////////////////////////////// DOWNLOADING /////////////////////////////// + +localparam FIO_FILE_TX = 8'h53; +localparam FIO_FILE_TX_DAT = 8'h54; +localparam FIO_FILE_INDEX = 8'h55; +localparam FIO_FILE_INFO = 8'h56; + +reg [15:0] fp_dout; +always@(posedge clk_sys) begin : fio_block + reg [15:0] cmd; + reg [2:0] cnt; + reg has_cmd; + reg [26:0] addr; + reg wr; + + ioctl_rd <= 0; + ioctl_wr <= wr; + wr <= 0; + + if(~fp_enable) has_cmd <= 0; + else begin + if(io_strobe) begin + + if(!has_cmd) begin + cmd <= io_din; + has_cmd <= 1; + cnt <= 0; + end else begin + + case(cmd) + FIO_FILE_INFO: + if(~cnt[1]) begin + case(cnt) + 0: ioctl_file_ext[31:16] <= io_din; + 1: ioctl_file_ext[15:00] <= io_din; + endcase + cnt <= cnt + 1'd1; + end + + FIO_FILE_INDEX: + begin + ioctl_index <= io_din[15:0]; + end + + FIO_FILE_TX: + begin + cnt <= cnt + 1'd1; + case(cnt) + 0: if(io_din[7:0] == 8'hAA) begin + ioctl_addr <= 0; + ioctl_upload <= 1; + ioctl_rd <= 1; + end + else if(io_din[7:0]) begin + addr <= 0; + ioctl_download <= 1; + end + else begin + if(ioctl_download) ioctl_addr <= addr; + ioctl_download <= 0; + ioctl_upload <= 0; + end + + 1: begin + ioctl_addr[15:0] <= io_din; + addr[15:0] <= io_din; + end + + 2: begin + ioctl_addr[26:16] <= io_din[10:0]; + addr[26:16] <= io_din[10:0]; + end + endcase + end + + FIO_FILE_TX_DAT: + if(ioctl_download) begin + ioctl_addr <= addr; + ioctl_dout <= io_din[DW:0]; + wr <= 1; + addr <= addr + (WIDE ? 2'd2 : 2'd1); + end + else begin + ioctl_addr <= ioctl_addr + (WIDE ? 2'd2 : 2'd1); + fp_dout <= ioctl_din; + ioctl_rd <= 1; + end + endcase + end + end + end +end + +endmodule + +////////////////////////////////////////////////////////////////////////////////// + + +module ps2_device #(parameter PS2_FIFO_BITS=5) +( + input clk_sys, + + input [7:0] wdata, + input we, + + input ps2_clk, + output reg ps2_clk_out, + output reg ps2_dat_out, + output reg tx_empty, + + input ps2_clk_in, + input ps2_dat_in, + + output [8:0] rdata, + input rd +); + + +(* ramstyle = "logic" *) reg [7:0] fifo[1<= 1)&&(tx_state < 9)) begin + ps2_dat_out <= tx_byte[0]; // data bits + tx_byte[6:0] <= tx_byte[7:1]; // shift down + if(tx_byte[0]) + parity <= !parity; + end + + // transmission of parity + if(tx_state == 9) ps2_dat_out <= parity; + + // transmission of stop bit + if(tx_state == 10) ps2_dat_out <= 1; // stop bit is 1 + + // advance state machine + if(tx_state < 11) tx_state <= tx_state + 1'd1; + else tx_state <= 0; + end + end + end + + if(~old_clk & ps2_clk) ps2_clk_out <= 1; + if(old_clk & ~ps2_clk) ps2_clk_out <= ((tx_state == 0) && (rx_state<2)); + +end + +endmodule + + +///////////////// calc video parameters ////////////////// +module video_calc +( + input clk_100, + input clk_vid, + input clk_sys, + + input ce_pix, + input de, + input hs, + input vs, + input vs_hdmi, + input f1, + input new_vmode, + input video_rotated, + + input [3:0] par_num, + output reg [15:0] dout +); + +always @(posedge clk_sys) begin + case(par_num) + 1: dout <= {video_rotated, |vid_int, vid_nres}; + 2: dout <= vid_hcnt[15:0]; + 3: dout <= vid_hcnt[31:16]; + 4: dout <= vid_vcnt[15:0]; + 5: dout <= vid_vcnt[31:16]; + 6: dout <= vid_htime[15:0]; + 7: dout <= vid_htime[31:16]; + 8: dout <= vid_vtime[15:0]; + 9: dout <= vid_vtime[31:16]; + 10: dout <= vid_pix[15:0]; + 11: dout <= vid_pix[31:16]; + 12: dout <= vid_vtime_hdmi[15:0]; + 13: dout <= vid_vtime_hdmi[31:16]; + default dout <= 0; + endcase +end + +reg [31:0] vid_hcnt = 0; +reg [31:0] vid_vcnt = 0; +reg [7:0] vid_nres = 0; +reg [1:0] vid_int = 0; + +always @(posedge clk_vid) begin + integer hcnt; + integer vcnt; + reg old_vs= 0, old_de = 0, old_vmode = 0; + reg [3:0] resto = 0; + reg calch = 0; + + if(ce_pix) begin + old_vs <= vs; + old_de <= de; + + if(~vs & ~old_de & de) vcnt <= vcnt + 1; + if(calch & de) hcnt <= hcnt + 1; + if(old_de & ~de) calch <= 0; + + if(old_vs & ~vs) begin + vid_int <= {vid_int[0],f1}; + if(~f1) begin + if(hcnt && vcnt) begin + old_vmode <= new_vmode; + + //report new resolution after timeout + if(resto) resto <= resto + 1'd1; + if(vid_hcnt != hcnt || vid_vcnt != vcnt || old_vmode != new_vmode) resto <= 1; + if(&resto) vid_nres <= vid_nres + 1'd1; + vid_hcnt <= hcnt; + vid_vcnt <= vcnt; + end + vcnt <= 0; + hcnt <= 0; + calch <= 1; + end + end + end +end + +reg [31:0] vid_htime = 0; +reg [31:0] vid_vtime = 0; +reg [31:0] vid_pix = 0; + +always @(posedge clk_100) begin + integer vtime, htime, hcnt; + reg old_vs, old_hs, old_vs2, old_hs2, old_de, old_de2; + reg calch = 0; + + old_vs <= vs; + old_hs <= hs; + + old_vs2 <= old_vs; + old_hs2 <= old_hs; + + vtime <= vtime + 1'd1; + htime <= htime + 1'd1; + + if(~old_vs2 & old_vs) begin + vid_pix <= hcnt; + vid_vtime <= vtime; + vtime <= 0; + hcnt <= 0; + end + + if(old_vs2 & ~old_vs) calch <= 1; + + if(~old_hs2 & old_hs) begin + vid_htime <= htime; + htime <= 0; + end + + old_de <= de; + old_de2 <= old_de; + + if(calch & old_de) hcnt <= hcnt + 1; + if(old_de2 & ~old_de) calch <= 0; +end + +reg [31:0] vid_vtime_hdmi; +always @(posedge clk_100) begin + integer vtime; + reg old_vs, old_vs2; + + old_vs <= vs_hdmi; + old_vs2 <= old_vs; + + vtime <= vtime + 1'd1; + + if(~old_vs2 & old_vs) begin + vid_vtime_hdmi <= vtime; + vtime <= 0; + end +end + +endmodule + +module confstr_rom #(parameter CONF_STR, STRLEN) +( + input clk_sys, + input [$clog2(STRLEN+1)-1:0] conf_addr, + output reg [7:0] conf_byte +); + +wire [7:0] rom[STRLEN]; +initial for(int i = 0; i < STRLEN; i++) rom[i] = CONF_STR[((STRLEN-i)*8)-1 -:8]; +always @ (posedge clk_sys) conf_byte <= rom[conf_addr]; + +endmodule diff --git a/sys/hq2x.sv b/sys/hq2x.sv new file mode 100644 index 0000000..f5fcc71 --- /dev/null +++ b/sys/hq2x.sv @@ -0,0 +1,371 @@ +// +// +// Copyright (c) 2012-2013 Ludvig Strigeus +// Copyright (c) 2017,2018 Sorgelig +// +// This program is GPL Licensed. See COPYING for the full license. +// +// +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +// altera message_off 10030 + +module Hq2x #(parameter LENGTH, parameter HALF_DEPTH) +( + input clk, + + input ce_in, + input [DWIDTH:0] inputpixel, + input mono, + input disable_hq2x, + input reset_frame, + input reset_line, + + input ce_out, + input [1:0] read_y, + input hblank, + output [DWIDTH:0] outpixel +); + + +localparam AWIDTH = $clog2(LENGTH)-1; +localparam DWIDTH = HALF_DEPTH ? 11 : 23; +localparam DWIDTH1 = DWIDTH+1; + +(* romstyle = "MLAB" *) reg [5:0] hqTable[256]; +initial begin + hqTable = '{ + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 47, 35, 23, 15, 55, 39, + 19, 19, 26, 58, 19, 19, 26, 58, 23, 15, 35, 35, 23, 15, 7, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 55, 39, 23, 15, 51, 43, + 19, 19, 26, 58, 19, 19, 26, 58, 23, 15, 51, 35, 23, 15, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 61, 35, 35, 23, 61, 51, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 51, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 61, 7, 35, 23, 61, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 58, 23, 15, 51, 35, 23, 61, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 47, 35, 23, 15, 55, 39, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 51, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 55, 39, 23, 15, 51, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 39, 23, 15, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 51, 39, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 7, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 7, 35, 23, 15, 7, 43 + }; +end + +wire [5:0] hqrule = hqTable[nextpatt]; + +reg [23:0] Prev0, Prev1, Prev2, Curr0, Curr1, Curr2, Next0, Next1, Next2; +reg [23:0] A, B, D, F, G, H; +reg [7:0] pattern, nextpatt; +reg [1:0] cyc; + +reg curbuf; +reg prevbuf = 0; +wire iobuf = !curbuf; + +wire diff0, diff1; +DiffCheck diffcheck0(Curr1, (cyc == 0) ? Prev0 : (cyc == 1) ? Curr0 : (cyc == 2) ? Prev2 : Next1, diff0); +DiffCheck diffcheck1(Curr1, (cyc == 0) ? Prev1 : (cyc == 1) ? Next0 : (cyc == 2) ? Curr2 : Next2, diff1); + +wire [7:0] new_pattern = {diff1, diff0, pattern[7:2]}; + +wire [23:0] X = (cyc == 0) ? A : (cyc == 1) ? Prev1 : (cyc == 2) ? Next1 : G; +wire [23:0] blend_result_pre; +Blend blender(clk, ce_in, disable_hq2x ? 6'd0 : hqrule, Curr0, X, B, D, F, H, blend_result_pre); + +wire [DWIDTH:0] Curr20tmp; +wire [23:0] Curr20 = HALF_DEPTH ? h2rgb(Curr20tmp) : Curr20tmp; +wire [DWIDTH:0] Curr21tmp; +wire [23:0] Curr21 = HALF_DEPTH ? h2rgb(Curr21tmp) : Curr21tmp; + +reg [AWIDTH:0] wrin_addr2; +reg [DWIDTH:0] wrpix; +reg wrin_en; + +function [23:0] h2rgb; + input [11:0] v; +begin + h2rgb = mono ? {v[7:0], v[7:0], v[7:0]} : {v[11:8],v[11:8],v[7:4],v[7:4],v[3:0],v[3:0]}; +end +endfunction + +function [11:0] rgb2h; + input [23:0] v; +begin + rgb2h = mono ? {4'b0000, v[23:20], v[19:16]} : {v[23:20], v[15:12], v[7:4]}; +end +endfunction + +hq2x_in #(.LENGTH(LENGTH), .DWIDTH(DWIDTH)) hq2x_in +( + .clk(clk), + + .rdaddr(offs), + .rdbuf0(prevbuf), + .rdbuf1(curbuf), + .q0(Curr20tmp), + .q1(Curr21tmp), + + .wraddr(wrin_addr2), + .wrbuf(iobuf), + .data(wrpix), + .wren(wrin_en) +); + +reg [AWIDTH+1:0] read_x; +reg [AWIDTH+1:0] wrout_addr; +reg wrout_en; +reg [DWIDTH1*4-1:0] wrdata, wrdata_pre; +wire [DWIDTH1*4-1:0] outpixel_x4; +reg [DWIDTH1*2-1:0] outpixel_x2; + +assign outpixel = read_x[0] ? outpixel_x2[DWIDTH1*2-1:DWIDTH1] : outpixel_x2[DWIDTH:0]; + +hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH+1), .DWIDTH(DWIDTH1*4-1)) hq2x_out +( + .clock(clk), + + .rdaddress({read_x[AWIDTH+1:1],read_y[1]}), + .q(outpixel_x4), + + .data(wrdata), + .wraddress(wrout_addr), + .wren(wrout_en) +); + +always @(posedge clk) begin + if(ce_out) begin + if(read_x[0]) outpixel_x2 <= read_y[0] ? outpixel_x4[DWIDTH1*4-1:DWIDTH1*2] : outpixel_x4[DWIDTH1*2-1:0]; + if(~hblank & ~&read_x) read_x <= read_x + 1'd1; + if(hblank) read_x <= 0; + end +end + +wire [DWIDTH:0] blend_result = HALF_DEPTH ? rgb2h(blend_result_pre) : blend_result_pre[DWIDTH:0]; + +reg [AWIDTH:0] offs; +always @(posedge clk) begin + reg old_reset_line; + reg old_reset_frame; + reg [3:0] wrdata_finished; + reg [AWIDTH+1:0] waddr; + + wrout_en <= 0; + wrin_en <= 0; + + if(ce_in) begin + + // blend_result has been delayed by 4 cycles + case(cyc) + 0: wrdata[DWIDTH:0] <= blend_result; + 1: wrdata[DWIDTH1+DWIDTH:DWIDTH1] <= blend_result; + 2: wrdata[DWIDTH1*3+DWIDTH:DWIDTH1*3] <= blend_result; + 3: wrdata[DWIDTH1*2+DWIDTH:DWIDTH1*2] <= blend_result; + endcase + + wrdata_finished <= wrdata_finished << 1; + if(wrdata_finished[3]) begin + wrout_en <= 1; + wrout_addr <= waddr; + end + + if(~&offs) begin + if (cyc == 1) begin + Prev2 <= Curr20; + Curr2 <= Curr21; + Next2 <= HALF_DEPTH ? h2rgb(inputpixel) : inputpixel; + wrpix <= inputpixel; + wrin_addr2 <= offs; + wrin_en <= 1; + end + + if(cyc==3) begin + offs <= offs + 1'd1; + waddr <= {offs, curbuf}; + wrdata_finished[0] <= 1; + end + end + + pattern <= new_pattern; + if(cyc==3) begin + nextpatt <= {new_pattern[7:6], new_pattern[3], new_pattern[5], new_pattern[2], new_pattern[4], new_pattern[1:0]}; + {A, G} <= {Prev0, Next0}; + {B, F, H, D} <= {Prev1, Curr2, Next1, Curr0}; + {Prev0, Prev1} <= {Prev1, Prev2}; + {Curr0, Curr1} <= {Curr1, Curr2}; + {Next0, Next1} <= {Next1, Next2}; + end else begin + nextpatt <= {nextpatt[5], nextpatt[3], nextpatt[0], nextpatt[6], nextpatt[1], nextpatt[7], nextpatt[4], nextpatt[2]}; + {B, F, H, D} <= {F, H, D, B}; + end + + cyc <= cyc + 1'b1; + if(old_reset_line && ~reset_line) begin + old_reset_frame <= reset_frame; + offs <= 0; + cyc <= 0; + curbuf <= ~curbuf; + prevbuf <= curbuf; + {Prev0, Prev1, Prev2, Curr0, Curr1, Curr2, Next0, Next1, Next2} <= '0; + if(old_reset_frame & ~reset_frame) begin + curbuf <= 0; + prevbuf <= 0; + end + end + + old_reset_line <= reset_line; + end +end + +endmodule + +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +module hq2x_in #(parameter LENGTH, parameter DWIDTH) +( + input clk, + + input [AWIDTH:0] rdaddr, + input rdbuf0, rdbuf1, + output[DWIDTH:0] q0,q1, + + input [AWIDTH:0] wraddr, + input wrbuf, + input [DWIDTH:0] data, + input wren +); + +localparam AWIDTH = $clog2(LENGTH)-1; +wire [DWIDTH:0] out[2]; +assign q0 = out[rdbuf0]; +assign q1 = out[rdbuf1]; + +hq2x_buf #(.NUMWORDS(LENGTH), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf0(clk,data,rdaddr,wraddr,wren && (wrbuf == 0),out[0]); +hq2x_buf #(.NUMWORDS(LENGTH), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf1(clk,data,rdaddr,wraddr,wren && (wrbuf == 1),out[1]); + +endmodule + +module hq2x_buf #(parameter NUMWORDS, parameter AWIDTH, parameter DWIDTH) +( + input clock, + input [DWIDTH:0] data, + input [AWIDTH:0] rdaddress, + input [AWIDTH:0] wraddress, + input wren, + output reg [DWIDTH:0] q +); + +reg [DWIDTH:0] ram[0:NUMWORDS-1]; + +always_ff@(posedge clock) begin + if(wren) ram[wraddress] <= data; + q <= ram[rdaddress]; +end + +endmodule + +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +module DiffCheck +( + input [23:0] rgb1, + input [23:0] rgb2, + output result +); + + wire [7:0] r = rgb1[7:1] - rgb2[7:1]; + wire [7:0] g = rgb1[15:9] - rgb2[15:9]; + wire [7:0] b = rgb1[23:17] - rgb2[23:17]; + wire [8:0] t = $signed(r) + $signed(b); + wire [9:0] y = $signed(t) + $signed({g[7], g}); + wire [8:0] u = $signed(r) - $signed(b); + wire [9:0] v = $signed({g, 1'b0}) - $signed(t); + + // if y is inside (-96..96) + wire y_inside = (y < 10'h60 || y >= 10'h3a0); + + // if u is inside (-16, 16) + wire u_inside = (!u[8:4] || &u[8:4]); //(u < 9'h10 || u >= 9'h1f0); + + // if v is inside (-24, 24) + wire v_inside = (v < 10'h18 || v >= 10'h3e8); + assign result = !(y_inside && u_inside && v_inside); + +endmodule + +module Blend +( + input clk, + input clk_en, + input [5:0] rule, + input [23:0] E, + input [23:0] A, + input [23:0] B, + input [23:0] D, + input [23:0] F, + input [23:0] H, + output [23:0] Result +); + + localparam BLEND1 = 7'b110_10_00; // (A * 12 + B * 4 ) >> 4 + localparam BLEND2 = 7'b100_10_10; // (A * 8 + B * 4 + C * 4) >> 4 + localparam BLEND3 = 7'b101_10_01; // (A * 10 + B * 4 + C * 2) >> 4 + localparam BLEND4 = 7'b110_01_01; // (A * 12 + B * 2 + C * 2) >> 4 + localparam BLEND5 = 7'b010_11_11; // (A * 4 + B * 6 + C * 6) >> 4 + localparam BLEND6 = 7'b111_00_00; // (A * 14 + B * 1 + C * 1) >> 4 + + reg [23:0] a,b,d,e,h,f; + reg [3:0] bl_rule; + reg [1:0] df_rule; + always @(posedge clk) if (clk_en) begin + {bl_rule,df_rule} <= rule; + a <= A; b <= B; d <= D; e <= E; f <= F; h <= H; + end + + wire is_diff; + DiffCheck diff_checker(df_rule[1] ? b : h, df_rule[0] ? d : f, is_diff); + + reg [23:0] i10,i20,i30; + reg [6:0] op0; + always @(posedge clk) if (clk_en) begin + i10 <= e; + case({!is_diff, bl_rule}) + 1,11,12,13,17: {op0, i20, i30} <= {BLEND1, a, 24'd0}; + 2,14,18: {op0, i20, i30} <= {BLEND1, d, 24'd0}; + 3,15,19: {op0, i20, i30} <= {BLEND1, b, 24'd0}; + 4,20,24,27: {op0, i20, i30} <= {BLEND2, d, b}; + 5,21: {op0, i20, i30} <= {BLEND2, a, b}; + 6,22: {op0, i20, i30} <= {BLEND2, a, d}; + 25,29: {op0, i20, i30} <= {BLEND5, d, b}; + 26: {op0, i20, i30} <= {BLEND6, d, b}; + 28: {op0, i20, i30} <= {BLEND4, d, b}; + 30: {op0, i20, i30} <= {BLEND3, b, d}; + 31: {op0, i20, i30} <= {BLEND3, d, b}; + default: {op0, i20, i30} <= {BLEND1, e, 24'd0}; + endcase + end + + reg [23:0] i1,i2,i3; + reg [6:0] op; + always @(posedge clk) if (clk_en) begin + op <= op0; i1 <= i10; i2 <= i20; i3 <= i30; + end + + function [34:0] mul24x3; + input [23:0] op1; + input [2:0] op2; + begin + mul24x3 = 0; + if(op2[0]) mul24x3 = mul24x3 + {op1[23:16], 4'b0000, op1[15:8], 4'b0000, op1[7:0]}; + if(op2[1]) mul24x3 = mul24x3 + {op1[23:16], 4'b0000, op1[15:8], 4'b0000, op1[7:0], 1'b0}; + if(op2[2]) mul24x3 = mul24x3 + {op1[23:16], 4'b0000, op1[15:8], 4'b0000, op1[7:0], 2'b00}; + end + endfunction + + wire [35:0] res = {mul24x3(i1, op[6:4]), 1'b0} + mul24x3(i2, {op[3:2], !op[3:2]}) + mul24x3(i3, {op[1:0], !op[3:2]}); + + always @(posedge clk) if (clk_en) Result <= {res[35:28],res[23:16],res[11:4]}; + +endmodule diff --git a/sys/i2c.v b/sys/i2c.v new file mode 100644 index 0000000..35c8cbd --- /dev/null +++ b/sys/i2c.v @@ -0,0 +1,103 @@ + +module i2c +( + input CLK, + + input START, + input READ, + input [6:0] I2C_ADDR, + input I2C_WLEN, // 0 - one byte, 1 - two bytes + input [7:0] I2C_WDATA1, + input [7:0] I2C_WDATA2, + output [7:0] I2C_RDATA, + output reg END = 1, + output reg ACK = 0, + + //I2C bus + output I2C_SCL, + inout I2C_SDA +); + + +// Clock Setting +parameter CLK_Freq = 50_000_000; // 50 MHz +parameter I2C_Freq = 400_000; // 400 KHz + +localparam I2C_FreqX2 = I2C_Freq*2; + +reg I2C_CLOCK; +reg [31:0] cnt; +wire [31:0] cnt_next = cnt + I2C_FreqX2; + +always @(posedge CLK) begin + cnt <= cnt_next; + if(cnt_next >= CLK_Freq) begin + cnt <= cnt_next - CLK_Freq; + I2C_CLOCK <= ~I2C_CLOCK; + end +end + +assign I2C_SCL = (SCLK | I2C_CLOCK) ? 1'bZ : 1'b0; +assign I2C_SDA = SDO[3] ? 1'bz : 1'b0; + +reg SCLK; +reg [3:0] SDO; +reg [0:7] rdata; + +reg [5:0] SD_COUNTER; +reg [0:31] SD; + +initial begin + SD_COUNTER = 'b111111; + SD = 'hFFFF; + SCLK = 1; + SDO = 4'b1111; +end + +assign I2C_RDATA = rdata; + +always @(posedge CLK) begin + reg old_clk; + reg old_st; + reg rd,len; + + old_clk <= I2C_CLOCK; + old_st <= START; + + // delay to make sure SDA changed while SCL is stabilized at low + if(old_clk && ~I2C_CLOCK && ~SD_COUNTER[5]) SDO[0] <= SD[SD_COUNTER[4:0]]; + SDO[3:1] <= SDO[2:0]; + + if(~old_st && START) begin + SCLK <= 1; + SDO <= 4'b1111; + ACK <= 0; + END <= 0; + rd <= READ; + len <= I2C_WLEN; + if(READ) SD <= {2'b10, I2C_ADDR, 1'b1, 1'b1, 8'b11111111, 1'b0, 3'b011, 9'b111111111}; + else SD <= {2'b10, I2C_ADDR, 1'b0, 1'b1, I2C_WDATA1, 1'b1, I2C_WDATA2, 4'b1011}; + SD_COUNTER <= 0; + end else begin + if(~old_clk && I2C_CLOCK && ~&SD_COUNTER) begin + SD_COUNTER <= SD_COUNTER + 6'd1; + case(SD_COUNTER) + 01: SCLK <= 0; + 10: ACK <= ACK | I2C_SDA; + 19: if(~rd) begin + ACK <= ACK | I2C_SDA; + if(~len) SD_COUNTER <= 29; + end + 20: if(rd) SCLK <= 1; + 23: if(rd) END <= 1; + 28: if(~rd) ACK <= ACK | I2C_SDA; + 29: if(~rd) SCLK <= 1; + 32: if(~rd) END <= 1; + endcase + + if(SD_COUNTER >= 11 && SD_COUNTER <= 18) rdata[SD_COUNTER[4:0]-11] <= I2C_SDA; + end + end +end + +endmodule diff --git a/sys/i2s.v b/sys/i2s.v new file mode 100644 index 0000000..7d4517b --- /dev/null +++ b/sys/i2s.v @@ -0,0 +1,54 @@ + +module i2s +#( + parameter AUDIO_DW = 16 +) +( + input reset, + input clk, + input ce, + + output reg sclk, + output reg lrclk, + output reg sdata, + + input [AUDIO_DW-1:0] left_chan, + input [AUDIO_DW-1:0] right_chan +); + +always @(posedge clk) begin + reg [7:0] bit_cnt; + reg msclk; + + reg [AUDIO_DW-1:0] left; + reg [AUDIO_DW-1:0] right; + + if (reset) begin + bit_cnt <= 1; + lrclk <= 1; + sclk <= 1; + msclk <= 1; + end + else begin + sclk <= msclk; + if(ce) begin + msclk <= ~msclk; + if(msclk) begin + if(bit_cnt >= AUDIO_DW) begin + bit_cnt <= 1; + lrclk <= ~lrclk; + if(lrclk) begin + left <= left_chan; + right <= right_chan; + end + end + else begin + bit_cnt <= bit_cnt + 1'd1; + end + sdata <= lrclk ? right[AUDIO_DW - bit_cnt] : left[AUDIO_DW - bit_cnt]; + end + end + end +end + +endmodule diff --git a/sys/iir_filter.v b/sys/iir_filter.v new file mode 100644 index 0000000..a5336e9 --- /dev/null +++ b/sys/iir_filter.v @@ -0,0 +1,213 @@ + +// 3-tap IIR filter for 2 channels. +// Copyright (C) 2020 Sorgelig +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +// +// Can be converted to 2-tap (coeff_x2 = 0, coeff_y2 = 0) or 1-tap (coeff_x1,2 = 0, coeff_y1,2 = 0) +// +module IIR_filter +#( + parameter use_params = 1, // set to 1 to use following parameters, 0 for input port variables. + parameter stereo = 1, // 0 for mono (input_l) + + parameter coeff_x = 0.00000774701983513660, // Base gain value for X. Float. Range: 0.0 ... 0.999(9) + parameter coeff_x0 = 3, // Gain scale factor for X0. Integer. Range -7 ... +7 + parameter coeff_x1 = 3, // Gain scale factor for X1. Integer. Range -7 ... +7 + parameter coeff_x2 = 1, // Gain scale factor for X2. Integer. Range -7 ... +7 + parameter coeff_y0 = -2.96438150626551080000, // Coefficient for Y0. Float. Range -3.999(9) ... 3.999(9) + parameter coeff_y1 = 2.92939452735121100000, // Coefficient for Y1. Float. Range -3.999(9) ... 3.999(9) + parameter coeff_y2 = -0.96500747158831091000 // Coefficient for Y2. Float. Range -3.999(9) ... 3.999(9) +) +( + input clk, + input reset, + + input ce, // must be double of calculated rate for stereo! + input sample_ce, // desired output sample rate + + input [39:0] cx, + input [7:0] cx0, + input [7:0] cx1, + input [7:0] cx2, + input [23:0] cy0, + input [23:0] cy1, + input [23:0] cy2, + + input [15:0] input_l, input_r, // signed samples + output [15:0] output_l, output_r // signed samples +); + +localparam [39:0] pcoeff_x = coeff_x * 40'h8000000000; +localparam [31:0] pcoeff_y0 = coeff_y0 * 24'h200000; +localparam [31:0] pcoeff_y1 = coeff_y1 * 24'h200000; +localparam [31:0] pcoeff_y2 = coeff_y2 * 24'h200000; + +wire [39:0] vcoeff = use_params ? pcoeff_x : cx; +wire [23:0] vcoeff_y0 = use_params ? pcoeff_y0[23:0] : cy0; +wire [23:0] vcoeff_y1 = use_params ? pcoeff_y1[23:0] : cy1; +wire [23:0] vcoeff_y2 = use_params ? pcoeff_y2[23:0] : cy2; + +wire [59:0] inp_mul = $signed(inp) * $signed(vcoeff); + +wire [39:0] x = inp_mul[59:20]; +wire [39:0] y = x + tap0; + +wire [39:0] tap0; +iir_filter_tap iir_tap_0 +( + .clk(clk), + .reset(reset), + .ce(ce), + .ch(ch), + .cx(use_params ? coeff_x0[7:0] : cx0), + .cy(vcoeff_y0), + .x(x), + .y(y), + .z(tap1), + .tap(tap0) +); + +wire [39:0] tap1; +iir_filter_tap iir_tap_1 +( + .clk(clk), + .reset(reset), + .ce(ce), + .ch(ch), + .cx(use_params ? coeff_x1[7:0] : cx1), + .cy(vcoeff_y1), + .x(x), + .y(y), + .z(tap2), + .tap(tap1) +); + +wire [39:0] tap2; +iir_filter_tap iir_tap_2 +( + .clk(clk), + .reset(reset), + .ce(ce), + .ch(ch), + .cx(use_params ? coeff_x2[7:0] : cx2), + .cy(vcoeff_y2), + .x(x), + .y(y), + .z(0), + .tap(tap2) +); + +wire [15:0] y_clamp = (~y[39] & |y[38:35]) ? 16'h7FFF : (y[39] & ~&y[38:35]) ? 16'h8000 : y[35:20]; + +reg ch = 0; +reg [15:0] out_l, out_r, out_m; +reg [15:0] inp, inp_m; +always @(posedge clk) if (ce) begin + if(!stereo) begin + ch <= 0; + inp <= input_l; + out_l <= y_clamp; + out_r <= y_clamp; + end + else begin + ch <= ~ch; + if(ch) begin + out_m <= y_clamp; + inp <= inp_m; + end + else begin + out_l <= out_m; + out_r <= y_clamp; + inp <= input_l; + inp_m <= input_r; + end + end +end + +reg [31:0] out; +always @(posedge clk) if (sample_ce) out <= {out_l, out_r}; + +assign {output_l, output_r} = out; + +endmodule + +module iir_filter_tap +( + input clk, + input reset, + + input ce, + input ch, + + input [7:0] cx, + input [23:0] cy, + + input [39:0] x, + input [39:0] y, + input [39:0] z, + output [39:0] tap +); + +wire signed [60:0] y_mul = $signed(y[36:0]) * $signed(cy); + +function [39:0] x_mul; + input [39:0] x; +begin + x_mul = 0; + if(cx[0]) x_mul = x_mul + {{4{x[39]}}, x[39:4]}; + if(cx[1]) x_mul = x_mul + {{3{x[39]}}, x[39:3]}; + if(cx[2]) x_mul = x_mul + {{2{x[39]}}, x[39:2]}; + if(cx[7]) x_mul = ~x_mul; //cheap NEG +end +endfunction + +(* ramstyle = "logic" *) reg [39:0] intreg[2]; +always @(posedge clk, posedge reset) begin + if(reset) {intreg[0],intreg[1]} <= 80'd0; + else if(ce) intreg[ch] <= x_mul(x) - y_mul[60:21] + z; +end + +assign tap = intreg[ch]; + +endmodule + +// simplified IIR 1-tap. +module DC_blocker +( + input clk, + input ce, // 48/96 KHz + input mute, + + input sample_rate, + input [15:0] din, + output [15:0] dout +); + +wire [39:0] x = {din[15], din, 23'd0}; +wire [39:0] x0 = x - (sample_rate ? {{11{x[39]}}, x[39:11]} : {{10{x[39]}}, x[39:10]}); +wire [39:0] y1 = y - (sample_rate ? {{10{y[39]}}, y[39:10]} : {{09{y[39]}}, y[39:09]}); +wire [39:0] y0 = x0 - x1 + y1; + +reg [39:0] x1, y; +always @(posedge clk) if(ce) begin + x1 <= x0; + y <= ^y0[39:38] ? {{2{y0[39]}},{38{y0[38]}}} : y0; +end + +assign dout = mute ? 16'd0 : y[38:23]; + +endmodule diff --git a/sys/ltc2308.sv b/sys/ltc2308.sv new file mode 100644 index 0000000..33134fd --- /dev/null +++ b/sys/ltc2308.sv @@ -0,0 +1,162 @@ +//============================================================================ +// +// LTC2308 controller +// Copyright (C) 2019 Sorgelig +// +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +//============================================================================ + + +// NUM_CH 1..8 +// Sampling rate = ADC_RATE/NUM_CH +// ADC_RATE max is ~500KHz +// CLK_RATE max is ~80MHz +module ltc2308 #(parameter NUM_CH = 2, ADC_RATE = 96000, CLK_RATE = 50000000) +( + input reset, + input clk, + + inout [3:0] ADC_BUS, + + output reg dout_sync, // toggle with every ADC round + output reg [(NUM_CH*12)-1:0] dout // 12 bits per channel (unsigned) +); + +localparam TCONV = CLK_RATE/625000; + +reg sck; +wire sdo = cfg[5]; + +assign ADC_BUS[3] = sck; +wire sdi = ADC_BUS[2]; +assign ADC_BUS[1] = sdo; +assign ADC_BUS[0] = convst; + +reg convst; +reg [5:0] cfg; + +reg [31:0] sum; +wire [31:0] next_sum = sum + ADC_RATE; + +reg [2:0] pin; +wire [2:0] next_pin = (pin == (NUM_CH-1)) ? 3'd0 : (pin + 1'd1); + +always @(posedge clk) begin + reg [7:0] tconv; + reg [3:0] bitcnt; + reg [10:0] adcin; + + convst <= 0; + + if(reset) begin + sum <= 0; + tconv <= 0; + bitcnt <= 0; + sck <= 0; + cfg <= 0; + dout <= 0; + pin <= NUM_CH[2:0]-1'd1; + end + else begin + sum <= next_sum; + if(next_sum >= CLK_RATE) begin + sum <= next_sum - CLK_RATE; + tconv <= TCONV[7:0]; + convst <= 1; + bitcnt <= 12; + cfg <= {1'b1, next_pin[0], next_pin[2:1], 1'b1, 1'b0}; + if(!next_pin) dout_sync <= ~dout_sync; + end + + if(tconv) tconv <= tconv - 1'd1; + else if(bitcnt) begin + sck <= ~sck; + + if(sck) cfg <= cfg<<1; + else begin + adcin <= {adcin[9:0],sdi}; + bitcnt <= bitcnt - 1'd1; + if(bitcnt == 1) begin + dout[pin*12 +:12] <= {adcin,sdi}; + pin <= next_pin; + end + end + end + else sck <= 0; + end +end + +endmodule + +module ltc2308_tape #(parameter HIST_LOW = 16, HIST_HIGH = 64, ADC_RATE = 48000, CLK_RATE = 50000000) +( + input reset, + input clk, + + inout [3:0] ADC_BUS, + output reg dout, + output active +); + +wire [11:0] adc_data; +wire adc_sync; +ltc2308 #(1, ADC_RATE, CLK_RATE) adc +( + .reset(reset), + .clk(clk), + + .ADC_BUS(ADC_BUS), + .dout(adc_data), + .dout_sync(adc_sync) +); + +always @(posedge clk) begin + reg [13:0] data1,data2,data3,data4, sum; + reg adc_sync_d; + + adc_sync_d<=adc_sync; + if(adc_sync_d ^ adc_sync) begin + data1 <= data2; + data2 <= data3; + data3 <= data4; + data4 <= adc_data; + + sum <= data1+data2+data3+data4; + + if(sum[13:2]HIST_HIGH) dout <= 1; + end +end + +assign active = |act; + +reg [1:0] act; +always @(posedge clk) begin + reg [31:0] onesec; + reg old_dout; + + onesec <= onesec + 1; + if(onesec>CLK_RATE) begin + onesec <= 0; + if(act) act <= act - 1'd1; + end + + old_dout <= dout; + if(old_dout ^ dout) act <= 2; +end + +endmodule diff --git a/sys/math.sv b/sys/math.sv new file mode 100644 index 0000000..1cf327f --- /dev/null +++ b/sys/math.sv @@ -0,0 +1,109 @@ + +// result = num/div +module sys_udiv +#( + parameter NB_NUM, + parameter NB_DIV +) +( + input clk, + input start, + output busy, + + input [NB_NUM-1:0] num, + input [NB_DIV-1:0] div, + output reg [NB_NUM-1:0] result, + output reg [NB_DIV-1:0] remainder +); + +reg run; +assign busy = run; + +always @(posedge clk) begin + reg [5:0] cpt; + reg [NB_NUM+NB_DIV+1:0] rem; + + if (start) begin + cpt <= 0; + run <= 1; + rem <= num; + end + else if (run) begin + cpt <= cpt + 1'd1; + run <= (cpt != NB_NUM + 1'd1); + remainder <= rem[NB_NUM+NB_DIV:NB_NUM+1]; + if (!rem[NB_DIV + NB_NUM + 1'd1]) + rem <= {rem[NB_DIV+NB_NUM:0] - (div << NB_NUM),1'b0}; + else + rem <= {rem[NB_DIV+NB_NUM:0] + (div << NB_NUM),1'b0}; + result <= {result[NB_NUM-2:0], !rem[NB_DIV + NB_NUM + 1'd1]}; + end +end + +endmodule + +// result = mul1*mul2 +module sys_umul +#( + parameter NB_MUL1, + parameter NB_MUL2 +) +( + input clk, + input start, + output busy, + + input [NB_MUL1-1:0] mul1, + input [NB_MUL2-1:0] mul2, + output reg [NB_MUL1+NB_MUL2-1:0] result +); + +reg run; +assign busy = run; + +always @(posedge clk) begin + reg [NB_MUL1+NB_MUL2-1:0] add; + reg [NB_MUL2-1:0] map; + + if (start) begin + run <= 1; + result <= 0; + add <= mul1; + map <= mul2; + end + else if (run) begin + if(!map) run <= 0; + if(map[0]) result <= result + add; + add <= add << 1; + map <= map >> 1; + end +end + +endmodule + +// result = (mul1*mul2)/div +module sys_umuldiv +#( + parameter NB_MUL1, + parameter NB_MUL2, + parameter NB_DIV +) +( + input clk, + input start, + output busy, + + input [NB_MUL1-1:0] mul1, + input [NB_MUL2-1:0] mul2, + input [NB_DIV-1:0] div, + output [NB_MUL1+NB_MUL2-1:0] result, + output [NB_DIV-1:0] remainder +); + +wire mul_run; +wire [NB_MUL1+NB_MUL2-1:0] mul_res; +sys_umul #(NB_MUL1,NB_MUL2) umul(clk,start,mul_run,mul1,mul2,mul_res); + +sys_udiv #(NB_MUL1+NB_MUL2,NB_DIV) udiv(clk,start|mul_run,busy,mul_res,div,result,remainder); + +endmodule diff --git a/sys/mcp23009.sv b/sys/mcp23009.sv new file mode 100644 index 0000000..40cbf5e --- /dev/null +++ b/sys/mcp23009.sv @@ -0,0 +1,113 @@ +// +// MCP23009 +// (C) 2019 Alexey Melnikov +// +module mcp23009 +( + input clk, + + output reg [2:0] btn, + input [2:0] led, + output reg sd_cd, + + output scl, + inout sda +); + + +reg start = 0; +wire ready; +wire error; +reg rw; +wire [7:0] dout; +reg [15:0] din; + +i2c #(50_000_000, 500_000) i2c +( + .CLK(clk), + .START(start), + .READ(rw), + .I2C_ADDR('h20), + .I2C_WLEN(1), + .I2C_WDATA1(din[15:8]), + .I2C_WDATA2(din[7:0]), + .I2C_RDATA(dout), + .END(ready), + .ACK(error), + .I2C_SCL(scl), + .I2C_SDA(sda) +); + +always@(posedge clk) begin + reg [3:0] idx = 0; + reg [1:0] state = 0; + reg [15:0] timeout = 0; + + if(~&timeout) begin + timeout <= timeout + 1'd1; + start <= 0; + state <= 0; + idx <= 0; + btn <= 0; + rw <= 0; + sd_cd <= 1; + end + else begin + if(~&init_data[idx]) begin + case(state) + 0: begin + start <= 1; + state <= 1; + din <= init_data[idx]; + end + 1: if(~ready) state <= 2; + 2: begin + start <= 0; + if(ready) begin + state <= 0; + if(!error) idx <= idx + 1'd1; + end + end + endcase + end + else begin + case(state) + 0: begin + start <= 1; + state <= 1; + din <= {8'h09,5'b00000,led}; + end + 1: if(~ready) state <= 2; + 2: begin + start <= 0; + if(ready) begin + state <= 0; + rw <= 0; + if(!error) begin + if(rw) {sd_cd, btn} <= {dout[7], dout[5:3]}; + rw <= ~rw; + end + end + end + endcase + end + end +end + +wire [15:0] init_data[12] = +'{ + 16'h00F8, + 16'h0138, + 16'h0200, + 16'h0300, + 16'h0400, + 16'h0524, + 16'h06FF, + 16'h0700, + 16'h0800, + 16'h0900, + 16'h0A00, + 16'hFFFF +}; + +endmodule diff --git a/sys/mt32pi.sv b/sys/mt32pi.sv new file mode 100644 index 0000000..cafa880 --- /dev/null +++ b/sys/mt32pi.sv @@ -0,0 +1,283 @@ +// +// Communication module to MT32-pi (external MIDI emulator on RPi) +// (C) 2020 Sorgelig, Kitrinx +// +// https://github.com/dwhinham/mt32-pi +// + +module mt32pi +( + input CLK_AUDIO, + + input CLK_VIDEO, + input CE_PIXEL, + input VGA_VS, + input VGA_DE, + + input [6:0] USER_IN, + output [6:0] USER_OUT, + + input reset, + input midi_tx, + output midi_rx, + + output reg [15:0] mt32_i2s_r, + output reg [15:0] mt32_i2s_l, + + output reg mt32_available, + + input mt32_mode_req, + input [1:0] mt32_rom_req, + input [7:0] mt32_sf_req, + + output reg [7:0] mt32_mode, + output reg [7:0] mt32_rom, + output reg [7:0] mt32_sf, + output reg mt32_newmode, + + output reg mt32_lcd_en, + output reg mt32_lcd_pix, + output reg mt32_lcd_update +); + +// +// Pin | USB Name | Signal +// ----+----------+-------------- +// 0 | D+ | I/O I2C_SDA / RX (midi in) +// 1 | D- | O TX (midi out) +// 2 | TX- | I I2S_WS (1 == right) +// 3 | GND_d | I I2C_SCL +// 4 | RX+ | I I2S_BCLK +// 5 | RX- | I I2S_DAT +// 6 | TX+ | - none +// + +assign USER_OUT[0] = sda_out; +assign USER_OUT[1] = midi_tx; +assign USER_OUT[6:2] = '1; + + +// +// crossed/straight cable selection +// + +generate + genvar i; + for(i = 0; i<2; i++) begin : clk_rate + wire clk_in = i ? USER_IN[6] : USER_IN[4]; + reg [4:0] cnt; + always @(posedge CLK_AUDIO) begin : clkr + reg clk_sr, clk, old_clk; + reg [4:0] cnt_tmp; + + clk_sr <= clk_in; + if (clk_sr == clk_in) clk <= clk_sr; + + if(~&cnt_tmp) cnt_tmp <= cnt_tmp + 1'd1; + else cnt <= '1; + + old_clk <= clk; + if(~old_clk & clk) begin + cnt <= cnt_tmp; + cnt_tmp <= 0; + end + end + end + + reg crossed; + always @(posedge CLK_AUDIO) crossed <= (clk_rate[0].cnt <= clk_rate[1].cnt); +endgenerate + +wire i2s_ws = crossed ? USER_IN[2] : USER_IN[5]; +wire i2s_data = crossed ? USER_IN[5] : USER_IN[2]; +wire i2s_bclk = crossed ? USER_IN[4] : USER_IN[6]; +assign midi_rx = ~mt32_available ? USER_IN[0] : crossed ? USER_IN[6] : USER_IN[4]; + + +// +// i2s receiver +// + +always @(posedge CLK_AUDIO) begin : i2s_proc + reg [15:0] i2s_buf = 0; + reg [4:0] i2s_cnt = 0; + reg clk_sr; + reg i2s_clk = 0; + reg old_clk, old_ws; + reg i2s_next = 0; + + // Debounce clock + clk_sr <= i2s_bclk; + if (clk_sr == i2s_bclk) i2s_clk <= clk_sr; + + // Latch data and ws on rising edge + old_clk <= i2s_clk; + if (i2s_clk && ~old_clk) begin + + if (~i2s_cnt[4]) begin + i2s_cnt <= i2s_cnt + 1'd1; + i2s_buf[~i2s_cnt[3:0]] <= i2s_data; + end + + // Word Select will change 1 clock before the new word starts + old_ws <= i2s_ws; + if (old_ws != i2s_ws) i2s_next <= 1; + end + + if (i2s_next) begin + i2s_next <= 0; + i2s_cnt <= 0; + i2s_buf <= 0; + + if (i2s_ws) mt32_i2s_l <= i2s_buf; + else mt32_i2s_r <= i2s_buf; + end + + if (reset) begin + i2s_buf <= 0; + mt32_i2s_l <= 0; + mt32_i2s_r <= 0; + end +end + + +// +// i2c slave +// + +reg sda_out; +reg [7:0] lcd_data[1024]; +reg lcd_sz; + +reg reset_r = 0; +wire [7:0] mode_req = reset_r ? 8'hA0 : mt32_mode_req ? 8'hA2 : 8'hA1; +wire [7:0] rom_req = {6'd0, mt32_rom_req}; + +always @(posedge CLK_AUDIO) begin : i2c_slave + reg sda_sr, scl_sr; + reg old_sda, old_scl; + reg sda, scl; + reg [7:0] tmp; + reg [3:0] cnt = 0; + reg [10:0] bcnt = 0; + reg ack; + reg i2c_rw; + reg disp, dispdata; + reg [2:0] div; + reg old_reset; + + old_reset <= reset; + if(old_reset & ~reset) sda_out <= 1; + + div <= div + 1'd1; + if(!div) begin + sda_sr <= USER_IN[0]; + if(sda_sr == USER_IN[0]) sda <= sda_sr; + old_sda <= sda; + + scl_sr <= USER_IN[3]; + if(scl_sr == USER_IN[3]) scl <= scl_sr; + old_scl <= scl; + + //start + if(old_scl & scl & old_sda & ~sda) begin + cnt <= 9; + bcnt <= 0; + ack <= 0; + i2c_rw <= 0; + disp <= 0; + dispdata <= 0; + end + + //stop + if(old_scl & scl & ~old_sda & sda) begin + cnt <= 0; + if(dispdata) begin + lcd_sz <= ~bcnt[9]; + mt32_lcd_update <= ~mt32_lcd_update; + end + end + + //data latch + if(~old_scl && scl && cnt) begin + tmp <= {tmp[6:0], sda}; + cnt <= cnt - 1'd1; + end + + if(!cnt) sda_out <= 1; + + //data set + if(old_scl && ~scl) begin + sda_out <= 1; + if(cnt == 1) begin + if(!bcnt) begin + if(tmp[7:1] == 'h45 || tmp[7:1] == 'h3c) begin + disp <= (tmp[7:1] == 'h3c); + sda_out <= 0; + mt32_available <= 1; + ack <= 1; + i2c_rw <= tmp[0]; + bcnt <= bcnt + 1'd1; + cnt <= 10; + end + else begin + // wrong address, stop + cnt <= 0; + end + end + else if(ack) begin + if(~i2c_rw) begin + if(disp) begin + if(bcnt == 1) dispdata <= (tmp[7:6] == 2'b01); + else if(dispdata) lcd_data[bcnt[9:0] - 2'd2] <= tmp; + end + else begin + if(bcnt == 1) mt32_mode <= tmp; + if(bcnt == 2) mt32_rom <= tmp; + if(bcnt == 3) mt32_sf <= tmp; + if(bcnt == 3) mt32_newmode <= ~mt32_newmode; + end + end + if(~&bcnt) bcnt <= bcnt + 1'd1; + sda_out <= 0; + cnt <= 10; + end + end + else if(i2c_rw && ack && cnt && ~disp) begin + if(bcnt == 1) sda_out <= mode_req[cnt[2:0] - 2'd2]; + if(bcnt == 2) sda_out <= rom_req[cnt[2:0] - 2'd2]; + if(bcnt == 3) sda_out <= mt32_sf_req[cnt[2:0] - 2'd2]; + if(bcnt == 3) reset_r <= 0; + end + end + end + + if(reset) begin + reset_r <= 1; + mt32_available <= 0; + end +end + +always @(posedge CLK_VIDEO) begin + reg old_de, old_vs; + reg [7:0] hcnt; + reg [6:0] vcnt; + reg [7:0] sh; + + if(CE_PIXEL) begin + old_de <= VGA_DE; + old_vs <= VGA_VS; + + if(~&hcnt) hcnt <= hcnt + 1'd1; + sh <= (sh << 1) | (~old_de & VGA_DE); + if(sh[7]) hcnt <= 0; + + if(old_de & ~VGA_DE & ~&vcnt) vcnt <= vcnt + 1'd1; + if(~old_vs & VGA_VS) vcnt <= 0; + + mt32_lcd_en <= mt32_available & ~hcnt[7] && (lcd_sz ? !vcnt[6] : !vcnt[6:5]); + mt32_lcd_pix <= lcd_data[{vcnt[5:3],hcnt[6:0]}][vcnt[2:0]]; + end +end + +endmodule diff --git a/sys/osd.v b/sys/osd.v new file mode 100644 index 0000000..782fc81 --- /dev/null +++ b/sys/osd.v @@ -0,0 +1,286 @@ +// A simple OSD implementation. Can be hooked up between a cores +// VGA output and the physical VGA pins + +module osd +( + input clk_sys, + input io_osd, + input io_strobe, + input [15:0] io_din, + + input clk_video, + input [23:0] din, + input de_in, + input vs_in, + input hs_in, + output [23:0] dout, + output reg de_out, + output reg vs_out, + output reg hs_out, + + output reg osd_status +); + +parameter OSD_COLOR = 3'd4; + +localparam OSD_WIDTH = 12'd256; +localparam OSD_HEIGHT = 12'd64; + +`ifdef OSD_HEADER +localparam OSD_HDR = 12'd24; +`else +localparam OSD_HDR = 12'd0; +`endif + +reg osd_enable; +(* ramstyle="no_rw_check" *) reg [7:0] osd_buffer[OSD_HDR ? (4096+1024) : 4096]; + +reg info = 0; +reg [8:0] infoh; +reg [8:0] infow; +reg [21:0] infox; +reg [21:0] infoy; +reg [21:0] osd_h; +reg [21:0] osd_t; +reg [21:0] osd_w; + +reg [1:0] rot = 0; + +always@(posedge clk_sys) begin + reg [12:0] bcnt; + reg [7:0] cmd; + reg has_cmd; + reg old_strobe; + reg highres = 0; + + osd_t <= rot[0] ? OSD_WIDTH : (OSD_HEIGHT<<1); + osd_h <= rot[0] ? (info ? infow : OSD_WIDTH) : info ? infoh : (OSD_HEIGHT<> (9-rot[0])) > 1) ? (((cnt+1'b1) >> (9-rot[0])) - 1'd1) : 22'd0; + pixcnt <= 0; + end +end + +reg [2:0] osd_de; +reg osd_pixel; +reg [21:0] v_cnt; +reg v_cnt_h, v_cnt_1, v_cnt_2, v_cnt_3, v_cnt_4; +reg [21:0] v_osd_start_h, v_osd_start_1, v_osd_start_2, v_osd_start_3, v_osd_start_4, v_osd_start_5; +reg [21:0] v_info_start_h, v_info_start_1, v_info_start_2, v_info_start_3, v_info_start_4, v_info_start_5; + +wire [21:0] osd_h_hdr = (info || rot) ? osd_h : (osd_h + OSD_HDR); + +// pipeline the comparisons a bit +always @(posedge clk_video) if(ce_pix) begin + v_cnt_h <= v_cnt < osd_t; + v_cnt_1 <= v_cnt < 320; + v_cnt_2 <= v_cnt < 640; + v_cnt_3 <= v_cnt < 960; + v_cnt_4 <= v_cnt < 1280; + + v_osd_start_h <= (v_cnt-(osd_h_hdr>>1))>>1; + v_osd_start_1 <= (v_cnt-osd_h_hdr)>>1; + v_osd_start_2 <= (v_cnt-(osd_h_hdr<<1))>>1; + v_osd_start_3 <= (v_cnt-(osd_h_hdr + (osd_h_hdr<<1)))>>1; + v_osd_start_4 <= (v_cnt-(osd_h_hdr<<2))>>1; + v_osd_start_5 <= (v_cnt-(osd_h_hdr + (osd_h_hdr<<2)))>>1; + + v_info_start_h <= rot[0] ? infox : infoy; + v_info_start_1 <= rot[0] ? infox : infoy; + v_info_start_2 <= rot[0] ? (infox<<1) : (infoy<<1); + v_info_start_3 <= rot[0] ? (infox + (infox << 1)) : (infoy + (infoy << 1)); + v_info_start_4 <= rot[0] ? (infox << 2) : (infoy << 2); + v_info_start_5 <= rot[0] ? (infox + (infox << 2)) : (infoy + (infoy << 2)); +end + +always @(posedge clk_video) begin + reg deD; + reg [2:0] osd_div; + reg [2:0] multiscan; + reg [7:0] osd_byte; + reg [23:0] h_cnt; + reg [21:0] dsp_width; + reg [21:0] osd_vcnt; + reg [21:0] h_osd_start; + reg [21:0] v_osd_start; + reg [21:0] osd_hcnt; + reg [21:0] osd_hcnt2; + reg osd_de1,osd_de2; + reg [1:0] osd_en; + reg f1; + reg half; + + if(ce_pix) begin + + deD <= de_in; + if(~&h_cnt) h_cnt <= h_cnt + 1'd1; + + if(~&osd_hcnt) osd_hcnt <= osd_hcnt + 1'd1; + if(~&osd_hcnt2) osd_hcnt2 <= osd_hcnt2 + 1'd1; + + if (h_cnt == h_osd_start) begin + osd_de[0] <= osd_en[1] && osd_h && ( + osd_vcnt[11] ? (osd_vcnt[7] && (osd_vcnt[6:0] >= 4) && (osd_vcnt[6:0] < 19)) : + (info && (rot == 3)) ? !osd_vcnt[21:8] : + (osd_vcnt < osd_h) + ); + osd_hcnt <= 0; + osd_hcnt2 <= 0; + if(info && rot == 1) osd_hcnt2 <= 22'd128-infoh; + end + if (osd_hcnt+1 == osd_w) osd_de[0] <= 0; + + // falling edge of de + if(!de_in && deD) dsp_width <= h_cnt[21:0]; + + // rising edge of de + if(de_in && !deD) begin + h_cnt <= 0; + v_cnt <= v_cnt + 1'd1; + h_osd_start <= info ? (rot[0] ? infoy : infox) : (((dsp_width - osd_w)>>1) - 2'd2); + + if(h_cnt > {dsp_width, 2'b00}) begin + v_cnt <= 1; + f1 <= ~f1; // skip every other frame for interlace compatibility. + if(~f1) begin + + osd_en <= (osd_en << 1) | osd_enable; + if(~osd_enable) osd_en <= 0; + + half <= 0; + if(v_cnt_h) begin + multiscan <= 0; + v_osd_start <= info ? v_info_start_h : v_osd_start_h; + half <= 1; + end + else if(v_cnt_1 | (rot[0] & v_cnt_2)) begin + multiscan <= 0; + v_osd_start <= info ? v_info_start_1 : v_osd_start_1; + end + else if(rot[0] ? v_cnt_3 : v_cnt_2) begin + multiscan <= 1; + v_osd_start <= info ? v_info_start_2 : v_osd_start_2; + end + else if(rot[0] ? v_cnt_4 : v_cnt_3) begin + multiscan <= 2; + v_osd_start <= info ? v_info_start_3 : v_osd_start_3; + end + else if(rot[0] | v_cnt_4) begin + multiscan <= 3; + v_osd_start <= info ? v_info_start_4 : v_osd_start_4; + end + else begin + multiscan <= 4; + v_osd_start <= info ? v_info_start_5 : v_osd_start_5; + end + end + end + + osd_div <= osd_div + 1'd1; + if(osd_div == multiscan) begin + osd_div <= 0; + if(~osd_vcnt[10]) osd_vcnt <= osd_vcnt + 1'd1 + half; + if(osd_vcnt == 'b100010011111 && ~info) osd_vcnt <= 0; + end + if(v_osd_start == v_cnt) begin + {osd_div,osd_vcnt} <= 0; + if(info && rot == 3) osd_vcnt <= 22'd256-infow; + else if(OSD_HDR && !rot) osd_vcnt <= {~info, 3'b000, ~info, 7'b0000000}; + end + end + + osd_byte <= osd_buffer[rot[0] ? ({osd_hcnt2[6:3], osd_vcnt[7:0]} ^ { {4{~rot[1]}}, {8{rot[1]}} }) : {osd_vcnt[7:3], osd_hcnt[7:0]}]; + osd_pixel <= osd_byte[rot[0] ? ((osd_hcnt2[2:0]-1'd1) ^ {3{~rot[1]}}) : osd_vcnt[2:0]]; + osd_de[2:1] <= osd_de[1:0]; + end +end + +reg [23:0] rdout; +assign dout = rdout; + +always @(posedge clk_video) begin + reg [23:0] ordout1, nrdout1, rdout2, rdout3; + reg de1,de2,de3; + reg osd_mux; + reg vs1,vs2,vs3; + reg hs1,hs2,hs3; + + nrdout1 <= din; + ordout1 <= {{osd_pixel, osd_pixel, OSD_COLOR[2], din[23:19]},// 23:16 + {osd_pixel, osd_pixel, OSD_COLOR[1], din[15:11]},// 15:8 + {osd_pixel, osd_pixel, OSD_COLOR[0], din[7:3]}}; // 7:0 + + osd_mux <= ~osd_de[2]; + rdout2 <= osd_mux ? nrdout1 : ordout1; + rdout3 <= rdout2; + + de1 <= de_in; de2 <= de1; de3 <= de2; + hs1 <= hs_in; hs2 <= hs1; hs3 <= hs2; + vs1 <= vs_in; vs2 <= vs1; vs3 <= vs2; + + rdout <= rdout3; + de_out <= de3; + hs_out <= hs3; + vs_out <= vs3; +end + +endmodule diff --git a/sys/pll.13.qip b/sys/pll.13.qip new file mode 100644 index 0000000..a6a1dca --- /dev/null +++ b/sys/pll.13.qip @@ -0,0 +1,17 @@ +set_global_assignment -entity "pll" -library "pll" -name IP_TOOL_NAME "altera_pll" +set_global_assignment -entity "pll" -library "pll" -name IP_TOOL_VERSION "13.1" +set_global_assignment -entity "pll" -library "pll" -name IP_TOOL_ENV "mwpim" +set_global_assignment -library "pll" -name MISC_FILE [file join $::quartus(qip_path) "pll.cmp"] +set_global_assignment -name SYNTHESIS_ONLY_QIP ON + +set_global_assignment -library "pll" -name VERILOG_FILE rtl/pll.v +set_global_assignment -library "pll" -name VERILOG_FILE rtl/pll/pll_0002.v + +set_instance_assignment -name PLL_COMPENSATION_MODE DIRECT -to "*pll_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_CHANNEL_SPACING "0.0 KHz" -to "*pll_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_AUTO_RESET ON -to "*pll_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_BANDWIDTH_PRESET AUTO -to "*pll_0002*|altera_pll:altera_pll_i*|*" + +set_global_assignment -entity "pll_0002" -library "pll" -name IP_TOOL_NAME "altera_pll" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_TOOL_VERSION "13.1" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_TOOL_ENV "mwpim" diff --git a/sys/pll_audio.13.qip b/sys/pll_audio.13.qip new file mode 100644 index 0000000..e987931 --- /dev/null +++ b/sys/pll_audio.13.qip @@ -0,0 +1,17 @@ +set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_TOOL_NAME "altera_pll" +set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_TOOL_VERSION "13.1" +set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_TOOL_ENV "mwpim" +set_global_assignment -library "pll_audio" -name MISC_FILE [file join $::quartus(qip_path) "pll_audio.cmp"] +set_global_assignment -name SYNTHESIS_ONLY_QIP ON + +set_global_assignment -library "pll_audio" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_audio.v"] +set_global_assignment -library "pll_audio" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_audio/pll_audio_0002.v"] + +set_instance_assignment -name PLL_COMPENSATION_MODE DIRECT -to "*pll_audio_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_CHANNEL_SPACING "0.0 KHz" -to "*pll_audio_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_AUTO_RESET ON -to "*pll_audio_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_BANDWIDTH_PRESET AUTO -to "*pll_audio_0002*|altera_pll:altera_pll_i*|*" + +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_TOOL_NAME "altera_pll" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_TOOL_VERSION "13.1" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_TOOL_ENV "mwpim" diff --git a/sys/pll_audio.qip b/sys/pll_audio.qip new file mode 100644 index 0000000..abb013b --- /dev/null +++ b/sys/pll_audio.qip @@ -0,0 +1,337 @@ +set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_TOOL_NAME "altera_pll" +set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_TOOL_VERSION "17.0" +set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_TOOL_ENV "mwpim" +set_global_assignment -library "pll_audio" -name MISC_FILE [file join $::quartus(qip_path) "pll_audio.cmp"] +set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_TARGETED_DEVICE_FAMILY "Cyclone V" +set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_GENERATED_DEVICE_FAMILY "{Cyclone V}" +set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_QSYS_MODE "UNKNOWN" +set_global_assignment -name SYNTHESIS_ONLY_QIP ON +set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_COMPONENT_NAME "cGxsX2F1ZGlv" +set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_COMPONENT_DISPLAY_NAME "QWx0ZXJhIFBMTA==" +set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_COMPONENT_REPORT_HIERARCHY "Off" +set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_COMPONENT_INTERNAL "Off" +set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_COMPONENT_AUTHOR "QWx0ZXJhIENvcnBvcmF0aW9u" +set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_COMPONENT_VERSION "MTcuMA==" +set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_COMPONENT_DESCRIPTION "QWx0ZXJhIFBoYXNlLUxvY2tlZCBMb29wIChBTFRFUkFfUExMKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_NAME "cGxsX2F1ZGlvXzAwMDI=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_DISPLAY_NAME "QWx0ZXJhIFBMTA==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_REPORT_HIERARCHY "Off" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_INTERNAL "Off" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_AUTHOR "QWx0ZXJhIENvcnBvcmF0aW9u" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_VERSION "MTcuMA==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_DESCRIPTION "QWx0ZXJhIFBoYXNlLUxvY2tlZCBMb29wIChBTFRFUkFfUExMKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZGVidWdfcHJpbnRfb3V0cHV0::ZmFsc2U=::ZGVidWdfcHJpbnRfb3V0cHV0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZGVidWdfdXNlX3JiY190YWZfbWV0aG9k::ZmFsc2U=::ZGVidWdfdXNlX3JiY190YWZfbWV0aG9k" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZGV2aWNl::NUNFQkEyRjE3QTc=::ZGV2aWNl" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BsbF9tb2Rl::RnJhY3Rpb25hbC1OIFBMTA==::UExMIE1vZGU=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZnJhY3Rpb25hbF92Y29fbXVsdGlwbGllcg==::dHJ1ZQ==::ZnJhY3Rpb25hbF92Y29fbXVsdGlwbGllcg==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3JlZmVyZW5jZV9jbG9ja19mcmVxdWVuY3k=::NTAuMA==::UmVmZXJlbmNlIENsb2NrIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cmVmZXJlbmNlX2Nsb2NrX2ZyZXF1ZW5jeQ==::NTAuMCBNSHo=::cmVmZXJlbmNlX2Nsb2NrX2ZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2NoYW5uZWxfc3BhY2luZw==::MC4w::Q2hhbm5lbCBTcGFjaW5n" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX29wZXJhdGlvbl9tb2Rl::ZGlyZWN0::T3BlcmF0aW9uIE1vZGU=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2ZlZWRiYWNrX2Nsb2Nr::R2xvYmFsIENsb2Nr::RmVlZGJhY2sgQ2xvY2s=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2ZyYWN0aW9uYWxfY291dA==::MzI=::RnJhY3Rpb25hbCBjYXJyeSBvdXQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RzbV9vdXRfc2Vs::MXN0X29yZGVy::RFNNIE9yZGVy" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3BlcmF0aW9uX21vZGU=::ZGlyZWN0::b3BlcmF0aW9uX21vZGU=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3VzZV9sb2NrZWQ=::ZmFsc2U=::RW5hYmxlIGxvY2tlZCBvdXRwdXQgcG9ydA==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX2Fkdl9wYXJhbXM=::ZmFsc2U=::RW5hYmxlIHBoeXNpY2FsIG91dHB1dCBjbG9jayBwYXJhbWV0ZXJz" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX251bWJlcl9vZl9jbG9ja3M=::MQ==::TnVtYmVyIE9mIENsb2Nrcw==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "bnVtYmVyX29mX2Nsb2Nrcw==::MQ==::bnVtYmVyX29mX2Nsb2Nrcw==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX211bHRpcGx5X2ZhY3Rvcg==::MQ==::TXVsdGlwbHkgRmFjdG9yIChNLUNvdW50ZXIp" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2ZyYWNfbXVsdGlwbHlfZmFjdG9y::MQ==::RnJhY3Rpb25hbCBNdWx0aXBseSBGYWN0b3IgKEsp" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3Jfbg==::MQ==::RGl2aWRlIEZhY3RvciAoTi1Db3VudGVyKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjA=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kw::MjQuNTc2::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzA=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Iw::OA==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjA=::MTUyODMyMTE2Mw==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMA==::MTc=::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MA==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMA==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MA==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzA=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDA=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUw::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kx::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Ix::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMQ==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MQ==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMQ==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MQ==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUx::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjI=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3ky::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzI=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Iy::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjI=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMg==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Mg==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMg==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Mg==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzI=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDI=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUy::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjM=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kz::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzM=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Iz::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjM=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMw==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Mw==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMw==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Mw==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzM=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDM=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUz::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjQ=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k0::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzQ=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I0::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjQ=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNA==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5NA==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNA==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0NA==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzQ=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDQ=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU0::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjU=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k1::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzU=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I1::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjU=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNQ==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5NQ==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNQ==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0NQ==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzU=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDU=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU1::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjY=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k2::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzY=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I2::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjY=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNg==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Ng==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNg==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Ng==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzY=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDY=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU2::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjc=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k3::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzc=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I3::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3Rvcjc=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNw==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Nw==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNw==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Nw==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzc=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDc=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU3::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjg=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k4::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzg=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I4::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3Rvcjg=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yOA==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5OA==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzOA==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0OA==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzg=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDg=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU4::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjk=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k5::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzk=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I5::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3Rvcjk=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yOQ==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5OQ==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzOQ==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0OQ==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzk=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDk=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU5::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEw::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMA==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEw::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMA==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEw::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTA=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTA=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTA=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTA=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEw::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEw::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMA==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEx::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMQ==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEx::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMQ==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEx::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTE=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTE=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTE=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTE=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEx::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEx::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMQ==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEy::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMg==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEy::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMg==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEy::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTI=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTI=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTI=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTI=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEy::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEy::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMg==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEz::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMw==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEz::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMw==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEz::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTM=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTM=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTM=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTM=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEz::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEz::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMw==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE0::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNA==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE0::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNA==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE0::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTQ=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTQ=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTQ=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTQ=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE0::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE0::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNA==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE1::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNQ==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE1::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNQ==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE1::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTU=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTU=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTU=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTU=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE1::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE1::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNQ==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE2::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNg==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE2::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNg==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE2::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTY=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTY=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTY=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTY=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE2::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE2::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNg==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE3::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNw==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE3::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNw==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE3::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTc=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTc=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTc=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTc=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE3::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE3::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNw==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTA=::MjQuNTc2MDAwIE1Ieg==::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTA=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQw::MCBwcw==::cGhhc2Vfc2hpZnQw" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTA=::NTA=::ZHV0eV9jeWNsZTA=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQx::MCBwcw==::cGhhc2Vfc2hpZnQx" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE=::NTA=::ZHV0eV9jeWNsZTE=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTI=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTI=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQy::MCBwcw==::cGhhc2Vfc2hpZnQy" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTI=::NTA=::ZHV0eV9jeWNsZTI=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTM=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTM=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQz::MCBwcw==::cGhhc2Vfc2hpZnQz" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTM=::NTA=::ZHV0eV9jeWNsZTM=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTQ=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ0::MCBwcw==::cGhhc2Vfc2hpZnQ0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTQ=::NTA=::ZHV0eV9jeWNsZTQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTU=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTU=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ1::MCBwcw==::cGhhc2Vfc2hpZnQ1" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTU=::NTA=::ZHV0eV9jeWNsZTU=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTY=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTY=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ2::MCBwcw==::cGhhc2Vfc2hpZnQ2" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTY=::NTA=::ZHV0eV9jeWNsZTY=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTc=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTc=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ3::MCBwcw==::cGhhc2Vfc2hpZnQ3" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTc=::NTA=::ZHV0eV9jeWNsZTc=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTg=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTg=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ4::MCBwcw==::cGhhc2Vfc2hpZnQ4" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTg=::NTA=::ZHV0eV9jeWNsZTg=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTk=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTk=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ5::MCBwcw==::cGhhc2Vfc2hpZnQ5" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTk=::NTA=::ZHV0eV9jeWNsZTk=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEw::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEw" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMA==::MCBwcw==::cGhhc2Vfc2hpZnQxMA==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEw::NTA=::ZHV0eV9jeWNsZTEw" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEx::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEx" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMQ==::MCBwcw==::cGhhc2Vfc2hpZnQxMQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEx::NTA=::ZHV0eV9jeWNsZTEx" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEy::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEy" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMg==::MCBwcw==::cGhhc2Vfc2hpZnQxMg==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEy::NTA=::ZHV0eV9jeWNsZTEy" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEz::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEz" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMw==::MCBwcw==::cGhhc2Vfc2hpZnQxMw==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEz::NTA=::ZHV0eV9jeWNsZTEz" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE0::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNA==::MCBwcw==::cGhhc2Vfc2hpZnQxNA==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE0::NTA=::ZHV0eV9jeWNsZTE0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE1::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE1" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNQ==::MCBwcw==::cGhhc2Vfc2hpZnQxNQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE1::NTA=::ZHV0eV9jeWNsZTE1" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE2::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE2" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNg==::MCBwcw==::cGhhc2Vfc2hpZnQxNg==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE2::NTA=::ZHV0eV9jeWNsZTE2" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE3::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE3" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNw==::MCBwcw==::cGhhc2Vfc2hpZnQxNw==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE3::NTA=::ZHV0eV9jeWNsZTE3" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BsbF9hdXRvX3Jlc2V0::T24=::UExMIEF1dG8gUmVzZXQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BsbF9iYW5kd2lkdGhfcHJlc2V0::QXV0bw==::UExMIEJhbmR3aWR0aCBQcmVzZXQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX3JlY29uZg==::ZmFsc2U=::RW5hYmxlIGR5bmFtaWMgcmVjb25maWd1cmF0aW9uIG9mIFBMTA==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX2Rwc19wb3J0cw==::ZmFsc2U=::RW5hYmxlIGFjY2VzcyB0byBkeW5hbWljIHBoYXNlIHNoaWZ0IHBvcnRz" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX3Bob3V0X3BvcnRz::ZmFsc2U=::RW5hYmxlIGFjY2VzcyB0byBQTEwgRFBBIG91dHB1dCBwb3J0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGxsX3R5cGU=::R2VuZXJhbA==::UExMIFRZUEU=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGxsX3N1YnR5cGU=::R2VuZXJhbA==::UExMIFNVQlRZUEU=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BhcmFtZXRlcl9saXN0::TS1Db3VudGVyIEhpIERpdmlkZSxNLUNvdW50ZXIgTG93IERpdmlkZSxOLUNvdW50ZXIgSGkgRGl2aWRlLE4tQ291bnRlciBMb3cgRGl2aWRlLE0tQ291bnRlciBCeXBhc3MgRW5hYmxlLE4tQ291bnRlciBCeXBhc3MgRW5hYmxlLE0tQ291bnRlciBPZGQgRGl2aWRlIEVuYWJsZSxOLUNvdW50ZXIgT2RkIERpdmlkZSBFbmFibGUsQy1Db3VudGVyLTAgSGkgRGl2aWRlLEMtQ291bnRlci0wIExvdyBEaXZpZGUsQy1Db3VudGVyLTAgQ29hcnNlIFBoYXNlIFNoaWZ0LEMtQ291bnRlci0wIFZDTyBQaGFzZSBUYXAsQy1Db3VudGVyLTAgSW5wdXQgU291cmNlLEMtQ291bnRlci0wIEJ5cGFzcyBFbmFibGUsQy1Db3VudGVyLTAgT2RkIERpdmlkZSBFbmFibGUsVkNPIFBvc3QgRGl2aWRlIENvdW50ZXIgRW5hYmxlLENoYXJnZSBQdW1wIGN1cnJlbnQgKHVBKSxMb29wIEZpbHRlciBCYW5kd2lkdGggUmVzaXN0b3IgKE9obXMpICxQTEwgT3V0cHV0IFZDTyBGcmVxdWVuY3ksSy1GcmFjdGlvbmFsIERpdmlzaW9uIFZhbHVlIChEU00pLEZlZWRiYWNrIENsb2NrIFR5cGUsRmVlZGJhY2sgQ2xvY2sgTVVYIDEsRmVlZGJhY2sgQ2xvY2sgTVVYIDIsTSBDb3VudGVyIFNvdXJjZSBNVVgsUExMIEF1dG8gUmVzZXQ=::UGFyYW1ldGVyIE5hbWVz" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BhcmFtZXRlcl92YWx1ZXM=::NCw0LDI1NiwyNTYsZmFsc2UsdHJ1ZSxmYWxzZSxmYWxzZSw5LDgsMSwwLHBoX211eF9jbGssZmFsc2UsdHJ1ZSwyLDIwLDQwMDAsNDE3Ljc5MiBNSHosMTUyODMyMTE2Myxub25lLGdsYixtX2NudCxwaF9tdXhfY2xrLHRydWU=::UGFyYW1ldGVyIFZhbHVlcw==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX21pZl9nZW5lcmF0ZQ==::ZmFsc2U=::R2VuZXJhdGUgTUlGIGZpbGU=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9taWZfZHBz::ZmFsc2U=::RW5hYmxlIER5bmFtaWMgUGhhc2UgU2hpZnQgZm9yIE1JRiBzdHJlYW1pbmc=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Rwc19jbnRy::QzA=::RFBTIENvdW50ZXIgU2VsZWN0aW9u" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Rwc19udW0=::MQ==::TnVtYmVyIG9mIER5bmFtaWMgUGhhc2UgU2hpZnRz" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Rwc19kaXI=::UG9zaXRpdmU=::RHluYW1pYyBQaGFzZSBTaGlmdCBEaXJlY3Rpb24=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3JlZmNsa19zd2l0Y2g=::ZmFsc2U=::Q3JlYXRlIGEgc2Vjb25kIGlucHV0IGNsayAncmVmY2xrMSc=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9jYXNjYWRlX291dA==::ZmFsc2U=::Q3JlYXRlIGEgJ2Nhc2NhZGVfb3V0JyBzaWduYWwgdG8gY29ubmVjdCB3aXRoIGEgZG93bnN0cmVhbSBQTEw=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9jYXNjYWRlX2lu::ZmFsc2U=::Q3JlYXRlIGFuIGFkanBsbGluIG9yIGNjbGsgc2lnbmFsIHRvIGNvbm5lY3Qgd2l0aCBhbiB1cHN0cmVhbSBQTEw=" + +set_global_assignment -library "pll_audio" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_audio.v"] +set_global_assignment -library "pll_audio" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_audio/pll_audio_0002.v"] +set_global_assignment -library "pll_audio" -name QIP_FILE [file join $::quartus(qip_path) "pll_audio/pll_audio_0002.qip"] + +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_TOOL_NAME "altera_pll" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_TOOL_VERSION "17.0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_TOOL_ENV "mwpim" diff --git a/sys/pll_audio.v b/sys/pll_audio.v new file mode 100644 index 0000000..e96b248 --- /dev/null +++ b/sys/pll_audio.v @@ -0,0 +1,252 @@ +// megafunction wizard: %Altera PLL v17.0% +// GENERATION: XML +// pll_audio.v + +// Generated using ACDS version 17.0 602 + +`timescale 1 ps / 1 ps +module pll_audio ( + input wire refclk, // refclk.clk + input wire rst, // reset.reset + output wire outclk_0 // outclk0.clk + ); + + pll_audio_0002 pll_audio_inst ( + .refclk (refclk), // refclk.clk + .rst (rst), // reset.reset + .outclk_0 (outclk_0), // outclk0.clk + .locked () // (terminated) + ); + +endmodule +// Retrieval info: +// +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// IPFS_FILES : pll_audio.vo +// RELATED_FILES: pll_audio.v, pll_audio_0002.v diff --git a/sys/pll_audio/pll_audio_0002.qip b/sys/pll_audio/pll_audio_0002.qip new file mode 100644 index 0000000..dadd4b8 --- /dev/null +++ b/sys/pll_audio/pll_audio_0002.qip @@ -0,0 +1,4 @@ +set_instance_assignment -name PLL_COMPENSATION_MODE DIRECT -to "*pll_audio_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_CHANNEL_SPACING "0.0 KHz" -to "*pll_audio_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_AUTO_RESET ON -to "*pll_audio_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_BANDWIDTH_PRESET AUTO -to "*pll_audio_0002*|altera_pll:altera_pll_i*|*" diff --git a/sys/pll_audio/pll_audio_0002.v b/sys/pll_audio/pll_audio_0002.v new file mode 100644 index 0000000..37eea13 --- /dev/null +++ b/sys/pll_audio/pll_audio_0002.v @@ -0,0 +1,87 @@ +`timescale 1ns/10ps +module pll_audio_0002( + + // interface 'refclk' + input wire refclk, + + // interface 'reset' + input wire rst, + + // interface 'outclk0' + output wire outclk_0, + + // interface 'locked' + output wire locked +); + + altera_pll #( + .fractional_vco_multiplier("true"), + .reference_clock_frequency("50.0 MHz"), + .operation_mode("direct"), + .number_of_clocks(1), + .output_clock_frequency0("24.576000 MHz"), + .phase_shift0("0 ps"), + .duty_cycle0(50), + .output_clock_frequency1("0 MHz"), + .phase_shift1("0 ps"), + .duty_cycle1(50), + .output_clock_frequency2("0 MHz"), + .phase_shift2("0 ps"), + .duty_cycle2(50), + .output_clock_frequency3("0 MHz"), + .phase_shift3("0 ps"), + .duty_cycle3(50), + .output_clock_frequency4("0 MHz"), + .phase_shift4("0 ps"), + .duty_cycle4(50), + .output_clock_frequency5("0 MHz"), + .phase_shift5("0 ps"), + .duty_cycle5(50), + .output_clock_frequency6("0 MHz"), + .phase_shift6("0 ps"), + .duty_cycle6(50), + .output_clock_frequency7("0 MHz"), + .phase_shift7("0 ps"), + .duty_cycle7(50), + .output_clock_frequency8("0 MHz"), + .phase_shift8("0 ps"), + .duty_cycle8(50), + .output_clock_frequency9("0 MHz"), + .phase_shift9("0 ps"), + .duty_cycle9(50), + .output_clock_frequency10("0 MHz"), + .phase_shift10("0 ps"), + .duty_cycle10(50), + .output_clock_frequency11("0 MHz"), + .phase_shift11("0 ps"), + .duty_cycle11(50), + .output_clock_frequency12("0 MHz"), + .phase_shift12("0 ps"), + .duty_cycle12(50), + .output_clock_frequency13("0 MHz"), + .phase_shift13("0 ps"), + .duty_cycle13(50), + .output_clock_frequency14("0 MHz"), + .phase_shift14("0 ps"), + .duty_cycle14(50), + .output_clock_frequency15("0 MHz"), + .phase_shift15("0 ps"), + .duty_cycle15(50), + .output_clock_frequency16("0 MHz"), + .phase_shift16("0 ps"), + .duty_cycle16(50), + .output_clock_frequency17("0 MHz"), + .phase_shift17("0 ps"), + .duty_cycle17(50), + .pll_type("General"), + .pll_subtype("General") + ) altera_pll_i ( + .rst (rst), + .outclk ({outclk_0}), + .locked (locked), + .fboutclk ( ), + .fbclk (1'b0), + .refclk (refclk) + ); +endmodule + diff --git a/sys/pll_cfg.qip b/sys/pll_cfg.qip new file mode 100644 index 0000000..c3394be --- /dev/null +++ b/sys/pll_cfg.qip @@ -0,0 +1,44 @@ +set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_TOOL_NAME "altera_pll_reconfig" +set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_TOOL_VERSION "17.0" +set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_TOOL_ENV "mwpim" +set_global_assignment -library "pll_cfg" -name MISC_FILE [file join $::quartus(qip_path) "pll_cfg.cmp"] +set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_TARGETED_DEVICE_FAMILY "Cyclone V" +set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_GENERATED_DEVICE_FAMILY "{Cyclone V}" +set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_QSYS_MODE "UNKNOWN" +set_global_assignment -name SYNTHESIS_ONLY_QIP ON +set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_NAME "cGxsX2hkbWlfY2Zn" +set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_DISPLAY_NAME "QWx0ZXJhIFBMTCBSZWNvbmZpZw==" +set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_REPORT_HIERARCHY "Off" +set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_INTERNAL "Off" +set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_AUTHOR "QWx0ZXJhIENvcnBvcmF0aW9u" +set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_VERSION "MTcuMA==" +set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_DESCRIPTION "QWx0ZXJhIFBoYXNlLUxvY2tlZCBMb29wIFJlY29uZmlndXJhdGlvbiBCbG9jayhBTFRFUkFfUExMX1JFQ09ORklHKQ==" +set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "RU5BQkxFX0JZVEVFTkFCTEU=::ZmFsc2U=::QWRkIGJ5dGVlbmFibGUgcG9ydA==" +set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "QllURUVOQUJMRV9XSURUSA==::NA==::QllURUVOQUJMRV9XSURUSA==" +set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "UkVDT05GSUdfQUREUl9XSURUSA==::Ng==::UkVDT05GSUdfQUREUl9XSURUSA==" +set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "UkVDT05GSUdfREFUQV9XSURUSA==::MzI=::UkVDT05GSUdfREFUQV9XSURUSA==" +set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "cmVjb25mX3dpZHRo::NjQ=::cmVjb25mX3dpZHRo" +set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "V0FJVF9GT1JfTE9DSw==::dHJ1ZQ==::V0FJVF9GT1JfTE9DSw==" +set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_NAME "YWx0ZXJhX3BsbF9yZWNvbmZpZ190b3A=" +set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_DISPLAY_NAME "QWx0ZXJhIFBMTCBSZWNvbmZpZw==" +set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_REPORT_HIERARCHY "Off" +set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_INTERNAL "Off" +set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_AUTHOR "QWx0ZXJhIENvcnBvcmF0aW9u" +set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_VERSION "MTcuMA==" +set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_DESCRIPTION "QWx0ZXJhIFBoYXNlLUxvY2tlZCBMb29wIFJlY29uZmlndXJhdGlvbiBCbG9jayhBTFRFUkFfUExMX1JFQ09ORklHKQ==" +set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "ZGV2aWNlX2ZhbWlseQ==::Q3ljbG9uZSBW::ZGV2aWNlX2ZhbWlseQ==" +set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "RU5BQkxFX01JRg==::ZmFsc2U=::RW5hYmxlIE1JRiBTdHJlYW1pbmc=" +set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "RU5BQkxFX0JZVEVFTkFCTEU=::ZmFsc2U=::QWRkIGJ5dGVlbmFibGUgcG9ydA==" +set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "QllURUVOQUJMRV9XSURUSA==::NA==::QllURUVOQUJMRV9XSURUSA==" +set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "UkVDT05GSUdfQUREUl9XSURUSA==::Ng==::UkVDT05GSUdfQUREUl9XSURUSA==" +set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "UkVDT05GSUdfREFUQV9XSURUSA==::MzI=::UkVDT05GSUdfREFUQV9XSURUSA==" +set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "cmVjb25mX3dpZHRo::NjQ=::cmVjb25mX3dpZHRo" +set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "V0FJVF9GT1JfTE9DSw==::dHJ1ZQ==::V0FJVF9GT1JfTE9DSw==" + +set_global_assignment -library "pll_cfg" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_cfg.v"] +set_global_assignment -library "pll_cfg" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_cfg/altera_pll_reconfig_top.v"] +set_global_assignment -library "pll_cfg" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_cfg/altera_pll_reconfig_core.v"] + +set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_TOOL_NAME "altera_pll_reconfig" +set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_TOOL_VERSION "17.0" +set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_TOOL_ENV "mwpim" diff --git a/sys/pll_cfg.v b/sys/pll_cfg.v new file mode 100644 index 0000000..2a2f078 --- /dev/null +++ b/sys/pll_cfg.v @@ -0,0 +1,86 @@ +// megafunction wizard: %Altera PLL Reconfig v17.0% +// GENERATION: XML +// pll_cfg.v + +// Generated using ACDS version 17.0 598 + +`timescale 1 ps / 1 ps +module pll_cfg #( + parameter ENABLE_BYTEENABLE = 0, + parameter BYTEENABLE_WIDTH = 4, + parameter RECONFIG_ADDR_WIDTH = 6, + parameter RECONFIG_DATA_WIDTH = 32, + parameter reconf_width = 64, + parameter WAIT_FOR_LOCK = 1 + ) ( + input wire mgmt_clk, // mgmt_clk.clk + input wire mgmt_reset, // mgmt_reset.reset + output wire mgmt_waitrequest, // mgmt_avalon_slave.waitrequest + input wire mgmt_read, // .read + input wire mgmt_write, // .write + output wire [31:0] mgmt_readdata, // .readdata + input wire [5:0] mgmt_address, // .address + input wire [31:0] mgmt_writedata, // .writedata + output wire [63:0] reconfig_to_pll, // reconfig_to_pll.reconfig_to_pll + input wire [63:0] reconfig_from_pll // reconfig_from_pll.reconfig_from_pll + ); + + altera_pll_reconfig_top #( + .device_family ("Cyclone V"), + .ENABLE_MIF (0), + .MIF_FILE_NAME ("sys/pll_cfg.mif"), + .ENABLE_BYTEENABLE (ENABLE_BYTEENABLE), + .BYTEENABLE_WIDTH (BYTEENABLE_WIDTH), + .RECONFIG_ADDR_WIDTH (RECONFIG_ADDR_WIDTH), + .RECONFIG_DATA_WIDTH (RECONFIG_DATA_WIDTH), + .reconf_width (reconf_width), + .WAIT_FOR_LOCK (WAIT_FOR_LOCK) + ) pll_cfg_inst ( + .mgmt_clk (mgmt_clk), // mgmt_clk.clk + .mgmt_reset (mgmt_reset), // mgmt_reset.reset + .mgmt_waitrequest (mgmt_waitrequest), // mgmt_avalon_slave.waitrequest + .mgmt_read (mgmt_read), // .read + .mgmt_write (mgmt_write), // .write + .mgmt_readdata (mgmt_readdata), // .readdata + .mgmt_address (mgmt_address), // .address + .mgmt_writedata (mgmt_writedata), // .writedata + .reconfig_to_pll (reconfig_to_pll), // reconfig_to_pll.reconfig_to_pll + .reconfig_from_pll (reconfig_from_pll), // reconfig_from_pll.reconfig_from_pll + .mgmt_byteenable (4'b0000) // (terminated) + ); + +endmodule +// Retrieval info: +// +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// IPFS_FILES : pll_cfg.vo +// RELATED_FILES: pll_cfg.v, altera_pll_reconfig_top.v, altera_pll_reconfig_core.v, altera_std_synchronizer.v diff --git a/sys/pll_cfg/altera_pll_reconfig_core.v b/sys/pll_cfg/altera_pll_reconfig_core.v new file mode 100644 index 0000000..d06a746 --- /dev/null +++ b/sys/pll_cfg/altera_pll_reconfig_core.v @@ -0,0 +1,2184 @@ +// (C) 2001-2017 Intel Corporation. All rights reserved. +// Your use of Intel Corporation's design tools, logic functions and other +// software and tools, and its AMPP partner logic functions, and any output +// files any of the foregoing (including device programming or simulation +// files), and any associated documentation or information are expressly subject +// to the terms and conditions of the Intel Program License Subscription +// Agreement, Intel MegaCore Function License Agreement, or other applicable +// license agreement, including, without limitation, that your use is for the +// sole purpose of programming logic devices manufactured by Intel and sold by +// Intel or its authorized distributors. Please refer to the applicable +// agreement for further details. + + +`timescale 1ps/1ps + +module altera_pll_reconfig_core +#( + parameter reconf_width = 64, + parameter device_family = "Stratix V", + // MIF Streaming parameters + parameter RECONFIG_ADDR_WIDTH = 6, + parameter RECONFIG_DATA_WIDTH = 32, + parameter ROM_ADDR_WIDTH = 9, + parameter ROM_DATA_WIDTH = 32, + parameter ROM_NUM_WORDS = 512 +) ( + + //input + input wire mgmt_clk, + input wire mgmt_reset, + + + //conduits + output wire [reconf_width-1:0] reconfig_to_pll, + input wire [reconf_width-1:0] reconfig_from_pll, + + // user data (avalon-MM slave interface) + output wire [31:0] mgmt_readdata, + output wire mgmt_waitrequest, + input wire [5:0] mgmt_address, + input wire mgmt_read, + input wire mgmt_write, + input wire [31:0] mgmt_writedata, + + //other + output wire mif_start_out, + output reg [ROM_ADDR_WIDTH-1:0] mif_base_addr +); + localparam mode_WR = 1'b0; + localparam mode_POLL = 1'b1; + localparam MODE_REG = 6'b000000; + localparam STATUS_REG = 6'b000001; + localparam START_REG = 6'b000010; + localparam N_REG = 6'b000011; + localparam M_REG = 6'b000100; + localparam C_COUNTERS_REG = 6'b000101; + localparam DPS_REG = 6'b000110; + localparam DSM_REG = 6'b000111; + localparam BWCTRL_REG = 6'b001000; + localparam CP_CURRENT_REG = 6'b001001; + localparam ANY_DPRIO = 6'b100000; + localparam CNT_BASE = 5'b001010; + localparam VCO_REG = 6'b011100; + localparam MIF_REG = 6'b011111; + + //C Counters + localparam number_of_counters = 5'd18; + localparam CNT_0 = 1'd0, CNT_1 = 5'd1, CNT_2 = 5'd2, + CNT_3 = 5'd3, CNT_4 = 5'd4, CNT_5 = 5'd5, + CNT_6 = 5'd6, CNT_7 = 5'd7, CNT_8 = 5'd8, + CNT_9 = 5'd9, CNT_10 = 5'd10, CNT_11 = 5'd11, + CNT_12 = 5'd12, CNT_13 = 5'd13, CNT_14 = 5'd14, + CNT_15 = 5'd15, CNT_16 = 5'd16, CNT_17 = 5'd17; + //C counter addresses + localparam C_CNT_0_DIV_ADDR = 5'h00; + localparam C_CNT_0_DIV_ADDR_DPRIO_1 = 5'h11; + localparam C_CNT_0_3_BYPASS_EN_ADDR = 5'h15; + localparam C_CNT_0_3_ODD_DIV_EN_ADDR = 5'h17; + localparam C_CNT_4_17_BYPASS_EN_ADDR = 5'h14; + localparam C_CNT_4_17_ODD_DIV_EN_ADDR = 5'h16; + //N counter addresses + localparam N_CNT_DIV_ADDR = 5'h13; + localparam N_CNT_BYPASS_EN_ADDR = 5'h15; + localparam N_CNT_ODD_DIV_EN_ADDR = 5'h17; + //M counter addresses + localparam M_CNT_DIV_ADDR = 5'h12; + localparam M_CNT_BYPASS_EN_ADDR = 5'h15; + localparam M_CNT_ODD_DIV_EN_ADDR = 5'h17; + + //DSM address + localparam DSM_K_FRACTIONAL_DIVISION_ADDR_0 = 5'h18; + localparam DSM_K_FRACTIONAL_DIVISION_ADDR_1 = 5'h19; + localparam DSM_K_READY_ADDR = 5'h17; + localparam DSM_K_DITHER_ADDR = 5'h17; + localparam DSM_OUT_SEL_ADDR = 6'h30; + + //Other DSM params + localparam DSM_K_READY_BIT_INDEX = 4'd11; + //BWCTRL address + //Bit 0-3 of addr + localparam BWCTRL_ADDR = 6'h30; + //CP_CURRENT address + //Bit 0-2 of addr + localparam CP_CURRENT_ADDR = 6'h31; + + // VCODIV address + localparam VCO_ADDR = 5'h17; + + localparam DPRIO_IDLE = 3'd0, ONE = 3'd1, TWO = 3'd2, THREE = 3'd3, FOUR = 3'd4, + FIVE = 3'd5, SIX = 3'd6, SEVEN = 3'd7, EIGHT = 4'd8, NINE = 4'd9, TEN = 4'd10, + ELEVEN = 4'd11, TWELVE = 4'd12, THIRTEEN = 4'd13, FOURTEEN = 4'd14, DPRIO_DONE = 4'd15; + localparam IDLE = 2'b00, WAIT_ON_LOCK = 2'b01, LOCKED = 2'b10; + + wire clk; + wire reset; + wire gnd; + + wire [5: 0] slave_address; + wire slave_read; + wire slave_write; + wire [31: 0] slave_writedata; + + reg [31: 0] slave_readdata_d; + reg [31: 0] slave_readdata_q; + wire slave_waitrequest; + reg slave_mode; + + assign clk = mgmt_clk; + + assign slave_address = mgmt_address; + assign slave_read = mgmt_read; + assign slave_write = mgmt_write; + assign slave_writedata = mgmt_writedata; + + reg read_waitrequest; + // Outputs + assign mgmt_readdata = slave_readdata_q; + assign mgmt_waitrequest = slave_waitrequest | read_waitrequest; //Read waitrequest asserted in polling mode + + //internal signals + wire locked_orig; + wire locked; + + wire pll_start; + wire pll_start_valid; + reg status_read; + wire read_slave_mode_asserted; + + wire pll_start_asserted; + + reg [1:0] current_state; + reg [1:0] next_state; + + reg status;//0=busy, 1=ready + //user_mode_init user_mode_init_inst (clk, reset, dprio_mdio_dis, ser_shift_load); + //declaring the init wires. These will have 0 on them for 64 clk cycles + wire [ 5:0] init_dprio_address; + wire init_dprio_read; + wire [ 1:0] init_dprio_byteen; + wire init_dprio_write; + wire [15:0] init_dprio_writedata; + + wire init_atpgmode; + wire init_mdio_dis; + wire init_scanen; + wire init_ser_shift_load; + wire dprio_init_done; + + //DPRIO output signals after initialization is done + wire dprio_clk; + reg avmm_dprio_write; + reg avmm_dprio_read; + reg [5:0] avmm_dprio_address; + reg [15:0] avmm_dprio_writedata; + reg [1:0] avmm_dprio_byteen; + wire avmm_atpgmode; + wire avmm_mdio_dis; + wire avmm_scanen; + + //Final output wires that are muxed between the init and avmm wires. + wire dprio_init_reset; + wire [5:0] dprio_address /*synthesis keep*/; + wire dprio_read/*synthesis keep*/; + wire [1:0] dprio_byteen/*synthesis keep*/; + wire dprio_write/*synthesis keep*/; + wire [15:0] dprio_writedata/*synthesis keep*/; + wire dprio_mdio_dis/*synthesis keep*/; + wire dprio_ser_shift_load/*synthesis keep*/; + wire dprio_atpgmode/*synthesis keep*/; + wire dprio_scanen/*synthesis keep*/; + + + //other PLL signals for dyn ph shift + wire phase_done/*synthesis keep*/; + wire phase_en/*synthesis keep*/; + wire up_dn/*synthesis keep*/; + wire [4:0] cnt_sel; + + //DPRIO input signals + wire [15:0] dprio_readdata; + + //internal logic signals + //storage registers for user sent data + reg dprio_temp_read_1; + reg dprio_temp_read_2; + reg dprio_start; + reg mif_start_assert; + reg dps_start_assert; + wire usr_valid_changes; + reg [3:0] dprio_cur_state; + reg [3:0] dprio_next_state; + reg [15:0] dprio_temp_m_n_c_readdata_1_d; + reg [15:0] dprio_temp_m_n_c_readdata_2_d; + reg [15:0] dprio_temp_m_n_c_readdata_1_q; + reg [15:0] dprio_temp_m_n_c_readdata_2_q; + reg dprio_write_done; + //C counters signals + reg [7:0] usr_c_cnt_lo; + reg [7:0] usr_c_cnt_hi; + reg usr_c_cnt_bypass_en; + reg usr_c_cnt_odd_duty_div_en; + reg [7:0] temp_c_cnt_lo [0:17]; + reg [7:0] temp_c_cnt_hi [0:17]; + reg temp_c_cnt_bypass_en [0:17]; + reg temp_c_cnt_odd_duty_div_en [0:17]; + reg any_c_cnt_changed; + reg all_c_cnt_done_q; + reg all_c_cnt_done_d; + reg [17:0] c_cnt_changed; + reg [17:0] c_cnt_done_d; + reg [17:0] c_cnt_done_q; + //N counter signals + reg [7:0] usr_n_cnt_lo; + reg [7:0] usr_n_cnt_hi; + reg usr_n_cnt_bypass_en; + reg usr_n_cnt_odd_duty_div_en; + reg n_cnt_changed; + reg n_cnt_done_d; + reg n_cnt_done_q; + //M counter signals + reg [7:0] usr_m_cnt_lo; + reg [7:0] usr_m_cnt_hi; + reg usr_m_cnt_bypass_en; + reg usr_m_cnt_odd_duty_div_en; + reg m_cnt_changed; + reg m_cnt_done_d; + reg m_cnt_done_q; + //dyn phase regs + reg [15:0] usr_num_shifts; + reg [4:0] usr_cnt_sel /*synthesis preserve*/; + reg usr_up_dn; + reg dps_changed; + wire dps_changed_valid; + wire dps_done; + + //DSM Signals + reg [31:0] usr_k_value; + reg dsm_k_changed; + reg dsm_k_done_d; + reg dsm_k_done_q; + reg dsm_k_ready_false_done_d; + //BW signals + reg [3:0] usr_bwctrl_value; + reg bwctrl_changed; + reg bwctrl_done_d; + reg bwctrl_done_q; + //CP signals + reg [2:0] usr_cp_current_value; + reg cp_current_changed; + reg cp_current_done_d; + reg cp_current_done_q; + //VCO signals + reg usr_vco_value; + reg vco_changed; + reg vco_done_d; + reg vco_done_q; + //Manual DPRIO signals + reg manual_dprio_done_q; + reg manual_dprio_done_d; + reg manual_dprio_changed; + reg [5:0] usr_dprio_address; + reg [15:0] usr_dprio_writedata_0; + reg usr_r_w; + //keeping track of which operation happened last + reg [5:0] operation_address; + // Address wires for all C_counter DPRIO registers + // These are outputs of LUTS, changing depending + // on whether PLL_0 or PLL_1 being used + + + //Fitter will tell if FPLL1 is being used + wire fpll_1; + + // other + reg mif_reg_asserted; + // MAIN FSM + + // Synchronize locked signal + altera_std_synchronizer #( + .depth(3) + ) altera_std_synchronizer_inst ( + .clk(mgmt_clk), + .reset_n(~mgmt_reset), + .din(locked_orig), + .dout(locked) + ); + + always @(posedge clk) + begin + if (reset) + begin + dprio_cur_state <= DPRIO_IDLE; + current_state <= IDLE; + end + else + begin + current_state <= next_state; + dprio_cur_state <= dprio_next_state; + end + end + + always @(*) + begin + case(current_state) + IDLE: + begin + if (pll_start & !slave_waitrequest & usr_valid_changes) + next_state = WAIT_ON_LOCK; + else + next_state = IDLE; + end + WAIT_ON_LOCK: + begin + if (locked & dps_done & dprio_write_done) // received locked high from PLL + begin + if (slave_mode==mode_WR) //if the mode is waitrequest, then + // goto IDLE state directly + next_state = IDLE; + else + next_state = LOCKED; //otherwise go the locked state + end + else + next_state = WAIT_ON_LOCK; + end + + LOCKED: + begin + if (status_read) // stay in LOCKED until user reads status + next_state = IDLE; + else + next_state = LOCKED; + end + + default: next_state = 2'bxx; + + endcase + end + + + // ask the pll to start reconfig + assign pll_start = (pll_start_asserted & (current_state==IDLE)) ; + assign pll_start_valid = (pll_start & (next_state==WAIT_ON_LOCK)) ; + + + + // WRITE OPERATIONS + assign pll_start_asserted = slave_write & (slave_address == START_REG); + assign mif_start_out = pll_start & mif_reg_asserted; + + //reading the mode register to determine what mode the slave will operate + //in. + always @(posedge clk) + begin + if (reset) + slave_mode <= mode_WR; + else if (slave_write & (slave_address == MODE_REG) & !slave_waitrequest) + slave_mode <= slave_writedata[0]; + end + + //record which values user wants to change. + + //reading in the actual values that need to be reconfigged and sending + //them to the PLL + always @(posedge clk) + begin + if (reset) + begin + //reset all regs here + //BW signals reset + usr_bwctrl_value <= 0; + bwctrl_changed <= 0; + bwctrl_done_q <= 0; + //CP signals reset + usr_cp_current_value <= 0; + cp_current_changed <= 0; + cp_current_done_q <= 0; + //VCO signals reset + usr_vco_value <= 0; + vco_changed <= 0; + vco_done_q <= 0; + //DSM signals reset + usr_k_value <= 0; + dsm_k_changed <= 0; + dsm_k_done_q <= 0; + //N counter signals reset + usr_n_cnt_lo <= 0; + usr_n_cnt_hi <= 0; + usr_n_cnt_bypass_en <= 0; + usr_n_cnt_odd_duty_div_en <= 0; + n_cnt_changed <= 0; + n_cnt_done_q <= 0; + //M counter signals reset + usr_m_cnt_lo <= 0; + usr_m_cnt_hi <= 0; + usr_m_cnt_bypass_en <= 0; + usr_m_cnt_odd_duty_div_en <= 0; + m_cnt_changed <= 0; + m_cnt_done_q <= 0; + //C counter signals reset + usr_c_cnt_lo <= 0; + usr_c_cnt_hi <= 0; + usr_c_cnt_bypass_en <= 0; + usr_c_cnt_odd_duty_div_en <= 0; + any_c_cnt_changed <= 0; + all_c_cnt_done_q <= 0; + c_cnt_done_q <= 0; + //generic signals + dprio_start <= 0; + mif_start_assert <= 0; + dps_start_assert <= 0; + dprio_temp_m_n_c_readdata_1_q <= 0; + dprio_temp_m_n_c_readdata_2_q <= 0; + c_cnt_done_q <= 0; + //DPS signals + usr_up_dn <= 0; + usr_cnt_sel <= 0; + usr_num_shifts <= 0; + dps_changed <= 0; + //manual DPRIO signals + manual_dprio_changed <= 0; + usr_dprio_address <= 0; + usr_dprio_writedata_0 <= 0; + usr_r_w <= 0; + operation_address <= 0; + mif_reg_asserted <= 0; + mif_base_addr <= 0; + end + else + begin + if (dprio_temp_read_1) + begin + dprio_temp_m_n_c_readdata_1_q <= dprio_temp_m_n_c_readdata_1_d; + end + if (dprio_temp_read_2) + begin + dprio_temp_m_n_c_readdata_2_q <= dprio_temp_m_n_c_readdata_2_d; + end + if ((dps_done)) dps_changed <= 0; + if (dsm_k_done_d) dsm_k_done_q <= dsm_k_done_d; + if (n_cnt_done_d) n_cnt_done_q <= n_cnt_done_d; + if (m_cnt_done_d) m_cnt_done_q <= m_cnt_done_d; + if (all_c_cnt_done_d) all_c_cnt_done_q <= all_c_cnt_done_d; + if (c_cnt_done_d != 0) c_cnt_done_q <= c_cnt_done_q | c_cnt_done_d; + if (bwctrl_done_d) bwctrl_done_q <= bwctrl_done_d; + if (cp_current_done_d) cp_current_done_q <= cp_current_done_d; + if (vco_done_d) vco_done_q <= vco_done_d; + if (manual_dprio_done_d) manual_dprio_done_q <= manual_dprio_done_d; + + if (mif_start_out == 1'b1) + mif_start_assert <= 0; // Signaled MIF block to start, so deassert on next cycle + + if (dps_done != 1'b1) + dps_start_assert <= 0; // DPS has started, so dessert its start signal on next cycle + + if (dprio_next_state == ONE) + dprio_start <= 0; + if (dprio_write_done) + begin + bwctrl_done_q <= 0; + cp_current_done_q <= 0; + vco_done_q <= 0; + dsm_k_done_q <= 0; + dsm_k_done_q <= 0; + n_cnt_done_q <= 0; + m_cnt_done_q <= 0; + all_c_cnt_done_q <= 0; + c_cnt_done_q <= 0; + dsm_k_changed <= 0; + n_cnt_changed <= 0; + m_cnt_changed <= 0; + any_c_cnt_changed <= 0; + bwctrl_changed <= 0; + cp_current_changed <= 0; + vco_changed <= 0; + manual_dprio_changed <= 0; + manual_dprio_done_q <= 0; + if (dps_changed | dps_changed_valid | !dps_done ) + begin + usr_cnt_sel <= usr_cnt_sel; + end + else + begin + usr_cnt_sel <= 0; + end + mif_reg_asserted <= 0; + end + else + begin + dsm_k_changed <= dsm_k_changed; + n_cnt_changed <= n_cnt_changed; + m_cnt_changed <= m_cnt_changed; + any_c_cnt_changed <= any_c_cnt_changed; + manual_dprio_changed <= manual_dprio_changed; + mif_reg_asserted <= mif_reg_asserted; + usr_cnt_sel <= usr_cnt_sel; + end + + + if(slave_write & !slave_waitrequest) + begin + case(slave_address) + //read in the values here from the user and act on them + DSM_REG: + begin + operation_address <= DSM_REG; + usr_k_value <= slave_writedata[31:0]; + dsm_k_changed <= 1'b1; + dsm_k_done_q <= 0; + dprio_start <= 1'b1; + end + N_REG: + begin + operation_address <= N_REG; + usr_n_cnt_lo <= slave_writedata[7:0]; + usr_n_cnt_hi <= slave_writedata[15:8]; + usr_n_cnt_bypass_en <= slave_writedata[16]; + usr_n_cnt_odd_duty_div_en <= slave_writedata[17]; + n_cnt_changed <= 1'b1; + n_cnt_done_q <= 0; + dprio_start <= 1'b1; + end + M_REG: + begin + operation_address <= M_REG; + usr_m_cnt_lo <= slave_writedata[7:0]; + usr_m_cnt_hi <= slave_writedata[15:8]; + usr_m_cnt_bypass_en <= slave_writedata[16]; + usr_m_cnt_odd_duty_div_en <= slave_writedata[17]; + m_cnt_changed <= 1'b1; + m_cnt_done_q <= 0; + dprio_start <= 1'b1; + end + DPS_REG: + begin + operation_address <= DPS_REG; + usr_num_shifts <= slave_writedata[15:0]; + usr_cnt_sel <= slave_writedata[20:16]; + usr_up_dn <= slave_writedata[21]; + dps_changed <= 1; + dps_start_assert <= 1; + end + C_COUNTERS_REG: + begin + operation_address <= C_COUNTERS_REG; + usr_c_cnt_lo <= slave_writedata[7:0]; + usr_c_cnt_hi <= slave_writedata[15:8]; + usr_c_cnt_bypass_en <= slave_writedata[16]; + usr_c_cnt_odd_duty_div_en <= slave_writedata[17]; + usr_cnt_sel <= slave_writedata[22:18]; + any_c_cnt_changed <= 1'b1; + all_c_cnt_done_q <= 0; + dprio_start <= 1'b1; + end + BWCTRL_REG: + begin + usr_bwctrl_value <= slave_writedata[3:0]; + bwctrl_changed <= 1'b1; + bwctrl_done_q <= 0; + dprio_start <= 1'b1; + operation_address <= BWCTRL_REG; + end + CP_CURRENT_REG: + begin + usr_cp_current_value <= slave_writedata[2:0]; + cp_current_changed <= 1'b1; + cp_current_done_q <= 0; + dprio_start <= 1'b1; + operation_address <= CP_CURRENT_REG; + end + VCO_REG: + begin + usr_vco_value <= slave_writedata[0]; + vco_changed <= 1'b1; + vco_done_q <= 0; + dprio_start <= 1'b1; + operation_address <= VCO_REG; + end + ANY_DPRIO: + begin + operation_address <= ANY_DPRIO; + manual_dprio_changed <= 1'b1; + usr_dprio_address <= slave_writedata[5:0]; + usr_dprio_writedata_0 <= slave_writedata[21:6]; + usr_r_w <= slave_writedata[22]; + manual_dprio_done_q <= 0; + dprio_start <= 1'b1; + end + MIF_REG: + begin + mif_reg_asserted <= 1'b1; + mif_base_addr <= slave_writedata[ROM_ADDR_WIDTH-1:0]; + mif_start_assert <= 1'b1; + end + endcase + end + end + end + //C Counter assigning values to the 2-d array of values for each C counter + + reg [4:0] j; + always @(posedge clk) + begin + + if (reset) + begin + c_cnt_changed[17:0] <= 0; + for (j = 0; j < number_of_counters; j = j + 1'b1) + begin : c_cnt_reset + temp_c_cnt_bypass_en[j] <= 0; + temp_c_cnt_odd_duty_div_en[j] <= 0; + temp_c_cnt_lo[j][7:0] <= 0; + temp_c_cnt_hi[j][7:0] <= 0; + end + end + else + begin + if (dprio_write_done) + begin + c_cnt_changed <= 0; + end + if (any_c_cnt_changed && (operation_address == C_COUNTERS_REG)) + begin + case (cnt_sel) + CNT_0: + begin + temp_c_cnt_lo [0] <= usr_c_cnt_lo; + temp_c_cnt_hi [0] <= usr_c_cnt_hi; + temp_c_cnt_bypass_en [0] <= usr_c_cnt_bypass_en; + temp_c_cnt_odd_duty_div_en [0] <= usr_c_cnt_odd_duty_div_en; + c_cnt_changed [0] <= 1'b1; + end + CNT_1: + begin + temp_c_cnt_lo [1] <= usr_c_cnt_lo; + temp_c_cnt_hi [1] <= usr_c_cnt_hi; + temp_c_cnt_bypass_en [1] <= usr_c_cnt_bypass_en; + temp_c_cnt_odd_duty_div_en [1] <= usr_c_cnt_odd_duty_div_en; + c_cnt_changed [1] <= 1'b1; + end + CNT_2: + begin + temp_c_cnt_lo [2] <= usr_c_cnt_lo; + temp_c_cnt_hi [2] <= usr_c_cnt_hi; + temp_c_cnt_bypass_en [2] <= usr_c_cnt_bypass_en; + temp_c_cnt_odd_duty_div_en [2] <= usr_c_cnt_odd_duty_div_en; + c_cnt_changed [2] <= 1'b1; + end + CNT_3: + begin + temp_c_cnt_lo [3] <= usr_c_cnt_lo; + temp_c_cnt_hi [3] <= usr_c_cnt_hi; + temp_c_cnt_bypass_en [3] <= usr_c_cnt_bypass_en; + temp_c_cnt_odd_duty_div_en [3] <= usr_c_cnt_odd_duty_div_en; + c_cnt_changed [3] <= 1'b1; + end + CNT_4: + begin + temp_c_cnt_lo [4] <= usr_c_cnt_lo; + temp_c_cnt_hi [4] <= usr_c_cnt_hi; + temp_c_cnt_bypass_en [4] <= usr_c_cnt_bypass_en; + temp_c_cnt_odd_duty_div_en [4] <= usr_c_cnt_odd_duty_div_en; + c_cnt_changed [4] <= 1'b1; + end + CNT_5: + begin + temp_c_cnt_lo [5] <= usr_c_cnt_lo; + temp_c_cnt_hi [5] <= usr_c_cnt_hi; + temp_c_cnt_bypass_en [5] <= usr_c_cnt_bypass_en; + temp_c_cnt_odd_duty_div_en [5] <= usr_c_cnt_odd_duty_div_en; + c_cnt_changed [5] <= 1'b1; + end + CNT_6: + begin + temp_c_cnt_lo [6] <= usr_c_cnt_lo; + temp_c_cnt_hi [6] <= usr_c_cnt_hi; + temp_c_cnt_bypass_en [6] <= usr_c_cnt_bypass_en; + temp_c_cnt_odd_duty_div_en [6] <= usr_c_cnt_odd_duty_div_en; + c_cnt_changed [6] <= 1'b1; + end + CNT_7: + begin + temp_c_cnt_lo [7] <= usr_c_cnt_lo; + temp_c_cnt_hi [7] <= usr_c_cnt_hi; + temp_c_cnt_bypass_en [7] <= usr_c_cnt_bypass_en; + temp_c_cnt_odd_duty_div_en [7] <= usr_c_cnt_odd_duty_div_en; + c_cnt_changed [7] <= 1'b1; + end + CNT_8: + begin + temp_c_cnt_lo [8] <= usr_c_cnt_lo; + temp_c_cnt_hi [8] <= usr_c_cnt_hi; + temp_c_cnt_bypass_en [8] <= usr_c_cnt_bypass_en; + temp_c_cnt_odd_duty_div_en [8] <= usr_c_cnt_odd_duty_div_en; + c_cnt_changed [8] <= 1'b1; + end + CNT_9: + begin + temp_c_cnt_lo [9] <= usr_c_cnt_lo; + temp_c_cnt_hi [9] <= usr_c_cnt_hi; + temp_c_cnt_bypass_en [9] <= usr_c_cnt_bypass_en; + temp_c_cnt_odd_duty_div_en [9] <= usr_c_cnt_odd_duty_div_en; + c_cnt_changed [9] <= 1'b1; + end + CNT_10: + begin + temp_c_cnt_lo [10] <= usr_c_cnt_lo; + temp_c_cnt_hi [10] <= usr_c_cnt_hi; + temp_c_cnt_bypass_en [10] <= usr_c_cnt_bypass_en; + temp_c_cnt_odd_duty_div_en [10] <= usr_c_cnt_odd_duty_div_en; + c_cnt_changed [10] <= 1'b1; + end + CNT_11: + begin + temp_c_cnt_lo [11] <= usr_c_cnt_lo; + temp_c_cnt_hi [11] <= usr_c_cnt_hi; + temp_c_cnt_bypass_en [11] <= usr_c_cnt_bypass_en; + temp_c_cnt_odd_duty_div_en [11] <= usr_c_cnt_odd_duty_div_en; + c_cnt_changed [11] <= 1'b1; + end + CNT_12: + begin + temp_c_cnt_lo [12] <= usr_c_cnt_lo; + temp_c_cnt_hi [12] <= usr_c_cnt_hi; + temp_c_cnt_bypass_en [12] <= usr_c_cnt_bypass_en; + temp_c_cnt_odd_duty_div_en [12] <= usr_c_cnt_odd_duty_div_en; + c_cnt_changed [12] <= 1'b1; + end + CNT_13: + begin + temp_c_cnt_lo [13] <= usr_c_cnt_lo; + temp_c_cnt_hi [13] <= usr_c_cnt_hi; + temp_c_cnt_bypass_en [13] <= usr_c_cnt_bypass_en; + temp_c_cnt_odd_duty_div_en [13] <= usr_c_cnt_odd_duty_div_en; + c_cnt_changed [13] <= 1'b1; + end + CNT_14: + begin + temp_c_cnt_lo [14] <= usr_c_cnt_lo; + temp_c_cnt_hi [14] <= usr_c_cnt_hi; + temp_c_cnt_bypass_en [14] <= usr_c_cnt_bypass_en; + temp_c_cnt_odd_duty_div_en [14] <= usr_c_cnt_odd_duty_div_en; + c_cnt_changed [14] <= 1'b1; + end + CNT_15: + begin + temp_c_cnt_lo [15] <= usr_c_cnt_lo; + temp_c_cnt_hi [15] <= usr_c_cnt_hi; + temp_c_cnt_bypass_en [15] <= usr_c_cnt_bypass_en; + temp_c_cnt_odd_duty_div_en [15] <= usr_c_cnt_odd_duty_div_en; + c_cnt_changed [15] <= 1'b1; + end + CNT_16: + begin + temp_c_cnt_lo [16] <= usr_c_cnt_lo; + temp_c_cnt_hi [16] <= usr_c_cnt_hi; + temp_c_cnt_bypass_en [16] <= usr_c_cnt_bypass_en; + temp_c_cnt_odd_duty_div_en [16] <= usr_c_cnt_odd_duty_div_en; + c_cnt_changed [16] <= 1'b1; + end + CNT_17: + begin + temp_c_cnt_lo [17] <= usr_c_cnt_lo; + temp_c_cnt_hi [17] <= usr_c_cnt_hi; + temp_c_cnt_bypass_en [17] <= usr_c_cnt_bypass_en; + temp_c_cnt_odd_duty_div_en [17] <= usr_c_cnt_odd_duty_div_en; + c_cnt_changed [17] <= 1'b1; + end + endcase + + end + end + end + + + //logic to handle which writes the user indicated and wants to start. + assign usr_valid_changes =dsm_k_changed| any_c_cnt_changed |n_cnt_changed | m_cnt_changed | dps_changed_valid |manual_dprio_changed |cp_current_changed|bwctrl_changed|vco_changed; + + + //start the reconfig operations by writing to the DPRIO + reg break_loop; + reg [4:0] i; + always @(*) + begin + dprio_temp_read_1 = 0; + dprio_temp_read_2 = 0; + dprio_temp_m_n_c_readdata_1_d = 0; + dprio_temp_m_n_c_readdata_2_d = 0; + break_loop = 0; + dprio_next_state = DPRIO_IDLE; + avmm_dprio_write = 0; + avmm_dprio_read = 0; + avmm_dprio_address = 0; + avmm_dprio_writedata = 0; + avmm_dprio_byteen = 0; + dprio_write_done = 1; + manual_dprio_done_d = 0; + n_cnt_done_d = 0; + dsm_k_done_d = 0; + dsm_k_ready_false_done_d = 0; + m_cnt_done_d = 0; + c_cnt_done_d[17:0] = 0; + all_c_cnt_done_d = 0; + bwctrl_done_d = 0; + cp_current_done_d = 0; + vco_done_d = 0; + i = 0; + + // Deassert dprio_write_done so it doesn't reset mif_reg_asserted (toggled writes) + if (dprio_start | mif_start_assert) + dprio_write_done = 0; + + if (current_state == WAIT_ON_LOCK) + begin + case (dprio_cur_state) + ONE: + begin + if (n_cnt_changed & !n_cnt_done_q) + begin + dprio_write_done = 0; + avmm_dprio_write = 1'b1; + avmm_dprio_byteen = 2'b11; + dprio_next_state = TWO; + avmm_dprio_address = N_CNT_DIV_ADDR; + avmm_dprio_writedata[7:0] = usr_n_cnt_lo; + avmm_dprio_writedata[15:8] = usr_n_cnt_hi; + end + else if (m_cnt_changed & !m_cnt_done_q) + begin + dprio_write_done = 0; + avmm_dprio_write = 1'b1; + avmm_dprio_byteen = 2'b11; + dprio_next_state = TWO; + avmm_dprio_address = M_CNT_DIV_ADDR; + avmm_dprio_writedata[7:0] = usr_m_cnt_lo; + avmm_dprio_writedata[15:8] = usr_m_cnt_hi; + end + else if (any_c_cnt_changed & !all_c_cnt_done_q) + begin + + for (i = 0; (i < number_of_counters) & !break_loop; i = i + 1'b1) + begin : c_cnt_write_hilo + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + dprio_write_done = 0; + avmm_dprio_write = 1'b1; + avmm_dprio_byteen = 2'b11; + dprio_next_state = TWO; + if (fpll_1) avmm_dprio_address = C_CNT_0_DIV_ADDR + C_CNT_0_DIV_ADDR_DPRIO_1 - i; + else avmm_dprio_address = C_CNT_0_DIV_ADDR + i; + avmm_dprio_writedata[7:0] = temp_c_cnt_lo[i]; + avmm_dprio_writedata[15:8] = temp_c_cnt_hi[i]; + //To break from the loop, since only one counter + //is addressed at a time + break_loop = 1'b1; + end + end + end + else if (dsm_k_changed & !dsm_k_done_q) + begin + dprio_write_done = 0; + avmm_dprio_write = 0; + dprio_next_state = TWO; + end + else if (bwctrl_changed & !bwctrl_done_q) + begin + dprio_write_done = 0; + avmm_dprio_write = 0; + dprio_next_state = TWO; + end + else if (cp_current_changed & !cp_current_done_q) + begin + dprio_write_done = 0; + avmm_dprio_write = 0; + dprio_next_state = TWO; + end + else if (vco_changed & !vco_done_q) + begin + dprio_write_done = 0; + avmm_dprio_write = 0; + dprio_next_state = TWO; + end + else if (manual_dprio_changed & !manual_dprio_done_q) + begin + dprio_write_done = 0; + avmm_dprio_byteen = 2'b11; + dprio_next_state = TWO; + avmm_dprio_write = usr_r_w; + avmm_dprio_address = usr_dprio_address; + avmm_dprio_writedata[15:0] = usr_dprio_writedata_0; + end + else dprio_next_state = DPRIO_IDLE; + end + + TWO: + begin + //handle reading the two setting bits on n_cnt, then + //writing them back while preserving other bits. + //Issue two consecutive reads then wait; readLatency=3 + dprio_write_done = 0; + dprio_next_state = THREE; + avmm_dprio_byteen = 2'b11; + avmm_dprio_read = 1'b1; + if (n_cnt_changed & !n_cnt_done_q) + begin + avmm_dprio_address = N_CNT_BYPASS_EN_ADDR; + end + else if (m_cnt_changed & !m_cnt_done_q) + begin + avmm_dprio_address = M_CNT_BYPASS_EN_ADDR; + end + + else if (any_c_cnt_changed & !all_c_cnt_done_q) + begin + for (i = 0; (i < number_of_counters) & !break_loop; i = i + 1'b1) + begin : c_cnt_read_bypass + if (fpll_1) + begin + if (i > 13) + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_0_3_BYPASS_EN_ADDR; + break_loop = 1'b1; + end + end + else + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_4_17_BYPASS_EN_ADDR; + break_loop = 1'b1; + end + end + end + else + begin + if (i < 4) + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_0_3_BYPASS_EN_ADDR; + break_loop = 1'b1; + end + end + else + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_4_17_BYPASS_EN_ADDR; + break_loop = 1'b1; + end + end + end + end + end + //reading the K ready 16 bit word. Need to write 0 to it + //afterwards to indicate that K has not been done writing + else if (dsm_k_changed & !dsm_k_done_q) + begin + avmm_dprio_address = DSM_K_READY_ADDR; + dprio_next_state = FOUR; + end + else if (bwctrl_changed & !bwctrl_done_q) + begin + avmm_dprio_address = BWCTRL_ADDR; + dprio_next_state = FOUR; + end + else if (cp_current_changed & !cp_current_done_q) + begin + avmm_dprio_address = CP_CURRENT_ADDR; + dprio_next_state = FOUR; + end + else if (vco_changed & !vco_done_q) + begin + avmm_dprio_address = VCO_ADDR; + dprio_next_state = FOUR; + end + else if (manual_dprio_changed & !manual_dprio_done_q) + begin + avmm_dprio_read = ~usr_r_w; + avmm_dprio_address = usr_dprio_address; + dprio_next_state = DPRIO_DONE; + end + else dprio_next_state = DPRIO_IDLE; + end + THREE: + begin + dprio_write_done = 0; + avmm_dprio_byteen = 2'b11; + avmm_dprio_read = 1'b1; + dprio_next_state = FOUR; + if (n_cnt_changed & !n_cnt_done_q) + begin + avmm_dprio_address = N_CNT_ODD_DIV_EN_ADDR; + end + else if (m_cnt_changed & !m_cnt_done_q) + begin + avmm_dprio_address = M_CNT_ODD_DIV_EN_ADDR; + end + else if (any_c_cnt_changed & !all_c_cnt_done_q) + begin + for (i = 0; (i < number_of_counters) & !break_loop; i = i + 1'b1) + begin : c_cnt_read_odd_div + if (fpll_1) + begin + if (i > 13) + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_0_3_ODD_DIV_EN_ADDR; + break_loop = 1'b1; + end + end + else + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_4_17_ODD_DIV_EN_ADDR; + break_loop = 1'b1; + end + end + end + else + begin + if (i < 4) + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_0_3_ODD_DIV_EN_ADDR; + break_loop = 1'b1; + end + end + else + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_4_17_ODD_DIV_EN_ADDR; + break_loop = 1'b1; + end + end + end + end + end + else dprio_next_state = DPRIO_IDLE; + end + FOUR: + begin + dprio_temp_read_1 = 1'b1; + dprio_write_done = 0; + if (vco_changed|cp_current_changed|bwctrl_changed|dsm_k_changed|n_cnt_changed|m_cnt_changed|any_c_cnt_changed) + begin + dprio_temp_m_n_c_readdata_1_d = dprio_readdata; + dprio_next_state = FIVE; + end + else dprio_next_state = DPRIO_IDLE; + end + FIVE: + begin + dprio_write_done = 0; + dprio_temp_read_2 = 1'b1; + if (vco_changed|cp_current_changed|bwctrl_changed|dsm_k_changed|n_cnt_changed|m_cnt_changed|any_c_cnt_changed) + begin + //this is where DSM ready value comes. + //Need to store in a register to be used later + dprio_temp_m_n_c_readdata_2_d = dprio_readdata; + dprio_next_state = SIX; + end + else dprio_next_state = DPRIO_IDLE; + end + SIX: + begin + dprio_write_done = 0; + avmm_dprio_write = 1'b1; + avmm_dprio_byteen = 2'b11; + dprio_next_state = SEVEN; + avmm_dprio_writedata = dprio_temp_m_n_c_readdata_1_q; + if (n_cnt_changed & !n_cnt_done_q) + begin + avmm_dprio_address = N_CNT_BYPASS_EN_ADDR; + avmm_dprio_writedata[5] = usr_n_cnt_bypass_en; + end + else if (m_cnt_changed & !m_cnt_done_q) + begin + avmm_dprio_address = M_CNT_BYPASS_EN_ADDR; + avmm_dprio_writedata[4] = usr_m_cnt_bypass_en; + end + else if (any_c_cnt_changed & !all_c_cnt_done_q) + begin + for (i = 0; (i < number_of_counters) & !break_loop; i = i + 1'b1) + begin : c_cnt_write_bypass + if (fpll_1) + begin + if (i > 13) + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_0_3_BYPASS_EN_ADDR; + avmm_dprio_writedata[i-14] = temp_c_cnt_bypass_en[i]; + break_loop = 1'b1; + end + end + else + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_4_17_BYPASS_EN_ADDR; + avmm_dprio_writedata[i] = temp_c_cnt_bypass_en[i]; + break_loop = 1'b1; + end + end + end + else + begin + if (i < 4) + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_0_3_BYPASS_EN_ADDR; + avmm_dprio_writedata[3-i] = temp_c_cnt_bypass_en[i]; + break_loop = 1'b1; + end + end + else + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_4_17_BYPASS_EN_ADDR; + avmm_dprio_writedata[17-i] = temp_c_cnt_bypass_en[i]; + break_loop = 1'b1; + end + end + end + end + end + else if (dsm_k_changed & !dsm_k_done_q) + begin + avmm_dprio_write = 0; + end + else if (bwctrl_changed & !bwctrl_done_q) + begin + avmm_dprio_write = 0; + end + else if (cp_current_changed & !cp_current_done_q) + begin + avmm_dprio_write = 0; + end + else if (vco_changed & !vco_done_q) + begin + avmm_dprio_write = 0; + end + else dprio_next_state = DPRIO_IDLE; + end + SEVEN: + begin + dprio_write_done = 0; + dprio_next_state = EIGHT; + avmm_dprio_write = 1'b1; + avmm_dprio_byteen = 2'b11; + avmm_dprio_writedata = dprio_temp_m_n_c_readdata_2_q; + if (n_cnt_changed & !n_cnt_done_q) + begin + avmm_dprio_address = N_CNT_ODD_DIV_EN_ADDR; + avmm_dprio_writedata[5] = usr_n_cnt_odd_duty_div_en; + n_cnt_done_d = 1'b1; + end + else if (m_cnt_changed & !m_cnt_done_q) + begin + avmm_dprio_address = M_CNT_ODD_DIV_EN_ADDR; + avmm_dprio_writedata[4] = usr_m_cnt_odd_duty_div_en; + m_cnt_done_d = 1'b1; + end + + else if (any_c_cnt_changed & !all_c_cnt_done_q) + begin + for (i = 0; (i < number_of_counters) & !break_loop; i = i + 1'b1) + begin : c_cnt_write_odd_div + if (fpll_1) + begin + if (i > 13) + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_0_3_ODD_DIV_EN_ADDR; + avmm_dprio_writedata[i-14] = temp_c_cnt_odd_duty_div_en[i]; + c_cnt_done_d[i] = 1'b1; + //have to OR the signals to prevent + //overwriting of previous dones + c_cnt_done_d = c_cnt_done_d | c_cnt_done_q; + break_loop = 1'b1; + end + end + else + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_4_17_ODD_DIV_EN_ADDR; + avmm_dprio_writedata[i] = temp_c_cnt_odd_duty_div_en[i]; + c_cnt_done_d[i] = 1'b1; + c_cnt_done_d = c_cnt_done_d | c_cnt_done_q; + break_loop = 1'b1; + end + end + end + else + begin + if (i < 4) + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_0_3_ODD_DIV_EN_ADDR; + avmm_dprio_writedata[3-i] = temp_c_cnt_odd_duty_div_en[i]; + c_cnt_done_d[i] = 1'b1; + //have to OR the signals to prevent + //overwriting of previous dones + c_cnt_done_d = c_cnt_done_d | c_cnt_done_q; + break_loop = 1'b1; + end + end + else + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_4_17_ODD_DIV_EN_ADDR; + avmm_dprio_writedata[17-i] = temp_c_cnt_odd_duty_div_en[i]; + c_cnt_done_d[i] = 1'b1; + c_cnt_done_d = c_cnt_done_d | c_cnt_done_q; + break_loop = 1'b1; + end + end + end + end + end + else if (dsm_k_changed & !dsm_k_done_q) + begin + avmm_dprio_address = DSM_K_READY_ADDR; + avmm_dprio_writedata[DSM_K_READY_BIT_INDEX] = 1'b0; + dsm_k_ready_false_done_d = 1'b1; + end + else if (bwctrl_changed & !bwctrl_done_q) + begin + avmm_dprio_address = BWCTRL_ADDR; + avmm_dprio_writedata[3:0] = usr_bwctrl_value; + bwctrl_done_d = 1'b1; + end + else if (cp_current_changed & !cp_current_done_q) + begin + avmm_dprio_address = CP_CURRENT_ADDR; + avmm_dprio_writedata[2:0] = usr_cp_current_value; + cp_current_done_d = 1'b1; + end + else if (vco_changed & !vco_done_q) + begin + avmm_dprio_address = VCO_ADDR; + avmm_dprio_writedata[8] = usr_vco_value; + vco_done_d = 1'b1; + end + + + //if all C_cnt that were changed are done, then assert all_c_cnt_done + if (c_cnt_done_d == c_cnt_changed) + all_c_cnt_done_d = 1'b1; + if (n_cnt_changed & n_cnt_done_d) + dprio_next_state = DPRIO_DONE; + if (any_c_cnt_changed & !all_c_cnt_done_d & !all_c_cnt_done_q) + dprio_next_state = ONE; + else if (m_cnt_changed & !m_cnt_done_d & !m_cnt_done_q) + dprio_next_state = ONE; + else if (dsm_k_changed & !dsm_k_ready_false_done_d) + dprio_next_state = TWO; + else if (dsm_k_changed & !dsm_k_done_q) + dprio_next_state = EIGHT; + else if (bwctrl_changed & !bwctrl_done_d) + dprio_next_state = TWO; + else if (cp_current_changed & !cp_current_done_d) + dprio_next_state = TWO; + else if (vco_changed & !vco_done_d) + dprio_next_state = TWO; + else + begin + dprio_next_state = DPRIO_DONE; + dprio_write_done = 1'b1; + end + end + //finish the rest of the DSM reads/writes + //writing k value, writing k_ready to 1. + EIGHT: + begin + dprio_write_done = 0; + dprio_next_state = NINE; + avmm_dprio_write = 1'b1; + avmm_dprio_byteen = 2'b11; + if (dsm_k_changed & !dsm_k_done_q) + begin + avmm_dprio_address = DSM_K_FRACTIONAL_DIVISION_ADDR_0; + avmm_dprio_writedata[15:0] = usr_k_value[15:0]; + end + end + NINE: + begin + dprio_write_done = 0; + dprio_next_state = TEN; + avmm_dprio_write = 1'b1; + avmm_dprio_byteen = 2'b11; + if (dsm_k_changed & !dsm_k_done_q) + begin + avmm_dprio_address = DSM_K_FRACTIONAL_DIVISION_ADDR_1; + avmm_dprio_writedata[15:0] = usr_k_value[31:16]; + end + end + TEN: + begin + dprio_write_done = 0; + dprio_next_state = ONE; + avmm_dprio_write = 1'b1; + avmm_dprio_byteen = 2'b11; + if (dsm_k_changed & !dsm_k_done_q) + begin + avmm_dprio_address = DSM_K_READY_ADDR; + //already have the readdata for DSM_K_READY_ADDR since we read it + //earlier. Just reuse here + avmm_dprio_writedata = dprio_temp_m_n_c_readdata_2_q; + avmm_dprio_writedata[DSM_K_READY_BIT_INDEX] = 1'b1; + dsm_k_done_d = 1'b1; + end + end + DPRIO_DONE: + begin + dprio_write_done = 1'b1; + if (dprio_start) dprio_next_state = DPRIO_IDLE; + else dprio_next_state = DPRIO_DONE; + end + DPRIO_IDLE: + begin + if (dprio_start) dprio_next_state = ONE; + else dprio_next_state = DPRIO_IDLE; + end + default: dprio_next_state = 4'bxxxx; + endcase + end + + end + + + //assert the waitreq signal according to the state of the slave + assign slave_waitrequest = (slave_mode==mode_WR) ? ((locked === 1'b1) ? (((current_state==WAIT_ON_LOCK) & !dprio_write_done) | !dps_done |reset|!dprio_init_done) : 1'b1) : 1'b0; + + // Read operations + always @(*) + begin + status = 0; + if (slave_mode == mode_POLL) + //asserting status to 1 if the slave is done. + status = (current_state == LOCKED); + end + //************************************************************// + //************************************************************// + //******************** READ STATE MACHINE ********************// + //************************************************************// + //************************************************************// + reg [1:0] current_read_state; + reg [1:0] next_read_state; + reg [5:0] slave_address_int_d; + reg [5:0] slave_address_int_q; + reg dprio_read_1; + reg [5:0] dprio_address_1; + reg [1:0] dprio_byteen_1; + reg [4:0] usr_cnt_sel_1; + localparam READ = 2'b00, READ_WAIT = 2'b01, READ_IDLE = 2'b10, READ_POST_WAIT = 2'b11; + + always @(*) + begin + if(next_read_state == READ_IDLE) + begin + read_waitrequest <= 1'b0; + end + else + begin + read_waitrequest <= 1'b1; + end + end + + always @(posedge clk) + begin + if (reset) + begin + current_read_state <= READ_IDLE; + slave_address_int_q <= 0; + slave_readdata_q <= 0; + end + else + begin + current_read_state <= next_read_state; + slave_address_int_q <= slave_address_int_d; + slave_readdata_q <= slave_readdata_d; + end + end + always @(*) + begin + dprio_read_1 = 0; + dprio_address_1 = 0; + dprio_byteen_1 = 0; + slave_address_int_d = 0; + slave_readdata_d = 0; + status_read = 0; + usr_cnt_sel_1 = 0; + case(current_read_state) + READ_IDLE: + begin + slave_address_int_d = 0; + next_read_state = READ_IDLE; + if ((current_state != WAIT_ON_LOCK) && slave_read) + begin + slave_address_int_d = slave_address; + if ((slave_address >= CNT_BASE) && (slave_address < CNT_BASE+18)) + begin + next_read_state = READ_WAIT; + dprio_byteen_1 = 2'b11; + dprio_read_1 = 1'b1; + usr_cnt_sel_1 = (slave_address[4:0] - CNT_BASE); + if (fpll_1) dprio_address_1 = C_CNT_0_DIV_ADDR + C_CNT_0_DIV_ADDR_DPRIO_1 - cnt_sel; + else dprio_address_1 = C_CNT_0_DIV_ADDR + cnt_sel; + end + else + begin + case (slave_address) + MODE_REG: + begin + next_read_state = READ_WAIT; + slave_readdata_d = slave_mode; + end + STATUS_REG: + begin + next_read_state = READ_WAIT; + status_read = 1'b1; + slave_readdata_d = status; + end + N_REG: + begin + dprio_byteen_1 = 2'b11; + dprio_read_1 = 1'b1; + dprio_address_1 = N_CNT_DIV_ADDR; + next_read_state = READ_WAIT; + end + M_REG: + begin + dprio_byteen_1 = 2'b11; + dprio_read_1 = 1'b1; + dprio_address_1 = M_CNT_DIV_ADDR; + next_read_state = READ_WAIT; + end + BWCTRL_REG: + begin + dprio_byteen_1 = 2'b11; + dprio_read_1 = 1'b1; + dprio_address_1 = BWCTRL_ADDR; + next_read_state = READ_WAIT; + end + CP_CURRENT_REG: + begin + dprio_byteen_1 = 2'b11; + dprio_read_1 = 1'b1; + dprio_address_1 = CP_CURRENT_ADDR; + next_read_state = READ_WAIT; + end + VCO_REG: + begin + dprio_byteen_1 = 2'b11; + dprio_read_1 = 1'b1; + dprio_address_1 = VCO_ADDR; + next_read_state = READ_WAIT; + end + ANY_DPRIO: + begin + dprio_byteen_1 = 2'b11; + dprio_read_1 = ~slave_writedata[22]; + dprio_address_1 = slave_writedata[5:0]; + next_read_state = READ_WAIT; + end + default : next_read_state = READ_IDLE; + endcase + end + end + else + next_read_state = READ_IDLE; + end + READ_WAIT: + begin + next_read_state = READ; + slave_address_int_d = slave_address_int_q; + case (slave_address_int_q) + MODE_REG: + begin + slave_readdata_d = slave_readdata_q; + end + STATUS_REG: + begin + slave_readdata_d = slave_readdata_q; + end + endcase + end + READ: + begin + next_read_state = READ_POST_WAIT; + slave_address_int_d = slave_address_int_q; + slave_readdata_d = dprio_readdata; + case (slave_address_int_q) + MODE_REG: + begin + slave_readdata_d = slave_readdata_q; + end + STATUS_REG: + begin + slave_readdata_d = slave_readdata_q; + end + BWCTRL_REG: + begin + slave_readdata_d = dprio_readdata[3:0]; + end + CP_CURRENT_REG: + begin + slave_readdata_d = dprio_readdata[2:0]; + end + VCO_REG: + begin + slave_readdata_d = dprio_readdata[8]; + end + ANY_DPRIO: + begin + slave_readdata_d = dprio_readdata; + end + endcase + end + READ_POST_WAIT: + begin + next_read_state = READ_IDLE; + end + default: next_read_state = 2'bxx; + endcase + end + + + dyn_phase_shift dyn_phase_shift_inst ( + .clk(clk), + .reset(reset), + .phase_done(phase_done), + .pll_start_valid(pll_start_valid), + .dps_changed(dps_changed), + .dps_changed_valid(dps_changed_valid), + .dprio_write_done(dprio_write_done), + .usr_num_shifts(usr_num_shifts), + .usr_cnt_sel(usr_cnt_sel|usr_cnt_sel_1), + .usr_up_dn(usr_up_dn), + .locked(locked), + .dps_done(dps_done), + .phase_en(phase_en), + .up_dn(up_dn), + .cnt_sel(cnt_sel)); + defparam dyn_phase_shift_inst.device_family = device_family; + + assign dprio_clk = clk; + self_reset self_reset_inst (mgmt_reset, clk, reset, dprio_init_reset); + + dprio_mux dprio_mux_inst ( + .init_dprio_address(init_dprio_address), + .init_dprio_read(init_dprio_read), + .init_dprio_byteen(init_dprio_byteen), + .init_dprio_write(init_dprio_write), + .init_dprio_writedata(init_dprio_writedata), + + + .init_atpgmode(init_atpgmode), + .init_mdio_dis(init_mdio_dis), + .init_scanen(init_scanen), + .init_ser_shift_load(init_ser_shift_load), + .dprio_init_done(dprio_init_done), + + // Inputs from avmm master + .avmm_dprio_address(avmm_dprio_address | dprio_address_1), + .avmm_dprio_read(avmm_dprio_read | dprio_read_1), + .avmm_dprio_byteen(avmm_dprio_byteen | dprio_byteen_1), + .avmm_dprio_write(avmm_dprio_write), + .avmm_dprio_writedata(avmm_dprio_writedata), + + .avmm_atpgmode(avmm_atpgmode), + .avmm_mdio_dis(avmm_mdio_dis), + .avmm_scanen(avmm_scanen), + + // Outputs to fpll + .dprio_address(dprio_address), + .dprio_read(dprio_read), + .dprio_byteen(dprio_byteen), + .dprio_write(dprio_write), + .dprio_writedata(dprio_writedata), + + .atpgmode(dprio_atpgmode), + .mdio_dis(dprio_mdio_dis), + .scanen(dprio_scanen), + .ser_shift_load(dprio_ser_shift_load) + ); + + + fpll_dprio_init fpll_dprio_init_inst ( + .clk(clk), + .reset_n(~reset), + .locked(locked), + + //outputs + .dprio_address(init_dprio_address), + .dprio_read(init_dprio_read), + .dprio_byteen(init_dprio_byteen), + .dprio_write(init_dprio_write), + .dprio_writedata(init_dprio_writedata), + + .atpgmode(init_atpgmode), + .mdio_dis(init_mdio_dis), + .scanen(init_scanen), + .ser_shift_load(init_ser_shift_load), + .dprio_init_done(dprio_init_done)); + + //address luts, to be reconfigged by the Fitter + //FPLL_1 or 0 address lut + generic_lcell_comb lcell_fpll_0_1 ( + .dataa(1'b0), + .combout (fpll_1)); + defparam lcell_fpll_0_1.lut_mask = 64'hAAAAAAAAAAAAAAAA; + defparam lcell_fpll_0_1.dont_touch = "on"; + defparam lcell_fpll_0_1.family = device_family; + + + wire dprio_read_combout; + generic_lcell_comb lcell_dprio_read ( + .dataa(fpll_1), + .datab(dprio_read), + .datac(1'b0), + .datad(1'b0), + .datae(1'b0), + .dataf(1'b0), + .combout (dprio_read_combout)); + defparam lcell_dprio_read.lut_mask = 64'hCCCCCCCCCCCCCCCC; + defparam lcell_dprio_read.dont_touch = "on"; + defparam lcell_dprio_read.family = device_family; + + + + + + //assign reconfig_to_pll signals + assign reconfig_to_pll[0] = dprio_clk; + assign reconfig_to_pll[1] = ~dprio_init_reset; + assign reconfig_to_pll[2] = dprio_write; + assign reconfig_to_pll[3] = dprio_read_combout; + assign reconfig_to_pll[9:4] = dprio_address; + assign reconfig_to_pll[25:10] = dprio_writedata; + assign reconfig_to_pll[27:26] = dprio_byteen; + assign reconfig_to_pll[28] = dprio_ser_shift_load; + assign reconfig_to_pll[29] = dprio_mdio_dis; + assign reconfig_to_pll[30] = phase_en; + assign reconfig_to_pll[31] = up_dn; + assign reconfig_to_pll[36:32] = cnt_sel; + assign reconfig_to_pll[37] = dprio_scanen; + assign reconfig_to_pll[38] = dprio_atpgmode; + //assign reconfig_to_pll[40:37] = clken; + assign reconfig_to_pll[63:39] = 0; + + //assign reconfig_from_pll signals + assign dprio_readdata = reconfig_from_pll [15:0]; + assign locked_orig = reconfig_from_pll [16]; + assign phase_done = reconfig_from_pll [17]; + +endmodule +module self_reset (input wire mgmt_reset, input wire clk, output wire reset, output wire init_reset); + + localparam RESET_COUNTER_VALUE = 3'd2; + localparam INITIAL_WAIT_VALUE = 9'd340; + reg [9:0]counter; + reg local_reset; + reg usr_mode_init_wait; + initial + begin + local_reset = 1'b1; + counter = 0; + usr_mode_init_wait = 0; + end + + always @(posedge clk) + begin + if (mgmt_reset) + begin + counter <= 0; + end + else + begin + if (!usr_mode_init_wait) + begin + if (counter == INITIAL_WAIT_VALUE) + begin + local_reset <= 0; + usr_mode_init_wait <= 1'b1; + counter <= 0; + end + else + begin + counter <= counter + 1'b1; + end + end + else + begin + if (counter == RESET_COUNTER_VALUE) + local_reset <= 0; + else + counter <= counter + 1'b1; + end + end + end + assign reset = mgmt_reset | local_reset; + assign init_reset = local_reset; +endmodule + +module dprio_mux ( + // Inputs from init block + input [ 5:0] init_dprio_address, + input init_dprio_read, + input [ 1:0] init_dprio_byteen, + input init_dprio_write, + input [15:0] init_dprio_writedata, + + input init_atpgmode, + input init_mdio_dis, + input init_scanen, + input init_ser_shift_load, + input dprio_init_done, + + // Inputs from avmm master + input [ 5:0] avmm_dprio_address, + input avmm_dprio_read, + input [ 1:0] avmm_dprio_byteen, + input avmm_dprio_write, + input [15:0] avmm_dprio_writedata, + + input avmm_atpgmode, + input avmm_mdio_dis, + input avmm_scanen, + input avmm_ser_shift_load, + + // Outputs to fpll + output [ 5:0] dprio_address, + output dprio_read, + output [ 1:0] dprio_byteen, + output dprio_write, + output [15:0] dprio_writedata, + + output atpgmode, + output mdio_dis, + output scanen, + output ser_shift_load +); + + assign dprio_address = dprio_init_done ? avmm_dprio_address : init_dprio_address; + assign dprio_read = dprio_init_done ? avmm_dprio_read : init_dprio_read; + assign dprio_byteen = dprio_init_done ? avmm_dprio_byteen : init_dprio_byteen; + assign dprio_write = dprio_init_done ? avmm_dprio_write : init_dprio_write; + assign dprio_writedata = dprio_init_done ? avmm_dprio_writedata : init_dprio_writedata; + + assign atpgmode = init_atpgmode; + assign scanen = init_scanen; + assign mdio_dis = init_mdio_dis; + assign ser_shift_load = init_ser_shift_load ; +endmodule +module fpll_dprio_init ( + input clk, + input reset_n, + input locked, + + output [ 5:0] dprio_address, + output dprio_read, + output [ 1:0] dprio_byteen, + output dprio_write, + output [15:0] dprio_writedata, + + output reg atpgmode, + output reg mdio_dis, + output reg scanen, + output reg ser_shift_load, + output reg dprio_init_done +); + + reg [1:0] rst_n = 2'b00; + reg [6:0] count = 7'd0; + reg init_done_forever; + + // Internal versions of control signals + wire int_mdio_dis; + wire int_ser_shift_load; + wire int_dprio_init_done; + wire int_atpgmode/*synthesis keep*/; + wire int_scanen/*synthesis keep*/; + + + assign dprio_address = count[6] ? 5'b0 : count[5:0] ; + assign dprio_byteen = 2'b11; // always enabled + assign dprio_write = ~count[6] & reset_n ; // write for first 64 cycles + assign dprio_read = 1'b0; + assign dprio_writedata = 16'd0; + + assign int_ser_shift_load = count[6] ? |count[2:1] : 1'b1; + assign int_mdio_dis = count[6] ? ~count[2] : 1'b1; + assign int_dprio_init_done = ~init_done_forever ? (count[6] ? &count[2:0] : 1'b0) + : 1'b1; + assign int_atpgmode = 0; + assign int_scanen = 0; + + initial begin + count = 7'd0; + init_done_forever = 0; + mdio_dis = 1'b1; + ser_shift_load = 1'b1; + dprio_init_done = 1'b0; + scanen = 1'b0; + atpgmode = 1'b0; + end + + // reset synch. + always @(posedge clk or negedge reset_n) + if(!reset_n) rst_n <= 2'b00; + else rst_n <= {rst_n[0],1'b1}; + + // counter + always @(posedge clk) + begin + if (!rst_n[1]) + init_done_forever <= 1'b0; + else + begin + if (count[6] && &count[1:0]) + init_done_forever <= 1'b1; + end + end + always @(posedge clk or negedge rst_n[1]) + begin + if(!rst_n[1]) + begin + count <= 7'd0; + end + else if(~int_dprio_init_done) + begin + count <= count + 7'd1; + end + else + begin + count <= count; + end + end + + // outputs + always @(posedge clk) begin + mdio_dis <= int_mdio_dis; + ser_shift_load <= int_ser_shift_load; + dprio_init_done <= int_dprio_init_done; + atpgmode <= int_atpgmode; + scanen <= int_scanen; + end + +endmodule +module dyn_phase_shift +#( + parameter device_family = "Stratix V" +) ( + + input wire clk, + input wire reset, + input wire phase_done, + input wire pll_start_valid, + input wire dps_changed, + input wire dprio_write_done, + input wire [15:0] usr_num_shifts, + input wire [4:0] usr_cnt_sel, + input wire usr_up_dn, + input wire locked, + + //output + output wire dps_done, + output reg phase_en, + output wire up_dn, + output wire dps_changed_valid, + output wire [4:0] cnt_sel); + + + + reg first_phase_shift_d; + reg first_phase_shift_q; + reg [15:0] phase_en_counter; + reg [3:0] dps_current_state; + reg [3:0] dps_next_state; + localparam DPS_START = 4'd0, DPS_WAIT_PHASE_DONE = 4'd1, DPS_DONE = 4'd2, DPS_WAIT_PHASE_EN = 4'd3, DPS_WAIT_DPRIO_WRITING = 4'd4, DPS_CHANGED = 4'd5; + localparam PHASE_EN_WAIT_COUNTER = 5'd1; + + reg [15:0] shifts_done_counter; + reg phase_done_final; + wire gnd /*synthesis keep*/; + + //fsm + //always block controlling the state regs + always @(posedge clk) + begin + if (reset) + begin + dps_current_state <= DPS_DONE; + end + else + begin + dps_current_state <= dps_next_state; + end + end + //the combinational part. assigning the next state + //this turns on the phase_done_final signal when phase_done does this: + //_____ ______ + // |______| + always @(*) + begin + phase_done_final = 0; + first_phase_shift_d = 0; + phase_en = 0; + dps_next_state = DPS_DONE; + case (dps_current_state) + DPS_START: + begin + phase_en = 1'b1; + dps_next_state = DPS_WAIT_PHASE_EN; + end + DPS_WAIT_PHASE_EN: + begin + phase_en = 1'b1; + if (first_phase_shift_q) + begin + first_phase_shift_d = 1'b1; + dps_next_state = DPS_WAIT_PHASE_EN; + end + else + begin + if (phase_en_counter == PHASE_EN_WAIT_COUNTER) + dps_next_state = DPS_WAIT_PHASE_DONE; + else dps_next_state = DPS_WAIT_PHASE_EN; + end + end + DPS_WAIT_PHASE_DONE: + begin + if (!phase_done | !locked) + begin + dps_next_state = DPS_WAIT_PHASE_DONE; + end + else + begin + if ((usr_num_shifts != shifts_done_counter) & (usr_num_shifts != 0)) + begin + dps_next_state = DPS_START; + phase_done_final = 1'b1; + end + else + begin + dps_next_state = DPS_DONE; + end + + end + end + DPS_DONE: + begin + phase_done_final = 0; + if (dps_changed) + dps_next_state = DPS_CHANGED; + else dps_next_state = DPS_DONE; + + end + DPS_CHANGED: + begin + if (pll_start_valid) + dps_next_state = DPS_WAIT_DPRIO_WRITING; + else + dps_next_state = DPS_CHANGED; + end + DPS_WAIT_DPRIO_WRITING: + begin + if (dprio_write_done) + dps_next_state = DPS_START; + else + dps_next_state = DPS_WAIT_DPRIO_WRITING; + end + + default: dps_next_state = 4'bxxxx; + endcase + + + end + + always @(posedge clk) + begin + + + if (dps_current_state == DPS_WAIT_PHASE_DONE) + phase_en_counter <= 0; + else if (dps_current_state == DPS_WAIT_PHASE_EN) + phase_en_counter <= phase_en_counter + 1'b1; + + if (reset) + begin + phase_en_counter <= 0; + shifts_done_counter <= 1'b1; + first_phase_shift_q <= 1; + end + else + begin + if (first_phase_shift_d) + first_phase_shift_q <= 0; + if (dps_done) + begin + shifts_done_counter <= 1'b1; + end + else + begin + if (phase_done_final & (dps_next_state!= DPS_DONE)) + shifts_done_counter <= shifts_done_counter + 1'b1; + else + shifts_done_counter <= shifts_done_counter; + end + end + end + + assign dps_changed_valid = (dps_current_state == DPS_CHANGED); + assign dps_done =(dps_current_state == DPS_DONE) | (dps_current_state == DPS_CHANGED); + assign up_dn = usr_up_dn; + assign gnd = 1'b0; + + //cnt select luts (5) + generic_lcell_comb lcell_cnt_sel_0 ( + .dataa(usr_cnt_sel[0]), + .datab(usr_cnt_sel[1]), + .datac(usr_cnt_sel[2]), + .datad(usr_cnt_sel[3]), + .datae(usr_cnt_sel[4]), + .dataf(gnd), + .combout (cnt_sel[0])); + defparam lcell_cnt_sel_0.lut_mask = 64'hAAAAAAAAAAAAAAAA; + defparam lcell_cnt_sel_0.dont_touch = "on"; + defparam lcell_cnt_sel_0.family = device_family; + generic_lcell_comb lcell_cnt_sel_1 ( + .dataa(usr_cnt_sel[0]), + .datab(usr_cnt_sel[1]), + .datac(usr_cnt_sel[2]), + .datad(usr_cnt_sel[3]), + .datae(usr_cnt_sel[4]), + .dataf(gnd), + .combout (cnt_sel[1])); + defparam lcell_cnt_sel_1.lut_mask = 64'hCCCCCCCCCCCCCCCC; + defparam lcell_cnt_sel_1.dont_touch = "on"; + defparam lcell_cnt_sel_1.family = device_family; + generic_lcell_comb lcell_cnt_sel_2 ( + .dataa(usr_cnt_sel[0]), + .datab(usr_cnt_sel[1]), + .datac(usr_cnt_sel[2]), + .datad(usr_cnt_sel[3]), + .datae(usr_cnt_sel[4]), + .dataf(gnd), + .combout (cnt_sel[2])); + defparam lcell_cnt_sel_2.lut_mask = 64'hF0F0F0F0F0F0F0F0; + defparam lcell_cnt_sel_2.dont_touch = "on"; + defparam lcell_cnt_sel_2.family = device_family; + generic_lcell_comb lcell_cnt_sel_3 ( + .dataa(usr_cnt_sel[0]), + .datab(usr_cnt_sel[1]), + .datac(usr_cnt_sel[2]), + .datad(usr_cnt_sel[3]), + .datae(usr_cnt_sel[4]), + .dataf(gnd), + .combout (cnt_sel[3])); + defparam lcell_cnt_sel_3.lut_mask = 64'hFF00FF00FF00FF00; + defparam lcell_cnt_sel_3.dont_touch = "on"; + defparam lcell_cnt_sel_3.family = device_family; + generic_lcell_comb lcell_cnt_sel_4 ( + .dataa(usr_cnt_sel[0]), + .datab(usr_cnt_sel[1]), + .datac(usr_cnt_sel[2]), + .datad(usr_cnt_sel[3]), + .datae(usr_cnt_sel[4]), + .dataf(gnd), + .combout (cnt_sel[4])); + defparam lcell_cnt_sel_4.lut_mask = 64'hFFFF0000FFFF0000; + defparam lcell_cnt_sel_4.dont_touch = "on"; + defparam lcell_cnt_sel_4.family = device_family; + + +endmodule + +module generic_lcell_comb +#( + //parameter + parameter family = "Stratix V", + parameter lut_mask = 64'hAAAAAAAAAAAAAAAA, + parameter dont_touch = "on" +) ( + + input dataa, + input datab, + input datac, + input datad, + input datae, + input dataf, + + output combout +); + + generate + if (family == "Stratix V") + begin + stratixv_lcell_comb lcell_inst ( + .dataa(dataa), + .datab(datab), + .datac(datac), + .datad(datad), + .datae(datae), + .dataf(dataf), + .combout (combout)); + defparam lcell_inst.lut_mask = lut_mask; + defparam lcell_inst.dont_touch = dont_touch; + end + else if (family == "Arria V") + begin + arriav_lcell_comb lcell_inst ( + .dataa(dataa), + .datab(datab), + .datac(datac), + .datad(datad), + .datae(datae), + .dataf(dataf), + .combout (combout)); + defparam lcell_inst.lut_mask = lut_mask; + defparam lcell_inst.dont_touch = dont_touch; + end + else if (family == "Arria V GZ") + begin + arriavgz_lcell_comb lcell_inst ( + .dataa(dataa), + .datab(datab), + .datac(datac), + .datad(datad), + .datae(datae), + .dataf(dataf), + .combout (combout)); + defparam lcell_inst.lut_mask = lut_mask; + defparam lcell_inst.dont_touch = dont_touch; + end + else if (family == "Cyclone V") + begin + cyclonev_lcell_comb lcell_inst ( + .dataa(dataa), + .datab(datab), + .datac(datac), + .datad(datad), + .datae(datae), + .dataf(dataf), + .combout (combout)); + defparam lcell_inst.lut_mask = lut_mask; + defparam lcell_inst.dont_touch = dont_touch; + end + endgenerate +endmodule diff --git a/sys/pll_cfg/altera_pll_reconfig_top.v b/sys/pll_cfg/altera_pll_reconfig_top.v new file mode 100644 index 0000000..c6d27bf --- /dev/null +++ b/sys/pll_cfg/altera_pll_reconfig_top.v @@ -0,0 +1,428 @@ +// (C) 2001-2017 Intel Corporation. All rights reserved. +// Your use of Intel Corporation's design tools, logic functions and other +// software and tools, and its AMPP partner logic functions, and any output +// files any of the foregoing (including device programming or simulation +// files), and any associated documentation or information are expressly subject +// to the terms and conditions of the Intel Program License Subscription +// Agreement, Intel MegaCore Function License Agreement, or other applicable +// license agreement, including, without limitation, that your use is for the +// sole purpose of programming logic devices manufactured by Intel and sold by +// Intel or its authorized distributors. Please refer to the applicable +// agreement for further details. + + +`timescale 1ps/1ps + +module altera_pll_reconfig_top +#( + parameter reconf_width = 64, + parameter device_family = "Stratix V", + parameter RECONFIG_ADDR_WIDTH = 6, + parameter RECONFIG_DATA_WIDTH = 32, + + parameter ROM_ADDR_WIDTH = 9, + parameter ROM_DATA_WIDTH = 32, + parameter ROM_NUM_WORDS = 512, + + parameter ENABLE_MIF = 0, + parameter MIF_FILE_NAME = "", + + parameter ENABLE_BYTEENABLE = 0, + parameter BYTEENABLE_WIDTH = 4, + parameter WAIT_FOR_LOCK = 1 +) ( + + //input + input wire mgmt_clk, + input wire mgmt_reset, + + + //conduits + output wire [reconf_width-1:0] reconfig_to_pll, + input wire [reconf_width-1:0] reconfig_from_pll, + + // user data (avalon-MM slave interface) + output wire [RECONFIG_DATA_WIDTH-1:0] mgmt_readdata, + output wire mgmt_waitrequest, + input wire [RECONFIG_ADDR_WIDTH-1:0] mgmt_address, + input wire mgmt_read, + input wire mgmt_write, + input wire [RECONFIG_DATA_WIDTH-1:0] mgmt_writedata, + + //conditional input + input wire [BYTEENABLE_WIDTH-1:0] mgmt_byteenable +); + +localparam NM28_START_REG = 6'b000010; +localparam NM20_START_REG = 9'b000000000; +localparam NM20_MIFSTART_ADDR = 9'b000010000; + +localparam MIF_STATE_DONE = 2'b00; +localparam MIF_STATE_START = 2'b01; +localparam MIF_STATE_BUSY = 2'b10; + +wire mgmt_byteenable_write; +assign mgmt_byteenable_write = (ENABLE_BYTEENABLE == 1) ? + ((mgmt_byteenable == {BYTEENABLE_WIDTH{1'b1}}) ? mgmt_write : 1'b0) : + mgmt_write; + +generate +if (device_family == "Arria 10") +begin:nm20_reconfig + if(ENABLE_MIF == 1) + begin:mif_reconfig_20nm // Generate Reconfig with MIF + + // MIF-related regs/wires + reg [RECONFIG_ADDR_WIDTH-1:0] reconfig_mgmt_addr; + reg reconfig_mgmt_read; + reg reconfig_mgmt_write; + reg [RECONFIG_DATA_WIDTH-1:0] reconfig_mgmt_writedata; + wire reconfig_mgmt_waitrequest; + wire [RECONFIG_DATA_WIDTH-1:0] reconfig_mgmt_readdata; + + wire [RECONFIG_ADDR_WIDTH-1:0] mif2reconfig_addr; + wire mif_busy; + wire mif2reconfig_read; + wire mif2reconfig_write; + wire [RECONFIG_DATA_WIDTH-1:0] mif2reconfig_writedata; + wire [ROM_ADDR_WIDTH-1:0] mif_base_addr; + reg mif_select; + //wire mif_user_start; // start signal provided by user to start mif + //reg user_start; + + reg [1:0] mif_curstate; + reg [1:0] mif_nextstate; + + wire mif_start; //start signal to mif reader + + assign mgmt_waitrequest = reconfig_mgmt_waitrequest | mif_busy;// | user_start; + // Don't output readdata if MIF streaming is taking place + assign mgmt_readdata = (mif_select) ? 32'b0 : reconfig_mgmt_readdata; + + //user must lower this by the time mif streaming is done - suggest to lower after 1 cycle + assign mif_start = mgmt_byteenable_write & (mgmt_address == NM20_MIFSTART_ADDR); + + //mif base addr is initially specified by the user + assign mif_base_addr = mgmt_writedata[ROM_ADDR_WIDTH-1:0]; + + //MIF statemachine + always @(posedge mgmt_clk) + begin + if(mgmt_reset) + mif_curstate <= MIF_STATE_DONE; + else + mif_curstate <= mif_nextstate; + end + + always @(*) + begin + case (mif_curstate) + MIF_STATE_DONE: + begin + if(mif_start) + mif_nextstate <= MIF_STATE_START; + else + mif_nextstate <= MIF_STATE_DONE; + end + MIF_STATE_START: + begin + mif_nextstate <= MIF_STATE_BUSY; + end + MIF_STATE_BUSY: + begin + if(mif_busy) + mif_nextstate <= MIF_STATE_BUSY; + else + mif_nextstate <= MIF_STATE_DONE; + end + endcase + end + + //Mif muxes + always @(*) + begin + if (mgmt_reset) + begin + reconfig_mgmt_addr <= 0; + reconfig_mgmt_read <= 0; + reconfig_mgmt_write <= 0; + reconfig_mgmt_writedata <= 0; + //user_start <= 0; + end + else + begin + reconfig_mgmt_addr <= (mif_select) ? mif2reconfig_addr : mgmt_address; + reconfig_mgmt_read <= (mif_select) ? mif2reconfig_read : mgmt_read; + reconfig_mgmt_write <= (mif_select) ? mif2reconfig_write : mgmt_byteenable_write; + reconfig_mgmt_writedata <= (mif_select) ? mif2reconfig_writedata : mgmt_writedata; + //user_start <= (mgmt_address == NM20_START_REG && mgmt_write == 1'b1) ? 1'b1 : 1'b0; + end + end + + always @(*) + begin + if (mgmt_reset) + begin + mif_select <= 0; + end + else + begin + mif_select <= (mif_start || mif_busy) ? 1'b1 : 1'b0; + end + end + + twentynm_pll_reconfig_mif_reader + #( + .RECONFIG_ADDR_WIDTH(RECONFIG_ADDR_WIDTH), + .RECONFIG_DATA_WIDTH(RECONFIG_DATA_WIDTH), + .ROM_ADDR_WIDTH(ROM_ADDR_WIDTH), + .ROM_DATA_WIDTH(ROM_DATA_WIDTH), + .ROM_NUM_WORDS(ROM_NUM_WORDS), + .DEVICE_FAMILY(device_family), + .ENABLE_MIF(ENABLE_MIF), + .MIF_FILE_NAME(MIF_FILE_NAME) + ) twentynm_pll_reconfig_mif_reader_inst0 ( + .mif_clk(mgmt_clk), + .mif_rst(mgmt_reset), + + //Altera_PLL Reconfig interface + //inputs + .reconfig_waitrequest(reconfig_mgmt_waitrequest), + //.reconfig_read_data(reconfig_mgmt_readdata), + //outputs + .reconfig_write_data(mif2reconfig_writedata), + .reconfig_addr(mif2reconfig_addr), + .reconfig_write(mif2reconfig_write), + .reconfig_read(mif2reconfig_read), + + //MIF Ctrl Interface + //inputs + .mif_base_addr(mif_base_addr), + .mif_start(mif_start), + //outputs + .mif_busy(mif_busy) + ); + + // ------ END MIF-RELATED MANAGEMENT ------ + + twentynm_iopll_reconfig_core + #( + .WAIT_FOR_LOCK(WAIT_FOR_LOCK) + ) twentynm_iopll_reconfig_core_inst ( + // Inputs + .mgmt_clk(mgmt_clk), + .mgmt_rst_n(~mgmt_reset), + .mgmt_read(reconfig_mgmt_read), + .mgmt_write(reconfig_mgmt_write), + .mgmt_address(reconfig_mgmt_addr), + .mgmt_writedata(reconfig_mgmt_writedata), + + // Outputs + .mgmt_readdata(reconfig_mgmt_readdata), + .mgmt_waitrequest(reconfig_mgmt_waitrequest), + + // PLL Conduits + .reconfig_to_pll(reconfig_to_pll), + .reconfig_from_pll(reconfig_from_pll) + ); + + end // End generate reconfig with MIF + else + begin:reconfig_core_20nm + twentynm_iopll_reconfig_core + #( + .WAIT_FOR_LOCK(WAIT_FOR_LOCK) + ) twentynm_iopll_reconfig_core_inst ( + // Inputs + .mgmt_clk(mgmt_clk), + .mgmt_rst_n(~mgmt_reset), + .mgmt_read(mgmt_read), + .mgmt_write(mgmt_byteenable_write), + .mgmt_address(mgmt_address), + .mgmt_writedata(mgmt_writedata), + + // Outputs + .mgmt_readdata(mgmt_readdata), + .mgmt_waitrequest(mgmt_waitrequest), + + // PLL Conduits + .reconfig_to_pll(reconfig_to_pll), + .reconfig_from_pll(reconfig_from_pll) + ); + end +end // 20nm reconfig +else +begin:NM28_reconfig + if (ENABLE_MIF == 1) + begin:mif_reconfig // Generate Reconfig with MIF + + // MIF-related regs/wires + reg [RECONFIG_ADDR_WIDTH-1:0] reconfig_mgmt_addr; + reg reconfig_mgmt_read; + reg reconfig_mgmt_write; + reg [RECONFIG_DATA_WIDTH-1:0] reconfig_mgmt_writedata; + wire reconfig_mgmt_waitrequest; + wire [RECONFIG_DATA_WIDTH-1:0] reconfig_mgmt_readdata; + + wire [RECONFIG_ADDR_WIDTH-1:0] mif2reconfig_addr; + wire mif2reconfig_busy; + wire mif2reconfig_read; + wire mif2reconfig_write; + wire [RECONFIG_DATA_WIDTH-1:0] mif2reconfig_writedata; + wire [ROM_ADDR_WIDTH-1:0] mif_base_addr; + reg mif_select; + reg user_start; + + wire reconfig2mif_start_out; + + assign mgmt_waitrequest = reconfig_mgmt_waitrequest | mif2reconfig_busy | user_start; + // Don't output readdata if MIF streaming is taking place + assign mgmt_readdata = (mif_select) ? 32'b0 : reconfig_mgmt_readdata; + + always @(posedge mgmt_clk) + begin + if (mgmt_reset) + begin + reconfig_mgmt_addr <= 0; + reconfig_mgmt_read <= 0; + reconfig_mgmt_write <= 0; + reconfig_mgmt_writedata <= 0; + user_start <= 0; + end + else + begin + reconfig_mgmt_addr <= (mif_select) ? mif2reconfig_addr : mgmt_address; + reconfig_mgmt_read <= (mif_select) ? mif2reconfig_read : mgmt_read; + reconfig_mgmt_write <= (mif_select) ? mif2reconfig_write : mgmt_byteenable_write; + reconfig_mgmt_writedata <= (mif_select) ? mif2reconfig_writedata : mgmt_writedata; + user_start <= (mgmt_address == NM28_START_REG && mgmt_byteenable_write == 1'b1) ? 1'b1 : 1'b0; + end + end + + always @(*) + begin + if (mgmt_reset) + begin + mif_select <= 0; + end + else + begin + mif_select <= (reconfig2mif_start_out || mif2reconfig_busy) ? 1'b1 : 1'b0; + end + end + + altera_pll_reconfig_mif_reader + #( + .RECONFIG_ADDR_WIDTH(RECONFIG_ADDR_WIDTH), + .RECONFIG_DATA_WIDTH(RECONFIG_DATA_WIDTH), + .ROM_ADDR_WIDTH(ROM_ADDR_WIDTH), + .ROM_DATA_WIDTH(ROM_DATA_WIDTH), + .ROM_NUM_WORDS(ROM_NUM_WORDS), + .DEVICE_FAMILY(device_family), + .ENABLE_MIF(ENABLE_MIF), + .MIF_FILE_NAME(MIF_FILE_NAME) + ) altera_pll_reconfig_mif_reader_inst0 ( + .mif_clk(mgmt_clk), + .mif_rst(mgmt_reset), + + //Altera_PLL Reconfig interface + //inputs + .reconfig_busy(reconfig_mgmt_waitrequest), + .reconfig_read_data(reconfig_mgmt_readdata), + //outputs + .reconfig_write_data(mif2reconfig_writedata), + .reconfig_addr(mif2reconfig_addr), + .reconfig_write(mif2reconfig_write), + .reconfig_read(mif2reconfig_read), + + //MIF Ctrl Interface + //inputs + .mif_base_addr(mif_base_addr), + .mif_start(reconfig2mif_start_out), + //outputs + .mif_busy(mif2reconfig_busy) + ); + + // ------ END MIF-RELATED MANAGEMENT ------ + + + altera_pll_reconfig_core + #( + .reconf_width(reconf_width), + .device_family(device_family), + .RECONFIG_ADDR_WIDTH(RECONFIG_ADDR_WIDTH), + .RECONFIG_DATA_WIDTH(RECONFIG_DATA_WIDTH), + .ROM_ADDR_WIDTH(ROM_ADDR_WIDTH), + .ROM_DATA_WIDTH(ROM_DATA_WIDTH), + .ROM_NUM_WORDS(ROM_NUM_WORDS) + ) altera_pll_reconfig_core_inst0 ( + //inputs + .mgmt_clk(mgmt_clk), + .mgmt_reset(mgmt_reset), + + //PLL interface conduits + .reconfig_to_pll(reconfig_to_pll), + .reconfig_from_pll(reconfig_from_pll), + + //User data outputs + .mgmt_readdata(reconfig_mgmt_readdata), + .mgmt_waitrequest(reconfig_mgmt_waitrequest), + + //User data inputs + .mgmt_address(reconfig_mgmt_addr), + .mgmt_read(reconfig_mgmt_read), + .mgmt_write(reconfig_mgmt_write), + .mgmt_writedata(reconfig_mgmt_writedata), + + // other + .mif_start_out(reconfig2mif_start_out), + .mif_base_addr(mif_base_addr) + ); + + end // End generate reconfig with MIF + else + begin:reconfig_core // Generate Reconfig core only + + wire reconfig2mif_start_out; + wire [ROM_ADDR_WIDTH-1:0] mif_base_addr; + + altera_pll_reconfig_core + #( + .reconf_width(reconf_width), + .device_family(device_family), + .RECONFIG_ADDR_WIDTH(RECONFIG_ADDR_WIDTH), + .RECONFIG_DATA_WIDTH(RECONFIG_DATA_WIDTH), + .ROM_ADDR_WIDTH(ROM_ADDR_WIDTH), + .ROM_DATA_WIDTH(ROM_DATA_WIDTH), + .ROM_NUM_WORDS(ROM_NUM_WORDS) + ) altera_pll_reconfig_core_inst0 ( + //inputs + .mgmt_clk(mgmt_clk), + .mgmt_reset(mgmt_reset), + + //PLL interface conduits + .reconfig_to_pll(reconfig_to_pll), + .reconfig_from_pll(reconfig_from_pll), + + //User data outputs + .mgmt_readdata(mgmt_readdata), + .mgmt_waitrequest(mgmt_waitrequest), + + //User data inputs + .mgmt_address(mgmt_address), + .mgmt_read(mgmt_read), + .mgmt_write(mgmt_byteenable_write), + .mgmt_writedata(mgmt_writedata), + + // other + .mif_start_out(reconfig2mif_start_out), + .mif_base_addr(mif_base_addr) + ); + + + end // End generate reconfig core only +end // End 28nm Reconfig +endgenerate + +endmodule + diff --git a/sys/pll_hdmi.13.qip b/sys/pll_hdmi.13.qip new file mode 100644 index 0000000..76def89 --- /dev/null +++ b/sys/pll_hdmi.13.qip @@ -0,0 +1,17 @@ +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_TOOL_NAME "altera_pll" +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_TOOL_VERSION "13.1" +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_TOOL_ENV "mwpim" +set_global_assignment -library "pll_hdmi" -name MISC_FILE [file join $::quartus(qip_path) "pll_hdmi.cmp"] +set_global_assignment -name SYNTHESIS_ONLY_QIP ON + +set_global_assignment -library "pll_hdmi" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_hdmi.v"] +set_global_assignment -library "pll_hdmi" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_hdmi/pll_hdmi_0002.v"] + +set_instance_assignment -name PLL_COMPENSATION_MODE DIRECT -to "*pll_hdmi_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_CHANNEL_SPACING "0.0 KHz" -to "*pll_hdmi_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_AUTO_RESET ON -to "*pll_hdmi_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_BANDWIDTH_PRESET AUTO -to "*pll_hdmi_0002*|altera_pll:altera_pll_i*|*" + +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_TOOL_NAME "altera_pll" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_TOOL_VERSION "13.1" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_TOOL_ENV "mwpim" diff --git a/sys/pll_hdmi.qip b/sys/pll_hdmi.qip new file mode 100644 index 0000000..be34aeb --- /dev/null +++ b/sys/pll_hdmi.qip @@ -0,0 +1,483 @@ +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_TOOL_NAME "altera_pll" +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_TOOL_VERSION "17.0" +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_TOOL_ENV "mwpim" +set_global_assignment -library "pll_hdmi" -name MISC_FILE [file join $::quartus(qip_path) "pll_hdmi.cmp"] +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_TARGETED_DEVICE_FAMILY "Cyclone V" +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_GENERATED_DEVICE_FAMILY "{Cyclone V}" +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_QSYS_MODE "UNKNOWN" +set_global_assignment -name SYNTHESIS_ONLY_QIP ON +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_COMPONENT_NAME "cGxsX2hkbWk=" +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_COMPONENT_DISPLAY_NAME "QWx0ZXJhIFBMTA==" +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_COMPONENT_REPORT_HIERARCHY "Off" +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_COMPONENT_INTERNAL "Off" +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_COMPONENT_AUTHOR "QWx0ZXJhIENvcnBvcmF0aW9u" +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_COMPONENT_VERSION "MTcuMA==" +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_COMPONENT_DESCRIPTION "QWx0ZXJhIFBoYXNlLUxvY2tlZCBMb29wIChBTFRFUkFfUExMKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_NAME "cGxsX2hkbWlfMDAwMg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_DISPLAY_NAME "QWx0ZXJhIFBMTA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_REPORT_HIERARCHY "Off" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_INTERNAL "Off" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_AUTHOR "QWx0ZXJhIENvcnBvcmF0aW9u" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_VERSION "MTcuMA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_DESCRIPTION "QWx0ZXJhIFBoYXNlLUxvY2tlZCBMb29wIChBTFRFUkFfUExMKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZGVidWdfcHJpbnRfb3V0cHV0::ZmFsc2U=::ZGVidWdfcHJpbnRfb3V0cHV0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZGVidWdfdXNlX3JiY190YWZfbWV0aG9k::ZmFsc2U=::ZGVidWdfdXNlX3JiY190YWZfbWV0aG9k" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZGV2aWNl::NUNFQkEyRjE3QTc=::ZGV2aWNl" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BsbF9tb2Rl::RnJhY3Rpb25hbC1OIFBMTA==::UExMIE1vZGU=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZnJhY3Rpb25hbF92Y29fbXVsdGlwbGllcg==::dHJ1ZQ==::ZnJhY3Rpb25hbF92Y29fbXVsdGlwbGllcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3JlZmVyZW5jZV9jbG9ja19mcmVxdWVuY3k=::NTAuMA==::UmVmZXJlbmNlIENsb2NrIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cmVmZXJlbmNlX2Nsb2NrX2ZyZXF1ZW5jeQ==::NTAuMCBNSHo=::cmVmZXJlbmNlX2Nsb2NrX2ZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2NoYW5uZWxfc3BhY2luZw==::MC4w::Q2hhbm5lbCBTcGFjaW5n" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX29wZXJhdGlvbl9tb2Rl::ZGlyZWN0::T3BlcmF0aW9uIE1vZGU=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2ZlZWRiYWNrX2Nsb2Nr::R2xvYmFsIENsb2Nr::RmVlZGJhY2sgQ2xvY2s=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2ZyYWN0aW9uYWxfY291dA==::MzI=::RnJhY3Rpb25hbCBjYXJyeSBvdXQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGxsX2ZyYWN0aW9uYWxfY291dA==::MzI=::cGxsX2ZyYWN0aW9uYWxfY291dA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RzbV9vdXRfc2Vs::MXN0X29yZGVy::RFNNIE9yZGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGxsX2RzbV9vdXRfc2Vs::MXN0X29yZGVy::cGxsX2RzbV9vdXRfc2Vs" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3BlcmF0aW9uX21vZGU=::ZGlyZWN0::b3BlcmF0aW9uX21vZGU=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3VzZV9sb2NrZWQ=::ZmFsc2U=::RW5hYmxlIGxvY2tlZCBvdXRwdXQgcG9ydA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX2Fkdl9wYXJhbXM=::ZmFsc2U=::RW5hYmxlIHBoeXNpY2FsIG91dHB1dCBjbG9jayBwYXJhbWV0ZXJz" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX251bWJlcl9vZl9jbG9ja3M=::MQ==::TnVtYmVyIE9mIENsb2Nrcw==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "bnVtYmVyX29mX2Nsb2Nrcw==::MQ==::bnVtYmVyX29mX2Nsb2Nrcw==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX211bHRpcGx5X2ZhY3Rvcg==::MQ==::TXVsdGlwbHkgRmFjdG9yIChNLUNvdW50ZXIp" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2ZyYWNfbXVsdGlwbHlfZmFjdG9y::MQ==::RnJhY3Rpb25hbCBNdWx0aXBseSBGYWN0b3IgKEsp" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3Jfbg==::MQ==::RGl2aWRlIEZhY3RvciAoTi1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjA=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kw::MTQ4LjU=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzA=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Iw::OA==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjA=::MzkwODQyMDE1Mw==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMA==::Mw==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MA==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMA==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MA==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzA=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDA=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUw::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kx::NjUuMA==::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Ix::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMQ==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MQ==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMQ==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MQ==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUx::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjI=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3ky::MjcuMA==::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzI=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Iy::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjI=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMg==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Mg==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMg==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Mg==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzI=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDI=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUy::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjM=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kz::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzM=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Iz::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjM=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMw==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Mw==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMw==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Mw==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzM=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDM=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUz::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjQ=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k0::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzQ=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I0::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjQ=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNA==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5NA==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNA==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0NA==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzQ=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDQ=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU0::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjU=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k1::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzU=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I1::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjU=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNQ==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5NQ==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNQ==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0NQ==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzU=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDU=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU1::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjY=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k2::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzY=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I2::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjY=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNg==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Ng==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNg==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Ng==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzY=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDY=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU2::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjc=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k3::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzc=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I3::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3Rvcjc=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNw==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Nw==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNw==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Nw==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzc=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDc=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU3::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjg=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k4::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzg=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I4::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3Rvcjg=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yOA==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5OA==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzOA==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0OA==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzg=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDg=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU4::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjk=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k5::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzk=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I5::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3Rvcjk=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yOQ==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5OQ==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzOQ==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0OQ==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzk=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDk=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU5::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEw::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMA==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEw::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMA==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEw::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTA=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTA=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTA=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTA=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEw::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEw::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMA==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEx::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMQ==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEx::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMQ==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEx::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTE=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTE=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTE=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTE=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEx::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEx::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMQ==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEy::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMg==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEy::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMg==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEy::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTI=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTI=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTI=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTI=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEy::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEy::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMg==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEz::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMw==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEz::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMw==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEz::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTM=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTM=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTM=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTM=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEz::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEz::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMw==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE0::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNA==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE0::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNA==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE0::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTQ=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTQ=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTQ=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTQ=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE0::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE0::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNA==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE1::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNQ==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE1::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNQ==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE1::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTU=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTU=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTU=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTU=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE1::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE1::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNQ==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE2::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNg==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE2::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNg==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE2::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTY=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTY=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTY=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTY=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE2::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE2::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNg==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE3::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNw==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE3::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNw==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE3::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTc=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTc=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTc=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTc=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE3::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE3::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNw==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTA=::MTQ4LjUwMDAwMCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTA=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQw::MCBwcw==::cGhhc2Vfc2hpZnQw" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTA=::NTA=::ZHV0eV9jeWNsZTA=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQx::MCBwcw==::cGhhc2Vfc2hpZnQx" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE=::NTA=::ZHV0eV9jeWNsZTE=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTI=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTI=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQy::MCBwcw==::cGhhc2Vfc2hpZnQy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTI=::NTA=::ZHV0eV9jeWNsZTI=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTM=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQz::MCBwcw==::cGhhc2Vfc2hpZnQz" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTM=::NTA=::ZHV0eV9jeWNsZTM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTQ=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ0::MCBwcw==::cGhhc2Vfc2hpZnQ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTQ=::NTA=::ZHV0eV9jeWNsZTQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTU=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTU=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ1::MCBwcw==::cGhhc2Vfc2hpZnQ1" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTU=::NTA=::ZHV0eV9jeWNsZTU=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTY=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTY=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ2::MCBwcw==::cGhhc2Vfc2hpZnQ2" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTY=::NTA=::ZHV0eV9jeWNsZTY=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTc=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTc=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ3::MCBwcw==::cGhhc2Vfc2hpZnQ3" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTc=::NTA=::ZHV0eV9jeWNsZTc=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTg=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTg=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ4::MCBwcw==::cGhhc2Vfc2hpZnQ4" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTg=::NTA=::ZHV0eV9jeWNsZTg=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTk=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTk=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ5::MCBwcw==::cGhhc2Vfc2hpZnQ5" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTk=::NTA=::ZHV0eV9jeWNsZTk=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEw::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEw" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMA==::MCBwcw==::cGhhc2Vfc2hpZnQxMA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEw::NTA=::ZHV0eV9jeWNsZTEw" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEx::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEx" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMQ==::MCBwcw==::cGhhc2Vfc2hpZnQxMQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEx::NTA=::ZHV0eV9jeWNsZTEx" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEy::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMg==::MCBwcw==::cGhhc2Vfc2hpZnQxMg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEy::NTA=::ZHV0eV9jeWNsZTEy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEz::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEz" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMw==::MCBwcw==::cGhhc2Vfc2hpZnQxMw==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEz::NTA=::ZHV0eV9jeWNsZTEz" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE0::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNA==::MCBwcw==::cGhhc2Vfc2hpZnQxNA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE0::NTA=::ZHV0eV9jeWNsZTE0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE1::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE1" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNQ==::MCBwcw==::cGhhc2Vfc2hpZnQxNQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE1::NTA=::ZHV0eV9jeWNsZTE1" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE2::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE2" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNg==::MCBwcw==::cGhhc2Vfc2hpZnQxNg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE2::NTA=::ZHV0eV9jeWNsZTE2" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE3::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE3" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNw==::MCBwcw==::cGhhc2Vfc2hpZnQxNw==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE3::NTA=::ZHV0eV9jeWNsZTE3" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BsbF9hdXRvX3Jlc2V0::T24=::UExMIEF1dG8gUmVzZXQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BsbF9iYW5kd2lkdGhfcHJlc2V0::QXV0bw==::UExMIEJhbmR3aWR0aCBQcmVzZXQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX3JlY29uZg==::dHJ1ZQ==::RW5hYmxlIGR5bmFtaWMgcmVjb25maWd1cmF0aW9uIG9mIFBMTA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX2Rwc19wb3J0cw==::ZmFsc2U=::RW5hYmxlIGFjY2VzcyB0byBkeW5hbWljIHBoYXNlIHNoaWZ0IHBvcnRz" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX3Bob3V0X3BvcnRz::ZmFsc2U=::RW5hYmxlIGFjY2VzcyB0byBQTEwgRFBBIG91dHB1dCBwb3J0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGxsX3R5cGU=::Q3ljbG9uZSBW::UExMIFRZUEU=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGxsX3N1YnR5cGU=::UmVjb25maWd1cmFibGU=::UExMIFNVQlRZUEU=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "bV9jbnRfaGlfZGl2::NA==::bV9jbnRfaGlfZGl2" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "bV9jbnRfbG9fZGl2::NA==::bV9jbnRfbG9fZGl2" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "bl9jbnRfaGlfZGl2::MjU2::bl9jbnRfaGlfZGl2" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "bl9jbnRfbG9fZGl2::MjU2::bl9jbnRfbG9fZGl2" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "bV9jbnRfYnlwYXNzX2Vu::ZmFsc2U=::bV9jbnRfYnlwYXNzX2Vu" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "bl9jbnRfYnlwYXNzX2Vu::dHJ1ZQ==::bl9jbnRfYnlwYXNzX2Vu" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "bV9jbnRfb2RkX2Rpdl9kdXR5X2Vu::ZmFsc2U=::bV9jbnRfb2RkX2Rpdl9kdXR5X2Vu" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "bl9jbnRfb2RkX2Rpdl9kdXR5X2Vu::ZmFsc2U=::bl9jbnRfb2RkX2Rpdl9kdXR5X2Vu" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaGlfZGl2MA==::Mg==::Y19jbnRfaGlfZGl2MA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfbG9fZGl2MA==::MQ==::Y19jbnRfbG9fZGl2MA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcHJzdDA=::MQ==::Y19jbnRfcHJzdDA=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcGhfbXV4X3Byc3Qw::MA==::Y19jbnRfcGhfbXV4X3Byc3Qw" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaW5fc3JjMA==::cGhfbXV4X2Nsaw==::Y19jbnRfaW5fc3JjMA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfYnlwYXNzX2VuMA==::ZmFsc2U=::Y19jbnRfYnlwYXNzX2VuMA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMA==::dHJ1ZQ==::Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaGlfZGl2MQ==::MQ==::Y19jbnRfaGlfZGl2MQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfbG9fZGl2MQ==::MQ==::Y19jbnRfbG9fZGl2MQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcHJzdDE=::MQ==::Y19jbnRfcHJzdDE=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcGhfbXV4X3Byc3Qx::MA==::Y19jbnRfcGhfbXV4X3Byc3Qx" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaW5fc3JjMQ==::cGhfbXV4X2Nsaw==::Y19jbnRfaW5fc3JjMQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfYnlwYXNzX2VuMQ==::dHJ1ZQ==::Y19jbnRfYnlwYXNzX2VuMQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMQ==::ZmFsc2U=::Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaGlfZGl2Mg==::MQ==::Y19jbnRfaGlfZGl2Mg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfbG9fZGl2Mg==::MQ==::Y19jbnRfbG9fZGl2Mg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcHJzdDI=::MQ==::Y19jbnRfcHJzdDI=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcGhfbXV4X3Byc3Qy::MA==::Y19jbnRfcGhfbXV4X3Byc3Qy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaW5fc3JjMg==::cGhfbXV4X2Nsaw==::Y19jbnRfaW5fc3JjMg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfYnlwYXNzX2VuMg==::dHJ1ZQ==::Y19jbnRfYnlwYXNzX2VuMg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMg==::ZmFsc2U=::Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaGlfZGl2Mw==::MQ==::Y19jbnRfaGlfZGl2Mw==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfbG9fZGl2Mw==::MQ==::Y19jbnRfbG9fZGl2Mw==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcHJzdDM=::MQ==::Y19jbnRfcHJzdDM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcGhfbXV4X3Byc3Qz::MA==::Y19jbnRfcGhfbXV4X3Byc3Qz" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaW5fc3JjMw==::cGhfbXV4X2Nsaw==::Y19jbnRfaW5fc3JjMw==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfYnlwYXNzX2VuMw==::dHJ1ZQ==::Y19jbnRfYnlwYXNzX2VuMw==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMw==::ZmFsc2U=::Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMw==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaGlfZGl2NA==::MQ==::Y19jbnRfaGlfZGl2NA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfbG9fZGl2NA==::MQ==::Y19jbnRfbG9fZGl2NA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcHJzdDQ=::MQ==::Y19jbnRfcHJzdDQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcGhfbXV4X3Byc3Q0::MA==::Y19jbnRfcGhfbXV4X3Byc3Q0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaW5fc3JjNA==::cGhfbXV4X2Nsaw==::Y19jbnRfaW5fc3JjNA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfYnlwYXNzX2VuNA==::dHJ1ZQ==::Y19jbnRfYnlwYXNzX2VuNA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfb2RkX2Rpdl9kdXR5X2VuNA==::ZmFsc2U=::Y19jbnRfb2RkX2Rpdl9kdXR5X2VuNA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaGlfZGl2NQ==::MQ==::Y19jbnRfaGlfZGl2NQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfbG9fZGl2NQ==::MQ==::Y19jbnRfbG9fZGl2NQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcHJzdDU=::MQ==::Y19jbnRfcHJzdDU=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcGhfbXV4X3Byc3Q1::MA==::Y19jbnRfcGhfbXV4X3Byc3Q1" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaW5fc3JjNQ==::cGhfbXV4X2Nsaw==::Y19jbnRfaW5fc3JjNQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfYnlwYXNzX2VuNQ==::dHJ1ZQ==::Y19jbnRfYnlwYXNzX2VuNQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfb2RkX2Rpdl9kdXR5X2VuNQ==::ZmFsc2U=::Y19jbnRfb2RkX2Rpdl9kdXR5X2VuNQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaGlfZGl2Ng==::MQ==::Y19jbnRfaGlfZGl2Ng==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfbG9fZGl2Ng==::MQ==::Y19jbnRfbG9fZGl2Ng==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcHJzdDY=::MQ==::Y19jbnRfcHJzdDY=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcGhfbXV4X3Byc3Q2::MA==::Y19jbnRfcGhfbXV4X3Byc3Q2" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaW5fc3JjNg==::cGhfbXV4X2Nsaw==::Y19jbnRfaW5fc3JjNg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfYnlwYXNzX2VuNg==::dHJ1ZQ==::Y19jbnRfYnlwYXNzX2VuNg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfb2RkX2Rpdl9kdXR5X2VuNg==::ZmFsc2U=::Y19jbnRfb2RkX2Rpdl9kdXR5X2VuNg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaGlfZGl2Nw==::MQ==::Y19jbnRfaGlfZGl2Nw==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfbG9fZGl2Nw==::MQ==::Y19jbnRfbG9fZGl2Nw==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcHJzdDc=::MQ==::Y19jbnRfcHJzdDc=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcGhfbXV4X3Byc3Q3::MA==::Y19jbnRfcGhfbXV4X3Byc3Q3" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaW5fc3JjNw==::cGhfbXV4X2Nsaw==::Y19jbnRfaW5fc3JjNw==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfYnlwYXNzX2VuNw==::dHJ1ZQ==::Y19jbnRfYnlwYXNzX2VuNw==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfb2RkX2Rpdl9kdXR5X2VuNw==::ZmFsc2U=::Y19jbnRfb2RkX2Rpdl9kdXR5X2VuNw==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaGlfZGl2OA==::MQ==::Y19jbnRfaGlfZGl2OA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfbG9fZGl2OA==::MQ==::Y19jbnRfbG9fZGl2OA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcHJzdDg=::MQ==::Y19jbnRfcHJzdDg=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcGhfbXV4X3Byc3Q4::MA==::Y19jbnRfcGhfbXV4X3Byc3Q4" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaW5fc3JjOA==::cGhfbXV4X2Nsaw==::Y19jbnRfaW5fc3JjOA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfYnlwYXNzX2VuOA==::dHJ1ZQ==::Y19jbnRfYnlwYXNzX2VuOA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfb2RkX2Rpdl9kdXR5X2VuOA==::ZmFsc2U=::Y19jbnRfb2RkX2Rpdl9kdXR5X2VuOA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaGlfZGl2OQ==::MQ==::Y19jbnRfaGlfZGl2OQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfbG9fZGl2OQ==::MQ==::Y19jbnRfbG9fZGl2OQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcHJzdDk=::MQ==::Y19jbnRfcHJzdDk=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcGhfbXV4X3Byc3Q5::MA==::Y19jbnRfcGhfbXV4X3Byc3Q5" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaW5fc3JjOQ==::cGhfbXV4X2Nsaw==::Y19jbnRfaW5fc3JjOQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfYnlwYXNzX2VuOQ==::dHJ1ZQ==::Y19jbnRfYnlwYXNzX2VuOQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfb2RkX2Rpdl9kdXR5X2VuOQ==::ZmFsc2U=::Y19jbnRfb2RkX2Rpdl9kdXR5X2VuOQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaGlfZGl2MTA=::MQ==::Y19jbnRfaGlfZGl2MTA=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfbG9fZGl2MTA=::MQ==::Y19jbnRfbG9fZGl2MTA=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcHJzdDEw::MQ==::Y19jbnRfcHJzdDEw" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcGhfbXV4X3Byc3QxMA==::MA==::Y19jbnRfcGhfbXV4X3Byc3QxMA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaW5fc3JjMTA=::cGhfbXV4X2Nsaw==::Y19jbnRfaW5fc3JjMTA=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfYnlwYXNzX2VuMTA=::dHJ1ZQ==::Y19jbnRfYnlwYXNzX2VuMTA=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMTA=::ZmFsc2U=::Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMTA=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaGlfZGl2MTE=::MQ==::Y19jbnRfaGlfZGl2MTE=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfbG9fZGl2MTE=::MQ==::Y19jbnRfbG9fZGl2MTE=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcHJzdDEx::MQ==::Y19jbnRfcHJzdDEx" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcGhfbXV4X3Byc3QxMQ==::MA==::Y19jbnRfcGhfbXV4X3Byc3QxMQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaW5fc3JjMTE=::cGhfbXV4X2Nsaw==::Y19jbnRfaW5fc3JjMTE=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfYnlwYXNzX2VuMTE=::dHJ1ZQ==::Y19jbnRfYnlwYXNzX2VuMTE=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMTE=::ZmFsc2U=::Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMTE=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaGlfZGl2MTI=::MQ==::Y19jbnRfaGlfZGl2MTI=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfbG9fZGl2MTI=::MQ==::Y19jbnRfbG9fZGl2MTI=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcHJzdDEy::MQ==::Y19jbnRfcHJzdDEy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcGhfbXV4X3Byc3QxMg==::MA==::Y19jbnRfcGhfbXV4X3Byc3QxMg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaW5fc3JjMTI=::cGhfbXV4X2Nsaw==::Y19jbnRfaW5fc3JjMTI=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfYnlwYXNzX2VuMTI=::dHJ1ZQ==::Y19jbnRfYnlwYXNzX2VuMTI=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMTI=::ZmFsc2U=::Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMTI=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaGlfZGl2MTM=::MQ==::Y19jbnRfaGlfZGl2MTM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfbG9fZGl2MTM=::MQ==::Y19jbnRfbG9fZGl2MTM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcHJzdDEz::MQ==::Y19jbnRfcHJzdDEz" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcGhfbXV4X3Byc3QxMw==::MA==::Y19jbnRfcGhfbXV4X3Byc3QxMw==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaW5fc3JjMTM=::cGhfbXV4X2Nsaw==::Y19jbnRfaW5fc3JjMTM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfYnlwYXNzX2VuMTM=::dHJ1ZQ==::Y19jbnRfYnlwYXNzX2VuMTM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMTM=::ZmFsc2U=::Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMTM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaGlfZGl2MTQ=::MQ==::Y19jbnRfaGlfZGl2MTQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfbG9fZGl2MTQ=::MQ==::Y19jbnRfbG9fZGl2MTQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcHJzdDE0::MQ==::Y19jbnRfcHJzdDE0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcGhfbXV4X3Byc3QxNA==::MA==::Y19jbnRfcGhfbXV4X3Byc3QxNA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaW5fc3JjMTQ=::cGhfbXV4X2Nsaw==::Y19jbnRfaW5fc3JjMTQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfYnlwYXNzX2VuMTQ=::dHJ1ZQ==::Y19jbnRfYnlwYXNzX2VuMTQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMTQ=::ZmFsc2U=::Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMTQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaGlfZGl2MTU=::MQ==::Y19jbnRfaGlfZGl2MTU=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfbG9fZGl2MTU=::MQ==::Y19jbnRfbG9fZGl2MTU=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcHJzdDE1::MQ==::Y19jbnRfcHJzdDE1" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcGhfbXV4X3Byc3QxNQ==::MA==::Y19jbnRfcGhfbXV4X3Byc3QxNQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaW5fc3JjMTU=::cGhfbXV4X2Nsaw==::Y19jbnRfaW5fc3JjMTU=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfYnlwYXNzX2VuMTU=::dHJ1ZQ==::Y19jbnRfYnlwYXNzX2VuMTU=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMTU=::ZmFsc2U=::Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMTU=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaGlfZGl2MTY=::MQ==::Y19jbnRfaGlfZGl2MTY=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfbG9fZGl2MTY=::MQ==::Y19jbnRfbG9fZGl2MTY=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcHJzdDE2::MQ==::Y19jbnRfcHJzdDE2" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcGhfbXV4X3Byc3QxNg==::MA==::Y19jbnRfcGhfbXV4X3Byc3QxNg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaW5fc3JjMTY=::cGhfbXV4X2Nsaw==::Y19jbnRfaW5fc3JjMTY=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfYnlwYXNzX2VuMTY=::dHJ1ZQ==::Y19jbnRfYnlwYXNzX2VuMTY=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMTY=::ZmFsc2U=::Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMTY=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaGlfZGl2MTc=::MQ==::Y19jbnRfaGlfZGl2MTc=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfbG9fZGl2MTc=::MQ==::Y19jbnRfbG9fZGl2MTc=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcHJzdDE3::MQ==::Y19jbnRfcHJzdDE3" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcGhfbXV4X3Byc3QxNw==::MA==::Y19jbnRfcGhfbXV4X3Byc3QxNw==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaW5fc3JjMTc=::cGhfbXV4X2Nsaw==::Y19jbnRfaW5fc3JjMTc=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfYnlwYXNzX2VuMTc=::dHJ1ZQ==::Y19jbnRfYnlwYXNzX2VuMTc=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMTc=::ZmFsc2U=::Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMTc=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGxsX3Zjb19kaXY=::Mg==::cGxsX3Zjb19kaXY=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGxsX2NwX2N1cnJlbnQ=::MjA=::cGxsX2NwX2N1cnJlbnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGxsX2J3Y3RybA==::NDAwMA==::cGxsX2J3Y3RybA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGxsX291dHB1dF9jbGtfZnJlcXVlbmN5::NDQ1LjQ5OTk5OSBNSHo=::cGxsX291dHB1dF9jbGtfZnJlcXVlbmN5" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGxsX2ZyYWN0aW9uYWxfZGl2aXNpb24=::MzkwODQyMDE1Mw==::cGxsX2ZyYWN0aW9uYWxfZGl2aXNpb24=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "bWltaWNfZmJjbGtfdHlwZQ==::bm9uZQ==::bWltaWNfZmJjbGtfdHlwZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGxsX2ZiY2xrX211eF8x::Z2xi::cGxsX2ZiY2xrX211eF8x" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGxsX2ZiY2xrX211eF8y::bV9jbnQ=::cGxsX2ZiY2xrX211eF8y" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGxsX21fY250X2luX3NyYw==::cGhfbXV4X2Nsaw==::cGxsX21fY250X2luX3NyYw==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGxsX3NsZl9yc3Q=::dHJ1ZQ==::cGxsX3NsZl9yc3Q=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BhcmFtZXRlcl9saXN0::TS1Db3VudGVyIEhpIERpdmlkZSxNLUNvdW50ZXIgTG93IERpdmlkZSxOLUNvdW50ZXIgSGkgRGl2aWRlLE4tQ291bnRlciBMb3cgRGl2aWRlLE0tQ291bnRlciBCeXBhc3MgRW5hYmxlLE4tQ291bnRlciBCeXBhc3MgRW5hYmxlLE0tQ291bnRlciBPZGQgRGl2aWRlIEVuYWJsZSxOLUNvdW50ZXIgT2RkIERpdmlkZSBFbmFibGUsQy1Db3VudGVyLTAgSGkgRGl2aWRlLEMtQ291bnRlci0wIExvdyBEaXZpZGUsQy1Db3VudGVyLTAgQ29hcnNlIFBoYXNlIFNoaWZ0LEMtQ291bnRlci0wIFZDTyBQaGFzZSBUYXAsQy1Db3VudGVyLTAgSW5wdXQgU291cmNlLEMtQ291bnRlci0wIEJ5cGFzcyBFbmFibGUsQy1Db3VudGVyLTAgT2RkIERpdmlkZSBFbmFibGUsVkNPIFBvc3QgRGl2aWRlIENvdW50ZXIgRW5hYmxlLENoYXJnZSBQdW1wIGN1cnJlbnQgKHVBKSxMb29wIEZpbHRlciBCYW5kd2lkdGggUmVzaXN0b3IgKE9obXMpICxQTEwgT3V0cHV0IFZDTyBGcmVxdWVuY3ksSy1GcmFjdGlvbmFsIERpdmlzaW9uIFZhbHVlIChEU00pLEZlZWRiYWNrIENsb2NrIFR5cGUsRmVlZGJhY2sgQ2xvY2sgTVVYIDEsRmVlZGJhY2sgQ2xvY2sgTVVYIDIsTSBDb3VudGVyIFNvdXJjZSBNVVgsUExMIEF1dG8gUmVzZXQ=::UGFyYW1ldGVyIE5hbWVz" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BhcmFtZXRlcl92YWx1ZXM=::NCw0LDI1NiwyNTYsZmFsc2UsdHJ1ZSxmYWxzZSxmYWxzZSwyLDEsMSwwLHBoX211eF9jbGssZmFsc2UsdHJ1ZSwyLDIwLDQwMDAsNDQ1LjQ5OTk5OSBNSHosMzkwODQyMDE1Myxub25lLGdsYixtX2NudCxwaF9tdXhfY2xrLHRydWU=::UGFyYW1ldGVyIFZhbHVlcw==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX21pZl9nZW5lcmF0ZQ==::ZmFsc2U=::R2VuZXJhdGUgTUlGIGZpbGU=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9taWZfZHBz::ZmFsc2U=::RW5hYmxlIER5bmFtaWMgUGhhc2UgU2hpZnQgZm9yIE1JRiBzdHJlYW1pbmc=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Rwc19jbnRy::QzA=::RFBTIENvdW50ZXIgU2VsZWN0aW9u" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Rwc19udW0=::MQ==::TnVtYmVyIG9mIER5bmFtaWMgUGhhc2UgU2hpZnRz" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Rwc19kaXI=::UG9zaXRpdmU=::RHluYW1pYyBQaGFzZSBTaGlmdCBEaXJlY3Rpb24=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3JlZmNsa19zd2l0Y2g=::ZmFsc2U=::Q3JlYXRlIGEgc2Vjb25kIGlucHV0IGNsayAncmVmY2xrMSc=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9jYXNjYWRlX291dA==::ZmFsc2U=::Q3JlYXRlIGEgJ2Nhc2NhZGVfb3V0JyBzaWduYWwgdG8gY29ubmVjdCB3aXRoIGEgZG93bnN0cmVhbSBQTEw=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9jYXNjYWRlX2lu::ZmFsc2U=::Q3JlYXRlIGFuIGFkanBsbGluIG9yIGNjbGsgc2lnbmFsIHRvIGNvbm5lY3Qgd2l0aCBhbiB1cHN0cmVhbSBQTEw=" + +set_global_assignment -library "pll_hdmi" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_hdmi.v"] +set_global_assignment -library "pll_hdmi" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_hdmi/pll_hdmi_0002.v"] +set_global_assignment -library "pll_hdmi" -name QIP_FILE [file join $::quartus(qip_path) "pll_hdmi/pll_hdmi_0002.qip"] + +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_TOOL_NAME "altera_pll" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_TOOL_VERSION "17.0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_TOOL_ENV "mwpim" diff --git a/sys/pll_hdmi.v b/sys/pll_hdmi.v new file mode 100644 index 0000000..52a9de9 --- /dev/null +++ b/sys/pll_hdmi.v @@ -0,0 +1,256 @@ +// megafunction wizard: %Altera PLL v17.0% +// GENERATION: XML +// pll_hdmi.v + +// Generated using ACDS version 17.0 598 + +`timescale 1 ps / 1 ps +module pll_hdmi ( + input wire refclk, // refclk.clk + input wire rst, // reset.reset + output wire outclk_0, // outclk0.clk + input wire [63:0] reconfig_to_pll, // reconfig_to_pll.reconfig_to_pll + output wire [63:0] reconfig_from_pll // reconfig_from_pll.reconfig_from_pll + ); + + pll_hdmi_0002 pll_hdmi_inst ( + .refclk (refclk), // refclk.clk + .rst (rst), // reset.reset + .outclk_0 (outclk_0), // outclk0.clk + .reconfig_to_pll (reconfig_to_pll), // reconfig_to_pll.reconfig_to_pll + .reconfig_from_pll (reconfig_from_pll), // reconfig_from_pll.reconfig_from_pll + .locked () // (terminated) + ); + +endmodule +// Retrieval info: +// +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// IPFS_FILES : pll_hdmi.vo +// RELATED_FILES: pll_hdmi.v, pll_hdmi_0002.v diff --git a/sys/pll_hdmi/pll_hdmi_0002.qip b/sys/pll_hdmi/pll_hdmi_0002.qip new file mode 100644 index 0000000..3cb7073 --- /dev/null +++ b/sys/pll_hdmi/pll_hdmi_0002.qip @@ -0,0 +1,2 @@ +set_instance_assignment -name PLL_COMPENSATION_MODE DIRECT -to "*pll_hdmi_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name UNFORCE_MERGE_PLL_OUTPUT_COUNTER ON -to "*pll_hdmi_0002*|altera_pll:altera_pll_i*|*" diff --git a/sys/pll_hdmi/pll_hdmi_0002.v b/sys/pll_hdmi/pll_hdmi_0002.v new file mode 100644 index 0000000..dc63100 --- /dev/null +++ b/sys/pll_hdmi/pll_hdmi_0002.v @@ -0,0 +1,241 @@ +`timescale 1ns/10ps +module pll_hdmi_0002( + + // interface 'refclk' + input wire refclk, + + // interface 'reset' + input wire rst, + + // interface 'outclk0' + output wire outclk_0, + + // interface 'locked' + output wire locked, + + // interface 'reconfig_to_pll' + input wire [63:0] reconfig_to_pll, + + // interface 'reconfig_from_pll' + output wire [63:0] reconfig_from_pll +); + + altera_pll #( + .fractional_vco_multiplier("true"), + .reference_clock_frequency("50.0 MHz"), + .pll_fractional_cout(32), + .pll_dsm_out_sel("1st_order"), + .operation_mode("direct"), + .number_of_clocks(1), + .output_clock_frequency0("148.500000 MHz"), + .phase_shift0("0 ps"), + .duty_cycle0(50), + .output_clock_frequency1("0 MHz"), + .phase_shift1("0 ps"), + .duty_cycle1(50), + .output_clock_frequency2("0 MHz"), + .phase_shift2("0 ps"), + .duty_cycle2(50), + .output_clock_frequency3("0 MHz"), + .phase_shift3("0 ps"), + .duty_cycle3(50), + .output_clock_frequency4("0 MHz"), + .phase_shift4("0 ps"), + .duty_cycle4(50), + .output_clock_frequency5("0 MHz"), + .phase_shift5("0 ps"), + .duty_cycle5(50), + .output_clock_frequency6("0 MHz"), + .phase_shift6("0 ps"), + .duty_cycle6(50), + .output_clock_frequency7("0 MHz"), + .phase_shift7("0 ps"), + .duty_cycle7(50), + .output_clock_frequency8("0 MHz"), + .phase_shift8("0 ps"), + .duty_cycle8(50), + .output_clock_frequency9("0 MHz"), + .phase_shift9("0 ps"), + .duty_cycle9(50), + .output_clock_frequency10("0 MHz"), + .phase_shift10("0 ps"), + .duty_cycle10(50), + .output_clock_frequency11("0 MHz"), + .phase_shift11("0 ps"), + .duty_cycle11(50), + .output_clock_frequency12("0 MHz"), + .phase_shift12("0 ps"), + .duty_cycle12(50), + .output_clock_frequency13("0 MHz"), + .phase_shift13("0 ps"), + .duty_cycle13(50), + .output_clock_frequency14("0 MHz"), + .phase_shift14("0 ps"), + .duty_cycle14(50), + .output_clock_frequency15("0 MHz"), + .phase_shift15("0 ps"), + .duty_cycle15(50), + .output_clock_frequency16("0 MHz"), + .phase_shift16("0 ps"), + .duty_cycle16(50), + .output_clock_frequency17("0 MHz"), + .phase_shift17("0 ps"), + .duty_cycle17(50), + .pll_type("Cyclone V"), + .pll_subtype("Reconfigurable"), + .m_cnt_hi_div(4), + .m_cnt_lo_div(4), + .n_cnt_hi_div(256), + .n_cnt_lo_div(256), + .m_cnt_bypass_en("false"), + .n_cnt_bypass_en("true"), + .m_cnt_odd_div_duty_en("false"), + .n_cnt_odd_div_duty_en("false"), + .c_cnt_hi_div0(2), + .c_cnt_lo_div0(1), + .c_cnt_prst0(1), + .c_cnt_ph_mux_prst0(0), + .c_cnt_in_src0("ph_mux_clk"), + .c_cnt_bypass_en0("false"), + .c_cnt_odd_div_duty_en0("true"), + .c_cnt_hi_div1(1), + .c_cnt_lo_div1(1), + .c_cnt_prst1(1), + .c_cnt_ph_mux_prst1(0), + .c_cnt_in_src1("ph_mux_clk"), + .c_cnt_bypass_en1("true"), + .c_cnt_odd_div_duty_en1("false"), + .c_cnt_hi_div2(1), + .c_cnt_lo_div2(1), + .c_cnt_prst2(1), + .c_cnt_ph_mux_prst2(0), + .c_cnt_in_src2("ph_mux_clk"), + .c_cnt_bypass_en2("true"), + .c_cnt_odd_div_duty_en2("false"), + .c_cnt_hi_div3(1), + .c_cnt_lo_div3(1), + .c_cnt_prst3(1), + .c_cnt_ph_mux_prst3(0), + .c_cnt_in_src3("ph_mux_clk"), + .c_cnt_bypass_en3("true"), + .c_cnt_odd_div_duty_en3("false"), + .c_cnt_hi_div4(1), + .c_cnt_lo_div4(1), + .c_cnt_prst4(1), + .c_cnt_ph_mux_prst4(0), + .c_cnt_in_src4("ph_mux_clk"), + .c_cnt_bypass_en4("true"), + .c_cnt_odd_div_duty_en4("false"), + .c_cnt_hi_div5(1), + .c_cnt_lo_div5(1), + .c_cnt_prst5(1), + .c_cnt_ph_mux_prst5(0), + .c_cnt_in_src5("ph_mux_clk"), + .c_cnt_bypass_en5("true"), + .c_cnt_odd_div_duty_en5("false"), + .c_cnt_hi_div6(1), + .c_cnt_lo_div6(1), + .c_cnt_prst6(1), + .c_cnt_ph_mux_prst6(0), + .c_cnt_in_src6("ph_mux_clk"), + .c_cnt_bypass_en6("true"), + .c_cnt_odd_div_duty_en6("false"), + .c_cnt_hi_div7(1), + .c_cnt_lo_div7(1), + .c_cnt_prst7(1), + .c_cnt_ph_mux_prst7(0), + .c_cnt_in_src7("ph_mux_clk"), + .c_cnt_bypass_en7("true"), + .c_cnt_odd_div_duty_en7("false"), + .c_cnt_hi_div8(1), + .c_cnt_lo_div8(1), + .c_cnt_prst8(1), + .c_cnt_ph_mux_prst8(0), + .c_cnt_in_src8("ph_mux_clk"), + .c_cnt_bypass_en8("true"), + .c_cnt_odd_div_duty_en8("false"), + .c_cnt_hi_div9(1), + .c_cnt_lo_div9(1), + .c_cnt_prst9(1), + .c_cnt_ph_mux_prst9(0), + .c_cnt_in_src9("ph_mux_clk"), + .c_cnt_bypass_en9("true"), + .c_cnt_odd_div_duty_en9("false"), + .c_cnt_hi_div10(1), + .c_cnt_lo_div10(1), + .c_cnt_prst10(1), + .c_cnt_ph_mux_prst10(0), + .c_cnt_in_src10("ph_mux_clk"), + .c_cnt_bypass_en10("true"), + .c_cnt_odd_div_duty_en10("false"), + .c_cnt_hi_div11(1), + .c_cnt_lo_div11(1), + .c_cnt_prst11(1), + .c_cnt_ph_mux_prst11(0), + .c_cnt_in_src11("ph_mux_clk"), + .c_cnt_bypass_en11("true"), + .c_cnt_odd_div_duty_en11("false"), + .c_cnt_hi_div12(1), + .c_cnt_lo_div12(1), + .c_cnt_prst12(1), + .c_cnt_ph_mux_prst12(0), + .c_cnt_in_src12("ph_mux_clk"), + .c_cnt_bypass_en12("true"), + .c_cnt_odd_div_duty_en12("false"), + .c_cnt_hi_div13(1), + .c_cnt_lo_div13(1), + .c_cnt_prst13(1), + .c_cnt_ph_mux_prst13(0), + .c_cnt_in_src13("ph_mux_clk"), + .c_cnt_bypass_en13("true"), + .c_cnt_odd_div_duty_en13("false"), + .c_cnt_hi_div14(1), + .c_cnt_lo_div14(1), + .c_cnt_prst14(1), + .c_cnt_ph_mux_prst14(0), + .c_cnt_in_src14("ph_mux_clk"), + .c_cnt_bypass_en14("true"), + .c_cnt_odd_div_duty_en14("false"), + .c_cnt_hi_div15(1), + .c_cnt_lo_div15(1), + .c_cnt_prst15(1), + .c_cnt_ph_mux_prst15(0), + .c_cnt_in_src15("ph_mux_clk"), + .c_cnt_bypass_en15("true"), + .c_cnt_odd_div_duty_en15("false"), + .c_cnt_hi_div16(1), + .c_cnt_lo_div16(1), + .c_cnt_prst16(1), + .c_cnt_ph_mux_prst16(0), + .c_cnt_in_src16("ph_mux_clk"), + .c_cnt_bypass_en16("true"), + .c_cnt_odd_div_duty_en16("false"), + .c_cnt_hi_div17(1), + .c_cnt_lo_div17(1), + .c_cnt_prst17(1), + .c_cnt_ph_mux_prst17(0), + .c_cnt_in_src17("ph_mux_clk"), + .c_cnt_bypass_en17("true"), + .c_cnt_odd_div_duty_en17("false"), + .pll_vco_div(2), + .pll_cp_current(20), + .pll_bwctrl(4000), + .pll_output_clk_frequency("445.499999 MHz"), + .pll_fractional_division("3908420153"), + .mimic_fbclk_type("none"), + .pll_fbclk_mux_1("glb"), + .pll_fbclk_mux_2("m_cnt"), + .pll_m_cnt_in_src("ph_mux_clk"), + .pll_slf_rst("true") + ) altera_pll_i ( + .rst (rst), + .outclk ({outclk_0}), + .locked (locked), + .reconfig_to_pll (reconfig_to_pll), + .fboutclk ( ), + .fbclk (1'b0), + .refclk (refclk), + .reconfig_from_pll (reconfig_from_pll) + ); +endmodule + diff --git a/sys/pll_hdmi_adj.vhd b/sys/pll_hdmi_adj.vhd new file mode 100644 index 0000000..67287cb --- /dev/null +++ b/sys/pll_hdmi_adj.vhd @@ -0,0 +1,433 @@ +-------------------------------------------------------------------------------- +-- HDMI PLL Adjust +-------------------------------------------------------------------------------- + +-- Changes the HDMI PLL frequency according to the scaler suggestions. +-------------------------------------------- +-- LLTUNE : +-- 0 : Input Display Enable +-- 1 : Input Vsync +-- 2 : Input Interlaced mode +-- 3 : Input Interlaced field +-- 4 : Output Image frame +-- 5 : +-- 6 : Input clock +-- 7 : Output clock + +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; +USE ieee.numeric_std.ALL; + +ENTITY pll_hdmi_adj IS + PORT ( + -- Scaler + llena : IN std_logic; -- 0=Disabled 1=Enabled + lltune : IN unsigned(15 DOWNTO 0); -- Outputs from scaler + + locked : OUT std_logic; + + -- Signals from reconfig commands + i_waitrequest : OUT std_logic; + i_write : IN std_logic; + i_address : IN unsigned(5 DOWNTO 0); + i_writedata : IN unsigned(31 DOWNTO 0); + + -- Outputs to PLL_HDMI_CFG + o_waitrequest : IN std_logic; + o_write : OUT std_logic; + o_address : OUT unsigned(5 DOWNTO 0); + o_writedata : OUT unsigned(31 DOWNTO 0); + + ------------------------------------ + clk : IN std_logic; + reset_na : IN std_logic + ); + +BEGIN + + +END ENTITY pll_hdmi_adj; + +--############################################################################## + +ARCHITECTURE rtl OF pll_hdmi_adj IS + + SIGNAL i_clk,i_de,i_de2,i_vss,i_vss2,i_vss_delay,i_ce : std_logic; + SIGNAL i_linecpt,i_line : natural RANGE 0 TO 2**12-1; + SIGNAL i_delay : natural RANGE 0 TO 2**14-1; + + SIGNAL pwrite : std_logic; + SIGNAL paddress : unsigned(5 DOWNTO 0); + SIGNAL pdata : unsigned(31 DOWNTO 0); + TYPE enum_state IS (sIDLE,sW1,sW2,sW3,sW4,sW5,sW6); + SIGNAL state : enum_state; + SIGNAL tune_freq,tune_phase : unsigned(5 DOWNTO 0); + SIGNAL lltune_sync,lltune_sync2,lltune_sync3 : unsigned(15 DOWNTO 0); + SIGNAL mfrac,mfrac_mem,mfrac_ref,diff : unsigned(40 DOWNTO 0); + SIGNAL mul : unsigned(15 DOWNTO 0); + SIGNAL sign,sign_pre : std_logic; + SIGNAL expand : boolean; + SIGNAL up,modo,phm,dir : std_logic; + SIGNAL cpt : natural RANGE 0 TO 3; + SIGNAL col : natural RANGE 0 TO 15; + + SIGNAL icpt,ocpt,o2cpt,ssh,ofsize,ifsize : natural RANGE 0 TO 2**24-1; + SIGNAL ivss,ivss2,itog : std_logic; + SIGNAL ovss,ovss2,otog : std_logic; + SIGNAL sync,pulse,los,lop : std_logic; + SIGNAL osize,offset,osizep,offsetp : signed(23 DOWNTO 0); + SIGNAL logcpt : natural RANGE 0 TO 31; + SIGNAL udiff : integer RANGE -2**23 TO 2**23-1 :=0; + +BEGIN + + ---------------------------------------------------------------------------- + -- 4 lines delay to input + i_vss<=lltune(0); + i_de <=lltune(1); + i_ce <=lltune(5); + i_clk<=lltune(6); + + Delay:PROCESS(i_clk) IS + BEGIN + IF rising_edge(i_clk) THEN + IF i_ce='1' THEN + -- Measure input line time. + i_de2<=i_de; + + IF i_de='1' AND i_de2='0' THEN + i_linecpt<=0; + IF i_vss='1' THEN + i_line<=i_linecpt; + END IF; + ELSE + i_linecpt<=i_linecpt+1; + END IF; + + -- Delay 4 lines + i_vss2<=i_vss; + IF i_vss/=i_vss2 THEN + i_delay<=0; + ELSIF i_delay=i_line * 4 THEN + i_vss_delay<=i_vss; + ELSE + i_delay<=i_delay+1; + END IF; + END IF; + END IF; + END PROCESS Delay; + + ---------------------------------------------------------------------------- + -- Sample image sizes + Sampler:PROCESS(clk,reset_na) IS + BEGIN + IF reset_na='0' THEN +--pragma synthesis_off + otog<='0'; + itog<='0'; + ivss<='0'; + ivss2<='0'; + ovss<='0'; + ovss2<='0'; +--pragma synthesis_on + + ELSIF rising_edge(clk) THEN + -- Clock domain crossing + + ivss<=i_vss_delay; -- + ivss2<=ivss; + + ovss<=lltune(4); -- + ovss2<=ovss; + + otog<=otog XOR (ovss AND NOT ovss2); + + -- Measure output frame time + IF ovss='1' AND ovss2='0' AND otog='1' THEN + ocpt<=0; + osizep<=to_signed(ocpt,24); + ELSE + ocpt<=ocpt+1; + END IF; + IF ovss='0' AND ovss2='1' AND otog='0' THEN + o2cpt<=0; + ELSE + o2cpt<=o2cpt+1; + END IF; + + -- Measure output image time + IF ovss='0' AND ovss2='1' AND otog='0' THEN + ofsize<=ocpt; + END IF; + + itog<=itog XOR (ivss AND NOT ivss2); + + -- Measure input frame time + IF ivss='1' AND ivss2='0' AND itog='1' THEN + icpt<=0; + osize<=osizep; + udiff<=integer(to_integer(osizep)) - integer(icpt); + sync<='1'; + ELSE + icpt<=icpt+1; + sync<='0'; + END IF; + + -- Measure input image time + IF ivss='0' AND ivss2='1' AND itog='0' THEN + ifsize<=icpt; + END IF; + + expand<=(ofsize>=ifsize); + -- IN | ######### | EXPAND = 1 + -- OUT | ############# | + + -- IN | ######### | EXPAND = 0 + -- OUT | ###### | + + IF expand THEN + IF ivss='1' AND ivss2='0' AND itog='1' THEN + offset<=to_signed(ocpt,24); + END IF; + ELSE + IF ivss='0' AND ivss2='1' AND itog='0' THEN + offset<=to_signed(o2cpt,24); + END IF; + END IF; + + -------------------------------------------- + pulse<='0'; + IF sync='1' THEN + logcpt<=0; + ssh<=to_integer(osize); + los<='0'; + lop<='0'; + + ELSIF logcpt<24 THEN + -- Frequency difference + IF udiff>0 AND ssh=osize/2 AND ssh<(osize-offset) AND lop='0' THEN + tune_phase<='1' & to_unsigned(logcpt,5); + lop<='1'; + END IF; + ssh<=ssh/2; + logcpt<=logcpt+1; + + ELSIF logcpt=24 THEN + pulse<='1'; + ssh<=ssh/2; + logcpt<=logcpt+1; + END IF; + + END IF; + END PROCESS Sampler; + + ---------------------------------------------------------------------------- + -- 000010 : Start reg "Write either 0 or 1 to start fractional PLL reconf. + -- 000100 : M counter + -- 000111 : M counter Fractional Value K + + Comb:PROCESS(i_write,i_address, + i_writedata,pwrite,paddress,pdata) IS + BEGIN + IF i_write='1' THEN + o_write <=i_write; + o_address <=i_address; + o_writedata <=i_writedata; + ELSE + o_write <=pwrite; + o_address <=paddress; + o_writedata<=pdata; + END IF; + END PROCESS Comb; + + i_waitrequest<=o_waitrequest WHEN state=sIDLE ELSE '0'; + + ---------------------------------------------------------------------------- + Schmurtz:PROCESS(clk,reset_na) IS + VARIABLE off_v,ofp_v : natural RANGE 0 TO 63; + VARIABLE diff_v : unsigned(40 DOWNTO 0); + VARIABLE mulco : unsigned(15 DOWNTO 0); + VARIABLE up_v,sign_v : std_logic; + BEGIN + IF reset_na='0' THEN + modo<='0'; + state<=sIDLE; + ELSIF rising_edge(clk) THEN + ------------------------------------------------------ + -- Snoop accesses to PLL reconfiguration + IF i_address="000100" AND i_write='1' THEN + mfrac (40 DOWNTO 32)<=('0' & i_writedata(15 DOWNTO 8)) + + ('0' & i_writedata(7 DOWNTO 0)); + mfrac_ref(40 DOWNTO 32)<=('0' & i_writedata(15 DOWNTO 8)) + + ('0' & i_writedata(7 DOWNTO 0)); + mfrac_mem(40 DOWNTO 32)<=('0' & i_writedata(15 DOWNTO 8)) + + ('0' & i_writedata(7 DOWNTO 0)); + mul<=i_writedata(15 DOWNTO 0); + modo<='1'; + END IF; + + IF i_address="000111" AND i_write='1' THEN + mfrac (31 DOWNTO 0)<=i_writedata; + mfrac_ref(31 DOWNTO 0)<=i_writedata; + mfrac_mem(31 DOWNTO 0)<=i_writedata; + modo<='1'; + END IF; + + ------------------------------------------------------ + -- Tuning + off_v:=to_integer('0' & tune_freq(4 DOWNTO 0)); + ofp_v:=to_integer('0' & tune_phase(4 DOWNTO 0)); + --IF off_v<8 THEN off_v:=8; END IF; + --IF ofp_v<7 THEN ofp_v:=7; END IF; + IF off_v<4 THEN off_v:=4; END IF; + IF ofp_v<4 THEN ofp_v:=4; END IF; + + IF off_v>=18 AND ofp_v>=18 THEN + locked<=llena; + ELSE + locked<='0'; + END IF; + + up_v:='0'; + IF pulse='1' THEN + cpt<=(cpt+1) MOD 4; + IF llena='0' THEN + -- Recover original freq when disabling low lag mode + cpt<=0; + col<=0; + IF modo='1' THEN + mfrac<=mfrac_mem; + mfrac_ref<=mfrac_mem; + up<='1'; + modo<='0'; + END IF; + + ELSIF phm='0' AND cpt=0 THEN + -- Frequency adjust + sign_v:=tune_freq(5); + IF col<10 THEN col<=col+1; END IF; + IF off_v>=16 AND col>=10 THEN + phm<='1'; + col<=0; + ELSE + off_v:=off_v+1; + IF off_v>17 THEN + off_v:=off_v + 3; + END IF; + up_v:='1'; + up<='1'; + END IF; + + ELSIF cpt=0 THEN + -- Phase adjust + sign_v:=NOT tune_phase(5); + col<=col+1; + IF col>=10 THEN + phm<='0'; + up_v:='1'; + off_v:=31; + col<=0; + ELSE + off_v:=ofp_v + 1; + IF ofp_v>7 THEN + off_v:=off_v + 1; + END IF; + IF ofp_v>14 THEN + off_v:=off_v + 2; + END IF; + IF ofp_v>17 THEN + off_v:=off_v + 3; + END IF; + up_v:='1'; + END IF; + up<='1'; + END IF; + END IF; + + diff_v:=shift_right(mfrac_ref,off_v); + IF sign_v='0' THEN + diff_v:=mfrac_ref + diff_v; + ELSE + diff_v:=mfrac_ref - diff_v; + END IF; + + IF up_v='1' THEN + mfrac<=diff_v; + END IF; + + IF up_v='1' AND phm='0' THEN + mfrac_ref<=diff_v; + END IF; + + ------------------------------------------------------ + -- Update PLL registers + mulco:=mfrac(40 DOWNTO 33) & (mfrac(40 DOWNTO 33) + ('0' & mfrac(32))); + + CASE state IS + WHEN sIDLE => + pwrite<='0'; + IF up='1' THEN + up<='0'; + IF mulco/=mul THEN + state<=sW1; + ELSE + state<=sW3; + END IF; + END IF; + + WHEN sW1 => -- Change M multiplier + mul<=mulco; + pdata<=x"0000" & mulco; + paddress<="000100"; + pwrite<='1'; + state<=sW2; + + WHEN sW2 => + IF pwrite='1' AND o_waitrequest='0' THEN + state<=sW3; + pwrite<='0'; + END IF; + + WHEN sW3 => -- Change M fractional value + pdata<=mfrac(31 DOWNTO 0); + paddress<="000111"; + pwrite<='1'; + state<=sW4; + + WHEN sW4 => + IF pwrite='1' AND o_waitrequest='0' THEN + state<=sW5; + pwrite<='0'; + END IF; + + WHEN sW5 => + pdata<=x"0000_0001"; + paddress<="000010"; + pwrite<='1'; + state<=sW6; + + WHEN sW6 => + IF pwrite='1' AND o_waitrequest='0' THEN + pwrite<='0'; + state<=sIDLE; + END IF; + END CASE; + + END IF; + END PROCESS Schmurtz; + + ---------------------------------------------------------------------------- + +END ARCHITECTURE rtl; + diff --git a/sys/pll_q13.qip b/sys/pll_q13.qip new file mode 100644 index 0000000..13a7ed4 --- /dev/null +++ b/sys/pll_q13.qip @@ -0,0 +1,6 @@ +set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll.13.qip ] +set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll_hdmi.13.qip ] +set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll_audio.13.qip ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) pll_cfg.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) pll_cfg/altera_pll_reconfig_core.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) pll_cfg/altera_pll_reconfig_top.v ] diff --git a/sys/pll_q17.qip b/sys/pll_q17.qip new file mode 100644 index 0000000..85cc84b --- /dev/null +++ b/sys/pll_q17.qip @@ -0,0 +1,4 @@ +set_global_assignment -name QIP_FILE rtl/pll.qip +set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll_hdmi.qip ] +set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll_audio.qip ] +set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll_cfg.qip ] diff --git a/sys/scandoubler.v b/sys/scandoubler.v new file mode 100644 index 0000000..81e7c3f --- /dev/null +++ b/sys/scandoubler.v @@ -0,0 +1,211 @@ +// +// scandoubler.v +// +// Copyright (c) 2015 Till Harbaum +// Copyright (c) 2017-2021 Alexey Melnikov +// +// This source file is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This source file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// TODO: Delay vsync one line + +module scandoubler #(parameter LENGTH, parameter HALF_DEPTH) +( + // system interface + input clk_vid, + input hq2x, + + // shifter video interface + input ce_pix, + input hs_in, + input vs_in, + input hb_in, + input vb_in, + input [DWIDTH:0] r_in, + input [DWIDTH:0] g_in, + input [DWIDTH:0] b_in, + + // output interface + output ce_pix_out, + output reg hs_out, + output vs_out, + output hb_out, + output vb_out, + output [DWIDTH:0] r_out, + output [DWIDTH:0] g_out, + output [DWIDTH:0] b_out +); + +localparam DWIDTH = HALF_DEPTH ? 3 : 7; + +reg [7:0] pix_len = 0; +wire [7:0] pl = pix_len + 1'b1; + +reg [7:0] pix_in_cnt = 0; +wire [7:0] pc_in = pix_in_cnt + 1'b1; +reg [7:0] pixsz, pixsz2, pixsz4 = 0; + +reg ce_x4i, ce_x1i; +always @(posedge clk_vid) begin + reg old_ce, valid, hs; + + if(~&pix_len) pix_len <= pl; + if(~&pix_in_cnt) pix_in_cnt <= pc_in; + + ce_x4i <= 0; + ce_x1i <= 0; + + // use such odd comparison to place ce_x4 evenly if master clock isn't multiple of 4. + if((pc_in == pixsz4) || (pc_in == pixsz2) || (pc_in == (pixsz2+pixsz4))) ce_x4i <= 1; + + old_ce <= ce_pix; + if(~old_ce & ce_pix) begin + if(valid & ~hb_in & ~vb_in) begin + pixsz <= pl; + pixsz2 <= {1'b0, pl[7:1]}; + pixsz4 <= {2'b00, pl[7:2]}; + end + pix_len <= 0; + valid <= 1; + end + + hs <= hs_in; + if((~hs & hs_in) || (pc_in >= pixsz)) begin + ce_x4i <= 1; + ce_x1i <= 1; + pix_in_cnt <= 0; + end + + if(hb_in | vb_in) valid <= 0; +end + +reg req_line_reset; +reg [DWIDTH:0] r_d, g_d, b_d; +always @(posedge clk_vid) begin + if(ce_x1i) begin + req_line_reset <= hb_in; + r_d <= r_in; + g_d <= g_in; + b_d <= b_in; + end +end + +Hq2x #(.LENGTH(LENGTH), .HALF_DEPTH(HALF_DEPTH)) Hq2x +( + .clk(clk_vid), + + .ce_in(ce_x4i), + .inputpixel({b_d,g_d,r_d}), + .disable_hq2x(~hq2x), + .reset_frame(vb_in), + .reset_line(req_line_reset), + + .ce_out(ce_x4o), + .read_y(sd_line), + .hblank(hbo[0]&hbo[8]), + .outpixel({b_out,g_out,r_out}) +); + +reg [7:0] pix_out_cnt = 0; +wire [7:0] pc_out = pix_out_cnt + 1'b1; + +reg ce_x4o, ce_x2o; +always @(posedge clk_vid) begin + reg hs; + + if(~&pix_out_cnt) pix_out_cnt <= pc_out; + + ce_x4o <= 0; + ce_x2o <= 0; + + // use such odd comparison to place ce_x4 evenly if master clock isn't multiple of 4. + if((pc_out == pixsz4) || (pc_out == pixsz2) || (pc_out == (pixsz2+pixsz4))) ce_x4o <= 1; + if( pc_out == pixsz2) ce_x2o <= 1; + + hs <= hs_out; + if((~hs & hs_out) || (pc_out >= pixsz)) begin + ce_x2o <= 1; + ce_x4o <= 1; + pix_out_cnt <= 0; + end +end + +reg [1:0] sd_line; +reg [3:0] vbo; +reg [3:0] vso; +reg [8:0] hbo; +always @(posedge clk_vid) begin + + reg [31:0] hcnt; + reg [30:0] sd_hcnt; + reg [30:0] hs_start, hs_end; + reg [30:0] hde_start, hde_end; + + reg hs, hb; + + if(ce_x4o) begin + hbo[8:1] <= hbo[7:0]; + end + + // output counter synchronous to input and at twice the rate + sd_hcnt <= sd_hcnt + 1'd1; + if(sd_hcnt == hde_start) begin + sd_hcnt <= 0; + vbo[3:1] <= vbo[2:0]; + end + + if(sd_hcnt == hs_end) begin + sd_line <= sd_line + 1'd1; + if(&vbo[3:2]) sd_line <= 1; + vso[3:1] <= vso[2:0]; + end + + if(sd_hcnt == hde_start)hbo[0] <= 0; + if(sd_hcnt == hde_end) hbo[0] <= 1; + + // replicate horizontal sync at twice the speed + if(sd_hcnt == hs_end) hs_out <= 0; + if(sd_hcnt == hs_start) hs_out <= 1; + + hs <= hs_in; + hb <= hb_in; + + hcnt <= hcnt + 1'd1; + if(hb && !hb_in) begin + hde_start <= hcnt[31:1]; + hbo[0] <= 0; + hcnt <= 0; + sd_hcnt <= 0; + vbo <= {vbo[2:0],vb_in}; + end + + if(!hb && hb_in) hde_end <= hcnt[31:1]; + + // falling edge of hsync indicates start of line + if(hs && !hs_in) begin + hs_end <= hcnt[31:1]; + vso[0] <= vs_in; + end + + // save position of rising edge + if(!hs && hs_in) hs_start <= hcnt[31:1]; +end + +assign vs_out = vso[3]; +assign ce_pix_out = hq2x ? ce_x4o : ce_x2o; + +//Compensate picture shift after HQ2x +assign vb_out = vbo[3]; +assign hb_out = hbo[6]; + +endmodule diff --git a/sys/scanlines.v b/sys/scanlines.v new file mode 100644 index 0000000..43f890f --- /dev/null +++ b/sys/scanlines.v @@ -0,0 +1,68 @@ +module scanlines #(parameter v2=0) +( + input clk, + + input [1:0] scanlines, + input [23:0] din, + input hs_in,vs_in, + input de_in,ce_in, + + output reg [23:0] dout, + output reg hs_out,vs_out, + output reg de_out,ce_out +); + +reg [1:0] scanline; +always @(posedge clk) begin + reg old_hs, old_vs; + + old_hs <= hs_in; + old_vs <= vs_in; + + if(old_hs && ~hs_in) begin + if(v2) begin + scanline <= scanline + 1'd1; + if (scanline == scanlines) scanline <= 0; + end + else scanline <= scanline ^ scanlines; + end + if(old_vs && ~vs_in) scanline <= 0; +end + +wire [7:0] r,g,b; +assign {r,g,b} = din; + +reg [23:0] d; +always @(*) begin + case(scanline) + 1: // reduce 25% = 1/2 + 1/4 + d = {{1'b0, r[7:1]} + {2'b00, r[7:2]}, + {1'b0, g[7:1]} + {2'b00, g[7:2]}, + {1'b0, b[7:1]} + {2'b00, b[7:2]}}; + + 2: // reduce 50% = 1/2 + d = {{1'b0, r[7:1]}, + {1'b0, g[7:1]}, + {1'b0, b[7:1]}}; + + 3: // reduce 75% = 1/4 + d = {{2'b00, r[7:2]}, + {2'b00, g[7:2]}, + {2'b00, b[7:2]}}; + + default: d = {r,g,b}; + endcase +end + +always @(posedge clk) begin + reg [23:0] dout1, dout2; + reg de1,de2,vs1,vs2,hs1,hs2,ce1,ce2; + + dout <= dout2; dout2 <= dout1; dout1 <= d; + vs_out <= vs2; vs2 <= vs1; vs1 <= vs_in; + hs_out <= hs2; hs2 <= hs1; hs1 <= hs_in; + de_out <= de2; de2 <= de1; de1 <= de_in; + ce_out <= ce2; ce2 <= ce1; ce1 <= ce_in; +end + +endmodule diff --git a/sys/sd_card.sv b/sys/sd_card.sv new file mode 100644 index 0000000..8cb0560 --- /dev/null +++ b/sys/sd_card.sv @@ -0,0 +1,463 @@ +// +// sd_card.v +// +// Copyright (c) 2014 Till Harbaum +// Copyright (c) 2015-2018 Sorgelig +// +// This source file is free software: you can redistribute it and/or modify +// it under the terms of the Lesser GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This source file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// http://elm-chan.org/docs/mmc/mmc_e.html +// +///////////////////////////////////////////////////////////////////////// + +// +// Made module syncrhronous. Total code refactoring. (Sorgelig) +// clk_spi must be at least 2 x sck for proper work. + +module sd_card #(parameter WIDE = 0, OCTAL=0) +( + input clk_sys, + input reset, + + input sdhc, + input img_mounted, + input [63:0] img_size, + + output reg [31:0] sd_lba, + output reg sd_rd, + output reg sd_wr, + input sd_ack, + + input [AW:0] sd_buff_addr, + input [DW:0] sd_buff_dout, + output [DW:0] sd_buff_din, + input sd_buff_wr, + + // SPI interface + input clk_spi, + + input ss, + input sck, + input [SW:0] mosi, + output reg [SW:0] miso +); + +localparam AW = WIDE ? 7 : 8; +localparam DW = WIDE ? 15 : 7; +localparam SZ = OCTAL ? 8 : 1; +localparam SW = SZ-1; + +wire [7:0] DATA_TOKEN_CMD25 = 8'hfc; +wire [7:0] STOP_TRAN = 8'hfd; +wire [7:0] DATA_TOKEN = 8'hfe; +wire [7:0] WRITE_DATA_RESPONSE = 8'h05; + +// number of bytes to wait after a command before sending the reply +localparam NCR = 5+3; // 5 bytes are required (command length) + +localparam RD_STATE_IDLE = 0; +localparam RD_STATE_START = 1; +localparam RD_STATE_WAIT_IO = 2; +localparam RD_STATE_SEND_TOKEN = 3; +localparam RD_STATE_SEND_DATA = 4; +localparam RD_STATE_WAIT_M = 5; + +localparam WR_STATE_IDLE = 0; +localparam WR_STATE_EXP_DTOKEN = 1; +localparam WR_STATE_RECV_DATA = 2; +localparam WR_STATE_RECV_CRC0 = 3; +localparam WR_STATE_RECV_CRC1 = 4; +localparam WR_STATE_SEND_DRESP = 5; +localparam WR_STATE_BUSY = 6; + +localparam PREF_STATE_IDLE = 0; +localparam PREF_STATE_RD = 1; +localparam PREF_STATE_FINISH = 2; + +altsyncram sdbuf +( + .clock0 (clk_sys), + .address_a ({sd_buf,sd_buff_addr}), + .data_a (sd_buff_dout), + .wren_a (sd_ack & sd_buff_wr), + .q_a (sd_buff_din), + + .clock1 (clk_spi), + .address_b ({spi_buf,buffer_ptr}), + .data_b (buffer_din), + .wren_b (buffer_wr), + .q_b (buffer_dout), + + .aclr0(1'b0), + .aclr1(1'b0), + .addressstall_a(1'b0), + .addressstall_b(1'b0), + .byteena_a(1'b1), + .byteena_b(1'b1), + .clocken0(1'b1), + .clocken1(1'b1), + .clocken2(1'b1), + .clocken3(1'b1), + .eccstatus(), + .rden_a(1'b1), + .rden_b(1'b1) +); +defparam + sdbuf.numwords_a = 1<<(AW+3), + sdbuf.widthad_a = AW+3, + sdbuf.width_a = DW+1, + sdbuf.numwords_b = 2048, + sdbuf.widthad_b = 11, + sdbuf.width_b = 8, + sdbuf.address_reg_b = "CLOCK1", + sdbuf.clock_enable_input_a = "BYPASS", + sdbuf.clock_enable_input_b = "BYPASS", + sdbuf.clock_enable_output_a = "BYPASS", + sdbuf.clock_enable_output_b = "BYPASS", + sdbuf.indata_reg_b = "CLOCK1", + sdbuf.intended_device_family = "Cyclone V", + sdbuf.lpm_type = "altsyncram", + sdbuf.operation_mode = "BIDIR_DUAL_PORT", + sdbuf.outdata_aclr_a = "NONE", + sdbuf.outdata_aclr_b = "NONE", + sdbuf.outdata_reg_a = "UNREGISTERED", + sdbuf.outdata_reg_b = "UNREGISTERED", + sdbuf.power_up_uninitialized = "FALSE", + sdbuf.read_during_write_mode_port_a = "NEW_DATA_NO_NBE_READ", + sdbuf.read_during_write_mode_port_b = "NEW_DATA_NO_NBE_READ", + sdbuf.width_byteena_a = 1, + sdbuf.width_byteena_b = 1, + sdbuf.wrcontrol_wraddress_reg_b = "CLOCK1"; + +reg [26:0] csd_size; +reg csd_sdhc; +always @(posedge clk_sys) begin + if (img_mounted) begin + csd_sdhc <= sdhc; + if (sdhc) begin + csd_size[0] <= 0; + csd_size[22:1] <= img_size[40:19]; // in 512K units + csd_size[26:23] <= 0; + end + else begin + csd_size[2:0] <= 7; // C_SIZE_MULT + csd_size[14:3] <= 12'b101101101101; + csd_size[26:15] <= img_size[29:18]; // in 256K units ((2**(C_SIZE_MULT+2))*512) + end + end +end + +wire [127:0] CSD = {1'b0,csd_sdhc,6'h00,8'h0e,8'h00,8'h32,8'h5b,8'h59,6'h00,csd_size,7'h7f,8'h80,8'h0a,8'h40,8'h40,8'hf1}; +wire [127:0] CID = {8'hcd,8'hc7,8'h00,8'h93,8'h6f,8'h2f,8'h73,8'h00,8'h00,8'h44,8'h32,8'h38,8'h34,8'h00,8'h00,8'h3e}; + +reg [8:0] buffer_ptr; +reg [7:0] buffer_din; +wire [7:0] buffer_dout; +reg buffer_wr; + +reg [1:0] sd_buf, spi_buf; + +reg [6:0] sbuf; +reg [2:0] bit_cnt; + +wire last_bit = &bit_cnt || OCTAL; +wire [7:0] ibuf = OCTAL ? mosi : {sbuf,mosi[0]}; + +always @(posedge clk_spi) begin + reg [2:0] read_state; + reg [2:0] write_state; + reg [1:0] pref_state; + reg [5:0] cmd; + reg cmd55; + reg [39:0] reply; + reg [3:0] byte_cnt; + reg old_sck; + reg [2:0] ack; + reg [2:0] wait_m_cnt; + reg [31:0] arg; + + ack[1:0] <= {ack[0],sd_ack}; + if(ack[1] == ack[0]) ack[2] <= ack[1]; + + if(~ack[2] & ack[1]) {sd_rd,sd_wr} <= 0; + if( ack[2] & ~ack[1]) begin + sd_buf <= sd_buf + 1'd1; + sd_lba <= sd_lba + 1; + end + + buffer_wr <= 0; + + if(reset) begin + bit_cnt <= 0; + byte_cnt <= '1; + miso <= '1; + cmd <= 0; + sd_wr <= 0; + sd_rd <= 0; + read_state <= RD_STATE_IDLE; + write_state <= WR_STATE_IDLE; + pref_state <= PREF_STATE_IDLE; + end + else begin + + if(buffer_wr) begin + if(~&buffer_ptr) buffer_ptr <= buffer_ptr + 1'd1; + else begin + spi_buf <= spi_buf + 1'd1; + sd_wr <= 1; + end + end + + case(pref_state) + PREF_STATE_IDLE: + if(((sd_buf - spi_buf) <= 1) && (read_state != RD_STATE_IDLE) && (cmd == 17 || cmd == 18)) begin + sd_rd <= 1; + pref_state <= PREF_STATE_RD; + end + + PREF_STATE_RD: + if(read_state == RD_STATE_IDLE) begin + pref_state <= PREF_STATE_IDLE; + end + else if(ack[2] & ~ack[1]) begin + pref_state <= (cmd == 18) ? PREF_STATE_IDLE : PREF_STATE_FINISH; + end + + PREF_STATE_FINISH: + if(read_state == RD_STATE_IDLE) begin + pref_state <= PREF_STATE_IDLE; + end + endcase + + old_sck <= sck; + if(ss) begin + bit_cnt <= 0; + byte_cnt <= '1; + miso <= '1; + end + else if(old_sck & ~sck) begin + miso <= '1; // default: send 1's (busy/wait) + if(byte_cnt >= NCR) {miso,reply} <= {reply, {SZ{1'b1}}}; + + // ---------- read state machine processing ------------- + case(read_state) + RD_STATE_IDLE: ; + + RD_STATE_START: begin + if(byte_cnt == NCR && last_bit) read_state <= (cmd == 9 || cmd == 10) ? RD_STATE_SEND_TOKEN : RD_STATE_WAIT_IO; + end + + // waiting for io controller to return data + RD_STATE_WAIT_IO: begin + if(sd_buf != spi_buf && last_bit) read_state <= RD_STATE_SEND_TOKEN; + end + + // send data token + RD_STATE_SEND_TOKEN: begin + miso <= DATA_TOKEN[~bit_cnt -:SZ]; + if(last_bit) begin + read_state <= RD_STATE_SEND_DATA; // next: send data + buffer_ptr <= 0; + end + end + + // send data + RD_STATE_SEND_DATA: begin + + miso <= (cmd == 9) ? CSD[{buffer_ptr[3:0],~bit_cnt} -:SZ] : (cmd == 10) ? CID[{buffer_ptr[3:0],~bit_cnt} -:SZ] : buffer_dout[~bit_cnt -:SZ]; + + if(last_bit) begin + + // sent 512 sector data bytes? + if(cmd == 17 && &buffer_ptr) read_state <= RD_STATE_IDLE; + else if(cmd == 18 && &buffer_ptr) begin + read_state <= RD_STATE_WAIT_M; + wait_m_cnt <= 0; + end + + // sent 16 cid/csd data bytes? + else if((cmd == 9 || cmd == 10) && &buffer_ptr[3:0]) read_state <= RD_STATE_IDLE; + + // not done yet -> trigger read of next data byte + else buffer_ptr <= buffer_ptr + 1'd1; + end + end + + RD_STATE_WAIT_M: begin + if(last_bit) begin + wait_m_cnt <= wait_m_cnt + 1'd1; + if(&wait_m_cnt) begin + spi_buf <= spi_buf + 1'd1; + read_state <= RD_STATE_WAIT_IO; + end + end + end + endcase + + // ------------------ write support ---------------------- + // send write data response + if(write_state == WR_STATE_SEND_DRESP) miso <= WRITE_DATA_RESPONSE[~bit_cnt -:SZ]; + + // busy after write until the io controller sends ack + if(write_state == WR_STATE_BUSY) miso <= 0; + end + else if(~old_sck & sck) begin + + sbuf[6:0] <= {sbuf[5:0],mosi[0]}; + bit_cnt <= bit_cnt + SZ[2:0]; + + if(last_bit) begin + // finished reading one byte + // byte counter runs against 15 byte boundary + if(~&byte_cnt) byte_cnt <= byte_cnt + 1'd1; + + // byte_cnt > 6 -> complete command received + // first byte of valid command is 01xxxxxx + // don't accept new commands once a write or read command has been accepted + if(byte_cnt > 5 && + ((write_state == WR_STATE_IDLE && read_state == RD_STATE_IDLE && ibuf[7:6] == 1) || + (read_state != RD_STATE_IDLE && ibuf == 8'h4c))) begin + byte_cnt <= 0; + cmd <= ibuf[5:0]; + cmd55 <= (cmd == 55); // set cmd55 flag if previous command was 55 + if(ibuf[5:0] == 12) read_state <= RD_STATE_IDLE; + end + + // parse additional command bytes + if(byte_cnt == 0) arg[31:24] <= ibuf; + if(byte_cnt == 1) arg[23:16] <= ibuf; + if(byte_cnt == 2) arg[15:8] <= ibuf; + if(byte_cnt == 3) arg[7:0] <= ibuf; + + // last byte (crc) received, evaluate + if(byte_cnt == 4) begin + + // default: + reply <= 40'h04FFFFFFFF; // illegal command + + case(cmd) + // CMD0: GO_IDLE_STATE + 0: reply[39:32] <= 1; // ok, busy + + // CMD1: SEND_OP_COND + 1: reply[39:32] <= 0; + + // CMD8: SEND_IF_COND (V2 only) + 8: reply <= 40'h01000001AA; // ok, busy + + // CMD9: SEND_CSD + 9, + // CMD10: SEND_CID + 10: begin + reply[39:32] <= 0; + read_state <= RD_STATE_START; + end + + // CMD12: STOP_TRANSMISSION + 12: reply[39:32] <= 0; + + // CMD13: SEND_STATUS + 13: reply[39:24] <= 16'h0000; + + // CMD16: SET_BLOCKLEN + 16: reply[39:32] <= (arg == 512) ? 8'h00 : 8'h40; // we only support a block size of 512 + + // CMD17: READ_SINGLE_BLOCK + 17, + // CMD18: READ_MULTIPLE + 18: begin + reply[39:32] <= 0; + read_state <= RD_STATE_START; + spi_buf <= 0; + sd_buf <= 0; + sd_lba <= csd_sdhc ? arg : {9'd0, arg[31:9]}; + end + + // ACMD23: SET_WR_BLK_ERASE_COUNT + 23: reply[39:32] <= 0; + + // CMD24: WRITE_BLOCK + 24, + // CMD25: WRITE_MULTIPLE + 25: begin + reply[39:32] <= 0; + write_state <= WR_STATE_EXP_DTOKEN; // expect data token + spi_buf <= 0; + sd_buf <= 0; + sd_lba <= csd_sdhc ? arg : {9'd0, arg[31:9]}; + end + + // ACMD41: APP_SEND_OP_COND + 41: if(cmd55) reply[39:32] <= 0; // ok, not busy + + // CMD55: APP_COND + 55: reply[39:32] <= 1; // ok, busy + + // CMD58: READ_OCR + 58: reply <= { 8'h00, 1'b1, csd_sdhc, 30'd0 }; // bit 30 = 1 -> high capacity card + + // CMD59: CRC_ON_OFF + 59: reply[39:32] <= 0; + endcase + end + + // ---------- handle write ----------- + case(write_state) + // do nothing in idle state + WR_STATE_IDLE: ; + + // waiting for data token + WR_STATE_EXP_DTOKEN: begin + buffer_ptr <= 0; + if(cmd == 24) begin + if(ibuf == DATA_TOKEN) write_state <= WR_STATE_RECV_DATA; + end + else begin + if(ibuf == DATA_TOKEN_CMD25) write_state <= WR_STATE_RECV_DATA; + if(ibuf == STOP_TRAN) write_state <= WR_STATE_IDLE; + end + end + + // transfer 512 bytes + WR_STATE_RECV_DATA: begin + // push one byte into local buffer + buffer_wr <= 1; + buffer_din <= ibuf; + + // all bytes written? + if(&buffer_ptr) write_state <= WR_STATE_RECV_CRC0; + end + + // transfer 1st crc byte + WR_STATE_RECV_CRC0: + write_state <= WR_STATE_RECV_CRC1; + + // transfer 2nd crc byte + WR_STATE_RECV_CRC1: + write_state <= WR_STATE_SEND_DRESP; + + // send data response + WR_STATE_SEND_DRESP: + write_state <= WR_STATE_BUSY; + + // wait for io controller to accept data + WR_STATE_BUSY: + if(spi_buf == sd_buf) write_state <= (cmd == 25) ? WR_STATE_EXP_DTOKEN : WR_STATE_IDLE; + endcase + end + end + end +end + +endmodule diff --git a/sys/shadowmask.sv b/sys/shadowmask.sv new file mode 100644 index 0000000..572679c --- /dev/null +++ b/sys/shadowmask.sv @@ -0,0 +1,136 @@ +module shadowmask +( + input clk, + input clk_sys, + + input cmd_wr, + input [15:0] cmd_in, + + input [23:0] din, + input hs_in,vs_in, + input de_in, + input brd_in, + input enable, + + output reg [23:0] dout, + output reg hs_out,vs_out, + output reg de_out +); + + +reg [4:0] hmax; +reg [4:0] vmax; +reg [7:0] mask_idx; +reg mask_2x; +reg mask_rotate; +reg mask_enable; +reg [10:0] mask_lut[256]; + +always @(posedge clk) begin + reg [4:0] hcount; + reg [4:0] vcount; + reg [3:0] hindex; + reg [3:0] vindex; + reg [4:0] hmax2; + reg [4:0] vmax2; + reg [11:0] pcnt,pde; + reg old_hs, old_vs, old_brd; + reg next_v; + + old_hs <= hs_in; + old_vs <= vs_in; + old_brd<= brd_in; + + // hcount and vcount counts pixel rows and columns + // hindex and vindex half the value of the counters for double size patterns + // hindex2, vindex2 swap the h and v counters for drawing rotated masks + hindex <= mask_2x ? hcount[4:1] : hcount[3:0]; + vindex <= mask_2x ? vcount[4:1] : vcount[3:0]; + mask_idx <= mask_rotate ? {hindex,vindex} : {vindex,hindex}; + + // hmax and vmax store these sizes + // hmax2 and vmax2 swap the values to handle rotation + hmax2 <= ((mask_rotate ? vmax : hmax) << mask_2x) | mask_2x; + vmax2 <= ((mask_rotate ? hmax : vmax) << mask_2x) | mask_2x; + + pcnt <= pcnt+1'd1; + if(old_brd && ~brd_in) pde <= pcnt-4'd3; + + hcount <= hcount+1'b1; + if(hcount == hmax2 || pde == pcnt) hcount <= 0; + + if(~old_brd && brd_in) next_v <= 1; + if(old_vs && ~vs_in) vcount <= 0; + if(old_hs && ~hs_in) begin + vcount <= vcount + next_v; + next_v <= 0; + pcnt <= 0; + if (vcount == vmax2) vcount <= 0; + end +end + +reg [4:0] r_mul, g_mul, b_mul; // 1.4 fixed point multipliers +always @(posedge clk) begin + reg [10:0] lut; + + lut <= mask_lut[mask_idx]; + + r_mul <= 5'b10000; g_mul <= 5'b10000; b_mul <= 5'b10000; // default 100% to all channels + if (mask_enable) begin + r_mul <= lut[10] ? {1'b1,lut[7:4]} : {1'b0,lut[3:0]}; + g_mul <= lut[9] ? {1'b1,lut[7:4]} : {1'b0,lut[3:0]}; + b_mul <= lut[8] ? {1'b1,lut[7:4]} : {1'b0,lut[3:0]}; + end +end + +always @(posedge clk) begin + reg [11:0] vid; + reg [7:0] r1, g1, b1; + reg [7:0] r2, g2, b2; + reg [7:0] r3_x, g3_x, b3_x; // 6.25% + 12.5% + reg [8:0] r3_y, g3_y, b3_y; // 25% + 50% + 100% + reg [8:0] r4, g4, b4; + + // C1 - data input + {r1,g1,b1} <= din; + vid <= {vid[8:0],vs_in, hs_in, de_in}; + + // C2 - relax timings + {r2,g2,b2} <= {r1,g1,b1}; + + // C3 - perform multiplications + r3_x <= ({4{r_mul[0]}} & r2[7:4]) + ({8{r_mul[1]}} & r2[7:3]); + r3_y <= ({6{r_mul[2]}} & r2[7:2]) + ({7{r_mul[3]}} & r2[7:1]) + ({9{r_mul[4]}} & r2[7:0]); + g3_x <= ({4{g_mul[0]}} & g2[7:4]) + ({8{g_mul[1]}} & g2[7:3]); + g3_y <= ({6{g_mul[2]}} & g2[7:2]) + ({7{g_mul[3]}} & g2[7:1]) + ({9{g_mul[4]}} & g2[7:0]); + b3_x <= ({4{b_mul[0]}} & b2[7:4]) + ({8{b_mul[1]}} & b2[7:3]); + b3_y <= ({6{b_mul[2]}} & b2[7:2]) + ({7{b_mul[3]}} & b2[7:1]) + ({9{b_mul[4]}} & b2[7:0]); + + // C4 - combine results + r4 <= r3_x + r3_y; + g4 <= g3_x + g3_y; + b4 <= b3_x + b3_y; + + // C5 - clamp and output + dout <= {{8{r4[8]}} | r4[7:0], {8{g4[8]}} | g4[7:0], {8{b4[8]}} | b4[7:0]}; + {vs_out,hs_out,de_out} <= vid[11:9]; +end + +// clock in mask commands +always @(posedge clk_sys) begin + reg m_enable; + reg [7:0] idx; + + if (cmd_wr) begin + case(cmd_in[15:13]) + 3'b000: begin {m_enable, mask_rotate, mask_2x} <= cmd_in[3:1]; idx <= 0; end + 3'b001: vmax <= cmd_in[3:0]; + 3'b010: hmax <= cmd_in[3:0]; + 3'b011: begin mask_lut[idx] <= cmd_in[10:0]; idx <= idx + 1'd1; end + endcase + end + + mask_enable <= m_enable & enable; +end + +endmodule diff --git a/sys/sigma_delta_dac.v b/sys/sigma_delta_dac.v new file mode 100644 index 0000000..d0d6be0 --- /dev/null +++ b/sys/sigma_delta_dac.v @@ -0,0 +1,33 @@ +// +// PWM DAC +// +// MSBI is the highest bit number. NOT amount of bits! +// +module sigma_delta_dac #(parameter MSBI=7, parameter INV=1'b1) +( + output reg DACout, //Average Output feeding analog lowpass + input [MSBI:0] DACin, //DAC input (excess 2**MSBI) + input CLK, + input RESET +); + +reg [MSBI+2:0] DeltaAdder; //Output of Delta Adder +reg [MSBI+2:0] SigmaAdder; //Output of Sigma Adder +reg [MSBI+2:0] SigmaLatch; //Latches output of Sigma Adder +reg [MSBI+2:0] DeltaB; //B input of Delta Adder + +always @(*) DeltaB = {SigmaLatch[MSBI+2], SigmaLatch[MSBI+2]} << (MSBI+1); +always @(*) DeltaAdder = DACin + DeltaB; +always @(*) SigmaAdder = DeltaAdder + SigmaLatch; + +always @(posedge CLK or posedge RESET) begin + if(RESET) begin + SigmaLatch <= 1'b1 << (MSBI+1); + DACout <= INV; + end else begin + SigmaLatch <= SigmaAdder; + DACout <= SigmaLatch[MSBI+2] ^ INV; + end +end + +endmodule diff --git a/sys/spdif.v b/sys/spdif.v new file mode 100644 index 0000000..eee2b08 --- /dev/null +++ b/sys/spdif.v @@ -0,0 +1,320 @@ +//----------------------------------------------------------------- +// SPDIF Transmitter +// V0.1 +// Ultra-Embedded.com +// Copyright 2012 +// +// Email: admin@ultra-embedded.com +// +// License: GPL +// If you would like a version with a more permissive license for +// use in closed source commercial applications please contact me +// for details. +//----------------------------------------------------------------- +// +// This file is open source HDL; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of +// the License, or (at your option) any later version. +// +// This file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public +// License along with this file; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +//----------------------------------------------------------------- +// altera message_off 10762 +// altera message_off 10240 + +module spdif +( + input clk_i, + input rst_i, + + // SPDIF bit output enable + // Single cycle pulse synchronous to clk_i which drives + // the output bit rate. + // For 44.1KHz, 44100×32×2×2 = 5,644,800Hz + // For 48KHz, 48000×32×2×2 = 6,144,000Hz + input bit_out_en_i, + + // Output + output spdif_o, + + // Audio interface (16-bit x 2 = RL) + input [31:0] sample_i, + output reg sample_req_o +); + +//----------------------------------------------------------------- +// Registers +//----------------------------------------------------------------- +reg [15:0] audio_sample_q; +reg [8:0] subframe_count_q; + +reg load_subframe_q; +reg [7:0] preamble_q; +wire [31:0] subframe_w; + +reg [5:0] bit_count_q; +reg bit_toggle_q; + +reg spdif_out_q; + +reg [5:0] parity_count_q; + +reg channel_status_bit_q; + +//----------------------------------------------------------------- +// Subframe Counter +//----------------------------------------------------------------- +always @ (posedge rst_i or posedge clk_i ) +begin + if (rst_i == 1'b1) + subframe_count_q <= 9'd0; + else if (load_subframe_q) + begin + // 192 frames (384 subframes) in an audio block + if (subframe_count_q == 9'd383) + subframe_count_q <= 9'd0; + else + subframe_count_q <= subframe_count_q + 9'd1; + end +end + +//----------------------------------------------------------------- +// Sample capture +//----------------------------------------------------------------- +reg [15:0] sample_buf_q; + +always @ (posedge rst_i or posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + audio_sample_q <= 16'h0000; + sample_buf_q <= 16'h0000; + sample_req_o <= 1'b0; + end + else if (load_subframe_q) + begin + // Start of frame (first subframe)? + if (subframe_count_q[0] == 1'b0) + begin + // Use left sample + audio_sample_q <= sample_i[15:0]; + + // Store right sample + sample_buf_q <= sample_i[31:16]; + + // Request next sample + sample_req_o <= 1'b1; + end + else + begin + // Use right sample + audio_sample_q <= sample_buf_q; + + sample_req_o <= 1'b0; + end + end + else + sample_req_o <= 1'b0; +end + +// Timeslots 3 - 0 = Preamble +assign subframe_w[3:0] = 4'b0000; + +// Timeslots 7 - 4 = 24-bit audio LSB +assign subframe_w[7:4] = 4'b0000; + +// Timeslots 11 - 8 = 20-bit audio LSB +assign subframe_w[11:8] = 4'b0000; + +// Timeslots 27 - 12 = 16-bit audio +assign subframe_w[27:12] = audio_sample_q; + +// Timeslots 28 = Validity +assign subframe_w[28] = 1'b0; // Valid + +// Timeslots 29 = User bit +assign subframe_w[29] = 1'b0; + +// Timeslots 30 = Channel status bit +assign subframe_w[30] = channel_status_bit_q ; //was constant 1'b0 enabling copy-bit; + +// Timeslots 31 = Even Parity bit (31:4) +assign subframe_w[31] = 1'b0; + +//----------------------------------------------------------------- +// Preamble and Channel status bit +//----------------------------------------------------------------- +localparam PREAMBLE_Z = 8'b00010111; // "B" channel A data at start of block +localparam PREAMBLE_Y = 8'b00100111; // "W" channel B data +localparam PREAMBLE_X = 8'b01000111; // "M" channel A data not at start of block + +reg [7:0] preamble_r; +reg channel_status_bit_r; + +always @ * +begin + // Start of audio block? + // Z(B) - Left channel + if (subframe_count_q == 9'd0) + preamble_r = PREAMBLE_Z; // Z(B) + // Right Channel? + else if (subframe_count_q[0] == 1'b1) + preamble_r = PREAMBLE_Y; // Y(W) + // Left Channel (but not start of block)? + else + preamble_r = PREAMBLE_X; // X(M) + + if (subframe_count_q[8:1] == 8'd2) // frame 2 => subframes 4 and 5 => 0 = copy inhibited, 1 = copy permitted + channel_status_bit_r = 1'b1; + else if (subframe_count_q[8:1] == 8'd15) // frame 15 => 0 = no indication, 1 = original media + channel_status_bit_r = 1'b1; + else if (subframe_count_q[8:1] == 8'd25) // frame 24 to 27 => sample frequency, 0100 = 48kHz, 0000 = 44kHz (l2r) + channel_status_bit_r = 1'b1; + else + channel_status_bit_r = 1'b0; // everything else defaults to 0 +end + +always @ (posedge rst_i or posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + preamble_q <= 8'h00; + channel_status_bit_q <= 1'b0; + end + else if (load_subframe_q) + begin + preamble_q <= preamble_r; + channel_status_bit_q <= channel_status_bit_r; + end +end + +//----------------------------------------------------------------- +// Parity Counter +//----------------------------------------------------------------- +always @ (posedge rst_i or posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + parity_count_q <= 6'd0; + end + // Time to output a bit? + else if (bit_out_en_i) + begin + // Preamble bits? + if (bit_count_q < 6'd8) + begin + parity_count_q <= 6'd0; + end + // Normal timeslots + else if (bit_count_q < 6'd62) + begin + // On first pass through this timeslot, count number of high bits + if (bit_count_q[0] == 0 && subframe_w[bit_count_q / 2] == 1'b1) + parity_count_q <= parity_count_q + 6'd1; + end + end +end + +//----------------------------------------------------------------- +// Bit Counter +//----------------------------------------------------------------- +always @ (posedge rst_i or posedge clk_i) +begin + if (rst_i == 1'b1) + begin + bit_count_q <= 6'b0; + load_subframe_q <= 1'b1; + end + // Time to output a bit? + else if (bit_out_en_i) + begin + // 32 timeslots (x2 for double frequency) + if (bit_count_q == 6'd63) + begin + bit_count_q <= 6'd0; + load_subframe_q <= 1'b1; + end + else + begin + bit_count_q <= bit_count_q + 6'd1; + load_subframe_q <= 1'b0; + end + end + else + load_subframe_q <= 1'b0; +end + +//----------------------------------------------------------------- +// Bit half toggle +//----------------------------------------------------------------- +always @ (posedge rst_i or posedge clk_i) +if (rst_i == 1'b1) + bit_toggle_q <= 1'b0; +// Time to output a bit? +else if (bit_out_en_i) + bit_toggle_q <= ~bit_toggle_q; + +//----------------------------------------------------------------- +// Output bit (BMC encoded) +//----------------------------------------------------------------- +reg bit_r; + +always @ * +begin + bit_r = spdif_out_q; + + // Time to output a bit? + if (bit_out_en_i) + begin + // Preamble bits? + if (bit_count_q < 6'd8) + begin + bit_r = preamble_q[bit_count_q[2:0]]; + end + // Normal timeslots + else if (bit_count_q < 6'd62) + begin + if (subframe_w[bit_count_q / 2] == 1'b0) + begin + if (bit_toggle_q == 1'b0) + bit_r = ~spdif_out_q; + else + bit_r = spdif_out_q; + end + else + bit_r = ~spdif_out_q; + end + // Parity timeslot + else + begin + // Even number of high bits, make odd + if (parity_count_q[0] == 1'b0) + begin + if (bit_toggle_q == 1'b0) + bit_r = ~spdif_out_q; + else + bit_r = spdif_out_q; + end + else + bit_r = ~spdif_out_q; + end + end +end + +always @ (posedge rst_i or posedge clk_i ) +if (rst_i == 1'b1) + spdif_out_q <= 1'b0; +else + spdif_out_q <= bit_r; + +assign spdif_o = spdif_out_q; + +endmodule diff --git a/sys/sys.qip b/sys/sys.qip new file mode 100644 index 0000000..094dab7 --- /dev/null +++ b/sys/sys.qip @@ -0,0 +1,34 @@ +set_global_assignment -name QIP_FILE [join [list $::quartus(qip_path) pll_q [regexp -inline {[0-9]+} $quartus(version)] .qip] {}] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) sys_top.v ] +set_global_assignment -name SDC_FILE [file join $::quartus(qip_path) sys_top.sdc ] +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) ascal.vhd ] +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) pll_hdmi_adj.vhd ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) math.sv ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) hq2x.sv ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) scandoubler.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) scanlines.v ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) shadowmask.sv ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) video_cleaner.sv ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) gamma_corr.sv ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) video_mixer.sv ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) video_freak.sv ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) video_freezer.sv ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) arcade_video.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) osd.v ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) vga_out.sv ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) i2c.v ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) alsa.sv ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) i2s.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) spdif.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) audio_out.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) iir_filter.v ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ltc2308.sv ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) sigma_delta_dac.v ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) mt32pi.sv ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) hdmi_config.sv ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) mcp23009.sv ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) f2sdram_safe_terminator.sv ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ddr_svc.sv ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) sysmem.sv ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) sd_card.sv ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) hps_io.sv ] diff --git a/sys/sys.tcl b/sys/sys.tcl new file mode 100644 index 0000000..8c10190 --- /dev/null +++ b/sys/sys.tcl @@ -0,0 +1,227 @@ +set_global_assignment -name FAMILY "Cyclone V" +set_global_assignment -name DEVICE 5CSEBA6U23I7 +set_global_assignment -name DEVICE_FILTER_PACKAGE UFBGA +set_global_assignment -name DEVICE_FILTER_PIN_COUNT 672 +set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 7 + +#============================================================ +# ADC +#============================================================ +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ADC_CONVST +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ADC_SCK +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ADC_SDI +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ADC_SDO +set_location_assignment PIN_U9 -to ADC_CONVST +set_location_assignment PIN_V10 -to ADC_SCK +set_location_assignment PIN_AC4 -to ADC_SDI +set_location_assignment PIN_AD4 -to ADC_SDO + +#============================================================ +# ARDUINO +#============================================================ +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ARDUINO_IO[*] +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to ARDUINO_IO[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to ARDUINO_IO[*] + +#============================================================ +# I2C LEDS/BUTTONS +#============================================================ +set_location_assignment PIN_U14 -to IO_SCL +set_location_assignment PIN_AG9 -to IO_SDA +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to IO_S* +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to IO_S* +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to IO_S* + +#============================================================ +# USER PORT +#============================================================ +set_location_assignment PIN_AF17 -to USER_IO[6] +set_location_assignment PIN_AF15 -to USER_IO[5] +set_location_assignment PIN_AG16 -to USER_IO[4] +set_location_assignment PIN_AH11 -to USER_IO[3] +set_location_assignment PIN_AH12 -to USER_IO[2] +set_location_assignment PIN_AH9 -to USER_IO[1] +set_location_assignment PIN_AG11 -to USER_IO[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to USER_IO[*] +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to USER_IO[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to USER_IO[*] + +#============================================================ +# SDIO_CD or SPDIF_OUT +#============================================================ +set_location_assignment PIN_AH7 -to SDCD_SPDIF +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDCD_SPDIF +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDCD_SPDIF +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to SDCD_SPDIF + +#============================================================ +# SDRAM +#============================================================ +set_location_assignment PIN_Y11 -to SDRAM_A[0] +set_location_assignment PIN_AA26 -to SDRAM_A[1] +set_location_assignment PIN_AA13 -to SDRAM_A[2] +set_location_assignment PIN_AA11 -to SDRAM_A[3] +set_location_assignment PIN_W11 -to SDRAM_A[4] +set_location_assignment PIN_Y19 -to SDRAM_A[5] +set_location_assignment PIN_AB23 -to SDRAM_A[6] +set_location_assignment PIN_AC23 -to SDRAM_A[7] +set_location_assignment PIN_AC22 -to SDRAM_A[8] +set_location_assignment PIN_C12 -to SDRAM_A[9] +set_location_assignment PIN_AB26 -to SDRAM_A[10] +set_location_assignment PIN_AD17 -to SDRAM_A[11] +set_location_assignment PIN_D12 -to SDRAM_A[12] +set_location_assignment PIN_Y17 -to SDRAM_BA[0] +set_location_assignment PIN_AB25 -to SDRAM_BA[1] +set_location_assignment PIN_E8 -to SDRAM_DQ[0] +set_location_assignment PIN_V12 -to SDRAM_DQ[1] +set_location_assignment PIN_D11 -to SDRAM_DQ[2] +set_location_assignment PIN_W12 -to SDRAM_DQ[3] +set_location_assignment PIN_AH13 -to SDRAM_DQ[4] +set_location_assignment PIN_D8 -to SDRAM_DQ[5] +set_location_assignment PIN_AH14 -to SDRAM_DQ[6] +set_location_assignment PIN_AF7 -to SDRAM_DQ[7] +set_location_assignment PIN_AE24 -to SDRAM_DQ[8] +set_location_assignment PIN_AD23 -to SDRAM_DQ[9] +set_location_assignment PIN_AE6 -to SDRAM_DQ[10] +set_location_assignment PIN_AE23 -to SDRAM_DQ[11] +set_location_assignment PIN_AG14 -to SDRAM_DQ[12] +set_location_assignment PIN_AD5 -to SDRAM_DQ[13] +set_location_assignment PIN_AF4 -to SDRAM_DQ[14] +set_location_assignment PIN_AH3 -to SDRAM_DQ[15] +set_location_assignment PIN_AG13 -to SDRAM_DQML +set_location_assignment PIN_AF13 -to SDRAM_DQMH +set_location_assignment PIN_AD20 -to SDRAM_CLK +set_location_assignment PIN_AG10 -to SDRAM_CKE +set_location_assignment PIN_AA19 -to SDRAM_nWE +set_location_assignment PIN_AA18 -to SDRAM_nCAS +set_location_assignment PIN_Y18 -to SDRAM_nCS +set_location_assignment PIN_W14 -to SDRAM_nRAS + +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_* +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_* +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_* +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM_DQ[*] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[*] +set_instance_assignment -name ALLOW_SYNCH_CTRL_USAGE OFF -to *|SDRAM_* + +#============================================================ +# SPI SD +#============================================================ +set_location_assignment PIN_AE15 -to SD_SPI_CS +set_location_assignment PIN_AH8 -to SD_SPI_MISO +set_location_assignment PIN_AG8 -to SD_SPI_CLK +set_location_assignment PIN_U13 -to SD_SPI_MOSI +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SD_SPI* +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SD_SPI* +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to SD_SPI* + + +#============================================================ +# CLOCK +#============================================================ +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FPGA_CLK1_50 +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FPGA_CLK2_50 +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FPGA_CLK3_50 +set_location_assignment PIN_V11 -to FPGA_CLK1_50 +set_location_assignment PIN_Y13 -to FPGA_CLK2_50 +set_location_assignment PIN_E11 -to FPGA_CLK3_50 + +#============================================================ +# HDMI +#============================================================ +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_I2C_* +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_I2S +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_LRCLK +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_MCLK +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_SCLK +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_* +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to HDMI_TX_D[*] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to HDMI_TX_DE +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to HDMI_TX_HS +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to HDMI_TX_VS +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to HDMI_TX_CLK +set_location_assignment PIN_U10 -to HDMI_I2C_SCL +set_location_assignment PIN_AA4 -to HDMI_I2C_SDA +set_location_assignment PIN_T13 -to HDMI_I2S +set_location_assignment PIN_T11 -to HDMI_LRCLK +set_location_assignment PIN_U11 -to HDMI_MCLK +set_location_assignment PIN_T12 -to HDMI_SCLK +set_location_assignment PIN_AG5 -to HDMI_TX_CLK +set_location_assignment PIN_AD19 -to HDMI_TX_DE +set_location_assignment PIN_AD12 -to HDMI_TX_D[0] +set_location_assignment PIN_AE12 -to HDMI_TX_D[1] +set_location_assignment PIN_W8 -to HDMI_TX_D[2] +set_location_assignment PIN_Y8 -to HDMI_TX_D[3] +set_location_assignment PIN_AD11 -to HDMI_TX_D[4] +set_location_assignment PIN_AD10 -to HDMI_TX_D[5] +set_location_assignment PIN_AE11 -to HDMI_TX_D[6] +set_location_assignment PIN_Y5 -to HDMI_TX_D[7] +set_location_assignment PIN_AF10 -to HDMI_TX_D[8] +set_location_assignment PIN_Y4 -to HDMI_TX_D[9] +set_location_assignment PIN_AE9 -to HDMI_TX_D[10] +set_location_assignment PIN_AB4 -to HDMI_TX_D[11] +set_location_assignment PIN_AE7 -to HDMI_TX_D[12] +set_location_assignment PIN_AF6 -to HDMI_TX_D[13] +set_location_assignment PIN_AF8 -to HDMI_TX_D[14] +set_location_assignment PIN_AF5 -to HDMI_TX_D[15] +set_location_assignment PIN_AE4 -to HDMI_TX_D[16] +set_location_assignment PIN_AH2 -to HDMI_TX_D[17] +set_location_assignment PIN_AH4 -to HDMI_TX_D[18] +set_location_assignment PIN_AH5 -to HDMI_TX_D[19] +set_location_assignment PIN_AH6 -to HDMI_TX_D[20] +set_location_assignment PIN_AG6 -to HDMI_TX_D[21] +set_location_assignment PIN_AF9 -to HDMI_TX_D[22] +set_location_assignment PIN_AE8 -to HDMI_TX_D[23] +set_location_assignment PIN_T8 -to HDMI_TX_HS +set_location_assignment PIN_AF11 -to HDMI_TX_INT +set_location_assignment PIN_V13 -to HDMI_TX_VS + +#============================================================ +# KEY +#============================================================ +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to KEY[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to KEY[1] +set_location_assignment PIN_AH17 -to KEY[0] +set_location_assignment PIN_AH16 -to KEY[1] + +#============================================================ +# LED +#============================================================ +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[2] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[3] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[4] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[5] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[6] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[7] +set_location_assignment PIN_W15 -to LED[0] +set_location_assignment PIN_AA24 -to LED[1] +set_location_assignment PIN_V16 -to LED[2] +set_location_assignment PIN_V15 -to LED[3] +set_location_assignment PIN_AF26 -to LED[4] +set_location_assignment PIN_AE26 -to LED[5] +set_location_assignment PIN_Y16 -to LED[6] +set_location_assignment PIN_AA23 -to LED[7] + +#============================================================ +# SW +#============================================================ +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SW[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SW[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SW[2] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SW[3] +set_location_assignment PIN_Y24 -to SW[0] +set_location_assignment PIN_W24 -to SW[1] +set_location_assignment PIN_W21 -to SW[2] +set_location_assignment PIN_W20 -to SW[3] + +set_instance_assignment -name HPS_LOCATION HPSINTERFACEPERIPHERALSPIMASTER_X52_Y72_N111 -entity sys_top -to spi +set_instance_assignment -name HPS_LOCATION HPSINTERFACEPERIPHERALUART_X52_Y67_N111 -entity sys_top -to uart +set_instance_assignment -name HPS_LOCATION HPSINTERFACEPERIPHERALI2C_X52_Y60_N111 -entity sys_top -to hdmi_i2c + +set_global_assignment -name PRE_FLOW_SCRIPT_FILE "quartus_sh:sys/build_id.tcl" + +set_global_assignment -name CDF_FILE jtag.cdf +set_global_assignment -name QIP_FILE sys/sys.qip + diff --git a/sys/sys_analog.tcl b/sys/sys_analog.tcl new file mode 100644 index 0000000..7ffb3ec --- /dev/null +++ b/sys/sys_analog.tcl @@ -0,0 +1,71 @@ +#============================================================ +# SDIO +#============================================================ +set_location_assignment PIN_AF25 -to SDIO_DAT[0] +set_location_assignment PIN_AF23 -to SDIO_DAT[1] +set_location_assignment PIN_AD26 -to SDIO_DAT[2] +set_location_assignment PIN_AF28 -to SDIO_DAT[3] +set_location_assignment PIN_AF27 -to SDIO_CMD +set_location_assignment PIN_AH26 -to SDIO_CLK +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDIO_* + +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDIO_* +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to SDIO_DAT[*] +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to SDIO_CMD + +#============================================================ +# VGA +#============================================================ +set_location_assignment PIN_AE17 -to VGA_R[0] +set_location_assignment PIN_AE20 -to VGA_R[1] +set_location_assignment PIN_AF20 -to VGA_R[2] +set_location_assignment PIN_AH18 -to VGA_R[3] +set_location_assignment PIN_AH19 -to VGA_R[4] +set_location_assignment PIN_AF21 -to VGA_R[5] + +set_location_assignment PIN_AE19 -to VGA_G[0] +set_location_assignment PIN_AG15 -to VGA_G[1] +set_location_assignment PIN_AF18 -to VGA_G[2] +set_location_assignment PIN_AG18 -to VGA_G[3] +set_location_assignment PIN_AG19 -to VGA_G[4] +set_location_assignment PIN_AG20 -to VGA_G[5] + +set_location_assignment PIN_AG21 -to VGA_B[0] +set_location_assignment PIN_AA20 -to VGA_B[1] +set_location_assignment PIN_AE22 -to VGA_B[2] +set_location_assignment PIN_AF22 -to VGA_B[3] +set_location_assignment PIN_AH23 -to VGA_B[4] +set_location_assignment PIN_AH21 -to VGA_B[5] + +set_location_assignment PIN_AH22 -to VGA_HS +set_location_assignment PIN_AG24 -to VGA_VS + +set_location_assignment PIN_AH27 -to VGA_EN +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to VGA_EN + +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_* +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to VGA_* + +#============================================================ +# AUDIO +#============================================================ +set_location_assignment PIN_AC24 -to AUDIO_L +set_location_assignment PIN_AE25 -to AUDIO_R +set_location_assignment PIN_AG26 -to AUDIO_SPDIF +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to AUDIO_* +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to AUDIO_* + +#============================================================ +# I/O #1 +#============================================================ +set_location_assignment PIN_Y15 -to LED_USER +set_location_assignment PIN_AA15 -to LED_HDD +set_location_assignment PIN_AG28 -to LED_POWER + +set_location_assignment PIN_AH24 -to BTN_USER +set_location_assignment PIN_AG25 -to BTN_OSD +set_location_assignment PIN_AG23 -to BTN_RESET + +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED_* +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to BTN_* +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to BTN_* diff --git a/sys/sys_dual_sdram.tcl b/sys/sys_dual_sdram.tcl new file mode 100644 index 0000000..83485cd --- /dev/null +++ b/sys/sys_dual_sdram.tcl @@ -0,0 +1,50 @@ +#============================================================ +# Secondary SDRAM +#============================================================ +set_location_assignment PIN_Y15 -to SDRAM2_DQ[0] +set_location_assignment PIN_AC24 -to SDRAM2_DQ[1] +set_location_assignment PIN_AA15 -to SDRAM2_DQ[2] +set_location_assignment PIN_AD26 -to SDRAM2_DQ[3] +set_location_assignment PIN_AG28 -to SDRAM2_DQ[4] +set_location_assignment PIN_AF28 -to SDRAM2_DQ[5] +set_location_assignment PIN_AE25 -to SDRAM2_DQ[6] +set_location_assignment PIN_AF27 -to SDRAM2_DQ[7] +set_location_assignment PIN_AG26 -to SDRAM2_DQ[14] +set_location_assignment PIN_AH27 -to SDRAM2_DQ[15] + +set_location_assignment PIN_AG25 -to SDRAM2_DQ[13] +set_location_assignment PIN_AH26 -to SDRAM2_DQ[12] +set_location_assignment PIN_AH24 -to SDRAM2_DQ[11] +set_location_assignment PIN_AF25 -to SDRAM2_DQ[10] +set_location_assignment PIN_AG23 -to SDRAM2_DQ[9] +set_location_assignment PIN_AF23 -to SDRAM2_DQ[8] +set_location_assignment PIN_AG24 -to SDRAM2_A[12] +set_location_assignment PIN_AH22 -to SDRAM2_CLK +set_location_assignment PIN_AH21 -to SDRAM2_A[9] +set_location_assignment PIN_AG21 -to SDRAM2_A[11] +set_location_assignment PIN_AH23 -to SDRAM2_A[7] +set_location_assignment PIN_AA20 -to SDRAM2_A[8] +set_location_assignment PIN_AF22 -to SDRAM2_A[5] +set_location_assignment PIN_AE22 -to SDRAM2_A[6] +set_location_assignment PIN_AG20 -to SDRAM2_nWE +set_location_assignment PIN_AF21 -to SDRAM2_A[4] + +set_location_assignment PIN_AG19 -to SDRAM2_nCAS +set_location_assignment PIN_AH19 -to SDRAM2_nRAS +set_location_assignment PIN_AG18 -to SDRAM2_nCS +set_location_assignment PIN_AH18 -to SDRAM2_BA[0] +set_location_assignment PIN_AF18 -to SDRAM2_BA[1] +set_location_assignment PIN_AF20 -to SDRAM2_A[10] +set_location_assignment PIN_AG15 -to SDRAM2_A[0] +set_location_assignment PIN_AE20 -to SDRAM2_A[1] +set_location_assignment PIN_AE19 -to SDRAM2_A[2] +set_location_assignment PIN_AE17 -to SDRAM2_A[3] + +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM2_* +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM2_* +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM2_* +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM2_DQ[*] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM2_DQ[*] +set_instance_assignment -name ALLOW_SYNCH_CTRL_USAGE OFF -to *|SDRAM2_* + +set_global_assignment -name VERILOG_MACRO "MISTER_DUAL_SDRAM=1" diff --git a/sys/sys_top.sdc b/sys/sys_top.sdc new file mode 100644 index 0000000..e7846f5 --- /dev/null +++ b/sys/sys_top.sdc @@ -0,0 +1,71 @@ +# Specify root clocks +create_clock -period "50.0 MHz" [get_ports FPGA_CLK1_50] +create_clock -period "50.0 MHz" [get_ports FPGA_CLK2_50] +create_clock -period "50.0 MHz" [get_ports FPGA_CLK3_50] +create_clock -period "100.0 MHz" [get_pins -compatibility_mode *|h2f_user0_clk] +create_clock -period "100.0 MHz" [get_pins -compatibility_mode spi|sclk_out] -name spi_sck +create_clock -period "10.0 MHz" [get_pins -compatibility_mode hdmi_i2c|out_clk] -name hdmi_sck + +derive_pll_clocks +derive_clock_uncertainty + +# Decouple different clock groups (to simplify routing) +set_clock_groups -exclusive \ + -group [get_clocks { *|pll|pll_inst|altera_pll_i|*[*].*|divclk}] \ + -group [get_clocks { pll_hdmi|pll_hdmi_inst|altera_pll_i|*[0].*|divclk}] \ + -group [get_clocks { pll_audio|pll_audio_inst|altera_pll_i|*[0].*|divclk}] \ + -group [get_clocks { spi_sck}] \ + -group [get_clocks { hdmi_sck}] \ + -group [get_clocks { *|h2f_user0_clk}] \ + -group [get_clocks { FPGA_CLK1_50 }] \ + -group [get_clocks { FPGA_CLK2_50 }] \ + -group [get_clocks { FPGA_CLK3_50 }] + +set_false_path -from [get_ports {KEY*}] +set_false_path -from [get_ports {BTN_*}] +set_false_path -to [get_ports {LED_*}] +set_false_path -to [get_ports {VGA_*}] +set_false_path -to [get_ports {AUDIO_SPDIF}] +set_false_path -to [get_ports {AUDIO_L}] +set_false_path -to [get_ports {AUDIO_R}] +set_false_path -to {cfg[*]} +set_false_path -from {cfg[*]} +set_false_path -from {VSET[*]} +set_false_path -to {wcalc[*] hcalc[*]} +set_false_path -to {hdmi_width[*] hdmi_height[*]} + +set_multicycle_path -to {*_osd|osd_vcnt*} -setup 2 +set_multicycle_path -to {*_osd|osd_vcnt*} -hold 1 + +set_false_path -to {*_osd|v_cnt*} +set_false_path -to {*_osd|v_osd_start*} +set_false_path -to {*_osd|v_info_start*} +set_false_path -to {*_osd|h_osd_start*} +set_false_path -from {*_osd|v_osd_start*} +set_false_path -from {*_osd|v_info_start*} +set_false_path -from {*_osd|h_osd_start*} +set_false_path -from {*_osd|rot*} +set_false_path -from {*_osd|dsp_width*} +set_false_path -to {*_osd|half} + +set_false_path -to {WIDTH[*] HFP[*] HS[*] HBP[*] HEIGHT[*] VFP[*] VS[*] VBP[*]} +set_false_path -from {WIDTH[*] HFP[*] HS[*] HBP[*] HEIGHT[*] VFP[*] VS[*] VBP[*]} +set_false_path -to {FB_BASE[*] FB_BASE[*] FB_WIDTH[*] FB_HEIGHT[*] LFB_HMIN[*] LFB_HMAX[*] LFB_VMIN[*] LFB_VMAX[*]} +set_false_path -from {FB_BASE[*] FB_BASE[*] FB_WIDTH[*] FB_HEIGHT[*] LFB_HMIN[*] LFB_HMAX[*] LFB_VMIN[*] LFB_VMAX[*]} +set_false_path -to {vol_att[*] scaler_flt[*] led_overtake[*] led_state[*]} +set_false_path -from {vol_att[*] scaler_flt[*] led_overtake[*] led_state[*]} +set_false_path -from {aflt_* acx* acy* areset* arc*} +set_false_path -from {vs_line*} + +set_false_path -from {ascal|o_ihsize*} +set_false_path -from {ascal|o_ivsize*} +set_false_path -from {ascal|o_format*} +set_false_path -from {ascal|o_hdown} +set_false_path -from {ascal|o_vdown} +set_false_path -from {ascal|o_hmin* ascal|o_hmax* ascal|o_vmin* ascal|o_vmax*} +set_false_path -from {ascal|o_hdisp* ascal|o_vdisp*} +set_false_path -from {ascal|o_htotal* ascal|o_vtotal*} +set_false_path -from {ascal|o_hsstart* ascal|o_vsstart* ascal|o_hsend* ascal|o_vsend*} +set_false_path -from {ascal|o_hsize* ascal|o_vsize*} + +set_false_path -from {mcp23009|sd_cd} diff --git a/sys/sys_top.v b/sys/sys_top.v new file mode 100644 index 0000000..635ae56 --- /dev/null +++ b/sys/sys_top.v @@ -0,0 +1,1738 @@ +//============================================================================ +// +// MiSTer hardware abstraction module +// (c)2017-2020 Alexey Melnikov +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +//============================================================================ + +module sys_top +( + /////////// CLOCK ////////// + input FPGA_CLK1_50, + input FPGA_CLK2_50, + input FPGA_CLK3_50, + + //////////// HDMI ////////// + output HDMI_I2C_SCL, + inout HDMI_I2C_SDA, + + output HDMI_MCLK, + output HDMI_SCLK, + output HDMI_LRCLK, + output HDMI_I2S, + + output HDMI_TX_CLK, + output HDMI_TX_DE, + output [23:0] HDMI_TX_D, + output HDMI_TX_HS, + output HDMI_TX_VS, + + input HDMI_TX_INT, + + //////////// SDR /////////// + output [12:0] SDRAM_A, + inout [15:0] SDRAM_DQ, + output SDRAM_DQML, + output SDRAM_DQMH, + output SDRAM_nWE, + output SDRAM_nCAS, + output SDRAM_nRAS, + output SDRAM_nCS, + output [1:0] SDRAM_BA, + output SDRAM_CLK, + output SDRAM_CKE, + +`ifdef MISTER_DUAL_SDRAM + ////////// SDR #2 ////////// + output [12:0] SDRAM2_A, + inout [15:0] SDRAM2_DQ, + output SDRAM2_nWE, + output SDRAM2_nCAS, + output SDRAM2_nRAS, + output SDRAM2_nCS, + output [1:0] SDRAM2_BA, + output SDRAM2_CLK, + +`else + //////////// VGA /////////// + output [5:0] VGA_R, + output [5:0] VGA_G, + output [5:0] VGA_B, + inout VGA_HS, // VGA_HS is secondary SD card detect when VGA_EN = 1 (inactive) + output VGA_VS, + input VGA_EN, // active low + + /////////// AUDIO ////////// + output AUDIO_L, + output AUDIO_R, + output AUDIO_SPDIF, + + //////////// SDIO /////////// + inout [3:0] SDIO_DAT, + inout SDIO_CMD, + output SDIO_CLK, + + //////////// I/O /////////// + output LED_USER, + output LED_HDD, + output LED_POWER, + input BTN_USER, + input BTN_OSD, + input BTN_RESET, +`endif + + ////////// I/O ALT ///////// + output SD_SPI_CS, + input SD_SPI_MISO, + output SD_SPI_CLK, + output SD_SPI_MOSI, + + inout SDCD_SPDIF, + output IO_SCL, + inout IO_SDA, + + ////////// ADC ////////////// + output ADC_SCK, + input ADC_SDO, + output ADC_SDI, + output ADC_CONVST, + + ////////// MB KEY /////////// + input [1:0] KEY, + + ////////// MB SWITCH //////// + input [3:0] SW, + + ////////// MB LED /////////// + output [7:0] LED, + + ///////// USER IO /////////// + inout [6:0] USER_IO +); + +////////////////////// Secondary SD /////////////////////////////////// +wire SD_CS, SD_CLK, SD_MOSI; + +`ifndef MISTER_DUAL_SDRAM + wire sd_miso = SW[3] | SDIO_DAT[0]; +`else + wire sd_miso = 1; +`endif +wire SD_MISO = mcp_sdcd ? sd_miso : SD_SPI_MISO; + +`ifndef MISTER_DUAL_SDRAM + assign SDIO_DAT[2:1]= 2'bZZ; + assign SDIO_DAT[3] = SW[3] ? 1'bZ : SD_CS; + assign SDIO_CLK = SW[3] ? 1'bZ : SD_CLK; + assign SDIO_CMD = SW[3] ? 1'bZ : SD_MOSI; + assign SD_SPI_CS = mcp_sdcd ? ((~VGA_EN & sog & ~cs1) ? 1'b1 : 1'bZ) : SD_CS; +`else + assign SD_SPI_CS = mcp_sdcd ? 1'bZ : SD_CS; +`endif + +assign SD_SPI_CLK = mcp_sdcd ? 1'bZ : SD_CLK; +assign SD_SPI_MOSI = mcp_sdcd ? 1'bZ : SD_MOSI; + +////////////////////// LEDs/Buttons /////////////////////////////////// + +reg [7:0] led_overtake = 0; +reg [7:0] led_state = 0; + +wire led_p = led_power[1] ? ~led_power[0] : 1'b0; +wire led_d = led_disk[1] ? ~led_disk[0] : ~(led_disk[0] | gp_out[29]); +wire led_u = ~led_user; +wire led_locked; + +`ifndef MISTER_DUAL_SDRAM + assign LED_POWER = (SW[3] | led_p) ? 1'bZ : 1'b0; + assign LED_HDD = (SW[3] | led_d) ? 1'bZ : 1'b0; + assign LED_USER = (SW[3] | led_u) ? 1'bZ : 1'b0; +`endif + +//LEDs on main board +assign LED = (led_overtake & led_state) | (~led_overtake & {1'b0,led_locked,1'b0, ~led_p, 1'b0, ~led_d, 1'b0, ~led_u}); + +wire btn_r, btn_o, btn_u; +`ifdef MISTER_DUAL_SDRAM + assign {btn_r,btn_o,btn_u} = {mcp_btn[1],mcp_btn[2],mcp_btn[0]}; +`else + assign {btn_r,btn_o,btn_u} = ~{BTN_RESET,BTN_OSD,BTN_USER} | {mcp_btn[1],mcp_btn[2],mcp_btn[0]}; +`endif + +wire [2:0] mcp_btn; +wire mcp_sdcd; +mcp23009 mcp23009 +( + .clk(FPGA_CLK2_50), + + .btn(mcp_btn), + .led({led_p, led_d, led_u}), + .sd_cd(mcp_sdcd), + + .scl(IO_SCL), + .sda(IO_SDA) +); + + +reg btn_user, btn_osd; +always @(posedge FPGA_CLK2_50) begin + integer div; + reg [7:0] deb_user; + reg [7:0] deb_osd; + + div <= div + 1'b1; + if(div > 100000) div <= 0; + + if(!div) begin + deb_user <= {deb_user[6:0], btn_u | ~KEY[1]}; + if(&deb_user) btn_user <= 1; + if(!deb_user) btn_user <= 0; + + deb_osd <= {deb_osd[6:0], btn_o | ~KEY[0]}; + if(&deb_osd) btn_osd <= 1; + if(!deb_osd) btn_osd <= 0; + end +end + +///////////////////////// HPS I/O ///////////////////////////////////// + +// gp_in[31] = 0 - quick flag that FPGA is initialized (HPS reads 1 when FPGA is not in user mode) +// used to avoid lockups while JTAG loading +wire [31:0] gp_in = {1'b0, btn_user | btn[1], btn_osd | btn[0], SW[3], 8'd0, io_ver, io_ack, io_wide, io_dout}; +wire [31:0] gp_out; + +wire [1:0] io_ver = 1; // 0 - obsolete. 1 - optimized HPS I/O. 2,3 - reserved for future. +wire io_wait; +wire io_wide; +wire [15:0] io_dout; +wire [15:0] io_din = gp_outr[15:0]; +wire io_clk = gp_outr[17]; +wire io_ss0 = gp_outr[18]; +wire io_ss1 = gp_outr[19]; +wire io_ss2 = gp_outr[20]; + +`ifndef MISTER_DEBUG_NOHDMI +wire io_osd_hdmi = io_ss1 & ~io_ss0; +`endif + +wire io_fpga = ~io_ss1 & io_ss0; +wire io_uio = ~io_ss1 & io_ss2; + +reg io_ack; +reg rack; +wire io_strobe = ~rack & io_clk; + +always @(posedge clk_sys) begin + if(~(io_wait | vs_wait) | io_strobe) begin + rack <= io_clk; + io_ack <= rack; + end +end + +reg [31:0] gp_outr; +always @(posedge clk_sys) begin + reg [31:0] gp_outd; + gp_outr <= gp_outd; + gp_outd <= gp_out; +end + +`ifdef MISTER_DUAL_SDRAM + wire [7:0] core_type = 'hA8; // generic core, dual SDRAM. +`else + wire [7:0] core_type = 'hA4; // generic core. +`endif + +// HPS will not communicate to core if magic is different +wire [31:0] core_magic = {24'h5CA623, core_type}; + +cyclonev_hps_interface_mpu_general_purpose h2f_gp +( + .gp_in({~gp_out[31] ? core_magic : gp_in}), + .gp_out(gp_out) +); + + +reg [15:0] cfg; + +reg cfg_set = 0; +wire vga_fb = cfg[12] | vga_force_scaler; +wire [1:0] hdmi_limited = {cfg[11],cfg[8]}; + +`ifdef MISTER_DEBUG_NOHDMI +wire direct_video = 1; +`else +wire direct_video = cfg[10]; +`endif + +wire dvi_mode = cfg[7]; +wire audio_96k = cfg[6]; +wire csync_en = cfg[3]; +wire ypbpr_en = cfg[5]; +wire io_osd_vga = io_ss1 & ~io_ss2; +`ifndef MISTER_DUAL_SDRAM + wire sog = cfg[9]; + wire vga_scaler = cfg[2] | vga_force_scaler; +`endif + +reg cfg_custom_t = 0; +reg [5:0] cfg_custom_p1; +reg [31:0] cfg_custom_p2; + +reg [4:0] vol_att; +initial vol_att = 5'b11111; + +reg [11:0] coef_addr; +reg [9:0] coef_data; +reg coef_wr = 0; + +wire[12:0] ARX, ARY; +reg [11:0] VSET = 0, HSET = 0; +reg FREESCALE = 0; +reg [2:0] scaler_flt; +reg lowlat = 0; +reg cfg_dis = 0; + +reg vs_wait = 0; +reg [11:0] vs_line = 0; + +reg scaler_out = 0; + +reg [31:0] aflt_rate = 7056000; +reg [39:0] acx = 4258969; +reg [7:0] acx0 = 3; +reg [7:0] acx1 = 3; +reg [7:0] acx2 = 1; +reg [23:0] acy0 = -24'd6216759; +reg [23:0] acy1 = 24'd6143386; +reg [23:0] acy2 = -24'd2023767; +reg areset = 0; +reg [12:0] arc1x = 0; +reg [12:0] arc1y = 0; +reg [12:0] arc2x = 0; +reg [12:0] arc2y = 0; + +always@(posedge clk_sys) begin + reg [7:0] cmd; + reg has_cmd; + reg old_strobe; + reg [7:0] cnt = 0; + reg vs_d0,vs_d1,vs_d2; + reg [4:0] acx_att; + + old_strobe <= io_strobe; + coef_wr <= 0; + +`ifndef MISTER_DEBUG_NOHDMI + shadowmask_wr <= 0; +`endif + + if(~io_uio) begin + has_cmd <= 0; + cmd <= 0; + areset <= 0; + acx_att <= 0; + acx <= acx >> acx_att; + end + else + if(~old_strobe & io_strobe) begin + if(!has_cmd) begin + has_cmd <= 1; + cmd <= io_din[7:0]; + cnt <= 0; + if(io_din[7:0] == 'h30) vs_wait <= 1; + if(io_din[7:0] == 'h39) begin + aflt_rate <= 7056000; + acx <= 4258969; + acx0 <= 3; + acx1 <= 3; + acx2 <= 1; + acy0 <= -24'd6216759; + acy1 <= 24'd6143386; + acy2 <= -24'd2023767; + areset <= 1; + end + end + else begin + cnt <= cnt + 1'd1; + if(cmd == 1) begin + cfg <= io_din; + cfg_set <= 1; + scaler_out <= 1; + end + if(cmd == 'h20) begin + cfg_set <= 0; + if(cnt<8) begin + case(cnt[2:0]) + 0: WIDTH <= io_din[11:0]; + 1: HFP <= io_din[11:0]; + 2: HS <= {io_din[15], io_din[11:0]}; + 3: HBP <= io_din[11:0]; + 4: HEIGHT <= io_din[11:0]; + 5: VFP <= io_din[11:0]; + 6: VS <= {io_din[15],io_din[11:0]}; + 7: VBP <= io_din[11:0]; + endcase +`ifndef MISTER_DEBUG_NOHDMI + if(cnt == 1) begin + cfg_custom_p1 <= 0; + cfg_custom_p2 <= 0; + cfg_custom_t <= ~cfg_custom_t; + end + end + else begin + if(cnt[1:0]==0) cfg_custom_p1 <= io_din[5:0]; + if(cnt[1:0]==1) cfg_custom_p2[15:0] <= io_din; + if(cnt[1:0]==2) begin + cfg_custom_p2[31:16] <= io_din; + cfg_custom_t <= ~cfg_custom_t; + cnt[2:0] <= 3'b100; + end + if(cnt == 8) {lowlat,cfg_dis} <= io_din[15:14]; +`endif + end + end + if(cmd == 'h2F) begin + case(cnt[3:0]) + 0: {LFB_EN,LFB_FLT,LFB_FMT} <= {io_din[15], io_din[14], io_din[5:0]}; + 1: LFB_BASE[15:0] <= io_din[15:0]; + 2: LFB_BASE[31:16] <= io_din[15:0]; + 3: LFB_WIDTH <= io_din[11:0]; + 4: LFB_HEIGHT <= io_din[11:0]; + 5: LFB_HMIN <= io_din[11:0]; + 6: LFB_HMAX <= io_din[11:0]; + 7: LFB_VMIN <= io_din[11:0]; + 8: LFB_VMAX <= io_din[11:0]; + 9: LFB_STRIDE <= io_din[13:0]; + endcase + end + if(cmd == 'h25) {led_overtake, led_state} <= io_din; + if(cmd == 'h26) vol_att <= io_din[4:0]; + if(cmd == 'h27) VSET <= io_din[11:0]; + if(cmd == 'h2A) begin + if(cnt[0]) {coef_wr,coef_data} <= {1'b1,io_din[9:0]}; + else coef_addr <= io_din[11:0]; + end + if(cmd == 'h2B) scaler_flt <= io_din[2:0]; + if(cmd == 'h37) {FREESCALE,HSET} <= {io_din[15],io_din[11:0]}; + if(cmd == 'h38) vs_line <= io_din[11:0]; + if(cmd == 'h39) begin + case(cnt[3:0]) + 0: acx_att <= io_din[4:0]; + 1: aflt_rate[15:0] <= io_din; + 2: aflt_rate[31:16] <= io_din; + 3: acx[15:0] <= io_din; + 4: acx[31:16] <= io_din; + 5: acx[39:32] <= io_din[7:0]; + 6: acx0 <= io_din[7:0]; + 7: acx1 <= io_din[7:0]; + 8: acx2 <= io_din[7:0]; + 9: acy0[15:0] <= io_din; + 10: acy0[23:16] <= io_din[7:0]; + 11: acy1[15:0] <= io_din; + 12: acy1[23:16] <= io_din[7:0]; + 13: acy2[15:0] <= io_din; + 14: acy2[23:16] <= io_din[7:0]; + endcase + end + if(cmd == 'h3A) begin + case(cnt[3:0]) + 0: arc1x <= io_din[12:0]; + 1: arc1y <= io_din[12:0]; + 2: arc2x <= io_din[12:0]; + 3: arc2y <= io_din[12:0]; + endcase + end +`ifndef MISTER_DEBUG_NOHDMI + if(cmd == 'h3E) {shadowmask_wr,shadowmask_data} <= {1'b1, io_din}; +`endif + end + end + + vs_d0 <= HDMI_TX_VS; + if(vs_d0 == HDMI_TX_VS) vs_d1 <= vs_d0; + + vs_d2 <= vs_d1; + if(~vs_d2 & vs_d1) vs_wait <= 0; +end + +cyclonev_hps_interface_peripheral_uart uart +( + .ri(0), + .dsr(uart_dsr), + .dcd(uart_dsr), + .dtr(uart_dtr), + + .cts(uart_cts), + .rts(uart_rts), + .rxd(uart_rxd), + .txd(uart_txd) +); + +wire aspi_sck,aspi_mosi,aspi_ss,aspi_miso; +cyclonev_hps_interface_peripheral_spi_master spi +( + .sclk_out(aspi_sck), + .txd(aspi_mosi), // mosi + .rxd(aspi_miso), // miso + + .ss_0_n(aspi_ss), + .ss_in_n(1) +); + +wire [63:0] f2h_irq = {video_sync,HDMI_TX_VS}; +cyclonev_hps_interface_interrupts interrupts +( + .irq(f2h_irq) +); + +/////////////////////////// RESET /////////////////////////////////// + +reg reset_req = 0; +always @(posedge FPGA_CLK2_50) begin + reg [1:0] resetd, resetd2; + reg old_reset; + + //latch the reset + old_reset <= reset; + if(~old_reset & reset) reset_req <= 1; + + //special combination to set/clear the reset + //preventing of accidental reset control + if(resetd==1) reset_req <= 1; + if(resetd==2 && resetd2==0) reset_req <= 0; + + resetd <= gp_out[31:30]; + resetd2 <= resetd; +end + +//////////////////// SYSTEM MEMORY & SCALER ///////////////////////// + +wire reset; +wire clk_100m; + +sysmem_lite sysmem +( + //Reset/Clock + .reset_core_req(reset_req), + .reset_out(reset), + .clock(clk_100m), + + //DE10-nano has no reset signal on GPIO, so core has to emulate cold reset button. + .reset_hps_cold_req(btn_r), + + //64-bit DDR3 RAM access + .ram1_clk(ram_clk), + .ram1_address(ram_address), + .ram1_burstcount(ram_burstcount), + .ram1_waitrequest(ram_waitrequest), + .ram1_readdata(ram_readdata), + .ram1_readdatavalid(ram_readdatavalid), + .ram1_read(ram_read), + .ram1_writedata(ram_writedata), + .ram1_byteenable(ram_byteenable), + .ram1_write(ram_write), + + //64-bit DDR3 RAM access + .ram2_clk(clk_audio), + .ram2_address(ram2_address), + .ram2_burstcount(ram2_burstcount), + .ram2_waitrequest(ram2_waitrequest), + .ram2_readdata(ram2_readdata), + .ram2_readdatavalid(ram2_readdatavalid), + .ram2_read(ram2_read), + .ram2_writedata(ram2_writedata), + .ram2_byteenable(ram2_byteenable), + .ram2_write(ram2_write), + + //128-bit DDR3 RAM access + // HDMI frame buffer + .vbuf_clk(clk_100m), + .vbuf_address(vbuf_address), + .vbuf_burstcount(vbuf_burstcount), + .vbuf_waitrequest(vbuf_waitrequest), + .vbuf_writedata(vbuf_writedata), + .vbuf_byteenable(vbuf_byteenable), + .vbuf_write(vbuf_write), + .vbuf_readdata(vbuf_readdata), + .vbuf_readdatavalid(vbuf_readdatavalid), + .vbuf_read(vbuf_read) +); + +wire [28:0] ram2_address; +wire [7:0] ram2_burstcount; +wire [7:0] ram2_byteenable; +wire ram2_waitrequest; +wire [63:0] ram2_readdata; +wire [63:0] ram2_writedata; +wire ram2_readdatavalid; +wire ram2_read; +wire ram2_write; +wire [7:0] ram2_bcnt; + +ddr_svc ddr_svc +( + .clk(clk_audio), + + .ram_waitrequest(ram2_waitrequest), + .ram_burstcnt(ram2_burstcount), + .ram_addr(ram2_address), + .ram_readdata(ram2_readdata), + .ram_read_ready(ram2_readdatavalid), + .ram_read(ram2_read), + .ram_writedata(ram2_writedata), + .ram_byteenable(ram2_byteenable), + .ram_write(ram2_write), + .ram_bcnt(ram2_bcnt), + + .ch0_addr(alsa_address), + .ch0_burst(1), + .ch0_data(alsa_readdata), + .ch0_req(alsa_req), + .ch0_ready(alsa_ready), + + .ch1_addr(pal_addr), + .ch1_burst(128), + .ch1_data(pal_data), + .ch1_req(pal_req), + .ch1_ready(pal_wr) +); + +wire clk_pal = clk_audio; + + +wire [27:0] vbuf_address; +wire [7:0] vbuf_burstcount; +wire vbuf_waitrequest; +wire [127:0] vbuf_readdata; +wire vbuf_readdatavalid; +wire vbuf_read; +wire [127:0] vbuf_writedata; +wire [15:0] vbuf_byteenable; +wire vbuf_write; + +wire [23:0] hdmi_data; +wire hdmi_vs, hdmi_hs, hdmi_de, hdmi_vbl, hdmi_brd; +wire freeze; + +`ifndef MISTER_DEBUG_NOHDMI +wire clk_hdmi = hdmi_clk_out; + +ascal +#( + .RAMBASE(32'h20000000), +`ifndef MISTER_FB + .PALETTE2("false"), +`else + `ifndef MISTER_FB_PALETTE + .PALETTE2("false"), + `endif +`endif +`ifdef MISTER_DISABLE_ADAPTIVE + .ADAPTIVE("false"), +`endif +`ifdef MISTER_DOWNSCALE_NN + .DOWNSCALE_NN("true"), +`endif + .FRAC(8), + .N_DW(128), + .N_AW(28) +) +ascal +( + .reset_na (~reset_req), + .run (1), + .freeze (freeze), + + .i_clk (clk_ihdmi), + .i_ce (ce_hpix), + .i_r (hr_out), + .i_g (hg_out), + .i_b (hb_out), + .i_hs (hhs_fix), + .i_vs (hvs_fix), + .i_fl (f1), + .i_de (hde_emu), + .iauto (1), + .himin (0), + .himax (0), + .vimin (0), + .vimax (0), + + .o_clk (clk_hdmi), + .o_ce (scaler_out), + .o_r (hdmi_data[23:16]), + .o_g (hdmi_data[15:8]), + .o_b (hdmi_data[7:0]), + .o_hs (hdmi_hs), + .o_vs (hdmi_vs), + .o_de (hdmi_de), + .o_vbl (hdmi_vbl), + .o_brd (hdmi_brd), + .o_lltune (lltune), + .htotal (WIDTH + HFP + HBP + HS[11:0]), + .hsstart (WIDTH + HFP), + .hsend (WIDTH + HFP + HS[11:0]), + .hdisp (WIDTH), + .hmin (hmin), + .hmax (hmax), + .vtotal (HEIGHT + VFP + VBP + VS[11:0]), + .vsstart (HEIGHT + VFP), + .vsend (HEIGHT + VFP + VS[11:0]), + .vdisp (HEIGHT), + .vmin (vmin), + .vmax (vmax), + + .mode ({~lowlat,LFB_EN ? LFB_FLT : |scaler_flt,2'b00}), + .poly_clk (clk_sys), + .poly_a (coef_addr), + .poly_dw (coef_data), + .poly_wr (coef_wr), + + .pal1_clk (clk_pal), + .pal1_dw (pal_d), + .pal1_a (pal_a), + .pal1_wr (pal_wr), + +`ifdef MISTER_FB + `ifdef MISTER_FB_PALETTE + .pal2_clk (fb_pal_clk), + .pal2_dw (fb_pal_d), + .pal2_dr (fb_pal_q), + .pal2_a (fb_pal_a), + .pal2_wr (fb_pal_wr), + .pal_n (fb_en), + `endif +`endif + + .o_fb_ena (FB_EN), + .o_fb_hsize (FB_WIDTH), + .o_fb_vsize (FB_HEIGHT), + .o_fb_format (FB_FMT), + .o_fb_base (FB_BASE), + .o_fb_stride (FB_STRIDE), + + .avl_clk (clk_100m), + .avl_waitrequest (vbuf_waitrequest), + .avl_readdata (vbuf_readdata), + .avl_readdatavalid(vbuf_readdatavalid), + .avl_burstcount (vbuf_burstcount), + .avl_writedata (vbuf_writedata), + .avl_address (vbuf_address), + .avl_write (vbuf_write), + .avl_read (vbuf_read), + .avl_byteenable (vbuf_byteenable) +); +`endif + +reg LFB_EN = 0; +reg LFB_FLT = 0; +reg [5:0] LFB_FMT = 0; +reg [11:0] LFB_WIDTH = 0; +reg [11:0] LFB_HEIGHT = 0; +reg [11:0] LFB_HMIN = 0; +reg [11:0] LFB_HMAX = 0; +reg [11:0] LFB_VMIN = 0; +reg [11:0] LFB_VMAX = 0; +reg [31:0] LFB_BASE = 0; +reg [13:0] LFB_STRIDE = 0; + +reg FB_EN = 0; +reg [5:0] FB_FMT = 0; +reg [11:0] FB_WIDTH = 0; +reg [11:0] FB_HEIGHT = 0; +reg [31:0] FB_BASE = 0; +reg [13:0] FB_STRIDE = 0; + +always @(posedge clk_sys) begin + FB_EN <= LFB_EN | fb_en; + if(LFB_EN) begin + FB_FMT <= LFB_FMT; + FB_WIDTH <= LFB_WIDTH; + FB_HEIGHT <= LFB_HEIGHT; + FB_BASE <= LFB_BASE; + FB_STRIDE <= LFB_STRIDE; + end + else begin + FB_FMT <= fb_fmt; + FB_WIDTH <= fb_width; + FB_HEIGHT <= fb_height; + FB_BASE <= fb_base; + FB_STRIDE <= fb_stride; + end +end + +`ifdef MISTER_FB +reg fb_vbl; +always @(posedge clk_vid) fb_vbl <= hdmi_vbl; +`endif + +reg ar_md_start; +wire ar_md_busy; +reg [11:0] ar_md_mul1, ar_md_mul2, ar_md_div; +wire [11:0] ar_md_res; + +sys_umuldiv #(12,12,12) ar_muldiv +( + .clk(clk_vid), + .start(ar_md_start), + .busy(ar_md_busy), + + .mul1(ar_md_mul1), + .mul2(ar_md_mul2), + .div(ar_md_div), + .result(ar_md_res) +); + +reg [11:0] hmin; +reg [11:0] hmax; +reg [11:0] vmin; +reg [11:0] vmax; +reg [11:0] hdmi_height; +reg [11:0] hdmi_width; + +always @(posedge clk_vid) begin + reg [11:0] hmini,hmaxi,vmini,vmaxi; + reg [11:0] wcalc,videow,arx; + reg [11:0] hcalc,videoh,ary; + reg [2:0] state; + reg xy; + + hdmi_height <= (VSET && (VSET < HEIGHT)) ? VSET : HEIGHT; + hdmi_width <= (HSET && (HSET < WIDTH)) ? HSET : WIDTH; + + if(!ARY) begin + if(ARX == 1) begin + arx <= arc1x[11:0]; + ary <= arc1y[11:0]; + xy <= arc1x[12] | arc1y[12]; + end + else if(ARX == 2) begin + arx <= arc2x[11:0]; + ary <= arc2y[11:0]; + xy <= arc2x[12] | arc2y[12]; + end + else begin + arx <= 0; + ary <= 0; + xy <= 0; + end + end + else begin + arx <= ARX[11:0]; + ary <= ARY[11:0]; + xy <= ARX[12] | ARY[12]; + end + + ar_md_start <= 0; + state <= state + 1'd1; + case(state) + 0: if(LFB_EN) begin + hmini <= LFB_HMIN; + vmini <= LFB_VMIN; + hmaxi <= LFB_HMAX; + vmaxi <= LFB_VMAX; + state <= 0; + end + else if(FREESCALE || !arx || !ary) begin + wcalc <= hdmi_width; + hcalc <= hdmi_height; + state <= 6; + end + else if(xy) begin + wcalc <= arx; + hcalc <= ary; + state <= 6; + end + + 1: begin + ar_md_mul1 <= hdmi_height; + ar_md_mul2 <= arx; + ar_md_div <= ary; + ar_md_start<= 1; + end + 2: begin + wcalc <= ar_md_res; + if(ar_md_start | ar_md_busy) state <= 2; + end + + 3: begin + ar_md_mul1 <= hdmi_width; + ar_md_mul2 <= ary; + ar_md_div <= arx; + ar_md_start<= 1; + end + 4: begin + hcalc <= ar_md_res; + if(ar_md_start | ar_md_busy) state <= 4; + end + + 6: begin + videow <= (wcalc > hdmi_width) ? hdmi_width : wcalc[11:0]; + videoh <= (hcalc > hdmi_height) ? hdmi_height : hcalc[11:0]; + end + + 7: begin + hmini <= ((WIDTH - videow)>>1); + hmaxi <= ((WIDTH - videow)>>1) + videow - 1'd1; + vmini <= ((HEIGHT - videoh)>>1); + vmaxi <= ((HEIGHT - videoh)>>1) + videoh - 1'd1; + end + endcase + + hmin <= hmini; + hmax <= hmaxi; + vmin <= vmini; + vmax <= vmaxi; +end + +`ifndef MISTER_DEBUG_NOHDMI +wire [15:0] lltune; +pll_hdmi_adj pll_hdmi_adj +( + .clk(FPGA_CLK1_50), + .reset_na(~reset_req), + + .llena(lowlat), + .lltune({16{hdmi_config_done | cfg_dis}} & lltune), + .locked(led_locked), + .i_waitrequest(adj_waitrequest), + .i_write(adj_write), + .i_address(adj_address), + .i_writedata(adj_data), + .o_waitrequest(cfg_waitrequest), + .o_write(cfg_write), + .o_address(cfg_address), + .o_writedata(cfg_data) +); +`else + assign led_locked = 0; +`endif + +wire [63:0] pal_data; +wire [47:0] pal_d = {pal_data[55:32], pal_data[23:0]}; +wire [6:0] pal_a = ram2_bcnt[6:0]; +wire pal_wr; + +reg [28:0] pal_addr; +reg pal_req = 0; +always @(posedge clk_pal) begin + reg old_vs1, old_vs2; + + pal_addr <= LFB_BASE[31:3] - 29'd512; + + old_vs1 <= hdmi_vs; + old_vs2 <= old_vs1; + + if(~old_vs2 & old_vs1 & ~FB_FMT[2] & FB_FMT[1] & FB_FMT[0] & FB_EN) pal_req <= ~pal_req; +end + + +///////////////////////// HDMI output ///////////////////////////////// +`ifndef MISTER_DEBUG_NOHDMI +wire hdmi_clk_out; +pll_hdmi pll_hdmi +( + .refclk(FPGA_CLK1_50), + .rst(reset_req), + .reconfig_to_pll(reconfig_to_pll), + .reconfig_from_pll(reconfig_from_pll), + .outclk_0(hdmi_clk_out) +); +`endif + +//1920x1080@60 PCLK=148.5MHz CEA +reg [11:0] WIDTH = 1920; +reg [11:0] HFP = 88; +reg [12:0] HS = 48; +reg [11:0] HBP = 148; +reg [11:0] HEIGHT = 1080; +reg [11:0] VFP = 4; +reg [12:0] VS = 5; +reg [11:0] VBP = 36; + +wire [63:0] reconfig_to_pll; +wire [63:0] reconfig_from_pll; +wire cfg_waitrequest,adj_waitrequest; +wire cfg_write; +wire [5:0] cfg_address; +wire [31:0] cfg_data; +reg adj_write; +reg [5:0] adj_address; +reg [31:0] adj_data; + +`ifndef MISTER_DEBUG_NOHDMI +pll_cfg pll_cfg +( + .mgmt_clk(FPGA_CLK1_50), + .mgmt_reset(reset_req), + .mgmt_waitrequest(cfg_waitrequest), + .mgmt_read(0), + .mgmt_readdata(), + .mgmt_write(cfg_write), + .mgmt_address(cfg_address), + .mgmt_writedata(cfg_data), + .reconfig_to_pll(reconfig_to_pll), + .reconfig_from_pll(reconfig_from_pll) +); + +reg cfg_got = 0; +always @(posedge clk_sys) begin + reg vsd, vsd2; + if(~cfg_ready || ~cfg_set) cfg_got <= cfg_set; + else begin + vsd <= HDMI_TX_VS; + vsd2 <= vsd; + if(~vsd2 & vsd) cfg_got <= cfg_set; + end +end + +reg cfg_ready = 0; +always @(posedge FPGA_CLK1_50) begin + reg gotd = 0, gotd2 = 0; + reg custd = 0, custd2 = 0; + reg old_wait = 0; + + gotd <= cfg_got; + gotd2 <= gotd; + + adj_write <= 0; + + custd <= cfg_custom_t; + custd2 <= custd; + if(custd2 != custd & ~gotd) begin + adj_address <= cfg_custom_p1; + adj_data <= cfg_custom_p2; + adj_write <= 1; + end + + if(~gotd2 & gotd) begin + adj_address <= 2; + adj_data <= 0; + adj_write <= 1; + end + + old_wait <= adj_waitrequest; + if(old_wait & ~adj_waitrequest & gotd) cfg_ready <= 1; +end + +`else + +wire cfg_ready = 1; + +`endif + +wire hdmi_config_done; +hdmi_config hdmi_config +( + .iCLK(FPGA_CLK1_50), + .iRST_N(cfg_ready & ~HDMI_TX_INT & ~cfg_dis), + .done(hdmi_config_done), + + .I2C_SCL(HDMI_I2C_SCL), + .I2C_SDA(HDMI_I2C_SDA), + + .dvi_mode(dvi_mode), + .audio_96k(audio_96k), + .limited(hdmi_limited), + .ypbpr(ypbpr_en & direct_video) +); + +assign HDMI_I2C_SCL = hdmi_scl_en ? 1'b0 : 1'bZ; +assign HDMI_I2C_SDA = hdmi_sda_en ? 1'b0 : 1'bZ; + +wire hdmi_scl_en, hdmi_sda_en; +cyclonev_hps_interface_peripheral_i2c hdmi_i2c +( + .out_clk(hdmi_scl_en), + .scl(HDMI_I2C_SCL), + .out_data(hdmi_sda_en), + .sda(HDMI_I2C_SDA) +); + +`ifndef MISTER_DEBUG_NOHDMI + +`ifdef MISTER_FB +reg dis_output; +always @(posedge clk_hdmi) begin + reg dis; + dis <= fb_force_blank & ~LFB_EN; + dis_output <= dis; +end +`else +wire dis_output = 0; +`endif + +wire [23:0] hdmi_data_mask; +wire hdmi_de_mask, hdmi_vs_mask, hdmi_hs_mask; + +reg [15:0] shadowmask_data; +reg shadowmask_wr = 0; + +shadowmask HDMI_shadowmask +( + .clk(clk_hdmi), + .clk_sys(clk_sys), + + .cmd_wr(shadowmask_wr), + .cmd_in(shadowmask_data), + + .din(dis_output ? 24'd0 : hdmi_data), + .hs_in(hdmi_hs), + .vs_in(hdmi_vs), + .de_in(hdmi_de), + .brd_in(hdmi_brd), + .enable(~LFB_EN), + + .dout(hdmi_data_mask), + .hs_out(hdmi_hs_mask), + .vs_out(hdmi_vs_mask), + .de_out(hdmi_de_mask) +); + +wire [23:0] hdmi_data_osd; +wire hdmi_de_osd, hdmi_vs_osd, hdmi_hs_osd; + +osd hdmi_osd +( + .clk_sys(clk_sys), + + .io_osd(io_osd_hdmi), + .io_strobe(io_strobe), + .io_din(io_din), + + .clk_video(clk_hdmi), + .din(hdmi_data_mask), + .hs_in(hdmi_hs_mask), + .vs_in(hdmi_vs_mask), + .de_in(hdmi_de_mask), + + .dout(hdmi_data_osd), + .hs_out(hdmi_hs_osd), + .vs_out(hdmi_vs_osd), + .de_out(hdmi_de_osd) +); +`endif + +wire hdmi_cs_osd; +csync csync_hdmi(clk_hdmi, hdmi_hs_osd, hdmi_vs_osd, hdmi_cs_osd); + +reg [23:0] dv_data; +reg dv_hs, dv_vs, dv_de; +always @(posedge clk_vid) begin + reg [23:0] dv_d1, dv_d2; + reg dv_de1, dv_de2, dv_hs1, dv_hs2, dv_vs1, dv_vs2; + reg [12:0] vsz, vcnt; + reg old_hs, old_vs; + reg vde; + reg [3:0] hss; + + if(ce_pix) begin + hss <= (hss << 1) | vga_hs_osd; + + old_hs <= vga_hs_osd; + if(~old_hs && vga_hs_osd) begin + old_vs <= vga_vs_osd; + if(~&vcnt) vcnt <= vcnt + 1'd1; + if(~old_vs & vga_vs_osd & ~f1) vsz <= vcnt; + if(old_vs & ~vga_vs_osd) vcnt <= 0; + + if(vcnt == 1) vde <= 1; + if(vcnt == vsz - 3) vde <= 0; + end + + dv_de1 <= !{hss,vga_hs_osd} && vde; + dv_hs1 <= csync_en ? vga_cs_osd : vga_hs_osd; + dv_vs1 <= vga_vs_osd; + end + + dv_d1 <= vga_data_osd; + dv_d2 <= dv_d1; + dv_de2 <= dv_de1; + dv_hs2 <= dv_hs1; + dv_vs2 <= dv_vs1; + + dv_data<= dv_d2; + dv_de <= dv_de2; + dv_hs <= dv_hs2; + dv_vs <= dv_vs2; +end + +wire hdmi_tx_clk; +`ifndef MISTER_DEBUG_NOHDMI +cyclonev_clkselect hdmi_clk_sw +( + .clkselect({1'b1, ~vga_fb & direct_video}), + .inclk({clk_vid, hdmi_clk_out, 2'b00}), + .outclk(hdmi_tx_clk) +); +`else +assign hdmi_tx_clk = clk_vid; +`endif + +altddio_out +#( + .extend_oe_disable("OFF"), + .intended_device_family("Cyclone V"), + .invert_output("OFF"), + .lpm_hint("UNUSED"), + .lpm_type("altddio_out"), + .oe_reg("UNREGISTERED"), + .power_up_high("OFF"), + .width(1) +) +hdmiclk_ddr +( + .datain_h(1'b0), + .datain_l(1'b1), + .outclock(hdmi_tx_clk), + .dataout(HDMI_TX_CLK), + .aclr(1'b0), + .aset(1'b0), + .oe(1'b1), + .outclocken(1'b1), + .sclr(1'b0), + .sset(1'b0) +); + +reg hdmi_out_hs; +reg hdmi_out_vs; +reg hdmi_out_de; +reg [23:0] hdmi_out_d; + +always @(posedge hdmi_tx_clk) begin + reg [23:0] hdmi_dv_data; + reg hdmi_dv_hs, hdmi_dv_vs, hdmi_dv_de; + + reg hs,vs,de; + reg [23:0] d; + + hdmi_dv_data <= dv_data; + hdmi_dv_hs <= dv_hs; + hdmi_dv_vs <= dv_vs; + hdmi_dv_de <= dv_de; + + hs <= (~vga_fb & direct_video) ? hdmi_dv_hs : (direct_video & csync_en) ? hdmi_cs_osd : hdmi_hs_osd; + vs <= (~vga_fb & direct_video) ? hdmi_dv_vs : hdmi_vs_osd; + de <= (~vga_fb & direct_video) ? hdmi_dv_de : hdmi_de_osd; + d <= (~vga_fb & direct_video) ? hdmi_dv_data : hdmi_data_osd; + + hdmi_out_hs <= hs; + hdmi_out_vs <= vs; + hdmi_out_de <= de; + hdmi_out_d <= d; +end + +assign HDMI_TX_HS = hdmi_out_hs; +assign HDMI_TX_VS = hdmi_out_vs; +assign HDMI_TX_DE = hdmi_out_de; +assign HDMI_TX_D = hdmi_out_d; + +///////////////////////// VGA output ////////////////////////////////// + +wire [23:0] vga_data_sl; +wire vga_de_sl, vga_ce_sl, vga_vs_sl, vga_hs_sl; +scanlines #(0) VGA_scanlines +( + .clk(clk_vid), + + .scanlines(scanlines), + .din(de_emu ? {r_out, g_out, b_out} : 24'd0), + .hs_in(hs_fix), + .vs_in(vs_fix), + .de_in(de_emu), + .ce_in(ce_pix), + + .dout(vga_data_sl), + .hs_out(vga_hs_sl), + .vs_out(vga_vs_sl), + .de_out(vga_de_sl), + .ce_out(vga_ce_sl) +); + +wire [23:0] vga_data_osd; +wire vga_vs_osd, vga_hs_osd; +osd vga_osd +( + .clk_sys(clk_sys), + + .io_osd(io_osd_vga), + .io_strobe(io_strobe), + .io_din(io_din), + .osd_status(osd_status), + + .clk_video(clk_vid), + .din(vga_data_sl), + .hs_in(vga_hs_sl), + .vs_in(vga_vs_sl), + .de_in(vga_de_sl), + + .dout(vga_data_osd), + .hs_out(vga_hs_osd), + .vs_out(vga_vs_osd) +); + +wire vga_cs_osd; +csync csync_vga(clk_vid, vga_hs_osd, vga_vs_osd, vga_cs_osd); + +`ifndef MISTER_DUAL_SDRAM + wire [23:0] vgas_o; + wire vgas_hs, vgas_vs, vgas_cs; + vga_out vga_scaler_out + ( + .clk(clk_hdmi), + .ypbpr_en(ypbpr_en), + .hsync(hdmi_hs_osd), + .vsync(hdmi_vs_osd), + .csync(hdmi_cs_osd), + .dout(vgas_o), + .din({24{hdmi_de_osd}} & hdmi_data_osd), + .hsync_o(vgas_hs), + .vsync_o(vgas_vs), + .csync_o(vgas_cs) + ); + + wire [23:0] vga_o; + wire vga_hs, vga_vs, vga_cs; + vga_out vga_out + ( + .clk(clk_vid), + .ypbpr_en(ypbpr_en), + .hsync(vga_hs_osd), + .vsync(vga_vs_osd), + .csync(vga_cs_osd), + .dout(vga_o), + .din(vga_data_osd), + .hsync_o(vga_hs), + .vsync_o(vga_vs), + .csync_o(vga_cs) + ); + + wire cs1 = (vga_fb | vga_scaler) ? vgas_cs : vga_cs; + + assign VGA_VS = (VGA_EN | SW[3]) ? 1'bZ :((((vga_fb | vga_scaler) ? ~vgas_vs : ~vga_vs) | csync_en) ^ VS[12]); + assign VGA_HS = (VGA_EN | SW[3]) ? 1'bZ : (((vga_fb | vga_scaler) ? (csync_en ? ~vgas_cs : ~vgas_hs) : (csync_en ? ~vga_cs : ~vga_hs)) ^ HS[12]); + assign VGA_R = (VGA_EN | SW[3]) ? 6'bZZZZZZ : (vga_fb | vga_scaler) ? vgas_o[23:18] : vga_o[23:18]; + assign VGA_G = (VGA_EN | SW[3]) ? 6'bZZZZZZ : (vga_fb | vga_scaler) ? vgas_o[15:10] : vga_o[15:10]; + assign VGA_B = (VGA_EN | SW[3]) ? 6'bZZZZZZ : (vga_fb | vga_scaler) ? vgas_o[7:2] : vga_o[7:2] ; +`endif + +reg video_sync = 0; +always @(posedge clk_vid) begin + reg [11:0] line_cnt = 0; + reg [11:0] sync_line = 0; + reg [1:0] hs_cnt = 0; + reg old_hs; + + old_hs <= hs_fix; + if(~old_hs & hs_fix) begin + + video_sync <= (sync_line == line_cnt); + + line_cnt <= line_cnt + 1'd1; + if(~hs_cnt[1]) begin + hs_cnt <= hs_cnt + 1'd1; + if(hs_cnt[0]) begin + sync_line <= (line_cnt - vs_line); + line_cnt <= 0; + end + end + end + + if(de_emu) hs_cnt <= 0; +end + +///////////////////////// Audio output //////////////////////////////// + +assign SDCD_SPDIF =(SW[3] & ~spdif) ? 1'b0 : 1'bZ; + +`ifndef MISTER_DUAL_SDRAM + wire analog_l, analog_r; + + assign AUDIO_SPDIF = SW[3] ? 1'bZ : SW[0] ? HDMI_LRCLK : spdif; + assign AUDIO_R = SW[3] ? 1'bZ : SW[0] ? HDMI_I2S : analog_r; + assign AUDIO_L = SW[3] ? 1'bZ : SW[0] ? HDMI_SCLK : analog_l; +`endif + +assign HDMI_MCLK = clk_audio; +wire clk_audio; + +pll_audio pll_audio +( + .refclk(FPGA_CLK3_50), + .rst(0), + .outclk_0(clk_audio) +); + +wire spdif; +audio_out audio_out +( + .reset(reset | areset), + .clk(clk_audio), + + .att(vol_att), + .mix(audio_mix), + .sample_rate(audio_96k), + + .flt_rate(aflt_rate), + .cx(acx), + .cx0(acx0), + .cx1(acx1), + .cx2(acx2), + .cy0(acy0), + .cy1(acy1), + .cy2(acy2), + + .is_signed(audio_s), + .core_l(audio_l), + .core_r(audio_r), + + .alsa_l(alsa_l), + .alsa_r(alsa_r), + + .i2s_bclk(HDMI_SCLK), + .i2s_lrclk(HDMI_LRCLK), + .i2s_data(HDMI_I2S), +`ifndef MISTER_DUAL_SDRAM + .dac_l(analog_l), + .dac_r(analog_r), +`endif + .spdif(spdif) +); + + +wire [28:0] alsa_address; +wire [63:0] alsa_readdata; +wire alsa_ready; +wire alsa_req; +wire alsa_late; + +wire [15:0] alsa_l, alsa_r; + +alsa alsa +( + .reset(reset), + .clk(clk_audio), + + .ram_address(alsa_address), + .ram_data(alsa_readdata), + .ram_req(alsa_req), + .ram_ready(alsa_ready), + + .spi_ss(aspi_ss), + .spi_sck(aspi_sck), + .spi_mosi(aspi_mosi), + .spi_miso(aspi_miso), + + .pcm_l(alsa_l), + .pcm_r(alsa_r) +); + +//////////////// User I/O (USB 3.0 connector) ///////////////////////// + +assign USER_IO[0] = !user_out[0] ? 1'b0 : 1'bZ; +assign USER_IO[1] = !user_out[1] ? 1'b0 : 1'bZ; +assign USER_IO[2] = !(SW[1] ? HDMI_I2S : user_out[2]) ? 1'b0 : 1'bZ; +assign USER_IO[3] = !user_out[3] ? 1'b0 : 1'bZ; +assign USER_IO[4] = !(SW[1] ? HDMI_SCLK : user_out[4]) ? 1'b0 : 1'bZ; +assign USER_IO[5] = !(SW[1] ? HDMI_LRCLK : user_out[5]) ? 1'b0 : 1'bZ; +assign USER_IO[6] = !user_out[6] ? 1'b0 : 1'bZ; + +assign user_in[0] = USER_IO[0]; +assign user_in[1] = USER_IO[1]; +assign user_in[2] = SW[1] | USER_IO[2]; +assign user_in[3] = USER_IO[3]; +assign user_in[4] = SW[1] | USER_IO[4]; +assign user_in[5] = SW[1] | USER_IO[5]; +assign user_in[6] = USER_IO[6]; + + +/////////////////// User module connection //////////////////////////// + +wire clk_sys; +wire [15:0] audio_l, audio_r; +wire audio_s; +wire [1:0] audio_mix; +wire [1:0] scanlines; +wire [7:0] r_out, g_out, b_out, hr_out, hg_out, hb_out; +wire vs_fix, hs_fix, de_emu, vs_emu, hs_emu, f1; +wire hvs_fix, hhs_fix, hde_emu; +wire clk_vid, ce_pix, clk_ihdmi, ce_hpix; +wire vga_force_scaler; + +wire ram_clk; +wire [28:0] ram_address; +wire [7:0] ram_burstcount; +wire ram_waitrequest; +wire [63:0] ram_readdata; +wire ram_readdatavalid; +wire ram_read; +wire [63:0] ram_writedata; +wire [7:0] ram_byteenable; +wire ram_write; + +wire led_user; +wire [1:0] led_power; +wire [1:0] led_disk; +wire [1:0] btn; + +sync_fix sync_v(clk_vid, vs_emu, vs_fix); +sync_fix sync_h(clk_vid, hs_emu, hs_fix); + +wire [6:0] user_out, user_in; + +assign clk_ihdmi= clk_vid; +assign ce_hpix = vga_ce_sl; +assign hr_out = vga_data_sl[23:16]; +assign hg_out = vga_data_sl[15:8]; +assign hb_out = vga_data_sl[7:0]; +assign hhs_fix = vga_hs_sl; +assign hvs_fix = vga_vs_sl; +assign hde_emu = vga_de_sl; + +wire uart_dtr; +wire uart_dsr; +wire uart_cts; +wire uart_rts; +wire uart_rxd; +wire uart_txd; + +wire osd_status; + +wire fb_en; +wire [4:0] fb_fmt; +wire [11:0] fb_width; +wire [11:0] fb_height; +wire [31:0] fb_base; +wire [13:0] fb_stride; + + +`ifdef MISTER_FB + `ifdef MISTER_FB_PALETTE + wire fb_pal_clk; + wire [7:0] fb_pal_a; + wire [23:0] fb_pal_d; + wire [23:0] fb_pal_q; + wire fb_pal_wr; + `endif + wire fb_force_blank; +`else + assign fb_en = 0; + assign fb_fmt = 0; + assign fb_width = 0; + assign fb_height = 0; + assign fb_base = 0; + assign fb_stride = 0; +`endif + +reg [1:0] sl_r; +wire [1:0] sl = sl_r; +always @(posedge clk_sys) sl_r <= FB_EN ? 2'b00 : scanlines; + +emu emu +( + .CLK_50M(FPGA_CLK2_50), + .RESET(reset), + .HPS_BUS({fb_en, sl, f1, HDMI_TX_VS, + clk_100m, clk_ihdmi, + ce_hpix, hde_emu, hhs_fix, hvs_fix, + io_wait, clk_sys, io_fpga, io_uio, io_strobe, io_wide, io_din, io_dout}), + + .VGA_R(r_out), + .VGA_G(g_out), + .VGA_B(b_out), + .VGA_HS(hs_emu), + .VGA_VS(vs_emu), + .VGA_DE(de_emu), + .VGA_F1(f1), + .VGA_SCALER(vga_force_scaler), + + .HDMI_WIDTH(direct_video ? 12'd0 : hdmi_width), + .HDMI_HEIGHT(direct_video ? 12'd0 : hdmi_height), + .HDMI_FREEZE(freeze), + + .CLK_VIDEO(clk_vid), + .CE_PIXEL(ce_pix), + .VGA_SL(scanlines), + .VIDEO_ARX(ARX), + .VIDEO_ARY(ARY), + +`ifdef MISTER_FB + .FB_EN(fb_en), + .FB_FORMAT(fb_fmt), + .FB_WIDTH(fb_width), + .FB_HEIGHT(fb_height), + .FB_BASE(fb_base), + .FB_STRIDE(fb_stride), + .FB_VBL(fb_vbl), + .FB_LL(lowlat), + .FB_FORCE_BLANK(fb_force_blank), + +`ifdef MISTER_FB_PALETTE + .FB_PAL_CLK (fb_pal_clk), + .FB_PAL_ADDR(fb_pal_a), + .FB_PAL_DOUT(fb_pal_d), + .FB_PAL_DIN (fb_pal_q), + .FB_PAL_WR (fb_pal_wr), +`endif + +`endif + + .LED_USER(led_user), + .LED_POWER(led_power), + .LED_DISK(led_disk), + + .CLK_AUDIO(clk_audio), + .AUDIO_L(audio_l), + .AUDIO_R(audio_r), + .AUDIO_S(audio_s), + .AUDIO_MIX(audio_mix), + + .ADC_BUS({ADC_SCK,ADC_SDO,ADC_SDI,ADC_CONVST}), + + .DDRAM_CLK(ram_clk), + .DDRAM_ADDR(ram_address), + .DDRAM_BURSTCNT(ram_burstcount), + .DDRAM_BUSY(ram_waitrequest), + .DDRAM_DOUT(ram_readdata), + .DDRAM_DOUT_READY(ram_readdatavalid), + .DDRAM_RD(ram_read), + .DDRAM_DIN(ram_writedata), + .DDRAM_BE(ram_byteenable), + .DDRAM_WE(ram_write), + + .SDRAM_DQ(SDRAM_DQ), + .SDRAM_A(SDRAM_A), + .SDRAM_DQML(SDRAM_DQML), + .SDRAM_DQMH(SDRAM_DQMH), + .SDRAM_BA(SDRAM_BA), + .SDRAM_nCS(SDRAM_nCS), + .SDRAM_nWE(SDRAM_nWE), + .SDRAM_nRAS(SDRAM_nRAS), + .SDRAM_nCAS(SDRAM_nCAS), + .SDRAM_CLK(SDRAM_CLK), + .SDRAM_CKE(SDRAM_CKE), + +`ifdef MISTER_DUAL_SDRAM + .SDRAM2_DQ(SDRAM2_DQ), + .SDRAM2_A(SDRAM2_A), + .SDRAM2_BA(SDRAM2_BA), + .SDRAM2_nCS(SDRAM2_nCS), + .SDRAM2_nWE(SDRAM2_nWE), + .SDRAM2_nRAS(SDRAM2_nRAS), + .SDRAM2_nCAS(SDRAM2_nCAS), + .SDRAM2_CLK(SDRAM2_CLK), + .SDRAM2_EN(SW[3]), +`endif + + .BUTTONS(btn), + .OSD_STATUS(osd_status), + + .SD_SCK(SD_CLK), + .SD_MOSI(SD_MOSI), + .SD_MISO(SD_MISO), + .SD_CS(SD_CS), +`ifdef MISTER_DUAL_SDRAM + .SD_CD(mcp_sdcd), +`else + .SD_CD(mcp_sdcd & (SW[0] ? VGA_HS : (SW[3] | SDCD_SPDIF))), +`endif + + .UART_CTS(uart_rts), + .UART_RTS(uart_cts), + .UART_RXD(uart_txd), + .UART_TXD(uart_rxd), + .UART_DTR(uart_dsr), + .UART_DSR(uart_dtr), + + .USER_OUT(user_out), + .USER_IN(user_in) +); + +endmodule + +///////////////////////////////////////////////////////////////////// + +module sync_fix +( + input clk, + + input sync_in, + output sync_out +); + +assign sync_out = sync_in ^ pol; + +reg pol; +always @(posedge clk) begin + integer pos = 0, neg = 0, cnt = 0; + reg s1,s2; + + s1 <= sync_in; + s2 <= s1; + + if(~s2 & s1) neg <= cnt; + if(s2 & ~s1) pos <= cnt; + + cnt <= cnt + 1; + if(s2 != s1) cnt <= 0; + + pol <= pos > neg; +end + +endmodule + +///////////////////////////////////////////////////////////////////// + +// CSync generation +// Shifts HSync left by 1 HSync period during VSync + +module csync +( + input clk, + input hsync, + input vsync, + + output csync +); + +assign csync = (csync_vs ^ csync_hs); + +reg csync_hs, csync_vs; +always @(posedge clk) begin + reg prev_hs; + reg [15:0] h_cnt, line_len, hs_len; + + // Count line/Hsync length + h_cnt <= h_cnt + 1'd1; + + prev_hs <= hsync; + if (prev_hs ^ hsync) begin + h_cnt <= 0; + if (hsync) begin + line_len <= h_cnt - hs_len; + csync_hs <= 0; + end + else hs_len <= h_cnt; + end + + if (~vsync) csync_hs <= hsync; + else if(h_cnt == line_len) csync_hs <= 1; + + csync_vs <= vsync; +end + +endmodule diff --git a/sys/sysmem.sv b/sys/sysmem.sv new file mode 100644 index 0000000..8c17e86 --- /dev/null +++ b/sys/sysmem.sv @@ -0,0 +1,570 @@ +`timescale 1 ps / 1 ps +module sysmem_lite +( + output clock, + output reset_out, + + input reset_hps_cold_req, + input reset_hps_warm_req, + input reset_core_req, + + input ram1_clk, + input [28:0] ram1_address, + input [7:0] ram1_burstcount, + output ram1_waitrequest, + output [63:0] ram1_readdata, + output ram1_readdatavalid, + input ram1_read, + input [63:0] ram1_writedata, + input [7:0] ram1_byteenable, + input ram1_write, + + input ram2_clk, + input [28:0] ram2_address, + input [7:0] ram2_burstcount, + output ram2_waitrequest, + output [63:0] ram2_readdata, + output ram2_readdatavalid, + input ram2_read, + input [63:0] ram2_writedata, + input [7:0] ram2_byteenable, + input ram2_write, + + input vbuf_clk, + input [27:0] vbuf_address, + input [7:0] vbuf_burstcount, + output vbuf_waitrequest, + output [127:0] vbuf_readdata, + output vbuf_readdatavalid, + input vbuf_read, + input [127:0] vbuf_writedata, + input [15:0] vbuf_byteenable, + input vbuf_write +); + +assign reset_out = ~init_reset_n | ~hps_h2f_reset_n | reset_core_req; + +//////////////////////////////////////////////////////// +//// f2sdram_safe_terminator_ram1 //// +//////////////////////////////////////////////////////// +wire [28:0] f2h_ram1_address; +wire [7:0] f2h_ram1_burstcount; +wire f2h_ram1_waitrequest; +wire [63:0] f2h_ram1_readdata; +wire f2h_ram1_readdatavalid; +wire f2h_ram1_read; +wire [63:0] f2h_ram1_writedata; +wire [7:0] f2h_ram1_byteenable; +wire f2h_ram1_write; + +(* altera_attribute = {"-name SYNCHRONIZER_IDENTIFICATION FORCED_IF_ASYNCHRONOUS"} *) reg ram1_reset_0 = 1'b1; +(* altera_attribute = {"-name SYNCHRONIZER_IDENTIFICATION FORCED_IF_ASYNCHRONOUS"} *) reg ram1_reset_1 = 1'b1; +always @(posedge ram1_clk) begin + ram1_reset_0 <= reset_out; + ram1_reset_1 <= ram1_reset_0; +end + +f2sdram_safe_terminator #(64, 8) f2sdram_safe_terminator_ram1 +( + .clk (ram1_clk), + .rst_req_sync (ram1_reset_1), + + .waitrequest_slave (ram1_waitrequest), + .burstcount_slave (ram1_burstcount), + .address_slave (ram1_address), + .readdata_slave (ram1_readdata), + .readdatavalid_slave (ram1_readdatavalid), + .read_slave (ram1_read), + .writedata_slave (ram1_writedata), + .byteenable_slave (ram1_byteenable), + .write_slave (ram1_write), + + .waitrequest_master (f2h_ram1_waitrequest), + .burstcount_master (f2h_ram1_burstcount), + .address_master (f2h_ram1_address), + .readdata_master (f2h_ram1_readdata), + .readdatavalid_master (f2h_ram1_readdatavalid), + .read_master (f2h_ram1_read), + .writedata_master (f2h_ram1_writedata), + .byteenable_master (f2h_ram1_byteenable), + .write_master (f2h_ram1_write) +); + +//////////////////////////////////////////////////////// +//// f2sdram_safe_terminator_ram2 //// +//////////////////////////////////////////////////////// +wire [28:0] f2h_ram2_address; +wire [7:0] f2h_ram2_burstcount; +wire f2h_ram2_waitrequest; +wire [63:0] f2h_ram2_readdata; +wire f2h_ram2_readdatavalid; +wire f2h_ram2_read; +wire [63:0] f2h_ram2_writedata; +wire [7:0] f2h_ram2_byteenable; +wire f2h_ram2_write; + +(* altera_attribute = {"-name SYNCHRONIZER_IDENTIFICATION FORCED_IF_ASYNCHRONOUS"} *) reg ram2_reset_0 = 1'b1; +(* altera_attribute = {"-name SYNCHRONIZER_IDENTIFICATION FORCED_IF_ASYNCHRONOUS"} *) reg ram2_reset_1 = 1'b1; +always @(posedge ram2_clk) begin + ram2_reset_0 <= reset_out; + ram2_reset_1 <= ram2_reset_0; +end + +f2sdram_safe_terminator #(64, 8) f2sdram_safe_terminator_ram2 +( + .clk (ram2_clk), + .rst_req_sync (ram2_reset_1), + + .waitrequest_slave (ram2_waitrequest), + .burstcount_slave (ram2_burstcount), + .address_slave (ram2_address), + .readdata_slave (ram2_readdata), + .readdatavalid_slave (ram2_readdatavalid), + .read_slave (ram2_read), + .writedata_slave (ram2_writedata), + .byteenable_slave (ram2_byteenable), + .write_slave (ram2_write), + + .waitrequest_master (f2h_ram2_waitrequest), + .burstcount_master (f2h_ram2_burstcount), + .address_master (f2h_ram2_address), + .readdata_master (f2h_ram2_readdata), + .readdatavalid_master (f2h_ram2_readdatavalid), + .read_master (f2h_ram2_read), + .writedata_master (f2h_ram2_writedata), + .byteenable_master (f2h_ram2_byteenable), + .write_master (f2h_ram2_write) +); + +//////////////////////////////////////////////////////// +//// f2sdram_safe_terminator_vbuf //// +//////////////////////////////////////////////////////// +wire [27:0] f2h_vbuf_address; +wire [7:0] f2h_vbuf_burstcount; +wire f2h_vbuf_waitrequest; +wire [127:0] f2h_vbuf_readdata; +wire f2h_vbuf_readdatavalid; +wire f2h_vbuf_read; +wire [127:0] f2h_vbuf_writedata; +wire [15:0] f2h_vbuf_byteenable; +wire f2h_vbuf_write; + +(* altera_attribute = {"-name SYNCHRONIZER_IDENTIFICATION FORCED_IF_ASYNCHRONOUS"} *) reg vbuf_reset_0 = 1'b1; +(* altera_attribute = {"-name SYNCHRONIZER_IDENTIFICATION FORCED_IF_ASYNCHRONOUS"} *) reg vbuf_reset_1 = 1'b1; +always @(posedge vbuf_clk) begin + vbuf_reset_0 <= reset_out; + vbuf_reset_1 <= vbuf_reset_0; +end + +f2sdram_safe_terminator #(128, 8) f2sdram_safe_terminator_vbuf +( + .clk (vbuf_clk), + .rst_req_sync (vbuf_reset_1), + + .waitrequest_slave (vbuf_waitrequest), + .burstcount_slave (vbuf_burstcount), + .address_slave (vbuf_address), + .readdata_slave (vbuf_readdata), + .readdatavalid_slave (vbuf_readdatavalid), + .read_slave (vbuf_read), + .writedata_slave (vbuf_writedata), + .byteenable_slave (vbuf_byteenable), + .write_slave (vbuf_write), + + .waitrequest_master (f2h_vbuf_waitrequest), + .burstcount_master (f2h_vbuf_burstcount), + .address_master (f2h_vbuf_address), + .readdata_master (f2h_vbuf_readdata), + .readdatavalid_master (f2h_vbuf_readdatavalid), + .read_master (f2h_vbuf_read), + .writedata_master (f2h_vbuf_writedata), + .byteenable_master (f2h_vbuf_byteenable), + .write_master (f2h_vbuf_write) +); + +//////////////////////////////////////////////////////// +//// HPS <> FPGA interfaces //// +//////////////////////////////////////////////////////// +sysmem_HPS_fpga_interfaces fpga_interfaces ( + .f2h_cold_rst_req_n (~reset_hps_cold_req), + .f2h_warm_rst_req_n (~reset_hps_warm_req), + .h2f_user0_clk (clock), + .h2f_rst_n (hps_h2f_reset_n), + .f2h_sdram0_clk (vbuf_clk), + .f2h_sdram0_ADDRESS (f2h_vbuf_address), + .f2h_sdram0_BURSTCOUNT (f2h_vbuf_burstcount), + .f2h_sdram0_WAITREQUEST (f2h_vbuf_waitrequest), + .f2h_sdram0_READDATA (f2h_vbuf_readdata), + .f2h_sdram0_READDATAVALID (f2h_vbuf_readdatavalid), + .f2h_sdram0_READ (f2h_vbuf_read), + .f2h_sdram0_WRITEDATA (f2h_vbuf_writedata), + .f2h_sdram0_BYTEENABLE (f2h_vbuf_byteenable), + .f2h_sdram0_WRITE (f2h_vbuf_write), + .f2h_sdram1_clk (ram1_clk), + .f2h_sdram1_ADDRESS (f2h_ram1_address), + .f2h_sdram1_BURSTCOUNT (f2h_ram1_burstcount), + .f2h_sdram1_WAITREQUEST (f2h_ram1_waitrequest), + .f2h_sdram1_READDATA (f2h_ram1_readdata), + .f2h_sdram1_READDATAVALID (f2h_ram1_readdatavalid), + .f2h_sdram1_READ (f2h_ram1_read), + .f2h_sdram1_WRITEDATA (f2h_ram1_writedata), + .f2h_sdram1_BYTEENABLE (f2h_ram1_byteenable), + .f2h_sdram1_WRITE (f2h_ram1_write), + .f2h_sdram2_clk (ram2_clk), + .f2h_sdram2_ADDRESS (f2h_ram2_address), + .f2h_sdram2_BURSTCOUNT (f2h_ram2_burstcount), + .f2h_sdram2_WAITREQUEST (f2h_ram2_waitrequest), + .f2h_sdram2_READDATA (f2h_ram2_readdata), + .f2h_sdram2_READDATAVALID (f2h_ram2_readdatavalid), + .f2h_sdram2_READ (f2h_ram2_read), + .f2h_sdram2_WRITEDATA (f2h_ram2_writedata), + .f2h_sdram2_BYTEENABLE (f2h_ram2_byteenable), + .f2h_sdram2_WRITE (f2h_ram2_write) +); + +wire hps_h2f_reset_n; + +reg init_reset_n = 0; +always @(posedge clock) begin + integer timeout = 0; + + if(timeout < 2000000) begin + init_reset_n <= 0; + timeout <= timeout + 1; + end + else init_reset_n <= 1; +end + +endmodule + + +module sysmem_HPS_fpga_interfaces +( + // h2f_reset + output wire [1 - 1 : 0 ] h2f_rst_n + + // f2h_cold_reset_req + ,input wire [1 - 1 : 0 ] f2h_cold_rst_req_n + + // f2h_warm_reset_req + ,input wire [1 - 1 : 0 ] f2h_warm_rst_req_n + + // h2f_user0_clock + ,output wire [1 - 1 : 0 ] h2f_user0_clk + + // f2h_sdram0_data + ,input wire [28 - 1 : 0 ] f2h_sdram0_ADDRESS + ,input wire [8 - 1 : 0 ] f2h_sdram0_BURSTCOUNT + ,output wire [1 - 1 : 0 ] f2h_sdram0_WAITREQUEST + ,output wire [128 - 1 : 0 ] f2h_sdram0_READDATA + ,output wire [1 - 1 : 0 ] f2h_sdram0_READDATAVALID + ,input wire [1 - 1 : 0 ] f2h_sdram0_READ + ,input wire [128 - 1 : 0 ] f2h_sdram0_WRITEDATA + ,input wire [16 - 1 : 0 ] f2h_sdram0_BYTEENABLE + ,input wire [1 - 1 : 0 ] f2h_sdram0_WRITE + + // f2h_sdram0_clock + ,input wire [1 - 1 : 0 ] f2h_sdram0_clk + + // f2h_sdram1_data + ,input wire [29 - 1 : 0 ] f2h_sdram1_ADDRESS + ,input wire [8 - 1 : 0 ] f2h_sdram1_BURSTCOUNT + ,output wire [1 - 1 : 0 ] f2h_sdram1_WAITREQUEST + ,output wire [64 - 1 : 0 ] f2h_sdram1_READDATA + ,output wire [1 - 1 : 0 ] f2h_sdram1_READDATAVALID + ,input wire [1 - 1 : 0 ] f2h_sdram1_READ + ,input wire [64 - 1 : 0 ] f2h_sdram1_WRITEDATA + ,input wire [8 - 1 : 0 ] f2h_sdram1_BYTEENABLE + ,input wire [1 - 1 : 0 ] f2h_sdram1_WRITE + + // f2h_sdram1_clock + ,input wire [1 - 1 : 0 ] f2h_sdram1_clk + + // f2h_sdram2_data + ,input wire [29 - 1 : 0 ] f2h_sdram2_ADDRESS + ,input wire [8 - 1 : 0 ] f2h_sdram2_BURSTCOUNT + ,output wire [1 - 1 : 0 ] f2h_sdram2_WAITREQUEST + ,output wire [64 - 1 : 0 ] f2h_sdram2_READDATA + ,output wire [1 - 1 : 0 ] f2h_sdram2_READDATAVALID + ,input wire [1 - 1 : 0 ] f2h_sdram2_READ + ,input wire [64 - 1 : 0 ] f2h_sdram2_WRITEDATA + ,input wire [8 - 1 : 0 ] f2h_sdram2_BYTEENABLE + ,input wire [1 - 1 : 0 ] f2h_sdram2_WRITE + + // f2h_sdram2_clock + ,input wire [1 - 1 : 0 ] f2h_sdram2_clk +); + + +wire [29 - 1 : 0] intermediate; +assign intermediate[0:0] = ~intermediate[1:1]; +assign intermediate[8:8] = intermediate[4:4]|intermediate[7:7]; +assign intermediate[2:2] = intermediate[9:9]; +assign intermediate[3:3] = intermediate[9:9]; +assign intermediate[5:5] = intermediate[9:9]; +assign intermediate[6:6] = intermediate[9:9]; +assign intermediate[10:10] = intermediate[9:9]; +assign intermediate[11:11] = ~intermediate[12:12]; +assign intermediate[17:17] = intermediate[14:14]|intermediate[16:16]; +assign intermediate[13:13] = intermediate[18:18]; +assign intermediate[15:15] = intermediate[18:18]; +assign intermediate[19:19] = intermediate[18:18]; +assign intermediate[20:20] = ~intermediate[21:21]; +assign intermediate[26:26] = intermediate[23:23]|intermediate[25:25]; +assign intermediate[22:22] = intermediate[27:27]; +assign intermediate[24:24] = intermediate[27:27]; +assign intermediate[28:28] = intermediate[27:27]; +assign f2h_sdram0_WAITREQUEST[0:0] = intermediate[0:0]; +assign f2h_sdram1_WAITREQUEST[0:0] = intermediate[11:11]; +assign f2h_sdram2_WAITREQUEST[0:0] = intermediate[20:20]; +assign intermediate[4:4] = f2h_sdram0_READ[0:0]; +assign intermediate[7:7] = f2h_sdram0_WRITE[0:0]; +assign intermediate[9:9] = f2h_sdram0_clk[0:0]; +assign intermediate[14:14] = f2h_sdram1_READ[0:0]; +assign intermediate[16:16] = f2h_sdram1_WRITE[0:0]; +assign intermediate[18:18] = f2h_sdram1_clk[0:0]; +assign intermediate[23:23] = f2h_sdram2_READ[0:0]; +assign intermediate[25:25] = f2h_sdram2_WRITE[0:0]; +assign intermediate[27:27] = f2h_sdram2_clk[0:0]; + +cyclonev_hps_interface_clocks_resets clocks_resets( + .f2h_warm_rst_req_n({ + f2h_warm_rst_req_n[0:0] // 0:0 + }) +,.f2h_pending_rst_ack({ + 1'b1 // 0:0 + }) +,.f2h_dbg_rst_req_n({ + 1'b1 // 0:0 + }) +,.h2f_rst_n({ + h2f_rst_n[0:0] // 0:0 + }) +,.f2h_cold_rst_req_n({ + f2h_cold_rst_req_n[0:0] // 0:0 + }) +,.h2f_user0_clk({ + h2f_user0_clk[0:0] // 0:0 + }) +); + + +cyclonev_hps_interface_dbg_apb debug_apb( + .DBG_APB_DISABLE({ + 1'b0 // 0:0 + }) +,.P_CLK_EN({ + 1'b0 // 0:0 + }) +); + + +cyclonev_hps_interface_tpiu_trace tpiu( + .traceclk_ctl({ + 1'b1 // 0:0 + }) +); + + +cyclonev_hps_interface_boot_from_fpga boot_from_fpga( + .boot_from_fpga_ready({ + 1'b0 // 0:0 + }) +,.boot_from_fpga_on_failure({ + 1'b0 // 0:0 + }) +,.bsel_en({ + 1'b0 // 0:0 + }) +,.csel_en({ + 1'b0 // 0:0 + }) +,.csel({ + 2'b01 // 1:0 + }) +,.bsel({ + 3'b001 // 2:0 + }) +); + + +cyclonev_hps_interface_fpga2hps fpga2hps( + .port_size_config({ + 2'b11 // 1:0 + }) +); + + +cyclonev_hps_interface_hps2fpga hps2fpga( + .port_size_config({ + 2'b11 // 1:0 + }) +); + + +cyclonev_hps_interface_fpga2sdram f2sdram( + .cfg_rfifo_cport_map({ + 16'b0010000100000000 // 15:0 + }) +,.cfg_wfifo_cport_map({ + 16'b0010000100000000 // 15:0 + }) +,.rd_ready_3({ + 1'b1 // 0:0 + }) +,.cmd_port_clk_2({ + intermediate[28:28] // 0:0 + }) +,.rd_ready_2({ + 1'b1 // 0:0 + }) +,.cmd_port_clk_1({ + intermediate[19:19] // 0:0 + }) +,.rd_ready_1({ + 1'b1 // 0:0 + }) +,.cmd_port_clk_0({ + intermediate[10:10] // 0:0 + }) +,.rd_ready_0({ + 1'b1 // 0:0 + }) +,.wrack_ready_2({ + 1'b1 // 0:0 + }) +,.wrack_ready_1({ + 1'b1 // 0:0 + }) +,.wrack_ready_0({ + 1'b1 // 0:0 + }) +,.cmd_ready_2({ + intermediate[21:21] // 0:0 + }) +,.cmd_ready_1({ + intermediate[12:12] // 0:0 + }) +,.cmd_ready_0({ + intermediate[1:1] // 0:0 + }) +,.cfg_port_width({ + 12'b000000010110 // 11:0 + }) +,.rd_valid_3({ + f2h_sdram2_READDATAVALID[0:0] // 0:0 + }) +,.rd_valid_2({ + f2h_sdram1_READDATAVALID[0:0] // 0:0 + }) +,.rd_valid_1({ + f2h_sdram0_READDATAVALID[0:0] // 0:0 + }) +,.rd_clk_3({ + intermediate[22:22] // 0:0 + }) +,.rd_data_3({ + f2h_sdram2_READDATA[63:0] // 63:0 + }) +,.rd_clk_2({ + intermediate[13:13] // 0:0 + }) +,.rd_data_2({ + f2h_sdram1_READDATA[63:0] // 63:0 + }) +,.rd_clk_1({ + intermediate[3:3] // 0:0 + }) +,.rd_data_1({ + f2h_sdram0_READDATA[127:64] // 63:0 + }) +,.rd_clk_0({ + intermediate[2:2] // 0:0 + }) +,.rd_data_0({ + f2h_sdram0_READDATA[63:0] // 63:0 + }) +,.cfg_axi_mm_select({ + 6'b000000 // 5:0 + }) +,.cmd_valid_2({ + intermediate[26:26] // 0:0 + }) +,.cmd_valid_1({ + intermediate[17:17] // 0:0 + }) +,.cmd_valid_0({ + intermediate[8:8] // 0:0 + }) +,.cfg_cport_rfifo_map({ + 18'b000000000011010000 // 17:0 + }) +,.wr_data_3({ + 2'b00 // 89:88 + ,f2h_sdram2_BYTEENABLE[7:0] // 87:80 + ,16'b0000000000000000 // 79:64 + ,f2h_sdram2_WRITEDATA[63:0] // 63:0 + }) +,.wr_data_2({ + 2'b00 // 89:88 + ,f2h_sdram1_BYTEENABLE[7:0] // 87:80 + ,16'b0000000000000000 // 79:64 + ,f2h_sdram1_WRITEDATA[63:0] // 63:0 + }) +,.wr_data_1({ + 2'b00 // 89:88 + ,f2h_sdram0_BYTEENABLE[15:8] // 87:80 + ,16'b0000000000000000 // 79:64 + ,f2h_sdram0_WRITEDATA[127:64] // 63:0 + }) +,.cfg_cport_type({ + 12'b000000111111 // 11:0 + }) +,.wr_data_0({ + 2'b00 // 89:88 + ,f2h_sdram0_BYTEENABLE[7:0] // 87:80 + ,16'b0000000000000000 // 79:64 + ,f2h_sdram0_WRITEDATA[63:0] // 63:0 + }) +,.cfg_cport_wfifo_map({ + 18'b000000000011010000 // 17:0 + }) +,.wr_clk_3({ + intermediate[24:24] // 0:0 + }) +,.wr_clk_2({ + intermediate[15:15] // 0:0 + }) +,.wr_clk_1({ + intermediate[6:6] // 0:0 + }) +,.wr_clk_0({ + intermediate[5:5] // 0:0 + }) +,.cmd_data_2({ + 18'b000000000000000000 // 59:42 + ,f2h_sdram2_BURSTCOUNT[7:0] // 41:34 + ,3'b000 // 33:31 + ,f2h_sdram2_ADDRESS[28:0] // 30:2 + ,intermediate[25:25] // 1:1 + ,intermediate[23:23] // 0:0 + }) +,.cmd_data_1({ + 18'b000000000000000000 // 59:42 + ,f2h_sdram1_BURSTCOUNT[7:0] // 41:34 + ,3'b000 // 33:31 + ,f2h_sdram1_ADDRESS[28:0] // 30:2 + ,intermediate[16:16] // 1:1 + ,intermediate[14:14] // 0:0 + }) +,.cmd_data_0({ + 18'b000000000000000000 // 59:42 + ,f2h_sdram0_BURSTCOUNT[7:0] // 41:34 + ,4'b0000 // 33:30 + ,f2h_sdram0_ADDRESS[27:0] // 29:2 + ,intermediate[7:7] // 1:1 + ,intermediate[4:4] // 0:0 + }) +); + +endmodule diff --git a/sys/vga_out.sv b/sys/vga_out.sv new file mode 100644 index 0000000..fe8172b --- /dev/null +++ b/sys/vga_out.sv @@ -0,0 +1,68 @@ + +module vga_out +( + input clk, + input ypbpr_en, + + input hsync, + input vsync, + input csync, + + input [23:0] din, + output [23:0] dout, + + output reg hsync_o, + output reg vsync_o, + output reg csync_o +); + +wire [5:0] red = din[23:18]; +wire [5:0] green = din[15:10]; +wire [5:0] blue = din[7:2]; + +// http://marsee101.blog19.fc2.com/blog-entry-2311.html +// Y = 16 + 0.257*R + 0.504*G + 0.098*B (Y = 0.299*R + 0.587*G + 0.114*B) +// Pb = 128 - 0.148*R - 0.291*G + 0.439*B (Pb = -0.169*R - 0.331*G + 0.500*B) +// Pr = 128 + 0.439*R - 0.368*G - 0.071*B (Pr = 0.500*R - 0.419*G - 0.081*B) + +reg [7:0] y, pb, pr; +reg [23:0] rgb; +always @(posedge clk) begin + reg [18:0] y_1r, pb_1r, pr_1r; + reg [18:0] y_1g, pb_1g, pr_1g; + reg [18:0] y_1b, pb_1b, pr_1b; + reg [18:0] y_2, pb_2, pr_2; + reg [23:0] din1, din2; + reg hsync2, vsync2, csync2; + reg hsync1, vsync1, csync1; + + y_1r <= 19'd04096 + ({red, 8'd0} + {red, 3'd0}); + pb_1r <= 19'd32768 - ({red, 7'd0} + {red, 4'd0} + {red, 3'd0}); + pr_1r <= 19'd32768 + ({red, 8'd0} + {red, 7'd0} + {red, 6'd0}); + + y_1g <= {green, 9'd0} + {green, 2'd0}; + pb_1g <= {green, 8'd0} + {green, 5'd0} + {green, 3'd0}; + pr_1g <= {green, 8'd0} + {green, 6'd0} + {green, 5'd0} + {green, 4'd0} + {green, 3'd0}; + + y_1b <= {blue, 6'd0} + {blue, 5'd0} + {blue, 2'd0}; + pb_1b <= {blue, 8'd0} + {blue, 7'd0} + {blue, 6'd0}; + pr_1b <= {blue, 6'd0} + {blue, 3'd0}; + + y_2 <= y_1r + y_1g + y_1b; + pb_2 <= pb_1r - pb_1g + pb_1b; + pr_2 <= pr_1r - pr_1g - pr_1b; + + y <= ( y_2[18] || !y_2[17:12]) ? 8'd16 : (y_2[17:8] > 235) ? 8'd235 : y_2[15:8]; + pb <= (pb_2[18] || !pb_2[17:12]) ? 8'd16 : (&pb_2[17:12]) ? 8'd240 : pb_2[15:8]; + pr <= (pr_2[18] || !pr_2[17:12]) ? 8'd16 : (&pr_2[17:12]) ? 8'd240 : pr_2[15:8]; + + hsync_o <= hsync2; hsync2 <= hsync1; hsync1 <= hsync; + vsync_o <= vsync2; vsync2 <= vsync1; vsync1 <= vsync; + csync_o <= csync2; csync2 <= csync1; csync1 <= csync; + + rgb <= din2; din2 <= din1; din1 <= din; +end + +assign dout = ypbpr_en ? {pr, y, pb} : rgb; + +endmodule diff --git a/sys/video_cleaner.sv b/sys/video_cleaner.sv new file mode 100644 index 0000000..a99894c --- /dev/null +++ b/sys/video_cleaner.sv @@ -0,0 +1,99 @@ +// +// +// Copyright (c) 2018 Sorgelig +// +// This program is GPL Licensed. See COPYING for the full license. +// +// +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +`timescale 1ns / 1ps + +module video_cleaner +( + input clk_vid, + input ce_pix, + + input [7:0] R, + input [7:0] G, + input [7:0] B, + + input HSync, + input VSync, + input HBlank, + input VBlank, + + //optional de + input DE_in, + + // video output signals + output reg [7:0] VGA_R, + output reg [7:0] VGA_G, + output reg [7:0] VGA_B, + output reg VGA_VS, + output reg VGA_HS, + output VGA_DE, + + // optional aligned blank + output reg HBlank_out, + output reg VBlank_out, + + // optional aligned de + output reg DE_out +); + +wire hs, vs; +s_fix sync_v(clk_vid, HSync, hs); +s_fix sync_h(clk_vid, VSync, vs); + +wire hbl = hs | HBlank; +wire vbl = vs | VBlank; + +assign VGA_DE = ~(HBlank_out | VBlank_out); + +always @(posedge clk_vid) begin + if(ce_pix) begin + HBlank_out <= hbl; + + VGA_HS <= hs; + if(~VGA_HS & hs) VGA_VS <= vs; + + VGA_R <= R; + VGA_G <= G; + VGA_B <= B; + DE_out <= DE_in; + + if(HBlank_out & ~hbl) VBlank_out <= vbl; + end +end + +endmodule + +module s_fix +( + input clk, + + input sync_in, + output sync_out +); + +assign sync_out = sync_in ^ pol; + +reg pol; +always @(posedge clk) begin + integer pos = 0, neg = 0, cnt = 0; + reg s1,s2; + + s1 <= sync_in; + s2 <= s1; + + if(~s2 & s1) neg <= cnt; + if(s2 & ~s1) pos <= cnt; + + cnt <= cnt + 1; + if(s2 != s1) cnt <= 0; + + pol <= pos > neg; +end + +endmodule diff --git a/sys/video_freak.sv b/sys/video_freak.sv new file mode 100644 index 0000000..d542ae7 --- /dev/null +++ b/sys/video_freak.sv @@ -0,0 +1,278 @@ +// +// +// Video crop +// Copyright (c) 2020 Grabulosaure, (c) 2021 Alexey Melnikov +// +// Integer scaling +// Copyright (c) 2021 Alexey Melnikov +// +// This program is GPL Licensed. See COPYING for the full license. +// +// +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +`timescale 1ns / 1ps + +module video_freak +( + input CLK_VIDEO, + input CE_PIXEL, + input VGA_VS, + input [11:0] HDMI_WIDTH, + input [11:0] HDMI_HEIGHT, + output VGA_DE, + output reg [12:0] VIDEO_ARX, + output reg [12:0] VIDEO_ARY, + + input VGA_DE_IN, + input [11:0] ARX, + input [11:0] ARY, + input [11:0] CROP_SIZE, + input [4:0] CROP_OFF, // -16...+15 + input [2:0] SCALE //0 - normal, 1 - V-integer, 2 - HV-Integer-, 3 - HV-Integer+, 4 - HV-Integer +); + +reg mul_start; +wire mul_run; +reg [11:0] mul_arg1, mul_arg2; +wire [23:0] mul_res; +sys_umul #(12,12) mul(CLK_VIDEO,mul_start,mul_run, mul_arg1,mul_arg2,mul_res); + +reg vde; +reg [11:0] arxo,aryo; +reg [11:0] vsize; +reg [11:0] hsize; + +always @(posedge CLK_VIDEO) begin + reg old_de, old_vs,ovde; + reg [11:0] vtot,vcpt,vcrop,voff; + reg [11:0] hcpt; + reg [11:0] vadj; + reg [23:0] ARXG,ARYG; + reg [11:0] arx,ary; + reg [1:0] vcalc; + + if (CE_PIXEL) begin + old_de <= VGA_DE_IN; + old_vs <= VGA_VS; + if (VGA_VS & ~old_vs) begin + vcpt <= 0; + vtot <= vcpt; + vcalc <= 1; + vcrop <= (CROP_SIZE >= vcpt) ? 12'd0 : CROP_SIZE; + end + + if (VGA_DE_IN) hcpt <= hcpt + 1'd1; + if (~VGA_DE_IN & old_de) begin + vcpt <= vcpt + 1'd1; + if(!vcpt) hsize <= hcpt; + hcpt <= 0; + end + end + + arx <= ARX; + ary <= ARY; + + vsize <= vcrop ? vcrop : vtot; + + mul_start <= 0; + + if(!vcrop || !ary || !arx) begin + arxo <= arx; + aryo <= ary; + end + else if (vcalc) begin + if(~mul_start & ~mul_run) begin + vcalc <= vcalc + 1'd1; + case(vcalc) + 1: begin + mul_arg1 <= arx; + mul_arg2 <= vtot; + mul_start <= 1; + end + + 2: begin + ARXG <= mul_res; + mul_arg1 <= ary; + mul_arg2 <= vcrop; + mul_start <= 1; + end + + 3: begin + ARYG <= mul_res; + end + endcase + end + end + else if (ARXG[23] | ARYG[23]) begin + arxo <= ARXG[23:12]; + aryo <= ARYG[23:12]; + end + else begin + ARXG <= ARXG << 1; + ARYG <= ARYG << 1; + end + + vadj <= (vtot-vcrop) + {{6{CROP_OFF[4]}},CROP_OFF,1'b0}; + voff <= vadj[11] ? 12'd0 : ((vadj[11:1] + vcrop) > vtot) ? vtot-vcrop : vadj[11:1]; + ovde <= ((vcpt >= voff) && (vcpt < (vcrop + voff))) || !vcrop; + vde <= ovde; +end + +assign VGA_DE = vde & VGA_DE_IN; + +video_scale_int scale +( + .CLK_VIDEO(CLK_VIDEO), + .HDMI_WIDTH(HDMI_WIDTH), + .HDMI_HEIGHT(HDMI_HEIGHT), + .SCALE(SCALE), + .hsize(hsize), + .vsize(vsize), + .arx_i(arxo), + .ary_i(aryo), + .arx_o(VIDEO_ARX), + .ary_o(VIDEO_ARY) +); + +endmodule + + +module video_scale_int +( + input CLK_VIDEO, + + input [11:0] HDMI_WIDTH, + input [11:0] HDMI_HEIGHT, + + input [2:0] SCALE, + + input [11:0] hsize, + input [11:0] vsize, + + input [11:0] arx_i, + input [11:0] ary_i, + + output reg [12:0] arx_o, + output reg [12:0] ary_o +); + +reg div_start; +wire div_run; +reg [23:0] div_num; +reg [11:0] div_den; +wire [23:0] div_res; +sys_udiv #(24,12) div(CLK_VIDEO,div_start,div_run, div_num,div_den,div_res); + +reg mul_start; +wire mul_run; +reg [11:0] mul_arg1, mul_arg2; +wire [23:0] mul_res; +sys_umul #(12,12) mul(CLK_VIDEO,mul_start,mul_run, mul_arg1,mul_arg2,mul_res); + +wire [11:0] wideres = mul_res[11:0] + hsize; + +always @(posedge CLK_VIDEO) begin + reg [11:0] oheight,wres; + reg [12:0] arxf,aryf; + reg [3:0] cnt; + reg narrow; + + div_start <= 0; + mul_start <= 0; + + if (!SCALE || (!ary_i && arx_i)) begin + arxf <= arx_i; + aryf <= ary_i; + end + else if(~div_start & ~div_run & ~mul_start & ~mul_run) begin + cnt <= cnt + 1'd1; + case(cnt) + 0: begin + div_num <= HDMI_HEIGHT; + div_den <= vsize; + div_start <= 1; + end + + 1: if(!div_res[11:0]) begin + // screen resolution is lower than video resolution. + // Integer scaling is impossible. + arxf <= arx_i; + aryf <= ary_i; + cnt <= 0; + end + else begin + mul_arg1 <= vsize; + mul_arg2 <= div_res[11:0]; + mul_start <= 1; + end + + 2: begin + oheight <= mul_res[11:0]; + if(!ary_i) begin + cnt <= 8; + end + end + + 3: begin + mul_arg1 <= mul_res[11:0]; + mul_arg2 <= arx_i; + mul_start <= 1; + end + + 4: begin + div_num <= mul_res; + div_den <= ary_i; + div_start <= 1; + end + + 5: begin + div_num <= div_res; + div_den <= hsize; + div_start <= 1; + end + + 6: begin + mul_arg1 <= hsize; + mul_arg2 <= div_res[11:0] ? div_res[11:0] : 12'd1; + mul_start <= 1; + end + + 7: if(mul_res <= HDMI_WIDTH) begin + cnt <= 10; + end + + 8: begin + div_num <= HDMI_WIDTH; + div_den <= hsize; + div_start <= 1; + end + + 9: begin + mul_arg1 <= hsize; + mul_arg2 <= div_res[11:0] ? div_res[11:0] : 12'd1; + mul_start <= 1; + end + + 10: begin + narrow <= ((div_num[11:0] - mul_res[11:0]) <= (wideres - div_num[11:0])) || (wideres > HDMI_WIDTH); + wres <= wideres; + end + + 11: begin + case(SCALE) + 2: arxf <= {1'b1, mul_res[11:0]}; + 3: arxf <= {1'b1, (wres > HDMI_WIDTH) ? mul_res[11:0] : wres}; + 4: arxf <= {1'b1, narrow ? mul_res[11:0] : wres}; + default: arxf <= {1'b1, div_num[11:0]}; + endcase + aryf <= {1'b1, oheight}; + end + endcase + end + + arx_o <= arxf; + ary_o <= aryf; +end + +endmodule diff --git a/sys/video_freezer.sv b/sys/video_freezer.sv new file mode 100644 index 0000000..cfbdf22 --- /dev/null +++ b/sys/video_freezer.sv @@ -0,0 +1,143 @@ +// +// video freeze with sync +// (C) Alexey Melnikov +// +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + +module video_freezer +( + input clk, + + output sync, + input freeze, + + input hs_in, + input vs_in, + input hbl_in, + input vbl_in, + + output hs_out, + output vs_out, + output hbl_out, + output vbl_out +); + +sync_lock #(33) vs_lock +( + .clk(clk), + .sync_in(vs_in), + .sync_out(vs_out), + .de_in(vbl_in), + .de_out(vbl_out), + .freeze(freeze) +); + +wire sync_pt; +sync_lock #(21) hs_lock +( + .clk(clk), + .sync_in(hs_in), + .sync_out(hs_out), + .de_in(hbl_in), + .de_out(hbl_out), + .freeze(freeze), + .sync_pt(sync_pt) +); + +reg sync_o; +always @(posedge clk) begin + reg old_hs, old_vs; + reg vs_sync; + + old_vs <= vs_out; + + if(~old_vs & vs_out) vs_sync <= 1; + if(sync_pt & vs_sync) begin + vs_sync <= 0; + sync_o <= ~sync_o; + end +end + +assign sync = sync_o; + +endmodule + + +module sync_lock #(parameter WIDTH) +( + input clk, + + input sync_in, + input de_in, + + output sync_out, + output de_out, + + input freeze, + output sync_pt, + output valid +); + +reg [WIDTH-1:0] f_len, s_len, de_start, de_end; +reg sync_valid; + +reg old_sync; +always @(posedge clk) old_sync <= sync_in; + +always @(posedge clk) begin + reg [WIDTH-1:0] cnti; + reg f_valid; + reg old_de; + + cnti <= cnti + 1'd1; + if(~old_sync & sync_in) begin + if(sync_valid) f_len <= cnti; + f_valid <= 1; + sync_valid <= f_valid; + cnti <= 0; + end + + if(old_sync & ~sync_in & sync_valid) s_len <= cnti; + + old_de <= de_in; + if(~old_de & de_in & sync_valid) de_start <= cnti; + if(old_de & ~de_in & sync_valid) de_end <= cnti; + + if(freeze) {f_valid, sync_valid} <= 0; +end + +reg sync_o, de_o, sync_o_pre; +always @(posedge clk) begin + reg [WIDTH-1:0] cnto; + + cnto <= cnto + 1'd1; + if(old_sync & ~sync_in & sync_valid) cnto <= s_len + 2'd2; + if(cnto == f_len) cnto <= 0; + + sync_o_pre <= (cnto == (s_len>>1)); // middle in sync + if(cnto == f_len) sync_o <= 1; + if(cnto == s_len) sync_o <= 0; + if(cnto == de_start) de_o <= 1; + if(cnto == de_end) de_o <= 0; +end + +assign sync_out = freeze ? sync_o : sync_in; +assign valid = sync_valid; +assign sync_pt = sync_o_pre; +assign de_out = freeze ? de_o : de_in; + +endmodule diff --git a/sys/video_mixer.sv b/sys/video_mixer.sv new file mode 100644 index 0000000..fd0b08f --- /dev/null +++ b/sys/video_mixer.sv @@ -0,0 +1,219 @@ +// +// +// Copyright (c) 2017,2021 Alexey Melnikov +// +// This program is GPL Licensed. See COPYING for the full license. +// +// +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +`timescale 1ns / 1ps + +// +// LINE_LENGTH: Length of display line in pixels when HBlank = 0; +// HALF_DEPTH: If =1 then color dept is 4 bits per component +// +// altera message_off 10720 +// altera message_off 12161 + +module video_mixer +#( + parameter LINE_LENGTH = 768, + parameter HALF_DEPTH = 0, + parameter GAMMA = 0 +) +( + input CLK_VIDEO, // should be multiple by (ce_pix*4) + output reg CE_PIXEL, // output pixel clock enable + + input ce_pix, // input pixel clock or clock_enable + + input scandoubler, + input hq2x, // high quality 2x scaling + + inout [21:0] gamma_bus, + + // color + input [DWIDTH:0] R, + input [DWIDTH:0] G, + input [DWIDTH:0] B, + + // Positive pulses. + input HSync, + input VSync, + input HBlank, + input VBlank, + + // Freeze engine + // HDMI: displays last frame + // VGA: black screen with HSync and VSync + input HDMI_FREEZE, + output freeze_sync, + + // video output signals + output reg [7:0] VGA_R, + output reg [7:0] VGA_G, + output reg [7:0] VGA_B, + output reg VGA_VS, + output reg VGA_HS, + output reg VGA_DE +); + +localparam DWIDTH = HALF_DEPTH ? 3 : 7; +localparam DWIDTH_SD = GAMMA ? 7 : DWIDTH; +localparam HALF_DEPTH_SD = GAMMA ? 0 : HALF_DEPTH; + +wire frz_hs, frz_vs; +wire frz_hbl, frz_vbl; +video_freezer freezer +( + .clk(CLK_VIDEO), + .freeze(HDMI_FREEZE), + .hs_in(HSync), + .vs_in(VSync), + .hbl_in(HBlank), + .vbl_in(VBlank), + .sync(freeze_sync), + .hs_out(frz_hs), + .vs_out(frz_vs), + .hbl_out(frz_hbl), + .vbl_out(frz_vbl) +); + +reg frz; +always @(posedge CLK_VIDEO) begin + reg frz1; + + frz1 <= HDMI_FREEZE; + frz <= frz1; +end + +generate + if(GAMMA && HALF_DEPTH) begin + wire [7:0] R_in = frz ? 8'd0 : {R,R}; + wire [7:0] G_in = frz ? 8'd0 : {G,G}; + wire [7:0] B_in = frz ? 8'd0 : {B,B}; + end else begin + wire [DWIDTH:0] R_in = frz ? 1'd0 : R; + wire [DWIDTH:0] G_in = frz ? 1'd0 : G; + wire [DWIDTH:0] B_in = frz ? 1'd0 : B; + end +endgenerate + +wire hs_g, vs_g; +wire hb_g, vb_g; +wire [DWIDTH_SD:0] R_gamma, G_gamma, B_gamma; + +generate + if(GAMMA) begin + assign gamma_bus[21] = 1; + gamma_corr gamma( + .clk_sys(gamma_bus[20]), + .clk_vid(CLK_VIDEO), + .ce_pix(ce_pix), + + .gamma_en(gamma_bus[19]), + .gamma_wr(gamma_bus[18]), + .gamma_wr_addr(gamma_bus[17:8]), + .gamma_value(gamma_bus[7:0]), + + .HSync(frz_hs), + .VSync(frz_vs), + .HBlank(frz_hbl), + .VBlank(frz_vbl), + .RGB_in({R_in,G_in,B_in}), + + .HSync_out(hs_g), + .VSync_out(vs_g), + .HBlank_out(hb_g), + .VBlank_out(vb_g), + .RGB_out({R_gamma,G_gamma,B_gamma}) + ); + end else begin + assign gamma_bus[21] = 0; + assign {R_gamma,G_gamma,B_gamma} = {R_in,G_in,B_in}; + assign {hs_g, vs_g, hb_g, vb_g} = {frz_hs, frz_vs, frz_hbl, frz_vbl}; + end +endgenerate + +wire [DWIDTH_SD:0] R_sd; +wire [DWIDTH_SD:0] G_sd; +wire [DWIDTH_SD:0] B_sd; +wire hs_sd, vs_sd, hb_sd, vb_sd, ce_pix_sd; + +scandoubler #(.LENGTH(LINE_LENGTH), .HALF_DEPTH(HALF_DEPTH_SD)) sd +( + .clk_vid(CLK_VIDEO), + .hq2x(hq2x), + + .ce_pix(ce_pix), + .hs_in(hs_g), + .vs_in(vs_g), + .hb_in(hb_g), + .vb_in(vb_g), + .r_in(R_gamma), + .g_in(G_gamma), + .b_in(B_gamma), + + .ce_pix_out(ce_pix_sd), + .hs_out(hs_sd), + .vs_out(vs_sd), + .hb_out(hb_sd), + .vb_out(vb_sd), + .r_out(R_sd), + .g_out(G_sd), + .b_out(B_sd) +); + +wire [DWIDTH_SD:0] rt = (scandoubler ? R_sd : R_gamma); +wire [DWIDTH_SD:0] gt = (scandoubler ? G_sd : G_gamma); +wire [DWIDTH_SD:0] bt = (scandoubler ? B_sd : B_gamma); + +always @(posedge CLK_VIDEO) begin + reg [7:0] r,g,b; + reg hde,vde,hs,vs, old_vs; + reg old_hde; + reg old_ce; + reg ce_osc, fs_osc; + + old_ce <= ce_pix; + ce_osc <= ce_osc | (old_ce ^ ce_pix); + + old_vs <= vs; + if(~old_vs & vs) begin + fs_osc <= ce_osc; + ce_osc <= 0; + end + + CE_PIXEL <= scandoubler ? ce_pix_sd : fs_osc ? (~old_ce & ce_pix) : ce_pix; + + if(!GAMMA && HALF_DEPTH) begin + r <= {rt,rt}; + g <= {gt,gt}; + b <= {bt,bt}; + end + else begin + r <= rt; + g <= gt; + b <= bt; + end + + hde <= scandoubler ? ~hb_sd : ~hb_g; + vde <= scandoubler ? ~vb_sd : ~vb_g; + vs <= scandoubler ? vs_sd : vs_g; + hs <= scandoubler ? hs_sd : hs_g; + + if(CE_PIXEL) begin + VGA_R <= r; + VGA_G <= g; + VGA_B <= b; + + VGA_VS <= vs; + VGA_HS <= hs; + + old_hde <= hde; + if(old_hde ^ hde) VGA_DE <= vde & hde; + end +end + +endmodule