├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── Makefile ├── README.md ├── alu.v ├── cpu.v ├── fadder.v ├── mul4x4.v ├── pcounter.v ├── prog_add.list ├── prog_fib.list ├── prog_jump.list ├── prog_load_out.list ├── prog_load_store.list ├── prog_mul.list ├── prog_shl.list ├── prog_sub.list ├── ram.v ├── shl8.v ├── top.pcf ├── top.v ├── top_test_add.v ├── top_test_fibonacci.v ├── top_test_jump.v ├── top_test_load_out.v ├── top_test_load_store.v ├── top_test_mul.v ├── top_test_shl.v ├── top_test_sub.v └── uart-tx.v /.gitignore: -------------------------------------------------------------------------------- 1 | *.bin 2 | *.blif 3 | *.txt 4 | *.vcd 5 | *.vvp 6 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to Contribute 2 | 3 | We'd love to accept your patches and contributions to this project. There are 4 | just a few small guidelines you need to follow. 5 | 6 | ## Contributor License Agreement 7 | 8 | Contributions to this project must be accompanied by a Contributor License 9 | Agreement. You (or your employer) retain the copyright to your contribution, 10 | this simply gives us permission to use and redistribute your contributions as 11 | part of the project. Head over to to see 12 | your current agreements on file or to sign a new one. 13 | 14 | You generally only need to submit a CLA once, so if you've already submitted one 15 | (even if it was for a different project), you probably don't need to do it 16 | again. 17 | 18 | ## Code reviews 19 | 20 | All submissions, including submissions by project members, require review. We 21 | use GitHub pull requests for this purpose. Consult 22 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more 23 | information on using pull requests. 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2017 Google Inc. 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | COMP = iverilog 2 | SIM = vvp 3 | SYN = yosys 4 | PNR = arachne-pnr 5 | PACK = icepack 6 | PROG = iceprog 7 | 8 | PCF = top.pcf 9 | SOURCE = top 10 | TESTS = top_test_sub.vcd top_test_add.vcd top_test_jump.vcd top_test_load_out.vcd \ 11 | top_test_load_store.vcd top_test_shl.vcd top_test_mul.vcd top_test_fibonacci.vcd 12 | 13 | all: $(TESTS) 14 | 15 | %.vcd: %.vvp 16 | $(SIM) $< 17 | 18 | %.vvp: %.v 19 | $(COMP) -Wall -o $@ $< 20 | 21 | %.blif: %.v 22 | $(SYN) -q -p "synth_ice40 -blif $@" $< 23 | 24 | %.txt: %.blif 25 | $(PNR) -p $(PCF) -o $@ $< 26 | 27 | %.bin: %.txt 28 | $(PACK) $< $@ 29 | 30 | flash: $(SOURCE).bin 31 | $(PROG) $< 32 | 33 | clean: 34 | rm -f *.vvp *.vcd *.blif *.bin *.txt 35 | 36 | .PHONY: clean 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BBSoftCPU 2 | 3 | A Verilog HDL implementation of a breadboard TTL CPU design. The design itself is based on the 4 | series of educational [videos][1] by Ben Eater. 5 | 6 | Testing can be done on the Lattice iCE40 family of FPGAs. The specific board used during development is: 7 | 8 | * [icestick][2] 9 | 10 | This particular family of FPGAs is currently supported by a fully open source toolchain. 11 | For anyone interested further information is available at: 12 | 13 | * [Yosys][3] 14 | * [arachne-pnr][4] 15 | * [IceStorm][5] 16 | 17 | There are several notable modifications from the original design: 18 | 19 | * There is no internal bus or tri-state logic. The latter is rarely if ever supported internally on current FPGAs. Muxers 20 | are used as a replacement. 21 | * The ALU doesn't have sequantial logic. 22 | * Registers A, B are part of the main CPU module. 23 | * The control logic is not triggered by the negative clock edge. The positive clock edge is used throughout. 24 | * The 'OUT' instruction doesn't output to any display HW. The FPGA board used for testing does have an extra UART port. 25 | The instruction will transmit the value of register 'A' on the second port. 26 | 27 | ## Build environment 28 | 29 | Ubuntu 16.04 or newer. The toolchain and verilog simulator can be installed via: 30 | 31 | ``` 32 | sudo apt-get install build-essential arachne-pnr iverilog 33 | ``` 34 | 35 | You could also install GtkWave for viewing the simulation waveforms: 36 | 37 | ``` 38 | sudo apt-get install gtkwave 39 | ``` 40 | 41 | And minicom for receiving the output: 42 | 43 | ``` 44 | sudo apt-get install minicom 45 | ``` 46 | 47 | ## Running the simulator test bench 48 | 49 | The simulator can be invoked via: 50 | 51 | ``` 52 | make 53 | ``` 54 | 55 | The output should be a 'top_test_fibonacci.vcd' file that can be viewed using GtkWave: 56 | 57 | ``` 58 | gtkwave top_test_fibonacci.vcd 59 | ``` 60 | 61 | ## USB permissions for the FPGA board 62 | 63 | Before flashing the FPGA board, the USB access permissions need a minor adjustment that will allow the tools to 64 | write a bitstream on the device. Create a new file at: 65 | ``` 66 | /etc/udev/rules.d/53-lattice-ftdi.rules 67 | ``` 68 | 69 | Add this line inside: 70 | 71 | ``` 72 | ACTION=="add", ATTR{idVendor}=="0403", ATTR{idProduct}=="6010", MODE:="666" 73 | ``` 74 | 75 | ## Flashing 76 | 77 | Make sure that the icestick board is connected to the host PC. 78 | Flashing the bitstream on the FPGA can be done by invoking: 79 | 80 | ``` 81 | make flash 82 | ``` 83 | 84 | ## Receiving output 85 | 86 | The default program will currently calculate the fibonacci sequence of numbers. 87 | As mentioned before the 'OUT' instruction will transmit the register 'A' contents on the second UART port. 88 | The serial device will usually appear on the host as '/dev/ttyUSB1'. The configuration used right now is: 89 | 90 | * baudrate: 19000 91 | * bits: 8 92 | * parity: none 93 | * stop bits: 2 94 | * no hw flow control 95 | 96 | The data comes in as binary so for nicer output you can instruct minicom to display in hex mode: 97 | 98 | ``` 99 | minicom -H 100 | ``` 101 | 102 | This is not an official Google product 103 | 104 | [1]: https://www.youtube.com/user/eaterbc 105 | [2]: http://www.latticesemi.com/icestick 106 | [3]: http://www.clifford.at/yosys/ 107 | [4]: https://github.com/cseed/arachne-pnr 108 | [5]: http://www.clifford.at/icestorm/ 109 | 110 | -------------------------------------------------------------------------------- /alu.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | `include "mul4x4.v" 18 | 19 | module alu( 20 | input [WIDTH-1 : 0] a, 21 | input [WIDTH-1 : 0] b, 22 | input mul_enable, 23 | input sub_enable, 24 | input shift_enable, 25 | input [2 : 0] shift_pos, 26 | output [WIDTH-1 : 0] result, 27 | output carry_out); 28 | 29 | parameter WIDTH = 8; 30 | 31 | wire [WIDTH-1 : 0] adder_res; 32 | wire adder_carry; 33 | 34 | wire [7 : 0] shift_res; 35 | wire shift_carry; 36 | 37 | wire [7: 0] mul_res; 38 | 39 | assign result = (mul_enable) ? mul_res : 40 | (shift_enable) ? shift_res : 41 | (adder_res); 42 | assign carry_out = (shift_enable) ? shift_carry : 43 | adder_carry; 44 | 45 | fadder #(.WIDTH(WIDTH)) ripple_adder( 46 | .a(a), 47 | .b(b), 48 | .sub_enable(sub_enable), 49 | .carry_in(sub_enable), 50 | .res(adder_res), 51 | .carry_out(adder_carry)); 52 | 53 | shl8 left_shift( 54 | .a(a), 55 | .shift(shift_pos), 56 | .res(shift_res), 57 | .carry(shift_carry)); 58 | 59 | mul4x4 multiply(a[3:0], a[7:4], mul_res); 60 | 61 | endmodule 62 | -------------------------------------------------------------------------------- /cpu.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | `include "alu.v" 18 | `include "pcounter.v" 19 | `include "ram.v" 20 | `include "uart-tx.v" 21 | 22 | module cpu( 23 | input clk, 24 | output uart_tx_wire); 25 | localparam INSTR_SIZE = 4; 26 | localparam WIDTH = 8; 27 | localparam ADDRESS_WIDTH = WIDTH - INSTR_SIZE; 28 | 29 | localparam NOP = 4'b0000; //No operation. 30 | localparam LDA = 4'b0001; //Load register A from memory. 31 | localparam ADD = 4'b0010; //Add specified memory pointer to register A. 32 | //Store the result in register A. 33 | localparam SUB = 4'b0011; //Subtract specified memory from register A. 34 | //Store the result in register A. 35 | localparam STA = 4'b0100; //Store register A to memory. 36 | localparam OUT = 4'b0101; //Send register A to UART port. The instruction 37 | //will block until the transfer completes. 38 | localparam JMP = 4'b0110; //Jump at some code location 39 | localparam LDI = 4'b0111; //Load 4'bit immediate value in register A. 40 | localparam JC = 4'b1000; //Jump if carry flag is set. 41 | localparam SHLA= 4'b1001; //Logical shift left of register A. 42 | localparam MULA= 4'b1010; //Unsigned multiplcation between two nibbles in register A. 43 | //Result is stored again in register A. 44 | localparam HLT = 4'b1111; //Halt CPU control clock; 45 | 46 | //Control signals 47 | localparam j = 0; //Program counter jump 48 | localparam co = 1; //Program counter output enable 49 | localparam ce = 2; //Program counter enable 50 | localparam oi = 3; //Display/UART tx 51 | localparam su = 4; //Subtract enable 52 | localparam ao = 5; //Register A read enable 53 | localparam io = 6; //Instruction register read enable 54 | localparam ro = 7; //RAM out 55 | localparam ri = 8; //RAM in 56 | localparam mi = 9; //Address in 57 | localparam she = 10; //Shift enable 58 | localparam mul = 11; //Multiply enable 59 | localparam SIG_COUNT = mul + 1; 60 | 61 | localparam STAGE_T0 = 0; 62 | localparam STAGE_T1 = 1; 63 | localparam STAGE_T2 = 2; 64 | localparam STAGE_T3 = 3; 65 | localparam STAGE_T4 = 4; 66 | localparam STAGE_COUNT = STAGE_T4 + 1; 67 | localparam STAGE_WIDTH = $clog2(STAGE_COUNT); 68 | 69 | localparam rst_size = 5; 70 | localparam rst_max = (1 << 5) - 1; 71 | 72 | reg [rst_size : 0] rst_cnt = 0; 73 | reg rstn = 0; 74 | reg [WIDTH-1 : 0] ir; //Instruction register. 75 | reg [SIG_COUNT-1 : 0] ctrl_reg; //Holds control signal status. 76 | reg [STAGE_WIDTH-1 : 0] stage_reg; //Keeps track of the current execution stage. 77 | reg [WIDTH-1 : 0] reg_a; //A CPU register 78 | reg [WIDTH-1 : 0] reg_b; //B CPU register 79 | reg carry_status; 80 | wire [WIDTH-1 : 0] alu_out; //ALU I/O 81 | wire alu_carry; // 82 | wire [ADDRESS_WIDTH-1 : 0] pc_in; //Program counter I/O 83 | wire [ADDRESS_WIDTH-1 : 0] pc_out; // 84 | wire [WIDTH-1 : 0] mem_in; //RAM I/O 85 | wire [WIDTH-1 : 0] mem_out; // 86 | wire [WIDTH-1 : 0] mem_addr; // 87 | wire tx_idle; //UART TX idle signal 88 | 89 | //CPU modules 90 | pcounter #(.ADDRESS_WIDTH(ADDRESS_WIDTH)) pc( 91 | .rst(!rstn), 92 | .clk(clk), 93 | .enable(ctrl_reg[ce]), 94 | .jump(ctrl_reg[j]), 95 | .out_enable(ctrl_reg[co]), 96 | .bus_in(pc_in), 97 | .bus_out(pc_out)); 98 | 99 | alu #(.WIDTH(WIDTH)) alu( 100 | .a(reg_a), 101 | .b(reg_b), 102 | .mul_enable(ctrl_reg[mul]), 103 | .sub_enable(ctrl_reg[su]), 104 | .shift_enable(ctrl_reg[she]), 105 | .shift_pos(ir[2 : 0]), 106 | .result(alu_out), 107 | .carry_out(alu_carry)); 108 | 109 | ram #(.WIDTH(WIDTH),.ADDRESS_WIDTH(ADDRESS_WIDTH)) memory( 110 | .clk(clk), 111 | .enable(ctrl_reg[ro]), 112 | .write_enable(ctrl_reg[ri]), 113 | .addr(mem_addr), 114 | .data_in(mem_in), 115 | .data_out(mem_out)); 116 | 117 | uarttx uart( 118 | .rst(!rstn), 119 | .clk(clk), 120 | .tx_start(ctrl_reg[oi]), 121 | .tx_byte(reg_a), 122 | .tx(uart_tx_wire), 123 | .tx_ready(tx_idle)); 124 | 125 | //Data transfer paths 126 | assign pc_in = (ctrl_reg[j] && ctrl_reg[io]) ? ir[ADDRESS_WIDTH-1 : 0] : 0; 127 | assign mem_addr = (ctrl_reg[mi] && ctrl_reg[io]) ? ir[ADDRESS_WIDTH-1 : 0] : 128 | (ctrl_reg[mi] && ctrl_reg[co]) ? pc_out : 0; 129 | assign mem_in = (ctrl_reg[ri] && ctrl_reg[ao]) ? reg_a : 0; 130 | 131 | always @(posedge clk) begin 132 | if (rst_cnt != rst_max) begin 133 | rst_cnt <= rst_cnt + 1; 134 | end else begin 135 | rstn <= 1; 136 | end 137 | end 138 | 139 | always @(posedge clk) begin 140 | if (rstn) begin 141 | case (stage_reg) 142 | STAGE_T0: begin 143 | ctrl_reg <= (1 << ro) | (1 << mi) | (1 << co); 144 | stage_reg <= STAGE_T1; 145 | end 146 | STAGE_T1: begin 147 | ctrl_reg <= 1 << ce; 148 | ir <= mem_out; 149 | stage_reg <= STAGE_T2; 150 | end 151 | STAGE_T2: begin 152 | case (ir[WIDTH-1 : ADDRESS_WIDTH]) 153 | MULA: begin 154 | ctrl_reg <= (1 << mul); 155 | stage_reg <= STAGE_T3; 156 | end 157 | SHLA: begin 158 | ctrl_reg <= (1 << she); 159 | stage_reg <= STAGE_T3; 160 | end 161 | LDA: begin 162 | ctrl_reg <= (1 << ro) | (1 << mi) | (1 << io); 163 | stage_reg <= STAGE_T3; 164 | end 165 | STA: begin 166 | ctrl_reg <= (1 << ri) | (1 << ao) | (1 << mi) | (1 << io); 167 | stage_reg <= STAGE_T0; 168 | end 169 | ADD: begin 170 | ctrl_reg <= (1 << ro) | (1 << mi) | (1 << io); 171 | stage_reg <= STAGE_T3; 172 | end 173 | SUB: begin 174 | ctrl_reg <= (1 << ro) | (1 << mi) | (1 << io); 175 | stage_reg <= STAGE_T3; 176 | end 177 | OUT: begin 178 | ctrl_reg <= 1 << oi; 179 | stage_reg <= STAGE_T3; 180 | end 181 | JMP: begin 182 | ctrl_reg <= (1 << j) | (1 << io); 183 | stage_reg <= STAGE_T0; 184 | end 185 | JC: begin 186 | if (carry_status) begin 187 | ctrl_reg <= (1 << j) | (1 << io); 188 | end else begin 189 | ctrl_reg <= 0; 190 | end 191 | stage_reg <= STAGE_T0; 192 | end 193 | LDI: begin 194 | ctrl_reg <= 0; 195 | reg_a <= {4'b0, ir[3 : 0]}; 196 | stage_reg <= STAGE_T0; 197 | end 198 | NOP: begin 199 | ctrl_reg <= 0; 200 | stage_reg <= STAGE_T0; 201 | end 202 | HLT: begin 203 | ctrl_reg <= 0; 204 | stage_reg <= STAGE_COUNT; 205 | end 206 | default: begin 207 | stage_reg <= STAGE_COUNT; 208 | end 209 | endcase 210 | end 211 | STAGE_T3: begin 212 | case (ir[WIDTH-1 : ADDRESS_WIDTH]) 213 | MULA: begin 214 | reg_a <= alu_out; 215 | carry_status <= alu_carry; 216 | stage_reg <= STAGE_T0; 217 | end 218 | SHLA: begin 219 | reg_a <= alu_out; 220 | carry_status <= alu_carry; 221 | stage_reg <= STAGE_T0; 222 | end 223 | LDA: begin 224 | reg_a <= mem_out; 225 | stage_reg <= STAGE_T0; 226 | end 227 | ADD: begin 228 | ctrl_reg <= 0; 229 | reg_b <= mem_out; 230 | stage_reg <= STAGE_T4; 231 | end 232 | SUB: begin 233 | ctrl_reg <= 1 << su; 234 | reg_b <= mem_out; 235 | stage_reg <= STAGE_T4; 236 | end 237 | OUT: begin 238 | ctrl_reg <= 0; 239 | if (tx_idle) begin 240 | stage_reg <= STAGE_T0; 241 | end else begin 242 | stage_reg <= STAGE_T3; 243 | end 244 | end 245 | default: begin 246 | stage_reg <= STAGE_COUNT; 247 | end 248 | endcase 249 | end 250 | STAGE_T4: begin 251 | case (ir[WIDTH-1 : ADDRESS_WIDTH]) 252 | ADD: begin 253 | reg_a <= alu_out; 254 | carry_status <= alu_carry; 255 | stage_reg <= STAGE_T0; 256 | end 257 | SUB: begin 258 | reg_a <= alu_out; 259 | stage_reg <= STAGE_T0; 260 | end 261 | default: begin 262 | stage_reg <= STAGE_COUNT; 263 | end 264 | endcase 265 | end 266 | default: begin 267 | stage_reg <= STAGE_COUNT; 268 | end 269 | endcase 270 | end else begin 271 | ir <= 0; 272 | carry_status <= 0; 273 | ctrl_reg <= 0; 274 | reg_a <= 0; 275 | reg_b <= 0; 276 | stage_reg <= STAGE_T0; 277 | end 278 | end 279 | endmodule 280 | -------------------------------------------------------------------------------- /fadder.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | module fadder( 18 | input [WIDTH-1 : 0] a, 19 | input [WIDTH - 1 : 0] b, 20 | input sub_enable, 21 | input carry_in, 22 | output [WIDTH - 1 : 0] res, 23 | output carry_out); 24 | 25 | parameter WIDTH = 8; 26 | wire [WIDTH - 1 : 0] carry; 27 | wire [WIDTH - 1 : 0] b_in; 28 | 29 | assign carry_out = carry[WIDTH-1]; 30 | assign b_in = sub_enable ? ~(b) : b; 31 | 32 | genvar i; 33 | generate 34 | for (i = 0; i < WIDTH; i = i + 1) begin 35 | if (i == 0) begin 36 | assign res[i] = (a[i] ^ b_in[i]) ^ carry_in; 37 | assign carry[i] = ((a[i] ^ b_in[i]) & carry_in) | (a[i] & b_in[i]); 38 | end else begin 39 | assign res[i] = (a[i] ^ b_in[i]) ^ carry[i-1]; 40 | assign carry[i] = ((a[i] ^ b_in[i]) & carry[i-1]) | (a[i] & b_in[i]); 41 | end 42 | end 43 | endgenerate 44 | 45 | endmodule 46 | -------------------------------------------------------------------------------- /mul4x4.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | `include "fadder.v" 18 | `include "shl8.v" 19 | 20 | module mul4x4( 21 | input [3 : 0] a, 22 | input [3 : 0] b, 23 | output [7 : 0] res); 24 | 25 | wire [2 : 0] shift_carry, sum_carry; 26 | wire [7 : 0] a0, a1, a2, a3, sum0, sum1; 27 | 28 | assign a0 = {4'b0, b[0] ? a : {3'b0}}; 29 | 30 | shl8 shifta1( 31 | .a({4'b0, b[1] ? a : {3'b0}}), 32 | .shift(3'b001), 33 | .res(a1), 34 | .carry(shift_carry[0])); 35 | 36 | shl8 shifta2( 37 | .a({4'b0, b[2] ? a : {3'b0}}), 38 | .shift(3'b010), 39 | .res(a2), 40 | .carry(shift_carry[1])); 41 | 42 | shl8 shifta3( 43 | .a({4'b0, b[3] ? a : {3'b0}}), 44 | .shift(3'b011), 45 | .res(a3), 46 | .carry(shift_carry[2])); 47 | 48 | fadder #(.WIDTH(8)) adder1( 49 | .a(a0), 50 | .b(a1), 51 | .sub_enable(1'b0), 52 | .carry_in(1'b0), 53 | .res(sum0), 54 | .carry_out(sum_carry[0])); 55 | 56 | fadder #(.WIDTH(8)) adder2( 57 | .a(sum0), 58 | .b(a2), 59 | .sub_enable(1'b0), 60 | .carry_in(1'b0), 61 | .res(sum1), 62 | .carry_out(sum_carry[1])); 63 | 64 | fadder #(.WIDTH(8)) adder3( 65 | .a(sum1), 66 | .b(a3), 67 | .sub_enable(1'b0), 68 | .carry_in(1'b0), 69 | .res(res), 70 | .carry_out(sum_carry[2])); 71 | 72 | endmodule 73 | -------------------------------------------------------------------------------- /pcounter.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | module pcounter( 18 | input rst, 19 | input clk, 20 | input enable, 21 | input jump, 22 | input out_enable, 23 | input [ADDRESS_WIDTH-1 : 0] bus_in, 24 | output [ADDRESS_WIDTH-1 : 0] bus_out); 25 | 26 | parameter ADDRESS_WIDTH = 4; 27 | reg [ADDRESS_WIDTH-1 : 0] counter; 28 | 29 | assign bus_out = (out_enable) ? counter : 0; 30 | 31 | always @(posedge clk) begin 32 | if (rst) begin 33 | counter <= 0; 34 | end else begin 35 | if (enable) begin 36 | counter <= counter + 1; 37 | end else if (jump) begin 38 | counter <= bus_in; 39 | end 40 | end 41 | end 42 | endmodule 43 | -------------------------------------------------------------------------------- /prog_add.list: -------------------------------------------------------------------------------- 1 | 0111_0000 //LDI 0 2 | 0010_1111 //ADD 15 3 | 0101_0000 //OUT 4 | 0110_0001 //JMP 1 5 | 0000_0000 6 | 0000_0000 7 | 0000_0000 8 | 0000_0000 9 | 0000_0000 10 | 0000_0000 11 | 0000_0000 12 | 0000_0000 13 | 0000_0000 14 | 0000_0000 15 | 0000_0000 16 | 0000_0001 17 | -------------------------------------------------------------------------------- /prog_fib.list: -------------------------------------------------------------------------------- 1 | 0111_0001 //LDI 1 2 | 0100_1110 //STA 14 3 | 0111_0000 //LDI 0 4 | 0010_1110 //ADD 14 5 | 1000_0000 //JC 0 6 | 0101_0000 //OUT 7 | 0100_1111 //STA 15 8 | 0001_1110 //LDA 14 9 | 0100_1101 //STA 13 10 | 0001_1111 //LDA 15 11 | 0100_1110 //STA 14 12 | 0001_1101 //LDA 13 13 | 0110_0011 //JMP 3 14 | 0000_0000 15 | 0000_0000 16 | 0000_0000 17 | -------------------------------------------------------------------------------- /prog_jump.list: -------------------------------------------------------------------------------- 1 | 0111_0001 //LDI 1 2 | 0101_0000 //OUT 3 | 0110_0110 //JMP 6 4 | 0111_0010 //LDI 2 5 | 0101_0000 //OUT 6 | 0110_0000 //JMP 0 7 | 0111_0011 //LDI 3 8 | 0101_0000 //OUT 9 | 0110_1100 //JMP 12 10 | 0111_0100 //LDI 4 11 | 0101_0000 //OUT 12 | 0110_0000 //JMP 0 13 | 0111_0101 //LDI 5 14 | 0101_0000 //OUT 15 | 0110_0000 //JMP 0 16 | 0000_0000 17 | -------------------------------------------------------------------------------- /prog_load_out.list: -------------------------------------------------------------------------------- 1 | 0111_0000 //LDI 0 2 | 0101_0000 //OUT 3 | 0111_0001 //LDI 1 4 | 0101_0000 //OUT 5 | 0111_0010 //LDI 2 6 | 0101_0000 //OUT 7 | 0111_0011 //LDI 3 8 | 0101_0000 //OUT 9 | 0111_0100 //LDI 4 10 | 0101_0000 //OUT 11 | 0111_0101 //LDI 5 12 | 0101_0000 //OUT 13 | 0111_0110 //LDI 6 14 | 0101_0000 //OUT 15 | 0110_0000 //JMP 0 16 | 0000_0000 17 | -------------------------------------------------------------------------------- /prog_load_store.list: -------------------------------------------------------------------------------- 1 | 0111_0001 //LDI 1 2 | 0100_1111 //STA 15 3 | 0111_0010 //LDI 2 4 | 0100_1110 //STA 14 5 | 0111_0011 //LDI 3 6 | 0100_1101 //STA 13 7 | 0001_1111 //LDA 15 8 | 0101_0000 //OUT 9 | 0001_1110 //LDA 14 10 | 0101_0000 //OUT 11 | 0001_1101 //LDA 13 12 | 0101_0000 //OUT 13 | 0110_0000 //JMP 0 14 | 0000_0000 15 | 0000_0000 16 | 0000_0000 17 | -------------------------------------------------------------------------------- /prog_mul.list: -------------------------------------------------------------------------------- 1 | 0111_0000 //LDI 0 2 | 0010_1111 //ADD 15 3 | 0100_1110 //STA 14 4 | 1010_0000 //MULA 5 | 0101_0000 //OUT 6 | 0001_1110 //LDA 14 7 | 0110_0001 //JMP 1 8 | 0000_0000 9 | 0000_0000 10 | 0000_0000 11 | 0000_0000 12 | 0000_0000 13 | 0000_0000 14 | 0000_0000 15 | 0000_0000 16 | 0000_0001 17 | -------------------------------------------------------------------------------- /prog_shl.list: -------------------------------------------------------------------------------- 1 | 0111_0001 //LDI 1 2 | 0101_0000 //OUT 3 | 1001_0001 //SHLA 1 4 | 0110_0001 //JMP 1 5 | 0000_0000 6 | 0000_0000 7 | 0000_0000 8 | 0000_0000 9 | 0000_0000 10 | 0000_0000 11 | 0000_0000 12 | 0000_0000 13 | 0000_0000 14 | 0000_0000 15 | 0000_0000 16 | 0000_0000 17 | -------------------------------------------------------------------------------- /prog_sub.list: -------------------------------------------------------------------------------- 1 | 0001_1110 //LDA 14 2 | 0011_1111 //SUB 15 3 | 0101_0000 //OUT 4 | 0110_0001 //JMP 1 5 | 0000_0000 6 | 0000_0000 7 | 0000_0000 8 | 0000_0000 9 | 0000_0000 10 | 0000_0000 11 | 0000_0000 12 | 0000_0000 13 | 0000_0000 14 | 0000_0000 15 | 1111_1111 16 | 0000_0001 17 | -------------------------------------------------------------------------------- /ram.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | module ram( 18 | input clk, 19 | input enable, 20 | input write_enable, 21 | input [WIDTH-1 : 0] addr, 22 | input [WIDTH-1 : 0] data_in, 23 | output [WIDTH-1 : 0] data_out); 24 | 25 | parameter ADDRESS_WIDTH = 4; 26 | parameter WIDTH = 8; 27 | parameter MEMORY_SIZE = 1 << ADDRESS_WIDTH; 28 | reg [WIDTH-1 : 0] mem [0 : MEMORY_SIZE-1]; 29 | 30 | initial begin 31 | `ifdef IVERILOG_SIM 32 | $readmemb(`TEST_PROG, mem); 33 | `else 34 | $readmemb("prog_fib.list", mem); 35 | `endif 36 | end 37 | 38 | assign data_out = (enable) ? mem[addr] : {WIDTH{1'b0}}; 39 | 40 | always @(posedge clk) begin 41 | if (write_enable) begin 42 | mem[addr] <= data_in; 43 | end 44 | end 45 | endmodule 46 | -------------------------------------------------------------------------------- /shl8.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | module shl8( 18 | input [7 : 0] a, 19 | input [2 : 0] shift, 20 | output [7 : 0] res, 21 | output carry); 22 | assign {carry, res} = (shift == 3'b000) ? {1'b0, a} : 23 | (shift == 3'b001) ? {a[7 : 0], {1'b0}}: 24 | (shift == 3'b010) ? {a[6 : 0], {2'b0}}: 25 | (shift == 3'b011) ? {a[5 : 0], {3'b0}}: 26 | (shift == 3'b100) ? {a[4 : 0], {4'b0}}: 27 | (shift == 3'b101) ? {a[3 : 0], {5'b0}}: 28 | (shift == 3'b110) ? {a[2 : 0], {6'b0}}: 29 | {a[1 : 0], {7'b0}}; 30 | endmodule 31 | -------------------------------------------------------------------------------- /top.pcf: -------------------------------------------------------------------------------- 1 | set_io clk 21 2 | set_io uart_tx_line 8 3 | -------------------------------------------------------------------------------- /top.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | `include "cpu.v" 18 | 19 | module top( 20 | input clk, 21 | output uart_tx_line); 22 | 23 | cpu node( 24 | .clk(clk), 25 | .uart_tx_wire(uart_tx_line)); 26 | 27 | endmodule 28 | -------------------------------------------------------------------------------- /top_test_add.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | `define IVERILOG_SIM 18 | `define TEST_PROG "prog_add.list" 19 | `include "top.v" 20 | 21 | module top_test_add; 22 | 23 | localparam WIDTH = 8; 24 | localparam UART_WIDTH = $clog2(WIDTH); 25 | localparam OUTPUT_CNT = (1 << WIDTH) - 1; 26 | 27 | reg clk = 1; 28 | reg uart_clk = 0; 29 | reg receiving = 0; 30 | reg display = 0; 31 | reg [UART_WIDTH-1 : 0] serial_cnt = 0; 32 | reg [WIDTH-1 : 0] serial_data; 33 | wire uart_tx; 34 | 35 | reg [WIDTH : 0] expected_output = 1; 36 | 37 | always #2 clk = !clk; 38 | always #4 uart_clk = !uart_clk; 39 | 40 | top t( 41 | .clk(clk), 42 | .uart_tx_line(uart_tx)); 43 | 44 | always @ (posedge uart_clk) begin 45 | if (receiving) begin 46 | 47 | if (serial_cnt == WIDTH - 1 ) begin 48 | receiving <= 0; 49 | display <= 1; 50 | end 51 | 52 | serial_data[serial_cnt] <= uart_tx; 53 | serial_cnt <= serial_cnt + 1; 54 | 55 | end else if (display) begin 56 | 57 | if (expected_output >= OUTPUT_CNT) begin 58 | $display("Add test passed!\n"); 59 | $finish; 60 | end 61 | 62 | if (serial_data != expected_output) begin 63 | $display("Add test failed!\n"); 64 | $display("Serial output:%d doesn't match expected_output:%d\n", 65 | serial_data, expected_output); 66 | $finish; 67 | end 68 | 69 | expected_output <= expected_output + 1; 70 | display <= 0; 71 | 72 | end else begin 73 | 74 | if (uart_tx == 0) begin 75 | receiving <= 1; 76 | end 77 | 78 | end 79 | end 80 | 81 | endmodule 82 | -------------------------------------------------------------------------------- /top_test_fibonacci.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | `define IVERILOG_SIM 18 | `define TEST_PROG "prog_fib.list" 19 | `include "top.v" 20 | 21 | module top_test_fibonacci; 22 | 23 | localparam WIDTH = 8; 24 | localparam UART_WIDTH = $clog2(WIDTH); 25 | localparam OUTPUT_CNT = 12; 26 | 27 | reg clk = 1; 28 | reg uart_clk = 0; 29 | reg receiving = 0; 30 | reg display = 0; 31 | reg [UART_WIDTH-1 : 0] serial_cnt = 0; 32 | reg [WIDTH-1 : 0] serial_data; 33 | reg [WIDTH-1 : 0] expected_output [OUTPUT_CNT-1 : 0]; 34 | wire uart_tx; 35 | 36 | reg [WIDTH-1 : 0] i, j, k, l; 37 | initial begin 38 | j = 1; 39 | k = 1; 40 | l = 0; 41 | for (i = 0; i < OUTPUT_CNT; i = i + 1) begin 42 | expected_output[i] = k; 43 | l = k; 44 | k = k + j; 45 | j = l; 46 | end 47 | i = 0; 48 | end 49 | 50 | always #2 clk = !clk; 51 | always #4 uart_clk = !uart_clk; 52 | 53 | top t( 54 | .clk(clk), 55 | .uart_tx_line(uart_tx)); 56 | 57 | initial begin 58 | $dumpfile("top_test_fibonacci.vcd"); 59 | $dumpvars; 60 | end 61 | 62 | always @ (posedge uart_clk) begin 63 | if (receiving) begin 64 | 65 | if (serial_cnt == WIDTH - 1 ) begin 66 | receiving <= 0; 67 | display <= 1; 68 | end 69 | 70 | serial_data[serial_cnt] <= uart_tx; 71 | serial_cnt <= serial_cnt + 1; 72 | 73 | end else if (display) begin 74 | 75 | if (i >= OUTPUT_CNT) begin 76 | $display("Fibonacci test passed, computed results match the expected output!\n"); 77 | $finish; 78 | end 79 | 80 | if (serial_data != expected_output[i]) begin 81 | $display("Fibonacci test failed!\n"); 82 | $display("Serial output:%d doesn't match expected_output[%d]:%d\n", 83 | serial_data, i, expected_output[i]); 84 | $finish; 85 | end 86 | 87 | i <= i + 1; 88 | display <= 0; 89 | 90 | end else begin 91 | 92 | if (uart_tx == 0) begin 93 | receiving <= 1; 94 | end 95 | 96 | end 97 | end 98 | 99 | endmodule 100 | -------------------------------------------------------------------------------- /top_test_jump.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | `define IVERILOG_SIM 18 | `define TEST_PROG "prog_jump.list" 19 | `include "top.v" 20 | 21 | module top_test_jump; 22 | 23 | localparam WIDTH = 8; 24 | localparam UART_WIDTH = $clog2(WIDTH); 25 | localparam OUTPUT_CNT = 5; 26 | 27 | reg clk = 1; 28 | reg uart_clk = 0; 29 | reg receiving = 0; 30 | reg display = 0; 31 | reg [UART_WIDTH-1 : 0] serial_cnt = 0; 32 | reg [WIDTH-1 : 0] serial_data; 33 | wire uart_tx; 34 | 35 | reg [WIDTH-1 : 0] expected_output = 1; 36 | 37 | always #2 clk = !clk; 38 | always #4 uart_clk = !uart_clk; 39 | 40 | top t( 41 | .clk(clk), 42 | .uart_tx_line(uart_tx)); 43 | 44 | always @ (posedge uart_clk) begin 45 | if (receiving) begin 46 | 47 | if (serial_cnt == WIDTH - 1 ) begin 48 | receiving <= 0; 49 | display <= 1; 50 | end 51 | 52 | serial_data[serial_cnt] <= uart_tx; 53 | serial_cnt <= serial_cnt + 1; 54 | 55 | end else if (display) begin 56 | 57 | if (expected_output >= OUTPUT_CNT) begin 58 | $display("Jump test passed!\n"); 59 | $finish; 60 | end 61 | 62 | if (serial_data != expected_output) begin 63 | $display("Jump test failed!\n"); 64 | $display("Serial output:%d doesn't match expected_output:%d\n", 65 | serial_data, expected_output); 66 | $finish; 67 | end 68 | 69 | expected_output <= expected_output + 2; 70 | display <= 0; 71 | 72 | end else begin 73 | 74 | if (uart_tx == 0) begin 75 | receiving <= 1; 76 | end 77 | 78 | end 79 | end 80 | 81 | endmodule 82 | -------------------------------------------------------------------------------- /top_test_load_out.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | `define IVERILOG_SIM 18 | `define TEST_PROG "prog_load_out.list" 19 | `include "top.v" 20 | 21 | module top_test_load_out; 22 | 23 | localparam WIDTH = 8; 24 | localparam UART_WIDTH = $clog2(WIDTH); 25 | localparam OUTPUT_CNT = 7; 26 | 27 | reg clk = 1; 28 | reg uart_clk = 0; 29 | reg receiving = 0; 30 | reg display = 0; 31 | reg [UART_WIDTH-1 : 0] serial_cnt = 0; 32 | reg [WIDTH-1 : 0] serial_data; 33 | wire uart_tx; 34 | 35 | reg [WIDTH-1 : 0] expected_output = 0; 36 | 37 | always #2 clk = !clk; 38 | always #4 uart_clk = !uart_clk; 39 | 40 | top t( 41 | .clk(clk), 42 | .uart_tx_line(uart_tx)); 43 | 44 | always @ (posedge uart_clk) begin 45 | if (receiving) begin 46 | 47 | if (serial_cnt == WIDTH - 1 ) begin 48 | receiving <= 0; 49 | display <= 1; 50 | end 51 | 52 | serial_data[serial_cnt] <= uart_tx; 53 | serial_cnt <= serial_cnt + 1; 54 | 55 | end else if (display) begin 56 | 57 | if (expected_output >= OUTPUT_CNT) begin 58 | $display("Load and output test passed!\n"); 59 | $finish; 60 | end 61 | 62 | if (serial_data != expected_output) begin 63 | $display("Load and output test failed!\n"); 64 | $display("Serial output:%d doesn't match expected_output:%d\n", 65 | serial_data, expected_output); 66 | $finish; 67 | end 68 | 69 | expected_output <= expected_output + 1; 70 | display <= 0; 71 | 72 | end else begin 73 | 74 | if (uart_tx == 0) begin 75 | receiving <= 1; 76 | end 77 | 78 | end 79 | end 80 | 81 | endmodule 82 | -------------------------------------------------------------------------------- /top_test_load_store.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | `define IVERILOG_SIM 18 | `define TEST_PROG "prog_load_store.list" 19 | `include "top.v" 20 | 21 | module top_test_load_store; 22 | 23 | localparam WIDTH = 8; 24 | localparam UART_WIDTH = $clog2(WIDTH); 25 | localparam OUTPUT_CNT = 3; 26 | 27 | reg clk = 1; 28 | reg uart_clk = 0; 29 | reg receiving = 0; 30 | reg display = 0; 31 | reg [UART_WIDTH-1 : 0] serial_cnt = 0; 32 | reg [WIDTH-1 : 0] serial_data; 33 | wire uart_tx; 34 | 35 | reg [WIDTH-1 : 0] expected_output = 1; 36 | 37 | always #2 clk = !clk; 38 | always #4 uart_clk = !uart_clk; 39 | 40 | top t( 41 | .clk(clk), 42 | .uart_tx_line(uart_tx)); 43 | 44 | always @ (posedge uart_clk) begin 45 | if (receiving) begin 46 | 47 | if (serial_cnt == WIDTH - 1) begin 48 | receiving <= 0; 49 | display <= 1; 50 | end 51 | 52 | serial_data[serial_cnt] <= uart_tx; 53 | serial_cnt <= serial_cnt + 1; 54 | 55 | end else if (display) begin 56 | 57 | if (expected_output >= OUTPUT_CNT) begin 58 | $display("Load and store test passed!\n"); 59 | $finish; 60 | end 61 | 62 | if (serial_data != expected_output) begin 63 | $display("Load and store test failed!\n"); 64 | $display("Serial output:%d doesn't match expected_output:%d\n", 65 | serial_data, expected_output); 66 | $finish; 67 | end 68 | 69 | expected_output <= expected_output + 1; 70 | display <= 0; 71 | 72 | end else begin 73 | 74 | if (uart_tx == 0) begin 75 | receiving <= 1; 76 | end 77 | 78 | end 79 | end 80 | 81 | endmodule 82 | -------------------------------------------------------------------------------- /top_test_mul.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | `define IVERILOG_SIM 18 | `define TEST_PROG "prog_mul.list" 19 | `include "top.v" 20 | 21 | module top_test_mul; 22 | 23 | localparam WIDTH = 8; 24 | localparam UART_WIDTH = $clog2(WIDTH); 25 | localparam MUL_WIDTH = WIDTH / 2; 26 | 27 | reg clk = 1; 28 | reg uart_clk = 0; 29 | reg receiving = 0; 30 | reg display = 0; 31 | reg [UART_WIDTH-1 : 0] serial_cnt = 0; 32 | reg [WIDTH-1 : 0] serial_data; 33 | wire uart_tx; 34 | 35 | reg [WIDTH-1 : 0] in_args = 2; 36 | reg [WIDTH-1 : 0] expected_output = 0; 37 | 38 | always #2 clk = !clk; 39 | always #4 uart_clk = !uart_clk; 40 | 41 | top t( 42 | .clk(clk), 43 | .uart_tx_line(uart_tx)); 44 | 45 | always @ (posedge uart_clk) begin 46 | if (receiving) begin 47 | 48 | if (serial_cnt == WIDTH - 1) begin 49 | receiving <= 0; 50 | display <= 1; 51 | end 52 | 53 | serial_data[serial_cnt] <= uart_tx; 54 | serial_cnt <= serial_cnt + 1; 55 | 56 | end else if (display) begin 57 | 58 | if (in_args == 0) begin 59 | $display("Multiply4x4 test passed!\n"); 60 | $finish; 61 | end 62 | 63 | if (serial_data != expected_output) begin 64 | $display("Multiply4x4 test failed!\n"); 65 | $display("Serial output:%d doesn't match expected_output:%d\n", 66 | serial_data, expected_output); 67 | $finish; 68 | end 69 | 70 | in_args <= in_args + 1; 71 | expected_output <= in_args[WIDTH-1 : MUL_WIDTH] * in_args[MUL_WIDTH-1 : 0]; 72 | display <= 0; 73 | 74 | end else begin 75 | 76 | if (uart_tx == 0) begin 77 | receiving <= 1; 78 | end 79 | 80 | end 81 | end 82 | 83 | endmodule 84 | -------------------------------------------------------------------------------- /top_test_shl.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | `define IVERILOG_SIM 18 | `define TEST_PROG "prog_shl.list" 19 | `include "top.v" 20 | 21 | module top_test_shl; 22 | 23 | localparam WIDTH = 8; 24 | localparam UART_WIDTH = $clog2(WIDTH); 25 | localparam OUTPUT_CNT = (1 << WIDTH) - 1; 26 | 27 | reg clk = 1; 28 | reg uart_clk = 0; 29 | reg receiving = 0; 30 | reg display = 0; 31 | reg [UART_WIDTH-1 : 0] serial_cnt = 0; 32 | reg [WIDTH-1 : 0] serial_data; 33 | wire uart_tx; 34 | 35 | reg [WIDTH-1 : 0] expected_output = 1; 36 | 37 | always #2 clk = !clk; 38 | always #4 uart_clk = !uart_clk; 39 | 40 | top t( 41 | .clk(clk), 42 | .uart_tx_line(uart_tx)); 43 | 44 | always @ (posedge uart_clk) begin 45 | if (receiving) begin 46 | 47 | if (serial_cnt == WIDTH - 1) begin 48 | receiving <= 0; 49 | display <= 1; 50 | end 51 | 52 | serial_data[serial_cnt] <= uart_tx; 53 | serial_cnt <= serial_cnt + 1; 54 | 55 | end else if (display) begin 56 | 57 | if (expected_output == 0) begin 58 | $display("Shift left test passed!\n"); 59 | $finish; 60 | end 61 | 62 | if (serial_data != expected_output) begin 63 | $display("Shift left test failed!\n"); 64 | $display("Serial output:%d doesn't match expected_output:%d\n", 65 | serial_data, expected_output); 66 | $finish; 67 | end 68 | 69 | expected_output <= expected_output << 1; 70 | display <= 0; 71 | 72 | end else begin 73 | 74 | if (uart_tx == 0) begin 75 | receiving <= 1; 76 | end 77 | 78 | end 79 | end 80 | 81 | endmodule 82 | -------------------------------------------------------------------------------- /top_test_sub.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | `define IVERILOG_SIM 18 | `define TEST_PROG "prog_sub.list" 19 | `include "top.v" 20 | 21 | module top_test_sub; 22 | 23 | localparam WIDTH = 8; 24 | localparam UART_WIDTH = $clog2(WIDTH); 25 | localparam OUTPUT_CNT = (1 << WIDTH) - 1; 26 | 27 | reg clk = 1; 28 | reg uart_clk = 0; 29 | reg receiving = 0; 30 | reg display = 0; 31 | reg [UART_WIDTH-1 : 0] serial_cnt = 0; 32 | reg [WIDTH-1 : 0] serial_data; 33 | wire uart_tx; 34 | 35 | reg [WIDTH-1 : 0] expected_output = OUTPUT_CNT-1; 36 | 37 | always #2 clk = !clk; 38 | always #4 uart_clk = !uart_clk; 39 | 40 | top t( 41 | .clk(clk), 42 | .uart_tx_line(uart_tx)); 43 | 44 | always @ (posedge uart_clk) begin 45 | if (receiving) begin 46 | 47 | if (serial_cnt == WIDTH - 1) begin 48 | receiving <= 0; 49 | display <= 1; 50 | end 51 | 52 | serial_data[serial_cnt] <= uart_tx; 53 | serial_cnt <= serial_cnt + 1; 54 | 55 | end else if (display) begin 56 | 57 | if (expected_output == 0) begin 58 | $display("Subtract test passed!\n"); 59 | $finish; 60 | end 61 | 62 | if (serial_data != expected_output) begin 63 | $display("Subtract test failed!\n"); 64 | $display("Serial output:%d doesn't match expected_output:%d\n", 65 | serial_data, expected_output); 66 | $finish; 67 | end 68 | 69 | expected_output <= expected_output - 1; 70 | display <= 0; 71 | 72 | end else begin 73 | 74 | if (uart_tx == 0) begin 75 | receiving <= 1; 76 | end 77 | 78 | end 79 | end 80 | 81 | endmodule 82 | -------------------------------------------------------------------------------- /uart-tx.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | module uarttx( 18 | input rst, 19 | input clk, 20 | input tx_start, 21 | input [7 : 0] tx_byte, 22 | output tx, output tx_ready); 23 | 24 | localparam STATE_IDLE = 0; 25 | localparam STATE_START_BYTE = 1; 26 | localparam STATE_BYTE_1 = 2; 27 | localparam STATE_BYTE_2 = 3; 28 | localparam STATE_BYTE_3 = 4; 29 | localparam STATE_BYTE_4 = 5; 30 | localparam STATE_BYTE_5 = 6; 31 | localparam STATE_BYTE_6 = 7; 32 | localparam STATE_BYTE_7 = 8; 33 | localparam STATE_BYTE_8 = 9; 34 | localparam STATE_STOP_BYTE1 = 10; 35 | localparam STATE_STOP_BYTE2 = 11; 36 | localparam STATE_FINISH = 12; 37 | localparam STATE_WIDTH = $clog2(STATE_FINISH); 38 | 39 | parameter CLK_SPEED = 12000000; //Hz 40 | `ifdef IVERILOG_SIM 41 | parameter BAUD_RATE = CLK_SPEED / 2; 42 | `else 43 | parameter BAUD_RATE = 19200; 44 | `endif 45 | localparam BAUD_COUNT = CLK_SPEED / BAUD_RATE; 46 | localparam BAUD_REG_SIZE = $clog2(BAUD_COUNT); 47 | reg [BAUD_REG_SIZE-1 : 0] baud_counter; 48 | reg [STATE_WIDTH-1 : 0] tx_state; 49 | reg tx_val; 50 | reg [7 : 0] value; 51 | 52 | assign tx_ready = (tx_state != STATE_IDLE) || (tx_start) ? 0 : 1; 53 | assign tx = (tx_state == STATE_IDLE) ? 1 : tx_val; 54 | 55 | always @(posedge clk) begin 56 | if (rst) begin 57 | tx_state <= 0; 58 | tx_val <= 0; 59 | baud_counter <= 0; 60 | value <= 0; 61 | end else begin 62 | if (baud_counter == BAUD_COUNT) begin 63 | baud_counter <= 0; 64 | end else if (tx_state != STATE_IDLE) begin 65 | baud_counter <= baud_counter + 1; 66 | end 67 | 68 | case (tx_state) 69 | STATE_IDLE: begin 70 | if (tx_start) begin 71 | tx_state <= STATE_START_BYTE; 72 | tx_val <= 1; 73 | value <= tx_byte; 74 | end 75 | end 76 | STATE_START_BYTE: begin 77 | if (baud_counter == 0) begin 78 | tx_val <= 0; 79 | tx_state <= STATE_BYTE_1; 80 | end 81 | end 82 | STATE_BYTE_1: begin 83 | if (baud_counter == 0) begin 84 | tx_val <= value[0]; 85 | tx_state <= STATE_BYTE_2; 86 | end 87 | end 88 | STATE_BYTE_2: begin 89 | if (baud_counter == 0) begin 90 | tx_val <= value[1]; 91 | tx_state <= STATE_BYTE_3; 92 | end 93 | end 94 | STATE_BYTE_3: begin 95 | if (baud_counter == 0) begin 96 | tx_val <= value[2]; 97 | tx_state <= STATE_BYTE_4; 98 | end 99 | end 100 | STATE_BYTE_4: begin 101 | if (baud_counter == 0) begin 102 | tx_val <= value[3]; 103 | tx_state <= STATE_BYTE_5; 104 | end 105 | end 106 | STATE_BYTE_5: begin 107 | if (baud_counter == 0) begin 108 | tx_val <= value[4]; 109 | tx_state <= STATE_BYTE_6; 110 | end 111 | end 112 | STATE_BYTE_6: begin 113 | if (baud_counter == 0) begin 114 | tx_val <= value[5]; 115 | tx_state <= STATE_BYTE_7; 116 | end 117 | end 118 | STATE_BYTE_7: begin 119 | if (baud_counter == 0) begin 120 | tx_val <= value[6]; 121 | tx_state <= STATE_BYTE_8; 122 | end 123 | end 124 | STATE_BYTE_8: begin 125 | if (baud_counter == 0) begin 126 | tx_val <= value[7]; 127 | tx_state <= STATE_STOP_BYTE1; 128 | end 129 | end 130 | STATE_STOP_BYTE1: begin 131 | if (baud_counter == 0) begin 132 | tx_val <= 1; 133 | tx_state <= STATE_STOP_BYTE2; 134 | end 135 | end 136 | STATE_STOP_BYTE2: begin 137 | if (baud_counter == 0) begin 138 | tx_val <= 1; 139 | tx_state <= STATE_FINISH; 140 | end 141 | end 142 | STATE_FINISH : begin 143 | tx_state <= STATE_IDLE; 144 | end 145 | default: begin 146 | tx_state <= STATE_IDLE; 147 | end 148 | endcase 149 | end 150 | end 151 | endmodule 152 | --------------------------------------------------------------------------------