├── .github
└── FUNDING.yml
├── .gitignore
├── LICENSE
├── README.md
├── assets
├── Arcade.aseprite
└── pong.png
├── dist
├── Cores
│ └── agg23.Pong
│ │ ├── audio.json
│ │ ├── core.json
│ │ ├── data.json
│ │ ├── icon.bin
│ │ ├── info.txt
│ │ ├── input.json
│ │ ├── interact.json
│ │ ├── variants.json
│ │ └── video.json
└── Platforms
│ ├── _images
│ └── pong.bin
│ └── pong.json
└── src
└── fpga
├── .gitignore
├── ap_core.qpf
├── ap_core.qsf
├── ap_core_assignment_defaults.qdf
├── apf
├── apf.qip
├── apf_constraints.sdc
├── apf_top.v
├── build_id.mif
├── build_id_gen.tcl
├── common.v
├── io_bridge_peripheral.v
├── io_pad_controller.v
├── mf_datatable.qip
├── mf_datatable.v
├── mf_ddio_bidir_12.qip
└── mf_ddio_bidir_12.v
└── core
├── core_bridge_cmd.v
├── core_constraints.sdc
├── core_top.v
├── mf_pllbase.bsf
├── mf_pllbase.ppf
├── mf_pllbase.qip
├── mf_pllbase.sip
├── mf_pllbase.spd
├── mf_pllbase.v
├── mf_pllbase
├── mf_pllbase_0002.qip
└── mf_pllbase_0002.v
├── mf_pllbase_sim.f
├── mf_pllbase_sim
├── aldec
│ └── rivierapro_setup.tcl
├── cadence
│ ├── cds.lib
│ ├── hdl.var
│ └── ncsim_setup.sh
├── mentor
│ └── msim_setup.tcl
├── mf_pllbase.vo
└── synopsys
│ ├── vcs
│ └── vcs_setup.sh
│ └── vcsmx
│ ├── synopsys_sim.setup
│ └── vcsmx_setup.sh
├── pin_ddio_clk.ppf
├── pin_ddio_clk.qip
├── pin_ddio_clk.v
├── pong
├── ball
│ ├── horizontal.vhd
│ ├── horizontal_direction.vhd
│ ├── horizontal_position.vhd
│ ├── move.vhd
│ └── vertical.vhd
├── game_control.vhd
├── ic
│ ├── 555_timer.vhd
│ ├── 74107_neg_flip_flop.vhd
│ ├── 74153_double_mux.vhd
│ ├── 74153_mux.vhd
│ ├── 7448_bcd_7_segment.vhd
│ ├── 7474_sync.vhd
│ ├── 7483_full_adder_without_carry.vhd
│ ├── 7490_decade_counter.vhd
│ ├── 7493_4bit_counter.vhd
│ ├── 9316_internal.vhd
│ ├── 9316_sync_4bit_counter.vhd
│ ├── sr_nand.vhd
│ ├── sr_nor.vhd
│ ├── synchronizer.vhd
│ └── test
│ │ ├── 7474_tb.vhd
│ │ ├── 7493_tb.vhd
│ │ └── 9316_tb.vhd
├── net.vhd
├── paddle.vhd
├── pong.vhd
├── score
│ ├── bcd.vhd
│ ├── counter.vhd
│ ├── score.vhd
│ └── segments.vhd
├── sound.vhd
├── test
│ └── pong_tb.vhd
└── video
│ ├── hcounter.vhd
│ ├── hsync.vhd
│ ├── test
│ ├── hcounter_tb.vhd
│ ├── hsync_tb.vhd
│ └── vcounter_tb.vhd
│ ├── vcounter.vhd
│ ├── video.vhd
│ └── vsync.vhd
└── stp1.stp
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: agg23
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | tools/reverse.exe
2 | bitstream.rbf_r
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Adam Gastineau
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Atari's 1972 Pong
2 |
3 | A FPGA implementation of Atari's 1972 arcade game, Pong. This implementation is packaged for running on the Analogue Pocket.
4 |
5 | ## Controls
6 |
7 | Pong is a two player game that uses potentiometers (rotary dials) for control of each player's paddle. As the Pocket doesn't have rotary dials, we have to make due with its face buttons.
8 |
9 | | Action | Player 1 | Player 2 |
10 | |-----------------|---------------|------------------------------|
11 | | Paddle Movement | D Pad Up/Down | Face Button Top/Bottom (X/B) |
12 | | Fine Movement | Left Trigger | Right Trigger |
13 |
14 | Pong also supports the Analogue Pocket Dock, so you can play with two separate controllers. I suggest using the `Use Ctrl 2 for P2` setting described below for the best two controller experience.
15 |
16 | To insert a coin to start the game, press the button to the right of the Analogue button (considered to be the "Plus" button). Please note that the game will restart when an additional coin is inserted, so you can start a new game by pressing "Plus" at any time.
17 |
18 | ## Settings
19 |
20 | The original hardware only has one configurable setting available via a toggle switch: whether the game stops after 11 or 15 points. This core exposes this setting and a few "cheats" via the APF core settings.
21 |
22 | | Setting | Action |
23 | |-------------------------|----------------------------------------------------------------------------------------------------------------------------------|
24 | | Win at 11/15 points | Configures the game to end at either 11 or 15 points. When set (the checkbox is white), the game will end after 15 points |
25 | | Prevent coin reset | Pong resets by default when a coin is inserted, no matter the play state. This prevents the reset unless the game is over |
26 | | Cheat: Extended paddles | Doubles the height of the paddles. This modification was performed to many machines to make it easier |
27 | | Cheat: Training mode | Configures the Player 2 paddle to fill most of the side of the screen. The only way to score is to hit the ball above the paddle |
28 |
29 | ## Implementation
30 |
31 | This is a gate-level implementation of Pong, derived from the original schematic. All bugs and oddities with the original hardware should be represented in the synthesized hardware (if you find something that isn't, please open an issue).
32 |
33 | As Pong was implemented using 74-series TTL logic chips, driven in an asynchronous manner (outputs from one chip may clock another), certain steps had to be taken to ensure accurate synthesis.
34 |
35 | 1. In addition to the 7.159 MHz primary clock used by Pong, a 28.636 MHz clock (4x the primary clock) is used to synchronize the various async parts of the ciruit. We take advantage of the time it takes logic gates to stablize in the original ciruit to gate updating values until an edge (typically rising) of the 28 MHz clock. This makes the logic formally synchronous, and avoids a series of problems that may arise during synthesis (see [dc5953b](https://github.com/agg23/analogue-pong/commit/dc5953be54613d9eeb33aa888bffc915d3f99dce) for an example of how changing synthesis can make or break the operation of async logic).
36 | 2. Several instances of combinational logic are converted to be synchronous to prevent the creation of combinational loops. These are denoted with a comment. In `paddle.vhd` in particular, leaving the output of the NAND `a7b` as a combinational expression resulted in the undefined clocking of the paddle height counter, resulting in flickering graphics and strange functionality.
37 | 3. 555 timers are simulated as counters based off of the primary clock, with timing approximating those found in testing. Implementation based off of https://github.com/MiSTer-devel/Arcade-Pong_MiSTer/blob/master/rtl/paddle.v
38 | 4. Horizontal sync timing in the original ciruit relies on a long ripple counter, which has the odd effect of ending `h_blank` _after_ the next rising edge of the clock (count is incremented on falling edge, and `h_blank` doesn't fall until after the rising edge). This is solved for by using the inverted primary clock as the synchronization clock for `h_blank`.
39 |
40 | ## References
41 |
42 | * [Edwards 2012 - Reconstructing Pong on an FPGA](http://www1.cs.columbia.edu/~sedwards/papers/edwards2012reconstructing.pdf) - The primary explanations of Pong's circuitry, along with nicely reformated schematics.
43 | * [Holden - Atari Pong E Circuit Analysis & Lawn Tennis](http://www.pong-story.com/LAWN_TENNIS.pdf) - Discussion about Pong's history, circuit explanation, and common defects/mistakes in the circuit.
--------------------------------------------------------------------------------
/assets/Arcade.aseprite:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agg23/openfpga-pong/bf4d17e8cb6159d4457126c45f43a5df15e4779e/assets/Arcade.aseprite
--------------------------------------------------------------------------------
/assets/pong.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agg23/openfpga-pong/bf4d17e8cb6159d4457126c45f43a5df15e4779e/assets/pong.png
--------------------------------------------------------------------------------
/dist/Cores/agg23.Pong/audio.json:
--------------------------------------------------------------------------------
1 | {
2 | "audio": {
3 | "magic": "APF_VER_1"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/dist/Cores/agg23.Pong/core.json:
--------------------------------------------------------------------------------
1 | {
2 | "core": {
3 | "magic": "APF_VER_1",
4 | "metadata": {
5 | "platform_ids": ["pong"],
6 | "shortname": "Pong",
7 | "description": "Atari Pong arcade machine. 1972",
8 | "author": "agg23",
9 | "url": "https://github.com/agg23/analogue-pong/",
10 | "version": "1.2.0",
11 | "date_release": "2022-09-08"
12 | },
13 | "framework": {
14 | "target_product": "Analogue Pocket",
15 | "version_required": "1.1",
16 | "sleep_supported": false,
17 | "dock": {
18 | "supported": true,
19 | "analog_output": false
20 | },
21 | "hardware": {
22 | "link_port": false,
23 | "cartridge_adapter": -1
24 | }
25 | },
26 | "cores": [
27 | {
28 | "name": "default",
29 | "id": 0,
30 | "filename": "bitstream.rbf_r"
31 | }
32 | ]
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/dist/Cores/agg23.Pong/data.json:
--------------------------------------------------------------------------------
1 | {
2 | "data": {
3 | "magic": "APF_VER_1",
4 | "data_slots": []
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/dist/Cores/agg23.Pong/icon.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agg23/openfpga-pong/bf4d17e8cb6159d4457126c45f43a5df15e4779e/dist/Cores/agg23.Pong/icon.bin
--------------------------------------------------------------------------------
/dist/Cores/agg23.Pong/info.txt:
--------------------------------------------------------------------------------
1 | The arcade game classic, Pong, in its original form. Video, sound, and bugs are reproduced from the original schematic.
2 |
3 | Features additional "cheats":
4 | * Extended paddles
5 | * Training mode
--------------------------------------------------------------------------------
/dist/Cores/agg23.Pong/input.json:
--------------------------------------------------------------------------------
1 | {
2 | "input": {
3 | "magic": "APF_VER_1",
4 | "controllers": [
5 | {
6 | "type": "default",
7 | "mappings": [
8 | {
9 | "id": 30,
10 | "name": "P1 Fine Control",
11 | "key": "pad_trig_l"
12 | },
13 | {
14 | "id": 10,
15 | "name": "P2 Paddle Up",
16 | "key": "pad_btn_x"
17 | },
18 | {
19 | "id": 11,
20 | "name": "P2 Paddle Down",
21 | "key": "pad_btn_b"
22 | },
23 | {
24 | "id": 31,
25 | "name": "P2 Fine Control",
26 | "key": "pad_trig_r"
27 | },
28 | {
29 | "id": 20,
30 | "name": "Insert coin",
31 | "key": "pad_btn_start"
32 | }
33 | ]
34 | }
35 | ]
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/dist/Cores/agg23.Pong/interact.json:
--------------------------------------------------------------------------------
1 | {
2 | "interact": {
3 | "magic": "APF_VER_1",
4 | "variables": [
5 | {
6 | "id": 1,
7 | "name": "Win at 11/15 points",
8 | "type": "check",
9 | "enabled": true,
10 | "persist": true,
11 | "writeonly": true,
12 | "address": "0x0",
13 | "defaultval": 0,
14 | "value": 1
15 | },
16 | {
17 | "id": 6,
18 | "name": "Prevent coin reset",
19 | "type": "check",
20 | "enabled": true,
21 | "persist": true,
22 | "writeonly": true,
23 | "address": "0xC",
24 | "defaultval": 1,
25 | "value": 1
26 | },
27 | {
28 | "id": 10,
29 | "name": "Cheats",
30 | "type": "action",
31 | "enabled": false,
32 | "persist": false,
33 | "writeonly": true,
34 | "address": "0x10000",
35 | "value": 0
36 | },
37 | {
38 | "id": 11,
39 | "name": "Extended paddles",
40 | "type": "check",
41 | "enabled": true,
42 | "persist": true,
43 | "writeonly": true,
44 | "address": "0x14",
45 | "defaultval": 0,
46 | "value": 1
47 | },
48 | {
49 | "id": 12,
50 | "name": "Training mode",
51 | "type": "check",
52 | "enabled": true,
53 | "persist": true,
54 | "writeonly": true,
55 | "address": "0x18",
56 | "defaultval": 0,
57 | "value": 1
58 | }
59 | ],
60 | "messages": []
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/dist/Cores/agg23.Pong/variants.json:
--------------------------------------------------------------------------------
1 | {
2 | "variants": {
3 | "magic": "APF_VER_1",
4 | "variant_list": []
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/dist/Cores/agg23.Pong/video.json:
--------------------------------------------------------------------------------
1 | {
2 | "video": {
3 | "magic": "APF_VER_1",
4 | "scaler_modes": [
5 | {
6 | "width": 360,
7 | "height": 240,
8 | "aspect_w": 4,
9 | "aspect_h": 3,
10 | "rotation": 0,
11 | "mirror": 0
12 | }
13 | ]
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/dist/Platforms/_images/pong.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agg23/openfpga-pong/bf4d17e8cb6159d4457126c45f43a5df15e4779e/dist/Platforms/_images/pong.bin
--------------------------------------------------------------------------------
/dist/Platforms/pong.json:
--------------------------------------------------------------------------------
1 | {
2 | "platform": {
3 | "category": "Arcade",
4 | "name": "Pong",
5 | "manufacturer": "Atari",
6 | "year": 1972
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/fpga/.gitignore:
--------------------------------------------------------------------------------
1 | */db/
2 | */incremental_db/
3 | */simulation/
4 | */greybox_tmp/
5 | output_files/
6 | incremental_db/
7 | db/
8 | PLLJ_PLLSPE_INFO.txt
9 | c5_pin_model_dump.txt
10 | cr_ie_info.json
11 | *.pin
12 | *.pof
13 | *.ptf.*
14 | *.qar
15 | *.qarlog
16 | *.qws
17 | *.rpt
18 | *.smsg
19 | *.sof
20 | *.sopc_builder
21 | *.summary
22 | *.txt
23 | *.bak
24 | *.cmp
25 | *.done
26 | *.xml
27 | *.sld
28 | *.cdf
29 |
30 |
--------------------------------------------------------------------------------
/src/fpga/ap_core.qpf:
--------------------------------------------------------------------------------
1 | # -------------------------------------------------------------------------- #
2 | #
3 | # Copyright (C) 2019 Intel Corporation. All rights reserved.
4 | # Your use of Intel Corporation's design tools, logic functions
5 | # and other software and tools, and any partner logic
6 | # functions, and any output files from any of the foregoing
7 | # (including device programming or simulation files), and any
8 | # associated documentation or information are expressly subject
9 | # to the terms and conditions of the Intel Program License
10 | # Subscription Agreement, the Intel Quartus Prime License Agreement,
11 | # the Intel FPGA IP License Agreement, or other applicable license
12 | # agreement, including, without limitation, that your use is for
13 | # the sole purpose of programming logic devices manufactured by
14 | # Intel and sold by Intel or its authorized distributors. Please
15 | # refer to the applicable agreement for further details, at
16 | # https://fpgasoftware.intel.com/eula.
17 | #
18 | # -------------------------------------------------------------------------- #
19 | #
20 | # Quartus Prime
21 | # Version 18.1.1 Build 646 04/11/2019 SJ Lite Edition
22 | # Date created = 21:31:36 January 22, 2020
23 | #
24 | # -------------------------------------------------------------------------- #
25 |
26 | QUARTUS_VERSION = "18.1"
27 | DATE = "21:31:36 January 22, 2020"
28 |
29 | # Revisions
30 |
31 | PROJECT_REVISION = "ap_core"
32 |
--------------------------------------------------------------------------------
/src/fpga/apf/apf.qip:
--------------------------------------------------------------------------------
1 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "apf_top.v"]
2 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "common.v"]
3 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "io_bridge_peripheral.v"]
4 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "io_pad_controller.v"]
5 | set_global_assignment -name SDC_FILE [file join $::quartus(qip_path) "apf_constraints.sdc"]
6 | set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) "mf_ddio_bidir_12.qip"]
7 | set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) "mf_datatable.qip"]
8 |
--------------------------------------------------------------------------------
/src/fpga/apf/apf_constraints.sdc:
--------------------------------------------------------------------------------
1 | #
2 | # APF constraints
3 | # Do not edit this file.
4 | #
5 | # Add your own constraints in the \core_constraints.sdc in the core directory, which will also be loaded.
6 |
7 | create_clock -name clk_74a -period 13.468 [get_ports clk_74a]
8 | create_clock -name clk_74b -period 13.468 [get_ports clk_74b]
9 | create_clock -name bridge_spiclk -period 13.468 [get_ports bridge_spiclk]
10 |
11 | # autogenerate PLL clock names for use down below
12 | derive_pll_clocks
13 |
14 |
15 | # io constraints go here
16 | #
17 |
18 |
19 | # load in user constraints
20 | read_sdc "core/core_constraints.sdc"
--------------------------------------------------------------------------------
/src/fpga/apf/build_id.mif:
--------------------------------------------------------------------------------
1 | -- Build ID Memory Initialization File
2 | --
3 |
4 | DEPTH = 256;
5 | WIDTH = 32;
6 | ADDRESS_RADIX = HEX;
7 | DATA_RADIX = HEX;
8 |
9 | CONTENT
10 | BEGIN
11 |
12 | 0E0 : 20221009;
13 | 0E1 : 00074046;
14 | 0E2 : 4f62b4d0;
15 |
16 | END;
17 |
--------------------------------------------------------------------------------
/src/fpga/apf/build_id_gen.tcl:
--------------------------------------------------------------------------------
1 | # ================================================================================
2 | # (c) 2011 Altera Corporation. All rights reserved.
3 | # Altera products are protected under numerous U.S. and foreign patents, maskwork
4 | # rights, copyrights and other intellectual property laws.
5 | #
6 | # This reference design file, and your use thereof, is subject to and governed
7 | # by the terms and conditions of the applicable Altera Reference Design License
8 | # Agreement (either as signed by you, agreed by you upon download or as a
9 | # "click-through" agreement upon installation andor found at www.altera.com).
10 | # By using this reference design file, you indicate your acceptance of such terms
11 | # and conditions between you and Altera Corporation. In the event that you do
12 | # not agree with such terms and conditions, you may not use the reference design
13 | # file and please promptly destroy any copies you have made.
14 | #
15 | # This reference design file is being provided on an "as-is" basis and as an
16 | # accommodation and therefore all warranties, representations or guarantees of
17 | # any kind (whether express, implied or statutory) including, without limitation,
18 | # warranties of merchantability, non-infringement, or fitness for a particular
19 | # purpose, are specifically disclaimed. By making this reference design file
20 | # available, Altera expressly does not recommend, suggest or require that this
21 | # reference design file be used in combination with any other product not
22 | # provided by Altera.
23 | # ================================================================================
24 | #
25 | # Build ID Verilog Module Script
26 | # Jeff Wiencrot - 8/1/2011
27 | #
28 | # Generates a Verilog module that contains a timestamp, physical address, and host name
29 | # from the current build. These values are available from the build_date, build_time,
30 | # physical_address, and host_name output ports of the build_id module in the build_id.v
31 | # Verilog source file.
32 | #
33 | # The format for each value is as follows:
34 | # Date - 32-bit decimal number of the format mmddyyyy
35 | # Time - 32-bit decimal number of the format hhmmss
36 | # Phyiscal Address - 48-bit hexadecimal number
37 | # Host name - 120-bit hexadecimal number with pairs of digits equal to the
38 | # hexadecimal code for the first 15 ASCII characters of the host
39 | # name. For added clarity, host names that have fewer than 30
40 | # hexadecimal digits (15 characters) are padded on the left with
41 | # zeros.
42 | #
43 | # Usage:
44 | #
45 | # To manually execute this script, source this file using the following Tcl commands:
46 | # source build_id_verilog.tcl
47 | #
48 | # To have this script automatically execute each time your project is built, use the
49 | # following command (see: http://www.altera.com/support/examples/tcl/auto_processing.html):
50 | # set_global_assignment -name PRE_FLOW_SCRIPT_FILE quartus_sh:build_id_verilog.tcl
51 | #
52 | # Comment out the last line to prevent the process from automatically executing when
53 | # the file is sourced. The process can then be executed with the following command:
54 | # generateBuildID_Verilog
55 | #
56 | #
57 | # For more information, see "build_identification.pdf"
58 | #
59 | # ================================================================================
60 | #
61 | # 2021-01-21 Analogue
62 | #
63 | # Only care about generating build date/time, so the rest was removed.
64 | # The original can be downloaded from the Intel resource page
65 | #
66 |
67 | proc generateBuildID_Verilog {} {
68 |
69 | # Get the timestamp (see: http://www.altera.com/support/examples/tcl/tcl-date-time-stamp.html)
70 | set buildDate [ clock format [ clock seconds ] -format %Y%m%d ]
71 | set buildTime [ clock format [ clock seconds ] -format %H%M%S ]
72 |
73 | # Create a Verilog file for output
74 | set outputFileName "apf/build_id.v"
75 | set outputFile [open $outputFileName "w"]
76 |
77 | # Output the Verilog source
78 | puts $outputFile "// Build ID Verilog Module"
79 | puts $outputFile "//"
80 | puts $outputFile "// Note - these are stored as binary coded decimal"
81 | puts $outputFile "// Date: $buildDate"
82 | puts $outputFile "// Time: $buildTime"
83 | puts $outputFile ""
84 | puts $outputFile "module build_id"
85 | puts $outputFile "("
86 | puts $outputFile " output \[31:0\] build_date,"
87 | puts $outputFile " output \[31:0\] build_time"
88 | puts $outputFile ");"
89 | puts $outputFile ""
90 | puts $outputFile " assign build_date = 32'h$buildDate;"
91 | puts $outputFile " assign build_time = 32'h$buildTime;"
92 | puts $outputFile ""
93 | puts $outputFile "endmodule"
94 | close $outputFile
95 |
96 |
97 |
98 | # Send confirmation message to the Messages window
99 | #post_message "APF core build date/time generated: [pwd]/$outputFileName"
100 | #post_message "Date: $buildDate"
101 | #post_message "Time: $buildTime"
102 | }
103 |
104 |
105 | proc generateBuildID_MIF {} {
106 |
107 | # Get the timestamp (see: http://www.altera.com/support/examples/tcl/tcl-date-time-stamp.html)
108 | set buildDate [ clock format [ clock seconds ] -format %Y%m%d ]
109 | set buildTime [ clock format [ clock seconds ] -format %H%M%S ]
110 | set buildUnique [expr {int(rand()*(4294967295))}]
111 |
112 | set buildDateNoLeadingZeros [string trimleft $buildDate "0"]
113 | set buildTimeNoLeadingZeros [string trimleft $buildTime "0"]
114 | set buildDate4Byte [format "%08d" $buildDateNoLeadingZeros]
115 | set buildTime4Byte [format "%08d" $buildTimeNoLeadingZeros]
116 | set buildUnique4Byte [format "%08x" $buildUnique]
117 |
118 | #set buildDate4Byte \
119 | [concat [string range $buildDate 0 1] \
120 | [string range $buildDate 2 3] \
121 | [string range $buildDate 4 5] \
122 | [string range $buildDate 6 7] ]
123 |
124 |
125 | set buildDateNumBytes 4
126 | set buildTimeNumBytes 4
127 |
128 | # Calculate depth of the memory (8-bit) words
129 | set memoryDepth [expr $buildDateNumBytes + $buildTimeNumBytes]
130 |
131 | # Create a Memory Initialization File for output
132 | set outputFileName "apf/build_id.mif"
133 | set outputFile [open $outputFileName "w"]
134 |
135 | # Output the MIF header (see: http://quartushelp.altera.com/current/mergedProjects/reference/glossary/def_mif.htm)
136 | puts $outputFile "-- Build ID Memory Initialization File"
137 | puts $outputFile "--"
138 | puts $outputFile ""
139 | puts $outputFile "DEPTH = 256;"
140 | puts $outputFile "WIDTH = 32;"
141 | puts $outputFile "ADDRESS_RADIX = HEX;"
142 | puts $outputFile "DATA_RADIX = HEX;"
143 | puts $outputFile ""
144 | puts $outputFile "CONTENT"
145 | puts $outputFile "BEGIN"
146 | puts $outputFile ""
147 | puts $outputFile " 0E0 : $buildDate4Byte;"
148 | puts $outputFile " 0E1 : $buildTime4Byte;"
149 | puts $outputFile " 0E2 : $buildUnique4Byte;"
150 | puts $outputFile ""
151 | puts $outputFile "END;"
152 |
153 | # Close file to complete write
154 | close $outputFile
155 |
156 | # Send confirmation message to the Messages window
157 | post_message "APF core build date/time generated: [pwd]/$outputFileName"
158 | }
159 |
160 | generateBuildID_MIF
161 |
162 | # 2021-01-21 Analogue
163 | #
164 | # There are some circumstances where you want all parts of a FPGA flow to be deterministic, especially
165 | # when trying to hash out timing issues.
166 | # You should comment this line out and temporarily bypass buildid generation so that synthesis/par
167 | # have consistent working input. MIF bram contents like above won't affect the random seed or trigger
168 | # recompilation.
169 | # Don't forget to re-enable before you release.
170 | #
171 | # generateBuildID_Verilog
172 |
--------------------------------------------------------------------------------
/src/fpga/apf/common.v:
--------------------------------------------------------------------------------
1 | // Software License Agreement
2 |
3 | // The software supplied herewith by Analogue Enterprises Limited (the "Company”),
4 | // the Analogue Pocket Framework (“APF”), is provided and licensed to you, the
5 | // Company's customer, solely for use in designing, testing and creating
6 | // applications for use with Company's Products or Services. The software is
7 | // owned by the Company and/or its licensors, and is protected under applicable
8 | // laws, including, but not limited to, U.S. copyright law. All rights are
9 | // reserved. By using the APF code you are agreeing to the terms of the End User
10 | // License Agreement (“EULA”) located at [https://www.analogue.link/pocket-eula]
11 | // and incorporated herein by reference.
12 |
13 | // THE SOFTWARE IS PROVIDED "AS-IS" AND WE EXPRESSLY DISCLAIM ANY IMPLIED
14 | // WARRANTIES TO THE FULLEST EXTENT PROVIDED BY LAW, INCLUDING BUT NOT LIMITED TO,
15 | // ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE OR
16 | // NON-INFRINGEMENT. TO THE EXTENT APPLICABLE LAWS PROHIBIT TERMS OF USE FROM
17 | // DISCLAIMING ANY IMPLIED WARRANTY, SUCH IMPLIED WARRANTY SHALL BE LIMITED TO THE
18 | // MINIMUM WARRANTY PERIOD REQUIRED BY LAW, AND IF NO SUCH PERIOD IS REQUIRED,
19 | // THEN THIRTY (30) DAYS FROM FIRST USE OF THE SOFTWARE. WE CANNOT GUARANTEE AND
20 | // DO NOT PROMISE ANY SPECIFIC RESULTS FROM USE OF THE SOFTWARE. WITHOUT LIMITING
21 | // THE FOREGOING, WE DO NOT WARRANT THAT THE SOFTWARE WILL BE UNINTERRUPTED OR
22 | // ERROR-FREE. IN NO EVENT WILL WE BE LIABLE TO YOU OR ANY OTHER PERSON FOR ANY
23 | // INDIRECT, CONSEQUENTIAL, EXEMPLARY, INCIDENTAL, SPECIAL OR PUNITIVE DAMAGES,
24 | // INCLUDING BUT NOT LIMITED TO, LOST PROFITS ARISING OUT OF YOUR USE, OR
25 | // INABILITY TO USE, THE SOFTWARE, EVEN IF WE HAVE BEEN ADVISED OF THE POSSIBILITY
26 | // OF SUCH DAMAGES. UNDER NO CIRCUMSTANCES SHALL OUR LIABILITY TO YOU FOR ANY
27 | // CLAIM OR CAUSE OF ACTION WHATSOEVER, AND REGARDLESS OF THE FORM OF THE ACTION,
28 | // WHETHER ARISING IN CONTRACT, TORT OR OTHERWISE, EXCEED THE AMOUNT PAID BY YOU
29 | // TO US, IF ANY, DURING THE 90 DAY PERIOD IMMEDIATELY PRECEDING THE DATE ON WHICH
30 | // YOU FIRST ASSERT ANY SUCH CLAIM. THE FOREGOING LIMITATIONS SHALL APPLY TO THE
31 | // FULLEST EXTENT PERMITTED BY APPLICABLE LAW.
32 | //
33 | // 2-stage synchronizer
34 | //
35 | module synch_2 #(parameter WIDTH = 1) (
36 | input wire [WIDTH-1:0] i, // input signal
37 | output reg [WIDTH-1:0] o, // synchronized output
38 | input wire clk, // clock to synchronize on
39 | output wire rise, // one-cycle rising edge pulse
40 | output wire fall // one-cycle falling edge pulse
41 | );
42 |
43 | reg [WIDTH-1:0] stage_1;
44 | reg [WIDTH-1:0] stage_2;
45 | reg [WIDTH-1:0] stage_3;
46 |
47 | assign rise = (WIDTH == 1) ? (o & ~stage_2) : 1'b0;
48 | assign fall = (WIDTH == 1) ? (~o & stage_2) : 1'b0;
49 | always @(posedge clk)
50 | {stage_2, o, stage_1} <= {o, stage_1, i};
51 |
52 | endmodule
53 |
54 |
55 | //
56 | // 3-stage synchronizer
57 | //
58 | module synch_3 #(parameter WIDTH = 1) (
59 | input wire [WIDTH-1:0] i, // input signal
60 | output reg [WIDTH-1:0] o, // synchronized output
61 | input wire clk, // clock to synchronize on
62 | output wire rise, // one-cycle rising edge pulse
63 | output wire fall // one-cycle falling edge pulse
64 | );
65 |
66 | reg [WIDTH-1:0] stage_1;
67 | reg [WIDTH-1:0] stage_2;
68 | reg [WIDTH-1:0] stage_3;
69 |
70 | assign rise = (WIDTH == 1) ? (o & ~stage_3) : 1'b0;
71 | assign fall = (WIDTH == 1) ? (~o & stage_3) : 1'b0;
72 | always @(posedge clk)
73 | {stage_3, o, stage_2, stage_1} <= {o, stage_2, stage_1, i};
74 |
75 | endmodule
76 |
77 |
78 | module bram_block_dp #(
79 | parameter DATA = 32,
80 | parameter ADDR = 7
81 | ) (
82 | input wire a_clk,
83 | input wire a_wr,
84 | input wire [ADDR-1:0] a_addr,
85 | input wire [DATA-1:0] a_din,
86 | output reg [DATA-1:0] a_dout,
87 |
88 | input wire b_clk,
89 | input wire b_wr,
90 | input wire [ADDR-1:0] b_addr,
91 | input wire [DATA-1:0] b_din,
92 | output reg [DATA-1:0] b_dout
93 | );
94 |
95 | reg [DATA-1:0] mem [(2**ADDR)-1:0];
96 |
97 | always @(posedge a_clk) begin
98 | if(a_wr) begin
99 | a_dout <= a_din;
100 | mem[a_addr] <= a_din;
101 | end else
102 | a_dout <= mem[a_addr];
103 | end
104 |
105 | always @(posedge b_clk) begin
106 | if(b_wr) begin
107 | b_dout <= b_din;
108 | mem[b_addr] <= b_din;
109 | end else
110 | b_dout <= mem[b_addr];
111 | end
112 |
113 | endmodule
114 |
115 |
116 | module bram_block_dp_nonstd #(
117 | parameter DATA = 32,
118 | parameter ADDR = 7,
119 | parameter DEPTH = 128
120 | ) (
121 | input wire a_clk,
122 | input wire a_wr,
123 | input wire [ADDR-1:0] a_addr,
124 | input wire [DATA-1:0] a_din,
125 | output reg [DATA-1:0] a_dout,
126 |
127 | input wire b_clk,
128 | input wire b_wr,
129 | input wire [ADDR-1:0] b_addr,
130 | input wire [DATA-1:0] b_din,
131 | output reg [DATA-1:0] b_dout
132 | );
133 |
134 | reg [DATA-1:0] mem [DEPTH-1:0];
135 |
136 | always @(posedge a_clk) begin
137 | if(a_wr) begin
138 | a_dout <= a_din;
139 | mem[a_addr] <= a_din;
140 | end else
141 | a_dout <= mem[a_addr];
142 | end
143 |
144 | always @(posedge b_clk) begin
145 | if(b_wr) begin
146 | b_dout <= b_din;
147 | mem[b_addr] <= b_din;
148 | end else
149 | b_dout <= mem[b_addr];
150 | end
151 |
152 | endmodule
153 |
--------------------------------------------------------------------------------
/src/fpga/apf/io_bridge_peripheral.v:
--------------------------------------------------------------------------------
1 | // Software License Agreement
2 |
3 | // The software supplied herewith by Analogue Enterprises Limited (the "Company”),
4 | // the Analogue Pocket Framework (“APF”), is provided and licensed to you, the
5 | // Company's customer, solely for use in designing, testing and creating
6 | // applications for use with Company's Products or Services. The software is
7 | // owned by the Company and/or its licensors, and is protected under applicable
8 | // laws, including, but not limited to, U.S. copyright law. All rights are
9 | // reserved. By using the APF code you are agreeing to the terms of the End User
10 | // License Agreement (“EULA”) located at [https://www.analogue.link/pocket-eula]
11 | // and incorporated herein by reference. To the extent any use of the APF requires
12 | // application of the MIT License or the GNU General Public License and terms of
13 | // this APF Software License Agreement and EULA are inconsistent with such license,
14 | // the applicable terms of the MIT License or the GNU General Public License, as
15 | // applicable, will prevail.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS-IS" AND WE EXPRESSLY DISCLAIM ANY IMPLIED
18 | // WARRANTIES TO THE FULLEST EXTENT PROVIDED BY LAW, INCLUDING BUT NOT LIMITED TO,
19 | // ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE OR
20 | // NON-INFRINGEMENT. TO THE EXTENT APPLICABLE LAWS PROHIBIT TERMS OF USE FROM
21 | // DISCLAIMING ANY IMPLIED WARRANTY, SUCH IMPLIED WARRANTY SHALL BE LIMITED TO THE
22 | // MINIMUM WARRANTY PERIOD REQUIRED BY LAW, AND IF NO SUCH PERIOD IS REQUIRED,
23 | // THEN THIRTY (30) DAYS FROM FIRST USE OF THE SOFTWARE. WE CANNOT GUARANTEE AND
24 | // DO NOT PROMISE ANY SPECIFIC RESULTS FROM USE OF THE SOFTWARE. WITHOUT LIMITING
25 | // THE FOREGOING, WE DO NOT WARRANT THAT THE SOFTWARE WILL BE UNINTERRUPTED OR
26 | // ERROR-FREE. IN NO EVENT WILL WE BE LIABLE TO YOU OR ANY OTHER PERSON FOR ANY
27 | // INDIRECT, CONSEQUENTIAL, EXEMPLARY, INCIDENTAL, SPECIAL OR PUNITIVE DAMAGES,
28 | // INCLUDING BUT NOT LIMITED TO, LOST PROFITS ARISING OUT OF YOUR USE, OR
29 | // INABILITY TO USE, THE SOFTWARE, EVEN IF WE HAVE BEEN ADVISED OF THE POSSIBILITY
30 | // OF SUCH DAMAGES. UNDER NO CIRCUMSTANCES SHALL OUR LIABILITY TO YOU FOR ANY
31 | // CLAIM OR CAUSE OF ACTION WHATSOEVER, AND REGARDLESS OF THE FORM OF THE ACTION,
32 | // WHETHER ARISING IN CONTRACT, TORT OR OTHERWISE, EXCEED THE AMOUNT PAID BY YOU
33 | // TO US, IF ANY, DURING THE 90 DAY PERIOD IMMEDIATELY PRECEDING THE DATE ON WHICH
34 | // YOU FIRST ASSERT ANY SUCH CLAIM. THE FOREGOING LIMITATIONS SHALL APPLY TO THE
35 | // FULLEST EXTENT PERMITTED BY APPLICABLE LAW.
36 | //
37 | // bridge peripheral for socrates PMP bridge to heraclitus+aristotle
38 | // 2020-2022 Analogue
39 | //
40 | // please note that while writes are immediate,
41 | // reads are buffered by 1 word. this is necessary to maintain
42 | // data throughput while reading from slower data sources like
43 | // sdram.
44 | // reads should always return the current bus value, and kickstart
45 | // into the next read immediately. this way, you have the entire
46 | // next word time to retrieve the data, instead of just a few
47 | // cycles.
48 | //
49 | // the worst-case read/write timing is every 88 cycles @ 74.25mhz
50 | // which is about 1180ns.
51 |
52 | module io_bridge_peripheral (
53 |
54 | input wire clk,
55 | input wire reset_n,
56 |
57 | input wire endian_little,
58 |
59 | output reg [31:0] pmp_addr,
60 | output reg pmp_addr_valid,
61 | output reg pmp_rd,
62 | input wire [31:0] pmp_rd_data,
63 | output reg pmp_wr,
64 | output reg [31:0] pmp_wr_data,
65 |
66 | inout reg phy_spimosi,
67 | inout reg phy_spimiso,
68 | inout reg phy_spiclk,
69 | input wire phy_spiss
70 |
71 | );
72 |
73 | //
74 | // clock domain: clk (74.25mhz) rising edge
75 | //
76 | wire reset_n_s;
77 | synch_3 s00(reset_n, reset_n_s, clk);
78 |
79 | wire endian_little_s;
80 | synch_3 s01(endian_little, endian_little_s, clk);
81 |
82 | wire phy_spiss_s, phy_spiss_r, phy_spiss_f;
83 | synch_3 s02(phy_spiss, phy_spiss_s, clk, phy_spiss_r, phy_spiss_f);
84 |
85 |
86 | reg [4:0] state;
87 | localparam ST_RESET = 'd0;
88 | localparam ST_IDLE = 'd1;
89 | localparam ST_READ_0 = 'd2;
90 | localparam ST_READ_1 = 'd3;
91 | localparam ST_READ_2 = 'd4;
92 | localparam ST_READ_3 = 'd5;
93 | localparam ST_WRITE_0 = 'd6;
94 | localparam ST_WRITE_1 = 'd7;
95 | localparam ST_WRITE_2 = 'd8;
96 | localparam ST_ADDR_0 = 'd9;
97 |
98 | reg [1:0] addr_cnt;
99 | reg [1:0] data_cnt;
100 | reg [6:0] read_cnt;
101 |
102 | // synchronize rd byte flag's rising edge into clk
103 | wire rx_byte_done_s, rx_byte_done_r;
104 | synch_3 s03(rx_byte_done, rx_byte_done_s, clk, rx_byte_done_r);
105 |
106 | reg [4:0] spis;
107 | localparam ST_SIDLE = 'd1;
108 | localparam ST_SEND_N = 'd6;
109 | localparam ST_SEND_0 = 'd2;
110 | localparam ST_SEND_1 = 'd3;
111 | localparam ST_SEND_2 = 'd4;
112 | localparam ST_SEND_3 = 'd5;
113 | reg spis_tx;
114 | reg [31:0] spis_word_tx;
115 | reg [31:0] spis_word;
116 | reg [4:0] spis_count;
117 | reg spis_done;
118 |
119 | reg rx_byte_done_r_1, rx_byte_done_r_2;
120 | reg [7:0] rx_byte_1, rx_byte_2;
121 |
122 | // handle reversing endianness on both ports
123 | reg [31:0] pmp_wr_data_latch;
124 | reg [31:0] pmp_rd_data_e; // asynchronous
125 | reg [31:0] pmp_rd_data_buf; // buffer the last word for immediate response
126 | always @(*) begin
127 | pmp_wr_data <= endian_little_s ? { pmp_wr_data_latch[7:0],
128 | pmp_wr_data_latch[15:8],
129 | pmp_wr_data_latch[23:16],
130 | pmp_wr_data_latch[31:24]
131 | } : pmp_wr_data_latch;
132 |
133 | pmp_rd_data_e <= endian_little_s ? {pmp_rd_data[7:0],
134 | pmp_rd_data[15:8],
135 | pmp_rd_data[23:16],
136 | pmp_rd_data[31:24]
137 | } : pmp_rd_data;
138 | end
139 |
140 | always @(posedge clk) begin
141 |
142 | rx_byte_2 <= rx_byte_1;
143 | rx_byte_1 <= rx_byte;
144 |
145 | rx_byte_done_r_1 <= rx_byte_done_r;
146 | rx_byte_done_r_2 <= rx_byte_done_r_1;
147 |
148 | case(state)
149 | ST_RESET: begin
150 | addr_cnt <= 0;
151 | data_cnt <= 0;
152 | pmp_wr <= 0;
153 | pmp_rd <= 0;
154 | pmp_addr_valid <= 0;
155 | spis_tx <= 0;
156 |
157 | state <= ST_ADDR_0;
158 | end
159 | ST_ADDR_0: begin
160 | // transaction has started
161 |
162 | if(rx_byte_done_r_2) begin
163 | case(addr_cnt)
164 | 0: pmp_addr[31:24] <= rx_byte_2;
165 | 1: pmp_addr[23:16] <= rx_byte_2;
166 | 2: pmp_addr[15: 8] <= rx_byte_2;
167 | 3: begin
168 | pmp_addr[ 7: 0] <= {rx_byte_2[7:2], 2'b00};
169 | // address is latched
170 | if( rx_byte_2[0] ) begin
171 | data_cnt <= 0;
172 | state <= ST_WRITE_0;
173 | end else begin
174 | data_cnt <= 0;
175 | read_cnt <= 0;
176 | state <= ST_READ_0;
177 | end
178 | end
179 | endcase
180 |
181 | addr_cnt <= addr_cnt + 1'b1;
182 | end
183 | end
184 | ST_WRITE_0: begin
185 | // give notice, address has become valid
186 | pmp_addr_valid <= 1;
187 |
188 | if(rx_byte_done_r_2) begin
189 | case(data_cnt)
190 | 0: pmp_wr_data_latch[31:24] <= rx_byte_2;
191 | 1: pmp_wr_data_latch[23:16] <= rx_byte_2;
192 | 2: pmp_wr_data_latch[15: 8] <= rx_byte_2;
193 | 3: begin
194 | pmp_wr_data_latch[ 7: 0] <= rx_byte_2;
195 | state <= ST_WRITE_1;
196 | end
197 | endcase
198 | data_cnt <= data_cnt + 1'b1;
199 | end
200 | end
201 | ST_WRITE_1: begin
202 | pmp_wr <= 1;
203 | state <= ST_WRITE_2;
204 | end
205 | ST_WRITE_2: begin
206 | // exited upon new transaction
207 | pmp_wr <= 0;
208 | end
209 | ST_READ_0: begin
210 | pmp_addr_valid <= 1;
211 |
212 | // delay a few cycles
213 | read_cnt <= read_cnt + 1'b1;
214 | if(read_cnt == 4-1) begin
215 | // load the buffer with the current data
216 | // and give the current buffer contents to bridge
217 | spis_word_tx <= pmp_rd_data_e;
218 | spis_tx <= 1;
219 |
220 | state <= ST_READ_1;
221 | end
222 | end
223 | ST_READ_1: begin
224 | pmp_rd <= 1;
225 | state <= ST_READ_2;
226 | end
227 | ST_READ_2: begin
228 | pmp_rd <= 0;
229 | if(spis_done) begin
230 | spis_tx <= 0;
231 | state <= ST_READ_3;
232 | end
233 | end
234 | ST_READ_3: begin
235 | // exited upon new transaction
236 | end
237 | endcase
238 |
239 |
240 |
241 |
242 | //
243 | // word transmit
244 | //
245 | spis_done <= 0;
246 | case(spis)
247 | ST_SIDLE: begin
248 | spis_count <= 0;
249 |
250 | phy_spiclk <= 1'bZ;
251 | phy_spimosi <= 1'bZ;
252 | phy_spimiso <= 1'bZ;
253 |
254 | if(spis_tx) begin
255 | spis_word <= spis_word_tx;
256 | spis <= ST_SEND_N;
257 | end
258 | end
259 | // drive high first
260 | ST_SEND_N: begin
261 | phy_spiclk <= 1'b1;
262 | phy_spimosi <= 1'b1;
263 | phy_spimiso <= 1'b1;
264 | spis <= ST_SEND_0;
265 | end
266 | // tx, shift out bits
267 | ST_SEND_0: begin
268 | phy_spiclk <= 0;
269 | spis <= ST_SEND_1;
270 | phy_spimosi <= spis_word[31];
271 | phy_spimiso <= spis_word[30];
272 | spis_word <= {spis_word[29:0], 2'b00};
273 | end
274 | ST_SEND_1: begin
275 | phy_spiclk <= 1;
276 | spis <= ST_SEND_0;
277 | spis_count <= spis_count + 1'b1;
278 | if(spis_count == 15) spis <= ST_SEND_2;
279 | end
280 | ST_SEND_2: begin
281 | phy_spiclk <= 1'b1;
282 | phy_spimosi <= 1'b1;
283 | phy_spimiso <= 1'b1;
284 | spis <= ST_SEND_3;
285 | spis_done <= 1;
286 | end
287 | ST_SEND_3: begin
288 | spis <= ST_SIDLE;
289 | end
290 | endcase
291 |
292 | if(phy_spiss_s) begin
293 | // select is high, go back to reset
294 | state <= ST_RESET;
295 | spis <= ST_SIDLE;
296 | end
297 |
298 | end
299 |
300 |
301 | //
302 | // clock domain: phy_spiclk rising edge
303 | //
304 | reg [1:0] rx_latch_idx;
305 | reg [7:0] rx_dat;
306 | reg [7:0] rx_byte; // latched by clk, but upon a synchronized trigger
307 | reg rx_byte_done;
308 |
309 | always @(posedge phy_spiclk or posedge phy_spiss) begin
310 |
311 | if(phy_spiss) begin
312 | // reset
313 | rx_byte_done <= 0;
314 | rx_latch_idx <= 0;
315 |
316 | end else begin
317 | // spiclk rising edge, latch data
318 | rx_byte_done <= 0;
319 |
320 | case(rx_latch_idx)
321 | 0: begin rx_dat[7:6] <= {phy_spimosi, phy_spimiso}; rx_latch_idx <= 1; end
322 | 1: begin rx_dat[5:4] <= {phy_spimosi, phy_spimiso}; rx_latch_idx <= 2; end
323 | 2: begin rx_dat[3:2] <= {phy_spimosi, phy_spimiso}; rx_latch_idx <= 3; end
324 | 3: begin
325 | // final 2 bits
326 | rx_byte <= {rx_dat[7:2], phy_spimosi, phy_spimiso};
327 | rx_latch_idx <= 0;
328 | rx_byte_done <= 1;
329 | end
330 | endcase
331 | end
332 | end
333 |
334 | endmodule
--------------------------------------------------------------------------------
/src/fpga/apf/io_pad_controller.v:
--------------------------------------------------------------------------------
1 | // Software License Agreement
2 |
3 | // The software supplied herewith by Analogue Enterprises Limited (the "Company”),
4 | // the Analogue Pocket Framework (“APF”), is provided and licensed to you, the
5 | // Company's customer, solely for use in designing, testing and creating
6 | // applications for use with Company's Products or Services. The software is
7 | // owned by the Company and/or its licensors, and is protected under applicable
8 | // laws, including, but not limited to, U.S. copyright law. All rights are
9 | // reserved. By using the APF code you are agreeing to the terms of the End User
10 | // License Agreement (“EULA”) located at [https://www.analogue.link/pocket-eula]
11 | // and incorporated herein by reference. To the extent any use of the APF requires
12 | // application of the MIT License or the GNU General Public License and terms of
13 | // this APF Software License Agreement and EULA are inconsistent with such license,
14 | // the applicable terms of the MIT License or the GNU General Public License, as
15 | // applicable, will prevail.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS-IS" AND WE EXPRESSLY DISCLAIM ANY IMPLIED
18 | // WARRANTIES TO THE FULLEST EXTENT PROVIDED BY LAW, INCLUDING BUT NOT LIMITED TO,
19 | // ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE OR
20 | // NON-INFRINGEMENT. TO THE EXTENT APPLICABLE LAWS PROHIBIT TERMS OF USE FROM
21 | // DISCLAIMING ANY IMPLIED WARRANTY, SUCH IMPLIED WARRANTY SHALL BE LIMITED TO THE
22 | // MINIMUM WARRANTY PERIOD REQUIRED BY LAW, AND IF NO SUCH PERIOD IS REQUIRED,
23 | // THEN THIRTY (30) DAYS FROM FIRST USE OF THE SOFTWARE. WE CANNOT GUARANTEE AND
24 | // DO NOT PROMISE ANY SPECIFIC RESULTS FROM USE OF THE SOFTWARE. WITHOUT LIMITING
25 | // THE FOREGOING, WE DO NOT WARRANT THAT THE SOFTWARE WILL BE UNINTERRUPTED OR
26 | // ERROR-FREE. IN NO EVENT WILL WE BE LIABLE TO YOU OR ANY OTHER PERSON FOR ANY
27 | // INDIRECT, CONSEQUENTIAL, EXEMPLARY, INCIDENTAL, SPECIAL OR PUNITIVE DAMAGES,
28 | // INCLUDING BUT NOT LIMITED TO, LOST PROFITS ARISING OUT OF YOUR USE, OR
29 | // INABILITY TO USE, THE SOFTWARE, EVEN IF WE HAVE BEEN ADVISED OF THE POSSIBILITY
30 | // OF SUCH DAMAGES. UNDER NO CIRCUMSTANCES SHALL OUR LIABILITY TO YOU FOR ANY
31 | // CLAIM OR CAUSE OF ACTION WHATSOEVER, AND REGARDLESS OF THE FORM OF THE ACTION,
32 | // WHETHER ARISING IN CONTRACT, TORT OR OTHERWISE, EXCEED THE AMOUNT PAID BY YOU
33 | // TO US, IF ANY, DURING THE 90 DAY PERIOD IMMEDIATELY PRECEDING THE DATE ON WHICH
34 | // YOU FIRST ASSERT ANY SUCH CLAIM. THE FOREGOING LIMITATIONS SHALL APPLY TO THE
35 | // FULLEST EXTENT PERMITTED BY APPLICABLE LAW.
36 | //
37 | // pad controller
38 | // 2020-08-17 Analogue
39 | //
40 |
41 | module io_pad_controller (
42 |
43 | input wire clk,
44 | input wire reset_n,
45 |
46 | inout reg pad_1wire,
47 |
48 | output reg [31:0] cont1_key,
49 | output reg [31:0] cont2_key,
50 | output reg [31:0] cont3_key,
51 | output reg [31:0] cont4_key,
52 | output reg [31:0] cont1_joy,
53 | output reg [31:0] cont2_joy,
54 | output reg [31:0] cont3_joy,
55 | output reg [31:0] cont4_joy,
56 | output reg [15:0] cont1_trig,
57 | output reg [15:0] cont2_trig,
58 | output reg [15:0] cont3_trig,
59 | output reg [15:0] cont4_trig,
60 |
61 | output reg rx_timed_out
62 | );
63 |
64 | wire reset_n_s;
65 | synch_3 s00(reset_n, reset_n_s, clk);
66 |
67 | wire pad_1wire_s, pad_1wire_r, pad_1wire_f;
68 | synch_3 s01(pad_1wire, pad_1wire_s, clk, pad_1wire_r, pad_1wire_f);
69 |
70 |
71 | //
72 | // protocol fsm
73 | //
74 |
75 | reg [20:0] rx_timeout; // ~28ms
76 |
77 | reg [15:0] auto_poll_cnt; // 882us
78 | reg auto_poll_queue;
79 |
80 | reg [18:0] heartbeat_cnt; // 7ms
81 | reg heartbeat_queue;
82 |
83 |
84 | localparam ST_RESET = 'd0;
85 | localparam ST_IDLE = 'd1;
86 | localparam ST_RX_BUTTON_1 = 'd2;
87 | localparam ST_RX_BUTTON_2 = 'd3;
88 | localparam ST_TX_SCALER = 'd4;
89 | localparam ST_END_TX = 'd5;
90 |
91 | reg [3:0] state;
92 | reg [3:0] cnt;
93 |
94 | always @(posedge clk) begin
95 | tx_word_start <= 0;
96 |
97 | auto_poll_cnt <= auto_poll_cnt + 1'b1;
98 | heartbeat_cnt <= heartbeat_cnt + 1'b1;
99 |
100 | // increment rx timeout, override and reset when idle below
101 | rx_timeout <= rx_timeout + 1'b1;
102 |
103 | case(state)
104 | ST_RESET: begin
105 | reset_tr_n <= 0;
106 | rx_timed_out <= 0;
107 |
108 | if(&rx_timeout[19:0]) begin
109 | state <= ST_IDLE;
110 | end
111 | end
112 | ST_IDLE: begin
113 | // idle state
114 | reset_tr_n <= 1;
115 | rx_timeout <= 0;
116 | cnt <= 0;
117 | if(auto_poll_queue) begin
118 | auto_poll_queue <= 0;
119 |
120 | tx_word_start <= 1;
121 | tx_word <= 32'h4A10000C;
122 |
123 | state <= ST_RX_BUTTON_1;
124 | end else if(heartbeat_queue) begin
125 | heartbeat_queue <= 0;
126 |
127 | tx_word_start <= 1;
128 | tx_word <= 32'h4AFE0000;
129 |
130 | state <= ST_END_TX;
131 | end
132 | end
133 | // receive button words
134 | ST_RX_BUTTON_1: begin
135 | if(tx_word_done) begin
136 | state <= ST_RX_BUTTON_2;
137 | end
138 | end
139 | ST_RX_BUTTON_2: begin
140 | if(rx_word_done) begin
141 | cnt <= cnt + 1'b1;
142 | case(cnt)
143 | 0: cont1_key <= rx_word;
144 | 1: cont1_joy <= rx_word;
145 | 2: cont1_trig <= rx_word[15:0];
146 |
147 | 3: cont2_key <= rx_word;
148 | 4: cont2_joy <= rx_word;
149 | 5: cont2_trig <= rx_word[15:0];
150 |
151 | 6: cont3_key <= rx_word;
152 | 7: cont3_joy <= rx_word;
153 | 8: cont3_trig <= rx_word[15:0];
154 |
155 | 9: cont4_key <= rx_word;
156 | 10: cont4_joy <= rx_word;
157 | 11: begin
158 | cont4_trig <= rx_word[15:0];
159 | state <= ST_IDLE;
160 | end
161 | endcase
162 | end
163 | end
164 | // do nothing
165 | ST_END_TX: begin
166 | // done sending, idle again
167 | if(tx_word_done) begin
168 | state <= ST_IDLE;
169 | end
170 | end
171 | endcase
172 |
173 |
174 | if(&auto_poll_cnt) begin
175 | auto_poll_queue <= 1;
176 | end
177 | if(&heartbeat_cnt) begin
178 | heartbeat_queue <= 1;
179 | end
180 |
181 | if(&rx_timeout) begin
182 | // reset protocol FSM which will also reset t/r engine
183 | rx_timed_out <= 1;
184 | rx_timeout <= 0;
185 | state <= ST_RESET;
186 | end
187 |
188 | if(~reset_n_s) begin
189 | state <= ST_RESET;
190 | end
191 | end
192 |
193 |
194 |
195 |
196 |
197 | //
198 | // word receive/transmit engine
199 | //
200 | reg reset_tr_n;
201 | localparam BITLEN = 60;
202 |
203 | reg rx_word_done;
204 | reg [31:0] rx_word_shift;
205 | reg [31:0] rx_word;
206 |
207 | reg tx_word_start, tx_word_start_1;
208 | reg tx_word_done;
209 | reg [31:0] tx_word;
210 | reg [31:0] tx_word_shift;
211 |
212 | reg [7:0] tr_cnt;
213 | reg [5:0] tr_bit;
214 |
215 | localparam TR_IDLE = 'd1;
216 | localparam TR_TX_START = 'd2;
217 | localparam TR_TX_CONTINUE = 'd3;
218 | localparam TR_TX_DONE = 'd4;
219 | localparam TR_RX_START = 'd5;
220 | localparam TR_RX_WAITEDGE = 'd6;
221 | localparam TR_RX_DONE = 'd7;
222 |
223 | reg [3:0] tr_state;
224 |
225 | always @(posedge clk) begin
226 |
227 | rx_word_done <= 0;
228 | tx_word_done <= 0;
229 |
230 | tx_word_start_1 <= tx_word_start;
231 |
232 | case(tr_state)
233 | TR_IDLE: begin
234 | tr_bit <= 0;
235 | tr_cnt <= 0;
236 |
237 | pad_1wire <= 1'bZ;
238 |
239 | if(tx_word_start & ~tx_word_start_1) begin
240 | // transmit word
241 | tx_word_shift <= tx_word;
242 | tr_state <= TR_TX_START;
243 | end
244 |
245 | if(pad_1wire_f) begin
246 | // receive word
247 | tr_state <= TR_RX_START;
248 | end
249 | end
250 |
251 | // transmit 32bit
252 | TR_TX_START: begin
253 | // insert delay
254 | tr_cnt <= tr_cnt + 1'b1;
255 | if(&tr_cnt) begin
256 | // drive from tristate(high) to explicitly high to prevent glitching
257 | pad_1wire <= 1'b1;
258 | tr_state <= TR_TX_CONTINUE;
259 | end
260 | end
261 | TR_TX_CONTINUE: begin
262 | tr_cnt <= tr_cnt + 1'b1;
263 | case(tr_cnt)
264 | 0: begin
265 | pad_1wire <= 1'b0;
266 | end
267 | (BITLEN/3): begin
268 | pad_1wire <= tx_word_shift[31];
269 | end
270 | (BITLEN*2/3): begin
271 | pad_1wire <= 1'b1;
272 | end
273 | (BITLEN-1): begin
274 | tr_cnt <= 0;
275 | tx_word_shift <= {tx_word_shift[30:0], 1'b1};
276 |
277 | tr_bit <= tr_bit + 1'b1;
278 | if(tr_bit == 31) begin
279 | tr_state <= TR_TX_DONE;
280 | end
281 | end
282 | endcase
283 | end
284 | TR_TX_DONE: begin
285 | tx_word_done <= 1;
286 | tr_state <= TR_IDLE;
287 | end
288 |
289 | // receive 32bit
290 | TR_RX_START: begin
291 | tr_cnt <= tr_cnt + 1'b1;
292 | case(tr_cnt)
293 | (BITLEN/2-4): begin
294 | rx_word_shift <= {rx_word_shift[30:0], pad_1wire_s};
295 | end
296 | (BITLEN*5/6): begin
297 | tr_cnt <= 0;
298 |
299 | // wait for next falling edge
300 | tr_state <= TR_RX_WAITEDGE;
301 | tr_bit <= tr_bit + 1'b1;
302 | if(tr_bit == 31) begin
303 | // if this is bit32, don't wait and finish
304 | tr_state <= TR_RX_DONE;
305 | end
306 | end
307 | endcase
308 | end
309 | TR_RX_WAITEDGE: begin
310 | if(pad_1wire_f) begin
311 | tr_state <= TR_RX_START;
312 | end
313 | end
314 | TR_RX_DONE: begin
315 | rx_word <= rx_word_shift;
316 | rx_word_done <= 1;
317 | tr_state <= TR_IDLE;
318 | end
319 |
320 | default: begin
321 | tr_state <= TR_IDLE;
322 | end
323 | endcase
324 |
325 | if(~reset_n_s | ~reset_tr_n) tr_state <= TR_IDLE;
326 | end
327 |
328 | endmodule
--------------------------------------------------------------------------------
/src/fpga/apf/mf_datatable.qip:
--------------------------------------------------------------------------------
1 | set_global_assignment -name IP_TOOL_NAME "RAM: 2-PORT"
2 | set_global_assignment -name IP_TOOL_VERSION "18.1"
3 | set_global_assignment -name IP_GENERATED_DEVICE_FAMILY "{Cyclone V}"
4 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "mf_datatable.v"]
5 |
--------------------------------------------------------------------------------
/src/fpga/apf/mf_datatable.v:
--------------------------------------------------------------------------------
1 | // megafunction wizard: %RAM: 2-PORT%
2 | // GENERATION: STANDARD
3 | // VERSION: WM1.0
4 | // MODULE: altsyncram
5 |
6 | // ============================================================
7 | // File Name: mf_datatable.v
8 | // Megafunction Name(s):
9 | // altsyncram
10 | //
11 | // Simulation Library Files(s):
12 | // altera_mf
13 | // ============================================================
14 | // ************************************************************
15 | // THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
16 | //
17 | // 18.1.1 Build 646 04/11/2019 SJ Lite Edition
18 | // ************************************************************
19 |
20 |
21 | //Copyright (C) 2019 Intel Corporation. All rights reserved.
22 | //Your use of Intel Corporation's design tools, logic functions
23 | //and other software and tools, and any partner logic
24 | //functions, and any output files from any of the foregoing
25 | //(including device programming or simulation files), and any
26 | //associated documentation or information are expressly subject
27 | //to the terms and conditions of the Intel Program License
28 | //Subscription Agreement, the Intel Quartus Prime License Agreement,
29 | //the Intel FPGA IP License Agreement, or other applicable license
30 | //agreement, including, without limitation, that your use is for
31 | //the sole purpose of programming logic devices manufactured by
32 | //Intel and sold by Intel or its authorized distributors. Please
33 | //refer to the applicable agreement for further details, at
34 | //https://fpgasoftware.intel.com/eula.
35 |
36 |
37 | // synopsys translate_off
38 | `timescale 1 ps / 1 ps
39 | // synopsys translate_on
40 | module mf_datatable (
41 | address_a,
42 | address_b,
43 | clock_a,
44 | clock_b,
45 | data_a,
46 | data_b,
47 | wren_a,
48 | wren_b,
49 | q_a,
50 | q_b);
51 |
52 | input [7:0] address_a;
53 | input [7:0] address_b;
54 | input clock_a;
55 | input clock_b;
56 | input [31:0] data_a;
57 | input [31:0] data_b;
58 | input wren_a;
59 | input wren_b;
60 | output [31:0] q_a;
61 | output [31:0] q_b;
62 | `ifndef ALTERA_RESERVED_QIS
63 | // synopsys translate_off
64 | `endif
65 | tri1 clock_a;
66 | tri0 wren_a;
67 | tri0 wren_b;
68 | `ifndef ALTERA_RESERVED_QIS
69 | // synopsys translate_on
70 | `endif
71 |
72 | wire [31:0] sub_wire0;
73 | wire [31:0] sub_wire1;
74 | wire [31:0] q_a = sub_wire0[31:0];
75 | wire [31:0] q_b = sub_wire1[31:0];
76 |
77 | altsyncram altsyncram_component (
78 | .address_a (address_a),
79 | .address_b (address_b),
80 | .clock0 (clock_a),
81 | .clock1 (clock_b),
82 | .data_a (data_a),
83 | .data_b (data_b),
84 | .wren_a (wren_a),
85 | .wren_b (wren_b),
86 | .q_a (sub_wire0),
87 | .q_b (sub_wire1),
88 | .aclr0 (1'b0),
89 | .aclr1 (1'b0),
90 | .addressstall_a (1'b0),
91 | .addressstall_b (1'b0),
92 | .byteena_a (1'b1),
93 | .byteena_b (1'b1),
94 | .clocken0 (1'b1),
95 | .clocken1 (1'b1),
96 | .clocken2 (1'b1),
97 | .clocken3 (1'b1),
98 | .eccstatus (),
99 | .rden_a (1'b1),
100 | .rden_b (1'b1));
101 | defparam
102 | altsyncram_component.address_reg_b = "CLOCK1",
103 | altsyncram_component.clock_enable_input_a = "BYPASS",
104 | altsyncram_component.clock_enable_input_b = "BYPASS",
105 | altsyncram_component.clock_enable_output_a = "BYPASS",
106 | altsyncram_component.clock_enable_output_b = "BYPASS",
107 | altsyncram_component.indata_reg_b = "CLOCK1",
108 | altsyncram_component.init_file = "./apf/build_id.mif",
109 | altsyncram_component.intended_device_family = "Cyclone V",
110 | altsyncram_component.lpm_type = "altsyncram",
111 | altsyncram_component.numwords_a = 256,
112 | altsyncram_component.numwords_b = 256,
113 | altsyncram_component.operation_mode = "BIDIR_DUAL_PORT",
114 | altsyncram_component.outdata_aclr_a = "NONE",
115 | altsyncram_component.outdata_aclr_b = "NONE",
116 | altsyncram_component.outdata_reg_a = "CLOCK0",
117 | altsyncram_component.outdata_reg_b = "CLOCK1",
118 | altsyncram_component.power_up_uninitialized = "FALSE",
119 | altsyncram_component.read_during_write_mode_port_a = "NEW_DATA_NO_NBE_READ",
120 | altsyncram_component.read_during_write_mode_port_b = "NEW_DATA_NO_NBE_READ",
121 | altsyncram_component.widthad_a = 8,
122 | altsyncram_component.widthad_b = 8,
123 | altsyncram_component.width_a = 32,
124 | altsyncram_component.width_b = 32,
125 | altsyncram_component.width_byteena_a = 1,
126 | altsyncram_component.width_byteena_b = 1,
127 | altsyncram_component.wrcontrol_wraddress_reg_b = "CLOCK1";
128 |
129 |
130 | endmodule
131 |
132 | // ============================================================
133 | // CNX file retrieval info
134 | // ============================================================
135 | // Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0"
136 | // Retrieval info: PRIVATE: ADDRESSSTALL_B NUMERIC "0"
137 | // Retrieval info: PRIVATE: BYTEENA_ACLR_A NUMERIC "0"
138 | // Retrieval info: PRIVATE: BYTEENA_ACLR_B NUMERIC "0"
139 | // Retrieval info: PRIVATE: BYTE_ENABLE_A NUMERIC "0"
140 | // Retrieval info: PRIVATE: BYTE_ENABLE_B NUMERIC "0"
141 | // Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8"
142 | // Retrieval info: PRIVATE: BlankMemory NUMERIC "0"
143 | // Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0"
144 | // Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_B NUMERIC "0"
145 | // Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0"
146 | // Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_B NUMERIC "0"
147 | // Retrieval info: PRIVATE: CLRdata NUMERIC "0"
148 | // Retrieval info: PRIVATE: CLRq NUMERIC "0"
149 | // Retrieval info: PRIVATE: CLRrdaddress NUMERIC "0"
150 | // Retrieval info: PRIVATE: CLRrren NUMERIC "0"
151 | // Retrieval info: PRIVATE: CLRwraddress NUMERIC "0"
152 | // Retrieval info: PRIVATE: CLRwren NUMERIC "0"
153 | // Retrieval info: PRIVATE: Clock NUMERIC "5"
154 | // Retrieval info: PRIVATE: Clock_A NUMERIC "0"
155 | // Retrieval info: PRIVATE: Clock_B NUMERIC "0"
156 | // Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0"
157 | // Retrieval info: PRIVATE: INDATA_ACLR_B NUMERIC "0"
158 | // Retrieval info: PRIVATE: INDATA_REG_B NUMERIC "1"
159 | // Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A"
160 | // Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0"
161 | // Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone V"
162 | // Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0"
163 | // Retrieval info: PRIVATE: JTAG_ID STRING "NONE"
164 | // Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0"
165 | // Retrieval info: PRIVATE: MEMSIZE NUMERIC "8192"
166 | // Retrieval info: PRIVATE: MEM_IN_BITS NUMERIC "0"
167 | // Retrieval info: PRIVATE: MIFfilename STRING "./apf/build_id.mif"
168 | // Retrieval info: PRIVATE: OPERATION_MODE NUMERIC "3"
169 | // Retrieval info: PRIVATE: OUTDATA_ACLR_B NUMERIC "0"
170 | // Retrieval info: PRIVATE: OUTDATA_REG_B NUMERIC "1"
171 | // Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0"
172 | // Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_MIXED_PORTS NUMERIC "2"
173 | // Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_A NUMERIC "3"
174 | // Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_B NUMERIC "3"
175 | // Retrieval info: PRIVATE: REGdata NUMERIC "1"
176 | // Retrieval info: PRIVATE: REGq NUMERIC "1"
177 | // Retrieval info: PRIVATE: REGrdaddress NUMERIC "0"
178 | // Retrieval info: PRIVATE: REGrren NUMERIC "0"
179 | // Retrieval info: PRIVATE: REGwraddress NUMERIC "1"
180 | // Retrieval info: PRIVATE: REGwren NUMERIC "1"
181 | // Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
182 | // Retrieval info: PRIVATE: USE_DIFF_CLKEN NUMERIC "0"
183 | // Retrieval info: PRIVATE: UseDPRAM NUMERIC "1"
184 | // Retrieval info: PRIVATE: VarWidth NUMERIC "0"
185 | // Retrieval info: PRIVATE: WIDTH_READ_A NUMERIC "32"
186 | // Retrieval info: PRIVATE: WIDTH_READ_B NUMERIC "32"
187 | // Retrieval info: PRIVATE: WIDTH_WRITE_A NUMERIC "32"
188 | // Retrieval info: PRIVATE: WIDTH_WRITE_B NUMERIC "32"
189 | // Retrieval info: PRIVATE: WRADDR_ACLR_B NUMERIC "0"
190 | // Retrieval info: PRIVATE: WRADDR_REG_B NUMERIC "1"
191 | // Retrieval info: PRIVATE: WRCTRL_ACLR_B NUMERIC "0"
192 | // Retrieval info: PRIVATE: enable NUMERIC "0"
193 | // Retrieval info: PRIVATE: rden NUMERIC "0"
194 | // Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
195 | // Retrieval info: CONSTANT: ADDRESS_REG_B STRING "CLOCK1"
196 | // Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS"
197 | // Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_B STRING "BYPASS"
198 | // Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS"
199 | // Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_B STRING "BYPASS"
200 | // Retrieval info: CONSTANT: INDATA_REG_B STRING "CLOCK1"
201 | // Retrieval info: CONSTANT: INIT_FILE STRING "./apf/build_id.mif"
202 | // Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone V"
203 | // Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram"
204 | // Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "256"
205 | // Retrieval info: CONSTANT: NUMWORDS_B NUMERIC "256"
206 | // Retrieval info: CONSTANT: OPERATION_MODE STRING "BIDIR_DUAL_PORT"
207 | // Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE"
208 | // Retrieval info: CONSTANT: OUTDATA_ACLR_B STRING "NONE"
209 | // Retrieval info: CONSTANT: OUTDATA_REG_A STRING "CLOCK0"
210 | // Retrieval info: CONSTANT: OUTDATA_REG_B STRING "CLOCK1"
211 | // Retrieval info: CONSTANT: POWER_UP_UNINITIALIZED STRING "FALSE"
212 | // Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_PORT_A STRING "NEW_DATA_NO_NBE_READ"
213 | // Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_PORT_B STRING "NEW_DATA_NO_NBE_READ"
214 | // Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "8"
215 | // Retrieval info: CONSTANT: WIDTHAD_B NUMERIC "8"
216 | // Retrieval info: CONSTANT: WIDTH_A NUMERIC "32"
217 | // Retrieval info: CONSTANT: WIDTH_B NUMERIC "32"
218 | // Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1"
219 | // Retrieval info: CONSTANT: WIDTH_BYTEENA_B NUMERIC "1"
220 | // Retrieval info: CONSTANT: WRCONTROL_WRADDRESS_REG_B STRING "CLOCK1"
221 | // Retrieval info: USED_PORT: address_a 0 0 8 0 INPUT NODEFVAL "address_a[7..0]"
222 | // Retrieval info: USED_PORT: address_b 0 0 8 0 INPUT NODEFVAL "address_b[7..0]"
223 | // Retrieval info: USED_PORT: clock_a 0 0 0 0 INPUT VCC "clock_a"
224 | // Retrieval info: USED_PORT: clock_b 0 0 0 0 INPUT NODEFVAL "clock_b"
225 | // Retrieval info: USED_PORT: data_a 0 0 32 0 INPUT NODEFVAL "data_a[31..0]"
226 | // Retrieval info: USED_PORT: data_b 0 0 32 0 INPUT NODEFVAL "data_b[31..0]"
227 | // Retrieval info: USED_PORT: q_a 0 0 32 0 OUTPUT NODEFVAL "q_a[31..0]"
228 | // Retrieval info: USED_PORT: q_b 0 0 32 0 OUTPUT NODEFVAL "q_b[31..0]"
229 | // Retrieval info: USED_PORT: wren_a 0 0 0 0 INPUT GND "wren_a"
230 | // Retrieval info: USED_PORT: wren_b 0 0 0 0 INPUT GND "wren_b"
231 | // Retrieval info: CONNECT: @address_a 0 0 8 0 address_a 0 0 8 0
232 | // Retrieval info: CONNECT: @address_b 0 0 8 0 address_b 0 0 8 0
233 | // Retrieval info: CONNECT: @clock0 0 0 0 0 clock_a 0 0 0 0
234 | // Retrieval info: CONNECT: @clock1 0 0 0 0 clock_b 0 0 0 0
235 | // Retrieval info: CONNECT: @data_a 0 0 32 0 data_a 0 0 32 0
236 | // Retrieval info: CONNECT: @data_b 0 0 32 0 data_b 0 0 32 0
237 | // Retrieval info: CONNECT: @wren_a 0 0 0 0 wren_a 0 0 0 0
238 | // Retrieval info: CONNECT: @wren_b 0 0 0 0 wren_b 0 0 0 0
239 | // Retrieval info: CONNECT: q_a 0 0 32 0 @q_a 0 0 32 0
240 | // Retrieval info: CONNECT: q_b 0 0 32 0 @q_b 0 0 32 0
241 | // Retrieval info: GEN_FILE: TYPE_NORMAL mf_datatable.v TRUE
242 | // Retrieval info: GEN_FILE: TYPE_NORMAL mf_datatable.inc FALSE
243 | // Retrieval info: GEN_FILE: TYPE_NORMAL mf_datatable.cmp FALSE
244 | // Retrieval info: GEN_FILE: TYPE_NORMAL mf_datatable.bsf FALSE
245 | // Retrieval info: GEN_FILE: TYPE_NORMAL mf_datatable_inst.v FALSE
246 | // Retrieval info: GEN_FILE: TYPE_NORMAL mf_datatable_bb.v FALSE
247 | // Retrieval info: LIB_FILE: altera_mf
248 |
--------------------------------------------------------------------------------
/src/fpga/apf/mf_ddio_bidir_12.qip:
--------------------------------------------------------------------------------
1 | set_global_assignment -name IP_TOOL_NAME "ALTDDIO_BIDIR"
2 | set_global_assignment -name IP_TOOL_VERSION "18.1"
3 | set_global_assignment -name IP_GENERATED_DEVICE_FAMILY "{Cyclone V}"
4 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "mf_ddio_bidir_12.v"]
5 | set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "mf_ddio_bidir_12.ppf"]
6 |
--------------------------------------------------------------------------------
/src/fpga/apf/mf_ddio_bidir_12.v:
--------------------------------------------------------------------------------
1 | // megafunction wizard: %ALTDDIO_BIDIR%
2 | // GENERATION: STANDARD
3 | // VERSION: WM1.0
4 | // MODULE: ALTDDIO_BIDIR
5 |
6 | // ============================================================
7 | // File Name: mf_ddio_bidir_12.v
8 | // Megafunction Name(s):
9 | // ALTDDIO_BIDIR
10 | //
11 | // Simulation Library Files(s):
12 | // altera_mf
13 | // ============================================================
14 | // ************************************************************
15 | // THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
16 | //
17 | // 18.1.1 Build 646 04/11/2019 SJ Lite Edition
18 | // ************************************************************
19 |
20 |
21 | //Copyright (C) 2019 Intel Corporation. All rights reserved.
22 | //Your use of Intel Corporation's design tools, logic functions
23 | //and other software and tools, and any partner logic
24 | //functions, and any output files from any of the foregoing
25 | //(including device programming or simulation files), and any
26 | //associated documentation or information are expressly subject
27 | //to the terms and conditions of the Intel Program License
28 | //Subscription Agreement, the Intel Quartus Prime License Agreement,
29 | //the Intel FPGA IP License Agreement, or other applicable license
30 | //agreement, including, without limitation, that your use is for
31 | //the sole purpose of programming logic devices manufactured by
32 | //Intel and sold by Intel or its authorized distributors. Please
33 | //refer to the applicable agreement for further details, at
34 | //https://fpgasoftware.intel.com/eula.
35 |
36 |
37 | // synopsys translate_off
38 | `timescale 1 ps / 1 ps
39 | // synopsys translate_on
40 | module mf_ddio_bidir_12 (
41 | datain_h,
42 | datain_l,
43 | inclock,
44 | oe,
45 | outclock,
46 | dataout_h,
47 | dataout_l,
48 | padio);
49 |
50 | input [11:0] datain_h;
51 | input [11:0] datain_l;
52 | input inclock;
53 | input oe;
54 | input outclock;
55 | output [11:0] dataout_h;
56 | output [11:0] dataout_l;
57 | inout [11:0] padio;
58 |
59 | wire [11:0] sub_wire0;
60 | wire [11:0] sub_wire1;
61 | wire [11:0] dataout_h = sub_wire0[11:0];
62 | wire [11:0] dataout_l = sub_wire1[11:0];
63 |
64 | altddio_bidir ALTDDIO_BIDIR_component (
65 | .datain_h (datain_h),
66 | .datain_l (datain_l),
67 | .inclock (inclock),
68 | .oe (oe),
69 | .outclock (outclock),
70 | .padio (padio),
71 | .dataout_h (sub_wire0),
72 | .dataout_l (sub_wire1),
73 | .aclr (1'b0),
74 | .aset (1'b0),
75 | .combout (),
76 | .dqsundelayedout (),
77 | .inclocken (1'b1),
78 | .oe_out (),
79 | .outclocken (1'b1),
80 | .sclr (1'b0),
81 | .sset (1'b0));
82 | defparam
83 | ALTDDIO_BIDIR_component.extend_oe_disable = "OFF",
84 | ALTDDIO_BIDIR_component.implement_input_in_lcell = "OFF",
85 | ALTDDIO_BIDIR_component.intended_device_family = "Cyclone V",
86 | ALTDDIO_BIDIR_component.invert_output = "OFF",
87 | ALTDDIO_BIDIR_component.lpm_hint = "UNUSED",
88 | ALTDDIO_BIDIR_component.lpm_type = "altddio_bidir",
89 | ALTDDIO_BIDIR_component.oe_reg = "UNREGISTERED",
90 | ALTDDIO_BIDIR_component.power_up_high = "OFF",
91 | ALTDDIO_BIDIR_component.width = 12;
92 |
93 |
94 | endmodule
95 |
96 | // ============================================================
97 | // CNX file retrieval info
98 | // ============================================================
99 | // Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
100 | // Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone V"
101 | // Retrieval info: CONSTANT: EXTEND_OE_DISABLE STRING "OFF"
102 | // Retrieval info: CONSTANT: IMPLEMENT_INPUT_IN_LCELL STRING "OFF"
103 | // Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone V"
104 | // Retrieval info: CONSTANT: INVERT_OUTPUT STRING "OFF"
105 | // Retrieval info: CONSTANT: LPM_HINT STRING "UNUSED"
106 | // Retrieval info: CONSTANT: LPM_TYPE STRING "altddio_bidir"
107 | // Retrieval info: CONSTANT: OE_REG STRING "UNREGISTERED"
108 | // Retrieval info: CONSTANT: POWER_UP_HIGH STRING "OFF"
109 | // Retrieval info: CONSTANT: WIDTH NUMERIC "12"
110 | // Retrieval info: USED_PORT: datain_h 0 0 12 0 INPUT NODEFVAL "datain_h[11..0]"
111 | // Retrieval info: CONNECT: @datain_h 0 0 12 0 datain_h 0 0 12 0
112 | // Retrieval info: USED_PORT: datain_l 0 0 12 0 INPUT NODEFVAL "datain_l[11..0]"
113 | // Retrieval info: CONNECT: @datain_l 0 0 12 0 datain_l 0 0 12 0
114 | // Retrieval info: USED_PORT: dataout_h 0 0 12 0 OUTPUT NODEFVAL "dataout_h[11..0]"
115 | // Retrieval info: CONNECT: dataout_h 0 0 12 0 @dataout_h 0 0 12 0
116 | // Retrieval info: USED_PORT: dataout_l 0 0 12 0 OUTPUT NODEFVAL "dataout_l[11..0]"
117 | // Retrieval info: CONNECT: dataout_l 0 0 12 0 @dataout_l 0 0 12 0
118 | // Retrieval info: USED_PORT: inclock 0 0 0 0 INPUT_CLK_EXT NODEFVAL "inclock"
119 | // Retrieval info: CONNECT: @inclock 0 0 0 0 inclock 0 0 0 0
120 | // Retrieval info: USED_PORT: oe 0 0 0 0 INPUT NODEFVAL "oe"
121 | // Retrieval info: CONNECT: @oe 0 0 0 0 oe 0 0 0 0
122 | // Retrieval info: USED_PORT: outclock 0 0 0 0 INPUT_CLK_EXT NODEFVAL "outclock"
123 | // Retrieval info: CONNECT: @outclock 0 0 0 0 outclock 0 0 0 0
124 | // Retrieval info: USED_PORT: padio 0 0 12 0 BIDIR NODEFVAL "padio[11..0]"
125 | // Retrieval info: CONNECT: padio 0 0 12 0 @padio 0 0 12 0
126 | // Retrieval info: GEN_FILE: TYPE_NORMAL mf_ddio_bidir_12.v TRUE FALSE
127 | // Retrieval info: GEN_FILE: TYPE_NORMAL mf_ddio_bidir_12.qip TRUE FALSE
128 | // Retrieval info: GEN_FILE: TYPE_NORMAL mf_ddio_bidir_12.bsf FALSE TRUE
129 | // Retrieval info: GEN_FILE: TYPE_NORMAL mf_ddio_bidir_12_inst.v FALSE TRUE
130 | // Retrieval info: GEN_FILE: TYPE_NORMAL mf_ddio_bidir_12_bb.v FALSE TRUE
131 | // Retrieval info: GEN_FILE: TYPE_NORMAL mf_ddio_bidir_12.inc FALSE TRUE
132 | // Retrieval info: GEN_FILE: TYPE_NORMAL mf_ddio_bidir_12.cmp FALSE TRUE
133 | // Retrieval info: GEN_FILE: TYPE_NORMAL mf_ddio_bidir_12.ppf TRUE FALSE
134 | // Retrieval info: LIB_FILE: altera_mf
135 |
--------------------------------------------------------------------------------
/src/fpga/core/core_constraints.sdc:
--------------------------------------------------------------------------------
1 | #
2 | # user core constraints
3 | #
4 | # put your clock groups in here as well as any net assignments
5 | #
6 |
7 | set_clock_groups -asynchronous \
8 | -group { bridge_spiclk } \
9 | -group { clk_74a } \
10 | -group { clk_74b } \
11 | -group { ic|mp1|mf_pllbase_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk } \
12 | -group { ic|mp1|mf_pllbase_inst|altera_pll_i|general[1].gpll~PLL_OUTPUT_COUNTER|divclk } \
13 | -group { ic|mp1|mf_pllbase_inst|altera_pll_i|general[2].gpll~PLL_OUTPUT_COUNTER|divclk } \
14 | -group { ic|mp1|mf_pllbase_inst|altera_pll_i|general[3].gpll~PLL_OUTPUT_COUNTER|divclk }
15 |
--------------------------------------------------------------------------------
/src/fpga/core/mf_pllbase.bsf:
--------------------------------------------------------------------------------
1 | /*
2 | WARNING: Do NOT edit the input and output ports in this file in a text
3 | editor if you plan to continue editing the block that represents it in
4 | the Block Editor! File corruption is VERY likely to occur.
5 | */
6 | /*
7 | Copyright (C) 2022 Intel Corporation. All rights reserved.
8 | Your use of Intel Corporation's design tools, logic functions
9 | and other software and tools, and any partner logic
10 | functions, and any output files from any of the foregoing
11 | (including device programming or simulation files), and any
12 | associated documentation or information are expressly subject
13 | to the terms and conditions of the Intel Program License
14 | Subscription Agreement, the Intel Quartus Prime License Agreement,
15 | the Intel FPGA IP License Agreement, or other applicable license
16 | agreement, including, without limitation, that your use is for
17 | the sole purpose of programming logic devices manufactured by
18 | Intel and sold by Intel or its authorized distributors. Please
19 | refer to the applicable agreement for further details, at
20 | https://fpgasoftware.intel.com/eula.
21 | */
22 | (header "symbol" (version "1.1"))
23 | (symbol
24 | (rect 0 0 160 304)
25 | (text "mf_pllbase" (rect 48 -1 91 11)(font "Arial" (font_size 10)))
26 | (text "inst" (rect 8 288 20 300)(font "Arial" ))
27 | (port
28 | (pt 0 72)
29 | (input)
30 | (text "refclk" (rect 0 0 22 12)(font "Arial" (font_size 8)))
31 | (text "refclk" (rect 4 61 40 72)(font "Arial" (font_size 8)))
32 | (line (pt 0 72)(pt 48 72)(line_width 1))
33 | )
34 | (port
35 | (pt 0 112)
36 | (input)
37 | (text "rst" (rect 0 0 10 12)(font "Arial" (font_size 8)))
38 | (text "rst" (rect 4 101 22 112)(font "Arial" (font_size 8)))
39 | (line (pt 0 112)(pt 48 112)(line_width 1))
40 | )
41 | (port
42 | (pt 160 72)
43 | (output)
44 | (text "outclk_0" (rect 0 0 33 12)(font "Arial" (font_size 8)))
45 | (text "outclk_0" (rect 117 61 165 72)(font "Arial" (font_size 8)))
46 | (line (pt 160 72)(pt 112 72)(line_width 1))
47 | )
48 | (port
49 | (pt 160 112)
50 | (output)
51 | (text "outclk_1" (rect 0 0 31 12)(font "Arial" (font_size 8)))
52 | (text "outclk_1" (rect 119 101 167 112)(font "Arial" (font_size 8)))
53 | (line (pt 160 112)(pt 112 112)(line_width 1))
54 | )
55 | (port
56 | (pt 160 152)
57 | (output)
58 | (text "outclk_2" (rect 0 0 33 12)(font "Arial" (font_size 8)))
59 | (text "outclk_2" (rect 117 141 165 152)(font "Arial" (font_size 8)))
60 | (line (pt 160 152)(pt 112 152)(line_width 1))
61 | )
62 | (port
63 | (pt 160 192)
64 | (output)
65 | (text "outclk_3" (rect 0 0 33 12)(font "Arial" (font_size 8)))
66 | (text "outclk_3" (rect 117 181 165 192)(font "Arial" (font_size 8)))
67 | (line (pt 160 192)(pt 112 192)(line_width 1))
68 | )
69 | (port
70 | (pt 160 232)
71 | (output)
72 | (text "outclk_4" (rect 0 0 34 12)(font "Arial" (font_size 8)))
73 | (text "outclk_4" (rect 117 221 165 232)(font "Arial" (font_size 8)))
74 | (line (pt 160 232)(pt 112 232)(line_width 1))
75 | )
76 | (port
77 | (pt 160 272)
78 | (output)
79 | (text "locked" (rect 0 0 24 12)(font "Arial" (font_size 8)))
80 | (text "locked" (rect 127 261 163 272)(font "Arial" (font_size 8)))
81 | (line (pt 160 272)(pt 112 272)(line_width 1))
82 | )
83 | (drawing
84 | (text "refclk" (rect 16 43 68 99)(font "Arial" (color 128 0 0)(font_size 9)))
85 | (text "clk" (rect 53 67 124 144)(font "Arial" (color 0 0 0)))
86 | (text "reset" (rect 19 83 68 179)(font "Arial" (color 128 0 0)(font_size 9)))
87 | (text "reset" (rect 53 107 136 224)(font "Arial" (color 0 0 0)))
88 | (text "outclk0" (rect 113 43 268 99)(font "Arial" (color 128 0 0)(font_size 9)))
89 | (text "clk" (rect 97 67 212 144)(font "Arial" (color 0 0 0)))
90 | (text "outclk1" (rect 113 83 268 179)(font "Arial" (color 128 0 0)(font_size 9)))
91 | (text "clk" (rect 97 107 212 224)(font "Arial" (color 0 0 0)))
92 | (text "outclk2" (rect 113 123 268 259)(font "Arial" (color 128 0 0)(font_size 9)))
93 | (text "clk" (rect 97 147 212 304)(font "Arial" (color 0 0 0)))
94 | (text "outclk3" (rect 113 163 268 339)(font "Arial" (color 128 0 0)(font_size 9)))
95 | (text "clk" (rect 97 187 212 384)(font "Arial" (color 0 0 0)))
96 | (text "outclk4" (rect 113 203 268 419)(font "Arial" (color 128 0 0)(font_size 9)))
97 | (text "clk" (rect 97 227 212 464)(font "Arial" (color 0 0 0)))
98 | (text "locked" (rect 113 243 262 499)(font "Arial" (color 128 0 0)(font_size 9)))
99 | (text "export" (rect 82 267 200 544)(font "Arial" (color 0 0 0)))
100 | (text " altera_pll " (rect 118 288 308 586)(font "Arial" ))
101 | (line (pt 48 32)(pt 112 32)(line_width 1))
102 | (line (pt 112 32)(pt 112 288)(line_width 1))
103 | (line (pt 48 288)(pt 112 288)(line_width 1))
104 | (line (pt 48 32)(pt 48 288)(line_width 1))
105 | (line (pt 49 52)(pt 49 76)(line_width 1))
106 | (line (pt 50 52)(pt 50 76)(line_width 1))
107 | (line (pt 49 92)(pt 49 116)(line_width 1))
108 | (line (pt 50 92)(pt 50 116)(line_width 1))
109 | (line (pt 111 52)(pt 111 76)(line_width 1))
110 | (line (pt 110 52)(pt 110 76)(line_width 1))
111 | (line (pt 111 92)(pt 111 116)(line_width 1))
112 | (line (pt 110 92)(pt 110 116)(line_width 1))
113 | (line (pt 111 132)(pt 111 156)(line_width 1))
114 | (line (pt 110 132)(pt 110 156)(line_width 1))
115 | (line (pt 111 172)(pt 111 196)(line_width 1))
116 | (line (pt 110 172)(pt 110 196)(line_width 1))
117 | (line (pt 111 212)(pt 111 236)(line_width 1))
118 | (line (pt 110 212)(pt 110 236)(line_width 1))
119 | (line (pt 111 252)(pt 111 276)(line_width 1))
120 | (line (pt 110 252)(pt 110 276)(line_width 1))
121 | (line (pt 0 0)(pt 160 0)(line_width 1))
122 | (line (pt 160 0)(pt 160 304)(line_width 1))
123 | (line (pt 0 304)(pt 160 304)(line_width 1))
124 | (line (pt 0 0)(pt 0 304)(line_width 1))
125 | )
126 | )
127 |
--------------------------------------------------------------------------------
/src/fpga/core/mf_pllbase.ppf:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/fpga/core/mf_pllbase.sip:
--------------------------------------------------------------------------------
1 | set_global_assignment -entity "mf_pllbase" -library "lib_mf_pllbase" -name IP_TOOL_NAME "altera_pll"
2 | set_global_assignment -entity "mf_pllbase" -library "lib_mf_pllbase" -name IP_TOOL_VERSION "21.1"
3 | set_global_assignment -entity "mf_pllbase" -library "lib_mf_pllbase" -name IP_TOOL_ENV "mwpim"
4 | set_global_assignment -library "lib_mf_pllbase" -name SPD_FILE [file join $::quartus(sip_path) "mf_pllbase.spd"]
5 |
6 | set_global_assignment -library "lib_mf_pllbase" -name MISC_FILE [file join $::quartus(sip_path) "mf_pllbase_sim/mf_pllbase.vo"]
7 |
--------------------------------------------------------------------------------
/src/fpga/core/mf_pllbase.spd:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/src/fpga/core/mf_pllbase/mf_pllbase_0002.qip:
--------------------------------------------------------------------------------
1 | set_instance_assignment -name PLL_COMPENSATION_MODE NORMAL -to "*mf_pllbase_0002*|altera_pll:altera_pll_i*|*"
2 | set_instance_assignment -name PLL_CHANNEL_SPACING "0.0 KHz" -to "*mf_pllbase_0002*|altera_pll:altera_pll_i*|*"
3 | set_instance_assignment -name PLL_AUTO_RESET OFF -to "*mf_pllbase_0002*|altera_pll:altera_pll_i*|*"
4 | set_instance_assignment -name PLL_BANDWIDTH_PRESET AUTO -to "*mf_pllbase_0002*|altera_pll:altera_pll_i*|*"
5 |
--------------------------------------------------------------------------------
/src/fpga/core/mf_pllbase/mf_pllbase_0002.v:
--------------------------------------------------------------------------------
1 | `timescale 1ns/10ps
2 | module mf_pllbase_0002(
3 |
4 | // interface 'refclk'
5 | input wire refclk,
6 |
7 | // interface 'reset'
8 | input wire rst,
9 |
10 | // interface 'outclk0'
11 | output wire outclk_0,
12 |
13 | // interface 'outclk1'
14 | output wire outclk_1,
15 |
16 | // interface 'outclk2'
17 | output wire outclk_2,
18 |
19 | // interface 'outclk3'
20 | output wire outclk_3,
21 |
22 | // interface 'outclk4'
23 | output wire outclk_4,
24 |
25 | // interface 'locked'
26 | output wire locked
27 | );
28 |
29 | altera_pll #(
30 | .fractional_vco_multiplier("true"),
31 | .reference_clock_frequency("74.25 MHz"),
32 | .operation_mode("normal"),
33 | .number_of_clocks(5),
34 | .output_clock_frequency0("7.158999 MHz"),
35 | .phase_shift0("0 ps"),
36 | .duty_cycle0(50),
37 | .output_clock_frequency1("7.158999 MHz"),
38 | .phase_shift1("34921 ps"),
39 | .duty_cycle1(50),
40 | .output_clock_frequency2("28.635997 MHz"),
41 | .phase_shift2("0 ps"),
42 | .duty_cycle2(50),
43 | .output_clock_frequency3("132.766896 MHz"),
44 | .phase_shift3("6590 ps"),
45 | .duty_cycle3(50),
46 | .output_clock_frequency4("132.766892 MHz"),
47 | .phase_shift4("5649 ps"),
48 | .duty_cycle4(50),
49 | .output_clock_frequency5("0 MHz"),
50 | .phase_shift5("0 ps"),
51 | .duty_cycle5(50),
52 | .output_clock_frequency6("0 MHz"),
53 | .phase_shift6("0 ps"),
54 | .duty_cycle6(50),
55 | .output_clock_frequency7("0 MHz"),
56 | .phase_shift7("0 ps"),
57 | .duty_cycle7(50),
58 | .output_clock_frequency8("0 MHz"),
59 | .phase_shift8("0 ps"),
60 | .duty_cycle8(50),
61 | .output_clock_frequency9("0 MHz"),
62 | .phase_shift9("0 ps"),
63 | .duty_cycle9(50),
64 | .output_clock_frequency10("0 MHz"),
65 | .phase_shift10("0 ps"),
66 | .duty_cycle10(50),
67 | .output_clock_frequency11("0 MHz"),
68 | .phase_shift11("0 ps"),
69 | .duty_cycle11(50),
70 | .output_clock_frequency12("0 MHz"),
71 | .phase_shift12("0 ps"),
72 | .duty_cycle12(50),
73 | .output_clock_frequency13("0 MHz"),
74 | .phase_shift13("0 ps"),
75 | .duty_cycle13(50),
76 | .output_clock_frequency14("0 MHz"),
77 | .phase_shift14("0 ps"),
78 | .duty_cycle14(50),
79 | .output_clock_frequency15("0 MHz"),
80 | .phase_shift15("0 ps"),
81 | .duty_cycle15(50),
82 | .output_clock_frequency16("0 MHz"),
83 | .phase_shift16("0 ps"),
84 | .duty_cycle16(50),
85 | .output_clock_frequency17("0 MHz"),
86 | .phase_shift17("0 ps"),
87 | .duty_cycle17(50),
88 | .pll_type("General"),
89 | .pll_subtype("General")
90 | ) altera_pll_i (
91 | .rst (rst),
92 | .outclk ({outclk_4, outclk_3, outclk_2, outclk_1, outclk_0}),
93 | .locked (locked),
94 | .fboutclk ( ),
95 | .fbclk (1'b0),
96 | .refclk (refclk)
97 | );
98 | endmodule
99 |
100 |
--------------------------------------------------------------------------------
/src/fpga/core/mf_pllbase_sim.f:
--------------------------------------------------------------------------------
1 | mf_pllbase_sim/mf_pllbase.vo
2 |
--------------------------------------------------------------------------------
/src/fpga/core/mf_pllbase_sim/aldec/rivierapro_setup.tcl:
--------------------------------------------------------------------------------
1 |
2 | # (C) 2001-2022 Altera Corporation. All rights reserved.
3 | # Your use of Altera Corporation's design tools, logic functions and
4 | # other software and tools, and its AMPP partner logic functions, and
5 | # any output files any of the foregoing (including device programming
6 | # or simulation files), and any associated documentation or information
7 | # are expressly subject to the terms and conditions of the Altera
8 | # Program License Subscription Agreement, Altera MegaCore Function
9 | # License Agreement, or other applicable license agreement, including,
10 | # without limitation, that your use is for the sole purpose of
11 | # programming logic devices manufactured by Altera and sold by Altera
12 | # or its authorized distributors. Please refer to the applicable
13 | # agreement for further details.
14 |
15 | # ACDS 21.1 850 win32 2022.08.17.10:52:31
16 | # ----------------------------------------
17 | # Auto-generated simulation script rivierapro_setup.tcl
18 | # ----------------------------------------
19 | # This script provides commands to simulate the following IP detected in
20 | # your Quartus project:
21 | # mf_pllbase
22 | #
23 | # Altera recommends that you source this Quartus-generated IP simulation
24 | # script from your own customized top-level script, and avoid editing this
25 | # generated script.
26 | #
27 | # To write a top-level script that compiles Altera simulation libraries and
28 | # the Quartus-generated IP in your project, along with your design and
29 | # testbench files, copy the text from the TOP-LEVEL TEMPLATE section below
30 | # into a new file, e.g. named "aldec.do", and modify the text as directed.
31 | #
32 | # ----------------------------------------
33 | # # TOP-LEVEL TEMPLATE - BEGIN
34 | # #
35 | # # QSYS_SIMDIR is used in the Quartus-generated IP simulation script to
36 | # # construct paths to the files required to simulate the IP in your Quartus
37 | # # project. By default, the IP script assumes that you are launching the
38 | # # simulator from the IP script location. If launching from another
39 | # # location, set QSYS_SIMDIR to the output directory you specified when you
40 | # # generated the IP script, relative to the directory from which you launch
41 | # # the simulator.
42 | # #
43 | # set QSYS_SIMDIR