├── .gitignore ├── ALU.v ├── README ├── README.license ├── build-xilinx ├── Makefile ├── chip.ucf └── chip.v ├── cpu.v ├── simulation-isim ├── run_isim.sh ├── sim1.wcfg ├── testbench.prj └── testbench.v ├── system-rtl ├── gop16.v ├── hexloader.as ├── i2cslave.v.missing ├── i2cslave.v.patch ├── ram4k.v ├── tinybootrom.as ├── tinybootrom.v ├── tinytestrom.as └── uart.v └── tools ├── hexloader.as └── usb.i2c.py /.gitignore: -------------------------------------------------------------------------------- 1 | # emacs-style backup files 2 | *~ 3 | # patch detritus 4 | *.orig 5 | *.rej 6 | # non-redistributable files 7 | i2cslave.v 8 | asm65Org16.py 9 | # xilinx FPGA derived files 10 | *.xml 11 | *.wdb 12 | *.bgn 13 | *.bit 14 | *.bld 15 | *.cfi 16 | *.drc 17 | *.map 18 | *.mcs 19 | *.mrp 20 | *.ncd 21 | *.ngc 22 | *.ngd 23 | *.ngm 24 | *.pad 25 | *.par 26 | *.pcf 27 | *.prm 28 | *.ptwx 29 | *.twr 30 | *.twx 31 | *.unroutes 32 | *.xpi 33 | *_annot.nlf 34 | *_annot.sdf 35 | *_annot.v 36 | *_annot_mhf_info.txt 37 | *_bitgen.xwbt 38 | *_ngdbuild.xrpt 39 | *_pad.csv 40 | *_pad.txt 41 | *_xst.xrpt 42 | *.xrpt 43 | make.log 44 | fuse.log 45 | isim.log 46 | x.exe 47 | usage_statistics_webtalk.html 48 | webtalk.log 49 | netlist.lst 50 | glbl.v 51 | -------------------------------------------------------------------------------- /ALU.v: -------------------------------------------------------------------------------- 1 | /* 2 | * parameterisable ALU for 6502 and 65Org16 3 | * 4 | * verilog-6502 project: verilog model of 6502 and 65Org16 CPU core 5 | * 6 | * (C) 2011 Arlet Ottens, 7 | * (C) 2011 Ed Spittles, 8 | * 9 | * This library is free software; you can redistribute it and/or 10 | * modify it under the terms of the GNU Lesser General Public 11 | * License version 2.1 as published by the Free Software Foundation. 12 | * 13 | * AI and BI are 8 bit inputs. Result in OUT. 14 | * CI is Carry In. 15 | * CO is Carry Out. 16 | * 17 | * op[3:0] is defined as follows: 18 | * 19 | * 0011 AI + BI 20 | * 0111 AI - BI 21 | * 1011 AI + AI 22 | * 1100 AI | BI 23 | * 1101 AI & BI 24 | * 1110 AI ^ BI 25 | * 1111 AI 26 | * 27 | */ 28 | 29 | module ALU( clk, op, right, AI, BI, CI, CO, OUT, V, Z, N, 30 | `ifdef BCD_ENABLED 31 | BCD, 32 | HC, 33 | `endif 34 | RDY ); 35 | 36 | parameter dw = 16; // data width (8 for 6502, 16 for 65Org16) 37 | 38 | input clk; 39 | input right; 40 | input [3:0] op; // operation 41 | input [dw-1:0] AI; 42 | input [dw-1:0] BI; 43 | input CI; 44 | output [dw-1:0] OUT; 45 | output CO; 46 | output V; 47 | output Z; 48 | output N; 49 | `ifdef BCD_ENABLED 50 | input BCD; // BCD style carry 51 | output HC; 52 | `endif 53 | input RDY; 54 | 55 | reg [dw-1:0] OUT; 56 | reg CO; 57 | reg V; 58 | reg Z; 59 | reg N; 60 | 61 | reg [dw:0] logical; 62 | reg [dw-1:0] temp_BI; 63 | 64 | `ifdef BCD_ENABLED 65 | reg HC; 66 | reg [4:0] temp_l; 67 | reg [dw-4:0] temp_h; 68 | wire [dw:0] temp = { temp_h, temp_l[3:0] }; 69 | `else 70 | wire [dw:0] temp = logical + temp_BI + adder_CI; 71 | `endif 72 | 73 | wire adder_CI = (right | (op[3:2] == 2'b11)) ? 0 : CI; 74 | 75 | // calculate the logic operations. The 'case' can be done in 1 LUT per 76 | // bit. The 'right' shift is a simple mux that can be implemented by 77 | // F5MUX. 78 | always @* begin 79 | case( op[1:0] ) 80 | 2'b00: logical = AI | BI; 81 | 2'b01: logical = AI & BI; 82 | 2'b10: logical = AI ^ BI; 83 | 2'b11: logical = AI; 84 | endcase 85 | 86 | if( right ) 87 | logical = { AI[0], CI, AI[dw-1:1] }; 88 | end 89 | 90 | // Add logic result to BI input. This only makes sense when logic = AI. 91 | // This stage can be done in 1 LUT per bit, using carry chain logic. 92 | always @* begin 93 | case( op[3:2] ) 94 | 2'b00: temp_BI = BI; // A+B 95 | 2'b01: temp_BI = ~BI; // A-B 96 | 2'b10: temp_BI = logical[dw-1:0]; // A+A 97 | 2'b11: temp_BI = 0; // A+0 98 | endcase 99 | end 100 | 101 | `ifdef BCD_ENABLED 102 | 103 | // HC9 is the half carry bit when doing BCD add 104 | wire HC9 = BCD & (temp_l[3:1] >= 3'd5); 105 | 106 | // CO9 is the carry-out bit when doing BCD add 107 | wire CO9 = BCD & (temp_h[3:1] >= 3'd5); 108 | 109 | // combined half carry bit 110 | wire temp_HC = temp_l[4] | HC9; 111 | 112 | // perform the addition as 2 separate nibble, so we get 113 | // access to the half carry flag 114 | always @* begin 115 | temp_l = logical[3:0] + temp_BI[3:0] + adder_CI; 116 | temp_h = logical[dw:4] + temp_BI[dw-1:4] + temp_HC; 117 | end 118 | 119 | `endif 120 | 121 | // calculate the flags 122 | always @(posedge clk) 123 | if( RDY ) begin 124 | OUT <= temp[dw-1:0]; 125 | CO <= temp[dw] 126 | `ifdef BCD_ENABLED 127 | | CO9 128 | `endif 129 | ; 130 | Z <= ~|temp[dw-1:0]; 131 | N <= temp[dw-1]; 132 | V <= AI[dw-1] ^ temp_BI[dw-1] ^ temp[dw-1] ^ temp[dw]; 133 | `ifdef BCD_ENABLED 134 | HC <= temp_HC; 135 | `endif 136 | end 137 | 138 | endmodule 139 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | A Verilog HDL project for CPU cores related to the original MOS 6502 CPU. 2 | 3 | Have fun. 4 | 5 | The 65Org16-master branch is for a CPU core with: 6 | - 32-bit address space 7 | - by using 16-bit bytes 8 | - with no specific support for 8-bit bytes 9 | - with BCD mode as unspecified behaviour 10 | - and otherwise all opcodes and addressing modes like NMOS 6502 11 | 12 | Please use other branches and add a suffix to your core name for 13 | CPU cores with other goals. 14 | 15 | Please note: 16 | 17 | - The core has had next to no testing, 18 | 19 | - There's an in-browser emulator at http://biged.github.com/6502js/ 20 | 21 | - Assembler support is catalogued at http://forum.6502.org/viewtopic.php?f=2&t=1851 22 | 23 | - There are also verilog and support files here for a small system on 24 | FPGA, intended for xilinx spartan 3 as found on OHO GOP 24-pin module. 25 | The system has a uart module for communication to a host computer, 26 | which is implemented over i2c. The i2c module is not included for 27 | copyright reasons. The system is absolutely minimal but is a work 28 | in progress, 29 | 30 | - As a secondary goal it might be possible to configure the HDL as 31 | a 6502-compatible core with 8-bit bytes. 32 | 33 | - LGPL license v2.1 is used for compatibility with opencores.org and to 34 | encourage redistribution of any source code improvements. 35 | (The license can be changed by agreement of all the copyright holders) 36 | 37 | Notes on the cpu core: 38 | 39 | - clk is active on the positive edge (is a phi1 clock) 40 | - reset, IRQ and NMI are active high 41 | - WE replaces, and is inverse sense of, read not write. 42 | - databus has separate DI and DO 43 | - RDY is not implemented 44 | - external memory is assumed synchronous, so external pipelining is needed 45 | - `define SIM for extra simulation instrumentation 46 | - memory accesses may diverge from the original 47 | 48 | Website for the original: http://ladybug.xs4all.nl/arlet/fpga/6502/ 49 | 50 | Note on licensing: 51 | 52 | Relicensed to LGPL by kind permission of Arlet Ottens 53 | "If you want to distribute it under the LGPL license that's fine with me" 54 | 16 May 2011 12:08 55 | -------------------------------------------------------------------------------- /README.license: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 2.1, February 1999 3 | 4 | Copyright (C) 1991, 1999 Free Software Foundation, Inc. 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | [This is the first released version of the Lesser GPL. It also counts 10 | as the successor of the GNU Library Public License, version 2, hence 11 | the version number 2.1.] 12 | 13 | Preamble 14 | 15 | The licenses for most software are designed to take away your 16 | freedom to share and change it. By contrast, the GNU General Public 17 | Licenses are intended to guarantee your freedom to share and change 18 | free software--to make sure the software is free for all its users. 19 | 20 | This license, the Lesser General Public License, applies to some 21 | specially designated software packages--typically libraries--of the 22 | Free Software Foundation and other authors who decide to use it. You 23 | can use it too, but we suggest you first think carefully about whether 24 | this license or the ordinary General Public License is the better 25 | strategy to use in any particular case, based on the explanations below. 26 | 27 | When we speak of free software, we are referring to freedom of use, 28 | not price. Our General Public Licenses are designed to make sure that 29 | you have the freedom to distribute copies of free software (and charge 30 | for this service if you wish); that you receive source code or can get 31 | it if you want it; that you can change the software and use pieces of 32 | it in new free programs; and that you are informed that you can do 33 | these things. 34 | 35 | To protect your rights, we need to make restrictions that forbid 36 | distributors to deny you these rights or to ask you to surrender these 37 | rights. These restrictions translate to certain responsibilities for 38 | you if you distribute copies of the library or if you modify it. 39 | 40 | For example, if you distribute copies of the library, whether gratis 41 | or for a fee, you must give the recipients all the rights that we gave 42 | you. You must make sure that they, too, receive or can get the source 43 | code. If you link other code with the library, you must provide 44 | complete object files to the recipients, so that they can relink them 45 | with the library after making changes to the library and recompiling 46 | it. And you must show them these terms so they know their rights. 47 | 48 | We protect your rights with a two-step method: (1) we copyright the 49 | library, and (2) we offer you this license, which gives you legal 50 | permission to copy, distribute and/or modify the library. 51 | 52 | To protect each distributor, we want to make it very clear that 53 | there is no warranty for the free library. Also, if the library is 54 | modified by someone else and passed on, the recipients should know 55 | that what they have is not the original version, so that the original 56 | author's reputation will not be affected by problems that might be 57 | introduced by others. 58 | 59 | Finally, software patents pose a constant threat to the existence of 60 | any free program. We wish to make sure that a company cannot 61 | effectively restrict the users of a free program by obtaining a 62 | restrictive license from a patent holder. Therefore, we insist that 63 | any patent license obtained for a version of the library must be 64 | consistent with the full freedom of use specified in this license. 65 | 66 | Most GNU software, including some libraries, is covered by the 67 | ordinary GNU General Public License. This license, the GNU Lesser 68 | General Public License, applies to certain designated libraries, and 69 | is quite different from the ordinary General Public License. We use 70 | this license for certain libraries in order to permit linking those 71 | libraries into non-free programs. 72 | 73 | When a program is linked with a library, whether statically or using 74 | a shared library, the combination of the two is legally speaking a 75 | combined work, a derivative of the original library. The ordinary 76 | General Public License therefore permits such linking only if the 77 | entire combination fits its criteria of freedom. The Lesser General 78 | Public License permits more lax criteria for linking other code with 79 | the library. 80 | 81 | We call this license the "Lesser" General Public License because it 82 | does Less to protect the user's freedom than the ordinary General 83 | Public License. It also provides other free software developers Less 84 | of an advantage over competing non-free programs. These disadvantages 85 | are the reason we use the ordinary General Public License for many 86 | libraries. However, the Lesser license provides advantages in certain 87 | special circumstances. 88 | 89 | For example, on rare occasions, there may be a special need to 90 | encourage the widest possible use of a certain library, so that it becomes 91 | a de-facto standard. To achieve this, non-free programs must be 92 | allowed to use the library. A more frequent case is that a free 93 | library does the same job as widely used non-free libraries. In this 94 | case, there is little to gain by limiting the free library to free 95 | software only, so we use the Lesser General Public License. 96 | 97 | In other cases, permission to use a particular library in non-free 98 | programs enables a greater number of people to use a large body of 99 | free software. For example, permission to use the GNU C Library in 100 | non-free programs enables many more people to use the whole GNU 101 | operating system, as well as its variant, the GNU/Linux operating 102 | system. 103 | 104 | Although the Lesser General Public License is Less protective of the 105 | users' freedom, it does ensure that the user of a program that is 106 | linked with the Library has the freedom and the wherewithal to run 107 | that program using a modified version of the Library. 108 | 109 | The precise terms and conditions for copying, distribution and 110 | modification follow. Pay close attention to the difference between a 111 | "work based on the library" and a "work that uses the library". The 112 | former contains code derived from the library, whereas the latter must 113 | be combined with the library in order to run. 114 | 115 | GNU LESSER GENERAL PUBLIC LICENSE 116 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 117 | 118 | 0. This License Agreement applies to any software library or other 119 | program which contains a notice placed by the copyright holder or 120 | other authorized party saying it may be distributed under the terms of 121 | this Lesser General Public License (also called "this License"). 122 | Each licensee is addressed as "you". 123 | 124 | A "library" means a collection of software functions and/or data 125 | prepared so as to be conveniently linked with application programs 126 | (which use some of those functions and data) to form executables. 127 | 128 | The "Library", below, refers to any such software library or work 129 | which has been distributed under these terms. A "work based on the 130 | Library" means either the Library or any derivative work under 131 | copyright law: that is to say, a work containing the Library or a 132 | portion of it, either verbatim or with modifications and/or translated 133 | straightforwardly into another language. (Hereinafter, translation is 134 | included without limitation in the term "modification".) 135 | 136 | "Source code" for a work means the preferred form of the work for 137 | making modifications to it. For a library, complete source code means 138 | all the source code for all modules it contains, plus any associated 139 | interface definition files, plus the scripts used to control compilation 140 | and installation of the library. 141 | 142 | Activities other than copying, distribution and modification are not 143 | covered by this License; they are outside its scope. The act of 144 | running a program using the Library is not restricted, and output from 145 | such a program is covered only if its contents constitute a work based 146 | on the Library (independent of the use of the Library in a tool for 147 | writing it). Whether that is true depends on what the Library does 148 | and what the program that uses the Library does. 149 | 150 | 1. You may copy and distribute verbatim copies of the Library's 151 | complete source code as you receive it, in any medium, provided that 152 | you conspicuously and appropriately publish on each copy an 153 | appropriate copyright notice and disclaimer of warranty; keep intact 154 | all the notices that refer to this License and to the absence of any 155 | warranty; and distribute a copy of this License along with the 156 | Library. 157 | 158 | You may charge a fee for the physical act of transferring a copy, 159 | and you may at your option offer warranty protection in exchange for a 160 | fee. 161 | 162 | 2. You may modify your copy or copies of the Library or any portion 163 | of it, thus forming a work based on the Library, and copy and 164 | distribute such modifications or work under the terms of Section 1 165 | above, provided that you also meet all of these conditions: 166 | 167 | a) The modified work must itself be a software library. 168 | 169 | b) You must cause the files modified to carry prominent notices 170 | stating that you changed the files and the date of any change. 171 | 172 | c) You must cause the whole of the work to be licensed at no 173 | charge to all third parties under the terms of this License. 174 | 175 | d) If a facility in the modified Library refers to a function or a 176 | table of data to be supplied by an application program that uses 177 | the facility, other than as an argument passed when the facility 178 | is invoked, then you must make a good faith effort to ensure that, 179 | in the event an application does not supply such function or 180 | table, the facility still operates, and performs whatever part of 181 | its purpose remains meaningful. 182 | 183 | (For example, a function in a library to compute square roots has 184 | a purpose that is entirely well-defined independent of the 185 | application. Therefore, Subsection 2d requires that any 186 | application-supplied function or table used by this function must 187 | be optional: if the application does not supply it, the square 188 | root function must still compute square roots.) 189 | 190 | These requirements apply to the modified work as a whole. If 191 | identifiable sections of that work are not derived from the Library, 192 | and can be reasonably considered independent and separate works in 193 | themselves, then this License, and its terms, do not apply to those 194 | sections when you distribute them as separate works. But when you 195 | distribute the same sections as part of a whole which is a work based 196 | on the Library, the distribution of the whole must be on the terms of 197 | this License, whose permissions for other licensees extend to the 198 | entire whole, and thus to each and every part regardless of who wrote 199 | it. 200 | 201 | Thus, it is not the intent of this section to claim rights or contest 202 | your rights to work written entirely by you; rather, the intent is to 203 | exercise the right to control the distribution of derivative or 204 | collective works based on the Library. 205 | 206 | In addition, mere aggregation of another work not based on the Library 207 | with the Library (or with a work based on the Library) on a volume of 208 | a storage or distribution medium does not bring the other work under 209 | the scope of this License. 210 | 211 | 3. You may opt to apply the terms of the ordinary GNU General Public 212 | License instead of this License to a given copy of the Library. To do 213 | this, you must alter all the notices that refer to this License, so 214 | that they refer to the ordinary GNU General Public License, version 2, 215 | instead of to this License. (If a newer version than version 2 of the 216 | ordinary GNU General Public License has appeared, then you can specify 217 | that version instead if you wish.) Do not make any other change in 218 | these notices. 219 | 220 | Once this change is made in a given copy, it is irreversible for 221 | that copy, so the ordinary GNU General Public License applies to all 222 | subsequent copies and derivative works made from that copy. 223 | 224 | This option is useful when you wish to copy part of the code of 225 | the Library into a program that is not a library. 226 | 227 | 4. You may copy and distribute the Library (or a portion or 228 | derivative of it, under Section 2) in object code or executable form 229 | under the terms of Sections 1 and 2 above provided that you accompany 230 | it with the complete corresponding machine-readable source code, which 231 | must be distributed under the terms of Sections 1 and 2 above on a 232 | medium customarily used for software interchange. 233 | 234 | If distribution of object code is made by offering access to copy 235 | from a designated place, then offering equivalent access to copy the 236 | source code from the same place satisfies the requirement to 237 | distribute the source code, even though third parties are not 238 | compelled to copy the source along with the object code. 239 | 240 | 5. A program that contains no derivative of any portion of the 241 | Library, but is designed to work with the Library by being compiled or 242 | linked with it, is called a "work that uses the Library". Such a 243 | work, in isolation, is not a derivative work of the Library, and 244 | therefore falls outside the scope of this License. 245 | 246 | However, linking a "work that uses the Library" with the Library 247 | creates an executable that is a derivative of the Library (because it 248 | contains portions of the Library), rather than a "work that uses the 249 | library". The executable is therefore covered by this License. 250 | Section 6 states terms for distribution of such executables. 251 | 252 | When a "work that uses the Library" uses material from a header file 253 | that is part of the Library, the object code for the work may be a 254 | derivative work of the Library even though the source code is not. 255 | Whether this is true is especially significant if the work can be 256 | linked without the Library, or if the work is itself a library. The 257 | threshold for this to be true is not precisely defined by law. 258 | 259 | If such an object file uses only numerical parameters, data 260 | structure layouts and accessors, and small macros and small inline 261 | functions (ten lines or less in length), then the use of the object 262 | file is unrestricted, regardless of whether it is legally a derivative 263 | work. (Executables containing this object code plus portions of the 264 | Library will still fall under Section 6.) 265 | 266 | Otherwise, if the work is a derivative of the Library, you may 267 | distribute the object code for the work under the terms of Section 6. 268 | Any executables containing that work also fall under Section 6, 269 | whether or not they are linked directly with the Library itself. 270 | 271 | 6. As an exception to the Sections above, you may also combine or 272 | link a "work that uses the Library" with the Library to produce a 273 | work containing portions of the Library, and distribute that work 274 | under terms of your choice, provided that the terms permit 275 | modification of the work for the customer's own use and reverse 276 | engineering for debugging such modifications. 277 | 278 | You must give prominent notice with each copy of the work that the 279 | Library is used in it and that the Library and its use are covered by 280 | this License. You must supply a copy of this License. If the work 281 | during execution displays copyright notices, you must include the 282 | copyright notice for the Library among them, as well as a reference 283 | directing the user to the copy of this License. Also, you must do one 284 | of these things: 285 | 286 | a) Accompany the work with the complete corresponding 287 | machine-readable source code for the Library including whatever 288 | changes were used in the work (which must be distributed under 289 | Sections 1 and 2 above); and, if the work is an executable linked 290 | with the Library, with the complete machine-readable "work that 291 | uses the Library", as object code and/or source code, so that the 292 | user can modify the Library and then relink to produce a modified 293 | executable containing the modified Library. (It is understood 294 | that the user who changes the contents of definitions files in the 295 | Library will not necessarily be able to recompile the application 296 | to use the modified definitions.) 297 | 298 | b) Use a suitable shared library mechanism for linking with the 299 | Library. A suitable mechanism is one that (1) uses at run time a 300 | copy of the library already present on the user's computer system, 301 | rather than copying library functions into the executable, and (2) 302 | will operate properly with a modified version of the library, if 303 | the user installs one, as long as the modified version is 304 | interface-compatible with the version that the work was made with. 305 | 306 | c) Accompany the work with a written offer, valid for at 307 | least three years, to give the same user the materials 308 | specified in Subsection 6a, above, for a charge no more 309 | than the cost of performing this distribution. 310 | 311 | d) If distribution of the work is made by offering access to copy 312 | from a designated place, offer equivalent access to copy the above 313 | specified materials from the same place. 314 | 315 | e) Verify that the user has already received a copy of these 316 | materials or that you have already sent this user a copy. 317 | 318 | For an executable, the required form of the "work that uses the 319 | Library" must include any data and utility programs needed for 320 | reproducing the executable from it. However, as a special exception, 321 | the materials to be distributed need not include anything that is 322 | normally distributed (in either source or binary form) with the major 323 | components (compiler, kernel, and so on) of the operating system on 324 | which the executable runs, unless that component itself accompanies 325 | the executable. 326 | 327 | It may happen that this requirement contradicts the license 328 | restrictions of other proprietary libraries that do not normally 329 | accompany the operating system. Such a contradiction means you cannot 330 | use both them and the Library together in an executable that you 331 | distribute. 332 | 333 | 7. You may place library facilities that are a work based on the 334 | Library side-by-side in a single library together with other library 335 | facilities not covered by this License, and distribute such a combined 336 | library, provided that the separate distribution of the work based on 337 | the Library and of the other library facilities is otherwise 338 | permitted, and provided that you do these two things: 339 | 340 | a) Accompany the combined library with a copy of the same work 341 | based on the Library, uncombined with any other library 342 | facilities. This must be distributed under the terms of the 343 | Sections above. 344 | 345 | b) Give prominent notice with the combined library of the fact 346 | that part of it is a work based on the Library, and explaining 347 | where to find the accompanying uncombined form of the same work. 348 | 349 | 8. You may not copy, modify, sublicense, link with, or distribute 350 | the Library except as expressly provided under this License. Any 351 | attempt otherwise to copy, modify, sublicense, link with, or 352 | distribute the Library is void, and will automatically terminate your 353 | rights under this License. However, parties who have received copies, 354 | or rights, from you under this License will not have their licenses 355 | terminated so long as such parties remain in full compliance. 356 | 357 | 9. You are not required to accept this License, since you have not 358 | signed it. However, nothing else grants you permission to modify or 359 | distribute the Library or its derivative works. These actions are 360 | prohibited by law if you do not accept this License. Therefore, by 361 | modifying or distributing the Library (or any work based on the 362 | Library), you indicate your acceptance of this License to do so, and 363 | all its terms and conditions for copying, distributing or modifying 364 | the Library or works based on it. 365 | 366 | 10. Each time you redistribute the Library (or any work based on the 367 | Library), the recipient automatically receives a license from the 368 | original licensor to copy, distribute, link with or modify the Library 369 | subject to these terms and conditions. You may not impose any further 370 | restrictions on the recipients' exercise of the rights granted herein. 371 | You are not responsible for enforcing compliance by third parties with 372 | this License. 373 | 374 | 11. If, as a consequence of a court judgment or allegation of patent 375 | infringement or for any other reason (not limited to patent issues), 376 | conditions are imposed on you (whether by court order, agreement or 377 | otherwise) that contradict the conditions of this License, they do not 378 | excuse you from the conditions of this License. If you cannot 379 | distribute so as to satisfy simultaneously your obligations under this 380 | License and any other pertinent obligations, then as a consequence you 381 | may not distribute the Library at all. For example, if a patent 382 | license would not permit royalty-free redistribution of the Library by 383 | all those who receive copies directly or indirectly through you, then 384 | the only way you could satisfy both it and this License would be to 385 | refrain entirely from distribution of the Library. 386 | 387 | If any portion of this section is held invalid or unenforceable under any 388 | particular circumstance, the balance of the section is intended to apply, 389 | and the section as a whole is intended to apply in other circumstances. 390 | 391 | It is not the purpose of this section to induce you to infringe any 392 | patents or other property right claims or to contest validity of any 393 | such claims; this section has the sole purpose of protecting the 394 | integrity of the free software distribution system which is 395 | implemented by public license practices. Many people have made 396 | generous contributions to the wide range of software distributed 397 | through that system in reliance on consistent application of that 398 | system; it is up to the author/donor to decide if he or she is willing 399 | to distribute software through any other system and a licensee cannot 400 | impose that choice. 401 | 402 | This section is intended to make thoroughly clear what is believed to 403 | be a consequence of the rest of this License. 404 | 405 | 12. If the distribution and/or use of the Library is restricted in 406 | certain countries either by patents or by copyrighted interfaces, the 407 | original copyright holder who places the Library under this License may add 408 | an explicit geographical distribution limitation excluding those countries, 409 | so that distribution is permitted only in or among countries not thus 410 | excluded. In such case, this License incorporates the limitation as if 411 | written in the body of this License. 412 | 413 | 13. The Free Software Foundation may publish revised and/or new 414 | versions of the Lesser General Public License from time to time. 415 | Such new versions will be similar in spirit to the present version, 416 | but may differ in detail to address new problems or concerns. 417 | 418 | Each version is given a distinguishing version number. If the Library 419 | specifies a version number of this License which applies to it and 420 | "any later version", you have the option of following the terms and 421 | conditions either of that version or of any later version published by 422 | the Free Software Foundation. If the Library does not specify a 423 | license version number, you may choose any version ever published by 424 | the Free Software Foundation. 425 | 426 | 14. If you wish to incorporate parts of the Library into other free 427 | programs whose distribution conditions are incompatible with these, 428 | write to the author to ask for permission. For software which is 429 | copyrighted by the Free Software Foundation, write to the Free 430 | Software Foundation; we sometimes make exceptions for this. Our 431 | decision will be guided by the two goals of preserving the free status 432 | of all derivatives of our free software and of promoting the sharing 433 | and reuse of software generally. 434 | 435 | NO WARRANTY 436 | 437 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO 438 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 439 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 440 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY 441 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 442 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 443 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 444 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME 445 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 446 | 447 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 448 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 449 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU 450 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 451 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 452 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 453 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 454 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 455 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 456 | DAMAGES. 457 | 458 | END OF TERMS AND CONDITIONS 459 | 460 | How to Apply These Terms to Your New Libraries 461 | 462 | If you develop a new library, and you want it to be of the greatest 463 | possible use to the public, we recommend making it free software that 464 | everyone can redistribute and change. You can do so by permitting 465 | redistribution under these terms (or, alternatively, under the terms of the 466 | ordinary General Public License). 467 | 468 | To apply these terms, attach the following notices to the library. It is 469 | safest to attach them to the start of each source file to most effectively 470 | convey the exclusion of warranty; and each file should have at least the 471 | "copyright" line and a pointer to where the full notice is found. 472 | 473 | 474 | Copyright (C) 475 | 476 | This library is free software; you can redistribute it and/or 477 | modify it under the terms of the GNU Lesser General Public 478 | License as published by the Free Software Foundation; either 479 | version 2.1 of the License, or (at your option) any later version. 480 | 481 | This library is distributed in the hope that it will be useful, 482 | but WITHOUT ANY WARRANTY; without even the implied warranty of 483 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 484 | Lesser General Public License for more details. 485 | 486 | You should have received a copy of the GNU Lesser General Public 487 | License along with this library; if not, write to the Free Software 488 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 489 | 490 | Also add information on how to contact you by electronic and paper mail. 491 | 492 | You should also get your employer (if you work as a programmer) or your 493 | school, if any, to sign a "copyright disclaimer" for the library, if 494 | necessary. Here is a sample; alter the names: 495 | 496 | Yoyodyne, Inc., hereby disclaims all copyright interest in the 497 | library `Frob' (a library for tweaking knobs) written by James Random Hacker. 498 | 499 | , 1 April 1990 500 | Ty Coon, President of Vice 501 | 502 | That's all there is to it! 503 | -------------------------------------------------------------------------------- /build-xilinx/Makefile: -------------------------------------------------------------------------------- 1 | # derived from code in Peter Monta's FPGA-netlist-tools project 2 | 3 | DEVICE=XC3S200-4VQ100 4 | 5 | TOP=gop16 6 | 7 | DESIGN=chip 8 | 9 | all: 10 | echo "run -ifn ${DESIGN}.v -ifmt Verilog -top ${TOP} -ofn ${DESIGN} -p ${DEVICE}" | xst 11 | ngdbuild -p ${DEVICE} -uc ${DESIGN}.ucf ${DESIGN} 12 | map -w -timing -detail -ol high -p ${DEVICE} ${DESIGN}.ngd ${DESIGN}.pcf 13 | par -w -ol high ${DESIGN}.ncd ${DESIGN}.ncd ${DESIGN}.pcf 14 | trce -v 20 -u 20 ${DESIGN}.ncd ${DESIGN}.pcf 15 | bitgen -m -g StartupClk:CClk -g GTS_cycle:3 -g LCK_cycle:4 -g GWE_cycle:5 -g DONE_cycle:6 -w ${DESIGN}.ncd ${DESIGN}.bit ${DESIGN}.pcf 16 | promgen -w -spi -p mcs -s 4096 -u 0 ${DESIGN}.bit 17 | netgen -sim -w -ofmt verilog -sdf_anno true -ism -aka ${DESIGN}.ncd ${DESIGN}_annot.v 18 | 19 | clean: 20 | rm -rf xst _xmsgs xlnx_auto_0_xdb 21 | rm -f *~ 22 | rm -f *.bgn *.bld *.drc *.map *.mrp *.ncd *.ngc *.ngd *.ngm *.pad *.par *.pcf *.ptwx *.unroutes *.xpi 23 | rm -f *.cfi *.prm 24 | rm -f _impact.cmd _impact.log 25 | rm -f *_bitgen.xwbt *_ngdbuild.xrpt *_pad.csv *_pad.txt *_summary.xml *_usage.xml 26 | rm -f *_xst.xrpt *_map.xrpt *_par.xrpt 27 | rm -f _impactbatch.log netlist.lst usage_statistics_webtalk.html webtalk.log 28 | rm -f *.psr *.twr *.twx 29 | rm -f output.txt 30 | -------------------------------------------------------------------------------- /build-xilinx/chip.ucf: -------------------------------------------------------------------------------- 1 | # GOP_XC3S200 .UCF definition template 24pin 2 | 3 | NET phi0 PERIOD = 20.0ns ; 4 | 5 | # 8 user LEDs are multi-purpose with some SRAM address lines 6 | NET "userled<0>" LOC = "P81" | IOSTANDARD = LVCMOS33 ; 7 | NET "userled<1>" LOC = "P1" | IOSTANDARD = LVCMOS33 ; 8 | NET "userled<2>" LOC = "P96" | IOSTANDARD = LVCMOS33 ; 9 | NET "userled<3>" LOC = "P97" | IOSTANDARD = LVCMOS33 ; 10 | NET "userled<4>" LOC = "P53" | IOSTANDARD = LVCMOS33 ; 11 | NET "userled<5>" LOC = "P50" | IOSTANDARD = LVCMOS33 ; 12 | NET "userled<6>" LOC = "P75" | IOSTANDARD = LVCMOS33 ; 13 | NET "userled<7>" LOC = "P74" | IOSTANDARD = LVCMOS33 ; 14 | 15 | #NET "sa<0>" LOC = "P40" | IOSTANDARD = LVCMOS33 ; # also SI for SPI flash 16 | #NET "sa<1>" LOC = "P63" | IOSTANDARD = LVCMOS33 ; 17 | #NET "sa<2>" LOC = "P48" | IOSTANDARD = LVCMOS33 ; # also SO for SPI flash 18 | #NET "sa<3>" LOC = "P65" | IOSTANDARD = LVCMOS33 ; 19 | #NET "sa<4>" LOC = "P42" | IOSTANDARD = LVCMOS33 ; # also INIT for config PROM 20 | #NET "sa<5>" LOC = "P68" | IOSTANDARD = LVCMOS33 ; 21 | #NET "sa<6>" LOC = "P71" | IOSTANDARD = LVCMOS33 ; 22 | #NET "sa<7>" LOC = "P79" | IOSTANDARD = LVCMOS33 ; 23 | #NET "sa<8>" LOC = "P72" | IOSTANDARD = LVCMOS33 ; 24 | #NET "sa<9>" LOC = "P80" | IOSTANDARD = LVCMOS33 ; 25 | #NET "sa<10>" LOC = "P67" | IOSTANDARD = LVCMOS33 ; 26 | #NET "sa<11>" LOC = "P81" | IOSTANDARD = LVCMOS33 ; # led3 27 | #NET "sa<12>" LOC = "P1" | IOSTANDARD = LVCMOS33 ; # led4 28 | #NET "sa<13>" LOC = "P96" | IOSTANDARD = LVCMOS33 ; # led5 29 | #NET "sa<14>" LOC = "P97" | IOSTANDARD = LVCMOS33 ; # led6 30 | #NET "sa<15>" LOC = "P53" | IOSTANDARD = LVCMOS33 ; # led7 31 | #NET "sa<16>" LOC = "P50" | IOSTANDARD = LVCMOS33 ; # led8 32 | #NET "sa<17>" LOC = "P75" | IOSTANDARD = LVCMOS33 ; # led9 33 | #NET "sa<18>" LOC = "P74" | IOSTANDARD = LVCMOS33 ; # led10 34 | 35 | #NET "sd<0>" LOC = "P2" | IOSTANDARD = LVCMOS33 ; 36 | #NET "sd<1>" LOC = "P4" | IOSTANDARD = LVCMOS33 ; 37 | #NET "sd<2>" LOC = "P5" | IOSTANDARD = LVCMOS33 ; 38 | #NET "sd<3>" LOC = "P8" | IOSTANDARD = LVCMOS33 ; 39 | #NET "sd<4>" LOC = "P9" | IOSTANDARD = LVCMOS33 ; 40 | #NET "sd<5>" LOC = "P11" | IOSTANDARD = LVCMOS33 ; 41 | #NET "sd<6>" LOC = "P12" | IOSTANDARD = LVCMOS33 ; 42 | #NET "sd<7>" LOC = "P13" | IOSTANDARD = LVCMOS33 ; 43 | 44 | NET "phi0" LOC = "P38" | IOSTANDARD = LVCMOS33 ; # 49.152MHz crystal, GCLK0 45 | #NET "scs" LOC = "P43" | IOSTANDARD = LVCMOS33 ; 46 | #NET "soe" LOC = "P44" | IOSTANDARD = LVCMOS33 ; 47 | #NET "swr" LOC = "P64" | IOSTANDARD = LVCMOS33 ; 48 | #NET "fcs" LOC = "P49" | IOSTANDARD = LVCMOS33 ; 49 | 50 | #NET "pin1" LOC = "P89" | IOSTANDARD = LVCMOS33 ; # GCLK6 51 | #NET "pin2" LOC = "P90" | IOSTANDARD = LVCMOS33 ; # GCLK7 52 | #NET "pin3" LOC = "P92" | IOSTANDARD = LVCMOS33 ; 53 | #NET "pin4" LOC = "P91" | IOSTANDARD = LVCMOS33 ; 54 | #NET "pin5" LOC = "P16" | IOSTANDARD = LVCMOS33 ; 55 | #NET "pin6" LOC = "P14" | IOSTANDARD = LVCMOS33 ; 56 | #NET "pin7" LOC = "P17" | IOSTANDARD = LVCMOS33 ; 57 | #NET "pin8" LOC = "P15" | IOSTANDARD = LVCMOS33 ; 58 | #NET "pin9" LOC = "P21" | IOSTANDARD = LVCMOS33 ; 59 | #NET "pin10" LOC = "P22" | IOSTANDARD = LVCMOS33 ; 60 | #NET "pin11" LOC = "P23" | IOSTANDARD = LVCMOS33 ; 61 | 62 | NET "SCL" LOC = "P39" | IOSTANDARD = LVCMOS33 ; # GCLK1 # pin13 63 | NET "SDA" LOC = "P54" | IOSTANDARD = LVCMOS33 ; # pin14 64 | #NET "pin15" LOC = "P55" | IOSTANDARD = LVCMOS33 ; 65 | #NET "pin16" LOC = "P62" | IOSTANDARD = LVCMOS33 ; 66 | #NET "pin17" LOC = "P60" | IOSTANDARD = LVCMOS33 ; 67 | #NET "pin18" LOC = "P61" | IOSTANDARD = LVCMOS33 ; 68 | #NET "pin19" LOC = "P59" | IOSTANDARD = LVCMOS33 ; 69 | #NET "pin20" LOC = "P85" | IOSTANDARD = LVCMOS33 ; 70 | #NET "pin21" LOC = "P87" | IOSTANDARD = LVCMOS33 ; # GCLK4 71 | #NET "pin22" LOC = "P86" | IOSTANDARD = LVCMOS33 ; 72 | #NET "pin23" LOC = "P88" | IOSTANDARD = LVCMOS33 ; # GCLK5 73 | 74 | NET "res" LOC = "P27" | PULLUP | IOSTANDARD = LVCMOS33 ; # switch 1 75 | #NET "sw2" LOC = "P28" | PULLUP | IOSTANDARD = LVCMOS33 ; # switch 2 (fpga re-configure, optionally) 76 | 77 | # 7-pin test connector for display and other expansion 78 | # only tp7 and tp8 are 5V tolerant with level shifter 79 | #NET "tp2" LOC = "P30" | IOSTANDARD = LVCMOS33 ; 80 | #NET "tp3" LOC = "P32" | IOSTANDARD = LVCMOS33 ; 81 | #NET "tp4" LOC = "P34" | IOSTANDARD = LVCMOS33 ; 82 | #NET "tp5" LOC = "P35" | IOSTANDARD = LVCMOS33 ; 83 | #NET "tp6" LOC = "P36" | IOSTANDARD = LVCMOS33 ; 84 | #NET "tp7" LOC = "P37" | IOSTANDARD = LVCMOS33 ; # GCLK3 85 | #NET "tp8" LOC = "P47" | IOSTANDARD = LVCMOS33 ; 86 | -------------------------------------------------------------------------------- /build-xilinx/chip.v: -------------------------------------------------------------------------------- 1 | `include "../system-rtl/gop16.v" 2 | `include "../system-rtl/ram4k.v" 3 | `include "../system-rtl/uart.v" 4 | `include "../system-rtl/i2cslave.v" 5 | `include "../system-rtl/tinybootrom.v" 6 | `include "../cpu.v" 7 | `include "../ALU.v" 8 | -------------------------------------------------------------------------------- /cpu.v: -------------------------------------------------------------------------------- 1 | /* 2 | * verilog-6502 project: verilog model of 6502 and 65Org16 CPU core 3 | * 4 | * (C) 2011 Arlet Ottens, 5 | * (C) 2011 Ed Spittles, 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License version 2.1 as published by the Free Software Foundation. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | * 20 | */ 21 | 22 | /* 23 | * Note that not all 6502 interface signals are supported (yet). The goal 24 | * is to create an Acorn Atom model, and the Atom didn't use all signals on 25 | * the main board. 26 | * 27 | * The data bus is implemented as separate read/write buses. Combine them 28 | * on the output pads if external memory is required. 29 | */ 30 | 31 | module cpu( clk, reset, AB, DI, DO, WE, IRQ, NMI, RDY ); 32 | 33 | parameter dw = 16; // data width (8 for 6502, 16 for 65Org16) 34 | parameter aw = 32; // address width (16 for 6502, 32 for 65Org16) 35 | 36 | input clk; // CPU clock 37 | input reset; // reset signal 38 | output reg [aw-1:0] AB; // address bus 39 | input [dw-1:0] DI; // data in, read bus 40 | output [dw-1:0] DO; // data out, write bus 41 | output WE; // write enable 42 | input IRQ; // interrupt request 43 | input NMI; // non-maskable interrupt request 44 | input RDY; // Ready signal. Pauses CPU when RDY=0 45 | 46 | /* 47 | * internal signals 48 | */ 49 | 50 | reg [aw-1:0] PC; // Program Counter 51 | reg [dw-1:0] ABL; // Address Bus Register LSB 52 | reg [dw-1:0] ABH; // Address Bus Register MSB 53 | wire [dw-1:0] ADD; // Adder Hold Register (registered in ALU) 54 | 55 | reg [dw-1:0] DIHOLD; // Hold for Data In 56 | reg DIHOLD_valid; // 57 | wire [dw-1:0] DIMUX; // 58 | 59 | reg [dw-1:0] IRHOLD; // Hold for Instruction register 60 | reg IRHOLD_valid; // Valid instruction in IRHOLD 61 | 62 | reg [dw-1:0] AXYS[3:0]; // A, X, Y and S register file 63 | 64 | reg C = 0; // carry flag (init at zero to avoid X's in ALU sim) 65 | reg Z = 0; // zero flag 66 | reg I = 0; // interrupt flag 67 | reg D = 0; // decimal flag 68 | reg V = 0; // overflow flag 69 | reg N = 0; // negative flag 70 | wire AZ; // ALU Zero flag 71 | wire AV; // ALU overflow flag 72 | wire AN; // ALU negative flag 73 | wire HC; // ALU half carry 74 | 75 | reg [dw-1:0] AI; // ALU Input A 76 | reg [dw-1:0] BI; // ALU Input B 77 | wire [dw-1:0] DI; // Data In 78 | wire [dw-1:0] IR; // Instruction register 79 | reg [dw-1:0] DO; // Data Out 80 | reg WE; // Write Enable 81 | reg CI; // Carry In 82 | wire CO; // Carry Out 83 | wire [dw-1:0] PCH = PC[aw-1:dw]; 84 | wire [dw-1:0] PCL = PC[dw-1:0]; 85 | 86 | reg NMI_edge = 0; // captured NMI edge 87 | 88 | reg [1:0] regsel; // Select A, X, Y or S register 89 | wire [dw-1:0] regfile = AXYS[regsel]; // Selected register output 90 | 91 | parameter 92 | SEL_A = 2'd0, 93 | SEL_S = 2'd1, 94 | SEL_X = 2'd2, 95 | SEL_Y = 2'd3; 96 | 97 | /* 98 | * define some signals for watching in simulator output 99 | */ 100 | 101 | 102 | `ifdef SIM 103 | wire [dw-1:0] A = AXYS[SEL_A]; // Accumulator 104 | wire [dw-1:0] X = AXYS[SEL_X]; // X register 105 | wire [dw-1:0] Y = AXYS[SEL_Y]; // Y register 106 | wire [dw-1:0] S = AXYS[SEL_S]; // Stack pointer 107 | `endif 108 | 109 | wire [dw-1:0] P = { N, V, 2'b11, D, I, Z, C }; 110 | 111 | /* 112 | * instruction decoder/sequencer 113 | */ 114 | 115 | reg [5:0] state; 116 | 117 | /* 118 | * control signals 119 | */ 120 | 121 | reg PC_inc; // Increment PC 122 | reg [aw-1:0] PC_temp; // intermediate value of PC 123 | 124 | reg [1:0] src_reg; // source register index 125 | reg [1:0] dst_reg; // destination register index 126 | 127 | reg index_y; // if set, then Y is index reg rather than X 128 | reg load_reg; // loading a register (A, X, Y, S) in this instruction 129 | reg inc; // increment 130 | reg write_back; // set if memory is read/modified/written 131 | reg load_only; // LDA/LDX/LDY instruction 132 | reg store; // doing store (STA/STX/STY) 133 | reg adc_sbc; // doing ADC/SBC 134 | reg compare; // doing CMP/CPY/CPX 135 | reg shift; // doing shift/rotate instruction 136 | reg rotate; // doing rotate (no shift) 137 | reg backwards; // backwards branch 138 | reg cond_true; // branch condition is true 139 | reg [2:0] cond_code; // condition code bits from instruction 140 | reg shift_right; // Instruction ALU shift/rotate right 141 | reg alu_shift_right; // Current cycle shift right enable 142 | reg [3:0] op; // Main ALU operation for instruction 143 | reg [3:0] alu_op; // Current cycle ALU operation 144 | `ifdef BCD_ENABLED 145 | reg adc_bcd; // ALU should do BCD style carry 146 | reg adj_bcd; // results should be BCD adjusted 147 | `endif 148 | 149 | /* 150 | * some flip flops to remember we're doing special instructions. These 151 | * get loaded at the DECODE state, and used later 152 | */ 153 | reg bti; // doing BIT instruction (renamed: system verilog keyword) 154 | reg plp; // doing PLP instruction 155 | reg php; // doing PHP instruction 156 | reg clc; // clear carry 157 | reg sec; // set carry 158 | reg cld; // clear decimal 159 | reg sed; // set decimal 160 | reg cli; // clear interrupt 161 | reg sei; // set interrupt 162 | reg clv; // clear overflow 163 | // reg brk; // doing BRK 164 | 165 | reg res; // in reset 166 | 167 | /* 168 | * ALU operations 169 | */ 170 | 171 | parameter 172 | OP_OR = 4'b1100, 173 | OP_AND = 4'b1101, 174 | OP_EOR = 4'b1110, 175 | OP_ADD = 4'b0011, 176 | OP_SUB = 4'b0111, 177 | OP_ROL = 4'b1011, 178 | OP_A = 4'b1111; 179 | 180 | /* 181 | * Microcode state machine. Basically, every addressing mode has its own 182 | * path through the state machine. Additional information, such as the 183 | * operation, source and destination registers are decoded in parallel, and 184 | * kept in separate flops. 185 | */ 186 | 187 | parameter 188 | ABS0 = 6'd0, // ABS - fetch LSB 189 | ABS1 = 6'd1, // ABS - fetch MSB 190 | ABSX0 = 6'd2, // ABS, X - fetch LSB and send to ALU (+X) 191 | ABSX1 = 6'd3, // ABS, X - fetch MSB and send to ALU (+Carry) 192 | ABSX2 = 6'd4, // ABS, X - Wait for ALU (only if needed) 193 | BRA0 = 6'd5, // Branch - fetch offset and send to ALU (+PC[dw-1:0]) 194 | BRA1 = 6'd6, // Branch - fetch opcode, and send PC[aw-1:dw] to ALU 195 | BRA2 = 6'd7, // Branch - fetch opcode (if page boundary crossed) 196 | BRK0 = 6'd8, // BRK/IRQ - push PCH, send S to ALU (-1) 197 | BRK1 = 6'd9, // BRK/IRQ - push PCL, send S to ALU (-1) 198 | BRK2 = 6'd10, // BRK/IRQ - push P, send S to ALU (-1) 199 | BRK3 = 6'd11, // BRK/IRQ - write S, and fetch @ fffe 200 | DECODE = 6'd12, // IR is valid, decode instruction, and write prev reg 201 | FETCH = 6'd13, // fetch next opcode, and perform prev ALU op 202 | INDX0 = 6'd14, // (ZP,X) - fetch ZP address, and send to ALU (+X) 203 | INDX1 = 6'd15, // (ZP,X) - fetch LSB at ZP+X, calculate ZP+X+1 204 | INDX2 = 6'd16, // (ZP,X) - fetch MSB at ZP+X+1 205 | INDX3 = 6'd17, // (ZP,X) - fetch data 206 | INDY0 = 6'd18, // (ZP),Y - fetch ZP address, and send ZP to ALU (+1) 207 | INDY1 = 6'd19, // (ZP),Y - fetch at ZP+1, and send LSB to ALU (+Y) 208 | INDY2 = 6'd20, // (ZP),Y - fetch data, and send MSB to ALU (+Carry) 209 | INDY3 = 6'd21, // (ZP),Y) - fetch data (if page boundary crossed) 210 | JMP0 = 6'd22, // JMP - fetch PCL and hold 211 | JMP1 = 6'd23, // JMP - fetch PCH 212 | JMPI0 = 6'd24, // JMP IND - fetch LSB and send to ALU for delay (+0) 213 | JMPI1 = 6'd25, // JMP IND - fetch MSB, proceed with JMP0 state 214 | JSR0 = 6'd26, // JSR - push PCH, save LSB, send S to ALU (-1) 215 | JSR1 = 6'd27, // JSR - push PCL, send S to ALU (-1) 216 | JSR2 = 6'd28, // JSR - write S 217 | JSR3 = 6'd29, // JSR - fetch MSB 218 | PULL0 = 6'd30, // PLP/PLA - save next op in IRHOLD, send S to ALU (+1) 219 | PULL1 = 6'd31, // PLP/PLA - fetch data from stack, write S 220 | PULL2 = 6'd32, // PLP/PLA - prefetch op, but don't increment PC 221 | PUSH0 = 6'd33, // PHP/PHA - send A to ALU (+0) 222 | PUSH1 = 6'd34, // PHP/PHA - write A/P, send S to ALU (-1) 223 | READ = 6'd35, // Read memory for read/modify/write (INC, DEC, shift) 224 | REG = 6'd36, // Read register for reg-reg transfers 225 | RTI0 = 6'd37, // RTI - send S to ALU (+1) 226 | RTI1 = 6'd38, // RTI - read P from stack 227 | RTI2 = 6'd39, // RTI - read PCL from stack 228 | RTI3 = 6'd40, // RTI - read PCH from stack 229 | RTI4 = 6'd41, // RTI - read PCH from stack 230 | RTS0 = 6'd42, // RTS - send S to ALU (+1) 231 | RTS1 = 6'd43, // RTS - read PCL from stack 232 | RTS2 = 6'd44, // RTS - write PCL to ALU, read PCH 233 | RTS3 = 6'd45, // RTS - load PC and increment 234 | WRITE = 6'd46, // Write memory for read/modify/write 235 | ZP0 = 6'd47, // Z-page - fetch ZP address 236 | ZPX0 = 6'd48, // ZP, X - fetch ZP, and send to ALU (+X) 237 | ZPX1 = 6'd49; // ZP, X - load from memory 238 | 239 | `ifdef SIM 240 | 241 | /* 242 | * easy to read names in simulator output 243 | */ 244 | reg [8*6-1:0] statename; 245 | 246 | always @* 247 | case( state ) 248 | DECODE: statename = "DECODE"; 249 | REG: statename = "REG"; 250 | ZP0: statename = "ZP0"; 251 | ZPX0: statename = "ZPX0"; 252 | ZPX1: statename = "ZPX1"; 253 | ABS0: statename = "ABS0"; 254 | ABS1: statename = "ABS1"; 255 | ABSX0: statename = "ABSX0"; 256 | ABSX1: statename = "ABSX1"; 257 | ABSX2: statename = "ABSX2"; 258 | INDX0: statename = "INDX0"; 259 | INDX1: statename = "INDX1"; 260 | INDX2: statename = "INDX2"; 261 | INDX3: statename = "INDX3"; 262 | INDY0: statename = "INDY0"; 263 | INDY1: statename = "INDY1"; 264 | INDY2: statename = "INDY2"; 265 | INDY3: statename = "INDY3"; 266 | READ: statename = "READ"; 267 | WRITE: statename = "WRITE"; 268 | FETCH: statename = "FETCH"; 269 | PUSH0: statename = "PUSH0"; 270 | PUSH1: statename = "PUSH1"; 271 | PULL0: statename = "PULL0"; 272 | PULL1: statename = "PULL1"; 273 | PULL2: statename = "PULL2"; 274 | JSR0: statename = "JSR0"; 275 | JSR1: statename = "JSR1"; 276 | JSR2: statename = "JSR2"; 277 | JSR3: statename = "JSR3"; 278 | RTI0: statename = "RTI0"; 279 | RTI1: statename = "RTI1"; 280 | RTI2: statename = "RTI2"; 281 | RTI3: statename = "RTI3"; 282 | RTI4: statename = "RTI4"; 283 | RTS0: statename = "RTS0"; 284 | RTS1: statename = "RTS1"; 285 | RTS2: statename = "RTS2"; 286 | RTS3: statename = "RTS3"; 287 | BRK0: statename = "BRK0"; 288 | BRK1: statename = "BRK1"; 289 | BRK2: statename = "BRK2"; 290 | BRK3: statename = "BRK3"; 291 | BRA0: statename = "BRA0"; 292 | BRA1: statename = "BRA1"; 293 | BRA2: statename = "BRA2"; 294 | JMP0: statename = "JMP0"; 295 | JMP1: statename = "JMP1"; 296 | JMPI0: statename = "JMPI0"; 297 | JMPI1: statename = "JMPI1"; 298 | endcase 299 | 300 | //always @( PC ) 301 | // $display( "%t, PC:%04x IR:%02x A:%02x X:%02x Y:%02x S:%02x C:%d Z:%d V:%d N:%d P:%02x", $time, PC, IR, A, X, Y, S, C, Z, V, N, P ); 302 | 303 | `endif 304 | 305 | 306 | 307 | /* 308 | * Program Counter Increment/Load. First calculate the base value in 309 | * PC_temp. 310 | */ 311 | always @* 312 | case( state ) 313 | DECODE: if( (~I & IRQ) | NMI_edge ) 314 | PC_temp = { ABH, ABL }; 315 | else 316 | PC_temp = PC; 317 | 318 | 319 | JMP1, 320 | JMPI1, 321 | JSR3, 322 | RTS3, 323 | RTI4: PC_temp = { DIMUX, ADD }; 324 | 325 | BRA1: PC_temp = { ABH, ADD }; 326 | 327 | BRA2: PC_temp = { ADD, PCL }; 328 | 329 | BRK2: PC_temp = res ? 32'hfffffffc : 330 | NMI_edge ? 32'hfffffffa : 32'hfffffffe; // width should be parameterised 331 | 332 | default: PC_temp = PC; 333 | endcase 334 | 335 | /* 336 | * Determine wether we need PC_temp, or PC_temp + 1 337 | */ 338 | always @* 339 | case( state ) 340 | DECODE: if( (~I & IRQ) | NMI_edge ) 341 | PC_inc = 0; 342 | else 343 | PC_inc = 1; 344 | 345 | ABS0, 346 | ABSX0, 347 | FETCH, 348 | BRA0, 349 | BRA2, 350 | BRK3, 351 | JMPI1, 352 | JMP1, 353 | RTI4, 354 | RTS3: PC_inc = 1; 355 | 356 | BRA1: PC_inc = CO ^~ backwards; 357 | 358 | default: PC_inc = 0; 359 | endcase 360 | 361 | /* 362 | * Set new PC 363 | */ 364 | always @(posedge clk) 365 | if( RDY ) 366 | PC <= PC_temp + PC_inc; 367 | 368 | /* 369 | * Address Generator 370 | */ 371 | 372 | parameter dw_m1 = dw -1; 373 | 374 | parameter 375 | ZEROPAGE = {dw{1'b0}}; // all zero 376 | parameter 377 | STACKPAGE = 1'b1; // one 378 | // STACKPAGE = {dw_m1{1'b0}, 1'b1}; // one 379 | 380 | always @* 381 | case( state ) 382 | ABSX1, 383 | INDX3, 384 | INDY2, 385 | JMP1, 386 | JMPI1, 387 | RTI4, 388 | ABS1: AB = { DIMUX, ADD }; 389 | 390 | BRA2, 391 | INDY3, 392 | ABSX2: AB = { ADD, ABL }; 393 | 394 | BRA1: AB = { ABH, ADD }; 395 | 396 | JSR0, 397 | PUSH1, 398 | RTS0, 399 | RTI0, 400 | BRK0: AB = { STACKPAGE, regfile }; 401 | 402 | BRK1, 403 | JSR1, 404 | PULL1, 405 | RTS1, 406 | RTS2, 407 | RTI1, 408 | RTI2, 409 | RTI3, 410 | BRK2: AB = { STACKPAGE, ADD }; 411 | 412 | INDY1, 413 | INDX1, 414 | ZPX1, 415 | INDX2: AB = { ZEROPAGE, ADD }; 416 | 417 | ZP0, 418 | INDY0: AB = { ZEROPAGE, DIMUX }; 419 | 420 | REG, 421 | READ, 422 | WRITE: AB = { ABH, ABL }; 423 | 424 | default: AB = PC; 425 | endcase 426 | 427 | /* 428 | * ABH/ABL pair is used for registering previous address bus state. 429 | * This can be used to keep the current address, freeing up the original 430 | * source of the address, such as the ALU or DI. 431 | */ 432 | always @(posedge clk) 433 | if( state != PUSH0 && state != PUSH1 && RDY && 434 | state != PULL0 && state != PULL1 && state != PULL2 ) 435 | begin 436 | ABL <= AB[dw-1:0]; 437 | ABH <= AB[aw-1:dw]; 438 | end 439 | 440 | /* 441 | * Data Out MUX 442 | */ 443 | always @* 444 | case( state ) 445 | WRITE: DO = ADD; 446 | 447 | JSR0, 448 | BRK0: DO = PCH; 449 | 450 | JSR1, 451 | BRK1: DO = PCL; 452 | 453 | PUSH1: DO = php ? P : ADD; 454 | 455 | BRK2: DO = (IRQ | NMI_edge) ? (P & ~8'b0001_0000) : P; // B bit should be parameterised 456 | 457 | default: DO = regfile; 458 | endcase 459 | 460 | /* 461 | * Write Enable Generator 462 | */ 463 | 464 | always @* 465 | case( state ) 466 | BRK0, // writing to stack or memory 467 | BRK1, 468 | BRK2, 469 | JSR0, 470 | JSR1, 471 | PUSH1, 472 | WRITE: WE = 1; 473 | 474 | INDX3, // only if doing a STA, STX or STY 475 | INDY3, 476 | ABSX2, 477 | ABS1, 478 | ZPX1, 479 | ZP0: WE = store; 480 | 481 | default: WE = 0; 482 | endcase 483 | 484 | /* 485 | * register file, contains A, X, Y and S (stack pointer) registers. At each 486 | * cycle only 1 of those registers needs to be accessed, so they combined 487 | * in a small memory, saving resources. 488 | */ 489 | 490 | reg write_register; // set when register file is written 491 | 492 | always @* 493 | case( state ) 494 | DECODE: write_register = load_reg & ~plp; 495 | 496 | PULL1, 497 | RTS2, 498 | RTI3, 499 | BRK3, 500 | JSR0, 501 | JSR2 : write_register = 1; 502 | 503 | default: write_register = 0; 504 | endcase 505 | 506 | `ifdef BCD_ENABLED 507 | /* 508 | * BCD adjust logic 509 | */ 510 | 511 | always @(posedge clk) 512 | adj_bcd <= adc_sbc & D; // '1' when doing a BCD instruction 513 | 514 | reg [3:0] ADJL; 515 | reg [3:0] ADJH; 516 | 517 | // adjustment term to be added to ADD[3:0] based on the following 518 | // adj_bcd: '1' if doing ADC/SBC with D=1 519 | // adc_bcd: '1' if doing ADC with D=1 520 | // HC : half carry bit from ALU 521 | always @* begin 522 | casex( {adj_bcd, adc_bcd, HC} ) 523 | 3'b0xx: ADJL = 4'd0; // no BCD instruction 524 | 3'b100: ADJL = 4'd10; // SBC, and digital borrow 525 | 3'b101: ADJL = 4'd0; // SBC, but no borrow 526 | 3'b110: ADJL = 4'd0; // ADC, but no carry 527 | 3'b111: ADJL = 4'd6; // ADC, and decimal/digital carry 528 | endcase 529 | end 530 | 531 | // adjustment term to be added to ADD[dw-1:4] based on the following 532 | // adj_bcd: '1' if doing ADC/SBC with D=1 533 | // adc_bcd: '1' if doing ADC with D=1 534 | // CO : carry out bit from ALU 535 | always @* begin 536 | casex( {adj_bcd, adc_bcd, CO} ) 537 | 3'b0xx: ADJH = 4'd0; // no BCD instruction 538 | 3'b100: ADJH = 4'd10; // SBC, and digital borrow 539 | 3'b101: ADJH = 4'd0; // SBC, but no borrow 540 | 3'b110: ADJH = 4'd0; // ADC, but no carry 541 | 3'b111: ADJH = 4'd6; // ADC, and decimal/digital carry 542 | endcase 543 | end 544 | `else 545 | parameter ADJH = 4'd0; 546 | parameter ADJL = 4'd0; 547 | `endif 548 | 549 | /* 550 | * write to a register. Usually this is the (BCD corrected) output of the 551 | * ALU, but in case of the JSR0 we use the S register to temporarily store 552 | * the PCL. This is possible, because the S register itself is stored in 553 | * the ALU during those cycles. 554 | */ 555 | always @(posedge clk) 556 | if( write_register & RDY ) 557 | AXYS[regsel] <= (state == JSR0) ? DIMUX : { ADD[dw-1:4] + ADJH, ADD[3:0] + ADJL }; 558 | 559 | /* 560 | * register select logic. This determines which of the A, X, Y or 561 | * S registers will be accessed. 562 | */ 563 | 564 | always @* 565 | case( state ) 566 | INDY1, 567 | INDX0, 568 | ZPX0, 569 | ABSX0 : regsel = index_y ? SEL_Y : SEL_X; 570 | 571 | 572 | DECODE : regsel = dst_reg; 573 | 574 | BRK0, 575 | BRK3, 576 | JSR0, 577 | JSR2, 578 | PULL0, 579 | PULL1, 580 | PUSH1, 581 | RTI0, 582 | RTI3, 583 | RTS0, 584 | RTS2 : regsel = SEL_S; 585 | 586 | default: regsel = src_reg; 587 | endcase 588 | 589 | /* 590 | * ALU 591 | */ 592 | 593 | ALU #(.dw(dw)) _ALU( 594 | .clk(clk), 595 | .op(alu_op), 596 | .right(alu_shift_right), 597 | .AI(AI), 598 | .BI(BI), 599 | .CI(CI), 600 | .CO(CO), 601 | .OUT(ADD), 602 | .V(AV), 603 | .Z(AZ), 604 | .N(AN), 605 | `ifdef BCD_ENABLED 606 | .BCD(adc_bcd & (state == FETCH)), 607 | .HC(HC), 608 | `endif 609 | .RDY(RDY) ); 610 | 611 | /* 612 | * Select current ALU operation 613 | */ 614 | 615 | always @* 616 | case( state ) 617 | READ: alu_op = op; 618 | 619 | BRA1: alu_op = backwards ? OP_SUB : OP_ADD; 620 | 621 | FETCH, 622 | REG : alu_op = op; 623 | 624 | DECODE, 625 | ABS1: alu_op = 1'bx; 626 | 627 | PUSH1, 628 | BRK0, 629 | BRK1, 630 | BRK2, 631 | JSR0, 632 | JSR1: alu_op = OP_SUB; 633 | 634 | default: alu_op = OP_ADD; 635 | endcase 636 | 637 | /* 638 | * Determine shift right signal to ALU 639 | */ 640 | 641 | always @* 642 | if( state == FETCH || state == REG || state == READ ) 643 | alu_shift_right = shift_right; 644 | else 645 | alu_shift_right = 0; 646 | 647 | /* 648 | * Sign extend branch offset. 649 | */ 650 | 651 | always @(posedge clk) 652 | if( RDY ) 653 | backwards <= DIMUX[dw-1]; 654 | 655 | /* 656 | * ALU A Input MUX 657 | */ 658 | 659 | always @* 660 | case( state ) 661 | JSR1, 662 | RTS1, 663 | RTI1, 664 | RTI2, 665 | BRK1, 666 | BRK2, 667 | INDX1: AI = ADD; 668 | 669 | REG, 670 | ZPX0, 671 | INDX0, 672 | ABSX0, 673 | RTI0, 674 | RTS0, 675 | JSR0, 676 | JSR2, 677 | BRK0, 678 | PULL0, 679 | INDY1, 680 | PUSH0, 681 | PUSH1: AI = regfile; 682 | 683 | BRA0, 684 | READ: AI = DIMUX; 685 | 686 | BRA1: AI = ABH; // don't use PCH in case we're 687 | 688 | FETCH: AI = load_only ? {dw{1'b0}} : regfile; 689 | 690 | DECODE, 691 | ABS1: AI = {dw{1'bx}}; // don't care 692 | 693 | default: AI = 0; 694 | endcase 695 | 696 | 697 | /* 698 | * ALU B Input mux 699 | */ 700 | 701 | always @* 702 | case( state ) 703 | BRA1, 704 | JSR1, 705 | RTS1, 706 | RTI0, 707 | RTI1, 708 | RTI2, 709 | INDX1, 710 | READ, 711 | REG, 712 | JSR0, 713 | JSR2, 714 | BRK0, 715 | BRK1, 716 | BRK2, 717 | PUSH0, 718 | PUSH1, 719 | PULL0, 720 | RTS0: BI = {dw{1'b0}}; 721 | 722 | BRA0: BI = PCL; 723 | 724 | DECODE, 725 | ABS1: BI = {dw{1'bx}}; // don't care 726 | 727 | default: BI = DIMUX; 728 | endcase 729 | 730 | /* 731 | * ALU CI (carry in) mux 732 | */ 733 | 734 | always @* 735 | case( state ) 736 | INDY2, 737 | BRA1, 738 | ABSX1: CI = CO; 739 | 740 | DECODE, 741 | ABS1: CI = 1'bx; 742 | 743 | READ, 744 | REG: CI = rotate ? C : 745 | shift ? 1'b0 : inc; 746 | 747 | FETCH: CI = rotate ? C : 748 | compare ? 1'b1 : 749 | (shift | load_only) ? 1'b0 : C; 750 | 751 | PULL0, 752 | RTI0, 753 | RTI1, 754 | RTI2, 755 | RTS0, 756 | RTS1, 757 | INDY0, 758 | INDX1: CI = 1; 759 | 760 | default: CI = 0; 761 | endcase 762 | 763 | /* 764 | * Processor Status Register update 765 | * 766 | */ 767 | 768 | /* 769 | * Update C flag when doing ADC/SBC, shift/rotate, compare 770 | */ 771 | always @(posedge clk ) 772 | if( shift && state == WRITE ) 773 | C <= CO; 774 | else if( state == RTI2 ) 775 | C <= DIMUX[0]; 776 | else if( ~write_back && state == DECODE ) begin 777 | if( adc_sbc | shift | compare ) 778 | C <= CO; 779 | else if( plp ) 780 | C <= ADD[0]; 781 | else begin 782 | if( sec ) C <= 1; 783 | if( clc ) C <= 0; 784 | end 785 | end 786 | 787 | /* 788 | * Update Z, N flags when writing A, X, Y, Memory, or when doing compare 789 | */ 790 | 791 | always @(posedge clk) 792 | if( state == WRITE ) 793 | Z <= AZ; 794 | else if( state == RTI2 ) 795 | Z <= DIMUX[1]; 796 | else if( state == DECODE ) begin 797 | if( plp ) 798 | Z <= ADD[1]; 799 | else if( (load_reg & (regsel != SEL_S)) | compare | bti ) 800 | Z <= AZ; 801 | end 802 | 803 | always @(posedge clk) 804 | if( state == WRITE ) 805 | N <= AN; 806 | else if( state == RTI2 ) 807 | N <= DIMUX[dw-1]; 808 | else if( state == DECODE ) begin 809 | if( plp ) 810 | N <= ADD[dw-1]; 811 | else if( (load_reg & (regsel != SEL_S)) | compare ) 812 | N <= AN; 813 | end else if( state == FETCH && bti ) 814 | N <= DIMUX[dw-1]; 815 | 816 | /* 817 | * Update I flag 818 | */ 819 | 820 | always @(posedge clk) 821 | if( state == BRK3 ) 822 | I <= 1; 823 | else if( state == RTI2 ) 824 | I <= DIMUX[2]; 825 | else if( state == REG ) begin 826 | if( sei ) I <= 1; 827 | if( cli ) I <= 0; 828 | end else if( state == DECODE ) 829 | if( plp ) I <= ADD[2]; 830 | 831 | /* 832 | * Update D flag 833 | */ 834 | always @(posedge clk ) 835 | if( state == RTI2 ) 836 | D <= DIMUX[3]; 837 | else if( state == DECODE ) begin 838 | if( sed ) D <= 1; 839 | if( cld ) D <= 0; 840 | if( plp ) D <= ADD[3]; 841 | end 842 | 843 | /* 844 | * Update V flag (next to top bit) 845 | */ 846 | always @(posedge clk ) 847 | if( state == RTI2 ) 848 | V <= DIMUX[dw-2]; 849 | else if( state == DECODE ) begin 850 | if( adc_sbc ) V <= AV; 851 | if( clv ) V <= 0; 852 | if( plp ) V <= ADD[dw-2]; 853 | end else if( state == FETCH && bti ) 854 | V <= DIMUX[dw-2]; 855 | 856 | /* 857 | * Instruction decoder 858 | */ 859 | 860 | /* 861 | * IR register/mux. Hold previous DI value in IRHOLD in PULL0 and PUSH0 862 | * states. In these states, the IR has been prefetched, and there is no 863 | * time to read the IR again before the next decode. 864 | */ 865 | 866 | reg RDY1 = 1; 867 | 868 | always @(posedge clk ) 869 | RDY1 <= RDY; 870 | 871 | always @(posedge clk ) 872 | if( ~RDY && RDY1 ) 873 | DIHOLD <= DI; 874 | 875 | always @(posedge clk ) 876 | if( reset ) 877 | IRHOLD_valid <= 0; 878 | else if( RDY ) begin 879 | if( state == PULL0 || state == PUSH0 ) begin 880 | IRHOLD <= DIMUX; 881 | IRHOLD_valid <= 1; 882 | end else if( state == DECODE ) 883 | IRHOLD_valid <= 0; 884 | end 885 | 886 | assign IR = (IRQ & ~I) | NMI_edge ? {dw{1'b0}} : 887 | IRHOLD_valid ? IRHOLD : DIMUX; 888 | 889 | assign DIMUX = ~RDY1 ? DIHOLD : DI; 890 | 891 | /* 892 | * Microcode state machine 893 | */ 894 | always @(posedge clk or posedge reset) 895 | if( reset ) 896 | state <= BRK0; 897 | else if( RDY ) case( state ) 898 | DECODE : 899 | casex ( IR[7:0] ) // just decode the low 8 bits 900 | 8'b0000_0000: state <= BRK0; 901 | 8'b0010_0000: state <= JSR0; 902 | 8'b0010_1100: state <= ABS0; // BIT abs 903 | 8'b0100_0000: state <= RTI0; // 904 | 8'b0100_1100: state <= JMP0; 905 | 8'b0110_0000: state <= RTS0; 906 | 8'b0110_1100: state <= JMPI0; 907 | 8'b0x00_1000: state <= PUSH0; 908 | 8'b0x10_1000: state <= PULL0; 909 | 8'b0xx1_1000: state <= REG; // CLC, SEC, CLI, SEI 910 | 8'b1xx0_00x0: state <= FETCH; // IMM 911 | 8'b1xx0_1100: state <= ABS0; // X/Y abs 912 | 8'b1xxx_1000: state <= REG; // DEY, TYA, ... 913 | 8'bxxx0_0001: state <= INDX0; 914 | 8'bxxx0_01xx: state <= ZP0; 915 | 8'bxxx0_1001: state <= FETCH; // IMM 916 | 8'bxxx0_1101: state <= ABS0; // even E column 917 | 8'bxxx0_1110: state <= ABS0; // even E column 918 | 8'bxxx1_0000: state <= BRA0; // odd 0 column 919 | 8'bxxx1_0001: state <= INDY0; // odd 1 column 920 | 8'bxxx1_01xx: state <= ZPX0; // odd 4,5,6,7 columns 921 | 8'bxxx1_1001: state <= ABSX0; // odd 9 column 922 | 8'bxxx1_11xx: state <= ABSX0; // odd C, D, E, F columns 923 | 8'bxxxx_1010: state <= REG; // A, TXA, ... NOP 924 | endcase 925 | 926 | ZP0 : state <= write_back ? READ : FETCH; 927 | 928 | ZPX0 : state <= ZPX1; 929 | ZPX1 : state <= write_back ? READ : FETCH; 930 | 931 | ABS0 : state <= ABS1; 932 | ABS1 : state <= write_back ? READ : FETCH; 933 | 934 | ABSX0 : state <= ABSX1; 935 | ABSX1 : state <= (CO | store | write_back) ? ABSX2 : FETCH; 936 | ABSX2 : state <= write_back ? READ : FETCH; 937 | 938 | INDX0 : state <= INDX1; 939 | INDX1 : state <= INDX2; 940 | INDX2 : state <= INDX3; 941 | INDX3 : state <= FETCH; 942 | 943 | INDY0 : state <= INDY1; 944 | INDY1 : state <= INDY2; 945 | INDY2 : state <= (CO | store) ? INDY3 : FETCH; 946 | INDY3 : state <= FETCH; 947 | 948 | READ : state <= WRITE; 949 | WRITE : state <= FETCH; 950 | FETCH : state <= DECODE; 951 | 952 | REG : state <= DECODE; 953 | 954 | PUSH0 : state <= PUSH1; 955 | PUSH1 : state <= DECODE; 956 | 957 | PULL0 : state <= PULL1; 958 | PULL1 : state <= PULL2; 959 | PULL2 : state <= DECODE; 960 | 961 | JSR0 : state <= JSR1; 962 | JSR1 : state <= JSR2; 963 | JSR2 : state <= JSR3; 964 | JSR3 : state <= FETCH; 965 | 966 | RTI0 : state <= RTI1; 967 | RTI1 : state <= RTI2; 968 | RTI2 : state <= RTI3; 969 | RTI3 : state <= RTI4; 970 | RTI4 : state <= DECODE; 971 | 972 | RTS0 : state <= RTS1; 973 | RTS1 : state <= RTS2; 974 | RTS2 : state <= RTS3; 975 | RTS3 : state <= FETCH; 976 | 977 | BRA0 : state <= cond_true ? BRA1 : DECODE; 978 | BRA1 : state <= (CO ^ backwards) ? BRA2 : DECODE; 979 | BRA2 : state <= DECODE; 980 | 981 | JMP0 : state <= JMP1; 982 | JMP1 : state <= DECODE; 983 | 984 | JMPI0 : state <= JMPI1; 985 | JMPI1 : state <= JMP0; 986 | 987 | BRK0 : state <= BRK1; 988 | BRK1 : state <= BRK2; 989 | BRK2 : state <= BRK3; 990 | BRK3 : state <= JMP0; 991 | 992 | endcase 993 | 994 | /* 995 | * Additional control signals 996 | */ 997 | 998 | always @(posedge clk) 999 | if( reset ) 1000 | res <= 1; 1001 | else if( state == DECODE ) 1002 | res <= 0; 1003 | 1004 | always @(posedge clk) 1005 | if( state == DECODE && RDY ) 1006 | casex( IR ) 1007 | 8'b0xxx_xx01, // ORA, AND, EOR, ADC 1008 | 8'b1x1x_xx01, // LDA, SBC 1009 | 8'bxxxx_1010, // ASLA, ROLA, LSRA, RORA, T[XS][SX], DEX, NOP, 1010 | 8'bxxx0_1000, // PHP, PLP, PHA, PLA, DEY, TAY, INY, INX 1011 | 8'b1001_1000, // TYA 1012 | 8'b1011_x1x0, // LDX/LDY 1013 | 8'b1010_xxx0: // LDA/LDX/LDY 1014 | load_reg <= 1; 1015 | 1016 | default: load_reg <= 0; 1017 | endcase 1018 | 1019 | always @(posedge clk) 1020 | if( state == DECODE && RDY ) 1021 | casex( IR[7:0] ) // just decode the low 8 bits 1022 | 8'b1110_1000, // INX 1023 | 8'b1100_1010, // DEX 1024 | 8'b101x_xx10: // LDX, TAX, TSX 1025 | dst_reg <= SEL_X; 1026 | 1027 | 8'b0x00_1000, // PHP, PHA 1028 | 8'b1001_1010: // TXS 1029 | dst_reg <= SEL_S; 1030 | 1031 | 8'b1x00_1000, // DEY, DEX 1032 | 8'b101x_x100, // LDY 1033 | 8'b1010_x000: // LDY #imm, TAY 1034 | dst_reg <= SEL_Y; 1035 | 1036 | default: dst_reg <= SEL_A; 1037 | endcase 1038 | 1039 | always @(posedge clk) 1040 | if( state == DECODE && RDY ) 1041 | casex( IR[7:0] ) // just decode the low 8 bits 1042 | 8'b1011_1010: // TSX 1043 | src_reg <= SEL_S; 1044 | 1045 | 8'b100x_x110, // STX 1046 | 8'b100x_1x10, // TXA, TXS 1047 | 8'b1110_xx00, // INX, CPX 1048 | 8'b1100_1010: // DEX 1049 | src_reg <= SEL_X; 1050 | 1051 | 8'b100x_x100, // STY 1052 | 8'b1001_1000, // TYA 1053 | 8'b1100_xx00, // CPY 1054 | 8'b1x00_1000: // DEY, INY 1055 | src_reg <= SEL_Y; 1056 | 1057 | default: src_reg <= SEL_A; 1058 | endcase 1059 | 1060 | always @(posedge clk) 1061 | if( state == DECODE && RDY ) 1062 | casex( IR[7:0] ) // just decode the low 8 bits 1063 | 8'bxxx1_0001, // INDY 1064 | 8'b10x1_x110, // LDX/STX zpg/abs, Y 1065 | 8'bxxxx_1001: // abs, Y 1066 | index_y <= 1; 1067 | 1068 | default: index_y <= 0; 1069 | endcase 1070 | 1071 | 1072 | always @(posedge clk) 1073 | if( state == DECODE && RDY ) 1074 | casex( IR[7:0] ) // just decode the low 8 bits 1075 | 8'b100x_x1x0, // STX, STY 1076 | 8'b100x_xx01: // STA 1077 | store <= 1; 1078 | 1079 | default: store <= 0; 1080 | 1081 | endcase 1082 | 1083 | always @(posedge clk ) 1084 | if( state == DECODE && RDY ) 1085 | casex( IR[7:0] ) // just decode the low 8 bits 1086 | 8'b0xxx_x110, // ASL, ROL, LSR, ROR 1087 | 8'b11xx_x110: // DEC/INC 1088 | write_back <= 1; 1089 | 1090 | default: write_back <= 0; 1091 | endcase 1092 | 1093 | 1094 | always @(posedge clk ) 1095 | if( state == DECODE && RDY ) 1096 | casex( IR[7:0] ) // just decode the low 8 bits 1097 | 8'b101x_xxxx: // LDA, LDX, LDY 1098 | load_only <= 1; 1099 | default: load_only <= 0; 1100 | endcase 1101 | 1102 | always @(posedge clk ) 1103 | if( state == DECODE && RDY ) 1104 | casex( IR[7:0] ) // just decode the low 8 bits 1105 | 8'b111x_x110, // INC 1106 | 8'b11x0_1000: // INX, INY 1107 | inc <= 1; 1108 | 1109 | default: inc <= 0; 1110 | endcase 1111 | 1112 | always @(posedge clk ) 1113 | if( (state == DECODE || state == BRK0) && RDY ) 1114 | casex( IR[7:0] ) // just decode the low 8 bits 1115 | 8'bx11x_xx01: // SBC, ADC 1116 | adc_sbc <= 1; 1117 | 1118 | default: adc_sbc <= 0; 1119 | endcase 1120 | 1121 | `ifdef BCD_ENABLED 1122 | always @(posedge clk ) 1123 | if( (state == DECODE || state == BRK0) && RDY ) 1124 | casex( IR[7:0] ) // just decode the low 8 bits 1125 | 8'b011x_xx01: // ADC 1126 | adc_bcd <= D; 1127 | 1128 | default: adc_bcd <= 0; 1129 | endcase 1130 | `endif 1131 | 1132 | always @(posedge clk ) 1133 | if( state == DECODE && RDY ) 1134 | casex( IR[7:0] ) // just decode the low 8 bits 1135 | 8'b0xxx_x110, // ASL, ROL, LSR, ROR (abs, absx, zpg, zpgx) 1136 | 8'b0xxx_1010: // ASL, ROL, LSR, ROR (acc) 1137 | shift <= 1; 1138 | 1139 | default: shift <= 0; 1140 | endcase 1141 | 1142 | always @(posedge clk ) 1143 | if( state == DECODE && RDY ) 1144 | casex( IR[7:0] ) // just decode the low 8 bits 1145 | 8'b11x0_0x00, // CPX, CPY (imm/zp) 1146 | 8'b11x0_1100, // CPX, CPY (abs) 1147 | 8'b110x_xx01: // CMP 1148 | compare <= 1; 1149 | 1150 | default: compare <= 0; 1151 | endcase 1152 | 1153 | always @(posedge clk ) 1154 | if( state == DECODE && RDY ) 1155 | casex( IR[7:0] ) // just decode the low 8 bits 1156 | 8'b01xx_xx10: // ROR, LSR 1157 | shift_right <= 1; 1158 | 1159 | default: shift_right <= 0; 1160 | endcase 1161 | 1162 | always @(posedge clk ) 1163 | if( state == DECODE && RDY ) 1164 | casex( IR[7:0] ) // just decode the low 8 bits 1165 | 8'b0x1x_1010, // ROL A, ROR A 1166 | 8'b0x1x_x110: // ROR, ROL 1167 | rotate <= 1; 1168 | 1169 | default: rotate <= 0; 1170 | endcase 1171 | 1172 | always @(posedge clk ) 1173 | if( state == DECODE && RDY ) 1174 | casex( IR[7:0] ) // just decode the low 8 bits 1175 | 8'b00xx_xx10: // ROL, ASL 1176 | op <= OP_ROL; 1177 | 1178 | 8'b0010_x100: // BIT zp/abs 1179 | op <= OP_AND; 1180 | 1181 | 8'b01xx_xx10: // ROR, LSR 1182 | op <= OP_A; 1183 | 1184 | 8'b1000_1000, // DEY 1185 | 8'b1100_1010, // DEX 1186 | 8'b110x_x110, // DEC 1187 | 8'b11xx_xx01, // CMP, SBC 1188 | 8'b11x0_0x00, // CPX, CPY (imm, zpg) 1189 | 8'b11x0_1100: op <= OP_SUB; 1190 | 1191 | 8'b010x_xx01, // EOR 1192 | 8'b00xx_xx01: // ORA, AND 1193 | op <= { 2'b11, IR[6:5] }; 1194 | 1195 | default: op <= OP_ADD; 1196 | endcase 1197 | 1198 | always @(posedge clk ) 1199 | if( state == DECODE && RDY ) 1200 | casex( IR[7:0] ) // just decode the low 8 bits 1201 | 8'b0010_x100: // BIT zp/abs 1202 | bti <= 1; 1203 | 1204 | default: bti <= 0; 1205 | endcase 1206 | 1207 | /* 1208 | * special instructions 1209 | */ 1210 | always @(posedge clk ) 1211 | if( state == DECODE && RDY ) begin 1212 | php <= (IR[7:0] == 8'h08); 1213 | clc <= (IR[7:0] == 8'h18); 1214 | plp <= (IR[7:0] == 8'h28); 1215 | sec <= (IR[7:0] == 8'h38); 1216 | cli <= (IR[7:0] == 8'h58); 1217 | sei <= (IR[7:0] == 8'h78); 1218 | clv <= (IR[7:0] == 8'hb8); 1219 | cld <= (IR[7:0] == 8'hd8); 1220 | sed <= (IR[7:0] == 8'hf8); 1221 | // brk <= (IR[7:0] == 8'h00); 1222 | end 1223 | 1224 | always @(posedge clk) 1225 | if( RDY ) 1226 | cond_code <= IR[7:5]; 1227 | 1228 | always @* 1229 | case( cond_code ) 1230 | 3'b000: cond_true = ~N; 1231 | 3'b001: cond_true = N; 1232 | 3'b010: cond_true = ~V; 1233 | 3'b011: cond_true = V; 1234 | 3'b100: cond_true = ~C; 1235 | 3'b101: cond_true = C; 1236 | 3'b110: cond_true = ~Z; 1237 | 3'b111: cond_true = Z; 1238 | endcase 1239 | 1240 | 1241 | reg NMI_1 = 0; // delayed NMI signal 1242 | 1243 | always @(posedge clk) 1244 | NMI_1 <= NMI; 1245 | 1246 | always @(posedge clk ) 1247 | if( NMI_edge && state == BRK3 ) 1248 | NMI_edge <= 0; 1249 | else if( NMI & ~NMI_1 ) 1250 | NMI_edge <= 1; 1251 | 1252 | endmodule 1253 | -------------------------------------------------------------------------------- /simulation-isim/run_isim.sh: -------------------------------------------------------------------------------- 1 | : 2 | fuse \ 3 | -prj testbench.prj testbench && 4 | ./x.exe -gui -view sim1.wcfg 5 | -------------------------------------------------------------------------------- /simulation-isim/sim1.wcfg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | reset 15 | reset 16 | 17 | 18 | clk 19 | clk 20 | 21 | 22 | addrbus_w[31:0] 23 | addrbus_w[31:0] 24 | HEXRADIX 25 | 26 | 27 | DI[15:0] 28 | DI[15:0] 29 | HEXRADIX 30 | 31 | 32 | DO[15:0] 33 | DO[15:0] 34 | HEXRADIX 35 | 36 | 37 | rnw 38 | rnw 39 | 40 | 41 | ram_select_w 42 | ram_select_w 43 | 44 | 45 | databus_ram_w[15:0] 46 | databus_ram_w[15:0] 47 | HEXRADIX 48 | 49 | 50 | rom_select_w 51 | rom_select_w 52 | 53 | 54 | databus_rom_w[15:0] 55 | databus_rom_w[15:0] 56 | HEXRADIX 57 | 58 | 59 | uart_select_w 60 | uart_select_w 61 | 62 | 63 | databus_uart_w[15:0] 64 | databus_uart_w[15:0] 65 | HEXRADIX 66 | 67 | 68 | userled[7:0] 69 | userled[7:0] 70 | HEXRADIX 71 | 72 | 73 | AXYS[3:0,15:0] 74 | AXYS[3:0,15:0] 75 | HEXRADIX 76 | 77 | [3,15:0] 78 | AXYS[3,15:0] 79 | HEXRADIX 80 | 81 | 82 | [2,15:0] 83 | AXYS[2,15:0] 84 | HEXRADIX 85 | 86 | 87 | [1,15:0] 88 | AXYS[1,15:0] 89 | HEXRADIX 90 | 91 | 92 | [0,15:0] 93 | AXYS[0,15:0] 94 | HEXRADIX 95 | 96 | 97 | 98 | led_select_w 99 | led_select_w 100 | 101 | 102 | PC[31:0] 103 | PC[31:0] 104 | HEXRADIX 105 | 106 | 107 | -------------------------------------------------------------------------------- /simulation-isim/testbench.prj: -------------------------------------------------------------------------------- 1 | verilog work testbench.v 2 | verilog work ../build-xilinx/chip.v 3 | -------------------------------------------------------------------------------- /simulation-isim/testbench.v: -------------------------------------------------------------------------------- 1 | //************************************************************************** 2 | // testbench.v - top level module testbench for the GOP-based 65Org16 CPU 3 | // 4 | // COPYRIGHT 2011 Richard Evans 5 | // COPYRIGHT 2011 Ed Spittles 6 | // 7 | // This file is part of verilog-6502 project 8 | // 9 | // This library is free software; you can redistribute it and/or 10 | // modify it under the terms of the GNU Lesser General Public 11 | // License version 2.1 as published by the Free Software Foundation. 12 | // 13 | // This library is distributed in the hope that it will be useful, 14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | // Lesser General Public License for more details. 17 | // 18 | // You should have received a copy of the GNU Lesser General Public 19 | // License along with this library; if not, write to the Free Software 20 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21 | // 22 | // ============================================================================ 23 | `timescale 1ns / 1ns 24 | 25 | module testbench (); 26 | 27 | // this is a testbench sitting above the GOP design 28 | // so it only needs to act as the clock and the host 29 | // and perhaps the buttons and LEDs 30 | 31 | reg res_r, phi0_r; 32 | wire res_w = res_r; 33 | wire phi0_w = phi0_r; 34 | wire [7:0] userled; 35 | 36 | gop16 dut ( 37 | .res(res_w), 38 | .phi0(phi0_w), 39 | .SDA(SDA), 40 | .SCL(SCL), 41 | .userled(userled) 42 | ); 43 | 44 | initial 45 | begin 46 | res_r = 1'b0; 47 | phi0_r = 1'b0; 48 | @ ( negedge phi0_w ); 49 | @ ( negedge phi0_w ) 50 | res_r <= 1'b1; 51 | #100000 $display("Simulation time out"); 52 | $finish; 53 | end // initial begin 54 | 55 | always 56 | begin 57 | #252 phi0_r <= 1'b1; 58 | #252 phi0_r <= 1'b0; 59 | end 60 | 61 | endmodule 62 | -------------------------------------------------------------------------------- /system-rtl/gop16.v: -------------------------------------------------------------------------------- 1 | //************************************************************************** 2 | // gop16.v - system-on-chip 65Org16 CPU experiment 3 | // 4 | // COPYRIGHT 2011 Richard Evans 5 | // COPYRIGHT 2011 Ed Spittles 6 | // 7 | // This file is part of verilog-6502 project 8 | // 9 | // This library is free software; you can redistribute it and/or 10 | // modify it under the terms of the GNU Lesser General Public 11 | // License version 2.1 as published by the Free Software Foundation. 12 | // 13 | // This library is distributed in the hope that it will be useful, 14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | // Lesser General Public License for more details. 17 | // 18 | // You should have received a copy of the GNU Lesser General Public 19 | // License along with this library; if not, write to the Free Software 20 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21 | // 22 | // ============================================================================ 23 | // 24 | // 16-bit CPU on an OHO FPGA module 25 | // 24-pin DIL module 26 | // 6502-derived CPU 27 | // 28 | // I/O is limited to an i2c connection 29 | // and some diagnostic LEDs 30 | // also two push buttons are available 31 | // 32 | // limited to on-FPGA RAM at present (12 blocks of 2k by 9bits) 33 | 34 | module gop16 ( 35 | input res, // active low 36 | input phi0, 37 | inout SDA, 38 | input SCL, 39 | output [7:0] userled 40 | ); 41 | 42 | `define bytesize 16 43 | //`define bytesize 8 44 | `define datasize `bytesize 45 | `define addresssize (2*`bytesize) 46 | `define addresswidth `addresssize-1:0 47 | `define datawidth `datasize-1:0 48 | 49 | wire [`addresswidth] addrbus_w; 50 | reg [`datawidth] databus_r; 51 | wire [`datawidth] databus_from_cpu_w; 52 | wire [`datawidth] databus_ram_w; 53 | wire [`datawidth] databus_rom_w; 54 | wire [`datawidth] databus_uart_w; 55 | 56 | wire reset = ! res; 57 | wire clk; 58 | wire write; 59 | wire rnw = ! write; 60 | 61 | // if 50MHz clock in from crystal is too fast for this core 62 | // DCM #( 63 | // .CLKFX_MULTIPLY(3), // Can be any integer from 2 to 32 64 | // .CLKFX_DIVIDE(5), // Can be any integer from 1 to 32 65 | // .STARTUP_WAIT("TRUE"), // Delay configuration DONE until DCM LOCK, TRUE/FALSE 66 | // .CLK_FEEDBACK("NONE") // External closed loop? 67 | // ) _divider ( 68 | // .CLKFX(clk), // DCM CLK synthesis out (Mult/Div) 69 | // .CLKIN(phi0) // Clock input (from IBUFG, BUFG or DCM) 70 | // ); 71 | 72 | assign clk=phi0; 73 | 74 | // user LEDs address decode (placed at 0xfd00 or 0xfffd0000) 75 | wire led_select_w = (addrbus_w[`bytesize+7:`bytesize] == 8'hfd); 76 | 77 | // RAM address decode (covers lower half of memory map) 78 | wire ram_select_w = (addrbus_w[`addresssize-1] == 1'b0); 79 | 80 | // ROM address decode 81 | wire rom_select_w = (addrbus_w[`bytesize+7:`bytesize] == 8'hff); 82 | 83 | // UART address decode 84 | wire uart_select_w = (addrbus_w[`bytesize+7:`bytesize] == 8'hfe); 85 | 86 | // There's probably scope to simplify the pipelining arrangements here 87 | // but this has the merit of working in simulation 88 | 89 | // This core requires that the peripherals are registered 90 | // so we do them all on their own databus 91 | reg [`datawidth] databus_rr; 92 | always @(posedge clk) 93 | databus_rr <= databus_r; 94 | 95 | // The pipelined memory needs an output valid signal 96 | reg ram_valid_data_r; 97 | always @(posedge clk) 98 | ram_valid_data_r = rnw & ram_select_w; 99 | 100 | // The CPU reads the (registered) outputs of the peripherals, or the ram 101 | // (OR might be preferred to a mux) 102 | wire [`datawidth] databus_to_cpu; 103 | assign databus_to_cpu = (ram_valid_data_r) ? databus_ram_w : databus_rr; 104 | 105 | cpu _cpu ( 106 | .clk(clk), // positive edge (phi1) 107 | .reset(reset), // active high 108 | .AB(addrbus_w), 109 | .DI(databus_to_cpu), 110 | .DO(databus_from_cpu_w), 111 | .WE(write), 112 | .IRQ(1'b0), 113 | .NMI(1'b0), 114 | .RDY(1'b1) 115 | ); 116 | 117 | // block ram is registered (incorporates a pipeline stage) 118 | ram4k _ram0 ( 119 | .Clk(clk), 120 | .We(write & ram_select_w), 121 | .Waddr(addrbus_w[11:0]), 122 | .Raddr(addrbus_w[11:0]), 123 | .Din(databus_from_cpu_w), 124 | .Dout(databus_ram_w) 125 | ); 126 | 127 | // uart function: bidirectional, bytewide, asynchronous, in this case over i2c 128 | uart _uart( 129 | .SDA(SDA), 130 | .SCL(SCL), 131 | .clk(clk), 132 | .read(!write & uart_select_w), 133 | .write(write & uart_select_w), 134 | .address(addrbus_w[0]), 135 | .datain(databus_from_cpu_w), 136 | .dataout(databus_uart_w) 137 | ); 138 | 139 | tinybootrom _rom1 ( 140 | .address(addrbus_w[9:0]), 141 | .dataout(databus_rom_w) 142 | ); 143 | 144 | // diagnostic port - user LEDS 145 | reg [7:0] userled_r; 146 | always @(posedge clk) 147 | if (!rnw & led_select_w) 148 | userled_r <= databus_r[7:0]; 149 | assign userled = userled_r; 150 | 151 | // fpga normal practice: an onchip bus is the output of a wide mux 152 | // (wired-OR might be more efficient) 153 | always @(*) 154 | begin 155 | casex ( {write, rom_select_w} ) 156 | 2'b1x: databus_r = databus_from_cpu_w; 157 | 2'bx1: databus_r = databus_rom_w; 158 | default: databus_r = databus_uart_w; 159 | endcase 160 | end 161 | 162 | endmodule 163 | -------------------------------------------------------------------------------- /system-rtl/hexloader.as: -------------------------------------------------------------------------------- 1 | 2 | ;;************************************************************************** 3 | ;; 4 | ;; hexloader.as - boot ROM and support routines for system-on-chip 65Org16 CPU experiment 5 | ;; for use with i2c uart connected to 65Org16 in OHO GOP24 6 | ;; 7 | ;; load and run (variant) intel hex format as output by HXA assembler 8 | ;; see http://home.earthlink.net/~hxa/docs/hxa_demo.htm#l12 9 | ;; 10 | ;; COPYRIGHT 2001 Ross Archer (parts derived from http://www.6502.org/source/monitors/intelhex/intelhex.htm) 11 | ;; COPYRIGHT 2011 Ed Spittles 12 | ;; 13 | ;; This file is part of verilog-6502 project on github 14 | ;; 15 | ;; This library is free software; you can redistribute it and/or 16 | ;; modify it under the terms of the GNU Lesser General Public 17 | ;; License version 2.1 as published by the Free Software Foundation. 18 | ;; 19 | ;; This library is distributed in the hope that it will be useful, 20 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22 | ;; Lesser General Public License for more details. 23 | ;; 24 | ;; You should have received a copy of the GNU Lesser General Public 25 | ;; License along with this library; if not, write to the Free Software 26 | ;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 27 | ;; 28 | ;; ============================================================================ 29 | 30 | .LIST 31 | 32 | ;; build instructions: 33 | ;; 34 | ;; use Andrew Jacobs' experimental assembler http://www.obelisk.demon.co.uk/files/65016.zip 35 | ;; see http://forum.6502.org/viewtopic.php?p=15144#15144 36 | ;; 37 | ;; java -cp ./65016.jar org.x6502.x65016.As65016 hexloader.as 38 | ;; java -cp ./65016.jar org.x6502.x65016.Lk65016 -bss \$00010000-\$EFFFFFFF -code \$fffffd80-\$ffffFFFF -bin -output hexloader.bin hexloader.obj 39 | ;; 40 | 41 | ROMSTART = $fffffd80 42 | 43 | ; hardware interface 44 | ; 45 | UartS1=$FFFEFFF8 46 | UartR1=$FFFEFFF9 47 | UserLeds=$FFFD0000 48 | 49 | ; application binary interface 50 | ; 51 | OSRDCH = $FFFFFFE0 52 | OSWRCH = $FFFFFFEE 53 | 54 | ; memory allocations 55 | 56 | ; where the RAM program MUST have its first instruction 57 | ENTRY_POINT = $0200 58 | 59 | ; allocate all the storage in zero page, which is large so we can even place buffers there 60 | ; but note that the hexloader will place the application at $0200 61 | 62 | .ORG 0 63 | 64 | kBufferMask = $3f 65 | InputBuffer .SPACE kBufferMask+1 66 | InputPointer .SPACE 1 67 | OutputBuffer .SPACE kBufferMask+1 68 | OutputHeadPointer .SPACE 1 69 | OutputTailPointer .SPACE 1 70 | 71 | kDPL .SPACE 1 ; kernel temporary data pointer low 72 | kDPH .SPACE 1 73 | ktempx .SPACE 1 ; kernel temporary 74 | ktempy .SPACE 1 ; kernel temporary 75 | 76 | ; 77 | ; Note that Hex format for 65Org16 uses ';' not ':' as the start of record mark 78 | ; also note that some fields are now composed of 16-bit elements: 79 | ; previously: 80 | ; length offset type data checksum 81 | ; :/08/E008/00/08090A0B0C0D0E0F/xx 82 | ; now 83 | ; ;/10/E008/00/00080009000A000B000C000D000E000F/xx 84 | 85 | RECLEN .SPACE 1 ; record length in bytes 86 | START_LO .SPACE 1 87 | START_HI .SPACE 1 88 | RECTYPE .SPACE 1 89 | CHKSUM .SPACE 1 ; record checksum accumulator 90 | DLFAIL .SPACE 1 ; flag for download failure 91 | TEMP .SPACE 1 ; save hex value 92 | TMPHEX .SPACE 1 ; save another hex value 93 | 94 | ; hexloader rom entry point - cold reset vector 95 | 96 | .ORG ROMSTART 97 | 98 | sei ; disable interrupts 99 | cld ; binary mode arithmetic 100 | ldx #$1FF ; Set up the stack pointer 101 | txs ; (beware! aliased physical RAM!) 102 | 103 | LDA #0 104 | STA InputPointer 105 | STA OutputHeadPointer 106 | STA OutputTailPointer 107 | 108 | uartinit: 109 | LDA #3 110 | STA UartS1 111 | 112 | sta UserLeds 113 | 114 | ; Download Intel hex. The program you download MUST have its entry 115 | ; instruction (even if only a jump to somewhere else) at ENTRY_POINT. 116 | HEXDNLD lda #0 117 | sta START_HI ; store all programs in bank 0 (page 0) for now 118 | sta DLFAIL ; Start by assuming no D/L failure 119 | jsr kputstring 120 | .byte 13,10,13,10 121 | .byte "Send 65Org16 code in" 122 | .byte " variant Intel Hex format" 123 | .byte " at 19200,n,8,1 ->" 124 | .byte 13,10 125 | .byte 0 ; Null-terminate unless you prefer to crash. 126 | HDWRECS jsr kgetc ; Wait for start of record mark ';' 127 | cmp #';' 128 | bne HDWRECS ; not found yet 129 | ; Start of record marker has been found 130 | lda #0 131 | sta CHKSUM 132 | jsr GETHEX ; Get the record length 133 | sta RECLEN ; save it 134 | jsr GET4HX ; Get the 16-bit offset 135 | sta START_LO 136 | jsr GETHEX ; Get the record type 137 | sta RECTYPE ; & save it 138 | bne HDER1 ; end-of-record 139 | ldx RECLEN ; number of data bytes to write to memory 140 | ldy #0 ; start offset at 0 141 | HDLP1 jsr GET4HX ; Get the first/next/last data word 142 | sta (START_LO),y ; Save it to RAM 143 | iny ; update data pointer 144 | dex ; decrement character count 145 | dex ; ... twice 146 | bne HDLP1 147 | jsr GETHEX ; get the checksum 148 | lda CHKSUM 149 | bne HDDLF1 ; If failed, report it 150 | ; Another successful record has been processed 151 | lda #'#' ; Character indicating record OK = '#' 152 | 153 | ; jsr kputc ; write it out 154 | sta UartR1 ; jam it out (fire and forget) 155 | 156 | jmp HDWRECS ; get next record 157 | HDDLF1 lda #'F' ; Character indicating record failure = 'F' 158 | sta DLFAIL ; download failed if non-zero 159 | jsr kputc ; write it out 160 | jmp HDWRECS ; wait for next record start 161 | HDER1 cmp #1 ; Check for end-of-record type 162 | beq HDER2 163 | jsr kputstring ; Warn user of unknown record type 164 | .byte 13,10,13,10 165 | .byte "Unknown record type $" 166 | .byte 0 ; null-terminate unless you prefer to crash! 167 | lda RECTYPE ; Get it 168 | sta DLFAIL ; non-zero --> download has failed 169 | jsr kputhex ; print it 170 | lda #13 ; but we'll let it finish so as not to 171 | jsr kputc ; falsely start a new d/l from existing 172 | lda #10 ; file that may still be coming in for 173 | jsr kputc ; quite some time yet. 174 | jmp HDWRECS 175 | ; We've reached the end-of-record record 176 | HDER2 jsr GETHEX ; get the checksum 177 | lda CHKSUM ; Add previous checksum accumulator value 178 | beq HDER3 ; checksum = 0 means we're OK! 179 | jsr kputstring ; Warn user of bad checksum 180 | .byte 13,10,13,10 181 | .byte "Bad record checksum!",13,10 182 | .byte 0 ; Null-terminate or 6502 go bye-bye 183 | jmp HEXDNLD 184 | HDER3 lda DLFAIL 185 | beq HDEROK 186 | ;A download failure has occurred 187 | jsr kputstring 188 | .byte 13,10,13,10 189 | .byte "Download Failed",13,10 190 | .byte "Aborting!",13,10 191 | .byte 0 ; null-terminate every string yada yada. 192 | jmp HEXDNLD 193 | HDEROK jsr kputstring 194 | .byte 13,10,13,10 195 | .byte "Download Successful!",13,10 196 | .byte "Jumping to location $" 197 | .byte 0 ; by now, I figure you know what this is for. :) 198 | lda #HI(ENTRY_POINT) ; Print the entry point in hex 199 | jsr kputhex 200 | lda #LO(ENTRY_POINT) 201 | jsr kputhex 202 | jsr kputstring 203 | .byte 13,10 204 | .byte 0 ; stop lemming-like march of the program ctr. thru data 205 | jmp ENTRY_POINT ; jump to canonical entry point 206 | 207 | ; get four ascii chars, adding both octets into the checksum 208 | GET4HX jsr GETHEX 209 | asl a 210 | asl a 211 | asl a 212 | asl a 213 | asl a 214 | asl a 215 | asl a 216 | asl a 217 | sta TMPHEX 218 | jsr GETHEX 219 | ora TMPHEX 220 | rts 221 | 222 | ; get two ascii chars, add into the checksum 223 | GETHEX jsr kgetc 224 | jsr MKNIBL ; Convert to 0..F numeric 225 | asl a 226 | asl a 227 | asl a 228 | asl a ; This is the upper nibble 229 | and #$F0 230 | sta TEMP 231 | jsr kgetc 232 | jsr MKNIBL 233 | ora TEMP 234 | sta TEMP 235 | clc 236 | adc CHKSUM ; Add in the checksum 237 | and #$ff 238 | sta CHKSUM ; 239 | lda TEMP 240 | rts ; return with the nibble received 241 | 242 | ; Convert the ASCII nibble to numeric value from 0-F: 243 | MKNIBL cmp #'9'+1 ; See if it's 0-9 or 'A'..'F' (no lowercase yet) 244 | bcc MKNNH ; If we borrowed, we lost the carry so 0..9 245 | sbc #7+1 ; Subtract off extra 7 (sbc subtracts off one less) 246 | ; If we fall through, carry is set unlike direct entry at MKNNH 247 | MKNNH sbc #'0'-1 ; subtract off '0' (if carry clear coming in) 248 | and #$0F ; no upper nibble no matter what 249 | rts ; and return the nibble 250 | 251 | ;; kernel routines 252 | 253 | ; main loop for I/O handling 254 | ; we have no interrupts or operating system 255 | ; so all I/O is performed when the application is ready for input 256 | ; at which point it may opportunistically also send output 257 | 258 | ; deal with input as highest priority 259 | ; because we don't want to drop any incoming on the floor 260 | ; and we can afford to let outgoing traffic buffer up 261 | ; (we assume no flow control and no interrupts) 262 | 263 | kgetc: 264 | txa ; preserve X 265 | pha 266 | 267 | uartloop: 268 | LDA UartS1 269 | LSR A 270 | BCS dealWithIncoming 271 | LSR A ; any room for transmission? 272 | BCC uartloop 273 | 274 | ;; handle any pending buffered output 275 | okToSend: 276 | LDX OutputTailPointer 277 | CPX OutputHeadPointer 278 | BEQ uartloop 279 | LDA OutputBuffer,X 280 | STA UartR1 281 | INX 282 | TXA 283 | AND #kBufferMask 284 | STA OutputTailPointer 285 | JMP uartloop 286 | 287 | dealWithIncoming: 288 | pla ; restore X - this is the only exit path from kgetc 289 | tax 290 | 291 | LDA UartR1 292 | STA UserLeds ; incoming data is shown on LEDs for debug 293 | 294 | RTS ; the incoming character is returned to the application 295 | 296 | ;Put the string following in-line until a NULL out to the console 297 | kputstring: 298 | 299 | sty ktempy ; preserve Y 300 | 301 | pla ; Get the low part of "return" address (data start address) 302 | sta kDPL 303 | pla 304 | sta kDPH ; Get the high part of "return" address 305 | ; (data start address) 306 | ; Note: actually we're pointing one short 307 | PSINB ldy #1 308 | lda (kDPL),y ; Get the next string character 309 | inc kDPL ; update the pointer 310 | bne PSICHO ; if not, we're pointing to next character 311 | inc kDPH ; account for page crossing 312 | PSICHO ora #0 ; Set flags according to contents of Accumulator 313 | beq PSIX1 ; don't print the final NULL 314 | jsr kputc ; write it out 315 | jmp PSINB ; back around 316 | PSIX1 inc kDPL ; 317 | bne PSIX2 ; 318 | inc kDPH ; account for page crossing 319 | PSIX2: 320 | ldy ktempy ; restore Y 321 | 322 | jmp (kDPL) ; return to byte following final NULL 323 | 324 | ; Put byte in A to stdout as 2 hex chars 325 | kputhex: 326 | pha ; 327 | lsr a 328 | lsr a 329 | lsr a 330 | lsr a 331 | jsr PRNIBL 332 | pla 333 | PRNIBL and #$0F ; strip off the low nibble 334 | cmp #$0A 335 | bcc NOTHEX ; if it's 0-9, add '0' else also add 7 336 | adc #6 ; Add 7 (6+carry=1), result will be carry clear 337 | NOTHEX adc #'0' ; If carry clear, we're 0-9 338 | 339 | ;; falling through 340 | 341 | ; kernel write to stdout, single 8-bit character 342 | kputc: 343 | pha 344 | kputcblocked: 345 | LDA UartS1 346 | LSR A 347 | LSR A ; any room for transmission? 348 | BCC kputcblocked 349 | pla 350 | sta UartR1 351 | rts 352 | 353 | kputcbuffered: 354 | ; for use with slow output peripherals 355 | ; writes to a circular buffer 356 | ; no overflow check 357 | ; buffer is consumed elsewhere 358 | 359 | stx ktempx ; preserve X 360 | 361 | LDX OutputHeadPointer 362 | STA OutputBuffer,X 363 | ; STA UserLeds ; too fast to see, but good for simulation 364 | INX 365 | TXA 366 | AND #kBufferMask 367 | STA OutputHeadPointer 368 | 369 | ldx ktempx ; restore X 370 | RTS 371 | 372 | ; we're not ready for interrupts yet 373 | NMIHANDLE 374 | IRQHANDLE 375 | RTI 376 | 377 | .ORG OSRDCH 378 | jmp kgetc 379 | 380 | .ORG OSWRCH 381 | jmp kputc 382 | 383 | .ORG $FFFFFFFA 384 | NMIENT .word NMIHANDLE 385 | RSTENT .word ROMSTART 386 | IRQENT .word IRQHANDLE 387 | .end ; finally. das Ende. 388 | -------------------------------------------------------------------------------- /system-rtl/i2cslave.v.missing: -------------------------------------------------------------------------------- 1 | // stub module for i2cslave 2 | // fetch original from http://www.fpga4fun.com/I2C.html 3 | // specifically http://www.fpga4fun.com/files/I2Cslave1.zip 4 | // 5 | // and apply patch i2cslave.v.patch 6 | // 7 | module i2cslave(SDA, SCL, IOout, IOin); 8 | endmodule 9 | -------------------------------------------------------------------------------- /system-rtl/i2cslave.v.patch: -------------------------------------------------------------------------------- 1 | 4a5 2 | > // modified 2011 Ed Spittles added IOin port 3 | 11c12 4 | < module I2CslaveWith8bitsIO(SDA, SCL, IOout); 5 | --- 6 | > module i2cslave(SDA, SCL, IOout, IOin, serialTxDataAck, serialRxDataAck); 7 | 14a16,18 8 | > input [7:0] IOin; 9 | > output serialTxDataAck; 10 | > output serialRxDataAck; 11 | 80c84,88 12 | < if(adr_phase & bitcnt==0) op_read <= SDAr; 13 | --- 14 | > if(adr_phase & bitcnt==0) begin 15 | > op_read <= SDAr; 16 | > if(SDAr) mem <= IOin; // memory write (from parallel) 17 | > end; 18 | > 19 | 83c91 20 | < if(adr_match & bit_DATA & data_phase & op_write) mem[bitcnt] <= SDAr; // memory write 21 | --- 22 | > if(adr_match & bit_DATA & data_phase & op_write) mem[bitcnt] <= SDAr; // memory write (from serial) 23 | 92a101,104 24 | > // signal successful operations to our parallel side (true for one bit-time) 25 | > assign serialTxDataAck = adr_match & data_phase & op_read & got_ACK; 26 | > assign serialRxDataAck = adr_match & data_phase & op_write & got_ACK; 27 | > 28 | -------------------------------------------------------------------------------- /system-rtl/ram4k.v: -------------------------------------------------------------------------------- 1 | 2 | // usually we want this RAM module to be synthesised to a xilinx block ram 3 | // so take care to match the block ram capabilities 4 | 5 | module ram4k ( 6 | input Clk, 7 | input We, 8 | input [11:0] Waddr, 9 | input [11:0] Raddr, 10 | input [15:0] Din, 11 | output [15:0] Dout 12 | ); 13 | 14 | reg [15:0] mem[0:4095]; 15 | reg [11:0] raddr_reg; 16 | 17 | // Data, and the read address, are captured on the rising edge of the clock 18 | always @ (posedge Clk) 19 | begin 20 | raddr_reg <= Raddr; 21 | if (We) begin 22 | mem[Waddr] <= Din; 23 | end 24 | end 25 | 26 | assign Dout = mem[raddr_reg]; // read (from registered address) 27 | 28 | endmodule 29 | -------------------------------------------------------------------------------- /system-rtl/tinybootrom.as: -------------------------------------------------------------------------------- 1 | ;; for minimal proof-of-life with tube+T65 in GODIL40 2 | ;; 3 | ;; PATH=$PATH:/home/ed/cc65/v2.13.2/bin make -f ../../boot816/Makefile -B tinybootrom.bin BASE=0xFFE0 4 | ;; ca65 -l tinybootrom.as -D BASE=0xFFE4 -D SRECORD_D=0 5 | ;; cl65 tinybootrom.o --target none --start-addr 0xFFE4 -o tinybootrom.bin 6 | ;; xxd -c 1 tinybootrom.bin 7 | ;; 8 | 9 | .ORG BASE ; place the bootstrap so the reset vector lands at FFFC 10 | 11 | .DEFINE TubeS1 $FEF8 12 | .DEFINE TubeR1 $FEF9 13 | 14 | .DEFINE offset $FC ;; (256 - (writebyte - message)) 15 | 16 | bootstrap: 17 | LDX #offset 18 | TXS ;; initialise stack pointer for bc6502v2 19 | nextchar: 20 | LDA message-offset,X 21 | 22 | writebyte: ;; inlined write byte subroutine - no RAM required 23 | STA TubeR1 ;; trying write-before-read, to get some sign of life 24 | BIT TubeS1 25 | NOP 26 | BVC writebyte 27 | 28 | INX 29 | BNE nextchar 30 | done: 31 | BEQ done 32 | 33 | message: 34 | .byte "T65",0 35 | 36 | ; this is arranged to be placed in the reset vector, by careful initial .Org 37 | .word bootstrap 38 | -------------------------------------------------------------------------------- /system-rtl/tinybootrom.v: -------------------------------------------------------------------------------- 1 | // 2 | // tinybootrom: bootrom to load applications over i2c 3 | // for source, see hexloader.as 4 | // 5 | // convert from binary using something like 6 | // xxd -c2 -a hexloader.bin |\ 7 | // awk '{printf " 10'\''h%03x: dataout_d = 16'\''h%s;\n", 0x180+NR-1,$2}' 8 | 9 | // using global clock and output enable uses no extra resources 10 | // over a combinatorial ROM 11 | // 12 | module tinybootrom(address,dataout); 13 | input[9:0] address; 14 | output[15:0] dataout; 15 | 16 | // following the idiom in the xilinx guide 17 | reg [15:0] dataout_d; 18 | 19 | assign dataout = dataout_d ; 20 | 21 | always @ (*) 22 | begin 23 | case ( address ) 24 | 10'h180: dataout_d = 16'h0078; 25 | 10'h181: dataout_d = 16'h00d8; 26 | 10'h182: dataout_d = 16'h00a2; 27 | 10'h183: dataout_d = 16'h01ff; 28 | 10'h184: dataout_d = 16'h009a; 29 | 10'h185: dataout_d = 16'h00a9; 30 | 10'h186: dataout_d = 16'h0000; 31 | 10'h187: dataout_d = 16'h0085; 32 | 10'h188: dataout_d = 16'h0040; 33 | 10'h189: dataout_d = 16'h0085; 34 | 10'h18a: dataout_d = 16'h0081; 35 | 10'h18b: dataout_d = 16'h0085; 36 | 10'h18c: dataout_d = 16'h0082; 37 | 10'h18d: dataout_d = 16'h00a9; 38 | 10'h18e: dataout_d = 16'h0003; 39 | 10'h18f: dataout_d = 16'h008d; 40 | 10'h190: dataout_d = 16'hfff8; 41 | 10'h191: dataout_d = 16'hfffe; 42 | 10'h192: dataout_d = 16'h008d; 43 | 10'h193: dataout_d = 16'h0000; 44 | 10'h194: dataout_d = 16'hfffd; 45 | 10'h195: dataout_d = 16'h00a9; 46 | 10'h196: dataout_d = 16'h0000; 47 | 10'h197: dataout_d = 16'h0085; 48 | 10'h198: dataout_d = 16'h0089; 49 | 10'h199: dataout_d = 16'h0085; 50 | 10'h19a: dataout_d = 16'h008c; 51 | 10'h19b: dataout_d = 16'h0020; 52 | 10'h19c: dataout_d = 16'hff5d; 53 | 10'h19d: dataout_d = 16'hffff; 54 | 10'h19e: dataout_d = 16'h000d; 55 | 10'h19f: dataout_d = 16'h000a; 56 | 10'h1a0: dataout_d = 16'h000d; 57 | 10'h1a1: dataout_d = 16'h000a; 58 | 10'h1a2: dataout_d = 16'h0053; 59 | 10'h1a3: dataout_d = 16'h0065; 60 | 10'h1a4: dataout_d = 16'h006e; 61 | 10'h1a5: dataout_d = 16'h0064; 62 | 10'h1a6: dataout_d = 16'h0020; 63 | 10'h1a7: dataout_d = 16'h0036; 64 | 10'h1a8: dataout_d = 16'h0035; 65 | 10'h1a9: dataout_d = 16'h004f; 66 | 10'h1aa: dataout_d = 16'h0072; 67 | 10'h1ab: dataout_d = 16'h0067; 68 | 10'h1ac: dataout_d = 16'h0031; 69 | 10'h1ad: dataout_d = 16'h0036; 70 | 10'h1ae: dataout_d = 16'h0020; 71 | 10'h1af: dataout_d = 16'h0063; 72 | 10'h1b0: dataout_d = 16'h006f; 73 | 10'h1b1: dataout_d = 16'h0064; 74 | 10'h1b2: dataout_d = 16'h0065; 75 | 10'h1b3: dataout_d = 16'h0020; 76 | 10'h1b4: dataout_d = 16'h0069; 77 | 10'h1b5: dataout_d = 16'h006e; 78 | 10'h1b6: dataout_d = 16'h0020; 79 | 10'h1b7: dataout_d = 16'h0076; 80 | 10'h1b8: dataout_d = 16'h0061; 81 | 10'h1b9: dataout_d = 16'h0072; 82 | 10'h1ba: dataout_d = 16'h0069; 83 | 10'h1bb: dataout_d = 16'h0061; 84 | 10'h1bc: dataout_d = 16'h006e; 85 | 10'h1bd: dataout_d = 16'h0074; 86 | 10'h1be: dataout_d = 16'h0020; 87 | 10'h1bf: dataout_d = 16'h0049; 88 | 10'h1c0: dataout_d = 16'h006e; 89 | 10'h1c1: dataout_d = 16'h0074; 90 | 10'h1c2: dataout_d = 16'h0065; 91 | 10'h1c3: dataout_d = 16'h006c; 92 | 10'h1c4: dataout_d = 16'h0020; 93 | 10'h1c5: dataout_d = 16'h0048; 94 | 10'h1c6: dataout_d = 16'h0065; 95 | 10'h1c7: dataout_d = 16'h0078; 96 | 10'h1c8: dataout_d = 16'h0020; 97 | 10'h1c9: dataout_d = 16'h0066; 98 | 10'h1ca: dataout_d = 16'h006f; 99 | 10'h1cb: dataout_d = 16'h0072; 100 | 10'h1cc: dataout_d = 16'h006d; 101 | 10'h1cd: dataout_d = 16'h0061; 102 | 10'h1ce: dataout_d = 16'h0074; 103 | 10'h1cf: dataout_d = 16'h0020; 104 | 10'h1d0: dataout_d = 16'h0061; 105 | 10'h1d1: dataout_d = 16'h0074; 106 | 10'h1d2: dataout_d = 16'h0020; 107 | 10'h1d3: dataout_d = 16'h0031; 108 | 10'h1d4: dataout_d = 16'h0039; 109 | 10'h1d5: dataout_d = 16'h0032; 110 | 10'h1d6: dataout_d = 16'h0030; 111 | 10'h1d7: dataout_d = 16'h0030; 112 | 10'h1d8: dataout_d = 16'h002c; 113 | 10'h1d9: dataout_d = 16'h006e; 114 | 10'h1da: dataout_d = 16'h002c; 115 | 10'h1db: dataout_d = 16'h0038; 116 | 10'h1dc: dataout_d = 16'h002c; 117 | 10'h1dd: dataout_d = 16'h0031; 118 | 10'h1de: dataout_d = 16'h0020; 119 | 10'h1df: dataout_d = 16'h002d; 120 | 10'h1e0: dataout_d = 16'h003e; 121 | 10'h1e1: dataout_d = 16'h000d; 122 | 10'h1e2: dataout_d = 16'h000a; 123 | 10'h1e3: dataout_d = 16'h0000; 124 | 10'h1e4: dataout_d = 16'h0020; 125 | 10'h1e5: dataout_d = 16'hff35; 126 | 10'h1e6: dataout_d = 16'hffff; 127 | 10'h1e7: dataout_d = 16'h00c9; 128 | 10'h1e8: dataout_d = 16'h003b; 129 | 10'h1e9: dataout_d = 16'h00d0; 130 | 10'h1ea: dataout_d = 16'hfff9; 131 | 10'h1eb: dataout_d = 16'h00a9; 132 | 10'h1ec: dataout_d = 16'h0000; 133 | 10'h1ed: dataout_d = 16'h0085; 134 | 10'h1ee: dataout_d = 16'h008b; 135 | 10'h1ef: dataout_d = 16'h0020; 136 | 10'h1f0: dataout_d = 16'hff08; 137 | 10'h1f1: dataout_d = 16'hffff; 138 | 10'h1f2: dataout_d = 16'h0085; 139 | 10'h1f3: dataout_d = 16'h0087; 140 | 10'h1f4: dataout_d = 16'h0020; 141 | 10'h1f5: dataout_d = 16'hfef5; 142 | 10'h1f6: dataout_d = 16'hffff; 143 | 10'h1f7: dataout_d = 16'h0085; 144 | 10'h1f8: dataout_d = 16'h0088; 145 | 10'h1f9: dataout_d = 16'h0020; 146 | 10'h1fa: dataout_d = 16'hff08; 147 | 10'h1fb: dataout_d = 16'hffff; 148 | 10'h1fc: dataout_d = 16'h0085; 149 | 10'h1fd: dataout_d = 16'h008a; 150 | 10'h1fe: dataout_d = 16'h00d0; 151 | 10'h1ff: dataout_d = 16'h0027; 152 | 10'h200: dataout_d = 16'h00a6; 153 | 10'h201: dataout_d = 16'h0087; 154 | 10'h202: dataout_d = 16'h00a0; 155 | 10'h203: dataout_d = 16'h0000; 156 | 10'h204: dataout_d = 16'h0020; 157 | 10'h205: dataout_d = 16'hfef5; 158 | 10'h206: dataout_d = 16'hffff; 159 | 10'h207: dataout_d = 16'h0091; 160 | 10'h208: dataout_d = 16'h0088; 161 | 10'h209: dataout_d = 16'h00c8; 162 | 10'h20a: dataout_d = 16'h00ca; 163 | 10'h20b: dataout_d = 16'h00ca; 164 | 10'h20c: dataout_d = 16'h00d0; 165 | 10'h20d: dataout_d = 16'hfff6; 166 | 10'h20e: dataout_d = 16'h0020; 167 | 10'h20f: dataout_d = 16'hff08; 168 | 10'h210: dataout_d = 16'hffff; 169 | 10'h211: dataout_d = 16'h00a5; 170 | 10'h212: dataout_d = 16'h008b; 171 | 10'h213: dataout_d = 16'h00d0; 172 | 10'h214: dataout_d = 16'h0008; 173 | 10'h215: dataout_d = 16'h00a9; 174 | 10'h216: dataout_d = 16'h0023; 175 | 10'h217: dataout_d = 16'h008d; 176 | 10'h218: dataout_d = 16'hfff9; 177 | 10'h219: dataout_d = 16'hfffe; 178 | 10'h21a: dataout_d = 16'h004c; 179 | 10'h21b: dataout_d = 16'hfde4; 180 | 10'h21c: dataout_d = 16'hffff; 181 | 10'h21d: dataout_d = 16'h00a9; 182 | 10'h21e: dataout_d = 16'h0046; 183 | 10'h21f: dataout_d = 16'h0085; 184 | 10'h220: dataout_d = 16'h008c; 185 | 10'h221: dataout_d = 16'h0020; 186 | 10'h222: dataout_d = 16'hff97; 187 | 10'h223: dataout_d = 16'hffff; 188 | 10'h224: dataout_d = 16'h004c; 189 | 10'h225: dataout_d = 16'hfde4; 190 | 10'h226: dataout_d = 16'hffff; 191 | 10'h227: dataout_d = 16'h00c9; 192 | 10'h228: dataout_d = 16'h0001; 193 | 10'h229: dataout_d = 16'h00f0; 194 | 10'h22a: dataout_d = 16'h0031; 195 | 10'h22b: dataout_d = 16'h0020; 196 | 10'h22c: dataout_d = 16'hff5d; 197 | 10'h22d: dataout_d = 16'hffff; 198 | 10'h22e: dataout_d = 16'h000d; 199 | 10'h22f: dataout_d = 16'h000a; 200 | 10'h230: dataout_d = 16'h000d; 201 | 10'h231: dataout_d = 16'h000a; 202 | 10'h232: dataout_d = 16'h0055; 203 | 10'h233: dataout_d = 16'h006e; 204 | 10'h234: dataout_d = 16'h006b; 205 | 10'h235: dataout_d = 16'h006e; 206 | 10'h236: dataout_d = 16'h006f; 207 | 10'h237: dataout_d = 16'h0077; 208 | 10'h238: dataout_d = 16'h006e; 209 | 10'h239: dataout_d = 16'h0020; 210 | 10'h23a: dataout_d = 16'h0072; 211 | 10'h23b: dataout_d = 16'h0065; 212 | 10'h23c: dataout_d = 16'h0063; 213 | 10'h23d: dataout_d = 16'h006f; 214 | 10'h23e: dataout_d = 16'h0072; 215 | 10'h23f: dataout_d = 16'h0064; 216 | 10'h240: dataout_d = 16'h0020; 217 | 10'h241: dataout_d = 16'h0074; 218 | 10'h242: dataout_d = 16'h0079; 219 | 10'h243: dataout_d = 16'h0070; 220 | 10'h244: dataout_d = 16'h0065; 221 | 10'h245: dataout_d = 16'h0020; 222 | 10'h246: dataout_d = 16'h0024; 223 | 10'h247: dataout_d = 16'h0000; 224 | 10'h248: dataout_d = 16'h00a5; 225 | 10'h249: dataout_d = 16'h008a; 226 | 10'h24a: dataout_d = 16'h0085; 227 | 10'h24b: dataout_d = 16'h008c; 228 | 10'h24c: dataout_d = 16'h0020; 229 | 10'h24d: dataout_d = 16'hff84; 230 | 10'h24e: dataout_d = 16'hffff; 231 | 10'h24f: dataout_d = 16'h00a9; 232 | 10'h250: dataout_d = 16'h000d; 233 | 10'h251: dataout_d = 16'h0020; 234 | 10'h252: dataout_d = 16'hff97; 235 | 10'h253: dataout_d = 16'hffff; 236 | 10'h254: dataout_d = 16'h00a9; 237 | 10'h255: dataout_d = 16'h000a; 238 | 10'h256: dataout_d = 16'h0020; 239 | 10'h257: dataout_d = 16'hff97; 240 | 10'h258: dataout_d = 16'hffff; 241 | 10'h259: dataout_d = 16'h004c; 242 | 10'h25a: dataout_d = 16'hfde4; 243 | 10'h25b: dataout_d = 16'hffff; 244 | 10'h25c: dataout_d = 16'h0020; 245 | 10'h25d: dataout_d = 16'hff08; 246 | 10'h25e: dataout_d = 16'hffff; 247 | 10'h25f: dataout_d = 16'h00a5; 248 | 10'h260: dataout_d = 16'h008b; 249 | 10'h261: dataout_d = 16'h00f0; 250 | 10'h262: dataout_d = 16'h0021; 251 | 10'h263: dataout_d = 16'h0020; 252 | 10'h264: dataout_d = 16'hff5d; 253 | 10'h265: dataout_d = 16'hffff; 254 | 10'h266: dataout_d = 16'h000d; 255 | 10'h267: dataout_d = 16'h000a; 256 | 10'h268: dataout_d = 16'h000d; 257 | 10'h269: dataout_d = 16'h000a; 258 | 10'h26a: dataout_d = 16'h0042; 259 | 10'h26b: dataout_d = 16'h0061; 260 | 10'h26c: dataout_d = 16'h0064; 261 | 10'h26d: dataout_d = 16'h0020; 262 | 10'h26e: dataout_d = 16'h0072; 263 | 10'h26f: dataout_d = 16'h0065; 264 | 10'h270: dataout_d = 16'h0063; 265 | 10'h271: dataout_d = 16'h006f; 266 | 10'h272: dataout_d = 16'h0072; 267 | 10'h273: dataout_d = 16'h0064; 268 | 10'h274: dataout_d = 16'h0020; 269 | 10'h275: dataout_d = 16'h0063; 270 | 10'h276: dataout_d = 16'h0068; 271 | 10'h277: dataout_d = 16'h0065; 272 | 10'h278: dataout_d = 16'h0063; 273 | 10'h279: dataout_d = 16'h006b; 274 | 10'h27a: dataout_d = 16'h0073; 275 | 10'h27b: dataout_d = 16'h0075; 276 | 10'h27c: dataout_d = 16'h006d; 277 | 10'h27d: dataout_d = 16'h0021; 278 | 10'h27e: dataout_d = 16'h000d; 279 | 10'h27f: dataout_d = 16'h000a; 280 | 10'h280: dataout_d = 16'h0000; 281 | 10'h281: dataout_d = 16'h004c; 282 | 10'h282: dataout_d = 16'hfd95; 283 | 10'h283: dataout_d = 16'hffff; 284 | 10'h284: dataout_d = 16'h00a5; 285 | 10'h285: dataout_d = 16'h008c; 286 | 10'h286: dataout_d = 16'h00f0; 287 | 10'h287: dataout_d = 16'h0027; 288 | 10'h288: dataout_d = 16'h0020; 289 | 10'h289: dataout_d = 16'hff5d; 290 | 10'h28a: dataout_d = 16'hffff; 291 | 10'h28b: dataout_d = 16'h000d; 292 | 10'h28c: dataout_d = 16'h000a; 293 | 10'h28d: dataout_d = 16'h000d; 294 | 10'h28e: dataout_d = 16'h000a; 295 | 10'h28f: dataout_d = 16'h0044; 296 | 10'h290: dataout_d = 16'h006f; 297 | 10'h291: dataout_d = 16'h0077; 298 | 10'h292: dataout_d = 16'h006e; 299 | 10'h293: dataout_d = 16'h006c; 300 | 10'h294: dataout_d = 16'h006f; 301 | 10'h295: dataout_d = 16'h0061; 302 | 10'h296: dataout_d = 16'h0064; 303 | 10'h297: dataout_d = 16'h0020; 304 | 10'h298: dataout_d = 16'h0046; 305 | 10'h299: dataout_d = 16'h0061; 306 | 10'h29a: dataout_d = 16'h0069; 307 | 10'h29b: dataout_d = 16'h006c; 308 | 10'h29c: dataout_d = 16'h0065; 309 | 10'h29d: dataout_d = 16'h0064; 310 | 10'h29e: dataout_d = 16'h000d; 311 | 10'h29f: dataout_d = 16'h000a; 312 | 10'h2a0: dataout_d = 16'h0041; 313 | 10'h2a1: dataout_d = 16'h0062; 314 | 10'h2a2: dataout_d = 16'h006f; 315 | 10'h2a3: dataout_d = 16'h0072; 316 | 10'h2a4: dataout_d = 16'h0074; 317 | 10'h2a5: dataout_d = 16'h0069; 318 | 10'h2a6: dataout_d = 16'h006e; 319 | 10'h2a7: dataout_d = 16'h0067; 320 | 10'h2a8: dataout_d = 16'h0021; 321 | 10'h2a9: dataout_d = 16'h000d; 322 | 10'h2aa: dataout_d = 16'h000a; 323 | 10'h2ab: dataout_d = 16'h0000; 324 | 10'h2ac: dataout_d = 16'h004c; 325 | 10'h2ad: dataout_d = 16'hfd95; 326 | 10'h2ae: dataout_d = 16'hffff; 327 | 10'h2af: dataout_d = 16'h0020; 328 | 10'h2b0: dataout_d = 16'hff5d; 329 | 10'h2b1: dataout_d = 16'hffff; 330 | 10'h2b2: dataout_d = 16'h000d; 331 | 10'h2b3: dataout_d = 16'h000a; 332 | 10'h2b4: dataout_d = 16'h000d; 333 | 10'h2b5: dataout_d = 16'h000a; 334 | 10'h2b6: dataout_d = 16'h0044; 335 | 10'h2b7: dataout_d = 16'h006f; 336 | 10'h2b8: dataout_d = 16'h0077; 337 | 10'h2b9: dataout_d = 16'h006e; 338 | 10'h2ba: dataout_d = 16'h006c; 339 | 10'h2bb: dataout_d = 16'h006f; 340 | 10'h2bc: dataout_d = 16'h0061; 341 | 10'h2bd: dataout_d = 16'h0064; 342 | 10'h2be: dataout_d = 16'h0020; 343 | 10'h2bf: dataout_d = 16'h0053; 344 | 10'h2c0: dataout_d = 16'h0075; 345 | 10'h2c1: dataout_d = 16'h0063; 346 | 10'h2c2: dataout_d = 16'h0063; 347 | 10'h2c3: dataout_d = 16'h0065; 348 | 10'h2c4: dataout_d = 16'h0073; 349 | 10'h2c5: dataout_d = 16'h0073; 350 | 10'h2c6: dataout_d = 16'h0066; 351 | 10'h2c7: dataout_d = 16'h0075; 352 | 10'h2c8: dataout_d = 16'h006c; 353 | 10'h2c9: dataout_d = 16'h0021; 354 | 10'h2ca: dataout_d = 16'h000d; 355 | 10'h2cb: dataout_d = 16'h000a; 356 | 10'h2cc: dataout_d = 16'h004a; 357 | 10'h2cd: dataout_d = 16'h0075; 358 | 10'h2ce: dataout_d = 16'h006d; 359 | 10'h2cf: dataout_d = 16'h0070; 360 | 10'h2d0: dataout_d = 16'h0069; 361 | 10'h2d1: dataout_d = 16'h006e; 362 | 10'h2d2: dataout_d = 16'h0067; 363 | 10'h2d3: dataout_d = 16'h0020; 364 | 10'h2d4: dataout_d = 16'h0074; 365 | 10'h2d5: dataout_d = 16'h006f; 366 | 10'h2d6: dataout_d = 16'h0020; 367 | 10'h2d7: dataout_d = 16'h006c; 368 | 10'h2d8: dataout_d = 16'h006f; 369 | 10'h2d9: dataout_d = 16'h0063; 370 | 10'h2da: dataout_d = 16'h0061; 371 | 10'h2db: dataout_d = 16'h0074; 372 | 10'h2dc: dataout_d = 16'h0069; 373 | 10'h2dd: dataout_d = 16'h006f; 374 | 10'h2de: dataout_d = 16'h006e; 375 | 10'h2df: dataout_d = 16'h0020; 376 | 10'h2e0: dataout_d = 16'h0024; 377 | 10'h2e1: dataout_d = 16'h0000; 378 | 10'h2e2: dataout_d = 16'h00a9; 379 | 10'h2e3: dataout_d = 16'h0002; 380 | 10'h2e4: dataout_d = 16'h0020; 381 | 10'h2e5: dataout_d = 16'hff84; 382 | 10'h2e6: dataout_d = 16'hffff; 383 | 10'h2e7: dataout_d = 16'h00a9; 384 | 10'h2e8: dataout_d = 16'h0000; 385 | 10'h2e9: dataout_d = 16'h0020; 386 | 10'h2ea: dataout_d = 16'hff84; 387 | 10'h2eb: dataout_d = 16'hffff; 388 | 10'h2ec: dataout_d = 16'h0020; 389 | 10'h2ed: dataout_d = 16'hff5d; 390 | 10'h2ee: dataout_d = 16'hffff; 391 | 10'h2ef: dataout_d = 16'h000d; 392 | 10'h2f0: dataout_d = 16'h000a; 393 | 10'h2f1: dataout_d = 16'h0000; 394 | 10'h2f2: dataout_d = 16'h004c; 395 | 10'h2f3: dataout_d = 16'h0200; 396 | 10'h2f4: dataout_d = 16'h0000; 397 | 10'h2f5: dataout_d = 16'h0020; 398 | 10'h2f6: dataout_d = 16'hff08; 399 | 10'h2f7: dataout_d = 16'hffff; 400 | 10'h2f8: dataout_d = 16'h000a; 401 | 10'h2f9: dataout_d = 16'h000a; 402 | 10'h2fa: dataout_d = 16'h000a; 403 | 10'h2fb: dataout_d = 16'h000a; 404 | 10'h2fc: dataout_d = 16'h000a; 405 | 10'h2fd: dataout_d = 16'h000a; 406 | 10'h2fe: dataout_d = 16'h000a; 407 | 10'h2ff: dataout_d = 16'h000a; 408 | 10'h300: dataout_d = 16'h0085; 409 | 10'h301: dataout_d = 16'h008e; 410 | 10'h302: dataout_d = 16'h0020; 411 | 10'h303: dataout_d = 16'hff08; 412 | 10'h304: dataout_d = 16'hffff; 413 | 10'h305: dataout_d = 16'h0005; 414 | 10'h306: dataout_d = 16'h008e; 415 | 10'h307: dataout_d = 16'h0060; 416 | 10'h308: dataout_d = 16'h0020; 417 | 10'h309: dataout_d = 16'hff35; 418 | 10'h30a: dataout_d = 16'hffff; 419 | 10'h30b: dataout_d = 16'h0020; 420 | 10'h30c: dataout_d = 16'hff2a; 421 | 10'h30d: dataout_d = 16'hffff; 422 | 10'h30e: dataout_d = 16'h000a; 423 | 10'h30f: dataout_d = 16'h000a; 424 | 10'h310: dataout_d = 16'h000a; 425 | 10'h311: dataout_d = 16'h000a; 426 | 10'h312: dataout_d = 16'h0029; 427 | 10'h313: dataout_d = 16'h00f0; 428 | 10'h314: dataout_d = 16'h0085; 429 | 10'h315: dataout_d = 16'h008d; 430 | 10'h316: dataout_d = 16'h0020; 431 | 10'h317: dataout_d = 16'hff35; 432 | 10'h318: dataout_d = 16'hffff; 433 | 10'h319: dataout_d = 16'h0020; 434 | 10'h31a: dataout_d = 16'hff2a; 435 | 10'h31b: dataout_d = 16'hffff; 436 | 10'h31c: dataout_d = 16'h0005; 437 | 10'h31d: dataout_d = 16'h008d; 438 | 10'h31e: dataout_d = 16'h0085; 439 | 10'h31f: dataout_d = 16'h008d; 440 | 10'h320: dataout_d = 16'h0018; 441 | 10'h321: dataout_d = 16'h0065; 442 | 10'h322: dataout_d = 16'h008b; 443 | 10'h323: dataout_d = 16'h0029; 444 | 10'h324: dataout_d = 16'h00ff; 445 | 10'h325: dataout_d = 16'h0085; 446 | 10'h326: dataout_d = 16'h008b; 447 | 10'h327: dataout_d = 16'h00a5; 448 | 10'h328: dataout_d = 16'h008d; 449 | 10'h329: dataout_d = 16'h0060; 450 | 10'h32a: dataout_d = 16'h00c9; 451 | 10'h32b: dataout_d = 16'h003a; 452 | 10'h32c: dataout_d = 16'h0090; 453 | 10'h32d: dataout_d = 16'h0002; 454 | 10'h32e: dataout_d = 16'h00e9; 455 | 10'h32f: dataout_d = 16'h0008; 456 | 10'h330: dataout_d = 16'h00e9; 457 | 10'h331: dataout_d = 16'h002f; 458 | 10'h332: dataout_d = 16'h0029; 459 | 10'h333: dataout_d = 16'h000f; 460 | 10'h334: dataout_d = 16'h0060; 461 | 10'h335: dataout_d = 16'h008a; 462 | 10'h336: dataout_d = 16'h0048; 463 | 10'h337: dataout_d = 16'h00ad; 464 | 10'h338: dataout_d = 16'hfff8; 465 | 10'h339: dataout_d = 16'hfffe; 466 | 10'h33a: dataout_d = 16'h004a; 467 | 10'h33b: dataout_d = 16'h00b0; 468 | 10'h33c: dataout_d = 16'h0017; 469 | 10'h33d: dataout_d = 16'h004a; 470 | 10'h33e: dataout_d = 16'h0090; 471 | 10'h33f: dataout_d = 16'hfff7; 472 | 10'h340: dataout_d = 16'h00a6; 473 | 10'h341: dataout_d = 16'h0082; 474 | 10'h342: dataout_d = 16'h00e4; 475 | 10'h343: dataout_d = 16'h0081; 476 | 10'h344: dataout_d = 16'h00f0; 477 | 10'h345: dataout_d = 16'hfff1; 478 | 10'h346: dataout_d = 16'h00b5; 479 | 10'h347: dataout_d = 16'h0041; 480 | 10'h348: dataout_d = 16'h008d; 481 | 10'h349: dataout_d = 16'hfff9; 482 | 10'h34a: dataout_d = 16'hfffe; 483 | 10'h34b: dataout_d = 16'h00e8; 484 | 10'h34c: dataout_d = 16'h008a; 485 | 10'h34d: dataout_d = 16'h0029; 486 | 10'h34e: dataout_d = 16'h003f; 487 | 10'h34f: dataout_d = 16'h0085; 488 | 10'h350: dataout_d = 16'h0082; 489 | 10'h351: dataout_d = 16'h004c; 490 | 10'h352: dataout_d = 16'hff37; 491 | 10'h353: dataout_d = 16'hffff; 492 | 10'h354: dataout_d = 16'h0068; 493 | 10'h355: dataout_d = 16'h00aa; 494 | 10'h356: dataout_d = 16'h00ad; 495 | 10'h357: dataout_d = 16'hfff9; 496 | 10'h358: dataout_d = 16'hfffe; 497 | 10'h359: dataout_d = 16'h008d; 498 | 10'h35a: dataout_d = 16'h0000; 499 | 10'h35b: dataout_d = 16'hfffd; 500 | 10'h35c: dataout_d = 16'h0060; 501 | 10'h35d: dataout_d = 16'h0084; 502 | 10'h35e: dataout_d = 16'h0086; 503 | 10'h35f: dataout_d = 16'h0068; 504 | 10'h360: dataout_d = 16'h0085; 505 | 10'h361: dataout_d = 16'h0083; 506 | 10'h362: dataout_d = 16'h0068; 507 | 10'h363: dataout_d = 16'h0085; 508 | 10'h364: dataout_d = 16'h0084; 509 | 10'h365: dataout_d = 16'h00a0; 510 | 10'h366: dataout_d = 16'h0001; 511 | 10'h367: dataout_d = 16'h00b1; 512 | 10'h368: dataout_d = 16'h0083; 513 | 10'h369: dataout_d = 16'h00e6; 514 | 10'h36a: dataout_d = 16'h0083; 515 | 10'h36b: dataout_d = 16'h00d0; 516 | 10'h36c: dataout_d = 16'h0002; 517 | 10'h36d: dataout_d = 16'h00e6; 518 | 10'h36e: dataout_d = 16'h0084; 519 | 10'h36f: dataout_d = 16'h0009; 520 | 10'h370: dataout_d = 16'h0000; 521 | 10'h371: dataout_d = 16'h00f0; 522 | 10'h372: dataout_d = 16'h0006; 523 | 10'h373: dataout_d = 16'h0020; 524 | 10'h374: dataout_d = 16'hff97; 525 | 10'h375: dataout_d = 16'hffff; 526 | 10'h376: dataout_d = 16'h004c; 527 | 10'h377: dataout_d = 16'hff65; 528 | 10'h378: dataout_d = 16'hffff; 529 | 10'h379: dataout_d = 16'h00e6; 530 | 10'h37a: dataout_d = 16'h0083; 531 | 10'h37b: dataout_d = 16'h00d0; 532 | 10'h37c: dataout_d = 16'h0002; 533 | 10'h37d: dataout_d = 16'h00e6; 534 | 10'h37e: dataout_d = 16'h0084; 535 | 10'h37f: dataout_d = 16'h00a4; 536 | 10'h380: dataout_d = 16'h0086; 537 | 10'h381: dataout_d = 16'h006c; 538 | 10'h382: dataout_d = 16'h0083; 539 | 10'h383: dataout_d = 16'h0000; 540 | 10'h384: dataout_d = 16'h0048; 541 | 10'h385: dataout_d = 16'h004a; 542 | 10'h386: dataout_d = 16'h004a; 543 | 10'h387: dataout_d = 16'h004a; 544 | 10'h388: dataout_d = 16'h004a; 545 | 10'h389: dataout_d = 16'h0020; 546 | 10'h38a: dataout_d = 16'hff8d; 547 | 10'h38b: dataout_d = 16'hffff; 548 | 10'h38c: dataout_d = 16'h0068; 549 | 10'h38d: dataout_d = 16'h0029; 550 | 10'h38e: dataout_d = 16'h000f; 551 | 10'h38f: dataout_d = 16'h00c9; 552 | 10'h390: dataout_d = 16'h000a; 553 | 10'h391: dataout_d = 16'h0090; 554 | 10'h392: dataout_d = 16'h0002; 555 | 10'h393: dataout_d = 16'h0069; 556 | 10'h394: dataout_d = 16'h0006; 557 | 10'h395: dataout_d = 16'h0069; 558 | 10'h396: dataout_d = 16'h0030; 559 | 10'h397: dataout_d = 16'h0048; 560 | 10'h398: dataout_d = 16'h00ad; 561 | 10'h399: dataout_d = 16'hfff8; 562 | 10'h39a: dataout_d = 16'hfffe; 563 | 10'h39b: dataout_d = 16'h004a; 564 | 10'h39c: dataout_d = 16'h004a; 565 | 10'h39d: dataout_d = 16'h0090; 566 | 10'h39e: dataout_d = 16'hfff9; 567 | 10'h39f: dataout_d = 16'h0068; 568 | 10'h3a0: dataout_d = 16'h008d; 569 | 10'h3a1: dataout_d = 16'hfff9; 570 | 10'h3a2: dataout_d = 16'hfffe; 571 | 10'h3a3: dataout_d = 16'h0060; 572 | 10'h3a4: dataout_d = 16'h0086; 573 | 10'h3a5: dataout_d = 16'h0085; 574 | 10'h3a6: dataout_d = 16'h00a6; 575 | 10'h3a7: dataout_d = 16'h0081; 576 | 10'h3a8: dataout_d = 16'h0095; 577 | 10'h3a9: dataout_d = 16'h0041; 578 | 10'h3aa: dataout_d = 16'h00e8; 579 | 10'h3ab: dataout_d = 16'h008a; 580 | 10'h3ac: dataout_d = 16'h0029; 581 | 10'h3ad: dataout_d = 16'h003f; 582 | 10'h3ae: dataout_d = 16'h0085; 583 | 10'h3af: dataout_d = 16'h0081; 584 | 10'h3b0: dataout_d = 16'h00a6; 585 | 10'h3b1: dataout_d = 16'h0085; 586 | 10'h3b2: dataout_d = 16'h0060; 587 | 10'h3b3: dataout_d = 16'h0040; 588 | 10'h3b4: dataout_d = 16'h0000; 589 | 10'h3b5: dataout_d = 16'h0000; 590 | 10'h3b6: dataout_d = 16'h0000; 591 | 10'h3b7: dataout_d = 16'h0000; 592 | 10'h3b8: dataout_d = 16'h0000; 593 | 10'h3b9: dataout_d = 16'h0000; 594 | 10'h3ba: dataout_d = 16'h0000; 595 | 10'h3bb: dataout_d = 16'h0000; 596 | 10'h3bc: dataout_d = 16'h0000; 597 | 10'h3bd: dataout_d = 16'h0000; 598 | 10'h3be: dataout_d = 16'h0000; 599 | 10'h3bf: dataout_d = 16'h0000; 600 | 10'h3c0: dataout_d = 16'h0000; 601 | 10'h3c1: dataout_d = 16'h0000; 602 | 10'h3c2: dataout_d = 16'h0000; 603 | 10'h3c3: dataout_d = 16'h0000; 604 | 10'h3c4: dataout_d = 16'h0000; 605 | 10'h3c5: dataout_d = 16'h0000; 606 | 10'h3c6: dataout_d = 16'h0000; 607 | 10'h3c7: dataout_d = 16'h0000; 608 | 10'h3c8: dataout_d = 16'h0000; 609 | 10'h3c9: dataout_d = 16'h0000; 610 | 10'h3ca: dataout_d = 16'h0000; 611 | 10'h3cb: dataout_d = 16'h0000; 612 | 10'h3cc: dataout_d = 16'h0000; 613 | 10'h3cd: dataout_d = 16'h0000; 614 | 10'h3ce: dataout_d = 16'h0000; 615 | 10'h3cf: dataout_d = 16'h0000; 616 | 10'h3d0: dataout_d = 16'h0000; 617 | 10'h3d1: dataout_d = 16'h0000; 618 | 10'h3d2: dataout_d = 16'h0000; 619 | 10'h3d3: dataout_d = 16'h0000; 620 | 10'h3d4: dataout_d = 16'h0000; 621 | 10'h3d5: dataout_d = 16'h0000; 622 | 10'h3d6: dataout_d = 16'h0000; 623 | 10'h3d7: dataout_d = 16'h0000; 624 | 10'h3d8: dataout_d = 16'h0000; 625 | 10'h3d9: dataout_d = 16'h0000; 626 | 10'h3da: dataout_d = 16'h0000; 627 | 10'h3db: dataout_d = 16'h0000; 628 | 10'h3dc: dataout_d = 16'h0000; 629 | 10'h3dd: dataout_d = 16'h0000; 630 | 10'h3de: dataout_d = 16'h0000; 631 | 10'h3df: dataout_d = 16'h0000; 632 | 10'h3e0: dataout_d = 16'h004c; 633 | 10'h3e1: dataout_d = 16'hff35; 634 | 10'h3e2: dataout_d = 16'hffff; 635 | 10'h3e3: dataout_d = 16'h0000; 636 | 10'h3e4: dataout_d = 16'h0000; 637 | 10'h3e5: dataout_d = 16'h0000; 638 | 10'h3e6: dataout_d = 16'h0000; 639 | 10'h3e7: dataout_d = 16'h0000; 640 | 10'h3e8: dataout_d = 16'h0000; 641 | 10'h3e9: dataout_d = 16'h0000; 642 | 10'h3ea: dataout_d = 16'h0000; 643 | 10'h3eb: dataout_d = 16'h0000; 644 | 10'h3ec: dataout_d = 16'h0000; 645 | 10'h3ed: dataout_d = 16'h0000; 646 | 10'h3ee: dataout_d = 16'h004c; 647 | 10'h3ef: dataout_d = 16'hff97; 648 | 10'h3f0: dataout_d = 16'hffff; 649 | 10'h3f1: dataout_d = 16'h0000; 650 | 10'h3f2: dataout_d = 16'h0000; 651 | 10'h3f3: dataout_d = 16'h0000; 652 | 10'h3f4: dataout_d = 16'h0000; 653 | 10'h3f5: dataout_d = 16'h0000; 654 | 10'h3f6: dataout_d = 16'h0000; 655 | 10'h3f7: dataout_d = 16'h0000; 656 | 10'h3f8: dataout_d = 16'h0000; 657 | 10'h3f9: dataout_d = 16'h0000; 658 | 10'h3fa: dataout_d = 16'hffb3; 659 | 10'h3fb: dataout_d = 16'hffff; 660 | 10'h3fc: dataout_d = 16'hfd80; 661 | 10'h3fd: dataout_d = 16'hffff; 662 | 10'h3fe: dataout_d = 16'hffb3; 663 | 10'h3ff: dataout_d = 16'hffff; 664 | 665 | default: 666 | begin 667 | dataout_d = 16'hxxxx; 668 | end 669 | endcase 670 | end 671 | 672 | endmodule 673 | -------------------------------------------------------------------------------- /system-rtl/tinytestrom.as: -------------------------------------------------------------------------------- 1 | 2 | ;;************************************************************************** 3 | ;; 4 | ;; tinytestrom.as - support software for system-on-chip 65Org16 CPU experiment 5 | ;; for use i2c uart+led with 65Org16 in GOP24 6 | ;; 7 | ;; minimal ram test, prompt, read line of input into buffer and output back 8 | ;; 9 | ;; COPYRIGHT 2001 Ross Archer (parts derived from http://www.6502.org/source/monitors/intelhex/intelhex.htm) 10 | ;; COPYRIGHT 2011 Ed Spittles 11 | ;; 12 | ;; This file is part of verilog-6502 project 13 | ;; 14 | ;; This library is free software; you can redistribute it and/or 15 | ;; modify it under the terms of the GNU Lesser General Public 16 | ;; License version 2.1 as published by the Free Software Foundation. 17 | ;; 18 | ;; This library is distributed in the hope that it will be useful, 19 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 | ;; Lesser General Public License for more details. 22 | ;; 23 | ;; You should have received a copy of the GNU Lesser General Public 24 | ;; License along with this library; if not, write to the Free Software 25 | ;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 26 | ;; 27 | ;; ============================================================================ 28 | 29 | ;; assemble with patched version of David Beazley's http://www.dabeaz.com/superboard/asm6502.py 30 | ;; 31 | ;; python3 ../tools/asm65Org16.py tinytestrom.as |\ 32 | ;; sed 's/32.hffffff/ 8'\''h/;s/ :/: dataout_d =/' 33 | ;; 34 | ;; and patch into tinytestrom.v - alternatively we could initialise a block ram 35 | 36 | ;; place the origin so the reset vector lands at FFFFFFFC 37 | origin=0xFFFFFF0A 38 | UartS1=0xFFFEFFF8 39 | UartR1=0xFFFEFFF9 40 | UserLeds=0xFFFD0000 41 | 42 | ; zero page is large so we can place buffers there 43 | InputBuffer=0x0400 44 | InputPointer=0x0 45 | OutputBuffer=0x0500 46 | OutputHeadPointer=0x1 47 | OutputTailPointer=0x2 48 | 49 | DPL=0x3 ; temporary data pointer low 50 | DPH=0x4 51 | 52 | origin: 53 | 54 | ; kernel write to stdout 55 | ; writes to a circular buffer 56 | ; 256 bytes 57 | ; no overflow check 58 | ; uses X 59 | ; buffer is consumed elsewhere 60 | kwrite: 61 | LDX %OutputHeadPointer 62 | STA %OutputBuffer,X 63 | STA UserLeds ; too fast to see, but good for simulation 64 | INX 65 | TXA 66 | AND #0xFF 67 | STA %OutputHeadPointer 68 | RTS 69 | 70 | ;Put the string following in-line until a NULL out to the console 71 | putstring: 72 | PLA ; Get the low part of "return" address (data start address) 73 | STA DPL 74 | PLA 75 | STA DPH ; Get the high part of "return" address 76 | ; (data start address) 77 | ; Note: actually we're pointing one short 78 | PSINB: LDY #1 79 | LDA [DPL],Y ; Get the next string character 80 | INC DPL ; update the pointer 81 | BNE PSICHO ; if not, we're pointing to next character 82 | INC DPH ; account for page crossing 83 | PSICHO: ORA #0 ; Set flags according to contents of Accumulator 84 | BEQ PSIX1 ; don't print the final NULL 85 | JSR kwrite ; write it out 86 | JMP PSINB ; back around 87 | PSIX1: INC DPL ; 88 | BNE PSIX2 ; 89 | INC DPH ; account for page crossing 90 | PSIX2: JMP [DPL] ; return to byte following final NULL 91 | 92 | testram: 93 | LDA #0xA5C3 94 | LDX %0x0111 95 | STA %0x0111 96 | LDA #0x03FF 97 | LDY %0x0222 98 | STA %0x0222 99 | LDA %0x0111 100 | CMP #0xA5C3 101 | BNE fail 102 | LDA %0x0222 103 | CMP #0x03FF 104 | BEQ ramOK 105 | 106 | fail: 107 | LDA #0x007E 108 | STA UserLeds 109 | BNE fail 110 | 111 | ramOK: 112 | LDA #0x0081 ; signal success 113 | STA UserLeds 114 | STX %0x0111 ; restore the data we overwrote in the ram test 115 | STY %0x0222 116 | RTS 117 | 118 | lsr8: 119 | LSR 120 | LSR 121 | LSR 122 | LSR 123 | LSR 124 | LSR 125 | LSR 126 | LSR 127 | RTS 128 | 129 | writeprompt: 130 | JSR putstring 131 | DATA #ord('O') 132 | DATA #ord('K') 133 | DATA #ord('>') 134 | DATA #ord('\n') 135 | DATA #ord('\r') 136 | BRK 137 | RTS 138 | 139 | coldboot: 140 | LDX #0x03FF 141 | TXS ;; initialise stack pointer 142 | CLC 143 | 144 | LDA %0x0 145 | STA %0x8 146 | JSR testram 147 | 148 | init: 149 | LDA #0 150 | STA %InputPointer 151 | STA %OutputHeadPointer 152 | STA %OutputTailPointer 153 | 154 | JSR writeprompt 155 | 156 | ;; binary debug: output content of 16-bit locations 8 and 9 157 | LDA %0x8 158 | JSR kwrite 159 | LDA %0x8 160 | JSR lsr8 161 | JSR kwrite 162 | LDA %0x9 163 | JSR kwrite 164 | LDA %0x9 165 | JSR lsr8 166 | JSR kwrite 167 | 168 | uartinit: 169 | LDA #3 170 | STA UartS1 171 | 172 | ; main loop for I/O handling 173 | ; deal with input as highest priority 174 | uartloop: 175 | LDA UartS1 176 | LSR 177 | BCS dealWithIncoming 178 | LSR ; any room for transmission? 179 | BCC uartloop 180 | okToSend: 181 | LDX %OutputTailPointer 182 | CPX %OutputHeadPointer 183 | BEQ uartloop 184 | LDA %OutputBuffer,X 185 | STA UartR1 186 | INX 187 | TXA 188 | AND #0xFF 189 | STA %OutputTailPointer 190 | JMP uartloop 191 | 192 | dealWithIncoming: 193 | LDA UartR1 ; incoming data is shown on LEDs 194 | PHA 195 | STA UserLeds 196 | LDX %InputPointer 197 | STA %InputBuffer,X 198 | INX 199 | STX %InputPointer 200 | PLA 201 | CMP #0x0d ; newline 202 | BNE uartloop 203 | 204 | processLineOfInput: 205 | LDX #0 206 | nextInputChar: 207 | CPX %InputPointer 208 | BEQ clearInputBuffer 209 | TXA 210 | TAY 211 | LDA %InputBuffer,X 212 | JSR kwrite 213 | TYA 214 | TAX 215 | INX 216 | BNE nextInputChar 217 | 218 | clearInputBuffer: 219 | LDX #0 220 | STX %InputPointer 221 | BEQ uartloop ; we're finished 222 | 223 | nmivector: 224 | DATA # 0xFFFA ; as a reminder of location 225 | DATA # 0xFFFF 226 | resetvector: 227 | DATA # LOW(coldboot) 228 | DATA # HIGH(coldboot) 229 | irqbrkvector: 230 | DATA # 0xFFFE ; as a reminder of location 231 | DATA # 0xFFFF 232 | -------------------------------------------------------------------------------- /system-rtl/uart.v: -------------------------------------------------------------------------------- 1 | // uart function: bidirectional, bytewide, asynchronous 2 | // perhaps with some notion of flow control 3 | // 4 | // this implementation will transport over i2c but should 5 | // be swappable with something else 6 | 7 | module uart( 8 | inout SDA, 9 | input SCL, 10 | input clk, 11 | input read, 12 | input write, 13 | input address, 14 | input [`datawidth] datain, 15 | output [`datawidth] dataout 16 | ); 17 | 18 | // the local view is like a 6850: two addresses offering 4 registers 19 | // control (write) 20 | // write 0x03 to reset 21 | // status (read) 22 | // bit 0: serial inbound: 1 means data is available from host 23 | // bit 1: serial outbound: 1 means empty, data may be written for transmission to host 24 | // data (read/write) 25 | // Tx and Rx data 26 | // 27 | // the host-facing view is 2 i2c addresses 28 | // 4D (read) status: non-zero means data is available 29 | // 4E (write) 4F (read) data: to and from the SoC 30 | // 31 | // as an enhancement we could allow a local FIFO and allow multi-byte i2c transfers, 32 | // at which point the status to the host would inform it of FIFO space in both directions. 33 | // 34 | 35 | // the i2cslave from fpga4fun has some shortcomings 36 | // - is not redistributable - so we distribute a patch 37 | // - original at http://www.fpga4fun.com/I2C.html 38 | // - specifically http://www.fpga4fun.com/files/I2Cslave1.zip 39 | // - see also freeware version http://www.fpga4fun.com/ExternalContributions/VHDL_i2cs_rx_CPLD.zip 40 | // - is an output port only (fixed!) 41 | // - can't signal that an outgoing byte has left the building 42 | // - can't signal that an inbound byte is ready for reception 43 | // - can't signal (upstream) that there's no room for an inbound byte 44 | 45 | // while a 16-bit or 2-byte port might be neat, the least-effort solution 46 | // is a pair of instances 47 | // upstream towards the host: 48 | // gop2host_data 49 | // gop2host_status - for the host to determine if there's a byte to be fetched from gop 50 | // downstream from the host: 51 | // host2gop_data 52 | // host2gop_status - not an i2c register, but gop needs to know if there's room to write a byte 53 | 54 | reg [7:0] host_facing_status; 55 | 56 | // resample the ack signals into chip-side clock domain 57 | wire dataSent_w, dataReceived_w; 58 | reg [3:0] dataSent, dataReceived; 59 | always @(posedge clk) 60 | begin 61 | if(write & !address) // command register 62 | if (datain[1:0] == 2'b11) // reset command 63 | begin 64 | dataSent[3:0] <= 4'b0; 65 | dataReceived[3:0] <= 4'b0; 66 | end 67 | dataSent[3] <= dataSent_w; 68 | dataSent[2:0] <= dataSent[3:1]; 69 | dataReceived[3] <= dataReceived_w; 70 | dataReceived[2:0] <= dataReceived[3:1]; 71 | end 72 | 73 | // for illustration only we pick off the leading or trailing edge 74 | wire dataSentOK = dataSent[1] & !dataSent[0]; // leading edge 75 | wire dataReceivedOK = !dataReceived[1] & dataReceived[0]; // trailing edge 76 | 77 | reg [7:0] status, txdata; 78 | wire [7:0] rxdata; 79 | 80 | always @(posedge clk) 81 | begin 82 | if(write & address) // Tx data register 83 | txdata <= datain[7:0]; 84 | 85 | if(write & !address) // command register 86 | if (datain[1:0] == 2'b11) // reset command 87 | begin 88 | status[7:0] <= 8'b00000010; // initially "Ready/Empty" 89 | host_facing_status <= 8'h00; 90 | end 91 | 92 | // maintain the status bit 0: "Data can be read" 93 | if (dataReceivedOK) 94 | status[0] <= 1'b1; // an ACK came in: we have an Rx'd byte 95 | if (read & address) 96 | status[0] <= 1'b0; // we read the Rx byte - don't read the same one twice 97 | 98 | // maintain the status bit 1: "Ready/Empty" and the similar host-facing bit 99 | if (dataSentOK) 100 | begin 101 | status[1] <= 1'b1; // an ACK is going out: we're clear to Tx another byte 102 | host_facing_status <= 8'h00; 103 | end 104 | if (write & address) 105 | begin 106 | status[1] <= 1'b0; // we write a Tx byte: no more until it is transmitted 107 | host_facing_status <= 8'h01; 108 | end 109 | end 110 | 111 | assign dataout[15:8] = 8'b0; 112 | assign dataout[7:0] = address ? rxdata : status; 113 | 114 | i2cslave #(.I2C_ADR(7'h26)) _i2cstatus( 115 | .SDA(SDA), 116 | .SCL(SCL), 117 | .IOout(), 118 | .IOin(host_facing_status), 119 | .serialTxDataAck(), 120 | .serialRxDataAck() 121 | ); 122 | 123 | i2cslave #(.I2C_ADR(7'h27)) _i2cdata( 124 | .SDA(SDA), 125 | .SCL(SCL), 126 | .IOout(rxdata), 127 | .IOin(txdata), 128 | .serialTxDataAck(dataSent_w), 129 | .serialRxDataAck(dataReceived_w) 130 | ); 131 | 132 | endmodule 133 | -------------------------------------------------------------------------------- /tools/hexloader.as: -------------------------------------------------------------------------------- 1 | ; 2 | ; original downloaded from http://www.6502.org/source/monitors/intelhex/intelhex.htm 3 | ; 2011-05-23 18:57:40 UTC 4 | ; copyright Ross Archer dedicated as follows 5 | ; This program is freeware. Use it, modify it, ridicule it in public, 6 | ; or whatever, so long as authorship credit (blame?) is given somewhere to 7 | ; me for the base program. 8 | ; 9 | ; Ross seems uncontactable at the mail address given, also at ross@6502.org 10 | ; 11 | ; converted to format acceptable to asm65Org16.py 12 | ; 13 | ; ($7FFB, $7FFA): NMI RAM vector 14 | ; ($7FFF, $7FFE): IRQ RAM vector 15 | ; (User program may not set a new RESET vector, or we could load 16 | ; an unrecoverable program into SRAM if battery backed, which would 17 | ; kill the system until the RAM was removed!) 18 | ; 19 | ; 20 | ; 6551 ACIA equates for serial I/O 21 | ; 22 | ACIA_BASE = 0xF000 ; This is where the 6551 ACIA Starts 23 | SDR = ACIA_BASE ; RX'ed bytes read, TX bytes written, here 24 | SSR = ACIA_BASE+1 ; Serial data status register. A write here 25 | ; causes a programmed reset. 26 | SCMD = ACIA_BASE+2 ; Serial command reg. () 27 | SCTL = ACIA_BASE+3 ; Serial control reg. () 28 | ; Quick n'dirty assignments instead of proper definitions of each parameter 29 | ; "ORed" together to build the desired flexible configuration. We're going 30 | ; to run 19200 baud, no parity, 8 data bits, 1 stop bit. Period. For now. 31 | ; 32 | SCTL_V = 0b00011111 ; 1 stop, 8 bits, 19200 baud 33 | SCMD_V = 0b00001011 ; No parity, no echo, no tx or rx IRQ, DTR* 34 | TX_RDY = 0b00010000 ; AND mask for transmitter ready 35 | RX_RDY = 0b00001000 ; AND mask for receiver buffer full 36 | ; 37 | ; Zero-page storage 38 | DPL = 0x00 ; data pointer (two bytes) 39 | DPH = 0x01 ; high of data pointer 40 | RECLEN = 0x02 ; record length in bytes 41 | START_LO = 0x03 42 | START_HI = 0x04 43 | RECTYPE = 0x05 44 | CHKSUM = 0x06 ; record checksum accumulator 45 | DLFAIL = 0x07 ; flag for download failure 46 | TEMP = 0x08 ; save hex value 47 | 48 | ; "Shadow" RAM vectors (note each is 0x8000 below the actual ROM vector) 49 | NMIVEC= 0x7FFA ; write actual NMI vector here 50 | IRQVEC= 0x7FFE ; write IRQ vector here 51 | 52 | ENTRY_POINT =0x0200 ; where the RAM program MUST have its first instruction 53 | 54 | START= 0xF800 55 | ; 56 | START: SEI ; disable interrupts 57 | CLD ; binary mode arithmetic 58 | LDX #0xFF ; Set up the stack pointer 59 | TXS ; " 60 | LDA #HIGH(START) ; Initialiaze the interrupt vectors 61 | STA NMIVEC+1 ; User program at ENTRY_POINT may change 62 | STA IRQVEC+1 ; these vectors. Just do change before enabling 63 | LDA #LOW(START) ; the interrupts, or you'll end up back in the d/l monitor. 64 | STA NMIVEC 65 | STA IRQVEC 66 | JSR INITSER ; Set up baud rate, parity, etc. 67 | ; Download Intel hex. The program you download MUST have its entry 68 | ; instruction (even if only a jump to somewhere else) at ENTRY_POINT. 69 | HEXDNLD: 70 | LDA #0 71 | STA DLFAIL ;Start by assuming no D/L failure 72 | JSR PUTSTRI 73 | DATA #13 74 | DATA #10 75 | DATA #ord('>') 76 | DATA #0 77 | 78 | ; DATA 13,10,13,10 79 | ; DATA "Send 6502 code in" 80 | ; DATA " Intel Hex format" 81 | ; DATA " at 19200,n,8,1 ->" 82 | ; DATA 13,10 83 | ; DATA 0 ; Null-terminate unless you prefer to crash. 84 | HDWRECS: 85 | JSR GETSER ; Wait for start of record mark ':' 86 | CMP #0x3a ; ord(":") 87 | BNE HDWRECS ; not found yet 88 | ; Start of record marker has been found 89 | JSR GETHEX ; Get the record length 90 | STA RECLEN ; save it 91 | STA CHKSUM ; and save first byte of checksum 92 | JSR GETHEX ; Get the high part of start address 93 | STA START_HI 94 | CLC 95 | ADC CHKSUM ; Add in the checksum 96 | STA CHKSUM ; 97 | JSR GETHEX ; Get the low part of the start address 98 | STA START_LO 99 | CLC 100 | ADC CHKSUM 101 | STA CHKSUM 102 | JSR GETHEX ; Get the record type 103 | STA RECTYPE ; & save it 104 | CLC 105 | ADC CHKSUM 106 | STA CHKSUM 107 | LDA RECTYPE 108 | BNE HDER1 ; end-of-record 109 | LDX RECLEN ; number of data bytes to write to memory 110 | LDY #0 ; Start offset at 0 111 | HDLP1: JSR GETHEX ; Get the first/next/last data byte 112 | STA [START_LO],Y ; Save it to RAM 113 | CLC 114 | ADC CHKSUM 115 | STA CHKSUM ; 116 | INY ; update data pointer 117 | DEX ; decrement count 118 | BNE HDLP1 119 | JSR GETHEX ; get the checksum 120 | CLC 121 | ADC CHKSUM 122 | BNE HDDLF1 ; If failed, report it 123 | ; Another successful record has been processed 124 | LDA #'#' ; Character indicating record OK = '#' 125 | STA SDR ; write it out but don't wait for output 126 | JMP HDWRECS ; get next record 127 | HDDLF1: 128 | LDA #'F' ; Character indicating record failure = 'F' 129 | STA DLFAIL ; download failed if non-zero 130 | STA SDR ; write it to transmit buffer register 131 | JMP HDWRECS ; wait for next record start 132 | HDER1: 133 | CMP #1 ; Check for end-of-record type 134 | BEQ HDER2 135 | JSR PUTSTRI ; Warn user of unknown record type 136 | DATA #13 137 | DATA #10 138 | DATA #ord('?') 139 | DATA #0 140 | ; DATA 13,10,13,10 141 | ; DATA "Unknown record type 0x" 142 | ; DATA 0 ; null-terminate unless you prefer to crash! 143 | LDA RECTYPE ; Get it 144 | STA DLFAIL ; non-zero --> download has failed 145 | JSR PUTHEX ; print it 146 | LDA #13 ; but we'll let it finish so as not to 147 | JSR PUTSER ; falsely start a new d/l from existing 148 | LDA #10 ; file that may still be coming in for 149 | JSR PUTSER ; quite some time yet. 150 | JMP HDWRECS 151 | ; We've reached the end-of-record record 152 | HDER2: JSR GETHEX ; get the checksum 153 | CLC 154 | ADC CHKSUM ; Add previous checksum accumulator value 155 | BEQ HDER3 ; checksum = 0 means we're OK! 156 | JSR PUTSTRI ; Warn user of bad checksum 157 | DATA #13 158 | DATA #10 159 | DATA #ord('!') 160 | DATA #0 161 | ; DATA 13,10,13,10 162 | ; DATA "Bad record checksum!",13,10 163 | ; DATA 0 ; Null-terminate or 6502 go bye-bye 164 | JMP START 165 | HDER3: LDA DLFAIL 166 | BEQ HDEROK 167 | ;A download failure has occurred 168 | JSR PUTSTRI 169 | DATA #13 170 | DATA #10 171 | DATA #ord('~') 172 | DATA #0 173 | ; DATA 13,10,13,10 174 | ; DATA "Download Failed",13,10 175 | ; DATA "Aborting!",13,10 176 | ; DATA 0 ; null-terminate every string yada yada. 177 | JMP START 178 | HDEROK: JSR PUTSTRI 179 | DATA #13 180 | DATA #10 181 | DATA #ord('^') 182 | DATA #0 183 | ; DATA 13,10,13,10 184 | ; DATA "Download Successful!",13,10 185 | ; DATA "Jumping to location 0x"; 186 | ; DATA 0 ; by now, I figure you know what this is for. :) 187 | LDA #HIGH(ENTRY_POINT) ; Print the entry point in hex 188 | JSR PUTHEX 189 | LDA #LOW(ENTRY_POINT) 190 | JSR PUTHEX 191 | JSR PUTSTRI 192 | DATA #13 193 | DATA #10 194 | DATA #0 195 | JMP ENTRY_POINT ; jump to canonical entry point 196 | 197 | ; 198 | ; Set up baud rate, parity, stop bits, interrupt control, etc. for 199 | ; the serial port. 200 | INITSER: 201 | LDA #SCTL_V ; Set baud rate 'n stuff 202 | STA SCTL 203 | LDA #SCMD_V ; set parity, interrupt disable, n'stuff 204 | STA SCMD 205 | RTS 206 | 207 | ; 208 | ; 209 | ; SerRdy : Return 210 | SERRDY: LDA SSR ; look at serial status 211 | AND #RX_RDY ; strip off "character waiting" bit 212 | RTS ; if zero, nothing waiting. 213 | ; Warning: this routine busy-waits until a character is ready. 214 | ; If you don't want to wait, call SERRDY first, AND then only 215 | ; call GETSER once a character is waiting. 216 | GETSER: LDA SSR ; look at serial status 217 | AND #RX_RDY ; see if anything is ready 218 | BEQ GETSER ; busy-wait until character comes in! 219 | LDA SDR ; get the character 220 | RTS 221 | ; Busy wait 222 | 223 | GETHEX: JSR GETSER 224 | JSR MKNIBL ; Convert to 0..F numeric 225 | ASL 226 | ASL 227 | ASL 228 | ASL ; This is the upper nibble 229 | AND #0xF0 230 | STA TEMP 231 | JSR GETSER 232 | JSR MKNIBL 233 | ORA TEMP 234 | RTS ; return with the nibble received 235 | 236 | ; Convert the ASCII nibble to numeric value from 0-F: 237 | MKNIBL: CMP #ord('9')+1 ; See if it's 0-9 or 'A'..'F' (no lowercase yet) 238 | BCC MKNNH ; If we borrowed, we lost the carry so 0..9 239 | SBC #7+1 ; Subtract off extra 7 (SBC subtracts off one less) 240 | ; If we fall through, carry is set unlike direct entry at MKNNH 241 | MKNNH: SBC #ord('0')-1 ; subtract off '0' (if carry clear coming in) 242 | AND #0x0F ; no upper nibble no matter what 243 | RTS ; AND return the nibble 244 | 245 | ; Put byte in A as hexydecascii 246 | PUTHEX: PHA 247 | LSR 248 | LSR 249 | LSR 250 | LSR 251 | JSR PRNIBL 252 | PLA 253 | PRNIBL: AND #0x0F ; strip off the low nibble 254 | CMP #0x0A 255 | BCC NOTHEX ; if it's 0-9, add '0' else also add 7 256 | ADC #6 ; Add 7 (6+carry=1), result will be carry clear 257 | NOTHEX: ADC #'0' ; If carry clear, we're 0-9 258 | ; Write the character in A as ASCII: 259 | PUTSER: STA SDR ; write to transmit register 260 | WRS1: LDA SSR ; get status 261 | AND #TX_RDY ; see if transmitter is busy 262 | BEQ WRS1 ; if it is, wait 263 | RTS 264 | ;Put the string following in-line until a NULL out to the console 265 | PUTSTRI: 266 | PLA ; Get the low part of "return" address (data start address) 267 | STA DPL 268 | PLA 269 | STA DPH ; Get the high part of "return" address 270 | ; (data Start address) 271 | ; Note: actually we're pointing one short 272 | PSINB: LDY #1 273 | LDA [DPL],Y ; Get the next string character 274 | INC DPL ; update the pointer 275 | BNE PSICHO ; if not, we're pointing to next character 276 | INC DPH ; account for page crossing 277 | PSICHO: ORA #0 ; Set flags according to contents of Accumulator 278 | BEQ PSIX1 ; don't print the final NULL 279 | JSR PUTSER ; write it out 280 | JMP PSINB ; back around 281 | PSIX1: INC DPL ; 282 | BNE PSIX2 ; 283 | INC DPH ; account for page crossing 284 | PSIX2: JMP (DPL) ; return to byte following final NULL 285 | ; 286 | ; User "shadow" vectors: 287 | GOIRQ: JMP (IRQVEC) 288 | GONMI: JMP (NMIVEC) 289 | GORST: JMP START ; Allowing user program to change this is a mistake 290 | 291 | ; vectors=0xFFFA 292 | vectors: 293 | NMIENT: DATA #LOW(GONMI) 294 | DATA #HIGH(GONMI) 295 | RSTENT: DATA #LOW(GORST) 296 | DATA #HIGH(GORST) 297 | IRQENT: DATA #LOW(GOIRQ) 298 | DATA #HIGH(GOIRQ) 299 | ; ; finally. das Ende. 300 | -------------------------------------------------------------------------------- /tools/usb.i2c.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # test program for i2c testing of robotelectronics i2c adapter 3 | # 4 | # on windows, need unbuffered tty output so invoke with 5 | # /cygdrive/c/Python26/python -u usb.i2c.py 6 | # 7 | # talking to a GOP24 with fpga4fun slave (like an 8574) 8 | 9 | import serial 10 | import sys 11 | import time 12 | import select 13 | 14 | # some assistance from http://code.activestate.com/recipes/134892/ 15 | # - there's more there for OS X too 16 | # - also used http://effbot.org/pyfaq/how-do-i-get-a-single-keypress-at-a-time.htm 17 | class _Getch: 18 | """Gets a single character from standard input. Does not echo to the screen.""" 19 | def __init__(self): 20 | try: 21 | self.impl = _GetchWindows() 22 | except ImportError: 23 | self.impl = _GetchUnix() 24 | 25 | def __call__(self): return self.impl() 26 | 27 | class _GetchUnix: 28 | def __init__(self): 29 | import tty, sys 30 | 31 | def __call__(self): 32 | import sys, tty, termios 33 | fd = sys.stdin.fileno() 34 | old_settings = termios.tcgetattr(fd) 35 | try: 36 | tty.setraw(sys.stdin.fileno()) 37 | timeout = 0.1 38 | ch='X' 39 | r, w, e = select.select([fd], [], [], timeout) 40 | if r: 41 | ch = sys.stdin.read(1) 42 | finally: 43 | termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) 44 | return ch, r 45 | 46 | class _GetchWindows: 47 | # don't know how to do a timeout in Windows 48 | def __init__(self): 49 | import msvcrt 50 | 51 | def __call__(self): 52 | import msvcrt 53 | return msvcrt.getch(), True 54 | 55 | getchWithTimeout = _Getch() 56 | 57 | def readback(n): 58 | return ser.read(n) 59 | 60 | print "about to read back" 61 | 62 | bytes=ser.read(n) 63 | if len(bytes)>0 : 64 | print "%d bytes read" % len(bytes) 65 | for i in range(len(bytes)): 66 | print "byte was: %1x\n" % ord(bytes[i]) 67 | else: 68 | print "no bytes read (timeout)" 69 | 70 | def writebyteoverI2C(x): 71 | # 53 is the single-byte simple device command 72 | # byte1 is the address and read bit (we are 4E to write, 4F to read) 73 | ser.write("\x53\x4E"+x) 74 | if ord(readback(1))==0: 75 | print "failed to write a byte" 76 | exit(1) 77 | 78 | def readbyte(): 79 | ser.write("\x53\x4F") 80 | return readback(1) 81 | 82 | def anythingtoread(): 83 | # status reg tells us if there is data pending to be read 84 | ser.write("\x53\x4D") 85 | return ord(ser.read(1)[0])==1 86 | 87 | def readchar(): 88 | if anythingtoread(): 89 | print 'one char from FPGA: 0x%02x' % ord(readbyte()) 90 | time.sleep(1) 91 | else: 92 | print 'nothing to read, sleeping' 93 | time.sleep(1) 94 | 95 | def readanycharsfromUART(): 96 | while anythingtoread(): 97 | # print readbyte() 98 | ch=readbyte() 99 | # print "\r\nch: 0x%02x\n\r" % ord(ch) 100 | sys.stdout.write(ch) 101 | if ch=='\n': 102 | sys.stdout.write('\r') 103 | if ch=='\r': 104 | sys.stdout.write('\n') 105 | if ord(ch)<32: 106 | sys.stdout.flush() 107 | 108 | port_linux="/dev/ttyUSB0" 109 | port_windows="COM4" 110 | 111 | try: 112 | ser = serial.Serial(port_windows, 19200, timeout=2, stopbits=serial.STOPBITS_TWO) 113 | except: 114 | ser = serial.Serial(port_linux, 19200, timeout=2, stopbits=serial.STOPBITS_TWO) 115 | 116 | import sys, tty, termios 117 | fd = sys.stdin.fileno() 118 | old_settings = termios.tcgetattr(fd) 119 | try: 120 | tty.setraw(sys.stdin.fileno()) 121 | timeout = 0.1 # we will be polling the FPGA frequently 122 | ch='X' 123 | while 1: 124 | readanycharsfromUART() 125 | r, w, e = select.select([fd], [], [], timeout) 126 | if r: 127 | ch = sys.stdin.read(1) 128 | if ch == "\x03": # handle ^C as we're in raw mode 129 | break 130 | writebyteoverI2C(ch) 131 | # print "\n\r>>", "0x%02x" % ord(ch), "\n\r" 132 | 133 | finally: 134 | termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) 135 | 136 | print "done" 137 | exit(0) 138 | 139 | # 140 | # various historial efforts or tests 141 | # 142 | 143 | while 1: 144 | char, gotit = getchWithTimeout() 145 | if gotit: 146 | print ">>", char, 147 | readchar() 148 | 149 | while 1: 150 | readchar() 151 | print "trying a write of 0x60" 152 | writebyte("\x60") 153 | readchar() 154 | readchar() 155 | print "trying a write of 0x55" 156 | writebyte("\x55") 157 | readchar() 158 | print "trying a write of 0xaa" 159 | writebyte("\xaa") 160 | readchar() 161 | 162 | while 1: 163 | raw_input('Press Enter to read a byte') 164 | print 'status byte before read: %d' % readstatus() 165 | 166 | while 1: 167 | readbyte() 168 | print 'status byte after read:' 169 | readstatus() 170 | print 'about to write' 171 | writebyte("\xf0") 172 | print 'status byte after write:' 173 | readstatus() 174 | print 'another read:' 175 | readbyte() 176 | 177 | raw_input('Press Enter to read status') 178 | while 1: 179 | readstatus() 180 | 181 | while 1: 182 | writebyte("\x01") 183 | writebyte("\x02") 184 | writebyte("\x04") 185 | writebyte("\x08") 186 | writebyte("\x10") 187 | writebyte("\x20") 188 | writebyte("\x40") 189 | writebyte("\x80") 190 | 191 | ser.close() 192 | --------------------------------------------------------------------------------