diff --git a/designs/.lastupdated b/designs/.lastupdated new file mode 100644 index 0000000..4d7b8c3 --- /dev/null +++ b/designs/.lastupdated @@ -0,0 +1 @@ +2023-05-14 diff --git a/designs/d10_wabib_tictactoe/.lastupdated b/designs/d10_wabib_tictactoe/.lastupdated new file mode 100644 index 0000000..4d7b8c3 --- /dev/null +++ b/designs/d10_wabib_tictactoe/.lastupdated @@ -0,0 +1 @@ +2023-05-14 diff --git a/designs/d10_wabib_tictactoe/LICENSE b/designs/d10_wabib_tictactoe/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/designs/d10_wabib_tictactoe/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/designs/d10_wabib_tictactoe/README.md b/designs/d10_wabib_tictactoe/README.md new file mode 100644 index 0000000..ed593e8 --- /dev/null +++ b/designs/d10_wabib_tictactoe/README.md @@ -0,0 +1,26 @@ +# Tic-Tac-Toe + +Wahib Abib +18-224/624 Spring 2023 Final Tapeout Project + +## Overview + +The classic game of Tic-Tac-Toe on an ASIC, with a built in game AI if the user wants to play by themselves. The chip also supports 2 players competing agasint each other. + +## How it Works + +The user will first select how many players the game will have by flipping the on-board switch. The user can select what move they would like to make on the Tic-Tac-Toe board by pressing the buttons on the game board. If the move is invalid, the position was already selected, then the user has to select another move. During 1-player mode, the AI will select its move which will be displayed on the game board. During 2-player mode, the next player will be allowed to make their next move. When there is a winner, the game board will reset and and the user will have to press the start button the start a new game. + +## Inputs/Outputs + +The chip uses an external clock input at 2MHz + +9 of the inputs are used for the 9 positions on the tic tac toe board (b0-b8) which are driven by the on-board buttons, 1 input is for selecting 1 or 2 player mode (player_sel), and 1 input is to start the game (start). 9 of the outputs are used to drive onboard LEDs to display the player’s move (led0-led8). + +## Hardware Peripherals + +There will be 9 on-board buttons for each possible move, 9 on-board LED's to display the current game board, and 1 on-board switch to select the number of players + +## Design Testing / Bringup + +Once the game board is constructed, the chip can be tested by simply pressing the start button and pressing the on-board positions buttons to see if the move was registered and displayed. diff --git a/designs/d10_wabib_tictactoe/info.yaml b/designs/d10_wabib_tictactoe/info.yaml new file mode 100644 index 0000000..fc928e1 --- /dev/null +++ b/designs/d10_wabib_tictactoe/info.yaml @@ -0,0 +1,7 @@ +--- +project: + source_files: + - toplevel_chip.v + - chip.sv + - ttt.sv + top_module: "toplevel_chip" diff --git a/designs/d10_wabib_tictactoe/src/chip.sv b/designs/d10_wabib_tictactoe/src/chip.sv new file mode 100644 index 0000000..4b0e6a6 --- /dev/null +++ b/designs/d10_wabib_tictactoe/src/chip.sv @@ -0,0 +1,35 @@ +`default_nettype none + +module my_chip ( + input logic [11:0] io_in, // Inputs to your chip + output logic [11:0] io_out, // Outputs from your chip + input logic clock, + input logic reset // Important: Reset is ACTIVE-HIGH +); + + ttt_game_control ttt(.b0(io_in[0]), + .b1(io_in[1]), + .b2(io_in[2]), + .b3(io_in[3]), + .b4(io_in[4]), + .b5(io_in[5]), + .b6(io_in[6]), + .b7(io_in[7]), + .b8(io_in[8]), + .player_sel(io_in[9]), + .start(io_in[10]), + .led0(io_out[0]), + .led1(io_out[1]), + .led2(io_out[2]), + .led3(io_out[3]), + .led4(io_out[4]), + .led5(io_out[5]), + .led6(io_out[6]), + .led7(io_out[7]), + .led8(io_out[8]), + .clk(clock), + .reset(reset)); + + assign io_out[11:9] = 3'd0; + +endmodule diff --git a/designs/d10_wabib_tictactoe/src/config.tcl b/designs/d10_wabib_tictactoe/src/config.tcl new file mode 100644 index 0000000..aa589e4 --- /dev/null +++ b/designs/d10_wabib_tictactoe/src/config.tcl @@ -0,0 +1,68 @@ +# PLEASE DO NOT EDIT THIS FILE! +# IT WILL MAKE YOUR CHIP UNMANUFACTURABLE +# The only line you may edit is FP_CORE_UTIL +# (may benefit from reducing it slightly) + +# User config +set script_dir [file dirname [file normalize [info script]]] + +# read some user config that is written by the setup.py program. +# - the name of the module is defined +# - the list of source files +source $::env(DESIGN_DIR)/user_config.tcl + +# save some time +set ::env(RUN_KLAYOUT_XOR) 0 +set ::env(RUN_KLAYOUT_DRC) 0 + +# don't put clock buffers on the outputs +set ::env(PL_RESIZER_BUFFER_OUTPUT_PORTS) 0 + +# allow use of specific sky130 cells +set ::env(SYNTH_READ_BLACKBOX_LIB) 1 + +# put all the pins on the left +set ::env(FP_PIN_ORDER_CFG) $::env(DESIGN_DIR)/pin_order.cfg + +# reduce wasted space +set ::env(TOP_MARGIN_MULT) 2 +set ::env(BOTTOM_MARGIN_MULT) 2 + +# absolute die size +set ::env(FP_SIZING) absolute +set ::env(DIE_AREA) "0 0 280 280" + +## THIS IS THE ONLY LINE YOU CAN EDIT +set ::env(FP_CORE_UTIL) 45 + +## set ::env(PL_BASIC_PLACEMENT) {1} + +set ::env(FP_IO_HLENGTH) 2 +set ::env(FP_IO_VLENGTH) 2 + +# use alternative efabless decap cells to solve LI density issue +set ::env(DECAP_CELL) "\ + sky130_fd_sc_hd__decap_3 \ + sky130_fd_sc_hd__decap_4 \ + sky130_fd_sc_hd__decap_6 \ + sky130_fd_sc_hd__decap_8 \ + sky130_ef_sc_hd__decap_12" + +# clock +set ::env(CLOCK_TREE_SYNTH) 1 + +# period is in ns, so 500ns == 2 MHz +set ::env(CLOCK_PERIOD) "500" +set ::env(CLOCK_PORT) {io_in[12]} + +# hold/slack margin +# set ::env(PL_RESIZER_HOLD_SLACK_MARGIN) 0.8 +# set ::env(GLB_RESIZER_HOLD_SLACK_MARGIN) 0.8 + +# don't use power rings or met5 +set ::env(DESIGN_IS_CORE) 0 +set ::env(RT_MAX_LAYER) {met4} + +# connect to first digital rails +set ::env(VDD_NETS) [list {vccd1}] +set ::env(GND_NETS) [list {vssd1}] diff --git a/designs/d10_wabib_tictactoe/src/pin_order.cfg b/designs/d10_wabib_tictactoe/src/pin_order.cfg new file mode 100644 index 0000000..0b85c63 --- /dev/null +++ b/designs/d10_wabib_tictactoe/src/pin_order.cfg @@ -0,0 +1,9 @@ +#N + +#S + +#E + +#W +io_in.* +io_out.* diff --git a/designs/d10_wabib_tictactoe/src/toplevel_chip.v b/designs/d10_wabib_tictactoe/src/toplevel_chip.v new file mode 100644 index 0000000..a82b427 --- /dev/null +++ b/designs/d10_wabib_tictactoe/src/toplevel_chip.v @@ -0,0 +1,18 @@ +`default_nettype none + +// DO NOT EDIT THIS FILE +module toplevel_chip ( + input [13:0] io_in, + output [13:0] io_out +); + + my_chip mchip ( + .io_in(io_in[11:0]), + .io_out(io_out[11:0]), + .clock(io_in[12]), + .reset(io_in[13]) + ); + + assign io_out[13:12] = 2'b00; + +endmodule diff --git a/designs/d10_wabib_tictactoe/src/ttt.sv b/designs/d10_wabib_tictactoe/src/ttt.sv new file mode 100644 index 0000000..542dbc3 --- /dev/null +++ b/designs/d10_wabib_tictactoe/src/ttt.sv @@ -0,0 +1,624 @@ +module Register + #(parameter WIDTH = 3) + (input logic [WIDTH-1:0] D, + input logic en, clear, clock, + output logic [WIDTH-1:0] Q); + + always_ff @(posedge clock) + if (clear) Q <= '0; + else if (en) Q <= D; + else Q <= Q; + +endmodule: Register + +module random_number ( + input logic clear, clock, + output logic [3:0] Q +); + + logic val; + assign val = Q[3] ^ Q[0]; + + always_ff @(posedge clock) + if (clear) Q <= 4'hf; + else Q <= {Q[2:0], val}; + +endmodule: random_number + +module ttt_game_control ( + input logic b0, b1, b2, b3, b4, b5, b6, b7, b8, player_sel, start, + input logic clk, reset, + output logic led0, led1, led2, led3, led4, led5, led6, led7, led8 +); + + logic [8:0] game_state, p1_state, p2_state, game_state_reg, p1_state_reg, p2_state_reg; + logic [3:0] index; + logic curr_player, button_pressed, new_game, finished, next, led0_en, led1_en, led2_en, led3_en, led4_en, led5_en, + led6_en, led7_en, led8_en, game_state_en, p1_state_en, p2_state_en, led0_reg, led1_reg, led2_reg, led3_reg, + led4_reg, led5_reg, led6_reg, led7_reg, led8_reg, b0_reg0, b0_reg1, b1_reg0, b1_reg1, b2_reg0, b2_reg1, + b3_reg0, b3_reg1, b4_reg0, b4_reg1, b5_reg0, b5_reg1, b6_reg0, b6_reg1, b7_reg0, b7_reg1, b8_reg0, b8_reg1; + + Register #(1) db0_0(.D(b0), .Q(b0_reg0), .en(1'b1), .clear(reset), .clock(clk)); + Register #(1) db0_1(.D(b0_reg0), .Q(b0_reg1), .en(1'b1), .clear(reset), .clock(clk)); + + Register #(1) d1_0(.D(b1), .Q(b1_reg0), .en(1'b1), .clear(reset), .clock(clk)); + Register #(1) db1_1(.D(b1_reg0), .Q(b1_reg1), .en(1'b1), .clear(reset), .clock(clk)); + + Register #(1) db2_0(.D(b2), .Q(b2_reg0), .en(1'b1), .clear(reset), .clock(clk)); + Register #(1) db2_1(.D(b2_reg0), .Q(b2_reg1), .en(1'b1), .clear(reset), .clock(clk)); + + Register #(1) db3_0(.D(b3), .Q(b3_reg0), .en(1'b1), .clear(reset), .clock(clk)); + Register #(1) db3_1(.D(b3_reg0), .Q(b3_reg1), .en(1'b1), .clear(reset), .clock(clk)); + + Register #(1) db4_0(.D(b4), .Q(b4_reg0), .en(1'b1), .clear(reset), .clock(clk)); + Register #(1) db4_1(.D(b4_reg0), .Q(b4_reg1), .en(1'b1), .clear(reset), .clock(clk)); + + Register #(1) db5_0(.D(b5), .Q(b5_reg0), .en(1'b1), .clear(reset), .clock(clk)); + Register #(1) db5_1(.D(b5_reg0), .Q(b5_reg1), .en(1'b1), .clear(reset), .clock(clk)); + + Register #(1) db6_0(.D(b6), .Q(b6_reg0), .en(1'b1), .clear(reset), .clock(clk)); + Register #(1) db6_1(.D(b6_reg0), .Q(b6_reg1), .en(1'b1), .clear(reset), .clock(clk)); + + Register #(1) db7_0(.D(b7), .Q(b7_reg0), .en(1'b1), .clear(reset), .clock(clk)); + Register #(1) db7_1(.D(b7_reg0), .Q(b7_reg1), .en(1'b1), .clear(reset), .clock(clk)); + + Register #(1) db8_0(.D(b8), .Q(b8_reg0), .en(1'b1), .clear(reset), .clock(clk)); + Register #(1) db8_1(.D(b8_reg0), .Q(b8_reg1), .en(1'b1), .clear(reset), .clock(clk)); + + Register #(1) led0_r(.D(led0_reg), .Q(led0), .en(led0_en), .clear(reset), .clock(clk)); + Register #(1) led1_r(.D(led1_reg), .Q(led1), .en(led1_en), .clear(reset), .clock(clk)); + Register #(1) led2_r(.D(led2_reg), .Q(led2), .en(led2_en), .clear(reset), .clock(clk)); + Register #(1) led3_r(.D(led3_reg), .Q(led3), .en(led3_en), .clear(reset), .clock(clk)); + Register #(1) led4_r(.D(led4_reg), .Q(led4), .en(led4_en), .clear(reset), .clock(clk)); + Register #(1) led5_r(.D(led5_reg), .Q(led5), .en(led5_en), .clear(reset), .clock(clk)); + Register #(1) led6_r(.D(led6_reg), .Q(led6), .en(led6_en), .clear(reset), .clock(clk)); + Register #(1) led7_r(.D(led7_reg), .Q(led7), .en(led7_en), .clear(reset), .clock(clk)); + Register #(1) led8_r(.D(led8_reg), .Q(led8), .en(led8_en), .clear(reset), .clock(clk)); + + Register #(9) game_state_r(.D(game_state_reg), .Q(game_state), .en(game_state_en), .clear(reset), .clock(clk)); + Register #(9) p1_state_r(.D(p1_state_reg), .Q(p1_state), .en(p1_state_en), .clear(reset), .clock(clk)); + Register #(9) p2_state_r(.D(p2_state_reg), .Q(p2_state), .en(p2_state_en), .clear(reset), .clock(clk)); + + random_number rn(.Q(index), .clear(reset), .clock(clk)); + + assign button_pressed = b0_reg1 | b1_reg1 | b2_reg1 | b3_reg1 | b4_reg1 | b5_reg1 | b6_reg1 | b7_reg1 | b8_reg1 | next; + + always_comb begin + led0_en = 1'b0; + led1_en = 1'b0; + led2_en = 1'b0; + led3_en = 1'b0; + led4_en = 1'b0; + led5_en = 1'b0; + led6_en = 1'b0; + led7_en = 1'b0; + led8_en = 1'b0; + game_state_en = 1'b0; + p1_state_en = 1'b0; + p2_state_en = 1'b0; + led0_reg = 1'b0; + led1_reg = 1'b0; + led2_reg = 1'b0; + led3_reg = 1'b0; + led4_reg = 1'b0; + led5_reg = 1'b0; + led6_reg = 1'b0; + led7_reg = 1'b0; + led8_reg = 1'b0; + game_state_reg = 9'd0; + p1_state_reg = 9'd0; + p2_state_reg = 9'd0; + next = 0; + if (reset || new_game) begin + game_state_reg = 9'd0; + p1_state_reg = 9'd0; + p2_state_reg = 9'd0; + game_state_en = 1'b1; + p1_state_en = 1'b1; + p2_state_en = 1'b1; + end + else if (player_sel == 0) begin + if (curr_player == 0) begin // player 1 + if (b0_reg1 == 1 && game_state[0] == 0) begin + led0_reg = 1'b1; + game_state_reg = game_state | 9'h1; + p1_state_reg = p1_state | 9'h1; + led0_en = 1'b1; + game_state_en = 1'b1; + p1_state_en = 1'b1; + end + else if (b1_reg1 == 1 && game_state[1] == 0) begin + led1_reg = 1'b1; + game_state_reg = game_state | 9'h2; + p1_state_reg = p1_state | 9'h2; + led1_en = 1'b1; + game_state_en = 1'b1; + p1_state_en = 1'b1; + end + else if (b2_reg1 == 1 && game_state[2] == 0) begin + led2_reg = 1'b1; + game_state_reg = game_state | 9'h4; + p1_state_reg = p1_state | 9'h4; + led2_en = 1'b1; + game_state_en = 1'b1; + p1_state_en = 1'b1; + end + else if (b3_reg1 == 1 && game_state[3] == 0) begin + led3_reg = 1'b1; + game_state_reg = game_state | 9'h8; + p1_state_reg = p1_state | 9'h8; + led3_en = 1'b1; + game_state_en = 1'b1; + p1_state_en = 1'b1; + end + else if (b4_reg1 == 1 && game_state[4] == 0) begin + led4_reg = 1'b1; + game_state_reg = game_state | 9'h10; + p1_state_reg = p1_state | 9'h10; + led4_en = 1'b1; + game_state_en = 1'b1; + p1_state_en = 1'b1; + end + else if (b5_reg1 == 1 && game_state[5] == 0) begin + led5_reg = 1'b1; + game_state_reg = game_state | 9'h20; + p1_state_reg = p1_state | 9'h20; + led5_en = 1'b1; + game_state_en = 1'b1; + p1_state_en = 1'b1; + end + else if (b6_reg1 == 1 && game_state[6] == 0) begin + led6_reg = 1'b1; + game_state_reg = game_state | 9'h40; + p1_state_reg = p1_state | 9'h40; + led6_en = 1'b1; + game_state_en = 1'b1; + p1_state_en = 1'b1; + end + else if (b7_reg1 == 1 && game_state[7] == 0) begin + led7_reg = 1'b1; + game_state_reg = game_state | 9'h80; + p1_state_reg = p1_state | 9'h80; + led7_en = 1'b1; + game_state_en = 1'b1; + p1_state_en = 1'b1; + end + else if (b8_reg1 == 1 && game_state[8] == 0) begin + led8_reg = 1'b1; + game_state_reg = game_state | 9'h100; + p1_state_reg = p1_state | 9'h100; + led8_en = 1'b1; + game_state_en = 1'b1; + p1_state_en = 1'b1; + end + else begin + led0_en = 1'b0; + led1_en = 1'b0; + led2_en = 1'b0; + led3_en = 1'b0; + led4_en = 1'b0; + led5_en = 1'b0; + led6_en = 1'b0; + led7_en = 1'b0; + led8_en = 1'b0; + game_state_en = 1'b0; + p1_state_en = 1'b0; + p2_state_en = 1'b0; + led0_reg = 1'b0; + led1_reg = 1'b0; + led2_reg = 1'b0; + led3_reg = 1'b0; + led4_reg = 1'b0; + led5_reg = 1'b0; + led6_reg = 1'b0; + led7_reg = 1'b0; + led8_reg = 1'b0; + game_state_reg = 9'd0; + p1_state_reg = 9'd0; + p2_state_reg = 9'd0; + end + end + else begin + if (game_state[0] == 0) begin + next = 1'b1; + led0_reg = 1'b1; + game_state_reg = game_state | 9'h1; + p2_state_reg = p2_state | 9'h1; + led0_en = 1'b1; + game_state_en = 1'b1; + p2_state_en = 1'b1; + end + else if (game_state[1] == 0) begin + next = 1'b1; + led1_reg = 1'b1; + game_state_reg = game_state | 9'h2; + p2_state_reg = p2_state | 9'h2; + led1_en = 1'b1; + game_state_en = 1'b1; + p2_state_en = 1'b1; + end + else if (game_state[2] == 0) begin + next = 1'b1; + led2_reg = 1'b1; + game_state_reg = game_state | 9'h4; + p2_state_reg = p2_state | 9'h4; + led2_en = 1'b1; + game_state_en = 1'b1; + p2_state_en = 1'b1; + end + else if (game_state[3] == 0) begin + next = 1'b1; + led3_reg = 1'b1; + game_state_reg = game_state | 9'h8; + p2_state_reg = p2_state | 9'h8; + led3_en = 1'b1; + game_state_en = 1'b1; + p2_state_en = 1'b1; + end + else if (game_state[4] == 0) begin + next = 1'b1; + led4_reg = 1'b1; + game_state_reg = game_state | 9'h10; + p2_state_reg = p2_state | 9'h10; + led4_en = 1'b1; + game_state_en = 1'b1; + p2_state_en = 1'b1; + end + else if (game_state[5] == 0) begin + next = 1'b1; + led5_reg = 1'b1; + game_state_reg = game_state | 9'h20; + p2_state_reg = p2_state | 9'h20; + led5_en = 1'b1; + game_state_en = 1'b1; + p2_state_en = 1'b1; + end + else if (game_state[6] == 0) begin + next = 1'b1; + led6_reg = 1'b1; + game_state_reg = game_state | 9'h40; + p2_state_reg = p2_state | 9'h40; + led6_en = 1'b1; + game_state_en = 1'b1; + p2_state_en = 1'b1; + end + else if (game_state[7] == 0) begin + next = 1'b1; + led7_reg = 1'b1; + game_state_reg = game_state | 9'h80; + p2_state_reg = p2_state | 9'h80; + led7_en = 1'b1; + game_state_en = 1'b1; + p2_state_en = 1'b1; + end + else if (game_state[8] == 0) begin + next = 1'b1; + led8_reg = 1'b1; + game_state_reg = game_state | 9'h100; + p2_state_reg = p2_state | 9'h100; + led8_en = 1'b1; + game_state_en = 1'b1; + p2_state_en = 1'b1; + end + else begin + led0_en = 1'b0; + led1_en = 1'b0; + led2_en = 1'b0; + led3_en = 1'b0; + led4_en = 1'b0; + led5_en = 1'b0; + led6_en = 1'b0; + led7_en = 1'b0; + led8_en = 1'b0; + game_state_en = 1'b0; + p1_state_en = 1'b0; + p2_state_en = 1'b0; + led0_reg = 1'b0; + led1_reg = 1'b0; + led2_reg = 1'b0; + led3_reg = 1'b0; + led4_reg = 1'b0; + led5_reg = 1'b0; + led6_reg = 1'b0; + led7_reg = 1'b0; + led8_reg = 1'b0; + game_state_reg = 9'd0; + p1_state_reg = 9'd0; + p2_state_reg = 9'd0; + end + end + end + else begin + if (curr_player == 0) begin // player 1 + if (b0_reg1 == 1 && game_state[0] == 0) begin + led0_reg = 1'b1; + game_state_reg = game_state | 9'h1; + p1_state_reg = p1_state | 9'h1; + led0_en = 1'b1; + game_state_en = 1'b1; + p1_state_en = 1'b1; + end + else if (b1_reg1 == 1 && game_state[1] == 0) begin + led1_reg = 1'b1; + game_state_reg = game_state | 9'h2; + p1_state_reg = p1_state | 9'h2; + led1_en = 1'b1; + game_state_en = 1'b1; + p1_state_en = 1'b1; + end + else if (b2_reg1 == 1 && game_state[2] == 0) begin + led2_reg = 1'b1; + game_state_reg = game_state | 9'h4; + p1_state_reg = p1_state | 9'h4; + led2_en = 1'b1; + game_state_en = 1'b1; + p1_state_en = 1'b1; + end + else if (b3_reg1 == 1 && game_state[3] == 0) begin + led3_reg = 1'b1; + game_state_reg = game_state | 9'h8; + p1_state_reg = p1_state | 9'h8; + led3_en = 1'b1; + game_state_en = 1'b1; + p1_state_en = 1'b1; + end + else if (b4_reg1 == 1 && game_state[4] == 0) begin + led4_reg = 1'b1; + game_state_reg = game_state | 9'h10; + p1_state_reg = p1_state | 9'h10; + led4_en = 1'b1; + game_state_en = 1'b1; + p1_state_en = 1'b1; + end + else if (b5_reg1 == 1 && game_state[5] == 0) begin + led5_reg = 1'b1; + game_state_reg = game_state | 9'h20; + p1_state_reg = p1_state | 9'h20; + led5_en = 1'b1; + game_state_en = 1'b1; + p1_state_en = 1'b1; + end + else if (b6_reg1 == 1 && game_state[6] == 0) begin + led6_reg = 1'b1; + game_state_reg = game_state | 9'h40; + p1_state_reg = p1_state | 9'h40; + led6_en = 1'b1; + game_state_en = 1'b1; + p1_state_en = 1'b1; + end + else if (b7_reg1 == 1 && game_state[7] == 0) begin + led7_reg = 1'b1; + game_state_reg = game_state | 9'h80; + p1_state_reg = p1_state | 9'h80; + led7_en = 1'b1; + game_state_en = 1'b1; + p1_state_en = 1'b1; + end + else if (b8_reg1 == 1 && game_state[8] == 0) begin + led8_reg = 1'b1; + game_state_reg = game_state | 9'h100; + p1_state_reg = p1_state | 9'h100; + led8_en = 1'b1; + game_state_en = 1'b1; + p1_state_en = 1'b1; + end + else begin + led0_en = 1'b0; + led1_en = 1'b0; + led2_en = 1'b0; + led3_en = 1'b0; + led4_en = 1'b0; + led5_en = 1'b0; + led6_en = 1'b0; + led7_en = 1'b0; + led8_en = 1'b0; + game_state_en = 1'b0; + p1_state_en = 1'b0; + p2_state_en = 1'b0; + led0_reg = 1'b0; + led1_reg = 1'b0; + led2_reg = 1'b0; + led3_reg = 1'b0; + led4_reg = 1'b0; + led5_reg = 1'b0; + led6_reg = 1'b0; + led7_reg = 1'b0; + led8_reg = 1'b0; + game_state_reg = 9'd0; + p1_state_reg = 9'd0; + p2_state_reg = 9'd0; + end + end + else begin + if (b0_reg1 == 1 && game_state[0] == 0) begin + led0_reg = 1'b1; + game_state_reg = game_state | 9'h1; + p2_state_reg = p2_state | 9'h1; + led0_en = 1'b1; + game_state_en = 1'b1; + p2_state_en = 1'b1; + end + else if (b1_reg1 == 1 && game_state[1] == 0) begin + led1_reg = 1'b1; + game_state_reg = game_state | 9'h2; + p2_state_reg = p2_state | 9'h2; + led1_en = 1'b1; + game_state_en = 1'b1; + p2_state_en = 1'b1; + end + else if (b2_reg1 == 1 && game_state[2] == 0) begin + led2_reg = 1'b1; + game_state_reg = game_state | 9'h4; + p2_state_reg = p2_state | 9'h4; + led2_en = 1'b1; + game_state_en = 1'b1; + p2_state_en = 1'b1; + end + else if (b3_reg1 == 1 && game_state[3] == 0) begin + led3_reg = 1'b1; + game_state_reg = game_state | 9'h8; + p2_state_reg = p2_state | 9'h8; + led3_en = 1'b1; + game_state_en = 1'b1; + p2_state_en = 1'b1; + end + else if (b4_reg1 == 1 && game_state[4] == 0) begin + led4_reg = 1'b1; + game_state_reg = game_state | 9'h10; + p2_state_reg = p2_state | 9'h10; + led4_en = 1'b1; + game_state_en = 1'b1; + p2_state_en = 1'b1; + end + else if (b5_reg1 == 1 && game_state[5] == 0) begin + led5_reg = 1'b1; + game_state_reg = game_state | 9'h20; + p2_state_reg = p2_state | 9'h20; + led5_en = 1'b1; + game_state_en = 1'b1; + p2_state_en = 1'b1; + end + else if (b6_reg1 == 1 && game_state[6] == 0) begin + led6_reg = 1'b1; + game_state_reg = game_state | 9'h40; + p2_state_reg = p2_state | 9'h40; + led6_en = 1'b1; + game_state_en = 1'b1; + p2_state_en = 1'b1; + end + else if (b7_reg1 == 1 && game_state[7] == 0) begin + led7_reg = 1'b1; + game_state_reg = game_state | 9'h80; + p2_state_reg = p2_state | 9'h80; + led7_en = 1'b1; + game_state_en = 1'b1; + p2_state_en = 1'b1; + end + else if (b8_reg1 == 1 && game_state[8] == 0) begin + led8_reg = 1'b1; + game_state_reg = game_state | 9'h100; + p2_state_reg = p2_state | 9'h100; + led8_en = 1'b1; + game_state_en = 1'b1; + p2_state_en = 1'b1; + end + else begin + led0_en = 1'b0; + led1_en = 1'b0; + led2_en = 1'b0; + led3_en = 1'b0; + led4_en = 1'b0; + led5_en = 1'b0; + led6_en = 1'b0; + led7_en = 1'b0; + led8_en = 1'b0; + game_state_en = 1'b0; + p1_state_en = 1'b0; + p2_state_en = 1'b0; + led0_reg = 1'b0; + led1_reg = 1'b0; + led2_reg = 1'b0; + led3_reg = 1'b0; + led4_reg = 1'b0; + led5_reg = 1'b0; + led6_reg = 1'b0; + led7_reg = 1'b0; + led8_reg = 1'b0; + game_state_reg = 9'd0; + p1_state_reg = 9'd0; + p2_state_reg = 9'd0; + end + end + end + end + + win_detection wd(.p1_state(p1_state), .p2_state(p2_state), .*); + ttt_fsm fsm(.*); + +endmodule: ttt_game_control + +module win_detection ( + input logic [8:0] p1_state, p2_state, + output logic finished +); + + always_comb begin + if (p1_state[0] == 1 && p1_state[1] == 1 && p1_state[2] == 1) finished = '1; + else if (p1_state[3] == 1 && p1_state[4] == 1 && p1_state[5] == 1) finished = '1; + else if (p1_state[6] == 1 && p1_state[7] == 1 && p1_state[8] == 1) finished = '1; + else if (p1_state[0] == 1 && p1_state[3] == 1 && p1_state[6] == 1) finished = '1; + else if (p1_state[1] == 1 && p1_state[4] == 1 && p1_state[7] == 1) finished = '1; + else if (p1_state[2] == 1 && p1_state[5] == 1 && p1_state[8] == 1) finished = '1; + else if (p1_state[0] == 1 && p1_state[4] == 1 && p1_state[8] == 1) finished = '1; + else if (p1_state[2] == 1 && p1_state[4] == 1 && p1_state[6] == 1) finished = '1; + else if (p2_state[0] == 1 && p2_state[1] == 1 && p2_state[2] == 1) finished = '1; + else if (p2_state[3] == 1 && p2_state[4] == 1 && p2_state[5] == 1) finished = '1; + else if (p2_state[6] == 1 && p2_state[7] == 1 && p2_state[8] == 1) finished = '1; + else if (p2_state[0] == 1 && p2_state[3] == 1 && p2_state[6] == 1) finished = '1; + else if (p2_state[1] == 1 && p2_state[4] == 1 && p2_state[7] == 1) finished = '1; + else if (p2_state[2] == 1 && p2_state[5] == 1 && p2_state[8] == 1) finished = '1; + else if (p2_state[0] == 1 && p2_state[4] == 1 && p2_state[8] == 1) finished = '1; + else if (p2_state[2] == 1 && p2_state[4] == 1 && p2_state[6] == 1) finished = '1; + else finished = '0; + end + +endmodule: win_detection + +module ttt_fsm ( + input logic start, button_pressed, finished, + input logic clk, reset, + output logic curr_player, // 0 = player 1, 1 = player 2 + output logic new_game +); + + enum logic [1:0] {START, WAIT_P1, WAIT_P2, END} state, nextState; + + always_comb begin + new_game = '0; + unique case (state) + START: begin + curr_player = '0; + if (start) nextState = WAIT_P1; + else nextState = START; + end + WAIT_P1: begin + if (finished) begin + curr_player = '0; + nextState = END; + end + else if (button_pressed) begin + curr_player = '1; + nextState = WAIT_P2; + end + else begin + curr_player = '0; + nextState = WAIT_P1; + end + end + WAIT_P2: begin + if (finished) begin + curr_player = '0; + nextState = END; + end + else if (button_pressed) begin + curr_player = '0; + nextState = WAIT_P1; + end + else begin + curr_player = '1; + nextState = WAIT_P2; + end + end + END: begin + curr_player = '0; + new_game = '1; + nextState = START; + end + endcase + end + + always_ff @(posedge clk) + if (reset) state <= START; + else state <= nextState; + +endmodule: ttt_fsm diff --git a/designs/d10_wabib_tictactoe/verif/mm.mk b/designs/d10_wabib_tictactoe/verif/mm.mk new file mode 100644 index 0000000..79daa70 --- /dev/null +++ b/designs/d10_wabib_tictactoe/verif/mm.mk @@ -0,0 +1,5 @@ +TOPLEVEL_LANG = verilog +VERILOG_SOURCES = $(shell pwd)/ttt.sv +TOPLEVEL = ttt_game_control +MODULE = tb +include $(shell cocotb-config --makefiles)/Makefile.sim diff --git a/designs/d10_wabib_tictactoe/verif/tb.py b/designs/d10_wabib_tictactoe/verif/tb.py new file mode 100644 index 0000000..e3eac68 --- /dev/null +++ b/designs/d10_wabib_tictactoe/verif/tb.py @@ -0,0 +1,87 @@ +import cocotb +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge, ReadOnly + + +async def reset(dut): + dut.reset.value = 1 + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + dut.reset.value = 0 + +@cocotb.test() +async def test_ttt_game_control(dut): + + # Automatic clock (timescale is for VCD files) + cocotb.start_soon(Clock(dut.clk, 10, units="ns").start()) + + # Reset DUT + dut.start.value = 0 + await reset(dut) + + dut.start.value = 1 + await RisingEdge(dut.clk) + dut.start.value = 0 + + dut.b0.value = 1 + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + print(f'led0 = {dut.led0.value} game_state = {dut.game_state.value}'); + assert(dut.led0.value == 1) + assert(dut.game_state.value == 1) + + dut.b1.value = 1 + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + print(f'led1 = {dut.led1.value} game_state = {dut.game_state.value}'); + assert(dut.led1.value == 1) + assert(dut.game_state.value == 3) + + dut.b2.value = 1 + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + print(f'led2 = {dut.led2.value} game_state = {dut.game_state.value}'); + assert(dut.led2.value == 1) + assert(dut.game_state.value == 7) + + dut.b3.value = 1 + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + print(f'led3 = {dut.led3.value} game_state = {dut.game_state.value}'); + assert(dut.led3.value == 1) + assert(dut.game_state.value == 15) + + dut.b4.value = 1 + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + print(f'led4 = {dut.led4.value} game_state = {dut.game_state.value}'); + assert(dut.led4.value == 1) + assert(dut.game_state.value == 31) + + dut.b5.value = 1 + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + print(f'led5 = {dut.led5.value} game_state = {dut.game_state.value}'); + assert(dut.led5.value == 1) + assert(dut.game_state.value == 63) + + dut.b6.value = 1 + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + print(f'led6 = {dut.led6.value} game_state = {dut.game_state.value}'); + assert(dut.led6.value == 1) + assert(dut.game_state.value == 127) + + dut.b7.value = 1 + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + print(f'led7 = {dut.led7.value} game_state = {dut.game_state.value}'); + assert(dut.led7.value == 1) + assert(dut.game_state.value == 255) + + dut.b8.value = 1 + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + print(f'led8 = {dut.led8.value} game_state = {dut.game_state.value}'); + assert(dut.led8.value == 1) + assert(dut.game_state.value == 511) diff --git a/designs/d10_wabib_tictactoe/verif/ttt.sv b/designs/d10_wabib_tictactoe/verif/ttt.sv new file mode 100644 index 0000000..a3babc5 --- /dev/null +++ b/designs/d10_wabib_tictactoe/verif/ttt.sv @@ -0,0 +1,205 @@ +module ttt_game_control ( + input logic b0, b1, b2, b3, b4, b5, b6, b7, b8, player_sel, start, + input logic clk, reset, + output logic led0, led1, led2, led3, led4, led5, led6, led7, led8 +); + + logic [8:0] game_state, p1_state, p2_state; + logic curr_player, button_pressed, new_game; + + assign button_pressed = b0 | b1 | b2 | b3 | b4 | b5 | b6 | b7 | b8; + + always_ff @(posedge clk, posedge reset) begin + if (reset || new_game) begin + game_state <= 9'd0; + p1_state <= 9'd0; + p2_state <= 9'd0; + end + else begin + if (curr_player == 0) begin // player 1 + if (b0 == 1 && game_state[0] == 0) begin + led0 <= 1; + game_state <= {game_state[8:1], 1'b1}; + p1_state <= {p1_state[8:1], 1'b1}; + end + else if (b1 == 1 && game_state[1] == 0) begin + led1 <= 1; + game_state <= {game_state[8:2], 1'b1, game_state[0]}; + p1_state <= {p1_state[8:2], 1'b1, p1_state[0]}; + end + else if (b2 == 1 && game_state[2] == 0) begin + led2 <= 1; + game_state <= {game_state[8:3], 1'b1, game_state[1:0]}; + p1_state <= {p1_state[8:3], 1'b1, p1_state[1:0]}; + end + else if (b3 == 1 && game_state[3] == 0) begin + led3 <= 1; + game_state <= {game_state[8:4], 1'b1, game_state[2:0]}; + p1_state <= {p1_state[8:4], 1'b1, p1_state[2:0]}; + end + else if (b4 == 1 && game_state[4] == 0) begin + led4 <= 1; + game_state <= {game_state[8:5], 1'b1, game_state[3:0]}; + p1_state <= {p1_state[8:5], 1'b1, p1_state[3:0]}; + end + else if (b5 == 1 && game_state[5] == 0) begin + led5 <= 1; + game_state <= {game_state[8:6], 1'b1, game_state[4:0]}; + p1_state <= {p1_state[8:6], 1'b1, p1_state[4:0]}; + end + else if (b6 == 1 && game_state[6] == 0) begin + led6 <= 1; + game_state <= {game_state[8:7], 1'b1, game_state[5:0]}; + p1_state <= {p1_state[8:7], 1'b1, p1_state[5:0]}; + end + else if (b7 == 1 && game_state[7] == 0) begin + led7 <= 1; + game_state <= {game_state[8], 1'b1, game_state[6:0]}; + p1_state <= {p1_state[8], 1'b1, p1_state[6:0]}; + end + else if (b8 == 1 && game_state[8] == 0) begin + led8 <= 1; + game_state <= {1'b1, game_state[7:0]}; + p1_state <= {1'b1, p1_state[7:0]}; + end + end + else begin + if (b0 == 1 && game_state[0] == 0) begin + led0 <= 1; + game_state <= {game_state[8:1], 1'b1}; + p1_state <= {p2_state[8:1], 1'b1}; + end + else if (b1 == 1 && game_state[1] == 0) begin + led1 <= 1; + game_state <= {game_state[8:2], 1'b1, game_state[0]}; + p2_state <= {p2_state[8:2], 1'b1, p2_state[0]}; + end + else if (b2 == 1 && game_state[2] == 0) begin + led2 <= 1; + game_state <= {game_state[8:3], 1'b1, game_state[1:0]}; + p2_state <= {p2_state[8:3], 1'b1, p2_state[1:0]}; + end + else if (b3 == 1 && game_state[3] == 0) begin + led3 <= 1; + game_state <= {game_state[8:4], 1'b1, game_state[2:0]}; + p2_state <= {p2_state[8:4], 1'b1, p2_state[2:0]}; + end + else if (b4 == 1 && game_state[4] == 0) begin + led4 <= 1; + game_state <= {game_state[8:5], 1'b1, game_state[3:0]}; + p2_state <= {p2_state[8:5], 1'b1, p2_state[3:0]}; + end + else if (b5 == 1 && game_state[5] == 0) begin + led5 <= 1; + game_state <= {game_state[8:6], 1'b1, game_state[4:0]}; + p2_state <= {p2_state[8:6], 1'b1, p2_state[4:0]}; + end + else if (b6 == 1 && game_state[6] == 0) begin + led6 <= 1; + game_state <= {game_state[8:7], 1'b1, game_state[5:0]}; + p2_state <= {p2_state[8:7], 1'b1, p2_state[5:0]}; + end + else if (b7 == 1 && game_state[7] == 0) begin + led7 <= 1; + game_state <= {game_state[8], 1'b1, game_state[6:0]}; + p2_state <= {p2_state[8], 1'b1, p2_state[6:0]}; + end + else if (b8 == 1 && game_state[8] == 0) begin + led8 <= 1; + game_state <= {1'b1, game_state[7:0]}; + p2_state <= {1'b1, p2_state[7:0]}; + end + end + end + end + + + ttt_fsm fsm(.finished(0), .*); + +endmodule: ttt_game_control + +module win_detection ( + input logic [8:0] p1_state, p2_state, clk, reset, + output logic finished +); + + always_comb begin + if (p1_state[0] == 1 && p1_state[1] == 1 && p1_state[2] == 1) finished = 1; + else if (p1_state[3] == 1 && p1_state[4] == 1 && p1_state[5] == 1) finished = 1; + else if (p1_state[6] == 1 && p1_state[7] == 1 && p1_state[8] == 1) finished = 1; + else if (p1_state[0] == 1 && p1_state[3] == 1 && p1_state[6] == 1) finished = 1; + else if (p1_state[1] == 1 && p1_state[4] == 1 && p1_state[7] == 1) finished = 1; + else if (p1_state[2] == 1 && p1_state[5] == 1 && p1_state[8] == 1) finished = 1; + else if (p1_state[0] == 1 && p1_state[4] == 1 && p1_state[8] == 1) finished = 1; + else if (p1_state[2] == 1 && p1_state[4] == 1 && p1_state[6] == 1) finished = 1; + else if (p2_state[0] == 1 && p2_state[1] == 1 && p2_state[2] == 1) finished = 1; + else if (p2_state[3] == 1 && p2_state[4] == 1 && p2_state[5] == 1) finished = 1; + else if (p2_state[6] == 1 && p2_state[7] == 1 && p2_state[8] == 1) finished = 1; + else if (p2_state[0] == 1 && p2_state[3] == 1 && p2_state[6] == 1) finished = 1; + else if (p2_state[1] == 1 && p2_state[4] == 1 && p2_state[7] == 1) finished = 1; + else if (p2_state[2] == 1 && p2_state[5] == 1 && p2_state[8] == 1) finished = 1; + else if (p2_state[0] == 1 && p2_state[4] == 1 && p2_state[8] == 1) finished = 1; + else if (p2_state[2] == 1 && p2_state[4] == 1 && p2_state[6] == 1) finished = 1; + else finished = 0; + end + +endmodule: win_detection + +module ttt_fsm ( + input logic start, button_pressed, finished, + input logic clk, reset, + output logic curr_player, // 0 = player 1, 1 = player 2 + output logic new_game +); + + enum logic [1:0] {START, WAIT_P1, WAIT_P2, END} state, nextState; + + always_comb begin + new_game = 0; + unique case (state) + START: begin + curr_player = 0; + if (start) nextState = WAIT_P1; + else nextState = START; + end + WAIT_P1: begin + if (finished) begin + curr_player = 0; + nextState = END; + end + else if (button_pressed) begin + curr_player = 1; + nextState = WAIT_P2; + end + else begin + curr_player = 0; + nextState = WAIT_P1; + end + end + WAIT_P2: begin + if (finished) begin + curr_player = 0; + nextState = END; + end + else if (button_pressed) begin + curr_player = 0; + nextState = WAIT_P1; + end + else begin + curr_player = 1; + nextState = WAIT_P2; + end + end + END: begin + curr_player = 0; + new_game = 1; + nextState = START; + end + endcase + end + + always_ff @(posedge clk, posedge reset) + if (reset) state <= START; + else state <= nextState; + +endmodule: ttt_fsm diff --git a/designs/d11_gbailey_bfchip/.lastupdated b/designs/d11_gbailey_bfchip/.lastupdated new file mode 100644 index 0000000..4d7b8c3 --- /dev/null +++ b/designs/d11_gbailey_bfchip/.lastupdated @@ -0,0 +1 @@ +2023-05-14 diff --git a/designs/d11_gbailey_bfchip/LICENSE b/designs/d11_gbailey_bfchip/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/designs/d11_gbailey_bfchip/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/designs/d11_gbailey_bfchip/README.md b/designs/d11_gbailey_bfchip/README.md new file mode 100644 index 0000000..e6cd83c --- /dev/null +++ b/designs/d11_gbailey_bfchip/README.md @@ -0,0 +1,215 @@ +# bfchip: Brainf*** CPU +Gary Bailey \ +Spring 2023 Final Tapeout Project \ +[18-224: Special Topics in Chip Design](https://courses.ece.cmu.edu/18224) + +## Overview +This project implements a simple CPU (written in SystemVerilog) which interprets +the esoteric programming language Brainf*** (BF) as its machine code. The +version of BF implemented by this project actually contains one extension: in +addition to the eight standard BF instructions `+-<>[].,`, a ninth instruction +`\0` (0-byte) is implemented, which halts the CPU. Architecturally, this CPU is +similar to the Harvard architecture, with separate 16-bit program and data +address spaces. + +## How it Works +This project consists mainly of two modules: `BF` (`dev/src/bf.sv`), the BF +core, which actually implements the CPU core, and `my_chip` (`dev/src/chip.sv`), +the bus interface, which translates the BF core's bus protocol. + +### BF Core +The BF core itself contains four registers: +- `pc`, the program counter +- `cursor`, the address of the currently selected cell +- `acc`, the accumulator +- `depth`, the nested loop depth of the current instruction when jumping forward + or backward + +These registers each have a set of operations which are defined in `consts.sv`. +These operations are packed into the microinstruction word, which is output by +each state in the main FSM. + +The FSM has 33 states in total. Its overall logical strucure is as follows. I've +also included the alphabetic names used to refer to each instruction within the +source code. (here, "instruction" refers to the byte in program memory at the +program counter, and "cell" refers to the byte in data memory at the cursor) + +- Fetch/decode: Fetch instruction, increment `pc`, then: + - if the instruction is one of the recognized instructions, go to that + instructions's stage + - otherwise, return to Fetch/decode +- Inc (`+`): Fetch cell, load cell into `acc`, store `acc+1` into cell, return + to Fetch/decode +- Dec (`-`): Fetch cell, load cell into `acc`, store `acc-1` into cell, return + to Fetch/decode +- Right (`>`): Increment `cursor`, return to Fetch/decode +- Left (`<`): Decrement `cursor`, return to Fetch/decode +- Print (`.`): Fetch cell, load cell into `acc`, write `acc` to I/O, return to + Fetch/decode +- Read (`,`): Fetch I/O, load I/O into `acc`, store `acc` into cell, return to + Fetch/decode +- Brz (`[`): Fetch cell, clear `depth`, then: + - if cell is nonzero, return to Fetch/decode + - (loop) if cell is zero, fetch instruction and increment `pc`: + - if the instruction is `[`, increment `depth` and loop + - if the instruction is `]`: + - if `depth` is zero, return to Fetch/decode + - if `depth` is nonzero, decrement `depth` and repeat loop + - otherwise, loop +- Brnz (`]`): Fetch cell, clear `depth`, then: + - if cell is zero, return to Fetch/decode + - if cell is nonzero, decrement `pc` twice, then + - (loop) fetch instruction and decrement `pc`: + - if the instruction is `]`, increment `depth` and loop + - if the instruction is `[`: + - if `depth` is zero, increment `pc` twice and return to Fetch/decode + - if `depth` is nonzero, decrement `depth` and loop + - otherwise, loop +- Halt (`\0`): Do nothing and repeat + +### Bus Interface +There is a secondary module which translates the 24-output, 8-input bus of the +BF core into a multiplexed, 11-output, 8-input bus to fit within the port +constraints of our tapeout. This consists of a very simple FSM which detects +when the BF core makes a memory or IO request. When this occurs, it disables the +core and successively sends the bus opcode, two address bytes, and written byte +(if applicable) on the output bus, and then waits for an external memory/IO +controller to assert `op_done` before continuing execution. See [Hardware +Peripherals](#hardware-peripherals) for more info about this protocol. + +## I/O + +### Inputs + +| Input | Assignment | +|-------|-------------| +| 0 | `bus_in[0]` | +| 1 | `bus_in[1]` | +| 2 | `bus_in[2]` | +| 3 | `bus_in[3]` | +| 4 | `bus_in[4]` | +| 5 | `bus_in[5]` | +| 6 | `bus_in[6]` | +| 7 | `bus_in[7]` | +| 8 | `op_done` | +| 9 | `enable` | +| 10 | *(NC)* | +| 11 | *(NC)* | + +#### `bus_in[7:0]` +The bus input value to be passed to the BF core. + +#### `op_done` +Asserted by the memory/IO controller to indicate that the requested operation is +complete. + +#### `enable` +Full system-wide enable. When deasserted, the clock has no effect. + +### Outputs + +| Output | Assignment | +|--------|--------------| +| 0 | `bus_out[0]` | +| 1 | `bus_out[1]` | +| 2 | `bus_out[2]` | +| 3 | `bus_out[3]` | +| 4 | `bus_out[4]` | +| 5 | `bus_out[5]` | +| 6 | `bus_out[6]` | +| 7 | `bus_out[7]` | +| 8 | `state[0]` | +| 9 | `state[1]` | +| 10 | `state[2]` | +| 11 | `halted` | + +#### `bus_out[7:0]` +The bus output value to be handled by the memory controller. The meaning of its +value is determined by the value of `state`. + +#### `state[2:0]` +The "bus state". Defines what is currently being sent an received from `bus_out` +and `bus_in`. Has the following possible values: + +| `state` | Name | Meaning | +|----------|---------------|--------------------------------| +| `3'b000` | `IoNone` | `bus_out` and `bus_in` ignored | +| `3'b001` | `IoOpcode` | `bus_out[2:0]` is the bus opcode | +| `3'b010` | `IoAddrHi` | `bus_out` is `addr[15:8]` | +| `3'b011` | `IoAddrLo` | `bus_out` is `addr[7:0]` | +| `3'b100` | `IoReadWrite` | `bus_out` is the value being written by the BF core, if any, and `bus_in` is passed to the BF core as input | + +The bus opcode can have the following values (the first 5 bits of `bus_out` are +ignored during the opcode step): + +| `opcode` | Name | Operation | +|----------|----------------|------------------------------| +| `3'b000` | `BusNone` | No operation | +| `3'b010` | `BusReadProg` | Read from the program memory | +| `3'b100` | `BusReadData` | Read from the data memory | +| `3'b101` | `BusWriteData` | Write to the data memory | +| `3'b110` | `BusReadIo` | Read from I/O | +| `3'b111` | `BusWriteIo` | Write to I/O | + +See [Hardware Peripherals](#hardware-peripherals) for more info. + +#### `halted` +When asserted, the BF core has halted. + +### Clock and reset +This chip uses active-high, synchronous reset. The clock speed is not strict. + +## Hardware Peripherals +In order for the BF core to operate, the `bus_out`, `bus_in`, `state`, and +`op_done` lines must be connected to a memory/IO controller which implements the +following protocol: + +- When `state == IoOpcode`, store `bus_out` to `opcode` on clock +- When `state == IoAddrHi`, store `bus_out` to `addr[15:8]` on clock +- When `state == IoAddrLo`, store `bus_out` to `addr[7:0]` on clock +- When `state == IoReadWrite`: + - If `opcode == BusReadProg`, set `bus_in` to the byte of program memory at + address `addr`, then assert `op_done` + - If `opcode == BusReadData`, set `bus_in` to the byte of data memory at + address `addr`, then assert `op_done` + - If `opcode == BusWriteData`, store `bus_out` to the byte of data memory at + address `addr` on the clock, then assert `op_done` + - If `opcode == BusReadIo`, set `bus_in` to the first-in byte of the input + stream, then assert `op_done`, and on the clock remove that byte from the + queue + - If `opcode == BusWriteIo`, write `bus_out` to the output stream on the + clock, then assert `op_done` + +The exact implementation/layout of the memory and I/O interfaced with the CPU is +up to the designer of the memory/IO controller. Reasonable options would be a +SPI flash interface for the program memory, SPI SRAM for the data memory, and a +UART interface connected to a terminal for the I/O. Beyond the interface itself, +the controller must make sure to zero-out the data memory before program +execution begins. + +## Design Testing / Bringup +The BF core itself is tested in simulation with CocoTB and is known to work on +the Icarus backend. Running `make test` in `dev/` will run the test suite, which +can be found in `dev/src/tests/`. The test suite consists of example BF +programs. Some of the tests are skipped by default due to taking too long to +execute in simulation, but they can be manually run using `make TESTCASE= +test` + +The `dev/src/fpga_test.py` script, when connected to the debug interface, will +act as the memory/IO controller and run a program on the CPU. It needs to be +passed a TOML file containing a program, inputs, and expected outputs. Several +of these programs can be found in `dev/src/tests/`. + +To test the design after manufacture, implement a memory/IO interface as defined +in [Hardware Peripherals](#hardware-peripherals), and use it to run BF test +programs on the CPU, such as those included in `dev/src/tests/`. + +## Media +Hello World program successfully running on FPGA, using the debug interface: \ +![Screenshot of bfchip successfully running Hello World on +FPGA](media/hello_world.png) + +Test suite passing: \ +![Screenshot of bfchip passing the test suite, except for the "quine" +test](media/tests_passing.png) \ +![Screenshot of bfchip passing the "quine" test](media/quine_passing.png) diff --git a/designs/d11_gbailey_bfchip/dev/Makefile b/designs/d11_gbailey_bfchip/dev/Makefile new file mode 100644 index 0000000..2add096 --- /dev/null +++ b/designs/d11_gbailey_bfchip/dev/Makefile @@ -0,0 +1,75 @@ +export BUILD_DIR ?= build +export SRC_DIR ?= src + +SV2V ?= sv2v +YOSYS ?= yosys +NEXTPNR ?= nextpnr-ice40 +ICEPACK ?= icepack + +DIR_GUARD = @mkdir -p $(@D) +export PYTHONDONTWRITEBYTECODE=1 + +.PHONY: all clean test fpga tapeout +all: test + +clean: + rm -rf $(BUILD_DIR) + +## Sim/testbench stuff: delegate to CocoTB ## +SIM_SOURCES += \ + $(SRC_DIR)/consts.sv \ + $(SRC_DIR)/bf.sv +export VERILOG_SOURCES = $(BUILD_DIR)/all_sim.v # for cocotb + +test: $(VERILOG_SOURCES) + $(MAKE) --no-print-directory -f cocotb.mk + +$(BUILD_DIR)/all_sim.v: $(SIM_SOURCES) + $(DIR_GUARD) + $(SV2V) -w $(BUILD_DIR)/all_sim.v $(SIM_SOURCES) + +## FPGA stuff ## +fpga: $(BUILD_DIR)/bitstream.bit + +FPGA_SOURCES += \ + $(SRC_DIR)/consts.sv \ + $(SRC_DIR)/bf.sv \ + $(SRC_DIR)/chip.sv \ + $(SRC_DIR)/fpga_top.sv \ + $(SRC_DIR)/debugbus.sv + +$(BUILD_DIR)/all_fpga.v: $(FPGA_SOURCES) + $(DIR_GUARD) + $(SV2V) -w $(BUILD_DIR)/all_fpga.v $(FPGA_SOURCES) + +$(BUILD_DIR)/synthesis.json: $(BUILD_DIR)/all_fpga.v + $(DIR_GUARD) + $(YOSYS) -p " \ + read_verilog -sv $(BUILD_DIR)/all_fpga.v; \ + synth_ice40 -json $(BUILD_DIR)/synthesis.json -top top;" + +$(BUILD_DIR)/pnr.asc: $(BUILD_DIR)/synthesis.json $(SRC_DIR)/constraints.pcf + $(DIR_GUARD) + $(NEXTPNR) \ + --hx8k \ + --json $(BUILD_DIR)/synthesis.json \ + --pcf $(SRC_DIR)/constraints.pcf \ + --package cb132 \ + --freq 32 \ + --asc $(BUILD_DIR)/pnr.asc + +$(BUILD_DIR)/bitstream.bit: $(BUILD_DIR)/pnr.asc + $(DIR_GUARD) + $(ICEPACK) $(BUILD_DIR)/pnr.asc $(BUILD_DIR)/bitstream.bit + +## Tapeout stuff ## +tapeout: $(BUILD_DIR)/all_tapeout.v + +TAPEOUT_SOURCES += \ + $(SRC_DIR)/consts.sv \ + $(SRC_DIR)/bf.sv \ + $(SRC_DIR)/chip.sv + +$(BUILD_DIR)/all_tapeout.v: $(TAPEOUT_SOURCES) + $(DIR_GUARD) + $(SV2V) -w $(BUILD_DIR)/all_tapeout.v $(TAPEOUT_SOURCES) diff --git a/designs/d11_gbailey_bfchip/dev/cocotb.mk b/designs/d11_gbailey_bfchip/dev/cocotb.mk new file mode 100644 index 0000000..2c8ad61 --- /dev/null +++ b/designs/d11_gbailey_bfchip/dev/cocotb.mk @@ -0,0 +1,15 @@ +# "Sub-makefile" for interfacing with CocoTB + +SIM ?= icarus +TOPLEVEL_LANG ?= verilog + +TOPLEVEL = BF +MODULE = src.bf_test + +SIM_BUILD = $(BUILD_DIR)/sim_build +COCOTB_RESULTS_FILE = $(BUILD_DIR)/results.xml +ifeq ($(SIM), verilator) +EXTRA_ARGS += -Wno-WIDTHEXPAND +endif + +include $(shell cocotb-config --makefiles)/Makefile.sim diff --git a/designs/d11_gbailey_bfchip/dev/src/bf.sv b/designs/d11_gbailey_bfchip/dev/src/bf.sv new file mode 100644 index 0000000..d9c27c8 --- /dev/null +++ b/designs/d11_gbailey_bfchip/dev/src/bf.sv @@ -0,0 +1,342 @@ +// Brainf*** CPU core +`default_nettype none + +module BF #( + parameter DATA_ADDR_WIDTH = 16, + parameter PROG_ADDR_WIDTH = 16, + parameter DATA_WIDTH = 8, + parameter DEPTH_WIDTH = 12, + parameter ADDR_WIDTH = max(DATA_ADDR_WIDTH, PROG_ADDR_WIDTH), + parameter BUS_WIDTH = max(DATA_WIDTH, 8) +)( + // Bus interface + output logic [ADDR_WIDTH-1:0] addr, + output logic [BUS_WIDTH-1:0] val_out, + input logic [BUS_WIDTH-1:0] val_in, + + // Bus control + output BusOp bus_op, + + // Interpreter control + output logic halted, + input logic clock, + input logic reset, + input logic enable, +); + + // Current microcode instruction and state + BFState state, next_state; + Ucode ucode; + + /// Datapath and registers /// + + // Address source + always_comb case (ucode.addr_src) + AddrNone: addr = '0; + AddrPc: addr = pc; + AddrCursor: addr = cursor; + default: addr = '0; + endcase + + // Bus val source + always_comb case (ucode.val_src) + ValNone: val_out = '0; + ValAcc: val_out = acc; + ValAccInc: val_out = acc + 1; + ValAccDec: val_out = acc - 1; + default: val_out = '0; + endcase + + // Program counter + logic [PROG_ADDR_WIDTH-1:0] pc, next_pc; + always_comb case (ucode.pc_op) + PcKeep: next_pc = pc; + PcInc: next_pc = pc + 1; + PcDec: next_pc = pc - 1; + default: next_pc = pc; + endcase + + // Data cursor + logic [DATA_ADDR_WIDTH-1:0] cursor, next_cursor; + always_comb case (ucode.cursor_op) + CursorKeep: next_cursor = cursor; + CursorInc: next_cursor = cursor + 1; + CursorDec: next_cursor = cursor - 1; + default: next_cursor = cursor; + endcase + + // Accumulator + logic [DATA_WIDTH-1:0] acc, next_acc; + always_comb case (ucode.acc_op) + AccKeep: next_acc = acc; + AccLoad: next_acc = val_in; + default: next_acc = acc; + endcase + + // Loop depth register + logic [DEPTH_WIDTH-1:0] depth, next_depth; + always_comb case (ucode.depth_op) + DepthKeep: next_depth = depth; + DepthClear: next_depth = '0; + DepthInc: next_depth = depth + 1; + DepthDec: next_depth = depth - 1; + default: next_depth = depth; + endcase + + // Bus operation + assign bus_op = ucode.bus_op; + + /// Datapath and FSM sequential logic /// + + always_ff @(posedge clock) + if (reset) begin + pc <= '0; + cursor <= '0; + acc <= '0; + depth <= '0; + + state <= Fetch; + end + else if (enable) begin + // Update registers and state + pc <= next_pc; + cursor <= next_cursor; + acc <= next_acc; + depth <= next_depth; + + state <= next_state; + end + + /// FSM implementation /// + + always_comb begin + // default values + halted = 0; + next_state = Halt; + + case (state) + /// Misc states /// + // Request instruction + Fetch: begin + ucode = {BusReadProg, AddrPc, ValNone, PcInc, CursorKeep, AccKeep, DepthClear}; + next_state = Decode; + end + // Receive instruction and decode + Decode: begin + ucode = {BusNone, AddrNone, ValNone, PcKeep, CursorKeep, AccKeep, DepthClear}; + case (val_in) + "+": next_state = IncFetch; // "Inc" + "-": next_state = DecFetch; // "Dec" + ">": next_state = Right; // "Right" + "<": next_state = Left; // "Left" + ".": next_state = PrintFetch; // "Print" + ",": next_state = ReadFetch; // "Read" + "[": next_state = BrzFetchVal; // "Brz" + "]": next_state = BrnzFetchVal; // "Brnz" + 8'h00: next_state = Halt; + default: next_state = Fetch; // "comments" + endcase + end + // Do nothing forever + Halt: begin + ucode = {BusNone, AddrNone, ValNone, PcKeep, CursorKeep, AccKeep, DepthClear}; + next_state = Halt; + halted = 1; + end + + /// Instruction "+" (Inc) /// + // Request cell value + IncFetch: begin + ucode = {BusReadData, AddrCursor, ValNone, PcKeep, CursorKeep, AccKeep, DepthClear}; + next_state = IncLoad; + end + // Load cell value into accumulator + IncLoad: begin + ucode = {BusNone, AddrNone, ValNone, PcKeep, CursorKeep, AccLoad, DepthClear}; + next_state = IncStore; + end + // Write modified value back into cell + IncStore: begin + ucode = {BusWriteData, AddrCursor, ValAccInc, PcKeep, CursorKeep, AccKeep, DepthClear}; + next_state = Fetch; + end + + /// Instruction "-" (Dec) /// + // Request cell value + DecFetch: begin + ucode = {BusReadData, AddrCursor, ValNone, PcKeep, CursorKeep, AccKeep, DepthClear}; + next_state = DecLoad; + end + // Load cell value into accumulator + DecLoad: begin + ucode = {BusNone, AddrNone, ValNone, PcKeep, CursorKeep, AccLoad, DepthClear}; + next_state = DecStore; + end + // Write modified value back into cell + DecStore: begin + ucode = {BusWriteData, AddrCursor, ValAccDec, PcKeep, CursorKeep, AccKeep, DepthClear}; + next_state = Fetch; + end + + /// Instruction ">" (Right) /// + Right: begin + ucode = {BusNone, AddrNone, ValNone, PcKeep, CursorInc, AccKeep, DepthClear}; + next_state = Fetch; + end + + /// Instruction "<" (Left) /// + Left: begin + ucode = {BusNone, AddrNone, ValNone, PcKeep, CursorDec, AccKeep, DepthClear}; + next_state = Fetch; + end + + /// Instruction "." (Print) /// + // Request cell value + PrintFetch: begin + ucode = {BusReadData, AddrCursor, ValNone, PcKeep, CursorKeep, AccKeep, DepthClear}; + next_state = PrintLoad; + end + // Load cell value into accumulator + PrintLoad: begin + ucode = {BusNone, AddrNone, ValNone, PcKeep, CursorKeep, AccLoad, DepthClear}; + next_state = PrintStore; + end + // Write cell value to IO + PrintStore: begin + ucode = {BusWriteIo, AddrNone, ValAcc, PcKeep, CursorKeep, AccKeep, DepthClear}; + next_state = Fetch; + end + + /// Instruction "," (Read) /// + // Request value from IO + ReadFetch: begin + ucode = {BusReadIo, AddrNone, ValNone, PcKeep, CursorKeep, AccKeep, DepthClear}; + next_state = ReadLoad; + end + // Load value into accumulator + ReadLoad: begin + ucode = {BusNone, AddrNone, ValNone, PcKeep, CursorKeep, AccLoad, DepthClear}; + next_state = ReadStore; + end + // Write value into cell + ReadStore: begin + ucode = {BusWriteData, AddrCursor, ValAcc, PcKeep, CursorKeep, AccKeep, DepthClear}; + next_state = Fetch; + end + + /// Instruction "[" (Brz) /// + // Request cell value to check + BrzFetchVal: begin + ucode = {BusReadData, AddrCursor, ValNone, PcKeep, CursorKeep, AccKeep, DepthClear}; + next_state = BrzDecodeVal; + end + // Branch forward if zero + BrzDecodeVal: begin + ucode = {BusNone, AddrNone, ValNone, PcKeep, CursorKeep, AccKeep, DepthClear}; + if (val_in == '0) + next_state = BrzFetchInstr; + else + next_state = Fetch; + end + // Request instruction to check + BrzFetchInstr: begin + ucode = {BusReadProg, AddrPc, ValNone, PcInc, CursorKeep, AccKeep, DepthKeep}; + next_state = BrzDecodeInstr; + end + // Receive instruction and decode + BrzDecodeInstr: begin + ucode = {BusNone, AddrNone, ValNone, PcKeep, CursorKeep, AccKeep, DepthKeep}; + case (val_in) + "[": next_state = BrzInc; + "]": + if (depth == '0) + next_state = Fetch; + else + next_state = BrzDec; + 8'h00: next_state = Halt; + default: next_state = BrzFetchInstr; + endcase + end + // Increment depth + BrzInc: begin + ucode = {BusNone, AddrNone, ValNone, PcKeep, CursorKeep, AccKeep, DepthInc}; + next_state = BrzFetchInstr; + end + // Decrement depth + BrzDec: begin + ucode = {BusNone, AddrNone, ValNone, PcKeep, CursorKeep, AccKeep, DepthDec}; + next_state = BrzFetchInstr; + end + + /// Instruction "]" (Brnz) /// + // Request cell value to check + BrnzFetchVal: begin + ucode = {BusReadData, AddrCursor, ValNone, PcKeep, CursorKeep, AccKeep, DepthClear}; + next_state = BrnzDecodeVal; + end + // Branch backward if nonzero + BrnzDecodeVal: begin + ucode = {BusNone, AddrNone, ValNone, PcKeep, CursorKeep, AccKeep, DepthClear}; + if (val_in == '0) + next_state = Fetch; + else + next_state = BrnzPcDec1; + end + // Move PC to instruction before the ] + BrnzPcDec1: begin + ucode = {BusNone, AddrNone, ValNone, PcDec, CursorKeep, AccKeep, DepthClear}; + next_state = BrnzPcDec2; + end + BrnzPcDec2: begin + ucode = {BusNone, AddrNone, ValNone, PcDec, CursorKeep, AccKeep, DepthClear}; + next_state = BrnzFetchInstr; + end + // Request instruction to check + BrnzFetchInstr: begin + ucode = {BusReadProg, AddrPc, ValNone, PcDec, CursorKeep, AccKeep, DepthKeep}; + next_state = BrnzDecodeInstr; + end + // Receive instruction and decode + BrnzDecodeInstr: begin + ucode = {BusNone, AddrNone, ValNone, PcKeep, CursorKeep, AccKeep, DepthKeep}; + case (val_in) + "[": + if (depth == '0) + next_state = BrnzPcInc1; + else + next_state = BrnzDec; + "]": next_state = BrnzInc; + 8'h00: next_state = Halt; + default: next_state = BrnzFetchInstr; + endcase + end + // Increment depth + BrnzInc: begin + ucode = {BusNone, AddrNone, ValNone, PcKeep, CursorKeep, AccKeep, DepthInc}; + next_state = BrnzFetchInstr; + end + // Decrement depth + BrnzDec: begin + ucode = {BusNone, AddrNone, ValNone, PcKeep, CursorKeep, AccKeep, DepthDec}; + next_state = BrnzFetchInstr; + end + // Move PC to instruction after the [ + BrnzPcInc1: begin + ucode = {BusNone, AddrNone, ValNone, PcInc, CursorKeep, AccKeep, DepthClear}; + next_state = BrnzPcInc2; + end + BrnzPcInc2: begin + ucode = {BusNone, AddrNone, ValNone, PcInc, CursorKeep, AccKeep, DepthClear}; + next_state = Fetch; + end + + // should be unreachable + default: begin + ucode = {BusNone, AddrNone, ValNone, PcKeep, CursorKeep, AccKeep, DepthKeep}; + next_state = Halt; + end + + endcase + end + +endmodule diff --git a/designs/d11_gbailey_bfchip/dev/src/bf_test.py b/designs/d11_gbailey_bfchip/dev/src/bf_test.py new file mode 100644 index 0000000..362aa4a --- /dev/null +++ b/designs/d11_gbailey_bfchip/dev/src/bf_test.py @@ -0,0 +1,101 @@ +# Runs the test suite in simulation + +import cocotb +from cocotb.triggers import Timer +import os +from pathlib import Path +import tomli + +def dbg(*args, **kwargs): + if "BF_DEBUG" in os.environ: + print(*args, **kwargs) + +async def test_program(dut, prog, stdin=b"", stdout=b"", failread=None): + if isinstance(prog, str): + prog = prog.encode("ascii") + if isinstance(stdin, str): + stdin = stdin.encode("ascii") + if isinstance(stdout, str): + stdout = stdout.encode("ascii") + if isinstance(stdout, str): + failread = failread.encode("ascii") + stdin = bytearray(stdin) + + actual_stdout = bytearray() + + memory = bytearray(65536) + + # Reset and initial values + dut.val_in.value = 0 + dut.clock.value = 0 + dut.reset.value = 1 + await Timer(10, "ns") + dut.clock.value = 1 + await Timer(10, "ns") + dut.clock.value = 0 + dut.reset.value = 0 + dut.enable.value = 1 + await Timer(10, "ns") + + entered_loop = False + while not dut.halted.value.integer: + entered_loop = True + dut.clock.value = 1 + # Get values right before they vanish + bus_op = dut.bus_op.value + addr = dut.addr.value + val_out = dut.val_out.value + await Timer(10, "ns") + dut.clock.value = 0 + if bus_op == 0b010: # BusReadProg + if addr.integer < len(prog): + dut.val_in.value = prog[addr.integer] + else: + dut.val_in.value = 0 + dbg("reading program") + elif bus_op == 0b100: # BusReadData + dut.val_in.value = memory[addr.integer] + dbg("reading data") + elif bus_op == 0b101: # BusWriteData + memory[addr.integer] = val_out.integer + dbg("writing data") + elif bus_op == 0b110: # BusReadIo + if len(stdin) > 0: + char = stdin.pop(0) + elif failread is None: + raise ValueError("reading on empty input is failure") + else: + char = failread + dut.val_in.value = char + dbg("reading io") + elif bus_op == 0b111: # BusWriteIo + actual_stdout.append(val_out.integer) + dbg("writing io") + + await Timer(10, "ns") + + assert(entered_loop) + dbg(stdout, actual_stdout) + assert(stdout == actual_stdout) + +# Construct test cases from files +tests_dir = Path(__file__).parent / "tests" +for test_file in tests_dir.iterdir(): + with open(test_file, "rb") as f: + test = tomli.load(f) + + async def test_fn(dut, test=test): + await test_program( + dut, + test["program"], + test.get("input", ""), + test.get("output", ""), + failread=test.get("input_end", None) + ) + + test_fn.__name__ = test["name"] + test_fn.__qualname__ = test["name"] + vars()[test["name"]] = cocotb.test( + skip=test.get("slow", False), + stage=test.get("stage", 0) + )(test_fn) diff --git a/designs/d11_gbailey_bfchip/dev/src/chip.sv b/designs/d11_gbailey_bfchip/dev/src/chip.sv new file mode 100644 index 0000000..cea45a1 --- /dev/null +++ b/designs/d11_gbailey_bfchip/dev/src/chip.sv @@ -0,0 +1,112 @@ +// Top module for tapeout: multiplexes BF's bus and connects to final ports +`default_nettype none + +// Name and ports are set by build system +module my_chip ( + input logic [11:0] io_in, // Inputs to your chip + output logic [11:0] io_out, // Outputs from your chip + input logic clock, + input logic reset // Important: Reset is ACTIVE-HIGH +); + + // Outputs / inputs + logic [7:0] bus_out; + IoOp state, next_state; + logic halted; + assign io_out = {halted, state, bus_out}; + + logic [7:0] bus_in; + assign bus_in = io_in[7:0]; + logic op_done; + assign op_done = io_in[8]; + logic enable; + assign enable = io_in[9]; + + // BF interface + logic [15:0] addr; + logic [7:0] val_in, val_out; + BusOp bus_op; + logic bf_enable; + + BF bf ( + .addr, + .val_in, + .val_out, + .bus_op, + .halted, + .clock, + .reset, + .enable(enable && bf_enable) + ); + + BusOp op_cache; + logic [15:0] addr_cache; + logic [7:0] val_cache; + + // Control signals + logic cache_out; + logic cache_in; + + always_comb begin + bf_enable = 0; + cache_out = 0; + cache_in = 0; + bus_out = '0; + + case (state) + IoNone: begin + bf_enable = 1; + cache_out = 1; + + if (bus_op != BusNone) + next_state = IoOpcode; + else + next_state = IoNone; + end + IoOpcode: begin + bus_out = {5'b0, op_cache}; + + next_state = IoAddrHi; + end + IoAddrHi: begin + bus_out = addr_cache[15:8]; + + next_state = IoAddrLo; + end + IoAddrLo: begin + bus_out = addr_cache[7:0]; + + next_state = IoReadWrite; + end + IoReadWrite: begin + bus_out = val_cache; + cache_in = 1; + + if (op_done) + next_state = IoNone; + else + next_state = IoReadWrite; + end + default: next_state = IoNone; + endcase + end + + always_ff @(posedge clock) + if (reset) begin + state <= IoNone; + op_cache <= BusNone; + addr_cache <= '0; + val_cache <= '0; + val_in <= '0; + end + else if (enable) begin + state <= next_state; + if (cache_out) begin + op_cache <= bus_op; + addr_cache <= addr; + val_cache <= val_out; + end + if (cache_in) val_in <= bus_in; + end + +endmodule diff --git a/designs/d11_gbailey_bfchip/dev/src/constraints.pcf b/designs/d11_gbailey_bfchip/dev/src/constraints.pcf new file mode 100644 index 0000000..ccf5f48 --- /dev/null +++ b/designs/d11_gbailey_bfchip/dev/src/constraints.pcf @@ -0,0 +1,86 @@ +# Constraints file for running on Alchitry Cu + +set_io clk100 P7 +set_io reset_n P8 + +set_io base_led[0] J11 +set_io base_led[1] K11 +set_io base_led[2] K12 +set_io base_led[3] K14 +set_io base_led[4] L12 +set_io base_led[5] L14 +set_io base_led[6] M12 +set_io base_led[7] N14 + +set_io uart_rx P14 +set_io uart_tx M9 + +set_io led[0] G14 +set_io led[1] F14 +set_io led[2] E12 +set_io led[3] E14 +set_io led[4] D14 +set_io led[5] C14 +set_io led[6] B14 +set_io led[7] A12 +set_io led[8] C10 +set_io led[9] C9 +set_io led[10] A11 +set_io led[11] A10 +set_io led[12] A7 +set_io led[13] A6 +set_io led[14] A4 +set_io led[15] A3 +set_io led[16] A2 +set_io led[17] A1 +set_io led[18] C3 +set_io led[19] D3 +set_io led[20] B1 +set_io led[21] C1 +set_io led[22] D1 +set_io led[23] E1 + +set_io sw[0] G12 +set_io sw[1] F12 +set_io sw[2] F11 +set_io sw[3] E11 +set_io sw[4] D12 +set_io sw[5] D11 +set_io sw[6] C12 +set_io sw[7] C11 +set_io sw[8] D10 +set_io sw[9] D9 +set_io sw[10] D7 +set_io sw[11] D6 +set_io sw[12] C7 +set_io sw[13] C6 +set_io sw[14] A5 +set_io sw[15] C5 +set_io sw[16] D5 +set_io sw[17] C4 +set_io sw[18] D4 +set_io sw[19] E4 +set_io sw[20] F4 +set_io sw[21] F3 +set_io sw[22] H4 +set_io sw[23] G4 + +set_io btn[0] G11 +set_io btn[1] H11 +set_io btn[2] H12 +set_io btn[3] J12 +set_io btn[4] P2 + +set_io display_sel[0] G3 +set_io display_sel[1] G1 +set_io display_sel[2] H1 +set_io display_sel[3] H3 + +set_io display[0] J1 +set_io display[1] J3 +set_io display[2] N1 +set_io display[3] K4 +set_io display[4] K3 +set_io display[5] L1 +set_io display[6] M1 +set_io display[7] P1 diff --git a/designs/d11_gbailey_bfchip/dev/src/consts.sv b/designs/d11_gbailey_bfchip/dev/src/consts.sv new file mode 100644 index 0000000..350c2be --- /dev/null +++ b/designs/d11_gbailey_bfchip/dev/src/consts.sv @@ -0,0 +1,124 @@ +// Types, constants, and functions used in the design +`default_nettype none + +typedef enum logic [2:0] { + IoNone = 3'b000, // No output on bus + IoOpcode = 3'b001, // Outputting opcode + IoAddrHi = 3'b010, // Outputting Address MSB + IoAddrLo = 3'b011, // Outputting Address LSB + IoReadWrite = 3'b100 // Outputting write / inputting read (waits until done) +} IoOp; + +typedef enum logic [2:0] { + BusNone = 3'b000, // No operation + BusReadProg = 3'b010, // Read program memory + BusReadData = 3'b100, // Read data memory + BusWriteData = 3'b101, // Write data memory + BusReadIo = 3'b110, // Read IO + BusWriteIo = 3'b111 // Write IO +} BusOp; + +typedef enum logic [1:0] { + AddrNone, + AddrPc, + AddrCursor +} AddrSrc; + +typedef enum logic [1:0] { + ValNone, + ValAcc, + ValAccInc, + ValAccDec +} ValSrc; + +typedef enum logic [1:0] { + PcKeep, + PcInc, + PcDec +} PcOp; + +typedef enum logic [1:0] { + CursorKeep, + CursorInc, + CursorDec +} CursorOp; + +typedef enum logic { + AccKeep, + AccLoad +} AccOp; + +typedef enum logic [1:0] { + DepthKeep, + DepthClear, + DepthInc, + DepthDec +} DepthOp; + +typedef struct packed { + BusOp bus_op; + AddrSrc addr_src; + ValSrc val_src; + PcOp pc_op; + CursorOp cursor_op; + AccOp acc_op; + DepthOp depth_op; +} Ucode; + +typedef enum logic [5:0] { + // Misc + Fetch, + Decode, + Halt, + + // Inc "+" + IncFetch, + IncLoad, + IncStore, + + // Dec "-" + DecFetch, + DecLoad, + DecStore, + + // Right ">" + Right, + + // Left "<" + Left, + + // Print "." + PrintFetch, + PrintLoad, + PrintStore, + + // Read "," + ReadFetch, + ReadLoad, + ReadStore, + + // Brz "[" + BrzFetchVal, + BrzDecodeVal, + BrzFetchInstr, + BrzDecodeInstr, + BrzInc, + BrzDec, + + // Brnz "]" + BrnzFetchVal, + BrnzDecodeVal, + BrnzPcDec1, + BrnzPcDec2, + BrnzFetchInstr, + BrnzDecodeInstr, + BrnzInc, + BrnzDec, + BrnzPcInc1, + BrnzPcInc2 +} BFState; + +// Simple max function for determining port sizes +function integer max(integer a, integer b); + max = (a > b) ? a : b; +endfunction diff --git a/designs/d11_gbailey_bfchip/dev/src/debugbus.sv b/designs/d11_gbailey_bfchip/dev/src/debugbus.sv new file mode 100644 index 0000000..2e6a7bf --- /dev/null +++ b/designs/d11_gbailey_bfchip/dev/src/debugbus.sv @@ -0,0 +1,1925 @@ +// Debug harness code generated from asinghani/wbdbgbus (in-class handout) +/* Generated by Yosys 0.25+83 (git sha1 755b753e1, aarch64-apple-darwin20.2-clang 10.0.0-4ubuntu1 -fPIC -Os) */ + +module debug_harness(uart_rx, uart_tx, chip_inputs, chip_outputs, chip_clock, chip_reset, clk100); + wire _0000_; + wire [11:0] _0001_; + wire _0002_; + wire [31:0] _0003_; + wire [2:0] _0004_; + wire _0005_; + wire [31:0] _0006_; + wire [31:0] _0007_; + wire [31:0] _0008_; + wire [31:0] _0009_; + wire [31:0] _0010_; + wire [31:0] _0011_; + wire [35:0] _0012_; + wire _0013_; + wire [35:0] _0014_; + wire _0015_; + wire _0016_; + wire _0017_; + wire [25:0] _0018_; + wire _0019_; + wire _0020_; + wire _0021_; + wire _0022_; + wire _0023_; + wire _0024_; + wire _0025_; + wire _0026_; + wire [39:0] _0027_; + wire [2:0] _0028_; + wire _0029_; + wire [35:0] _0030_; + wire _0031_; + wire [39:0] _0032_; + wire [2:0] _0033_; + wire [7:0] _0034_; + wire _0035_; + wire _0036_; + wire [35:0] _0037_; + wire _0038_; + wire _0039_; + wire _0040_; + wire [25:0] _0041_; + wire _0042_; + wire _0043_; + wire _0044_; + wire _0045_; + wire _0046_; + wire _0047_; + wire _0048_; + wire _0049_; + wire [39:0] _0050_; + wire [2:0] _0051_; + wire _0052_; + wire [35:0] _0053_; + wire _0054_; + wire [39:0] _0055_; + wire [2:0] _0056_; + wire _0057_; + wire [31:0] _0058_; + wire [31:0] _0059_; + wire _0060_; + wire _0061_; + wire _0062_; + wire _0063_; + wire _0064_; + wire _0065_; + wire _0066_; + wire _0067_; + wire _0068_; + wire _0069_; + wire _0070_; + wire _0071_; + wire _0072_; + wire _0073_; + wire _0074_; + wire _0075_; + wire _0076_; + wire _0077_; + wire _0078_; + wire _0079_; + wire _0080_; + wire _0081_; + wire _0082_; + wire _0083_; + wire _0084_; + wire _0085_; + wire _0086_; + wire _0087_; + wire _0088_; + wire _0089_; + wire _0090_; + wire _0091_; + wire _0092_; + wire _0093_; + wire _0094_; + wire _0095_; + wire _0096_; + wire _0097_; + wire _0098_; + wire _0099_; + wire _0100_; + wire _0101_; + wire _0102_; + wire _0103_; + wire _0104_; + wire _0105_; + wire _0106_; + wire [31:0] _0107_; + wire [3:0] _0108_; + wire [35:0] _0109_; + wire [35:0] _0110_; + wire [4:0] _0111_; + wire [35:0] _0112_; + wire _0113_; + wire [3:0] _0114_; + wire [3:0] _0115_; + wire [3:0] _0116_; + wire [35:0] _0117_; + wire [35:0] _0118_; + wire [4:0] _0119_; + wire _0120_; + wire [3:0] _0121_; + wire [3:0] _0122_; + wire [3:0] _0123_; + wire [35:0] _0124_; + wire [35:0] _0125_; + wire [31:0] _0126_; + wire [31:0] _0127_; + wire [31:0] _0128_; + wire _0129_; + wire _0130_; + wire _0131_; + wire _0132_; + wire _0133_; + wire _0134_; + wire [35:0] _0135_; + reg [3:0] _0136_; + reg [35:0] _0137_; + reg [35:0] _0138_; + wire _0139_; + wire _0140_; + wire _0141_; + wire _0142_; + wire _0143_; + wire [31:0] _0144_; + wire [3:0] _0145_; + wire [35:0] _0146_; + wire [35:0] _0147_; + wire [4:0] _0148_; + wire [35:0] _0149_; + wire _0150_; + wire [3:0] _0151_; + wire [3:0] _0152_; + wire [3:0] _0153_; + wire [35:0] _0154_; + wire [35:0] _0155_; + wire [4:0] _0156_; + wire _0157_; + wire [3:0] _0158_; + wire [3:0] _0159_; + wire [3:0] _0160_; + wire [35:0] _0161_; + wire [35:0] _0162_; + wire [31:0] _0163_; + wire [31:0] _0164_; + wire [31:0] _0165_; + wire _0166_; + wire _0167_; + wire _0168_; + wire _0169_; + wire _0170_; + wire _0171_; + wire [35:0] _0172_; + reg [3:0] _0173_; + reg [35:0] _0174_; + reg [35:0] _0175_; + wire _0176_; + wire _0177_; + wire _0178_; + wire _0179_; + wire _0180_; + wire [31:0] _0181_; + wire [7:0] _0182_; + wire [7:0] _0183_; + wire [31:0] _0184_; + wire [7:0] _0185_; + wire [9:0] _0186_; + wire [7:0] _0187_; + wire _0188_; + wire [3:0] _0189_; + wire [7:0] _0190_; + wire [7:0] _0191_; + wire [31:0] _0192_; + wire [7:0] _0193_; + wire [3:0] _0194_; + wire [7:0] _0195_; + wire [7:0] _0196_; + wire [31:0] _0197_; + wire [7:0] _0198_; + wire [7:0] _0199_; + wire [7:0] _0200_; + wire [31:0] _0201_; + wire [7:0] _0202_; + wire [31:0] _0203_; + wire [7:0] _0204_; + wire [7:0] _0205_; + reg [7:0] _0206_; + reg [7:0] _0207_; + reg [31:0] _0208_; + wire _0209_; + wire _0210_; + wire _0211_; + wire _0212_; + wire _0213_; + reg [7:0] _0214_; + wire [32:0] _0215_; + wire [32:0] _0216_; + wire [7:0] _0217_; + wire [7:0] _0218_; + wire [7:0] _0219_; + wire [7:0] _0220_; + wire [32:0] _0221_; + wire [32:0] _0222_; + wire [31:0] _0223_; + wire [31:0] _0224_; + wire [9:0] _0225_; + wire [7:0] _0226_; + wire _0227_; + wire [3:0] _0228_; + wire _0229_; + wire [3:0] _0230_; + wire _0231_; + wire _0232_; + wire [31:0] _0233_; + wire _0234_; + wire _0235_; + wire _0236_; + wire _0237_; + wire _0238_; + wire _0239_; + wire _0240_; + wire _0241_; + wire _0242_; + wire [31:0] _0243_; + wire [31:0] _0244_; + wire _0245_; + wire [35:0] _0246_; + wire _0247_; + wire [31:0] _0248_; + wire _0249_; + wire [31:0] _0250_; + wire _0251_; + wire _0252_; + wire _0253_; + wire _0254_; + wire [31:0] _0255_; + wire _0256_; + wire [31:0] _0257_; + wire _0258_; + wire _0259_; + wire [31:0] _0260_; + wire _0261_; + wire _0262_; + wire _0263_; + wire _0264_; + wire _0265_; + wire _0266_; + wire _0267_; + wire _0268_; + wire _0269_; + wire _0270_; + wire _0271_; + wire _0272_; + wire _0273_; + wire _0274_; + wire _0275_; + wire _0276_; + wire _0277_; + wire _0278_; + wire _0279_; + wire _0280_; + wire _0281_; + wire _0282_; + wire _0283_; + wire _0284_; + wire _0285_; + wire _0286_; + wire _0287_; + wire [35:0] _0288_; + wire _0289_; + wire _0290_; + wire _0291_; + wire _0292_; + wire _0293_; + wire _0294_; + wire _0295_; + wire _0296_; + wire _0297_; + wire _0298_; + wire _0299_; + wire _0300_; + wire _0301_; + wire _0302_; + wire _0303_; + wire _0304_; + wire _0305_; + wire _0306_; + wire _0307_; + wire _0308_; + wire _0309_; + wire _0310_; + wire _0311_; + wire _0312_; + wire _0313_; + wire _0314_; + wire _0315_; + wire _0316_; + wire _0317_; + wire _0318_; + wire _0319_; + wire _0320_; + wire _0321_; + wire _0322_; + wire _0323_; + wire _0324_; + wire _0325_; + wire _0326_; + wire _0327_; + wire _0328_; + wire _0329_; + wire _0330_; + wire _0331_; + wire _0332_; + wire _0333_; + wire _0334_; + wire _0335_; + wire _0336_; + wire _0337_; + wire _0338_; + wire _0339_; + wire _0340_; + wire _0341_; + wire _0342_; + wire _0343_; + wire _0344_; + wire _0345_; + wire _0346_; + wire _0347_; + wire [2:0] _0348_; + wire _0349_; + wire [2:0] _0350_; + wire _0351_; + wire [2:0] _0352_; + wire _0353_; + wire [2:0] _0354_; + wire _0355_; + wire [2:0] _0356_; + wire _0357_; + wire [2:0] _0358_; + wire _0359_; + wire [2:0] _0360_; + wire _0361_; + wire [2:0] _0362_; + wire _0363_; + wire [2:0] _0364_; + wire _0365_; + wire [39:0] _0366_; + wire _0367_; + wire [39:0] _0368_; + wire _0369_; + wire [39:0] _0370_; + wire _0371_; + wire [39:0] _0372_; + wire _0373_; + wire [39:0] _0374_; + wire _0375_; + wire [39:0] _0376_; + wire _0377_; + wire [39:0] _0378_; + wire _0379_; + wire [7:0] _0380_; + wire _0381_; + wire _0382_; + wire _0383_; + wire _0384_; + wire _0385_; + wire [7:0] _0386_; + wire _0387_; + wire [7:0] _0388_; + wire _0389_; + wire [7:0] _0390_; + wire _0391_; + wire [7:0] _0392_; + wire _0393_; + wire [7:0] _0394_; + wire _0395_; + wire [7:0] _0396_; + wire _0397_; + wire [7:0] _0398_; + wire _0399_; + wire [7:0] _0400_; + wire _0401_; + wire [7:0] _0402_; + wire _0403_; + wire [7:0] _0404_; + wire _0405_; + wire [7:0] _0406_; + wire _0407_; + wire [7:0] _0408_; + wire _0409_; + wire _0410_; + wire _0411_; + wire _0412_; + wire _0413_; + wire _0414_; + wire _0415_; + wire [25:0] _0416_; + wire _0417_; + wire [25:0] _0418_; + wire _0419_; + wire [2:0] _0420_; + wire _0421_; + wire [2:0] _0422_; + wire _0423_; + wire [2:0] _0424_; + wire _0425_; + wire [2:0] _0426_; + wire _0427_; + wire _0428_; + wire _0429_; + wire _0430_; + wire _0431_; + wire _0432_; + wire _0433_; + wire _0434_; + wire _0435_; + wire [35:0] _0436_; + wire _0437_; + wire [35:0] _0438_; + wire _0439_; + wire [35:0] _0440_; + wire _0441_; + wire [35:0] _0442_; + wire _0443_; + wire _0444_; + wire _0445_; + wire _0446_; + wire _0447_; + wire [35:0] _0448_; + wire _0449_; + wire [35:0] _0450_; + wire _0451_; + wire [35:0] _0452_; + wire _0453_; + wire [35:0] _0454_; + wire _0455_; + wire [35:0] _0456_; + wire _0457_; + wire [3:0] _0458_; + wire _0459_; + wire [3:0] _0460_; + wire _0461_; + wire [35:0] _0462_; + wire _0463_; + wire [35:0] _0464_; + wire _0465_; + wire [3:0] _0466_; + wire _0467_; + wire [3:0] _0468_; + wire _0469_; + wire [3:0] _0470_; + wire _0471_; + wire _0472_; + wire _0473_; + wire _0474_; + wire _0475_; + wire [3:0] _0476_; + wire _0477_; + wire [3:0] _0478_; + wire _0479_; + wire [35:0] _0480_; + wire _0481_; + wire [35:0] _0482_; + wire _0483_; + wire [4:0] _0484_; + wire _0485_; + wire [4:0] _0486_; + wire _0487_; + wire [4:0] _0488_; + wire _0489_; + wire [35:0] _0490_; + wire _0491_; + wire [35:0] _0492_; + wire _0493_; + wire [35:0] _0494_; + wire _0495_; + wire [35:0] _0496_; + wire _0497_; + wire [3:0] _0498_; + wire _0499_; + wire [3:0] _0500_; + wire _0501_; + wire [35:0] _0502_; + wire _0503_; + wire [35:0] _0504_; + wire _0505_; + wire [3:0] _0506_; + wire _0507_; + wire [3:0] _0508_; + wire _0509_; + wire [3:0] _0510_; + wire _0511_; + wire _0512_; + wire _0513_; + wire _0514_; + wire _0515_; + wire [3:0] _0516_; + wire _0517_; + wire [3:0] _0518_; + wire _0519_; + wire [35:0] _0520_; + wire _0521_; + wire [35:0] _0522_; + wire _0523_; + wire [4:0] _0524_; + wire _0525_; + wire [4:0] _0526_; + wire _0527_; + wire [4:0] _0528_; + wire _0529_; + wire [7:0] _0530_; + wire _0531_; + wire [7:0] _0532_; + wire _0533_; + wire [7:0] _0534_; + wire _0535_; + wire [31:0] _0536_; + wire _0537_; + wire [31:0] _0538_; + wire _0539_; + wire [31:0] _0540_; + wire _0541_; + wire [7:0] _0542_; + wire _0543_; + wire [7:0] _0544_; + wire _0545_; + wire [7:0] _0546_; + wire _0547_; + wire [7:0] _0548_; + wire _0549_; + wire [7:0] _0550_; + wire _0551_; + wire [7:0] _0552_; + wire _0553_; + wire [7:0] _0554_; + wire _0555_; + wire [7:0] _0556_; + wire _0557_; + wire [31:0] _0558_; + wire _0559_; + wire [31:0] _0560_; + wire _0561_; + wire [7:0] _0562_; + wire _0563_; + wire [7:0] _0564_; + wire _0565_; + wire [7:0] _0566_; + wire _0567_; + wire [7:0] _0568_; + wire _0569_; + wire [7:0] _0570_; + wire _0571_; + wire [31:0] _0572_; + wire _0573_; + wire [7:0] _0574_; + wire _0575_; + wire [7:0] _0576_; + wire _0577_; + wire [9:0] _0578_; + wire _0579_; + wire [9:0] _0580_; + wire _0581_; + wire [9:0] _0582_; + wire _0583_; + wire [9:0] _0584_; + wire _0585_; + wire _0586_; + wire _0587_; + wire _0588_; + wire _0589_; + wire _0590_; + wire _0591_; + wire _0592_; + wire _0593_; + wire [3:0] _0594_; + wire _0595_; + wire [3:0] _0596_; + wire _0597_; + wire [3:0] _0598_; + wire _0599_; + wire [3:0] _0600_; + wire _0601_; + wire _0602_; + wire _0603_; + wire _0604_; + wire _0605_; + wire _0606_; + wire _0607_; + wire _0608_; + wire _0609_; + wire _0610_; + wire _0611_; + wire _0612_; + wire _0613_; + wire [9:0] _0614_; + wire _0615_; + wire [9:0] _0616_; + wire _0617_; + wire [9:0] _0618_; + wire _0619_; + wire [9:0] _0620_; + wire _0621_; + wire [9:0] _0622_; + wire _0623_; + wire [7:0] _0624_; + wire _0625_; + wire [7:0] _0626_; + wire _0627_; + wire [3:0] _0628_; + wire _0629_; + wire [3:0] _0630_; + wire _0631_; + wire [3:0] _0632_; + wire _0633_; + wire [3:0] _0634_; + wire _0635_; + wire _0636_; + wire _0637_; + wire _0638_; + wire _0639_; + wire _0640_; + wire _0641_; + wire _0642_; + wire _0643_; + wire _0644_; + wire _0645_; + wire _0646_; + wire _0647_; + wire _0648_; + wire _0649_; + wire _0650_; + wire _0651_; + wire _0652_; + wire _0653_; + wire _0654_; + wire _0655_; + wire _0656_; + wire _0657_; + wire _0658_; + wire _0659_; + wire [31:0] _0660_; + wire _0661_; + wire [31:0] _0662_; + wire _0663_; + wire [31:0] _0664_; + wire _0665_; + wire _0666_; + wire _0667_; + wire [31:0] _0668_; + wire _0669_; + wire _0670_; + wire _0671_; + wire _0672_; + wire _0673_; + wire _0674_; + wire _0675_; + wire _0676_; + wire _0677_; + wire [35:0] _0678_; + wire _0679_; + wire [35:0] _0680_; + wire _0681_; + wire [35:0] _0682_; + wire _0683_; + wire [35:0] _0684_; + wire _0685_; + wire [35:0] _0686_; + wire _0687_; + wire _0688_; + wire _0689_; + wire [31:0] _0690_; + wire _0691_; + wire [31:0] _0692_; + wire _0693_; + wire _0694_; + wire _0695_; + wire _0696_; + wire _0697_; + wire _0698_; + wire _0699_; + wire _0700_; + wire _0701_; + wire [11:0] _0702_; + wire _0703_; + wire [11:0] _0704_; + wire _0705_; + output chip_clock; + reg chip_clock; + output [11:0] chip_inputs; + reg [11:0] chip_inputs; + input [11:0] chip_outputs; + wire [11:0] chip_outputs; + output chip_reset; + reg chip_reset; + wire clk; + input clk100; + wire clk100; + reg [31:0] data_in; + wire [31:0] data_out; + input uart_rx; + wire uart_rx; + reg [2:0] uart_rx_sync; + output uart_tx; + wire uart_tx; + reg wb_ack; + wire wb_cyc; + wire wb_stb; + wire wb_we; + reg [35:0] \wbdbg.cmd_data ; + wire \wbdbg.cmd_fifo.i_clk ; + wire \wbdbg.cmd_fifo.i_rd_en ; + wire \wbdbg.cmd_fifo.i_rst ; + wire [35:0] \wbdbg.cmd_fifo.i_wr_data ; + wire \wbdbg.cmd_fifo.i_wr_en ; + reg [4:0] \wbdbg.cmd_fifo.len = 5'h00; + wire \wbdbg.cmd_fifo.o_empty ; + wire \wbdbg.cmd_fifo.o_full ; + reg [35:0] \wbdbg.cmd_fifo.o_rd_data ; + reg \wbdbg.cmd_fifo.o_rd_valid = 1'h0; + reg [3:0] \wbdbg.cmd_fifo.rd_ptr = 4'h0; + reg [3:0] \wbdbg.cmd_fifo.wr_ptr = 4'h0; + wire \wbdbg.cmd_fifo_empty ; + wire \wbdbg.cmd_fifo_full ; + wire [35:0] \wbdbg.cmd_fifo_rd_data ; + reg \wbdbg.cmd_fifo_rd_en = 1'h0; + wire \wbdbg.cmd_fifo_rd_valid ; + reg [35:0] \wbdbg.cmd_fifo_wr_data = 36'h000000000; + reg \wbdbg.cmd_fifo_wr_en = 1'h0; + wire \wbdbg.cmd_ready ; + reg \wbdbg.cmd_reset = 1'h0; + reg \wbdbg.cmd_valid = 1'h0; + reg [25:0] \wbdbg.drop_timer = 26'h17d7840; + wire \wbdbg.i_clk ; + wire \wbdbg.i_interrupt_1 ; + wire \wbdbg.i_interrupt_2 ; + wire \wbdbg.i_interrupt_3 ; + wire \wbdbg.i_interrupt_4 ; + wire \wbdbg.i_rx ; + wire \wbdbg.i_wb_ack ; + wire [31:0] \wbdbg.i_wb_data ; + wire \wbdbg.i_wb_err ; + wire \wbdbg.i_wb_stall ; + reg \wbdbg.interrupt_1_last = 1'h0; + reg \wbdbg.interrupt_1_rising = 1'h0; + reg \wbdbg.interrupt_2_last = 1'h0; + reg \wbdbg.interrupt_2_rising = 1'h0; + reg \wbdbg.interrupt_3_last = 1'h0; + reg \wbdbg.interrupt_3_rising = 1'h0; + reg \wbdbg.interrupt_4_last = 1'h0; + reg \wbdbg.interrupt_4_rising = 1'h0; + wire \wbdbg.o_tx ; + wire [31:0] \wbdbg.o_wb_addr ; + wire \wbdbg.o_wb_cyc ; + wire [31:0] \wbdbg.o_wb_data ; + wire \wbdbg.o_wb_stb ; + wire \wbdbg.o_wb_we ; + reg [39:0] \wbdbg.recieve_data = 40'h0000000000; + reg [2:0] \wbdbg.recieve_state = 3'h0; + wire [35:0] \wbdbg.resp_data ; + wire \wbdbg.resp_fifo.i_clk ; + wire \wbdbg.resp_fifo.i_rd_en ; + wire \wbdbg.resp_fifo.i_rst ; + wire [35:0] \wbdbg.resp_fifo.i_wr_data ; + wire \wbdbg.resp_fifo.i_wr_en ; + reg [4:0] \wbdbg.resp_fifo.len = 5'h00; + wire \wbdbg.resp_fifo.o_empty ; + wire \wbdbg.resp_fifo.o_full ; + reg [35:0] \wbdbg.resp_fifo.o_rd_data ; + reg \wbdbg.resp_fifo.o_rd_valid = 1'h0; + reg [3:0] \wbdbg.resp_fifo.rd_ptr = 4'h0; + reg [3:0] \wbdbg.resp_fifo.wr_ptr = 4'h0; + wire \wbdbg.resp_fifo_empty ; + wire \wbdbg.resp_fifo_full ; + wire [35:0] \wbdbg.resp_fifo_rd_data ; + reg \wbdbg.resp_fifo_rd_en = 1'h0; + wire \wbdbg.resp_fifo_rd_valid ; + reg [35:0] \wbdbg.resp_fifo_wr_data = 36'h000000000; + reg \wbdbg.resp_fifo_wr_en = 1'h0; + wire \wbdbg.resp_valid ; + reg [39:0] \wbdbg.transmit_data = 40'h0000000000; + reg [2:0] \wbdbg.transmit_state = 3'h0; + reg [9:0] \wbdbg.uart_rx.counter ; + wire \wbdbg.uart_rx.i_clk ; + wire \wbdbg.uart_rx.i_in ; + reg [7:0] \wbdbg.uart_rx.o_data ; + reg \wbdbg.uart_rx.o_valid ; + reg [3:0] \wbdbg.uart_rx.state = 4'h0; + wire [7:0] \wbdbg.uart_rx_data ; + wire \wbdbg.uart_rx_valid ; + reg [9:0] \wbdbg.uart_tx.counter ; + reg [7:0] \wbdbg.uart_tx.data_send ; + wire \wbdbg.uart_tx.i_clk ; + wire [7:0] \wbdbg.uart_tx.i_data ; + wire \wbdbg.uart_tx.i_valid ; + wire \wbdbg.uart_tx.o_out ; + wire \wbdbg.uart_tx.o_ready ; + reg [3:0] \wbdbg.uart_tx.state = 4'h0; + reg [7:0] \wbdbg.uart_tx_data ; + wire \wbdbg.uart_tx_ready ; + reg \wbdbg.uart_tx_valid = 1'h0; + reg \wbdbg.wbdbgbusmaster.addr_inc = 1'h0; + wire [31:0] \wbdbg.wbdbgbusmaster.cmd_data ; + wire [3:0] \wbdbg.wbdbgbusmaster.cmd_inst ; + wire \wbdbg.wbdbgbusmaster.cmd_recv ; + wire \wbdbg.wbdbgbusmaster.i_clk ; + wire [35:0] \wbdbg.wbdbgbusmaster.i_cmd_data ; + wire \wbdbg.wbdbgbusmaster.i_cmd_reset ; + wire \wbdbg.wbdbgbusmaster.i_cmd_valid ; + wire \wbdbg.wbdbgbusmaster.i_wb_ack ; + wire [31:0] \wbdbg.wbdbgbusmaster.i_wb_data ; + wire \wbdbg.wbdbgbusmaster.i_wb_err ; + wire \wbdbg.wbdbgbusmaster.i_wb_stall ; + wire \wbdbg.wbdbgbusmaster.o_cmd_ready ; + reg [35:0] \wbdbg.wbdbgbusmaster.o_resp_data ; + reg \wbdbg.wbdbgbusmaster.o_resp_valid = 1'h0; + reg [31:0] \wbdbg.wbdbgbusmaster.o_wb_addr = 32'd0; + reg \wbdbg.wbdbgbusmaster.o_wb_cyc = 1'h0; + reg [31:0] \wbdbg.wbdbgbusmaster.o_wb_data = 32'd0; + reg \wbdbg.wbdbgbusmaster.o_wb_stb = 1'h0; + reg \wbdbg.wbdbgbusmaster.o_wb_we = 1'h0; + reg [35:0] \wbdbg.cmd_fifo.ram [15:0]; + always @(posedge \wbdbg.cmd_fifo.i_clk ) begin + if (_0118_[0]) + \wbdbg.cmd_fifo.ram [_0116_][0:0] <= _0117_[0]; + if (_0118_[1]) + \wbdbg.cmd_fifo.ram [_0116_][1:1] <= _0117_[1]; + if (_0118_[2]) + \wbdbg.cmd_fifo.ram [_0116_][2:2] <= _0117_[2]; + if (_0118_[3]) + \wbdbg.cmd_fifo.ram [_0116_][3:3] <= _0117_[3]; + if (_0118_[4]) + \wbdbg.cmd_fifo.ram [_0116_][4:4] <= _0117_[4]; + if (_0118_[5]) + \wbdbg.cmd_fifo.ram [_0116_][5:5] <= _0117_[5]; + if (_0118_[6]) + \wbdbg.cmd_fifo.ram [_0116_][6:6] <= _0117_[6]; + if (_0118_[7]) + \wbdbg.cmd_fifo.ram [_0116_][7:7] <= _0117_[7]; + if (_0118_[8]) + \wbdbg.cmd_fifo.ram [_0116_][8:8] <= _0117_[8]; + if (_0118_[9]) + \wbdbg.cmd_fifo.ram [_0116_][9:9] <= _0117_[9]; + if (_0118_[10]) + \wbdbg.cmd_fifo.ram [_0116_][10:10] <= _0117_[10]; + if (_0118_[11]) + \wbdbg.cmd_fifo.ram [_0116_][11:11] <= _0117_[11]; + if (_0118_[12]) + \wbdbg.cmd_fifo.ram [_0116_][12:12] <= _0117_[12]; + if (_0118_[13]) + \wbdbg.cmd_fifo.ram [_0116_][13:13] <= _0117_[13]; + if (_0118_[14]) + \wbdbg.cmd_fifo.ram [_0116_][14:14] <= _0117_[14]; + if (_0118_[15]) + \wbdbg.cmd_fifo.ram [_0116_][15:15] <= _0117_[15]; + if (_0118_[16]) + \wbdbg.cmd_fifo.ram [_0116_][16:16] <= _0117_[16]; + if (_0118_[17]) + \wbdbg.cmd_fifo.ram [_0116_][17:17] <= _0117_[17]; + if (_0118_[18]) + \wbdbg.cmd_fifo.ram [_0116_][18:18] <= _0117_[18]; + if (_0118_[19]) + \wbdbg.cmd_fifo.ram [_0116_][19:19] <= _0117_[19]; + if (_0118_[20]) + \wbdbg.cmd_fifo.ram [_0116_][20:20] <= _0117_[20]; + if (_0118_[21]) + \wbdbg.cmd_fifo.ram [_0116_][21:21] <= _0117_[21]; + if (_0118_[22]) + \wbdbg.cmd_fifo.ram [_0116_][22:22] <= _0117_[22]; + if (_0118_[23]) + \wbdbg.cmd_fifo.ram [_0116_][23:23] <= _0117_[23]; + if (_0118_[24]) + \wbdbg.cmd_fifo.ram [_0116_][24:24] <= _0117_[24]; + if (_0118_[25]) + \wbdbg.cmd_fifo.ram [_0116_][25:25] <= _0117_[25]; + if (_0118_[26]) + \wbdbg.cmd_fifo.ram [_0116_][26:26] <= _0117_[26]; + if (_0118_[27]) + \wbdbg.cmd_fifo.ram [_0116_][27:27] <= _0117_[27]; + if (_0118_[28]) + \wbdbg.cmd_fifo.ram [_0116_][28:28] <= _0117_[28]; + if (_0118_[29]) + \wbdbg.cmd_fifo.ram [_0116_][29:29] <= _0117_[29]; + if (_0118_[30]) + \wbdbg.cmd_fifo.ram [_0116_][30:30] <= _0117_[30]; + if (_0118_[31]) + \wbdbg.cmd_fifo.ram [_0116_][31:31] <= _0117_[31]; + if (_0118_[32]) + \wbdbg.cmd_fifo.ram [_0116_][32:32] <= _0117_[32]; + if (_0118_[33]) + \wbdbg.cmd_fifo.ram [_0116_][33:33] <= _0117_[33]; + if (_0118_[34]) + \wbdbg.cmd_fifo.ram [_0116_][34:34] <= _0117_[34]; + if (_0118_[35]) + \wbdbg.cmd_fifo.ram [_0116_][35:35] <= _0117_[35]; + end + assign _0135_ = \wbdbg.cmd_fifo.ram [\wbdbg.cmd_fifo.rd_ptr ]; + reg [35:0] \wbdbg.resp_fifo.ram [15:0]; + always @(posedge \wbdbg.resp_fifo.i_clk ) begin + if (_0155_[0]) + \wbdbg.resp_fifo.ram [_0153_][0:0] <= _0154_[0]; + if (_0155_[1]) + \wbdbg.resp_fifo.ram [_0153_][1:1] <= _0154_[1]; + if (_0155_[2]) + \wbdbg.resp_fifo.ram [_0153_][2:2] <= _0154_[2]; + if (_0155_[3]) + \wbdbg.resp_fifo.ram [_0153_][3:3] <= _0154_[3]; + if (_0155_[4]) + \wbdbg.resp_fifo.ram [_0153_][4:4] <= _0154_[4]; + if (_0155_[5]) + \wbdbg.resp_fifo.ram [_0153_][5:5] <= _0154_[5]; + if (_0155_[6]) + \wbdbg.resp_fifo.ram [_0153_][6:6] <= _0154_[6]; + if (_0155_[7]) + \wbdbg.resp_fifo.ram [_0153_][7:7] <= _0154_[7]; + if (_0155_[8]) + \wbdbg.resp_fifo.ram [_0153_][8:8] <= _0154_[8]; + if (_0155_[9]) + \wbdbg.resp_fifo.ram [_0153_][9:9] <= _0154_[9]; + if (_0155_[10]) + \wbdbg.resp_fifo.ram [_0153_][10:10] <= _0154_[10]; + if (_0155_[11]) + \wbdbg.resp_fifo.ram [_0153_][11:11] <= _0154_[11]; + if (_0155_[12]) + \wbdbg.resp_fifo.ram [_0153_][12:12] <= _0154_[12]; + if (_0155_[13]) + \wbdbg.resp_fifo.ram [_0153_][13:13] <= _0154_[13]; + if (_0155_[14]) + \wbdbg.resp_fifo.ram [_0153_][14:14] <= _0154_[14]; + if (_0155_[15]) + \wbdbg.resp_fifo.ram [_0153_][15:15] <= _0154_[15]; + if (_0155_[16]) + \wbdbg.resp_fifo.ram [_0153_][16:16] <= _0154_[16]; + if (_0155_[17]) + \wbdbg.resp_fifo.ram [_0153_][17:17] <= _0154_[17]; + if (_0155_[18]) + \wbdbg.resp_fifo.ram [_0153_][18:18] <= _0154_[18]; + if (_0155_[19]) + \wbdbg.resp_fifo.ram [_0153_][19:19] <= _0154_[19]; + if (_0155_[20]) + \wbdbg.resp_fifo.ram [_0153_][20:20] <= _0154_[20]; + if (_0155_[21]) + \wbdbg.resp_fifo.ram [_0153_][21:21] <= _0154_[21]; + if (_0155_[22]) + \wbdbg.resp_fifo.ram [_0153_][22:22] <= _0154_[22]; + if (_0155_[23]) + \wbdbg.resp_fifo.ram [_0153_][23:23] <= _0154_[23]; + if (_0155_[24]) + \wbdbg.resp_fifo.ram [_0153_][24:24] <= _0154_[24]; + if (_0155_[25]) + \wbdbg.resp_fifo.ram [_0153_][25:25] <= _0154_[25]; + if (_0155_[26]) + \wbdbg.resp_fifo.ram [_0153_][26:26] <= _0154_[26]; + if (_0155_[27]) + \wbdbg.resp_fifo.ram [_0153_][27:27] <= _0154_[27]; + if (_0155_[28]) + \wbdbg.resp_fifo.ram [_0153_][28:28] <= _0154_[28]; + if (_0155_[29]) + \wbdbg.resp_fifo.ram [_0153_][29:29] <= _0154_[29]; + if (_0155_[30]) + \wbdbg.resp_fifo.ram [_0153_][30:30] <= _0154_[30]; + if (_0155_[31]) + \wbdbg.resp_fifo.ram [_0153_][31:31] <= _0154_[31]; + if (_0155_[32]) + \wbdbg.resp_fifo.ram [_0153_][32:32] <= _0154_[32]; + if (_0155_[33]) + \wbdbg.resp_fifo.ram [_0153_][33:33] <= _0154_[33]; + if (_0155_[34]) + \wbdbg.resp_fifo.ram [_0153_][34:34] <= _0154_[34]; + if (_0155_[35]) + \wbdbg.resp_fifo.ram [_0153_][35:35] <= _0154_[35]; + end + assign _0172_ = \wbdbg.resp_fifo.ram [\wbdbg.resp_fifo.rd_ptr ]; + assign _0058_ = \wbdbg.transmit_state + 32'd1; + assign _0059_ = \wbdbg.recieve_state + 32'd1; + assign _0060_ = ! \wbdbg.transmit_state ; + assign _0062_ = \wbdbg.transmit_state == 3'h5; + assign _0063_ = \wbdbg.recieve_state == 3'h4; + assign _0064_ = \wbdbg.recieve_data [35:32] == 4'hf; + assign _0065_ = \wbdbg.drop_timer == 26'h0000001; + assign _0066_ = \wbdbg.recieve_state > 32'd0; + assign _0067_ = \wbdbg.resp_valid && _0087_; + assign _0072_ = _0060_ && _0092_; + assign _0073_ = _0072_ && _0093_; + assign _0074_ = _0073_ && _0094_; + assign _0075_ = _0074_ && _0095_; + assign _0076_ = _0075_ && _0096_; + assign _0077_ = _0076_ && _0097_; + assign _0078_ = _0077_ && _0098_; + assign _0079_ = \wbdbg.uart_tx_ready && _0099_; + assign _0080_ = _0101_ && \wbdbg.cmd_ready ; + assign _0081_ = _0080_ && _0102_; + assign _0082_ = _0081_ && _0103_; + assign _0083_ = _0082_ && _0104_; + assign _0084_ = _0083_ && _0105_; + assign _0085_ = \wbdbg.cmd_ready && \wbdbg.cmd_fifo_rd_valid ; + assign _0086_ = _0085_ && _0106_; + assign _0087_ = ~ \wbdbg.resp_fifo_full ; + assign _0088_ = ~ \wbdbg.interrupt_1_last ; + assign _0089_ = ~ \wbdbg.interrupt_2_last ; + assign _0090_ = ~ \wbdbg.interrupt_3_last ; + assign _0091_ = ~ \wbdbg.interrupt_4_last ; + assign _0092_ = ~ \wbdbg.resp_fifo_empty ; + assign _0093_ = ~ \wbdbg.resp_fifo_rd_valid ; + assign _0094_ = ~ \wbdbg.resp_fifo_rd_en ; + assign _0095_ = ~ \wbdbg.interrupt_1_rising ; + assign _0096_ = ~ \wbdbg.interrupt_2_rising ; + assign _0097_ = ~ \wbdbg.interrupt_3_rising ; + assign _0098_ = ~ \wbdbg.interrupt_4_rising ; + assign _0099_ = ~ \wbdbg.uart_tx_valid ; + assign _0100_ = ~ \wbdbg.cmd_fifo_full ; + assign _0101_ = ~ \wbdbg.cmd_reset ; + assign _0102_ = ~ \wbdbg.cmd_fifo_empty ; + assign _0103_ = ~ \wbdbg.cmd_fifo_rd_en ; + assign _0104_ = ~ \wbdbg.cmd_fifo_rd_valid ; + assign _0105_ = ~ \wbdbg.cmd_valid ; + assign _0107_ = \wbdbg.drop_timer - 32'd1; + assign _0126_ = \wbdbg.cmd_fifo.wr_ptr + 32'd1; + assign _0127_ = \wbdbg.cmd_fifo.rd_ptr + 32'd1; + assign _0128_ = \wbdbg.cmd_fifo.len + 32'd1; + assign _0129_ = ! \wbdbg.cmd_fifo.len ; + assign _0130_ = \wbdbg.cmd_fifo.len == 5'h10; + assign _0131_ = \wbdbg.cmd_fifo.i_rd_en && _0140_; + assign _0132_ = _0131_ && _0141_; + assign _0133_ = \wbdbg.cmd_fifo.i_wr_en && _0142_; + assign _0134_ = _0133_ && _0143_; + assign _0140_ = ~ \wbdbg.cmd_fifo.i_wr_en ; + assign _0144_ = \wbdbg.cmd_fifo.len - 32'd1; + assign _0163_ = \wbdbg.resp_fifo.wr_ptr + 32'd1; + assign _0164_ = \wbdbg.resp_fifo.rd_ptr + 32'd1; + assign _0165_ = \wbdbg.resp_fifo.len + 32'd1; + assign _0166_ = ! \wbdbg.resp_fifo.len ; + assign _0167_ = \wbdbg.resp_fifo.len == 5'h10; + assign _0168_ = \wbdbg.resp_fifo.i_rd_en && _0177_; + assign _0169_ = _0168_ && _0178_; + assign _0170_ = \wbdbg.resp_fifo.i_wr_en && _0179_; + assign _0171_ = _0170_ && _0180_; + assign _0177_ = ~ \wbdbg.resp_fifo.i_wr_en ; + assign _0181_ = \wbdbg.resp_fifo.len - 32'd1; + assign _0203_ = \wbdbg.uart_rx.state + 32'd1; + assign _0205_ = \wbdbg.uart_rx.o_data & _0217_; + assign _0209_ = ! \wbdbg.uart_rx.state ; + assign _0210_ = ~ \wbdbg.uart_rx.i_in ; + assign _0211_ = ! \wbdbg.uart_rx.counter ; + assign _0212_ = \wbdbg.uart_rx.state == 4'h9; + assign _0216_ = - $signed(_0222_); + assign _0217_ = ~ _0219_; + assign _0218_ = _0205_ | _0220_; + assign _0219_ = $signed(_0215_) < 0 ? 1'h1 << - _0215_ : 1'h1 >> _0215_; + assign _0220_ = $signed(_0216_) < 0 ? uart_rx_sync[2] << - _0216_ : uart_rx_sync[2] >> _0216_; + assign _0222_ = + $signed({ 1'h0, _0223_ }); + assign _0223_ = \wbdbg.uart_rx.state - 32'd1; + assign _0224_ = \wbdbg.uart_rx.counter - 32'd1; + assign _0233_ = \wbdbg.uart_tx.state + 32'd1; + assign _0236_ = ! \wbdbg.uart_tx.counter ; + assign _0239_ = ! \wbdbg.uart_tx.state ; + assign _0240_ = \wbdbg.uart_tx.state == 4'h1; + assign _0241_ = \wbdbg.uart_tx.state == 4'ha; + wire [7:0] _1087_ = \wbdbg.uart_tx.data_send ; + assign _0242_ = _1087_[$signed(_0244_) +: 1]; + assign _0243_ = \wbdbg.uart_tx.counter - 32'd1; + assign _0244_ = \wbdbg.uart_tx.state - 32'd2; + assign _0260_ = \wbdbg.wbdbgbusmaster.o_wb_addr + \wbdbg.wbdbgbusmaster.addr_inc ; + assign _0261_ = \wbdbg.wbdbgbusmaster.cmd_inst == 4'h1; + assign _0266_ = \wbdbg.wbdbgbusmaster.cmd_inst == 4'h2; + assign _0267_ = \wbdbg.wbdbgbusmaster.cmd_inst == 4'h3; + assign _0268_ = \wbdbg.wbdbgbusmaster.cmd_inst == 4'h7; + assign _0269_ = \wbdbg.wbdbgbusmaster.i_cmd_valid && \wbdbg.wbdbgbusmaster.o_cmd_ready ; + assign _0270_ = \wbdbg.wbdbgbusmaster.cmd_recv && _0278_; + assign _0272_ = \wbdbg.wbdbgbusmaster.cmd_recv && _0266_; + assign _0274_ = \wbdbg.wbdbgbusmaster.o_wb_cyc && \wbdbg.wbdbgbusmaster.i_wb_ack ; + assign _0275_ = \wbdbg.wbdbgbusmaster.cmd_recv && _0280_; + assign _0278_ = _0261_ || _0262_; + assign _0280_ = _0267_ || _0268_; + assign _0283_ = ~ \wbdbg.wbdbgbusmaster.o_wb_cyc ; + assign _0285_ = wb_cyc && wb_stb; + always @(posedge \wbdbg.i_clk ) + \wbdbg.interrupt_1_last <= 1'h0; + always @(posedge \wbdbg.i_clk ) + \wbdbg.interrupt_2_last <= 1'h0; + always @(posedge \wbdbg.i_clk ) + \wbdbg.interrupt_3_last <= 1'h0; + always @(posedge \wbdbg.i_clk ) + \wbdbg.interrupt_4_last <= 1'h0; + always @(posedge \wbdbg.i_clk ) + \wbdbg.resp_fifo_wr_en <= _0286_; + always @(posedge \wbdbg.i_clk ) + \wbdbg.resp_fifo_wr_data <= _0288_; + always @(posedge \wbdbg.i_clk ) + \wbdbg.uart_tx_data <= _0388_; + always @(posedge \wbdbg.i_clk ) + \wbdbg.uart_tx_valid <= _0294_; + always @(posedge \wbdbg.i_clk ) + \wbdbg.resp_fifo_rd_en <= _0290_; + always @(posedge \wbdbg.i_clk ) + \wbdbg.transmit_data <= _0378_; + always @(posedge \wbdbg.i_clk ) + \wbdbg.transmit_state <= _0364_; + always @(posedge \wbdbg.i_clk ) + \wbdbg.interrupt_1_rising <= _0346_; + always @(posedge \wbdbg.i_clk ) + \wbdbg.interrupt_2_rising <= _0336_; + always @(posedge \wbdbg.i_clk ) + \wbdbg.interrupt_3_rising <= _0324_; + always @(posedge \wbdbg.i_clk ) + \wbdbg.interrupt_4_rising <= _0310_; + always @(posedge \wbdbg.i_clk ) + \wbdbg.cmd_reset <= _0414_; + always @(posedge \wbdbg.i_clk ) + \wbdbg.cmd_fifo_wr_en <= _0434_; + always @(posedge \wbdbg.i_clk ) + \wbdbg.cmd_fifo_wr_data <= _0442_; + always @(posedge \wbdbg.i_clk ) + \wbdbg.recieve_data <= { _0408_, _0404_, _0400_, _0392_, _0396_ }; + always @(posedge \wbdbg.i_clk ) + \wbdbg.recieve_state <= _0426_; + always @(posedge \wbdbg.i_clk ) + \wbdbg.drop_timer <= _0418_; + always @(posedge \wbdbg.i_clk ) + \wbdbg.cmd_valid <= _0446_; + always @(posedge \wbdbg.i_clk ) + \wbdbg.cmd_data <= _0448_; + always @(posedge \wbdbg.i_clk ) + \wbdbg.cmd_fifo_rd_en <= _0444_; + always @(posedge \wbdbg.cmd_fifo.i_clk ) + \wbdbg.cmd_fifo.wr_ptr <= _0470_; + always @(posedge \wbdbg.cmd_fifo.i_clk ) + _0136_ <= _0466_; + always @(posedge \wbdbg.cmd_fifo.i_clk ) + _0137_ <= _0464_; + always @(posedge \wbdbg.cmd_fifo.i_clk ) + _0138_ <= _0462_; + always @(posedge \wbdbg.cmd_fifo.i_clk ) + \wbdbg.cmd_fifo.o_rd_data <= _0482_; + always @(posedge \wbdbg.cmd_fifo.i_clk ) + \wbdbg.cmd_fifo.o_rd_valid <= _0474_; + always @(posedge \wbdbg.cmd_fifo.i_clk ) + \wbdbg.cmd_fifo.rd_ptr <= _0478_; + always @(posedge \wbdbg.cmd_fifo.i_clk ) + \wbdbg.cmd_fifo.len <= _0488_; + always @(posedge \wbdbg.resp_fifo.i_clk ) + \wbdbg.resp_fifo.wr_ptr <= _0510_; + always @(posedge \wbdbg.resp_fifo.i_clk ) + _0173_ <= _0506_; + always @(posedge \wbdbg.resp_fifo.i_clk ) + _0174_ <= _0504_; + always @(posedge \wbdbg.resp_fifo.i_clk ) + _0175_ <= _0502_; + always @(posedge \wbdbg.resp_fifo.i_clk ) + \wbdbg.resp_fifo.o_rd_data <= _0522_; + always @(posedge \wbdbg.resp_fifo.i_clk ) + \wbdbg.resp_fifo.o_rd_valid <= _0514_; + always @(posedge \wbdbg.resp_fifo.i_clk ) + \wbdbg.resp_fifo.rd_ptr <= _0518_; + always @(posedge \wbdbg.resp_fifo.i_clk ) + \wbdbg.resp_fifo.len <= _0528_; + always @(posedge \wbdbg.uart_rx.i_clk ) + \wbdbg.uart_rx.o_data <= _0570_; + always @(posedge \wbdbg.uart_rx.i_clk ) + \wbdbg.uart_rx.o_valid <= _0592_; + always @(posedge \wbdbg.uart_rx.i_clk ) + \wbdbg.uart_rx.counter <= _0584_; + always @(posedge \wbdbg.uart_rx.i_clk ) + \wbdbg.uart_rx.state <= _0600_; + always @(posedge \wbdbg.uart_rx.i_clk ) + _0207_ <= 8'hxx; + always @(posedge \wbdbg.uart_rx.i_clk ) + _0206_ <= 8'hxx; + always @(posedge \wbdbg.uart_rx.i_clk ) + _0208_ <= 32'hxxxxxxxx; + always @(posedge \wbdbg.uart_rx.i_clk ) + _0214_ <= 8'hxx; + always @(posedge \wbdbg.uart_tx.i_clk ) + \wbdbg.uart_tx.counter <= _0622_; + always @(posedge \wbdbg.uart_tx.i_clk ) + \wbdbg.uart_tx.state <= _0634_; + always @(posedge \wbdbg.uart_tx.i_clk ) + \wbdbg.uart_tx.data_send <= _0626_; + always @(posedge \wbdbg.wbdbgbusmaster.i_clk ) + \wbdbg.wbdbgbusmaster.o_wb_cyc <= _0654_; + always @(posedge \wbdbg.wbdbgbusmaster.i_clk ) + \wbdbg.wbdbgbusmaster.o_wb_stb <= _0644_; + always @(posedge \wbdbg.wbdbgbusmaster.i_clk ) + \wbdbg.wbdbgbusmaster.o_wb_addr <= _0664_; + always @(posedge \wbdbg.wbdbgbusmaster.i_clk ) + \wbdbg.wbdbgbusmaster.addr_inc <= _0658_; + always @(posedge \wbdbg.wbdbgbusmaster.i_clk ) + \wbdbg.wbdbgbusmaster.o_wb_we <= _0666_; + always @(posedge \wbdbg.wbdbgbusmaster.i_clk ) + \wbdbg.wbdbgbusmaster.o_wb_data <= _0668_; + always @(posedge \wbdbg.wbdbgbusmaster.i_clk ) + \wbdbg.wbdbgbusmaster.o_resp_valid <= _0676_; + always @(posedge \wbdbg.wbdbgbusmaster.i_clk ) + \wbdbg.wbdbgbusmaster.o_resp_data <= _0686_; + always @(posedge clk) + uart_rx_sync <= { uart_rx_sync[1:0], uart_rx }; + always @(posedge clk) + chip_inputs <= _0704_; + always @(posedge clk) + chip_clock <= _0700_; + always @(posedge clk) + chip_reset <= _0696_; + always @(posedge clk) + wb_ack <= _0688_; + always @(posedge clk) + data_in <= _0692_; + assign _0286_ = _0287_ ? 1'h1 : 1'h0; + assign _0288_ = _0289_ ? \wbdbg.wbdbgbusmaster.o_resp_data : \wbdbg.resp_fifo_wr_data ; + assign _0290_ = _0291_ ? 1'h1 : 1'h0; + assign _0292_ = _0293_ ? 1'h1 : 1'h0; + assign _0294_ = _0295_ ? 1'h0 : _0292_; + assign _0298_ = _0299_ ? 1'h0 : _0296_; + assign _0300_ = _0301_ ? _0296_ : _0298_; + assign _0302_ = _0303_ ? _0296_ : _0300_; + assign _0304_ = _0305_ ? _0296_ : _0302_; + assign _0306_ = _0307_ ? _0296_ : _0304_; + assign _0308_ = _0309_ ? _0296_ : _0306_; + assign _0310_ = _0311_ ? _0308_ : _0296_; + assign _0314_ = _0315_ ? 1'h0 : _0312_; + assign _0316_ = _0317_ ? _0312_ : _0314_; + assign _0318_ = _0319_ ? _0312_ : _0316_; + assign _0320_ = _0321_ ? _0312_ : _0318_; + assign _0322_ = _0323_ ? _0312_ : _0320_; + assign _0324_ = _0325_ ? _0322_ : _0312_; + assign _0328_ = _0329_ ? 1'h0 : _0326_; + assign _0330_ = _0331_ ? _0326_ : _0328_; + assign _0332_ = _0333_ ? _0326_ : _0330_; + assign _0334_ = _0335_ ? _0326_ : _0332_; + assign _0336_ = _0337_ ? _0334_ : _0326_; + assign _0340_ = _0341_ ? 1'h0 : _0338_; + assign _0342_ = _0343_ ? _0338_ : _0340_; + assign _0344_ = _0345_ ? _0338_ : _0342_; + assign _0346_ = _0347_ ? _0344_ : _0338_; + assign _0348_ = _0349_ ? 3'h0 : _0058_[2:0]; + assign _0350_ = _0351_ ? _0348_ : \wbdbg.transmit_state ; + assign _0352_ = _0353_ ? 3'h1 : \wbdbg.transmit_state ; + assign _0354_ = _0355_ ? 3'h1 : _0352_; + assign _0356_ = _0357_ ? 3'h1 : _0354_; + assign _0358_ = _0359_ ? 3'h1 : _0356_; + assign _0360_ = _0361_ ? \wbdbg.transmit_state : _0358_; + assign _0362_ = _0363_ ? 3'h1 : _0360_; + assign _0364_ = _0365_ ? _0362_ : _0350_; + assign _0366_ = _0367_ ? 40'h0b00000000 : \wbdbg.transmit_data ; + assign _0368_ = _0369_ ? 40'h0a00000000 : _0366_; + assign _0370_ = _0371_ ? 40'h0900000000 : _0368_; + assign _0372_ = _0373_ ? 40'h0800000000 : _0370_; + assign _0374_ = _0375_ ? \wbdbg.transmit_data : _0372_; + assign _0376_ = _0377_ ? { 4'h0, \wbdbg.resp_fifo.o_rd_data } : _0374_; + assign _0378_ = _0379_ ? _0376_ : \wbdbg.transmit_data ; + function [7:0] _0920_; + input [7:0] a; + input [39:0] b; + input [4:0] s; + casez (s) // synopsys parallel_case + 5'b????1: + _0920_ = b[7:0]; + 5'b???1?: + _0920_ = b[15:8]; + 5'b??1??: + _0920_ = b[23:16]; + 5'b?1???: + _0920_ = b[31:24]; + 5'b1????: + _0920_ = b[39:32]; + default: + _0920_ = a; + endcase + endfunction + assign _0380_ = _0920_(8'h00, \wbdbg.transmit_data , { _0385_, _0384_, _0383_, _0382_, _0381_ }); + assign _0381_ = \wbdbg.transmit_state == 3'h5; + assign _0382_ = \wbdbg.transmit_state == 3'h4; + assign _0383_ = \wbdbg.transmit_state == 3'h3; + assign _0384_ = \wbdbg.transmit_state == 3'h2; + assign _0385_ = \wbdbg.transmit_state == 3'h1; + assign _0386_ = _0387_ ? _0380_ : \wbdbg.uart_tx_data ; + assign _0388_ = _0389_ ? \wbdbg.uart_tx_data : _0386_; + assign _0390_ = _0391_ ? \wbdbg.uart_rx.o_data : \wbdbg.recieve_data [15:8]; + assign _0391_ = \wbdbg.recieve_state == 3'h3; + assign _0392_ = _0393_ ? _0390_ : \wbdbg.recieve_data [15:8]; + assign _0394_ = _0395_ ? \wbdbg.uart_rx.o_data : \wbdbg.recieve_data [7:0]; + assign _0395_ = \wbdbg.recieve_state == 3'h4; + assign _0396_ = _0397_ ? _0394_ : \wbdbg.recieve_data [7:0]; + assign _0398_ = _0399_ ? \wbdbg.uart_rx.o_data : \wbdbg.recieve_data [23:16]; + assign _0399_ = \wbdbg.recieve_state == 3'h2; + assign _0400_ = _0401_ ? _0398_ : \wbdbg.recieve_data [23:16]; + assign _0402_ = _0403_ ? \wbdbg.uart_rx.o_data : \wbdbg.recieve_data [31:24]; + assign _0403_ = \wbdbg.recieve_state == 3'h1; + assign _0404_ = _0405_ ? _0402_ : \wbdbg.recieve_data [31:24]; + assign _0406_ = _0407_ ? \wbdbg.uart_rx.o_data : \wbdbg.recieve_data [39:32]; + assign _0407_ = ! \wbdbg.recieve_state ; + assign _0408_ = _0409_ ? _0406_ : \wbdbg.recieve_data [39:32]; + assign _0410_ = _0411_ ? 1'h1 : 1'h0; + assign _0412_ = _0413_ ? _0410_ : 1'h0; + assign _0414_ = _0415_ ? _0412_ : 1'h0; + assign _0416_ = _0417_ ? _0107_[25:0] : \wbdbg.drop_timer ; + assign _0418_ = _0419_ ? 26'h17d7840 : _0416_; + assign _0420_ = _0421_ ? 3'h0 : \wbdbg.recieve_state ; + assign _0422_ = _0423_ ? _0420_ : \wbdbg.recieve_state ; + assign _0424_ = _0425_ ? 3'h0 : _0059_[2:0]; + assign _0426_ = _0427_ ? _0424_ : _0422_; + assign _0428_ = _0130_ ? 1'h0 : 1'h1; + assign _0430_ = _0431_ ? 1'h0 : _0428_; + assign _0432_ = _0433_ ? _0430_ : 1'h0; + assign _0434_ = _0435_ ? _0432_ : 1'h0; + assign _0436_ = _0130_ ? \wbdbg.cmd_fifo_wr_data : { \wbdbg.recieve_data [35:8], \wbdbg.uart_rx.o_data }; + assign _0438_ = _0439_ ? \wbdbg.cmd_fifo_wr_data : _0436_; + assign _0440_ = _0441_ ? _0438_ : \wbdbg.cmd_fifo_wr_data ; + assign _0442_ = _0443_ ? _0440_ : \wbdbg.cmd_fifo_wr_data ; + assign _0444_ = _0445_ ? 1'h1 : 1'h0; + assign _0446_ = _0447_ ? 1'h1 : 1'h0; + assign _0448_ = _0449_ ? \wbdbg.cmd_fifo.o_rd_data : \wbdbg.cmd_data ; + assign _0450_ = _0451_ ? 36'hfffffffff : 36'h000000000; + assign _0452_ = _0453_ ? 36'hxxxxxxxxx : _0450_; + assign _0454_ = _0455_ ? \wbdbg.cmd_fifo_wr_data : 36'hxxxxxxxxx; + assign _0456_ = _0457_ ? 36'hxxxxxxxxx : _0454_; + assign _0458_ = _0459_ ? \wbdbg.cmd_fifo.wr_ptr : 4'hx; + assign _0460_ = _0461_ ? 4'hx : _0458_; + assign _0462_ = _0463_ ? 36'h000000000 : _0125_; + assign _0464_ = _0465_ ? 36'hxxxxxxxxx : _0124_; + assign _0466_ = _0467_ ? 4'hx : _0123_; + assign _0468_ = _0469_ ? _0126_[3:0] : \wbdbg.cmd_fifo.wr_ptr ; + assign _0470_ = _0471_ ? 4'h0 : _0468_; + assign _0472_ = _0473_ ? _0102_ : 1'h0; + assign _0474_ = _0475_ ? 1'h0 : _0472_; + assign _0476_ = _0477_ ? _0127_[3:0] : \wbdbg.cmd_fifo.rd_ptr ; + assign _0478_ = _0479_ ? 4'h0 : _0476_; + assign _0480_ = _0481_ ? _0135_ : \wbdbg.cmd_fifo.o_rd_data ; + assign _0482_ = _0483_ ? \wbdbg.cmd_fifo.o_rd_data : _0480_; + assign _0484_ = _0485_ ? _0128_[4:0] : \wbdbg.cmd_fifo.len ; + assign _0486_ = _0487_ ? _0144_[4:0] : _0484_; + assign _0488_ = _0489_ ? 5'h00 : _0486_; + assign _0490_ = _0491_ ? 36'hfffffffff : 36'h000000000; + assign _0492_ = _0493_ ? 36'hxxxxxxxxx : _0490_; + assign _0494_ = _0495_ ? \wbdbg.resp_fifo_wr_data : 36'hxxxxxxxxx; + assign _0496_ = _0497_ ? 36'hxxxxxxxxx : _0494_; + assign _0498_ = _0499_ ? \wbdbg.resp_fifo.wr_ptr : 4'hx; + assign _0500_ = _0501_ ? 4'hx : _0498_; + assign _0502_ = _0503_ ? 36'h000000000 : _0162_; + assign _0504_ = _0505_ ? 36'hxxxxxxxxx : _0161_; + assign _0506_ = _0507_ ? 4'hx : _0160_; + assign _0508_ = _0509_ ? _0163_[3:0] : \wbdbg.resp_fifo.wr_ptr ; + assign _0510_ = _0511_ ? 4'h0 : _0508_; + assign _0512_ = _0513_ ? _0092_ : 1'h0; + assign _0514_ = _0515_ ? 1'h0 : _0512_; + assign _0516_ = _0517_ ? _0164_[3:0] : \wbdbg.resp_fifo.rd_ptr ; + assign _0518_ = _0519_ ? 4'h0 : _0516_; + assign _0520_ = _0521_ ? _0172_ : \wbdbg.resp_fifo.o_rd_data ; + assign _0522_ = _0523_ ? \wbdbg.resp_fifo.o_rd_data : _0520_; + assign _0524_ = _0525_ ? _0165_[4:0] : \wbdbg.resp_fifo.len ; + assign _0526_ = _0527_ ? _0181_[4:0] : _0524_; + assign _0528_ = _0529_ ? 5'h00 : _0526_; + assign _0530_ = _0531_ ? \wbdbg.uart_rx.o_data : _0218_; + assign _0532_ = _0533_ ? _0530_ : 8'hxx; + assign _0534_ = _0535_ ? 8'hxx : _0532_; + assign _0536_ = _0537_ ? _0208_ : _0223_; + assign _0538_ = _0539_ ? _0536_ : 32'hxxxxxxxx; + assign _0540_ = _0541_ ? 32'hxxxxxxxx : _0538_; + assign _0542_ = _0543_ ? _0206_ : _0220_; + assign _0544_ = _0545_ ? _0542_ : 8'hxx; + assign _0546_ = _0547_ ? 8'hxx : _0544_; + assign _0548_ = _0549_ ? _0207_ : _0219_; + assign _0550_ = _0551_ ? _0548_ : 8'hxx; + assign _0552_ = _0553_ ? 8'hxx : _0550_; + assign _0554_ = _0555_ ? _0202_ : \wbdbg.uart_rx.o_data ; + assign _0556_ = _0557_ ? 8'hxx : _0554_; + assign _0558_ = _0559_ ? _0201_ : _0208_; + assign _0560_ = _0561_ ? 32'hxxxxxxxx : _0558_; + assign _0562_ = _0563_ ? _0199_ : _0206_; + assign _0564_ = _0565_ ? 8'hxx : _0562_; + assign _0566_ = _0567_ ? _0200_ : _0207_; + assign _0568_ = _0569_ ? 8'hxx : _0566_; + assign _0570_ = _0571_ ? \wbdbg.uart_rx.o_data : _0198_; + assign _0572_ = _0573_ ? _0208_ : _0197_; + assign _0574_ = _0575_ ? _0206_ : _0195_; + assign _0576_ = _0577_ ? _0207_ : _0196_; + assign _0578_ = _0579_ ? 10'h00a : 10'h08b; + assign _0580_ = _0581_ ? _0578_ : _0224_[9:0]; + assign _0582_ = uart_rx_sync[2] ? 10'h00a : 10'h0d0; + assign _0584_ = _0585_ ? _0582_ : _0580_; + assign _0586_ = _0587_ ? 1'h1 : 1'h0; + assign _0588_ = _0589_ ? _0586_ : 1'h0; + assign _0590_ = _0591_ ? _0588_ : 1'h0; + assign _0592_ = _0593_ ? 1'h0 : _0590_; + assign _0594_ = _0595_ ? 4'h0 : _0203_[3:0]; + assign _0596_ = _0597_ ? _0594_ : \wbdbg.uart_rx.state ; + assign _0598_ = uart_rx_sync[2] ? \wbdbg.uart_rx.state : 4'h1; + assign _0600_ = _0601_ ? _0598_ : _0596_; + assign _0602_ = _0603_ ? 1'h1 : _0242_; + assign _0604_ = _0605_ ? 1'hx : _0602_; + assign _0606_ = _0607_ ? 1'hx : _0604_; + assign _0608_ = _0609_ ? 1'h0 : _0232_; + assign _0610_ = _0611_ ? 1'hx : _0608_; + assign _0612_ = _0613_ ? 1'h1 : _0231_; + assign _0614_ = _0615_ ? 10'h08a : 10'h08b; + assign _0616_ = _0617_ ? 10'h00a : _0614_; + assign _0618_ = _0619_ ? _0616_ : _0243_[9:0]; + assign _0620_ = _0621_ ? 10'h08b : 10'h00a; + assign _0622_ = _0623_ ? _0620_ : _0618_; + assign _0624_ = _0625_ ? \wbdbg.uart_tx_data : \wbdbg.uart_tx.data_send ; + assign _0626_ = _0627_ ? _0624_ : \wbdbg.uart_tx.data_send ; + assign _0628_ = _0629_ ? 4'h0 : _0233_[3:0]; + assign _0630_ = _0631_ ? _0628_ : \wbdbg.uart_tx.state ; + assign _0632_ = _0633_ ? 4'h1 : \wbdbg.uart_tx.state ; + assign _0634_ = _0635_ ? _0632_ : _0630_; + assign _0636_ = _0637_ ? 1'h1 : \wbdbg.wbdbgbusmaster.o_wb_stb ; + assign _0638_ = _0639_ ? \wbdbg.wbdbgbusmaster.o_wb_stb : _0636_; + assign _0642_ = _0643_ ? 1'h0 : _0638_; + assign _0644_ = _0645_ ? 1'h0 : _0642_; + assign _0646_ = _0647_ ? 1'h1 : \wbdbg.wbdbgbusmaster.o_wb_cyc ; + assign _0648_ = _0649_ ? 1'h0 : \wbdbg.wbdbgbusmaster.o_wb_cyc ; + assign _0650_ = _0651_ ? _0648_ : _0646_; + assign _0652_ = _0653_ ? \wbdbg.wbdbgbusmaster.o_wb_cyc : _0650_; + assign _0654_ = _0655_ ? 1'h0 : _0652_; + assign _0656_ = _0657_ ? _0268_ : \wbdbg.wbdbgbusmaster.addr_inc ; + assign _0658_ = _0659_ ? _0656_ : \wbdbg.wbdbgbusmaster.addr_inc ; + assign _0660_ = _0661_ ? _0260_ : \wbdbg.wbdbgbusmaster.o_wb_addr ; + assign _0662_ = _0663_ ? \wbdbg.cmd_data [31:0] : \wbdbg.wbdbgbusmaster.o_wb_addr ; + assign _0664_ = _0665_ ? _0662_ : _0660_; + assign _0666_ = \wbdbg.wbdbgbusmaster.o_wb_cyc ? \wbdbg.wbdbgbusmaster.o_wb_we : _0272_; + assign _0670_ = _0671_ ? 1'h1 : 1'h0; + assign _0672_ = _0673_ ? 1'h1 : _0670_; + assign _0676_ = _0677_ ? 1'h1 : _0674_; + assign _0678_ = _0679_ ? 36'h300000000 : \wbdbg.wbdbgbusmaster.o_resp_data ; + assign _0680_ = _0681_ ? 36'h200000000 : { 24'h100000, chip_outputs }; + assign _0682_ = _0683_ ? _0680_ : _0678_; + assign _0686_ = _0687_ ? 36'h500000000 : _0684_; + assign _0688_ = _0689_ ? 1'h1 : 1'h0; + assign _0690_ = _0691_ ? data_in : { 20'h00000, chip_outputs }; + assign _0692_ = _0693_ ? _0690_ : data_in; + assign _0694_ = _0695_ ? \wbdbg.wbdbgbusmaster.o_wb_data [12] : chip_reset; + assign _0696_ = _0697_ ? _0694_ : chip_reset; + assign _0698_ = _0699_ ? \wbdbg.wbdbgbusmaster.o_wb_data [13] : chip_clock; + assign _0700_ = _0701_ ? _0698_ : chip_clock; + assign _0702_ = _0703_ ? \wbdbg.wbdbgbusmaster.o_wb_data [11:0] : chip_inputs; + assign _0704_ = _0705_ ? _0702_ : chip_inputs; + SB_PLL40_CORE #( + .DIVF(7'h28), + .DIVQ(3'h6), + .DIVR(4'h3), + .FEEDBACK_PATH("SIMPLE"), + .FILTER_RANGE(3'h2) + ) uut ( + .BYPASS(1'h0), + .PLLOUTCORE(clk), + .REFERENCECLK(clk100), + .RESETB(1'h1) + ); + assign _0006_ = 32'd0; + assign _0007_ = 32'd0; + assign _0008_ = 32'd0; + assign _0009_ = 32'd0; + assign _0010_ = 32'd0; + assign _0011_ = 32'd0; + assign \wbdbg.uart_rx.i_clk = \wbdbg.i_clk ; + assign \wbdbg.uart_rx.i_in = \wbdbg.i_rx ; + assign \wbdbg.uart_rx_valid = \wbdbg.uart_rx.o_valid ; + assign \wbdbg.uart_rx_data = \wbdbg.uart_rx.o_data ; + assign \wbdbg.uart_tx.o_ready = _0234_; + assign \wbdbg.uart_tx.i_clk = \wbdbg.i_clk ; + assign \wbdbg.uart_tx.i_valid = \wbdbg.uart_tx_valid ; + assign \wbdbg.uart_tx.i_data = \wbdbg.uart_tx_data ; + assign \wbdbg.o_tx = \wbdbg.uart_tx.o_out ; + assign \wbdbg.uart_tx_ready = \wbdbg.uart_tx.o_ready ; + assign \wbdbg.wbdbgbusmaster.o_cmd_ready = _0281_; + assign \wbdbg.wbdbgbusmaster.cmd_recv = _0269_; + assign \wbdbg.wbdbgbusmaster.cmd_inst = \wbdbg.wbdbgbusmaster.i_cmd_data [35:32]; + assign \wbdbg.wbdbgbusmaster.cmd_data = \wbdbg.wbdbgbusmaster.i_cmd_data [31:0]; + assign \wbdbg.wbdbgbusmaster.i_clk = \wbdbg.i_clk ; + assign \wbdbg.wbdbgbusmaster.i_wb_data = \wbdbg.i_wb_data ; + assign \wbdbg.wbdbgbusmaster.i_wb_stall = \wbdbg.i_wb_stall ; + assign \wbdbg.wbdbgbusmaster.i_wb_err = \wbdbg.i_wb_err ; + assign \wbdbg.wbdbgbusmaster.i_wb_ack = \wbdbg.i_wb_ack ; + assign \wbdbg.o_wb_data = \wbdbg.wbdbgbusmaster.o_wb_data ; + assign \wbdbg.o_wb_addr = \wbdbg.wbdbgbusmaster.o_wb_addr ; + assign \wbdbg.o_wb_we = \wbdbg.wbdbgbusmaster.o_wb_we ; + assign \wbdbg.o_wb_stb = \wbdbg.wbdbgbusmaster.o_wb_stb ; + assign \wbdbg.o_wb_cyc = \wbdbg.wbdbgbusmaster.o_wb_cyc ; + assign \wbdbg.resp_data = \wbdbg.wbdbgbusmaster.o_resp_data ; + assign \wbdbg.resp_valid = \wbdbg.wbdbgbusmaster.o_resp_valid ; + assign \wbdbg.wbdbgbusmaster.i_cmd_data = \wbdbg.cmd_data ; + assign \wbdbg.cmd_ready = \wbdbg.wbdbgbusmaster.o_cmd_ready ; + assign \wbdbg.wbdbgbusmaster.i_cmd_valid = \wbdbg.cmd_valid ; + assign \wbdbg.wbdbgbusmaster.i_cmd_reset = \wbdbg.cmd_reset ; + assign \wbdbg.cmd_fifo.o_empty = _0129_; + assign \wbdbg.cmd_fifo.o_full = _0130_; + assign \wbdbg.cmd_fifo.i_rst = \wbdbg.cmd_reset ; + assign \wbdbg.cmd_fifo.i_clk = \wbdbg.i_clk ; + assign \wbdbg.cmd_fifo_full = \wbdbg.cmd_fifo.o_full ; + assign \wbdbg.cmd_fifo_empty = \wbdbg.cmd_fifo.o_empty ; + assign \wbdbg.cmd_fifo.i_wr_data = \wbdbg.cmd_fifo_wr_data ; + assign \wbdbg.cmd_fifo.i_wr_en = \wbdbg.cmd_fifo_wr_en ; + assign \wbdbg.cmd_fifo_rd_valid = \wbdbg.cmd_fifo.o_rd_valid ; + assign \wbdbg.cmd_fifo_rd_data = \wbdbg.cmd_fifo.o_rd_data ; + assign \wbdbg.cmd_fifo.i_rd_en = \wbdbg.cmd_fifo_rd_en ; + assign \wbdbg.resp_fifo.o_empty = _0166_; + assign \wbdbg.resp_fifo.o_full = _0167_; + assign \wbdbg.resp_fifo.i_rst = \wbdbg.cmd_reset ; + assign \wbdbg.resp_fifo.i_clk = \wbdbg.i_clk ; + assign \wbdbg.resp_fifo_full = \wbdbg.resp_fifo.o_full ; + assign \wbdbg.resp_fifo_empty = \wbdbg.resp_fifo.o_empty ; + assign \wbdbg.resp_fifo.i_wr_data = \wbdbg.resp_fifo_wr_data ; + assign \wbdbg.resp_fifo.i_wr_en = \wbdbg.resp_fifo_wr_en ; + assign \wbdbg.resp_fifo_rd_valid = \wbdbg.resp_fifo.o_rd_valid ; + assign \wbdbg.resp_fifo_rd_data = \wbdbg.resp_fifo.o_rd_data ; + assign \wbdbg.resp_fifo.i_rd_en = \wbdbg.resp_fifo_rd_en ; + assign \wbdbg.i_clk = clk; + assign \wbdbg.i_interrupt_4 = _0011_[0]; + assign \wbdbg.i_interrupt_3 = _0010_[0]; + assign \wbdbg.i_interrupt_2 = _0009_[0]; + assign \wbdbg.i_interrupt_1 = _0008_[0]; + assign \wbdbg.i_wb_data = { 20'h00000, chip_outputs }; + assign \wbdbg.i_wb_stall = _0007_[0]; + assign \wbdbg.i_wb_err = _0006_[0]; + assign \wbdbg.i_wb_ack = wb_ack; + assign data_out = \wbdbg.o_wb_data ; + assign wb_we = \wbdbg.o_wb_we ; + assign wb_stb = \wbdbg.o_wb_stb ; + assign wb_cyc = \wbdbg.o_wb_cyc ; + assign \wbdbg.i_rx = uart_rx_sync[2]; + assign uart_tx = \wbdbg.o_tx ; + assign _0277_ = \wbdbg.cmd_reset ; + assign _0276_ = 1'h1; + assign _0282_ = 1'h1; + assign _0271_ = \wbdbg.wbdbgbusmaster.o_wb_stb ; + assign _0273_ = 1'h0; + assign _0284_ = 1'h1; + assign _0213_ = \wbdbg.uart_rx.i_in ; + assign _0204_ = { 7'h00, uart_rx_sync[2] }; + assign _0071_ = 1'h0; + assign _0070_ = 1'h0; + assign _0069_ = 1'h0; + assign _0068_ = 1'h0; + assign _0061_ = _0060_; + assign _0106_ = _0101_; + assign _0221_ = _0222_; + assign _0238_ = _0241_; + assign _0237_ = _0241_; + assign _0235_ = _0239_; + assign _0265_ = _0268_; + assign _0264_ = _0268_; + assign _0263_ = _0267_; + assign _0262_ = _0266_; + assign _0281_ = _0283_; + assign _0234_ = _0239_; + assign _0143_ = _0100_; + assign _0142_ = _0103_; + assign _0141_ = _0102_; + assign _0139_ = _0102_; + assign _0180_ = _0087_; + assign _0179_ = _0094_; + assign _0178_ = _0092_; + assign _0176_ = _0092_; + assign _0215_ = _0216_; + assign _0279_ = _0280_; + assign _0057_ = 1'h0; + assign _0039_ = 1'h0; + assign _0040_ = 1'h0; + assign _0036_ = 1'h0; + assign _0038_ = 1'h0; + assign _0037_ = 36'h000000000; + assign _0052_ = 1'h0; + assign _0054_ = 1'h0; + assign _0053_ = 36'h000000000; + assign _0055_ = 40'h0000000000; + assign _0056_ = 3'h0; + assign _0042_ = 1'h0; + assign _0044_ = 1'h0; + assign _0046_ = 1'h0; + assign _0048_ = 1'h0; + assign _0043_ = 1'h0; + assign _0045_ = 1'h0; + assign _0047_ = 1'h0; + assign _0049_ = 1'h0; + assign _0025_ = 1'h0; + assign _0023_ = 1'h0; + assign _0021_ = 1'h0; + assign _0019_ = 1'h0; + assign _0050_ = 40'h0000000000; + assign _0051_ = 3'h0; + assign _0041_ = 26'h17d7840; + assign _0120_ = 1'h0; + assign _0122_ = 4'h0; + assign _0121_ = 4'h0; + assign _0119_ = 5'h00; + assign _0110_ = _0118_; + assign _0109_ = _0117_; + assign _0108_ = _0116_; + assign _0157_ = 1'h0; + assign _0159_ = 4'h0; + assign _0158_ = 4'h0; + assign _0156_ = 5'h00; + assign _0147_ = _0155_; + assign _0146_ = _0154_; + assign _0145_ = _0153_; + assign _0194_ = 4'h0; + assign _0187_ = _0193_; + assign _0185_ = _0193_; + assign _0184_ = _0192_; + assign _0182_ = _0190_; + assign _0183_ = _0191_; + assign _0227_ = _0229_; + assign _0230_ = 4'h0; + assign _0254_ = 1'h0; + assign _0256_ = 1'h0; + assign _0258_ = 1'h0; + assign _0259_ = 1'h0; + assign _0255_ = 32'd0; + assign _0257_ = 32'd0; + assign _0253_ = 1'h0; + assign _0004_ = { uart_rx_sync[1:0], uart_rx }; + assign _0287_ = _0067_; + assign _0031_ = _0286_; + assign _0289_ = _0067_; + assign _0030_ = _0288_; + assign _0291_ = _0078_; + assign _0029_ = _0290_; + assign _0293_ = _0079_; + assign _0295_ = _0061_; + assign _0035_ = _0294_; + assign _0297_ = _0071_; + assign _0299_ = \wbdbg.interrupt_4_rising ; + assign _0301_ = \wbdbg.interrupt_3_rising ; + assign _0303_ = \wbdbg.interrupt_2_rising ; + assign _0305_ = \wbdbg.interrupt_1_rising ; + assign _0307_ = \wbdbg.resp_fifo_rd_en ; + assign _0309_ = \wbdbg.resp_fifo_rd_valid ; + assign _0311_ = _0061_; + assign _0026_ = _0310_; + assign _0313_ = _0070_; + assign _0315_ = \wbdbg.interrupt_3_rising ; + assign _0317_ = \wbdbg.interrupt_2_rising ; + assign _0319_ = \wbdbg.interrupt_1_rising ; + assign _0321_ = \wbdbg.resp_fifo_rd_en ; + assign _0323_ = \wbdbg.resp_fifo_rd_valid ; + assign _0325_ = _0061_; + assign _0024_ = _0324_; + assign _0327_ = _0069_; + assign _0329_ = \wbdbg.interrupt_2_rising ; + assign _0331_ = \wbdbg.interrupt_1_rising ; + assign _0333_ = \wbdbg.resp_fifo_rd_en ; + assign _0335_ = \wbdbg.resp_fifo_rd_valid ; + assign _0337_ = _0061_; + assign _0022_ = _0336_; + assign _0339_ = _0068_; + assign _0341_ = \wbdbg.interrupt_1_rising ; + assign _0343_ = \wbdbg.resp_fifo_rd_en ; + assign _0345_ = \wbdbg.resp_fifo_rd_valid ; + assign _0347_ = _0061_; + assign _0020_ = _0346_; + assign _0349_ = _0062_; + assign _0351_ = _0079_; + assign _0353_ = \wbdbg.interrupt_4_rising ; + assign _0355_ = \wbdbg.interrupt_3_rising ; + assign _0357_ = \wbdbg.interrupt_2_rising ; + assign _0359_ = \wbdbg.interrupt_1_rising ; + assign _0361_ = \wbdbg.resp_fifo_rd_en ; + assign _0363_ = \wbdbg.resp_fifo_rd_valid ; + assign _0365_ = _0061_; + assign _0033_ = _0364_; + assign _0367_ = \wbdbg.interrupt_4_rising ; + assign _0369_ = \wbdbg.interrupt_3_rising ; + assign _0371_ = \wbdbg.interrupt_2_rising ; + assign _0373_ = \wbdbg.interrupt_1_rising ; + assign _0375_ = \wbdbg.resp_fifo_rd_en ; + assign _0377_ = \wbdbg.resp_fifo_rd_valid ; + assign _0379_ = _0061_; + assign _0032_ = _0378_; + assign _0387_ = _0079_; + assign _0389_ = _0061_; + assign _0034_ = _0388_; + assign _0393_ = \wbdbg.uart_rx_valid ; + assign _0027_[15:8] = _0392_; + assign _0397_ = \wbdbg.uart_rx_valid ; + assign _0027_[7:0] = _0396_; + assign _0401_ = \wbdbg.uart_rx_valid ; + assign _0027_[23:16] = _0400_; + assign _0405_ = \wbdbg.uart_rx_valid ; + assign _0027_[31:24] = _0404_; + assign _0409_ = \wbdbg.uart_rx_valid ; + assign _0027_[39:32] = _0408_; + assign _0411_ = _0064_; + assign _0413_ = _0063_; + assign _0415_ = \wbdbg.uart_rx_valid ; + assign _0016_ = _0414_; + assign _0417_ = _0066_; + assign _0419_ = \wbdbg.uart_rx_valid ; + assign _0018_ = _0418_; + assign _0421_ = _0065_; + assign _0423_ = _0066_; + assign _0425_ = _0063_; + assign _0427_ = \wbdbg.uart_rx_valid ; + assign _0028_ = _0426_; + assign _0429_ = _0100_; + assign _0431_ = _0064_; + assign _0433_ = _0063_; + assign _0435_ = \wbdbg.uart_rx_valid ; + assign _0015_ = _0434_; + assign _0437_ = _0100_; + assign _0439_ = _0064_; + assign _0441_ = _0063_; + assign _0443_ = \wbdbg.uart_rx_valid ; + assign _0014_ = _0442_; + assign _0445_ = _0084_; + assign _0013_ = _0444_; + assign _0447_ = _0086_; + assign _0017_ = _0446_; + assign _0449_ = _0086_; + assign _0012_ = _0448_; + assign _0451_ = \wbdbg.cmd_fifo.i_wr_en ; + assign _0453_ = \wbdbg.cmd_fifo.i_rst ; + assign _0125_ = _0452_; + assign _0455_ = \wbdbg.cmd_fifo.i_wr_en ; + assign _0457_ = \wbdbg.cmd_fifo.i_rst ; + assign _0124_ = _0456_; + assign _0459_ = \wbdbg.cmd_fifo.i_wr_en ; + assign _0461_ = \wbdbg.cmd_fifo.i_rst ; + assign _0123_ = _0460_; + assign _0463_ = \wbdbg.cmd_fifo.i_rst ; + assign _0118_ = _0462_; + assign _0465_ = \wbdbg.cmd_fifo.i_rst ; + assign _0117_ = _0464_; + assign _0467_ = \wbdbg.cmd_fifo.i_rst ; + assign _0116_ = _0466_; + assign _0469_ = \wbdbg.cmd_fifo.i_wr_en ; + assign _0471_ = \wbdbg.cmd_fifo.i_rst ; + assign _0115_ = _0470_; + assign _0473_ = \wbdbg.cmd_fifo.i_rd_en ; + assign _0475_ = \wbdbg.cmd_fifo.i_rst ; + assign _0113_ = _0474_; + assign _0477_ = \wbdbg.cmd_fifo.i_rd_en ; + assign _0479_ = \wbdbg.cmd_fifo.i_rst ; + assign _0114_ = _0478_; + assign _0481_ = \wbdbg.cmd_fifo.i_rd_en ; + assign _0483_ = \wbdbg.cmd_fifo.i_rst ; + assign _0112_ = _0482_; + assign _0485_ = _0134_; + assign _0487_ = _0132_; + assign _0489_ = \wbdbg.cmd_fifo.i_rst ; + assign _0111_ = _0488_; + assign _0491_ = \wbdbg.resp_fifo.i_wr_en ; + assign _0493_ = \wbdbg.resp_fifo.i_rst ; + assign _0162_ = _0492_; + assign _0495_ = \wbdbg.resp_fifo.i_wr_en ; + assign _0497_ = \wbdbg.resp_fifo.i_rst ; + assign _0161_ = _0496_; + assign _0499_ = \wbdbg.resp_fifo.i_wr_en ; + assign _0501_ = \wbdbg.resp_fifo.i_rst ; + assign _0160_ = _0500_; + assign _0503_ = \wbdbg.resp_fifo.i_rst ; + assign _0155_ = _0502_; + assign _0505_ = \wbdbg.resp_fifo.i_rst ; + assign _0154_ = _0504_; + assign _0507_ = \wbdbg.resp_fifo.i_rst ; + assign _0153_ = _0506_; + assign _0509_ = \wbdbg.resp_fifo.i_wr_en ; + assign _0511_ = \wbdbg.resp_fifo.i_rst ; + assign _0152_ = _0510_; + assign _0513_ = \wbdbg.resp_fifo.i_rd_en ; + assign _0515_ = \wbdbg.resp_fifo.i_rst ; + assign _0150_ = _0514_; + assign _0517_ = \wbdbg.resp_fifo.i_rd_en ; + assign _0519_ = \wbdbg.resp_fifo.i_rst ; + assign _0151_ = _0518_; + assign _0521_ = \wbdbg.resp_fifo.i_rd_en ; + assign _0523_ = \wbdbg.resp_fifo.i_rst ; + assign _0149_ = _0522_; + assign _0525_ = _0171_; + assign _0527_ = _0169_; + assign _0529_ = \wbdbg.resp_fifo.i_rst ; + assign _0148_ = _0528_; + assign _0531_ = _0212_; + assign _0533_ = _0211_; + assign _0535_ = _0209_; + assign _0202_ = _0534_; + assign _0537_ = _0212_; + assign _0539_ = _0211_; + assign _0541_ = _0209_; + assign _0201_ = _0540_; + assign _0543_ = _0212_; + assign _0545_ = _0211_; + assign _0547_ = _0209_; + assign _0199_ = _0546_; + assign _0549_ = _0212_; + assign _0551_ = _0211_; + assign _0553_ = _0209_; + assign _0200_ = _0552_; + assign _0555_ = _0211_; + assign _0557_ = _0209_; + assign _0198_ = _0556_; + assign _0559_ = _0211_; + assign _0561_ = _0209_; + assign _0197_ = _0560_; + assign _0563_ = _0211_; + assign _0565_ = _0209_; + assign _0195_ = _0564_; + assign _0567_ = _0211_; + assign _0569_ = _0209_; + assign _0196_ = _0568_; + assign _0571_ = _0209_; + assign _0193_ = _0570_; + assign _0573_ = _0209_; + assign _0192_ = _0572_; + assign _0575_ = _0209_; + assign _0190_ = _0574_; + assign _0577_ = _0209_; + assign _0191_ = _0576_; + assign _0579_ = _0212_; + assign _0581_ = _0211_; + assign _0583_ = _0210_; + assign _0585_ = _0209_; + assign _0186_ = _0584_; + assign _0587_ = _0213_; + assign _0589_ = _0212_; + assign _0591_ = _0211_; + assign _0593_ = _0209_; + assign _0188_ = _0592_; + assign _0595_ = _0212_; + assign _0597_ = _0211_; + assign _0599_ = _0210_; + assign _0601_ = _0209_; + assign _0189_ = _0600_; + assign _0603_ = _0241_; + assign _0605_ = _0240_; + assign _0607_ = _0239_; + assign _0232_ = _0606_; + assign _0609_ = _0240_; + assign _0611_ = _0239_; + assign _0231_ = _0610_; + assign _0613_ = _0239_; + assign _0229_ = _0612_; + assign _0615_ = _0238_; + assign _0617_ = _0237_; + assign _0619_ = _0236_; + assign _0621_ = \wbdbg.uart_tx.i_valid ; + assign _0623_ = _0235_; + assign _0225_ = _0622_; + assign _0625_ = \wbdbg.uart_tx.i_valid ; + assign _0627_ = _0235_; + assign _0226_ = _0626_; + assign _0629_ = _0237_; + assign _0631_ = _0236_; + assign _0633_ = \wbdbg.uart_tx.i_valid ; + assign _0635_ = _0235_; + assign _0228_ = _0634_; + assign _0637_ = _0270_; + assign _0639_ = \wbdbg.wbdbgbusmaster.o_wb_cyc ; + assign _0641_ = _0276_; + assign _0643_ = \wbdbg.wbdbgbusmaster.o_wb_stb ; + assign _0645_ = _0277_; + assign _0251_ = _0644_; + assign _0647_ = _0270_; + assign _0649_ = \wbdbg.wbdbgbusmaster.i_wb_ack ; + assign _0651_ = \wbdbg.wbdbgbusmaster.o_wb_cyc ; + assign _0653_ = \wbdbg.wbdbgbusmaster.o_wb_stb ; + assign _0655_ = _0277_; + assign _0249_ = _0654_; + assign _0657_ = _0279_; + assign _0659_ = \wbdbg.wbdbgbusmaster.cmd_recv ; + assign _0245_ = _0658_; + assign _0661_ = _0271_; + assign _0663_ = _0279_; + assign _0665_ = \wbdbg.wbdbgbusmaster.cmd_recv ; + assign _0248_ = _0664_; + assign _0667_ = _0283_; + assign _0252_ = _0666_; + assign _0669_ = _0284_; + assign _0250_ = _0668_; + assign _0671_ = _0275_; + assign _0673_ = _0274_; + assign _0675_ = \wbdbg.wbdbgbusmaster.i_wb_err ; + assign _0677_ = \wbdbg.wbdbgbusmaster.i_cmd_reset ; + assign _0247_ = _0676_; + assign _0679_ = _0275_; + assign _0681_ = \wbdbg.wbdbgbusmaster.o_wb_we ; + assign _0683_ = _0274_; + assign _0685_ = \wbdbg.wbdbgbusmaster.i_wb_err ; + assign _0687_ = \wbdbg.wbdbgbusmaster.i_cmd_reset ; + assign _0246_ = _0686_; + assign _0689_ = _0285_; + assign _0005_ = _0688_; + assign _0691_ = wb_we; + assign _0693_ = _0285_; + assign _0003_ = _0692_; + assign _0695_ = wb_we; + assign _0697_ = _0285_; + assign _0002_ = _0696_; + assign _0699_ = wb_we; + assign _0701_ = _0285_; + assign _0000_ = _0700_; + assign _0703_ = wb_we; + assign _0705_ = _0285_; + assign _0001_ = _0704_; + assign \wbdbg.uart_tx.o_out = _0612_; + assign _0296_ = \wbdbg.interrupt_4_rising ; + assign _0312_ = \wbdbg.interrupt_3_rising ; + assign _0326_ = \wbdbg.interrupt_2_rising ; + assign _0338_ = \wbdbg.interrupt_1_rising ; + assign _0668_ = \wbdbg.cmd_data [31:0]; + assign _0674_ = _0672_; + assign _0684_ = _0682_; + assign _0640_ = 1'h0; +endmodule diff --git a/designs/d11_gbailey_bfchip/dev/src/fpga_test.py b/designs/d11_gbailey_bfchip/dev/src/fpga_test.py new file mode 100644 index 0000000..75d12e5 --- /dev/null +++ b/designs/d11_gbailey_bfchip/dev/src/fpga_test.py @@ -0,0 +1,129 @@ +# Runs a program on the FPGA. + +from interface import Chip +import sys +import tomli + +IoNone = 0b000 +IoOpcode = 0b001 +IoAddrHi = 0b010 +IoAddrLo = 0b011 +IoReadWrite = 0b100 +BusNone = 0b000 +BusReadProg = 0b010 +BusReadData = 0b100 +BusWriteData = 0b101 +BusReadIo = 0b110 +BusWriteIo = 0b111 + +class Inputs: + def __init__(self, chip): + self.bus_in = 0 + self.op_done = 0 + self.enable = 0 + self.chip = chip + + def set(self): + val = (self.enable << 9) | (self.op_done << 8) | self.bus_in + self.chip.set_all_inputs(val) + + def __repr__(self): + return f"bus_in={self.bus_in:08b}, " \ + f"op_done={self.op_done:b}, " \ + f"enable={self.enable:b}" + +class Outputs: + def __init__(self, chip): + self.bus_out = 0 + self.state = 0 + self.halted = 0 + self.chip = chip + + def get(self): + out = self.chip.get_all_outputs() + self.bus_out = out & 0x0FF + self.state = (out & 0x700) >> 8 + self.halted = (out & 0x800) >> 11 + + def __repr__(self): + return f"bus_out={self.bus_out:08b}, " \ + f"state={self.state:03b}, " \ + f"halted={self.halted:b}" + +if len(sys.argv) < 2: + print("must provide a .toml file with the program and expected IO") + exit(1) +with open(sys.argv[1], "rb") as f: + infile = tomli.load(f) + prog = bytearray(infile["program"].encode("ascii")) + stdin = bytearray(infile.get("input", "").encode("ascii")) + input_end = infile.get("input_end", 0) + stdout = bytearray(infile.get("output", "").encode("ascii")) + +chip = Chip("/dev/ttyUSB1") +inputs = Inputs(chip) +outputs = Outputs(chip) + +print("resetting") +chip.set_reset(1) +chip.step_clock() +chip.set_reset(0) + +inputs.enable = 1 +inputs.set() +outputs.get() + +# pseudo-registers +opcode = 0 +addr_hi = 0 +addr_lo = 0 + +data = bytearray(65536) +output = bytearray() + +cycles = 0 + +while not outputs.halted: + outputs.get() + # print(outputs) + if outputs.state == IoOpcode: + opcode = outputs.bus_out + elif outputs.state == IoAddrHi: + addr_hi = outputs.bus_out + elif outputs.state == IoAddrLo: + addr_lo = outputs.bus_out + elif outputs.state == IoReadWrite: + addr = (addr_hi << 8) | addr_lo + if opcode == BusReadProg: + if addr >= len(prog): + inputs.bus_in = 0 + else: + inputs.bus_in = prog[addr] + print(f"reading program [{addr:04x}]: {chr(inputs.bus_in)}") + elif opcode == BusReadData: + inputs.bus_in = data[addr] + print(f"reading data [{addr:04x}]: {inputs.bus_in}") + elif opcode == BusWriteData: + data[addr] = outputs.bus_out + print(f"writing data [{addr:04x}]: {outputs.bus_out}") + elif opcode == BusReadIo: + if len(stdin) > 0: + inputs.bus_in = stdin.pop(0) + else: + inputs.bus_in = input_end + print(f"reading io : {chr(inputs.bus_in)}") + elif opcode == BusWriteIo: + print(f"writing io : {chr(outputs.bus_out)}") + output.append(outputs.bus_out) + inputs.op_done = 1 + inputs.set() + # print(inputs) + chip.step_clock() + cycles += 1 + +print(f"halted, ran {cycles} cycles") +if output == stdout: + print(f"output: {bytes(output)}, success!") +else: + print(f"output: {bytes(output)}, differs from expected: {bytes(stdout)}") +assert(output == stdout) diff --git a/designs/d11_gbailey_bfchip/dev/src/fpga_top.sv b/designs/d11_gbailey_bfchip/dev/src/fpga_top.sv new file mode 100644 index 0000000..7148b14 --- /dev/null +++ b/designs/d11_gbailey_bfchip/dev/src/fpga_top.sv @@ -0,0 +1,29 @@ +// Top module for running on FPGA: just connects to debug harness. +`default_nettype none + +module top ( + input logic clk100, // 100MHz clock + + input logic uart_rx, // UART rx/tx from FTDI chip on FPGA + output logic uart_tx +); + + logic clock, reset; + logic [11:0] io_in, io_out; + + debug_harness dbg ( + .uart_rx, .uart_tx, + .chip_inputs(io_in), + .chip_outputs(io_out), + .chip_clock(clock), + .chip_reset(reset), + .clk100 + ); + + my_chip dut ( + .io_in, .io_out, + .clock, + .reset + ); + +endmodule diff --git a/designs/d11_gbailey_bfchip/dev/src/interface.py b/designs/d11_gbailey_bfchip/dev/src/interface.py new file mode 100644 index 0000000..77c7149 --- /dev/null +++ b/designs/d11_gbailey_bfchip/dev/src/interface.py @@ -0,0 +1,358 @@ +# Code for interfacing with debug harness on FPGA (from asinghani/wbdbgbus) + +import time +from serial import Serial + +CMD_READ_REQ = 0b0001 +CMD_WRITE_REQ = 0b0010 +CMD_SET_ADDR = 0b0011 +CMD_SET_ADDR_INC = 0b0111 +CMD_BUS_RESET = 0b1111 + +RESP_READ_RESP = 0b0001 +RESP_WRITE_ACK = 0b0010 +RESP_ADDR_ACK = 0b0011 +RESP_BUS_ERROR = 0b0100 +RESP_BUS_RESET = 0b0101 +RESP_INTERRUPT_1 = 0b1000 +RESP_INTERRUPT_2 = 0b1001 +RESP_INTERRUPT_3 = 0b1010 +RESP_INTERRUPT_4 = 0b1011 + +RESP_INTERRUPT_ALL = [RESP_INTERRUPT_1, RESP_INTERRUPT_2, + RESP_INTERRUPT_3, RESP_INTERRUPT_4] + +def create_instruction(inst, data): + return [ + inst, + (data & 0xff000000) >> 24, + (data & 0x00ff0000) >> 16, + (data & 0x0000ff00) >> 8, + (data & 0x000000ff) >> 0 + ] + +def parse_instruction(byte_list): + data = int("".join(["{0:08b}".format(x) for x in byte_list[1:]]), 2) + return byte_list[0] & 0x0f, data + +class Chip: + def __init__(self, serial_port, baud=115200): + self.bus = _DebugBus(serial_port, baud, fifo_size=1, timeout=2) + self.out_state = 0b00000000000000 + + def get_all_outputs(self): + o = self.bus.read_peripheral(0)[0] & 0xFFF + return o + + def get_output(self, index): + assert index >= 0 and index < 12 + + o = self.bus.read_peripheral(0)[0] & 0xFFF + o = o & (1 << index) + return (o != 0) + + def _push_outputs(self): + self.bus.write_peripheral(0, self.out_state) + + def set_input(self, index, value, _bp=False): + if not _bp: + assert index >= 0 and index < 12 + + value_n = int(not (int(value) & 0x1)) + self.out_state |= (1 << index) + self.out_state ^= (value_n << index) + + self._push_outputs() + + def set_all_inputs(self, value): + value = value & 0xFFF + + self.out_state &= 0xF000 + self.out_state |= value + + self._push_outputs() + + def set_reset(self, value): + self.set_input(12, value, _bp=True) + + def step_clock(self): + self.set_input(13, 1, _bp=True) + self.set_input(13, 0, _bp=True) + +class _DebugBus: + + def __init__(self, serial_port, baud, fifo_size, timeout=0): + # Maximum number of ops that can be in-pipeline at once + self.max_buf = (fifo_size - 2) if fifo_size > 2 else fifo_size + assert self.max_buf > 0 + + # No timeout for serial port + # Instead, use unblocking serial port and block internally + self.port = Serial(serial_port, baud, timeout=0) + self.timeout = timeout + + self.interrupts = [False, False, False, False] + + self.recv_buffer = [] + self.recv_responses = [] + + # Read as much data from the port as is available and store it + def _read_port(self): + data = self.port.read(10000) # Read as much data is available + self.recv_buffer.extend(list(data)) + + while len(self.recv_buffer) >= 5: + instr = parse_instruction(self.recv_buffer[0:5]) + self.recv_buffer = self.recv_buffer[5:] + + # Parse interrupts + if instr[0] in RESP_INTERRUPT_ALL: + if instr[0] == RESP_INTERRUPT_1: + self.interrupts[0] = True + if instr[0] == RESP_INTERRUPT_2: + self.interrupts[1] = True + if instr[0] == RESP_INTERRUPT_3: + self.interrupts[2] = True + if instr[0] == RESP_INTERRUPT_4: + self.interrupts[3] = True + + elif instr[0] == RESP_BUS_ERROR: + raise RuntimeError("Bus error received") + + else: + self.recv_responses.append(instr) + + # Blocking-read `n` instructions from serial port + # If n = 0, will read 1 instruction in a non-blocking manner + def _read_data(self, n=0): + first = True + + start_time = time.time() + while True: + self._read_port() + + if n == 0: + if len(self.recv_responses) >= 1: + resp = self.recv_responses[0:1] + self.recv_responses = self.recv_responses[1:] + return resp + else: + return None + + else: + if len(self.recv_responses) >= n: + resp = self.recv_responses[0:n] + self.recv_responses = self.recv_responses[n:] + return resp + + first = False + if (self.timeout != 0) and (time.time() - start_time > self.timeout): + raise TimeoutError("Remote device not responding") + + time.sleep(0.01) + + def read(self, address, n=1, _increment=True): + """ + Read `n` contiguous 32-bit words starting at `address`. Blocks execution until finished or timed out. For reading multiple values from the same address (for peripherals which use a single register as a pipe), use read_peripheral(). If `n` = 1, returns a single integer value read from the bus, otherwise returns an array of integer values with length `n`. + + Arguments: + address (int): The base address to read from. + n (int): The number of values to read starting at the given address. + """ + + ret = [] + + # Set address + self.port.write(bytearray(create_instruction( + CMD_SET_ADDR_INC if _increment else CMD_SET_ADDR, address + ))) + + # Include address-set in first-round buffer-count + first_round = 1 + + # One extra readback (for address) + n = n + 1 + + # Send only enough ops at once to avoid overflowing buffer + while n > 0: + num_words = min(self.max_buf, n) + + for i in range(num_words - first_round): + self.port.write(bytearray(create_instruction( + CMD_READ_REQ, 0 + ))) + + first_round = 0 + + ret.extend(self._read_data(num_words)) + n = n - num_words + + # Remove address-acknowledge + assert ret[0][0] == RESP_ADDR_ACK + ret = ret[1:] + for inst, data in ret: + assert inst == RESP_READ_RESP + ret = [int(x[1]) for x in ret] + + if n == 1: + return ret[0] + else: + return ret + + def read_peripheral(self, address, n=1): + """ + Read `n` 32-bit words, all from `address`. Blocks execution until finished or timed out. This should be used for peripherals which use a single register as a pipe. If `n` = 1, returns a single integer value read from the bus, otherwise returns an array of integer values with length `n`. + + Arguments: + address (int): The singular address to read from. + n (int): The number of values to read from the given address. + """ + + return self.read(address, n=n, _increment=False) + + def write(self, address, data, verify=False, _increment=True): + """ + Write `data` into contiguous 32-bit words starting at `address`. Blocks execution until finished or timed out. `None` values in the data array will not be written. For writing multiple values to the same address (for peripherals which use a single register as a pipe), use write_peripheral(). + + Arguments: + address (int): The base address to write to. + data (list[int] OR int): The data to write. + verify (bool): Whether to read-back and verify the data after writing it. + """ + + ret = [] + + # Set address + self.port.write(bytearray(create_instruction( + CMD_SET_ADDR_INC if _increment else CMD_SET_ADDR, address + ))) + + # Include address-set in first-round buffer-count + first_round = 1 + + # Check data format + if isinstance(data, int): + data = [data] + data_buf = data[:] + + n = len(data) + + # One extra readback (for address) + n = n + 1 + + # Send only enough ops at once to avoid overflowing buffer + while n > 0: + num_words = min(self.max_buf, n) + + for i in range(num_words - first_round): + if data_buf[0] is None: + assert _increment + # Use read req to increment address w/o writing + self.port.write(bytearray(create_instruction( + CMD_READ_REQ, 0 + ))) + else: + self.port.write(bytearray(create_instruction( + CMD_WRITE_REQ, data_buf[0] + ))) + + data_buf = data_buf[1:] + + first_round = 0 + + ret.extend(self._read_data(num_words)) + n = n - num_words + + assert len(data_buf) == 0 + + # Remove address-acknowledge + assert ret[0][0] == RESP_ADDR_ACK + ret = ret[1:] + for i, resp in enumerate(ret): + if data[i] is None: + assert resp[0] == RESP_READ_RESP + else: + assert resp[0] == RESP_WRITE_ACK + + # Verify that correct data was written + if verify and _increment: + data_read = self.read(address, n=len(data), _increment=True) + + if len(data) == 1: + assert (data_read == data[0]) or (data[0] is None) + else: + for i in range(len(data)): + assert (data_read[i] == data[i]) or (data[i] is None) + + def write_peripheral(self, address, data): + """ + Write all values in `data` to `address`. Blocks execution until finished or timed out. This should be used for peripherals which use a single register as a pipe. + + Arguments: + address (int): The singular address to write to. + data (list[int]): The data to write to the address. + """ + + self.write(address, data, verify=False, _increment=False) + + def reset(self): + """ + Forcibly reset the bus. Blocks until the bus-reset is acknowledged. + """ + self.port.write(bytearray(create_instruction( + CMD_BUS_RESET, 0 + ))) + + while True: + inst, data = self._read_data(1)[0] + + if inst == RESP_BUS_RESET: + return + + def poll_interrupts(self, reset=False): + """ + Poll the received interrupts. Returns an array of the 4 interrupts. + + Arguments: + reset (bool): Whether to reset the interrupts after reading. + """ + + self._read_port() + + ret = self.interrupts[:] + if reset: + self.reset_interrupts() + + return ret + + def poll_interrupts(self, reset=False): + """ + Poll the received interrupts. Returns an array of the 4 interrupts. + + Arguments: + reset (bool): Whether to reset the interrupts after reading. + """ + + self._read_port() + + ret = self.interrupts[:] + if reset: + self.reset_interrupts() + + return ret + + def reset_interrupts(self): + """ + Reset interrupts regardless of whether they have been polled. + """ + self.interrupts = [False, False, False, False] + + def close(self): + self.port.close() + + # Context manager compliance + def __enter__(self): + return self + + def __exit__(self, exception_type, exception_value, traceback): + self.close() diff --git a/designs/d11_gbailey_bfchip/dev/src/merged_test.py b/designs/d11_gbailey_bfchip/dev/src/merged_test.py new file mode 100644 index 0000000..215c40a --- /dev/null +++ b/designs/d11_gbailey_bfchip/dev/src/merged_test.py @@ -0,0 +1,124 @@ +# Version of `fpga_test.py` with the program merged in, for post-merge testing. + +from interface import Chip + +IoNone = 0b000 +IoOpcode = 0b001 +IoAddrHi = 0b010 +IoAddrLo = 0b011 +IoReadWrite = 0b100 +BusNone = 0b000 +BusReadProg = 0b010 +BusReadData = 0b100 +BusWriteData = 0b101 +BusReadIo = 0b110 +BusWriteIo = 0b111 + +class Inputs: + def __init__(self, chip): + self.bus_in = 0 + self.op_done = 0 + self.enable = 0 + self.chip = chip + + def set(self): + val = (self.enable << 9) | (self.op_done << 8) | self.bus_in + self.chip.set_all_inputs(val) + + def __repr__(self): + return f"bus_in={self.bus_in:08b}, " \ + f"op_done={self.op_done:b}, " \ + f"enable={self.enable:b}" + +class Outputs: + def __init__(self, chip): + self.bus_out = 0 + self.state = 0 + self.halted = 0 + self.chip = chip + + def get(self): + out = self.chip.get_all_outputs() + self.bus_out = out & 0x0FF + self.state = (out & 0x700) >> 8 + self.halted = (out & 0x800) >> 11 + + def __repr__(self): + return f"bus_out={self.bus_out:08b}, " \ + f"state={self.state:03b}, " \ + f"halted={self.halted:b}" + +# Modified version of Cristofani's IO test (CC-BY-SA). Includes a loop-forward +# check to make sure we're checking all the states. +prog = bytearray(b"++--[++++++++.]>,>+++++++++,>+++++++++++[<++++++<++++++<+>>>-]<<.>.<<-.>.>.<<.") +stdin = bytearray(b"\n") +input_end = 0 +stdout = bytearray(b"LB\nLB\n") + +chip = Chip("/dev/ttyUSB1") +inputs = Inputs(chip) +outputs = Outputs(chip) + +print("resetting") +chip.set_reset(1) +chip.step_clock() +chip.set_reset(0) + +inputs.enable = 1 +inputs.set() +outputs.get() + +# pseudo-registers +opcode = 0 +addr_hi = 0 +addr_lo = 0 + +data = bytearray(65536) +output = bytearray() + +cycles = 0 + +while not outputs.halted: + outputs.get() + # print(outputs) + if outputs.state == IoOpcode: + opcode = outputs.bus_out + elif outputs.state == IoAddrHi: + addr_hi = outputs.bus_out + elif outputs.state == IoAddrLo: + addr_lo = outputs.bus_out + elif outputs.state == IoReadWrite: + addr = (addr_hi << 8) | addr_lo + if opcode == BusReadProg: + if addr >= len(prog): + inputs.bus_in = 0 + else: + inputs.bus_in = prog[addr] + print(f"reading program [{addr:04x}]: {chr(inputs.bus_in)}") + elif opcode == BusReadData: + inputs.bus_in = data[addr] + print(f"reading data [{addr:04x}]: {inputs.bus_in}") + elif opcode == BusWriteData: + data[addr] = outputs.bus_out + print(f"writing data [{addr:04x}]: {outputs.bus_out}") + elif opcode == BusReadIo: + if len(stdin) > 0: + inputs.bus_in = stdin.pop(0) + else: + inputs.bus_in = input_end + print(f"reading io : {chr(inputs.bus_in)}") + elif opcode == BusWriteIo: + print(f"writing io : {chr(outputs.bus_out)}") + output.append(outputs.bus_out) + inputs.op_done = 1 + inputs.set() + # print(inputs) + chip.step_clock() + cycles += 1 + +print(f"halted, ran {cycles} cycles") +if output == stdout: + print(f"output: {bytes(output)}, success!") +else: + print(f"output: {bytes(output)}, differs from expected: {bytes(stdout)}") +assert(output == stdout) diff --git a/designs/d11_gbailey_bfchip/dev/src/tests/00-hello-world.toml b/designs/d11_gbailey_bfchip/dev/src/tests/00-hello-world.toml new file mode 100644 index 0000000..c71af84 --- /dev/null +++ b/designs/d11_gbailey_bfchip/dev/src/tests/00-hello-world.toml @@ -0,0 +1,8 @@ +# Obligatory Hello World test. Ensures that cell interactions, loops, and +# outputs are working. + +name = "hello_world" + +program = "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++." + +output = "Hello World!\n" diff --git a/designs/d11_gbailey_bfchip/dev/src/tests/01-cristofani-h.toml b/designs/d11_gbailey_bfchip/dev/src/tests/01-cristofani-h.toml new file mode 100644 index 0000000..c9c4167 --- /dev/null +++ b/designs/d11_gbailey_bfchip/dev/src/tests/01-cristofani-h.toml @@ -0,0 +1,8 @@ +name = "H" + +# Program by Daniel Cristofani, CC-BY-SA +# "Tests for several obscure problems. Should output an H." +program = """[]++++++++++[>>+>+>++++++[<<+<+++>>>-]<<<<-] +"A*$";?@![#>>+<<]>[>>]<<<<[>++<[-]]>.>.""" + +output = "H\n" diff --git a/designs/d11_gbailey_bfchip/dev/src/tests/02-cristofani-io-test.toml b/designs/d11_gbailey_bfchip/dev/src/tests/02-cristofani-io-test.toml new file mode 100644 index 0000000..ceb686b --- /dev/null +++ b/designs/d11_gbailey_bfchip/dev/src/tests/02-cristofani-io-test.toml @@ -0,0 +1,10 @@ +# Verifies that the input and output streams are behaving as expected + +name = "io_test" + +# Program by Daniel Cristofani, CC-BY-SA +program = ">,>+++++++++,>+++++++++++[<++++++<++++++<+>>>-]<<.>.<<-.>.>.<<." + +input = "\n" +input_end = 0 +output = "LB\nLB\n" # L=newline, B=null diff --git a/designs/d11_gbailey_bfchip/dev/src/tests/03-cristofani-rot13.toml b/designs/d11_gbailey_bfchip/dev/src/tests/03-cristofani-rot13.toml new file mode 100644 index 0000000..2608a02 --- /dev/null +++ b/designs/d11_gbailey_bfchip/dev/src/tests/03-cristofani-rot13.toml @@ -0,0 +1,34 @@ +# Not the best rot13 implementation, but it's used here to test very deep +# loop nesting. + +name = "rot13" + +# Program by Daniel Cristofani, CC-BY-SA +program = """, +[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<- +[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<- +[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<- +[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<- +[>++++++++++++++<- +[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<- +[>>+++++[<----->-]<<- +[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<- +[>++++++++++++++<- +[>+<-[>+<-[>+<-[>+<-[>+<- +[>++++++++++++++<- +[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<- +[>>+++++[<----->-]<<- +[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<- +[>++++++++++++++<- +[>+<-]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] +]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>.[-]<,] + +of course any function char f(char) can be made easily on the same principle + +[Daniel B Cristofani (cristofdathevanetdotcom) +http://www.hevanet.com/cristofd/brainfuck/] +""" + +input = "This is aTest of the rot13" +input_end = 0 +output = "Guvf vf nGrfg bs gur ebg13" diff --git a/designs/d11_gbailey_bfchip/dev/src/tests/04-cristofani-isort.toml b/designs/d11_gbailey_bfchip/dev/src/tests/04-cristofani-isort.toml new file mode 100644 index 0000000..44b60b2 --- /dev/null +++ b/designs/d11_gbailey_bfchip/dev/src/tests/04-cristofani-isort.toml @@ -0,0 +1,19 @@ +name = "isort" + +# Program by Daniel Cristofani, CC-BY-SA +program = """[isort.b -- insertion sort +(c) 2016 Daniel B. Cristofani +http://brainfuck.org/] + +>+[ + <[ + [>>+<<-]>[<<+<[->>+[<]]>>>[>]<<-]<<< + ]>>[<<+>>-]<[>+<-]>[>>]<, +]<<<[<+<]>[>.>] + +[This program sorts bytes of input using insertion sort.] +""" + +input = "43y 87th43gb4th43qiu haw4q" +input_end = 0 +output = " 3334444478abghhhiqqttuwy" diff --git a/designs/d11_gbailey_bfchip/dev/src/tests/05-cristofani-word-count.toml b/designs/d11_gbailey_bfchip/dev/src/tests/05-cristofani-word-count.toml new file mode 100644 index 0000000..4d73689 --- /dev/null +++ b/designs/d11_gbailey_bfchip/dev/src/tests/05-cristofani-word-count.toml @@ -0,0 +1,20 @@ +name = "word_count" + +# Program by Daniel Cristofani, CC-BY-SA +program = """>>>+>>>>>+>>+>>+[<<],[ + -[-[-[-[-[-[-[-[<+>-[>+<-[>-<-[-[-[<++[<++++++>-]< + [>>[-<]<[>]<-]>>[<+>-[<->[-]]]]]]]]]]]]]]]] + <[-<<[-]+>]<<[>>>>>>+<<<<<<-]>[>]>>>>>>>+>[ + <+[ + >+++++++++<-[>-<-]++>[<+++++++>-[<->-]+[+>>>>>>]] + <[>+<-]>[>>>>>++>[-]]+< + ]>[-<<<<<<]>>>> + ], +]+<++>>>[[+++++>>>>>>]<+>+[[<++++++++>-]<.<<<<<]>>>>>>>>] +[Counts lines, words, bytes. Assumes no-change-on-EOF or EOF->0. +Daniel B Cristofani (cristofdathevanetdotcom) +http://www.hevanet.com/cristofd/brainfuck/]""" + +input = "example 123\nasdf" +input_end = 0 +output = "\t1\t3\t16\n" diff --git a/designs/d11_gbailey_bfchip/dev/src/tests/10-bosman-quine.toml b/designs/d11_gbailey_bfchip/dev/src/tests/10-bosman-quine.toml new file mode 100644 index 0000000..bcf3c39 --- /dev/null +++ b/designs/d11_gbailey_bfchip/dev/src/tests/10-bosman-quine.toml @@ -0,0 +1,9 @@ +name = "quine" + +slow = true # skip normally (takes very long to run) +stage = 1 + +# Program by Erik Bosman +program = "-->+++>+>+>+>+++++>++>++>->+++>++>+>>>>>>>>>>>>>>>>->++++>>>>->+++>+++>+++>+++>+++>+++>+>+>>>->->>++++>+>>>>->>++++>+>+>>->->++>++>++>++++>+>++>->++>++++>+>+>++>++>->->++>++>++++>+>+>>>>>->>->>++++>++>++>++++>>>>>->>>>>+++>->++++>->->->+++>>>+>+>+++>+>++++>>+++>->>>>>->>>++++>++>++>+>+++>->++++>>->->+++>+>+++>+>++++>>>+++>->++++>>->->++>++++>++>++++>>++[-[->>+[>]++[<]<]>>+[>]<--[++>++++>]+[<]<<++]>>>[>]++++>++++[--[+>+>++++<<[-->>--<<[->-<[--->>+<<[+>+++<[+>>++<<]]]]]]>+++[>+++++++++++++++<-]>--.<<<]" + +output = "-->+++>+>+>+>+++++>++>++>->+++>++>+>>>>>>>>>>>>>>>>->++++>>>>->+++>+++>+++>+++>+++>+++>+>+>>>->->>++++>+>>>>->>++++>+>+>>->->++>++>++>++++>+>++>->++>++++>+>+>++>++>->->++>++>++++>+>+>>>>>->>->>++++>++>++>++++>>>>>->>>>>+++>->++++>->->->+++>>>+>+>+++>+>++++>>+++>->>>>>->>>++++>++>++>+>+++>->++++>>->->+++>+>+++>+>++++>>>+++>->++++>>->->++>++++>++>++++>>++[-[->>+[>]++[<]<]>>+[>]<--[++>++++>]+[<]<<++]>>>[>]++++>++++[--[+>+>++++<<[-->>--<<[->-<[--->>+<<[+>+++<[+>>++<<]]]]]]>+++[>+++++++++++++++<-]>--.<<<]" diff --git a/designs/d11_gbailey_bfchip/info.yaml b/designs/d11_gbailey_bfchip/info.yaml new file mode 100644 index 0000000..97ec142 --- /dev/null +++ b/designs/d11_gbailey_bfchip/info.yaml @@ -0,0 +1,6 @@ +--- +project: + source_files: + - toplevel_chip.v + - all_tapeout.v # file automatically generated + top_module: "toplevel_chip" diff --git a/designs/d11_gbailey_bfchip/media/hello_world.png b/designs/d11_gbailey_bfchip/media/hello_world.png new file mode 100644 index 0000000..cf73afb Binary files /dev/null and b/designs/d11_gbailey_bfchip/media/hello_world.png differ diff --git a/designs/d11_gbailey_bfchip/media/quine_passing.png b/designs/d11_gbailey_bfchip/media/quine_passing.png new file mode 100644 index 0000000..71835ff Binary files /dev/null and b/designs/d11_gbailey_bfchip/media/quine_passing.png differ diff --git a/designs/d11_gbailey_bfchip/media/tests_passing.png b/designs/d11_gbailey_bfchip/media/tests_passing.png new file mode 100644 index 0000000..f6369c3 Binary files /dev/null and b/designs/d11_gbailey_bfchip/media/tests_passing.png differ diff --git a/designs/d11_gbailey_bfchip/src/config.tcl b/designs/d11_gbailey_bfchip/src/config.tcl new file mode 100644 index 0000000..0f1a15d --- /dev/null +++ b/designs/d11_gbailey_bfchip/src/config.tcl @@ -0,0 +1,68 @@ +# PLEASE DO NOT EDIT THIS FILE! +# IT WILL MAKE YOUR CHIP UNMANUFACTURABLE +# The only line you may edit is FP_CORE_UTIL +# (may benefit from reducing it slightly) + +# User config +set script_dir [file dirname [file normalize [info script]]] + +# read some user config that is written by the setup.py program. +# - the name of the module is defined +# - the list of source files +source $::env(DESIGN_DIR)/user_config.tcl + +# save some time +set ::env(RUN_KLAYOUT_XOR) 0 +set ::env(RUN_KLAYOUT_DRC) 0 + +# don't put clock buffers on the outputs +set ::env(PL_RESIZER_BUFFER_OUTPUT_PORTS) 0 + +# allow use of specific sky130 cells +set ::env(SYNTH_READ_BLACKBOX_LIB) 1 + +# put all the pins on the left +set ::env(FP_PIN_ORDER_CFG) $::env(DESIGN_DIR)/pin_order.cfg + +# reduce wasted space +set ::env(TOP_MARGIN_MULT) 2 +set ::env(BOTTOM_MARGIN_MULT) 2 + +# absolute die size +set ::env(FP_SIZING) absolute +set ::env(DIE_AREA) "0 0 280 280" + +## THIS IS THE ONLY LINE YOU CAN EDIT +set ::env(FP_CORE_UTIL) 45 + +## set ::env(PL_BASIC_PLACEMENT) {1} + +set ::env(FP_IO_HLENGTH) 2 +set ::env(FP_IO_VLENGTH) 2 + +# use alternative efabless decap cells to solve LI density issue +set ::env(DECAP_CELL) "\ + sky130_fd_sc_hd__decap_3 \ + sky130_fd_sc_hd__decap_4 \ + sky130_fd_sc_hd__decap_6 \ + sky130_fd_sc_hd__decap_8 \ + sky130_ef_sc_hd__decap_12" + +# clock +set ::env(CLOCK_TREE_SYNTH) 1 + +# period is in ns, so 500ns == 2 MHz +set ::env(CLOCK_PERIOD) "500" +set ::env(CLOCK_PORT) {io_in[12]} + +# hold/slack margin +# set ::env(PL_RESIZER_HOLD_SLACK_MARGIN) 0.8 +# set ::env(GLB_RESIZER_HOLD_SLACK_MARGIN) 0.8 + +# don't use power rings or met5 +set ::env(DESIGN_IS_CORE) 0 +set ::env(RT_MAX_LAYER) {met4} + +# connect to first digital rails +set ::env(VDD_NETS) [list {vccd1}] +set ::env(GND_NETS) [list {vssd1}] diff --git a/designs/d11_gbailey_bfchip/src/pin_order.cfg b/designs/d11_gbailey_bfchip/src/pin_order.cfg new file mode 100644 index 0000000..0b85c63 --- /dev/null +++ b/designs/d11_gbailey_bfchip/src/pin_order.cfg @@ -0,0 +1,9 @@ +#N + +#S + +#E + +#W +io_in.* +io_out.* diff --git a/designs/d11_gbailey_bfchip/src/toplevel_chip.v b/designs/d11_gbailey_bfchip/src/toplevel_chip.v new file mode 100644 index 0000000..6a5acbe --- /dev/null +++ b/designs/d11_gbailey_bfchip/src/toplevel_chip.v @@ -0,0 +1,18 @@ +`default_nettype none + +// DO NOT EDIT THIS FILE +module toplevel_chip ( + input [13:0] io_in, + output [13:0] io_out +); + + my_chip mchip ( + .io_in(io_in[11:0]), + .io_out(io_out[11:0]), + .clock(io_in[12]), + .reset(io_in[13]) + ); + + assign io_out[13:12] = 2'b00; + +endmodule diff --git a/designs/d12_oball_i2c/.lastupdated b/designs/d12_oball_i2c/.lastupdated new file mode 100644 index 0000000..4d7b8c3 --- /dev/null +++ b/designs/d12_oball_i2c/.lastupdated @@ -0,0 +1 @@ +2023-05-14 diff --git a/designs/d12_oball_i2c/LICENSE b/designs/d12_oball_i2c/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/designs/d12_oball_i2c/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/designs/d12_oball_i2c/README.md b/designs/d12_oball_i2c/README.md new file mode 100644 index 0000000..5fea417 --- /dev/null +++ b/designs/d12_oball_i2c/README.md @@ -0,0 +1,160 @@ +# I2C I/O Peripheral Device + +Owen Ball +18-224/624 Spring 2023 Final Tapeout Project + +## Overview + +An I2C peripheral device with 24 8-bit registers. The device has one read only register +set to the value of 8 parallel inputs. The value of one register is outputted as a +parallel output. The device also features two PWM outputs controlled using the registers. + +# Design Specifications + +## Clock Speed +In order for proper function of the I2C line, the input clock should be approximately 10 to 15 times the frequency of the bus. To operate at the standard I2C clock speed of 100kHz, a clock of at least 1MHz should be used. +## Inputs/Outputs + +This design takes in a clock, active high reset, and has the following IO: + +| Number | Inputs | Outputs | +| :---: | :----: | :---: | +| 0 | SCL | SDA_N | +| 1 | SDA | UART_TX | +| 2 | ADDR_0 | PWM_0 | +| 3 | ADDR_1 | PWM_1 | +| 4 | D0_IN | D0_OUT | +| 5 | D1_IN | D1_OUT | +| 6 | D2_IN | D2_OUT | +| 7 | D3_IN | D3_OUT | +| 8 | D4_IN | D4_OUT | +| 9 | D5_IN | D5_OUT | +| 10 | D6_IN | D6_OUT | +| 11 | D7_IN | D7_OUT | + + +The inputs consist of the SCL line, the SDA line, 2 address select lines, and 8 input pins. The data pins directly map to the read-only register 0x00 as shown in the register map below. The address pins indicate the desired I2C address of the design. The table below shows the address that corresponds to each combination of these pins. + +| ADDR_1, ADDR_0 | I2C Address | +| :---: | :---: | +| 0,0 | 0x20 | +| 0,1 | 0x21 | +| 1,0 | 0x22 | +| 1,1 | 0x23 | + +The first output is SDA_N, which is the inverted SDA output of the chip, which +should then be connected to the gate of an NMOS to pull the SDA line to ground. +The chip also has two PWM outputs and a UART output. The functionality of these pins will be discussed in later sections. The last set of outputs is the 8-bit value stored in register 0x01 on the design. + + +## Register Map + +The design consists of 24 registers. + +- Register 0x00 is a read only register set to the value on the inputs D0_IN - D7_IN + +- Register 0x01 is directly outputted onto D0_OUT - D7_OUT + +- Registers 0x02-0x0B are used for controlling the PWM pins. However, they can be used +as memory registers if the PWM outputs are ignored or the PWM divider is set to 0. + +- Registers 0x0C-0x17 are not assigned to any function and can be used as volatile I2C memory + +![](media/registers.png) + + +## UART TX +The value in register 0x01 is continuously sent on output pin 1. 8 bits are sent per transmission with no parity bit. The line is held high for 7 bits worth of time before the next start bit is sent. + +The baud rate can be determined by dividing the clock speed of the design by 52. For a 1MHz clock, this corresponds to 19200 baud, and for a 500kHz clock, this corresponds to 9600 baud. + +![](media/UART.png) + +## PWM +The design features two PWM outputs, each controlled by 5 registers. For each PWM output. +- The 'High Cycles' registers correspond to the number of clock cycles that the PWM output will be high for. +- The 'Total Cycles' registers correspond to the number of clock cycles in one period of the PWM signal. If this value is lower than 'High Cycles,' the output will be held high. +- The clock divider register will be multiplied by the high time and period to allow for longer period PWM signals. Setting this register to 0 will deactivate the PWM output. + +When operating at 1MHz, it is recommended to set 'Total Cycles' to 16384 and operate 'High Cycles' between either 1000 and 2000 or 1024 and 2048. + +![](media/PWM.png) + +## Writing to Registers +In order to write to a register, the coordinator device should first send the I2C device address, followed by the target register, then the data to store to the register. If multiple bytes of data are provided, the target register will be incremented by 1 for each byte sent. This will wrap around to address 0x00, although it is not recommended to make use of this functionality. Address 0x00 is read only and will ignore attempts to write to it. + +An example transmission is shown below, where the device (address 0x23) has the bytes 0x00 and 0xFF written to registers 0x04 and 0x05. + +![](media/data_write.png) + +## Reading From Registers +In order to read from a register, the coordinator should first write the desired register address to the I2C device address. A repeated start condition should then be used, after which the I2C device address should be sent again, this time with the read/write bit set to read. The device will then send the data stored in the specified register. The device will continue to send the values stored in subsequent registers until a stop condition is sent. This will wrap around to register 0x00. + +All reads should first send the target register. Reading from the device without first sending the target register may yield the wrong data. + +An example transmission is shown below, where the value of 0x6A is read from register 0x00 of the I2C device (0x23). + +![](media/data_read.png) + + +# How it Works + +## FSM +The core of this design is the I2C peripheral functionality. All I/O is controlled either directly by the I2C controller or indirectly through the I2C registers. The I2C controller functions using an FSM and datapath to determine when to control the SDA line, when to send data, etc. + +The FSM for the design is shown below. Note that for clarity, a few of the transitions have been omitted, as noted at the top. +![](media/FSM.png) +The FSM consists of 4 main stages. +- Init+Idle: This stage prepares the design to receive a communication and puts it into a waiting state until the communication is started. Currently RESET serves no function, as the reset line directly controls the resetting of the I2C registers. However, if desired, this state could be made to reset only some parts of the design when an input is asserted +- Address: This stage receives the address being sent on the bus. If the address sent does not match the address of the design, it will return to its setup and waiting stage. If the address does match, and ACK will be sent and the state will be sent to either READ or GET_REG depending on the read/write bit. +- Write: This stage handles values being written to the I2C registers, or the sending of a register to be read from. This stage first reads in a byte from the bus, which is stored to a register select. An ACK is then sent. The design then reads in a byte in the WRITE stage, and will write this to the target register during the WRITE_ACK state. This state will also increment the register select for the next WRITE. If a read is being performed, the repeated start condition will move the FSM from the WRITE state to the ADDR state, and the register address written to the device will be remembered for the read operation. +- Read: Following the writing of the target register and the repeated start condition, the device will begin sending the data stored in the target register onto the bus. If an ACK is sent, the device will increment the target register and send another byte. If a NACK is sent, the design will move into the READ_DONE state, which will release the SDA line so a stop condition can be sent. This state is not necessary, and a return to WAIT would suffice. + +## Registers + +The 24 registers are multiplexed to a data line using the register select sent by the I2C coordinator device. For reading from the design, a single bit is then selected from this register and sent to the SDA line. All registers are volatile. Writes occur on falling edges of SCL and require a write enable. Register 0x00 will ignore attempts to write to it. + +## I/O + +Some of the I2C registers are used to determine the outputs sent to the PWM, UART, and parallel output pins. The PWM and UART pins use their own datapaths to control the outputs. These datapaths mostly include counters that divide down the main clock of the design and determine what the output should be at any given time. + +# Design Testing / Bringup + +## Hardware Peripherals + +Both the iCE40 FPGA and the ASIC do not support leaving outputs as high impedance. As a result, in order to drive the SDA line, the SDA_N output of the chip must be fed into an NMOS with a pull-up resistor. The drain of the NMOS should then be connected to SDA. Thus when SDA_N is high, SDA is pulled to ground and otherwise, is pulled to 3.3V. The resistor value should be somewhere in the range of 2kOhm to 10kOhm, with the NMOS being capable of switching fast enough for the desired I2C speed and being able to overpower the SDA pull up resistors. Note that this chip does not perform clock stretching and as such, has no need to drive the SCL line. + +![](media/MOSFET.png) + +The design was tested on an iCE40 FPGA using a RPi Pico running CircuitPython as the coordinator. + +## Testing + +Testing the I2C functionality can be achieved using the SCL, SDA, SDA_N (and accompanying hardware), the two ADDR_X lines, clock, and reset. Using the I2C coordinator, it can be verified that the design is responding to the proper address and the registers are functioning properly. This can be done by sending a write consisting of 23 different bytes starting at 0x01. A read of 24 bytes starting at 0x00 can then be performed, and it can be verified that these bytes read back match the bytes written to the design. If the design does not respond properly on the I2C bus, the clock and I2C bus speed should be slowed down until it does. + +Testing the PWM output can be done using an oscilloscope to verify that the time high and total time for the PWM signal match the values written to the control register. + +UART testing can be verified using the coordinator device to read in the UART signal and verify that it matches the value stored in register 0x01. + +Testing of the parallel inputs and outputs can either be done using 8 dip switches and 8 LEDs, or with GPIO pins on the coordinator device. + +## Alchitry Cu Testing Setup + +The primary testing of the design was performed on the Alchitry Cu iCE40 FPGA. The FPGA was connected to a RPi Pico, as well as a SparkFun LCD and a Sparkfun LED Button. Additionally, two breakout boards were made for the FPGA, one for the SDA MOSFET, output LEDs, and a reset button, and one for input DIP switches. + +The Pico was set up to read the status of the I2C button, and increment a counter accordingly. This counter value is then sent to 8 of the output LEDs by writing to register 0x01. The two PWM pins are also updated according to the counter. Address 0x00 is then read to get the status of the DIP switches. The lower 6 bits of this are converted to an RGB color, which is then sent to the LCD screen backlight. The UART line can be connected to the Pico if desired. The Pico also will perform writes to every register on the device, then read from all the registers to verify their contents. + +The code used on the Pico can be found [here.](src/picocode.py) +![](media/testing.png) + +# Media + +[Video](media/testing_video.mp4) + +![](media/breakout1.png) + +![](media/breakout2.png) + +![](media/FPGA.png) + + diff --git a/designs/d12_oball_i2c/info.yaml b/designs/d12_oball_i2c/info.yaml new file mode 100644 index 0000000..14513a5 --- /dev/null +++ b/designs/d12_oball_i2c/info.yaml @@ -0,0 +1,12 @@ +--- +project: + source_files: + - toplevel_chip.v + - chip.sv + - FSM.sv + - IO.sv + - datapath.sv + - library.sv + - I2C.sv + top_module: "toplevel_chip" + diff --git a/designs/d12_oball_i2c/media/FPGA.png b/designs/d12_oball_i2c/media/FPGA.png new file mode 100644 index 0000000..fab0635 Binary files /dev/null and b/designs/d12_oball_i2c/media/FPGA.png differ diff --git a/designs/d12_oball_i2c/media/FSM.png b/designs/d12_oball_i2c/media/FSM.png new file mode 100644 index 0000000..bf4df0c Binary files /dev/null and b/designs/d12_oball_i2c/media/FSM.png differ diff --git a/designs/d12_oball_i2c/media/IO.png b/designs/d12_oball_i2c/media/IO.png new file mode 100644 index 0000000..c2c715c Binary files /dev/null and b/designs/d12_oball_i2c/media/IO.png differ diff --git a/designs/d12_oball_i2c/media/MOSFET.png b/designs/d12_oball_i2c/media/MOSFET.png new file mode 100644 index 0000000..8477aa5 Binary files /dev/null and b/designs/d12_oball_i2c/media/MOSFET.png differ diff --git a/designs/d12_oball_i2c/media/PWM.png b/designs/d12_oball_i2c/media/PWM.png new file mode 100644 index 0000000..b0de7b8 Binary files /dev/null and b/designs/d12_oball_i2c/media/PWM.png differ diff --git a/designs/d12_oball_i2c/media/UART.png b/designs/d12_oball_i2c/media/UART.png new file mode 100644 index 0000000..84a32d6 Binary files /dev/null and b/designs/d12_oball_i2c/media/UART.png differ diff --git a/designs/d12_oball_i2c/media/breakout1.png b/designs/d12_oball_i2c/media/breakout1.png new file mode 100644 index 0000000..63eed71 Binary files /dev/null and b/designs/d12_oball_i2c/media/breakout1.png differ diff --git a/designs/d12_oball_i2c/media/breakout2.png b/designs/d12_oball_i2c/media/breakout2.png new file mode 100644 index 0000000..16911e0 Binary files /dev/null and b/designs/d12_oball_i2c/media/breakout2.png differ diff --git a/designs/d12_oball_i2c/media/data_read.png b/designs/d12_oball_i2c/media/data_read.png new file mode 100644 index 0000000..d8ebe36 Binary files /dev/null and b/designs/d12_oball_i2c/media/data_read.png differ diff --git a/designs/d12_oball_i2c/media/data_write.png b/designs/d12_oball_i2c/media/data_write.png new file mode 100644 index 0000000..021fa87 Binary files /dev/null and b/designs/d12_oball_i2c/media/data_write.png differ diff --git a/designs/d12_oball_i2c/media/registers.png b/designs/d12_oball_i2c/media/registers.png new file mode 100644 index 0000000..83a4695 Binary files /dev/null and b/designs/d12_oball_i2c/media/registers.png differ diff --git a/designs/d12_oball_i2c/media/testing.png b/designs/d12_oball_i2c/media/testing.png new file mode 100644 index 0000000..cc1ebba Binary files /dev/null and b/designs/d12_oball_i2c/media/testing.png differ diff --git a/designs/d12_oball_i2c/media/testing_video.mp4 b/designs/d12_oball_i2c/media/testing_video.mp4 new file mode 100644 index 0000000..008f7df Binary files /dev/null and b/designs/d12_oball_i2c/media/testing_video.mp4 differ diff --git a/designs/d12_oball_i2c/src/FSM.sv b/designs/d12_oball_i2c/src/FSM.sv new file mode 100644 index 0000000..5468dd1 --- /dev/null +++ b/designs/d12_oball_i2c/src/FSM.sv @@ -0,0 +1,89 @@ +`default_nettype none + +//A Mealy FSM to control the state of the chip +module FSM + (output logic clear_stop, clear_start, clear_counter, in_enable, send_ack, + output logic reg_sel_en, reg_sel_inc, we, out_en, + input logic clock, start, stop, reset, counted_8, addr_valid, ACK, + input logic SCL_negedge, + input logic [7:0] data_in); + + //Defines the states of the FSM + enum logic [3:0] {RESET, INIT, WAIT, ADDR, ADDR_ACK, GET_REG, REG_ACK, WRITE, READ, WRITE_ACK, READ_ACK, READ_DONE} currState, nextState; + logic read_write; + assign read_write = data_in[0]; + + + //nextState logic + always_comb begin + case (currState) + RESET: nextState = INIT; + INIT: nextState = WAIT; + WAIT: nextState = (start) ? ADDR : WAIT; + ADDR: begin + if (counted_8) + nextState = (addr_valid) ? ADDR_ACK : INIT; + else + nextState = ADDR; + end + ADDR_ACK: nextState = (read_write) ? READ : GET_REG; + GET_REG: nextState = (counted_8) ? REG_ACK : GET_REG; + REG_ACK: nextState = WRITE; + WRITE: nextState = (counted_8) ? WRITE_ACK : WRITE; + WRITE_ACK: nextState = WRITE; + READ: nextState = (counted_8) ? READ_ACK : READ; + READ_ACK: nextState = (~ACK) ? READ_DONE : READ; + READ_DONE: nextState = READ_DONE; + default: begin + nextState = INIT; + end + endcase + end + + //Determines the output of the FSM given currState + always_comb begin + //default values + clear_stop = 1'b0; + clear_start = 1'b0; + clear_counter = 1'b0; + in_enable = 1'b0; + send_ack = 1'b0; + reg_sel_en = 1'b0; + reg_sel_inc = 1'b0; + we = 1'b0; + out_en = 1'b0; + + case (currState) + RESET: ; + INIT: {clear_stop, clear_start} = 2'b11; + WAIT: clear_counter = 1'b1; + ADDR: {clear_start, in_enable} = 2'b11; + ADDR_ACK: {send_ack, clear_counter} = 2'b11; + GET_REG: in_enable = 1'b1; + REG_ACK: {send_ack, clear_counter, reg_sel_en} = 3'b111; + WRITE: begin + //handles the repeated start condition used when writing the register + //to read from, then immediately reading that register + if (start) clear_counter = 1'b1; + else in_enable = 1'b1; + + if (counted_8) we = 1'b1; + end + WRITE_ACK: {send_ack, clear_counter, reg_sel_inc} = 3'b111; + READ: out_en = 1'b1; + READ_ACK: {clear_counter, reg_sel_inc} = 2'b11; + READ_DONE: ; + default: ; + endcase + end + + //State transitions + always_ff @(posedge clock, posedge reset) begin + if (reset) currState <= RESET; + else if (stop) currState <= INIT; + else if (start) currState <= ADDR; + else if (currState == RESET || currState == INIT) currState <= nextState; + else if (SCL_negedge) currState <= nextState; + end + +endmodule: FSM diff --git a/designs/d12_oball_i2c/src/I2C.sv b/designs/d12_oball_i2c/src/I2C.sv new file mode 100644 index 0000000..964e888 --- /dev/null +++ b/designs/d12_oball_i2c/src/I2C.sv @@ -0,0 +1,56 @@ +`default_nettype none + + +//Module to interface with I2C bus +module I2C + (input logic SCL_in, SDA_in, clock, reset, + input logic [7:0] parallel_in, + input logic [1:0] addr_sel, + output logic SDA_out, + output logic [7:0] reg_out, + output logic [8*`REGCOUNT-1:0] registers_packed); + + logic SCL_sync, SDA_sync, counted_8, clear_counter, start, stop, clear_start; + logic clear_stop, addr_valid, in_enable, send_ack, we, out_en, ACK; + logic SCL_posedge, SCL_negedge, SDA_posedge, SDA_negedge; + logic [7:0] data_in; + logic reg_sel_en, reg_sel_inc, data_out; + logic [4:0] reg_sel_latched; + logic [3:0] count; + + //Synchronize bus lines and detect edges + synchronizer_edge_detect S1 (.async(SCL_in), .sync(SCL_sync), .clock, .sig_posedge(SCL_posedge), .sig_negedge(SCL_negedge)); + synchronizer_edge_detect S2 (.async(SDA_in), .sync(SDA_sync), .clock, .sig_posedge(SDA_posedge), .sig_negedge(SDA_negedge)); + + //Generate the I2C output + gen_output OUT (.send_ack, .serial_out(data_out), .out_en, .SDA_out); + + //Counts the number of bits that have been sent on the line + count_8 COUNT (.clock, .en(SCL_posedge), .done(counted_8), .clear(clear_counter), .count); + + //Detect start and stop conditions + start_detect START (.start, .clock, .SCL(SCL_sync), .SDA_negedge, .clear_start(clear_start | reset)); + stop_detect STOP (.stop, .clock, .SCL(SCL_sync), .SDA_posedge, .clear_stop(clear_stop | reset)); + + //Reads in the data from the bus + data_input IN_REG (.clock, .SCL_posedge, .SDA(SDA_sync), .enable(in_enable), .data_in, .reset); + + //Checks if the address matches 0x20 + check_addr ADDR (.data_in(data_in[7:1]), .addr_valid, .addr_sel); + + //Selects the target register + reg_sel REG(.reset, .clock, .SCL_negedge, .sel_out(reg_sel_latched), .sel_in(data_in[4:0]), .en(reg_sel_en), .inc(reg_sel_inc)); + + //Interface with the memory + memory MEM (.we, .clock, .SCL_negedge, .reset, .sel(reg_sel_latched), .count(count[2:0]), + .data_in(data_in[7:0]), .data_out, .reg_out, .registers_packed, .parallel_in); + + //Generate the acknowledge + get_ack READ_ACK (.clock, .SCL_posedge, .SDA(SDA_sync), .ACK); + + //Instantiate the FSM + FSM M (.*); + +endmodule: I2C + + diff --git a/designs/d12_oball_i2c/src/IO.sv b/designs/d12_oball_i2c/src/IO.sv new file mode 100644 index 0000000..4fb2ade --- /dev/null +++ b/designs/d12_oball_i2c/src/IO.sv @@ -0,0 +1,98 @@ +`default_nettype none + +module IO + (input logic clock, reset, + input logic [8*`REGCOUNT-1:0] registers_packed, + output logic [10:0] data_out); + + logic PWM1, PWM2, tx; + logic [7:0] reg_out; + + assign reg_out = registers_packed[8*(1)+7 -: 8]; + assign data_out[10:3] = reg_out; + + UART_TX UART_DRIVER (.clock, .reset, .data(reg_out), .tx); + PWM_out PWM_DRIVER (.registers_packed, .clock, .PWM1, .PWM2, .reset); + assign data_out[2:1] = {PWM2, PWM1}; + assign data_out[0] = tx; + +endmodule: IO + + +module PWM_out + (input logic [8*`REGCOUNT-1:0] registers_packed, + input logic clock, reset, + output logic PWM1, PWM2); + + logic [15:0] PWM1H, PWM1T, PWM2H, PWM2T; + logic [7:0] PWM1_div, PWM2_div; + + assign PWM1H = registers_packed[8*('h3)+7 -: 16]; + assign PWM1T = registers_packed[8*('h5)+7 -: 16]; + assign PWM1_div = registers_packed[8*('h6)+7 -: 8]; + assign PWM2H = registers_packed[8*('h8)+7 -: 16]; + assign PWM2T = registers_packed[8*('ha)+7 -: 16]; + assign PWM2_div = registers_packed[8*('hb)+7 -: 8]; + + PWM P1 (.clock, .PWM_out(PWM1), .PWMH(PWM1H), .PWMT(PWM1T), .PWM_div(PWM1_div), .reset); + PWM P2 (.clock, .PWM_out(PWM2), .PWMH(PWM2H), .PWMT(PWM2T), .PWM_div(PWM2_div), .reset); + +endmodule: PWM_out + + + +module PWM + (input logic clock, reset, + input logic [15:0] PWMH, PWMT, + input logic [7:0] PWM_div, + output logic PWM_out); + + logic [15:0] counter2; + logic [7:0] counter1; + + always_comb + if ((counter2 < PWMH) && (PWM_div != 8'b0)) + PWM_out = 1'b1; + else + PWM_out = 1'b0; + + always_ff @(posedge clock, posedge reset) begin + if (reset) begin + counter1 <= 8'b0; + counter2 <= 16'b1; + end + else if (counter1 >= PWM_div) begin + if (counter2 >= PWMT - 16'b1) counter2 <= 16'b0; + else counter2 <= counter2 + 16'b1; + counter1 <= 8'b1; + end + else counter1 <= counter1 + 8'b1; + end + + +endmodule: PWM + + +module UART_TX + (input logic clock, reset, + input logic [7:0] data, + output logic tx); + + logic [5:0] counter; + logic [15:0] frame; + + assign tx = frame[0]; + + always_ff @(posedge clock, posedge reset) begin + if (reset) begin + counter <= 6'b0; + frame <= {7'b1111111, 8'b0, 1'b0}; + end + else if (counter >= 6'd51) begin + counter <= 6'b0; + if (frame <= 16'b1) frame <= {7'b1111111, data, 1'b0}; + else frame = frame >> 1; + end + else counter <= counter + 6'b1; + end +endmodule: UART_TX \ No newline at end of file diff --git a/designs/d12_oball_i2c/src/chip.sv b/designs/d12_oball_i2c/src/chip.sv new file mode 100644 index 0000000..926dd67 --- /dev/null +++ b/designs/d12_oball_i2c/src/chip.sv @@ -0,0 +1,34 @@ +`default_nettype none + +`define REGCOUNT 24 + +//Top level module for design +module my_chip ( + input logic [11:0] io_in, // Inputs to your chip + output logic [11:0] io_out, // Outputs from your chip + input logic clock, + input logic reset // Important: Reset is ACTIVE-HIGH +); + + logic SCL_in, SDA_in, SDA_out; + logic [7:0] reg_out; + logic [8*`REGCOUNT-1:0] registers_packed; + logic SDA_out_temp; + + logic [10:0] data_out; + + assign SCL_in = io_in[0]; + assign SDA_in = io_in[1]; + + I2C M1 (.SCL_in, .SDA_in, .clock, .reset, .SDA_out(SDA_out_temp), .reg_out, + .registers_packed, .parallel_in(io_in[11:4]), .addr_sel(io_in[3:2])); + + IO M2 (.registers_packed, .data_out, .clock, .reset); + + assign SDA_out = ~SDA_out_temp; + + assign io_out[11:1] = data_out; + assign io_out[0] = SDA_out; + + +endmodule diff --git a/designs/d12_oball_i2c/src/config.tcl b/designs/d12_oball_i2c/src/config.tcl new file mode 100644 index 0000000..1e18c72 --- /dev/null +++ b/designs/d12_oball_i2c/src/config.tcl @@ -0,0 +1,68 @@ +# PLEASE DO NOT EDIT THIS FILE! +# IT WILL MAKE YOUR CHIP UNMANUFACTURABLE +# The only line you may edit is FP_CORE_UTIL +# (may benefit from reducing it slightly) + +# User config +set script_dir [file dirname [file normalize [info script]]] + +# read some user config that is written by the setup.py program. +# - the name of the module is defined +# - the list of source files +source $::env(DESIGN_DIR)/user_config.tcl + +# save some time +set ::env(RUN_KLAYOUT_XOR) 0 +set ::env(RUN_KLAYOUT_DRC) 0 + +# don't put clock buffers on the outputs +set ::env(PL_RESIZER_BUFFER_OUTPUT_PORTS) 0 + +# allow use of specific sky130 cells +set ::env(SYNTH_READ_BLACKBOX_LIB) 1 + +# put all the pins on the left +set ::env(FP_PIN_ORDER_CFG) $::env(DESIGN_DIR)/pin_order.cfg + +# reduce wasted space +set ::env(TOP_MARGIN_MULT) 2 +set ::env(BOTTOM_MARGIN_MULT) 2 + +# absolute die size +set ::env(FP_SIZING) absolute +set ::env(DIE_AREA) "0 0 280 280" + +## THIS IS THE ONLY LINE YOU CAN EDIT +set ::env(FP_CORE_UTIL) 40 + +## set ::env(PL_BASIC_PLACEMENT) {1} + +set ::env(FP_IO_HLENGTH) 2 +set ::env(FP_IO_VLENGTH) 2 + +# use alternative efabless decap cells to solve LI density issue +set ::env(DECAP_CELL) "\ + sky130_fd_sc_hd__decap_3 \ + sky130_fd_sc_hd__decap_4 \ + sky130_fd_sc_hd__decap_6 \ + sky130_fd_sc_hd__decap_8 \ + sky130_ef_sc_hd__decap_12" + +# clock +set ::env(CLOCK_TREE_SYNTH) 1 + +# period is in ns, so 500ns == 2 MHz +set ::env(CLOCK_PERIOD) "500" +set ::env(CLOCK_PORT) {io_in[12]} + +# hold/slack margin +# set ::env(PL_RESIZER_HOLD_SLACK_MARGIN) 0.8 +# set ::env(GLB_RESIZER_HOLD_SLACK_MARGIN) 0.8 + +# don't use power rings or met5 +set ::env(DESIGN_IS_CORE) 0 +set ::env(RT_MAX_LAYER) {met4} + +# connect to first digital rails +set ::env(VDD_NETS) [list {vccd1}] +set ::env(GND_NETS) [list {vssd1}] diff --git a/designs/d12_oball_i2c/src/constrain.py b/designs/d12_oball_i2c/src/constrain.py new file mode 100644 index 0000000..adf6b9f --- /dev/null +++ b/designs/d12_oball_i2c/src/constrain.py @@ -0,0 +1,7 @@ +ctx.createRectangularRegion("region", 1, 1, 1, 40) + +for cell, cellinfo in ctx.cells: + print("Floorplan", cell) + if "my_blinky" in str(cell): + print("Constrain", cell) + ctx.constrainCellToRegion(cell, "region") diff --git a/designs/d12_oball_i2c/src/constraint.txt b/designs/d12_oball_i2c/src/constraint.txt new file mode 100644 index 0000000..9fcdd00 --- /dev/null +++ b/designs/d12_oball_i2c/src/constraint.txt @@ -0,0 +1,9 @@ +set_io clk100 P7 +set_io reset_n P8 + +set_io SCL_in M1 // A2 +set_io SDA_in L1 // A3 +set_io SDA_out P1 //A49 +set_io i2c_reset J1 //A5 + + diff --git a/designs/d12_oball_i2c/src/constraints.pcf b/designs/d12_oball_i2c/src/constraints.pcf new file mode 100644 index 0000000..a6b48c9 --- /dev/null +++ b/designs/d12_oball_i2c/src/constraints.pcf @@ -0,0 +1,32 @@ +set_io clk100 P7 +set_io reset_n P8 + +set_io SCL_in M1 +set_io SDA_in L1 +set_io SDA_out J3 +set_io i2c_reset J1 + +set_io led[0] P1 +set_io led[1] K4 +set_io led[2] H3 +set_io led[3] G4 +set_io led[4] F3 +set_io led[5] E4 +set_io led[6] C4 +set_io led[7] C5 + +set_io parallel_in[0] M4 +set_io parallel_in[1] M3 +set_io parallel_in[2] P3 +set_io parallel_in[3] P2 +set_io parallel_in[4] L5 +set_io parallel_in[5] L4 +set_io parallel_in[6] P5 +set_io parallel_in[7] P4 + +set_io PWM[0] G1 +set_io PWM[1] E1 + +set_io UART C1 +set_io ADDR[0] D3 +set_io ADDR[1] A1 diff --git a/designs/d12_oball_i2c/src/datapath.sv b/designs/d12_oball_i2c/src/datapath.sv new file mode 100644 index 0000000..f3e70d4 --- /dev/null +++ b/designs/d12_oball_i2c/src/datapath.sv @@ -0,0 +1,193 @@ +`default_nettype none + +//Detects the start bit on the bus +module start_detect + (input logic SCL, SDA_negedge, clear_start, clock, + output logic start); + + always_ff @(posedge clock, posedge clear_start) + if (clear_start) start = 1'b0; + else if (SCL & SDA_negedge) start = 1'b1; + +endmodule: start_detect + + +//Detects the stop bit on the bus +module stop_detect + (input logic SCL, SDA_posedge, clear_stop, clock, + output logic stop); + + always_ff @(posedge clock, posedge clear_stop) + if (clear_stop) stop = 1'b0; + else if (SCL & SDA_posedge) stop = 1'b1; + +endmodule: stop_detect + + +//Uses a shift register to read in the data from the I2C line +module data_input + (input logic SCL_posedge, SDA, enable, reset, clock, + output logic [7:0] data_in); + + ShiftRegister_SIPO #(8) SHIFT (.serial(SDA), .clock(clock), .en(enable & SCL_posedge), + .Q(data_in), .reset); + +endmodule: data_input + + +//Counts the # of bits sent on the bus, and sets a flag when it reaches 8 +module count_8 + (input logic clear, clock, en, + output logic done, + output logic [3:0] count); + + assign done = (count == 4'b1000); + + always_ff @(posedge clock, posedge clear) + if (clear) count <= 4'b0000; + else if ((count < 4'b1000) & en) count <= count + 4'b1; + +endmodule: count_8 + + +//Determines if the address sent is 0x20; +module check_addr + (input logic [6:0] data_in, + input logic [1:0] addr_sel, + output logic addr_valid); + + logic [6:0] addr; + + assign addr_valid = (data_in == addr); + + always_comb + unique case (addr_sel) + 2'b00: addr = 7'h20; + 2'b01: addr = 7'h21; + 2'b10: addr = 7'h22; + 2'b11: addr = 7'h23; + endcase + +endmodule: check_addr + + +//Sets the selected register or increments it +module reg_sel + (input logic [4:0] sel_in, + input logic inc, en, clock, reset, SCL_negedge, + output logic [4:0] sel_out); + + always_ff @(posedge clock, posedge reset) begin + if (reset) sel_out <= 5'b00000; + else if (en & SCL_negedge) sel_out <= sel_in; + else if (inc & SCL_negedge & sel_out < `REGCOUNT-1) sel_out <= sel_out + 5'd1; + else if (inc & SCL_negedge) sel_out <= 5'b00000; + end + +endmodule: reg_sel + +//A collection of registers to read/write from +module memory + (input logic we, clock, reset, SCL_negedge, + input logic [4:0] sel, + input logic [2:0] count, + input logic [7:0] data_in, + input logic [7:0] parallel_in, + output logic data_out, + output logic [7:0] reg_out, + output logic [8*`REGCOUNT-1:0] registers_packed); + + logic [7:0] registers [`REGCOUNT-1:0]; + + logic [2:0] index; + logic [7:0] data_out_8, parallel_in_temp; + + integer i; + integer j; + + //Packs the registers into an array so it can be outputted (when converted to verilog) + always_comb + for (j = 0; j < `REGCOUNT; j=j+1) registers_packed[(8*(j+1)-1)-:8] = registers[j]; + + assign reg_out = registers[1]; + + //Gets a bit from the selected register when writing to bus + assign data_out = data_out_8[3'b111 - index]; + assign data_out_8 = registers[sel]; + + //Writes to the selected register, resets, and sets the read only register + always_ff @(posedge clock, posedge reset) begin + if (reset) begin + for (i = 1; i < 32; i=i+1) registers[i] <= 8'b0; + end + else begin + if (we & SCL_negedge & sel != 5'h0) begin + registers[sel] <= data_in; + end + else if (SCL_negedge) index <= count; + + registers[0] <= parallel_in_temp; + parallel_in_temp <= parallel_in; + end + end + +endmodule: memory + + +//Determines if the output line should be pulled low or not +module gen_output + (input logic send_ack, serial_out, out_en, + output logic SDA_out); + + always_comb + if (send_ack) SDA_out = 1'b0; + else if (out_en && ~serial_out) SDA_out = 1'b0; + else SDA_out = 1'b1; + +endmodule: gen_output + +//Determines if an ack is set by master (or any 0 bit for that matter) +module get_ack + (input logic SCL_posedge, SDA, clock, + output logic ACK); + + always_ff @(posedge clock) + if (SCL_posedge) ACK <= ~SDA; + +endmodule: get_ack + + +//Detects the edges of a signal +module edge_detect + (input logic sig, clock, + output logic sig_posedge, sig_negedge, sig_out); + + logic prev; + + assign sig_out = prev; + + always_ff @(posedge clock) begin + if (sig & ~prev) sig_posedge <= 1'b1; + else sig_posedge <= 1'b0; + + if (~sig & prev) sig_negedge <= 1'b1; + else sig_negedge <= 1'b0; + + prev <= sig; + end +endmodule: edge_detect + + +//A synchronizer module to synchronize an asynchronous input to a clock, as +//well as to determine clock edges +module synchronizer_edge_detect + (input logic async, clock, + output logic sync, sig_posedge, sig_negedge); + + logic temp; + + DFlipFlop m1 (.D(async), .clock, .Q(temp)); + + edge_detect EDGE (.sig(temp), .clock, .sig_posedge, .sig_negedge, .sig_out(sync)); + +endmodule: synchronizer_edge_detect \ No newline at end of file diff --git a/designs/d12_oball_i2c/src/datapath_FSM.pdf b/designs/d12_oball_i2c/src/datapath_FSM.pdf new file mode 100644 index 0000000..ccfe33a Binary files /dev/null and b/designs/d12_oball_i2c/src/datapath_FSM.pdf differ diff --git a/designs/d12_oball_i2c/src/decoder.v b/designs/d12_oball_i2c/src/decoder.v new file mode 100644 index 0000000..8d6310e --- /dev/null +++ b/designs/d12_oball_i2c/src/decoder.v @@ -0,0 +1,38 @@ + +/* + -- 1 -- + | | + 6 2 + | | + -- 7 -- + | | + 5 3 + | | + -- 4 -- +*/ + +module seg7 ( + input wire [3:0] counter, + output reg [6:0] segments +); + + always @(*) begin + case(counter) + // 7654321 + 0: segments = 7'b0111111; + 1: segments = 7'b0000110; + 2: segments = 7'b1011011; + 3: segments = 7'b1001111; + 4: segments = 7'b1100110; + 5: segments = 7'b1101101; + 6: segments = 7'b1111100; + 7: segments = 7'b0000111; + 8: segments = 7'b1111111; + 9: segments = 7'b1100111; + default: + segments = 7'b0000000; + endcase + end + +endmodule + diff --git a/designs/d12_oball_i2c/src/library.sv b/designs/d12_oball_i2c/src/library.sv new file mode 100644 index 0000000..ae672a8 --- /dev/null +++ b/designs/d12_oball_i2c/src/library.sv @@ -0,0 +1,27 @@ +`default_nettype none + + +//A positive edge D flip flop with active low preset and reset inputs +module DFlipFlop + (input logic D, clock, + output logic Q); + always_ff @(posedge clock) + Q <= D; +endmodule: DFlipFlop + + +//A serial-in parallel-out shift register. Takes in a serial input and shifts +//it into the register if 'en' is asseted. +module ShiftRegister_SIPO + #(parameter WIDTH = 8) + (input logic serial, en, clock, reset, + output logic [WIDTH-1:0]Q); + + always_ff @(posedge clock, posedge reset) + if (reset) Q <= {WIDTH {1'b0}}; + else if (en) Q <= {Q[WIDTH-2:0], serial}; + +endmodule: ShiftRegister_SIPO + + + diff --git a/designs/d12_oball_i2c/src/out.v b/designs/d12_oball_i2c/src/out.v new file mode 100644 index 0000000..8c0e8aa --- /dev/null +++ b/designs/d12_oball_i2c/src/out.v @@ -0,0 +1,435 @@ +`default_nettype none +module I2C ( + SCL_in, + SDA_in, + clock, + reset, + SDA_out +); + input wire SCL_in; + input wire SDA_in; + input wire clock; + input wire reset; + output wire SDA_out; + wire SCL_sync; + wire SDA_sync; + wire counted_8; + wire clear_counter; + wire start; + wire stop; + wire clear_start; + wire clear_stop; + wire addr_valid; + wire clear_mem; + wire in_enable; + wire send_ack; + wire we; + wire [8:0] data_in; + wire reg_sel_en; + wire reg_sel_inc; + wire data_out; + wire [2:0] reg_sel_latched; + wire [3:0] count; + Synchronizer S1( + .async(SCL_in), + .sync(SCL_sync), + .clock(clock) + ); + Synchronizer S2( + .async(SDA_in), + .sync(SDA_sync), + .clock(clock) + ); + gen_output OUT( + .send_ack(send_ack), + .serial_out(data_out), + .out_en(1'b0), + .SDA_out(SDA_out) + ); + count_8 COUNT( + .clock(SCL_sync), + .done(counted_8), + .clear(clear_counter), + .count(count) + ); + start_detect START( + .start(start), + .SCL(SCL_sync), + .SDA(SDA_sync), + .clear_start(clear_start | reset) + ); + stop_detect STOP( + .stop(stop), + .SCL(SCL_sync), + .SDA(SDA_sync), + .clear_stop(clear_stop | reset) + ); + data_input IN_REG( + .SCL(SCL_sync), + .SDA(SDA_sync), + .enable(in_enable), + .data_in(data_in), + .reset(reset) + ); + check_addr ADDR( + .data_in(data_in[7:1]), + .addr_valid(addr_valid) + ); + reg_sel REG( + .reset(reset), + .clock(SCL_sync), + .sel_out(reg_sel_latched), + .sel_in(data_in[2:0]), + .en(reg_sel_en), + .inc(reg_sel_inc) + ); + memory MEM( + .we(we), + .clock(SCL_sync), + .reset(reset), + .sel(reg_sel_latched), + .count(count[2:0]), + .data_in(data_in[7:0]), + .data_out(data_out) + ); + FSM M( + .clear_stop(clear_stop), + .clear_start(clear_start), + .clear_counter(clear_counter), + .clear_mem(clear_mem), + .SCL(SCL_sync), + .SDA(SDA_sync), + .clock(clock), + .start(start), + .stop(stop), + .reset(reset), + .counted_8(counted_8), + .addr_valid(addr_valid), + .data_in(data_in), + .in_enable(in_enable), + .send_ack(send_ack), + .reg_sel_en(reg_sel_en), + .reg_sel_inc(reg_sel_inc), + .we(we) + ); +endmodule +module FSM ( + clear_stop, + clear_start, + clear_counter, + clear_mem, + in_enable, + send_ack, + reg_sel_en, + reg_sel_inc, + we, + SCL, + SDA, + clock, + start, + stop, + reset, + counted_8, + addr_valid, + data_in +); + output reg clear_stop; + output reg clear_start; + output reg clear_counter; + output reg clear_mem; + output reg in_enable; + output reg send_ack; + output reg reg_sel_en; + output reg reg_sel_inc; + output reg we; + input wire SCL; + input wire SDA; + input wire clock; + input wire start; + input wire stop; + input wire reset; + input wire counted_8; + input wire addr_valid; + input wire [8:0] data_in; + reg [3:0] currState; + reg [3:0] nextState; + wire read_write; + assign read_write = data_in[8]; + always @(*) + case (currState) + 4'd0: nextState = 4'd1; + 4'd1: nextState = 4'd2; + 4'd2: nextState = (start ? 4'd3 : 4'd2); + 4'd3: + if (counted_8) + nextState = (addr_valid ? 4'd4 : 4'd1); + else + nextState = 4'd3; + 4'd4: nextState = 4'd5; + 4'd5: nextState = (counted_8 ? 4'd6 : 4'd5); + 4'd6: nextState = (read_write ? 4'd8 : 4'd7); + 4'd7: nextState = (counted_8 ? 4'd9 : 4'd7); + 4'd9: nextState = 4'd7; + default: nextState = 4'd1; + endcase + always @(*) begin + clear_stop = 1'b0; + clear_start = 1'b0; + clear_counter = 1'b0; + clear_mem = 1'b0; + in_enable = 1'b0; + send_ack = 1'b0; + reg_sel_en = 1'b0; + reg_sel_inc = 1'b0; + we = 1'b0; + case (currState) + 4'd0: clear_mem = 1'b1; + 4'd1: {clear_stop, clear_start} = 2'b11; + 4'd2: clear_counter = 1'b1; + 4'd3: {clear_start, in_enable} = 2'b11; + 4'd4: {send_ack, clear_counter} = 2'b11; + 4'd5: in_enable = 1'b1; + 4'd6: {send_ack, clear_counter, reg_sel_en} = 3'b111; + 4'd7: in_enable = 1'b1; + 4'd9: {send_ack, clear_counter, reg_sel_inc, we} = 4'b1111; + default: clear_mem = 1'b1; + endcase + end + reg prev_SCL; + always @(posedge clock) begin + if (reset) begin + currState <= 4'd0; + prev_SCL <= 1'b0; + end + else if (stop) + currState <= 4'd1; + else if ((currState == 4'd0) || (currState == 4'd1)) + currState <= nextState; + else if ((SCL == 1'b0) && (prev_SCL == 1'b1)) + currState <= nextState; + prev_SCL <= SCL; + end +endmodule +`default_nettype none +module Synchronizer ( + async, + clock, + sync +); + input wire async; + input wire clock; + output wire sync; + wire temp; + DFlipFlop m1( + .D(async), + .clock(clock), + .Q(temp) + ); + DFlipFlop m2( + .D(temp), + .clock(clock), + .Q(sync) + ); +endmodule +module DFlipFlop ( + D, + clock, + Q +); + input wire D; + input wire clock; + output reg Q; + always @(posedge clock) Q <= D; +endmodule +module start_detect ( + SCL, + SDA, + clear_start, + start +); + input wire SCL; + input wire SDA; + input wire clear_start; + output reg start; + always @(negedge SDA or posedge clear_start) + if (clear_start == 1'b1) + start = 1'b0; + else if (SCL == 1'b1) + start = 1'b1; +endmodule +module stop_detect ( + SCL, + SDA, + clear_stop, + stop +); + input wire SCL; + input wire SDA; + input wire clear_stop; + output reg stop; + always @(posedge SDA or posedge clear_stop) + if (clear_stop == 1'b1) + stop = 1'b0; + else if (SCL == 1'b1) + stop = 1'b1; +endmodule +module data_input ( + SCL, + SDA, + enable, + reset, + data_in +); + input wire SCL; + input wire SDA; + input wire enable; + input wire reset; + output wire [8:0] data_in; + ShiftRegister_SIPO #(.WIDTH(9)) SHIFT( + .serial(SDA), + .clock(SCL), + .en(enable), + .Q(data_in), + .reset(reset) + ); +endmodule +module ShiftRegister_SIPO ( + serial, + en, + clock, + reset, + Q +); + parameter WIDTH = 8; + input wire serial; + input wire en; + input wire clock; + input wire reset; + output reg [WIDTH - 1:0] Q; + always @(posedge clock or posedge reset) + if (reset) + Q <= {WIDTH - 1 {1'b0}}; + else if (en) + Q <= {Q[WIDTH - 2:0], serial}; +endmodule +module count_8 ( + clear, + clock, + done, + count +); + input wire clear; + input wire clock; + output wire done; + output reg [3:0] count; + assign done = count == 4'b1000; + always @(posedge clock or posedge clear) + if (clear == 1'b1) + count <= 4'b0000; + else if (count < 4'b1000) + count <= count + 4'b0001; +endmodule +module check_addr ( + data_in, + addr_valid +); + input wire [6:0] data_in; + output wire addr_valid; + assign addr_valid = data_in == 7'h20; +endmodule +module reg_sel ( + sel_in, + inc, + en, + clock, + reset, + sel_out +); + input wire [2:0] sel_in; + input wire inc; + input wire en; + input wire clock; + input wire reset; + output reg [2:0] sel_out; + always @(negedge clock or posedge reset) + if (reset) + sel_out <= 3'b000; + else if (en) + sel_out <= sel_in; + else if (inc) + sel_out = sel_out + 3'd1; +endmodule +module memory ( + we, + clock, + reset, + sel, + count, + data_in, + data_out +); + input wire we; + input wire clock; + input wire reset; + input wire [2:0] sel; + input wire [2:0] count; + input wire [7:0] data_in; + output wire data_out; + reg [2:0] index; + reg [7:0] r0; + reg [7:0] r1; + reg [7:0] r2; + reg [7:0] r3; + reg [7:0] r4; + reg [7:0] r5; + reg [7:0] r6; + reg [7:0] r7; + reg [7:0] data_out_8; + assign data_out = data_out_8[index]; + always @(*) + case (sel) + 3'd0: data_out_8 = r0; + 3'd1: data_out_8 = r1; + 3'd2: data_out_8 = r2; + 3'd3: data_out_8 = r3; + 3'd4: data_out_8 = r4; + 3'd5: data_out_8 = r5; + 3'd6: data_out_8 = r6; + 3'd7: data_out_8 = r7; + default: data_out_8 = 8'b00000000; + endcase + always @(negedge clock or posedge reset) + if (reset) + {r0, r1, r2, r3, r4, r5, r6, r7} <= 'b0; + else if (we) begin + case (sel) + 3'd0: r0 <= data_in; + 3'd1: r1 <= data_in; + 3'd2: r2 <= data_in; + 3'd3: r3 <= data_in; + 3'd4: r4 <= data_in; + 3'd5: r5 <= data_in; + 3'd6: r6 <= data_in; + 3'd7: r7 <= data_in; + endcase + index <= count; + end +endmodule +module gen_output ( + send_ack, + serial_out, + out_en, + SDA_out +); + input wire send_ack; + input wire serial_out; + input wire out_en; + output reg SDA_out; + always @(*) + if (send_ack) + SDA_out = 1'b0; + else if (out_en && ~serial_out) + SDA_out = 1'b0; + else + SDA_out = 1'b1; +endmodule diff --git a/designs/d12_oball_i2c/src/picocode.py b/designs/d12_oball_i2c/src/picocode.py new file mode 100644 index 0000000..2b152c7 --- /dev/null +++ b/designs/d12_oball_i2c/src/picocode.py @@ -0,0 +1,149 @@ +# load standard Python modules +import time + +# load the CircuitPython hardware definition module for pin definitions +import board +import busio + +# input output packages +import digitalio + +# address constants +BTN_ADDR = 0x6f +LCD_ADDR = 0x72 +CHIP_ADDR = 0x20 + +led = digitalio.DigitalInOut(board.LED) +led.direction = digitalio.Direction.OUTPUT + +i2c = busio.I2C(scl=board.GP5, sda=board.GP4, frequency=100000) +uart = busio.UART(tx=board.GP12, rx=board.GP13, baudrate=19200, receiver_buffer_size=1, timeout=.01) + +def checkDevices(): + while not i2c.try_lock(): + time.sleep(0.1) + l = i2c.scan() + i2c.unlock() + return l + +def writeBtnLED(brightness): + while not i2c.try_lock(): + time.sleep(0.1) + data_write = bytearray([0x19, brightness]) + i2c.writeto(BTN_ADDR, data_write) + i2c.unlock() + +def readBtnStatus(): + while not i2c.try_lock(): + time.sleep(0.1) + + data_write = bytearray([0x03]) + data_read = bytearray(1) + + i2c.writeto_then_readfrom(BTN_ADDR, data_write, data_read) + + i2c.unlock() + return bool(data_read[0] & 0x04) + +def writeLCD(text): + while not i2c.try_lock(): + time.sleep(0.1) + i2c.writeto(LCD_ADDR, text) + i2c.unlock() + +def clearLCD(): + while not i2c.try_lock(): + time.sleep(0.1) + data_write = bytearray([0x7c, 0x2d]) + i2c.writeto(LCD_ADDR, data_write) + i2c.unlock() + +def setBackLight(r, g, b): + while not i2c.try_lock(): + time.sleep(0.1) + data_write = bytearray([0x7c, 0x2b, r, g, b]) + i2c.writeto(LCD_ADDR, data_write) + i2c.unlock() + + +def writeReg(reg, data): + while not i2c.try_lock(): + time.sleep(0.1) + data_write = bytearray([reg] + data) + try: + i2c.writeto(CHIP_ADDR, data_write) + except: + print("Write failed") + i2c.unlock() + +def readReg(reg, num): + while not i2c.try_lock(): + time.sleep(0.1) + data = bytearray(num) + try: + i2c.writeto_then_readfrom(CHIP_ADDR, bytearray([reg]), data) + except: + print("Read failed") + i2c.unlock() + return list(data) + +def drivePWM1(high, period): + hLSB = high % (1<<8) + hMSB = (high - hLSB)>>8 + pLSB = period % (1<<8) + pMSB = (period - pLSB)>>8 + writeReg(0x02, [hLSB, hMSB]) + writeReg(0x04, [pLSB, pMSB]) + writeReg(0x06, [0x2F]) + +def drivePWM2(high, period): + hLSB = high % (1<<8) + hMSB = (high - hLSB)>>8 + pLSB = period % (1<<8) + pMSB = (period - pLSB)>>8 + writeReg(0x07, [hLSB, hMSB]) + writeReg(0x09, [pLSB, pMSB]) + writeReg(0x0b, [0x01]) + +print("Begining script") +d = list(range(0, 24)) +writeReg(0, d) +count = 0 +while True: + + #print(checkDevices()) + + if readBtnStatus(): + count += 1 + else: + count -= 1 + if count > 255: + count = 255 + elif count < 0: + count = 0 + + clearLCD() + writeLCD(f"{count}") + writeReg(0x01, [count]) + time.sleep(.01) + writeBtnLED(5*readBtnStatus()) + drivePWM1((count)<<4, 255<<4) + drivePWM2(count, 255) + time.sleep(.01) + + print(readReg(0x0, 24)) + + color_t = readReg(0x0, 1)[0] + r_t = int(((color_t & 0b00110000) << 2) * 1.3) + g_t = int(((color_t & 0b00001100) << 4) * 1.3) + b_t = int(((color_t & 0b00000011) << 6) * 1.3) + writeReg(0x10, [r_t, g_t, b_t]) + color = readReg(0x10, 3) + setBackLight(color[0], color[1], color[2]) + x = uart.read(1) + if x == None: x = bytearray(1) + uart.reset_input_buffer() + x = int.from_bytes(x, "little") + print(hex(x)) + time.sleep(.01) + diff --git a/designs/d12_oball_i2c/src/pin_order.cfg b/designs/d12_oball_i2c/src/pin_order.cfg new file mode 100644 index 0000000..0b85c63 --- /dev/null +++ b/designs/d12_oball_i2c/src/pin_order.cfg @@ -0,0 +1,9 @@ +#N + +#S + +#E + +#W +io_in.* +io_out.* diff --git a/designs/d12_oball_i2c/src/pll_veri.sv b/designs/d12_oball_i2c/src/pll_veri.sv new file mode 100644 index 0000000..7b1ce33 --- /dev/null +++ b/designs/d12_oball_i2c/src/pll_veri.sv @@ -0,0 +1,33 @@ +/** + * PLL configuration + * + * This Verilog module was generated automatically + * using the icepll tool from the IceStorm project. + * Use at your own risk. + * + * Given input frequency: 100.000 MHz + * Requested output frequency: 16.000 MHz + * Achieved output frequency: 16.016 MHz + */ + +module pll( + input clock_in, + output clock_out, + output locked + ); + +SB_PLL40_CORE #( + .FEEDBACK_PATH("SIMPLE"), + .DIVR(4'b0011), // DIVR = 3 + .DIVF(7'b0101000), // DIVF = 40 + .DIVQ(3'b110), // DIVQ = 6 + .FILTER_RANGE(3'b010) // FILTER_RANGE = 2 + ) uut ( + .LOCK(locked), + .RESETB(1'b1), + .BYPASS(1'b0), + .REFERENCECLK(clock_in), + .PLLOUTCORE(clock_out) + ); + +endmodule diff --git a/designs/d12_oball_i2c/src/testbench.sv b/designs/d12_oball_i2c/src/testbench.sv new file mode 100644 index 0000000..a098d5b --- /dev/null +++ b/designs/d12_oball_i2c/src/testbench.sv @@ -0,0 +1,142 @@ +/* +module I2C_test; + logic SCL, SDA, clock, reset, SDA_out; + logic [7:0] data_in; + + I2C m1 (.SCL_in(SCL), .SDA_in(SDA), .clock, .SDA_out, .reset); + + task send_byte (input logic [7:0] data); + for (int i = 7; i >= 0; i--) begin + SDA <= data[i]; + #5 + SCL <= 1'b1; + #8 + SCL <= 1'b0; + #5; + end + SDA = 1'b1; + $display("\tSent byte: %h", data); + #5; + endtask: send_byte + + task receive_byte (); + SDA <= 1'b1; + for (int i = 7; i >= 0; i--) begin + #5 + SCL <= 1'b1; + data_in[i] <= SDA_out; + #8 + SCL <= 1'b0; + #5; + end + $display("\tReceived byte: %h", data_in); + #5; + endtask: receive_byte + + task send_start (); + SDA <= 1'b1; + #4; + SCL <= 1'b1; + #6; + SDA <= 1'b0; + #6 + SCL <= 1'b0; + $display("Start sent"); + #5; + endtask: send_start + + task send_stop (); + SDA <= 1'b0; + #4; + SCL <= 1'b1; + #4; + SDA <= 1'b1; + $display("Stop sent"); + #5; + endtask: send_stop + + task get_ack (); + SCL <= 1'b1; + if (SDA_out == 1'b1) $display("\t\tSlave sent NACK"); + else $display("\t\tSlave sent ACK"); + #8; + SCL <= 1'b0; + #5; + endtask: get_ack + + task send_ack (); + SDA <= 1'b0; + #4 + SCL <= 1'b1; + #8; + SCL <= 1'b0; + #4 + SDA <= 1'b1; + $display("\t\tMaster sent ACK"); + #5; + endtask: send_ack + + task send_nack (); + SDA <= 1'b1; + #4 + SCL <= 1'b1; + #8; + SCL <= 1'b0; + #4 + SDA <= 1'b0; + $display("\t\tMaster sent NACK"); + #5; + endtask: send_nack + + initial begin + clock = 0; + forever #1 clock = ~clock; + end + + + initial begin + //$monitor ($time,, "SCL=%b, SDA=%b, SCL_sync=%b, data_in=%b", SCL, SDA, m1.SCL_sync, m1.M.data_in); + reset = 1; + SDA = 1; + SCL = 1; + @(posedge clock); + #4 + @(posedge clock); + reset = 0; + @(posedge clock); + + + send_start(); + send_byte({7'h20, 1'b0}); + get_ack(); + send_byte(8'h07); //select register + get_ack(); + send_byte(8'h42); //send data + get_ack(); + send_byte(8'h85); //send data + get_ack(); + send_stop(); + #20 + + send_start(); + send_byte({7'h20, 1'b0}); + get_ack(); + send_byte(8'h07); //select register + get_ack(); + send_start(); + send_byte({7'h20, 1'b1}); + get_ack(); + receive_byte(); //receive data + send_ack(); + receive_byte(); //receive data + send_ack(); + receive_byte(); //receive data + send_nack(); + send_stop(); + #40 + + $finish; + end + +endmodule: I2C_test +*/ \ No newline at end of file diff --git a/designs/d12_oball_i2c/src/toolchain.sh b/designs/d12_oball_i2c/src/toolchain.sh new file mode 100644 index 0000000..101293d --- /dev/null +++ b/designs/d12_oball_i2c/src/toolchain.sh @@ -0,0 +1,8 @@ +#!/bin/sh +#./toolchain +files='chip.sv top.sv datapath.sv IO.sv FSM.sv library.sv I2C.sv' +set -e +yosys -p "read_verilog -sv $files; synth_ice40 -json build/synthesis.json -top chipInterface; stat" +nextpnr-ice40 --hx8k --json build/synthesis.json --asc build/pnr.asc --package cb132 --pcf constraints.pcf --freq 90 --pre-place constrain.py +icepack build/pnr.asc build/bitstream.bit +yosys -p "read_verilog -sv $files; synth -top my_chip; stat" \ No newline at end of file diff --git a/designs/d12_oball_i2c/src/top.sv b/designs/d12_oball_i2c/src/top.sv new file mode 100644 index 0000000..872e4ac --- /dev/null +++ b/designs/d12_oball_i2c/src/top.sv @@ -0,0 +1,40 @@ +`default_nettype none + +//Top level module for interfacing with Alchitry Cu +module chipInterface ( + input logic clk100, // 100MHz clock + input logic reset_n, // Active-low reset + input logic SCL_in, SDA_in, i2c_reset, + input logic [1:0] ADDR, + input logic [7:0] parallel_in, + output logic [1:0] PWM, + output logic [7:0] led, + output logic SDA_out, UART +); + +logic [31:0] counter; +logic clock; +logic [11:0] io_in, io_out; + +always_ff @(posedge clk100) + if (~reset_n) begin + counter <= '0; + clock <= 1'b0; + end + else begin + counter <= counter + 1; + if (counter == 50) begin + clock <= ~clock; + counter <= '0; + end + end + +assign io_in = {parallel_in, ADDR, SDA_in, SCL_in}; +assign led = io_out[11:4]; +assign PWM = io_out[3:2]; +assign SDA_out = io_out[0]; +assign UART = io_out[1]; + +my_chip CHIP (.io_in, .io_out, .clock, .reset(i2c_reset)); + +endmodule: chipInterface \ No newline at end of file diff --git a/designs/d12_oball_i2c/src/toplevel_chip.v b/designs/d12_oball_i2c/src/toplevel_chip.v new file mode 100644 index 0000000..a82b427 --- /dev/null +++ b/designs/d12_oball_i2c/src/toplevel_chip.v @@ -0,0 +1,18 @@ +`default_nettype none + +// DO NOT EDIT THIS FILE +module toplevel_chip ( + input [13:0] io_in, + output [13:0] io_out +); + + my_chip mchip ( + .io_in(io_in[11:0]), + .io_out(io_out[11:0]), + .clock(io_in[12]), + .reset(io_in[13]) + ); + + assign io_out[13:12] = 2'b00; + +endmodule diff --git a/designs/d13_jrduvall_s444/.lastupdated b/designs/d13_jrduvall_s444/.lastupdated new file mode 100644 index 0000000..4d7b8c3 --- /dev/null +++ b/designs/d13_jrduvall_s444/.lastupdated @@ -0,0 +1 @@ +2023-05-14 diff --git a/designs/d13_jrduvall_s444/LICENSE b/designs/d13_jrduvall_s444/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/designs/d13_jrduvall_s444/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/designs/d13_jrduvall_s444/README.md b/designs/d13_jrduvall_s444/README.md new file mode 100644 index 0000000..dfa8a78 --- /dev/null +++ b/designs/d13_jrduvall_s444/README.md @@ -0,0 +1,24 @@ +# FPGA, "from scratch" + +Jack Duvall, 18-224 Spring 2023 + +Synthesizing FPGAs is not a new concept [citation needed]. However, +synthesizing an FPGA this laughably underpowered, is! It is a stretch to even +call this an FPGA, so instead I should probably be calling it a single S444 +logic cell, capable of simulating a LUT5 and storing 2 bits. [insert: it ain't +much but it's honest work meme]. + +## How It Works + +I took this: + +![A diagram of an S444 logic cell](https://assets.chaos.social/media_attachments/files/110/026/931/020/246/360/original/2f1ade7ba8151455.png) + +and turned it into SystemVerilog. and hooked it up to the tapeout's debug +interface. that is it :) + +## Testing + +The testing harness is run with CocoTB, so have that installed or something, +and then run `make` and wait like 15 seconds for the test to actually start +since CocoTB is a great testing library. diff --git a/designs/d13_jrduvall_s444/info.yaml b/designs/d13_jrduvall_s444/info.yaml new file mode 100644 index 0000000..50f998e --- /dev/null +++ b/designs/d13_jrduvall_s444/info.yaml @@ -0,0 +1,9 @@ +--- +project: + source_files: + - toplevel_chip.v + - chip.sv + - s444.sv + - library.sv + top_module: "toplevel_chip" + diff --git a/designs/d13_jrduvall_s444/src/chip.sv b/designs/d13_jrduvall_s444/src/chip.sv new file mode 100644 index 0000000..4a0b2f2 --- /dev/null +++ b/designs/d13_jrduvall_s444/src/chip.sv @@ -0,0 +1,33 @@ +`default_nettype none + +module my_chip ( + input logic [11:0] io_in, // Inputs to your chip + output logic [11:0] io_out, // Outputs from your chip + input logic clock, + input logic reset // Important: Reset is ACTIVE-HIGH +); + + S444_Cell s444( + .feed0_out(io_out[0]), + .feed1_out(io_out[1]), + .main_out(io_out[2]), + .dff0_out(io_out[3]), + .dff1_out(io_out[4]), + .sum_out(io_out[8]), + .c_out(io_out[9]), + + .feed0(io_in[3:0]), + .feed1({io_in[4], io_in[2:0]}), + .main(io_in[8:5]), + .c_in(io_in[9]), + + .shift_out(io_out[10]), + .shift_in(io_in[10]), + .clk(clock), + .en(io_in[11]), + .reset(reset)); + + assign io_out[7:5] = 3'b000; + assign io_out[11] = 1'b0; + +endmodule diff --git a/designs/d13_jrduvall_s444/src/config.tcl b/designs/d13_jrduvall_s444/src/config.tcl new file mode 100644 index 0000000..aa589e4 --- /dev/null +++ b/designs/d13_jrduvall_s444/src/config.tcl @@ -0,0 +1,68 @@ +# PLEASE DO NOT EDIT THIS FILE! +# IT WILL MAKE YOUR CHIP UNMANUFACTURABLE +# The only line you may edit is FP_CORE_UTIL +# (may benefit from reducing it slightly) + +# User config +set script_dir [file dirname [file normalize [info script]]] + +# read some user config that is written by the setup.py program. +# - the name of the module is defined +# - the list of source files +source $::env(DESIGN_DIR)/user_config.tcl + +# save some time +set ::env(RUN_KLAYOUT_XOR) 0 +set ::env(RUN_KLAYOUT_DRC) 0 + +# don't put clock buffers on the outputs +set ::env(PL_RESIZER_BUFFER_OUTPUT_PORTS) 0 + +# allow use of specific sky130 cells +set ::env(SYNTH_READ_BLACKBOX_LIB) 1 + +# put all the pins on the left +set ::env(FP_PIN_ORDER_CFG) $::env(DESIGN_DIR)/pin_order.cfg + +# reduce wasted space +set ::env(TOP_MARGIN_MULT) 2 +set ::env(BOTTOM_MARGIN_MULT) 2 + +# absolute die size +set ::env(FP_SIZING) absolute +set ::env(DIE_AREA) "0 0 280 280" + +## THIS IS THE ONLY LINE YOU CAN EDIT +set ::env(FP_CORE_UTIL) 45 + +## set ::env(PL_BASIC_PLACEMENT) {1} + +set ::env(FP_IO_HLENGTH) 2 +set ::env(FP_IO_VLENGTH) 2 + +# use alternative efabless decap cells to solve LI density issue +set ::env(DECAP_CELL) "\ + sky130_fd_sc_hd__decap_3 \ + sky130_fd_sc_hd__decap_4 \ + sky130_fd_sc_hd__decap_6 \ + sky130_fd_sc_hd__decap_8 \ + sky130_ef_sc_hd__decap_12" + +# clock +set ::env(CLOCK_TREE_SYNTH) 1 + +# period is in ns, so 500ns == 2 MHz +set ::env(CLOCK_PERIOD) "500" +set ::env(CLOCK_PORT) {io_in[12]} + +# hold/slack margin +# set ::env(PL_RESIZER_HOLD_SLACK_MARGIN) 0.8 +# set ::env(GLB_RESIZER_HOLD_SLACK_MARGIN) 0.8 + +# don't use power rings or met5 +set ::env(DESIGN_IS_CORE) 0 +set ::env(RT_MAX_LAYER) {met4} + +# connect to first digital rails +set ::env(VDD_NETS) [list {vccd1}] +set ::env(GND_NETS) [list {vssd1}] diff --git a/designs/d13_jrduvall_s444/src/library.sv b/designs/d13_jrduvall_s444/src/library.sv new file mode 100644 index 0000000..9eccfe9 --- /dev/null +++ b/designs/d13_jrduvall_s444/src/library.sv @@ -0,0 +1,57 @@ +`default_nettype none + +module Lut +#(parameter WIDTH = 3) +( + output logic O, + input logic [WIDTH-1:0] I, + input logic [WIDTH*WIDTH-1:0] D); + + assign O = D[I]; + +endmodule: Lut + +module Latch +#(parameter WIDTH = 8) +( + output logic [WIDTH-1:0] Q, + input logic [WIDTH-1:0] D, + input logic load, en, clear, clock +); + + always_ff @(posedge clock) + if (en) + if (clear) + Q <= 0; + else if (load) + Q <= D; + else + Q <= Q; + +endmodule: Latch + +module ShiftLatch +#(parameter WIDTH = 8) +( + output logic [WIDTH-1:0] Q, + output logic O, + input logic I, + input logic left, shift, + input logic reset, en, clock +); + + logic [WIDTH-1:0] shiftedLeft, shiftedRight, shiftResult; + logic lowBit, highBit; + + assign shiftedLeft = (Q << 1) | I; + assign shiftedRight = (Q >> 1) | ({I, {WIDTH-1{1'b0}}}); + assign lowBit = Q[0]; + assign highBit = Q[WIDTH-1]; + + assign shiftResult = (left) ? shiftedLeft : shiftedRight; + assign O = (left) ? highBit : lowBit; + + Latch #(WIDTH) myLatch(.Q, .D(shiftResult), + .load(shift), .en, .clear(reset), .clock); + +endmodule: ShiftLatch diff --git a/designs/d13_jrduvall_s444/src/pin_order.cfg b/designs/d13_jrduvall_s444/src/pin_order.cfg new file mode 100644 index 0000000..0b85c63 --- /dev/null +++ b/designs/d13_jrduvall_s444/src/pin_order.cfg @@ -0,0 +1,9 @@ +#N + +#S + +#E + +#W +io_in.* +io_out.* diff --git a/designs/d13_jrduvall_s444/src/s444.sv b/designs/d13_jrduvall_s444/src/s444.sv new file mode 100644 index 0000000..78ab471 --- /dev/null +++ b/designs/d13_jrduvall_s444/src/s444.sv @@ -0,0 +1,179 @@ +`default_nettype none + +// Source: +// https://assets.chaos.social/media_attachments/files/110/026/931/020/246/360/original/2f1ade7ba8151455.png + +module S444_Logic ( + output logic lut0, + output logic lut1, + output logic lut2, + input logic [3:0] feed0, + input logic [3:0] feed1, + input logic [3:0] main, + + output logic shift_out, + input logic shift_in, + input logic clk, + input logic en, + input logic reset); + + logic m0_sel, m1_sel, m2_sel; + logic [15:0] l0_dat, l1_dat, l2_dat; + logic shift_m0, shift_m1, shift_m2, shift_l0, shift_l1, shift_l2; + logic [3:0] feed2; + logic feed1_3_real; + + ShiftLatch #(1) m0_reg(.Q(m0_sel), + .O(shift_m0), .I(shift_in), + .left(1'b1), .reset, .shift(en), + .en(1'b1), .clock(clk)), + m1_reg(.Q(m1_sel), + .O(shift_m1), .I(shift_m0), + .left(1'b1), .reset, .shift(en), + .en(1'b1), .clock(clk)), + m2_reg(.Q(m2_sel), + .O(shift_m2), .I(shift_m1), + .left(1'b1), .reset, .shift(en), + .en(1'b1), .clock(clk)); + + assign feed2[3] = (m0_sel) ? main[3] : lut0; + assign feed2[2] = (m1_sel) ? main[2] : lut1; + assign feed1_3_real = (m2_sel) ? feed0[3] : feed1[3]; + + ShiftLatch #(16) l0_reg(.Q(l0_dat), + .O(shift_l0), .I(shift_m2), + .left(1'b1), .reset, .shift(en), + .en(1'b1), .clock(clk)), + l1_reg(.Q(l1_dat), + .O(shift_l1), .I(shift_l0), + .left(1'b1), .reset, .shift(en), + .en(1'b1), .clock(clk)), + l2_reg(.Q(l2_dat), + .O(shift_l2), .I(shift_l1), + .left(1'b1), .reset, .shift(en), + .en(1'b1), .clock(clk)); + + assign feed2[1:0] = main[1:0]; + assign shift_out = shift_l2; + + Lut #(4) l0(.O(lut0), .I(feed0), .D(l0_dat)), + l1(.O(lut1), .I({feed1_3_real, feed1[2:0]}), .D(l1_dat)), + l2(.O(lut2), .I(feed2), .D(l2_dat)); + +endmodule: S444_Logic + +module LUT5_Mux ( + output logic feed0_out, + input logic lut0, + input logic lut1, + input logic feed1_3, + + output logic shift_out, + input logic shift_in, + input logic clk, + input logic en, + input logic reset); + + logic feed0_sel, lut5_sel; + + ShiftLatch #(1) lut5_reg(.Q(lut5_sel), + .O(shift_out), .I(shift_in), + .left(1'b1), .reset, .shift(en), + .en(1'b1), .clock(clk)); + + assign feed0_sel = (lut5_sel) ? feed1_3 : 1'b0; + assign feed0_out = (feed0_sel) ? lut1 : lut0; + +endmodule: LUT5_Mux + +module Carry_Logic ( + output logic sum_out, + output logic c_out, + input logic prop, + input logic gen, + input logic c_in); + + assign c_out = (prop) ? c_in : gen; + + assign sum_out = c_in ^ prop; + +endmodule: Carry_Logic + +module D_Flip_Flops ( + output logic dff0_out, + output logic dff1_out, + input logic feed0_out, + input logic feed1_out, + input logic main_out, + input logic feed0_0, + input logic feed1_0, + input logic sum_out, + + output logic shift_out, + input logic shift_in, + input logic clk, + input logic en, + input logic reset); + + logic [1:0] dff0_sel, dff1_sel; + logic dff0, dff1; + + ShiftLatch #(4) dff_reg(.Q({dff1_sel, dff0_sel}), + .O(shift_out), .I(shift_in), + .left(1'b1), .reset, .shift(en), + .en(1'b1), .clock(clk)); + + Lut #(2) dff0_mux(.O(dff0), + .D({sum_out, feed0_0, main_out, feed0_out}), + .I(dff0_sel)), + dff1_mux(.O(dff1), + .D({sum_out, feed1_0, main_out, feed1_out}), + .I(dff1_sel)); + + Latch #(2) dff(.Q({dff1_out, dff0_out}), .D({dff1, dff0}), + .load(1'b1), .en(1'b1), .clear(reset), .clock(clk)); + +endmodule: D_Flip_Flops + +module S444_Cell ( + output logic feed0_out, + output logic feed1_out, + output logic main_out, + output logic dff0_out, + output logic dff1_out, + output logic sum_out, + output logic c_out, + + input logic [3:0] feed0, + input logic [3:0] feed1, + input logic [3:0] main, + input logic c_in, + + output logic shift_out, + input logic shift_in, + input logic clk, + input logic en, + input logic reset); + + logic lut0, lut1, lut2; + logic shift0, shift1; + + S444_Logic s444_logic(.lut0, .lut1, .lut2, + .feed0, .feed1, .main, + .shift_out(shift0), .shift_in, .clk, .en, .reset); + + LUT5_Mux lut5_mux(.feed0_out, .lut0, .lut1, .feed1_3(feed1[3]), + .shift_out(shift1), .shift_in(shift0), .clk, .en, .reset); + + Carry_Logic carry_logic(.sum_out, .c_out, .prop(lut1), .gen(lut2), .c_in); + + D_Flip_Flops d_flip_flops(.dff0_out, .dff1_out, + .feed0_out, .feed1_out, + .feed0_0(feed0[0]), .feed1_0(feed1[0]), + .sum_out, + .shift_out, .shift_in(shift1), .clk, .en, .reset); + + assign feed1_out = lut1; + assign main_out = lut2; + +endmodule: S444_Cell diff --git a/designs/d13_jrduvall_s444/src/toplevel_chip.v b/designs/d13_jrduvall_s444/src/toplevel_chip.v new file mode 100644 index 0000000..a82b427 --- /dev/null +++ b/designs/d13_jrduvall_s444/src/toplevel_chip.v @@ -0,0 +1,18 @@ +`default_nettype none + +// DO NOT EDIT THIS FILE +module toplevel_chip ( + input [13:0] io_in, + output [13:0] io_out +); + + my_chip mchip ( + .io_in(io_in[11:0]), + .io_out(io_out[11:0]), + .clock(io_in[12]), + .reset(io_in[13]) + ); + + assign io_out[13:12] = 2'b00; + +endmodule diff --git a/designs/d13_jrduvall_s444/verif/Makefile b/designs/d13_jrduvall_s444/verif/Makefile new file mode 100644 index 0000000..ebb1a43 --- /dev/null +++ b/designs/d13_jrduvall_s444/verif/Makefile @@ -0,0 +1,17 @@ +# Makefile + +# defaults +SIM ?= icarus +TOPLEVEL_LANG ?= verilog + +VERILOG_SOURCES += $(PWD)/../src/s444.sv $(PWD)/../src/library.sv +# use VHDL_SOURCES for VHDL files + +# TOPLEVEL is the name of the toplevel module in your Verilog or VHDL file +TOPLEVEL = S444_Cell + +# MODULE is the basename of the Python test file +MODULE = test_s444 + +# include cocotb's make rules to take care of the simulator setup +include $(shell cocotb-config --makefiles)/Makefile.sim diff --git a/designs/d13_jrduvall_s444/verif/lut4.py b/designs/d13_jrduvall_s444/verif/lut4.py new file mode 100644 index 0000000..e37d356 --- /dev/null +++ b/designs/d13_jrduvall_s444/verif/lut4.py @@ -0,0 +1,63 @@ +from abc import ABC, abstractmethod +from dataclasses import dataclass +from functools import partial +from typing import Callable + + +class LutBits: + def gen(self) -> list[bool]: + raise NotImplemented + + def __invert__(self) -> 'LutBits': + return Not(self) + + def __and__(self, other) -> 'LutBits': + return And(self, other) + + def __or__(self, other) -> 'LutBits': + return Or(self, other) + + def __xor__(self, other) -> 'LutBits': + return Xor(self, other) + + +@dataclass +class Constant(LutBits): + index: int + lut_width: int + + def gen(self) -> list[bool]: + mask = 1 << self.index + return [(mask & i) != 0 for i in range(1 << self.lut_width)] + + +I_0 = Constant(0, 4) +I_1 = Constant(1, 4) +I_2 = Constant(2, 4) +I_3 = Constant(3, 4) + + +@dataclass +class Not(LutBits): + b: LutBits + + def gen(self) -> list[bool]: + return [not i for i in self.b.gen()] + + +@dataclass +class BinOp(LutBits): + op: Callable[[bool, bool], bool] + left: LutBits + right: LutBits + + def gen(self) -> list[bool]: + return [ + self.op(lb, rb) + for lb, rb in zip(self.left.gen(), self.right.gen()) + ] + + +And = partial(BinOp, lambda a, b: a & b) +Or = partial(BinOp, lambda a, b: a | b) +Xor = partial(BinOp, lambda a, b: a ^ b) diff --git a/designs/d13_jrduvall_s444/verif/test_s444.py b/designs/d13_jrduvall_s444/verif/test_s444.py new file mode 100644 index 0000000..99ebe31 --- /dev/null +++ b/designs/d13_jrduvall_s444/verif/test_s444.py @@ -0,0 +1,405 @@ +#!/usr/bin/env python3 + +from dataclasses import dataclass +from random import randint +from typing import List + +import cocotb +from cocotb.handle import Force +from cocotb.triggers import ReadOnly, ReadWrite, Timer, NextTimeStep + +TEST_S444_BITSTREAM_ITERS = 50 +TEST_S444_LUT4_ITERS = 50 +TEST_S444_LUT5_ITERS = 100 + + +async def tick(dut): + """ + Toggles the `clk` field on `dut` + """ + dut.clk.value = 0 + await Timer(1, units="ns") + dut.clk.value = 1 + await Timer(1, units="ns") + + +async def write_bitstream(dut, bitstream): + """ + Writes a `bitstream` to the `shift_in` field of `dut`. Also verifies that + the bitstream read is of the exact length by reading from `shift_out` + + `bitstream` is a list of 1s and 0s + """ + dut.en.value = 1 + await tick(dut) + await tick(dut) + dut.reset.value = 1 + await tick(dut) + dut.reset.value = 0 + + # Write initial bitstream, asserting that value after reset is 0 + b = list(bitstream) + for bit in b: + dut.shift_in.value = bit + await ReadWrite() + assert dut.shift_out.value == 0 + await tick(dut) + + # Write bitstream again, asserting that the one written initially was good + for index, bit in enumerate(b): + dut.shift_in.value = bit + await ReadWrite() + assert dut.shift_out.value == bit + await tick(dut) + + dut.en.value = 0 + + +@cocotb.test() +async def test_s444_bitstream(dut): + """ + Test that writing random bitstreams succeeds + """ + for _ in range(TEST_S444_BITSTREAM_ITERS): + await write_bitstream( + dut, + [ + randint(0, 1) for _ in range(3 * 1 + 3 * 16 # S444_Logic + + 1 * 1 # LUT5_Mux + + 2 * 2 # D_Flip_Flops + ) + ]) + + +def int_to_bs(x: int, length: int) -> List[bool]: + """ + Converts x to a binary list, big-endian, padded with zeros + """ + mod = 2**length + output = [] + while mod > 1: + mod = mod // 2 + output.append(x & mod != 0) + return output + + +@dataclass +class S444LogicBitstream: + main3: bool + main2: bool + feed0_3: bool + lut0: List[bool] + lut1: List[bool] + lut2: List[bool] + + def to_bs(self) -> List[bool]: + return self.lut2[::-1] + self.lut1[::-1] + self.lut0[::-1] \ + + [self.feed0_3] + [self.main2] + [self.main3] + + +@dataclass +class LUT5MuxBitstream: + feed1_3: bool + + def to_bs(self) -> List[bool]: + return [self.feed1_3] + + +@dataclass +class DFlipFlopsBitstream: + dff0: int + dff1: int + + def to_bs(self) -> List[bool]: + return int_to_bs(self.dff1, 2) + int_to_bs(self.dff0, 2) + + +@dataclass +class S444Bitstream: + s444_logic: S444LogicBitstream + lut5_mux: LUT5MuxBitstream + d_flip_flops: DFlipFlopsBitstream + + def to_bs(self) -> List[bool]: + return self.d_flip_flops.to_bs() \ + + self.lut5_mux.to_bs() \ + + self.s444_logic.to_bs() + + +@cocotb.test() +async def test_s444_lut4_main(dut): + """ + Create a random main LUT4 and test that it was programmed correctly + """ + bs = S444Bitstream( + S444LogicBitstream( + main3=True, + main2=True, + feed0_3=False, + lut0=[0] * 16, + lut1=[0] * 16, + lut2=[0] * 16, + ), + LUT5MuxBitstream(feed1_3=False, ), + DFlipFlopsBitstream( + dff0=1, + dff1=2, + ), + ) + + for _ in range(TEST_S444_LUT4_ITERS): + lut = [randint(0, 1) for _ in range(16)] + bs.s444_logic.lut2 = lut + await write_bitstream(dut, bs.to_bs()) + await tick(dut) + + for i, o in enumerate(lut): + dut.main.value = Force(i) + await ReadOnly() + assert dut.main_out.value == o + await Timer(1, units="ns") + + +@cocotb.test() +async def test_s444_lut4_feed0(dut): + """ + Create a random feed0 LUT4 and test that it was programmed correctly + """ + bs = S444Bitstream( + S444LogicBitstream( + main3=True, + main2=True, + feed0_3=False, + lut0=[0] * 16, + lut1=[0] * 16, + lut2=[0] * 16, + ), + LUT5MuxBitstream(feed1_3=False, ), + DFlipFlopsBitstream( + dff0=1, + dff1=2, + ), + ) + + for _ in range(TEST_S444_LUT4_ITERS): + lut = [randint(0, 1) for _ in range(16)] + bs.s444_logic.lut0 = lut + await write_bitstream(dut, bs.to_bs()) + await tick(dut) + + for i, o in enumerate(lut): + dut.feed0.value = Force(i) + await ReadOnly() + assert dut.feed0_out.value == o + await Timer(1, units="ns") + + +@cocotb.test() +async def test_s444_lut4_feed1(dut): + """ + Create a random feed1 LUT4 and test that it was programmed correctly + """ + bs = S444Bitstream( + S444LogicBitstream( + main3=True, + main2=True, + feed0_3=False, + lut0=[0] * 16, + lut1=[0] * 16, + lut2=[0] * 16, + ), + LUT5MuxBitstream(feed1_3=False, ), + DFlipFlopsBitstream( + dff0=1, + dff1=2, + ), + ) + + for _ in range(TEST_S444_LUT4_ITERS): + lut = [randint(0, 1) for _ in range(16)] + bs.s444_logic.lut1 = lut + await write_bitstream(dut, bs.to_bs()) + await tick(dut) + + for i, o in enumerate(lut): + dut.feed1.value = Force(i) + await ReadOnly() + assert dut.feed1_out.value == o + await Timer(1, units="ns") + + +@cocotb.test() +async def test_s444_lut5(dut): + """ + Creates a LUT5 by combining feed0 and feed1 in the LUT5 mux + """ + bs = S444Bitstream( + S444LogicBitstream( + main3=True, + main2=True, + feed0_3=True, + lut0=[0] * 16, + lut1=[0] * 16, + lut2=[0] * 16, + ), + LUT5MuxBitstream(feed1_3=True, ), + DFlipFlopsBitstream( + dff0=1, + dff1=2, + ), + ) + + for _ in range(TEST_S444_LUT5_ITERS): + lut = [randint(0, 1) for _ in range(32)] + bs.s444_logic.lut0 = lut[0:16] + bs.s444_logic.lut1 = lut[16:32] + await write_bitstream(dut, bs.to_bs()) + await tick(dut) + + for i, o in enumerate(lut): + low4 = i % 16 + upp1 = i // 16 + dut.feed0.value = Force(low4) + # feed1_3 is set to feed0_3 thanks to the configuration, and this + # bit is instead used to switch between the two LUT4s, creating a + # LUT5 + dut.feed1.value = Force((low4 % 8) | (upp1 << 3)) + await ReadOnly() + assert dut.feed0_out.value == o + await Timer(1, units="ns") + + +@cocotb.test() +async def test_s444_2bit_adder(dut): + """ + Creates a 2-bit counter inside the d-flip-flops. + Hooks up {feed0, feed1, main} as the input bits. Bits [0:1] carry the + previous value, bit 2 is the carry input, and main_out is the carry output + """ + + bs = S444Bitstream( + S444LogicBitstream( + main3=True, + main2=True, + feed0_3=True, + lut0=(I_0 ^ I_2).gen(), + lut1=(I_1 ^ (I_0 & I_2)).gen(), + lut2=(I_0 & I_1 & I_2).gen() + ), + LUT5MuxBitstream(feed1_3=False, ), + DFlipFlopsBitstream( + dff0=0, # feed0_out + dff1=0, # feed1_out + ), + ) + + await write_bitstream(dut, bs.to_bs()) + bit2 = (1 << 2) + dut.feed0.value = bit2 + dut.feed1.value = bit2 + dut.main.value = bit2 + await tick(dut) + + def info(w): + w._log.info(f"{w.value}") + + # Do the increment a given number of times + for i in range(1, 10): + low2 = i % 4 + dut.feed0.value = low2 | bit2 + dut.feed1.value = low2 | bit2 + dut.main.value = low2 | bit2 + await ReadOnly() + info(dut.feed0_out) + info(dut.feed1_out) + info(dut.dff0_out) + info(dut.dff1_out) + info(dut.main_out) + assert dut.dff0_out.value == low2 % 2 + assert dut.dff1_out.value == low2 // 2 + assert dut.main_out.value == (low2 == 3) + await Timer(1, units="ns") + await tick(dut) + + # Stop doing the increment, and ensure the state holds + for _ in range(3): + low2 = i % 4 + dut.feed0.value = low2 + dut.feed1.value = low2 + dut.main.value = low2 + await tick(dut) + assert dut.dff0_out.value == low2 % 2 + assert dut.dff1_out.value == low2 // 2 + assert dut.main_out.value == (low2 == 3) + + +# ## s444.py +""" +This needs to be included in the same file since cocotb doesn't like having +multiple python files lol +""" + + +from abc import ABC, abstractmethod +from dataclasses import dataclass +from functools import partial +from typing import Callable, List + + +class LutBits: + def gen(self) -> List[bool]: + raise NotImplemented + + def __invert__(self) -> 'LutBits': + return Not(self) + + def __and__(self, other) -> 'LutBits': + return And(self, other) + + def __or__(self, other) -> 'LutBits': + return Or(self, other) + + def __xor__(self, other) -> 'LutBits': + return Xor(self, other) + + +@dataclass +class Constant(LutBits): + index: int + lut_width: int + + def gen(self) -> List[bool]: + mask = 1 << self.index + return [(mask & i) != 0 for i in range(1 << self.lut_width)] + + +I_0 = Constant(0, 4) +I_1 = Constant(1, 4) +I_2 = Constant(2, 4) +I_3 = Constant(3, 4) + + +@dataclass +class Not(LutBits): + b: LutBits + + def gen(self) -> List[bool]: + return [not i for i in self.b.gen()] + + +@dataclass +class BinOp(LutBits): + op: Callable[[bool, bool], bool] + left: LutBits + right: LutBits + + def gen(self) -> List[bool]: + return [ + self.op(lb, rb) + for lb, rb in zip(self.left.gen(), self.right.gen()) + ] + + +And = partial(BinOp, lambda a, b: a & b) +Or = partial(BinOp, lambda a, b: a | b) +Xor = partial(BinOp, lambda a, b: a ^ b) diff --git a/designs/d14_jessief_trafficlight/.lastupdated b/designs/d14_jessief_trafficlight/.lastupdated new file mode 100644 index 0000000..4d7b8c3 --- /dev/null +++ b/designs/d14_jessief_trafficlight/.lastupdated @@ -0,0 +1 @@ +2023-05-14 diff --git a/designs/d14_jessief_trafficlight/LICENSE b/designs/d14_jessief_trafficlight/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/designs/d14_jessief_trafficlight/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/designs/d14_jessief_trafficlight/README.md b/designs/d14_jessief_trafficlight/README.md new file mode 100644 index 0000000..c4fe1be --- /dev/null +++ b/designs/d14_jessief_trafficlight/README.md @@ -0,0 +1,36 @@ + +# Morewood traffic light +Jessie Fan +18-224/624 Spring 2023 Final Tapeout Project +## Overview +Functions as a traffic light & cross walk light signals +which takes in inputs of which cars are waiting and if +the pedestrian crossing button has been pressed. +## How it Works +FSM-D +Uses an FSM (Moore style) to control the different states +for each light for each car/ped waiting. Also uses +multiple counters (to count the time allotted for cars to go +in each direction) and a register to hold whether the pedestrian +crossing button has been pressed. +![FSM](fsm.png) +## Inputs/Outputs +I plan to implement a 3-way traffic intersection that includes: 1 crosswalk that signals +when pedestrians should walk and when they should wait, 3 traffic lights for each +direction (one of these traffic lights will include a turn signal in addition to the standard +green, yellow and red lights). +Inputs:
+● 1 pedestrian waiting to cross input [ped]
+● 3 car waiting signals for each (straight) direction [car1, car2, car3]
+● 1 car waiting signal for the turning lane [car 4]
+Outputs:
+● 3 LEDS (red, yellow, green) for each direction (9 total) [red1, yellow1, green1, etc.]
+● 1 additional LED for the turn signal (could be any color) [turn]
+● 2 LEDS (orange and white) for whether the pedestrian should cross or not [orange, +white]
+## Design Testing / Bringup +I tested this design by picking plausible inputs (combinations of cars and pedestrians waiting) to +plug into a test bench and visually check if the output (traffic lights) matches what I expected. +## Media +file containing output of test bench is included
+`traffic_light.sim` diff --git a/designs/d14_jessief_trafficlight/fsm.png b/designs/d14_jessief_trafficlight/fsm.png new file mode 100644 index 0000000..e7bf245 Binary files /dev/null and b/designs/d14_jessief_trafficlight/fsm.png differ diff --git a/designs/d14_jessief_trafficlight/info.yaml b/designs/d14_jessief_trafficlight/info.yaml new file mode 100644 index 0000000..41a2011 --- /dev/null +++ b/designs/d14_jessief_trafficlight/info.yaml @@ -0,0 +1,8 @@ +--- +project: + source_files: + - toplevel_chip.v + - chip.sv + - FSMD.sv + top_module: "toplevel_chip" + diff --git a/designs/d14_jessief_trafficlight/src/FSMD.sv b/designs/d14_jessief_trafficlight/src/FSMD.sv new file mode 100644 index 0000000..0cc36b8 --- /dev/null +++ b/designs/d14_jessief_trafficlight/src/FSMD.sv @@ -0,0 +1,218 @@ +`default_nettype none + +module Counter + #(parameter WIDTH = 8) + (input logic [WIDTH - 1:0] D, + input logic clear, load, clock, en, + output logic [WIDTH - 1:0] Q); + + always_ff @(posedge clock) + if(clear) + Q <= 8'b0; + else if(load) + Q <= D; + else if (en) + Q <= Q + 1'b1; + else + Q <= Q; + +endmodule: Counter + +module MagComp + #(parameter WIDTH = 8) + (input logic [WIDTH - 1:0] A, B, + output logic AgtB, AeqB, AltB); + + assign AeqB = (A == B); + assign AgtB = (A > B); + assign AltB = (A < B); + +endmodule: MagComp + +module Register + #(parameter WIDTH = 1) + (input logic button, ped_clr, clock, + output logic ped); + + always_ff @(posedge clock) + if(button) + ped <= 1'b1; + else if (ped_clr) + ped <= 1'b0; + else + ped <= ped; + +endmodule: Register + +module FSM + (input logic clock, reset, + car1, car2, car3, car4, ped, + stop_yellow, stop_ped, stop_five, + output logic red1, yellow1, green1, + red2, yellow2, green2, + red3, yellow3, green3, + turn, orange, white, + yellow_en, + yellow_clr, + stop_en, + stop_clr, + five_en, + five_clr, + ped_clr); + + enum logic [3:0] {INIT, CAR1, CAR2, CAR3_4, PED, + YELLOW1, YELLOW2, YELLOW3, DELAY} state, nextState; + + always_ff @(posedge clock) + if (reset) + state <= INIT; + else + state <= nextState; + + //default if no one waiting at yellow is PED + //next state logic + always_comb begin + unique case (state) + INIT: if (car1) nextState = CAR1; + else if (car2) nextState = CAR2; + else if (car3 | car4) nextState = CAR3_4; + else if (ped) nextState = PED; + else nextState = INIT; + CAR1: nextState = (~car1 | stop_ped) ? YELLOW1 : CAR1; + CAR2: nextState = (~car2 | stop_ped) ? YELLOW2 : CAR2; + CAR3_4: nextState = (~(car3 |car4) | stop_ped) ? YELLOW3 : CAR3_4; + PED: nextState = (stop_ped) ? DELAY : PED; + YELLOW1: if (stop_yellow) begin + if (car2) nextState = CAR2; + else if (car3 | car4) nextState = CAR3_4; + else if (ped) nextState = PED; + else if (car1) nextState = CAR1; + else nextState = PED; + end else nextState = YELLOW1; + YELLOW2: if (stop_yellow) begin + if (car3 | car4) nextState = CAR3_4; + else if (ped) nextState = PED; + else if (car1) nextState = CAR1; + else if (car2) nextState = CAR2; + else nextState = PED; + end else nextState = YELLOW2; + YELLOW3: if (stop_yellow) begin + if (ped) nextState = PED; + else if (car1) nextState = CAR1; + else if (car2) nextState = CAR2; + else if (car3 | car4) nextState = CAR3_4; + else nextState = PED; + end else nextState = YELLOW3; + DELAY: if (stop_five) begin + if (car1) nextState = CAR1; + else if (car2) nextState = CAR2; + else if (car3 | car4) nextState = CAR3_4; + else if (ped) nextState = PED; + else nextState = PED; + end else nextState = DELAY; + endcase + end + + //output logic + always_comb begin + red1 = 1'b0; + yellow1 = 1'b0; + green1 = 1'b0; + red2 = 1'b0; + yellow2 = 1'b0; + green2 = 1'b0; + red3 = 1'b0; + yellow3 = 1'b0; + green3 = 1'b0; + turn = 1'b0; + orange = 1'b0; + white = 1'b0; + yellow_en = 1'b0; + yellow_clr = 1'b0; + stop_en = 1'b0; + stop_clr = 1'b0; + five_en = 1'b0; + five_clr = 1'b0; + ped_clr = 1'b0; + + unique case (state) + INIT: begin + yellow_clr = 1'b1; + stop_clr = 1'b1; + five_clr = 1'b1; + red1 = 1'b1; + red2 = 1'b1; + red3 = 1'b1; + orange = 1'b1; + ped_clr = 1'b1; + end + CAR1: begin + green1 = 1'b1; + green3 = 1'b1; + red2 = 1'b1; + orange = 1'b1; + stop_en = 1'b1; + five_clr = 1'b1; + end + CAR2: begin + green2 = 1'b1; + red1 = 1'b1; + red3 = 1'b1; + orange = 1'b1; + stop_en = 1'b1; + yellow_clr = 1'b1; + end + CAR3_4: begin + green3 = 1'b1; + turn = 1'b1; + red1 = 1'b1; + red2 = 1'b1; + orange = 1'b1; + stop_en = 1'b1; + yellow_clr = 1'b1; + end + PED: begin + white = 1'b1; + red1 = 1'b1; + red2 = 1'b1; + red3 = 1'b1; + stop_en = 1'b1; + yellow_clr = 1'b1; + ped_clr = 1'b1; + end + YELLOW1: begin + yellow1 = 1'b1; + yellow3 = 1'b1; + yellow_en = 1'b1; + stop_clr = 1'b1; + red2 = 1'b1; + orange = 1'b1; + end + YELLOW2: begin + yellow2 = 1'b1; + red1 = 1'b1; + red3 = 1'b1; + stop_clr = 1'b1; + yellow_en = 1'b1; + orange = 1'b1; + end + YELLOW3: begin + yellow3 = 1'b1; + red1 = 1'b1; + red2 = 1'b1; + stop_clr = 1'b1; + yellow_en = 1'b1; + orange = 1'b1; + end + DELAY: begin + red1 = 1'b1; + red2 = 1'b1; + red3 = 1'b1; + stop_clr = 1'b1; + five_en = 1'b1; + orange = 1'b1; + end + endcase + end + +endmodule: FSM diff --git a/designs/d14_jessief_trafficlight/src/chip.sv b/designs/d14_jessief_trafficlight/src/chip.sv new file mode 100644 index 0000000..8751d6c --- /dev/null +++ b/designs/d14_jessief_trafficlight/src/chip.sv @@ -0,0 +1,36 @@ +`default_nettype none + +module my_chip ( + input logic [11:0] io_in, + input logic clock, reset, + output logic [11:0] io_out +); +logic car1, car2, car3, car4, ped, + stop_yellow, stop_ped, stop_five, + red1, yellow1, green1, + red2, yellow2, green2, + red3, yellow3, green3, + turn, orange, white, + yellow_en, + yellow_clr, + stop_en, + stop_clr, + five_en, + five_clr, + ped_clr, + button; + + assign {car1, car2, car3, car4, button} = io_in [4:0]; + + assign io_out = {red1, yellow1, green1, + red2, yellow2, green2, + red3, yellow3, green3, + turn, orange, white}; + + Counter yellow (.D(4'b0), .clear(yellow_clr), .load(1'b0), .clock, .en(yellow_en), .Q(stop_yellow)); + Counter stop (.D(4'b0), .clear(stop_clr), .load(1'b0), .clock, .en(stop_en), .Q(stop_ped)); + Counter five (.D(4'b0), .clear(five_clr), .load(1'b0), .clock, .en(five_en), .Q(stop_five)); + Register pedestrian (.clock, .ped, .ped_clr, .button); + FSM control(.*); + +endmodule diff --git a/designs/d14_jessief_trafficlight/src/config.tcl b/designs/d14_jessief_trafficlight/src/config.tcl new file mode 100644 index 0000000..aa589e4 --- /dev/null +++ b/designs/d14_jessief_trafficlight/src/config.tcl @@ -0,0 +1,68 @@ +# PLEASE DO NOT EDIT THIS FILE! +# IT WILL MAKE YOUR CHIP UNMANUFACTURABLE +# The only line you may edit is FP_CORE_UTIL +# (may benefit from reducing it slightly) + +# User config +set script_dir [file dirname [file normalize [info script]]] + +# read some user config that is written by the setup.py program. +# - the name of the module is defined +# - the list of source files +source $::env(DESIGN_DIR)/user_config.tcl + +# save some time +set ::env(RUN_KLAYOUT_XOR) 0 +set ::env(RUN_KLAYOUT_DRC) 0 + +# don't put clock buffers on the outputs +set ::env(PL_RESIZER_BUFFER_OUTPUT_PORTS) 0 + +# allow use of specific sky130 cells +set ::env(SYNTH_READ_BLACKBOX_LIB) 1 + +# put all the pins on the left +set ::env(FP_PIN_ORDER_CFG) $::env(DESIGN_DIR)/pin_order.cfg + +# reduce wasted space +set ::env(TOP_MARGIN_MULT) 2 +set ::env(BOTTOM_MARGIN_MULT) 2 + +# absolute die size +set ::env(FP_SIZING) absolute +set ::env(DIE_AREA) "0 0 280 280" + +## THIS IS THE ONLY LINE YOU CAN EDIT +set ::env(FP_CORE_UTIL) 45 + +## set ::env(PL_BASIC_PLACEMENT) {1} + +set ::env(FP_IO_HLENGTH) 2 +set ::env(FP_IO_VLENGTH) 2 + +# use alternative efabless decap cells to solve LI density issue +set ::env(DECAP_CELL) "\ + sky130_fd_sc_hd__decap_3 \ + sky130_fd_sc_hd__decap_4 \ + sky130_fd_sc_hd__decap_6 \ + sky130_fd_sc_hd__decap_8 \ + sky130_ef_sc_hd__decap_12" + +# clock +set ::env(CLOCK_TREE_SYNTH) 1 + +# period is in ns, so 500ns == 2 MHz +set ::env(CLOCK_PERIOD) "500" +set ::env(CLOCK_PORT) {io_in[12]} + +# hold/slack margin +# set ::env(PL_RESIZER_HOLD_SLACK_MARGIN) 0.8 +# set ::env(GLB_RESIZER_HOLD_SLACK_MARGIN) 0.8 + +# don't use power rings or met5 +set ::env(DESIGN_IS_CORE) 0 +set ::env(RT_MAX_LAYER) {met4} + +# connect to first digital rails +set ::env(VDD_NETS) [list {vccd1}] +set ::env(GND_NETS) [list {vssd1}] diff --git a/designs/d14_jessief_trafficlight/src/decoder.v b/designs/d14_jessief_trafficlight/src/decoder.v new file mode 100644 index 0000000..8d6310e --- /dev/null +++ b/designs/d14_jessief_trafficlight/src/decoder.v @@ -0,0 +1,38 @@ + +/* + -- 1 -- + | | + 6 2 + | | + -- 7 -- + | | + 5 3 + | | + -- 4 -- +*/ + +module seg7 ( + input wire [3:0] counter, + output reg [6:0] segments +); + + always @(*) begin + case(counter) + // 7654321 + 0: segments = 7'b0111111; + 1: segments = 7'b0000110; + 2: segments = 7'b1011011; + 3: segments = 7'b1001111; + 4: segments = 7'b1100110; + 5: segments = 7'b1101101; + 6: segments = 7'b1111100; + 7: segments = 7'b0000111; + 8: segments = 7'b1111111; + 9: segments = 7'b1100111; + default: + segments = 7'b0000000; + endcase + end + +endmodule + diff --git a/designs/d14_jessief_trafficlight/src/pin_order.cfg b/designs/d14_jessief_trafficlight/src/pin_order.cfg new file mode 100644 index 0000000..0b85c63 --- /dev/null +++ b/designs/d14_jessief_trafficlight/src/pin_order.cfg @@ -0,0 +1,9 @@ +#N + +#S + +#E + +#W +io_in.* +io_out.* diff --git a/designs/d14_jessief_trafficlight/src/toplevel_chip.v b/designs/d14_jessief_trafficlight/src/toplevel_chip.v new file mode 100644 index 0000000..a82b427 --- /dev/null +++ b/designs/d14_jessief_trafficlight/src/toplevel_chip.v @@ -0,0 +1,18 @@ +`default_nettype none + +// DO NOT EDIT THIS FILE +module toplevel_chip ( + input [13:0] io_in, + output [13:0] io_out +); + + my_chip mchip ( + .io_in(io_in[11:0]), + .io_out(io_out[11:0]), + .clock(io_in[12]), + .reset(io_in[13]) + ); + + assign io_out[13:12] = 2'b00; + +endmodule diff --git a/designs/d14_jessief_trafficlight/test.sv b/designs/d14_jessief_trafficlight/test.sv new file mode 100644 index 0000000..17293e0 --- /dev/null +++ b/designs/d14_jessief_trafficlight/test.sv @@ -0,0 +1,103 @@ +`default_nettype none + +module clock_maker + (output logic clock); + + initial begin + clock = 1'b1; + forever #1 clock = ~clock; + end + +endmodule: clock_maker + +module test (); + logic clock, reset, car1, car2, car3, car4, ped, + stop_yellow, stop_ped, stop_five, + red1, yellow1, green1, + red2, yellow2, green2, + red3, yellow3, green3, + turn, orange, white, + yellow_en, + yellow_clr, + stop_en, + stop_clr, + five_en, + five_clr, + ped_clr, + button; + + clock_maker clocky(.*); + + Counter yellow (.D(4'b0), .clear(yellow_clr), .load(1'b0), .clock, .en(yellow_en), .Q(stop_yellow)); + Counter stop (.D(4'b0), .clear(stop_clr), .load(1'b0), .clock, .en(stop_en), .Q(stop_ped)); + Counter five (.D(4'b0), .clear(five_clr), .load(1'b0), .clock, .en(five_en), .Q(stop_five)); + Register pedestrian (.clock, .ped, .ped_clr, .button); + FSM control(.*); + + initial begin + $monitor($time,, " STATE: %s \n", control.state.name, + "_________________________________________________________________________\n", + " |_| red %b \n", red3, + " |_| yellow %b <-- car %b \n", yellow3, car3, + " |_| green %b \n", green3, + "- - - - - - - - - - - |_| turn %b car %b \n", turn, car4, + " red %b |_| - - - - - - - - - - - -\n", red1, + "car %b --> yellow %b |_| \n", car1, yellow1, + " green %b |_| \n", green1, + "______________________ ____________________________\n", + " | | red %b | cross %b \n", red2, white, + " | yellow %b | stop %b \n", yellow2, orange, + " | | green %b | ^ \n", green2, + " | ^ | | \n", + " | | | | ped %b \n", ped, + " | car %b | \n", car2); + + //initialize + button <= 1'b0; + car1 <= 1'b0; + car2 <= 1'b0; + car3 <= 1'b0; + car4 <= 1'b0; + reset <= 1'b0; + @(posedge clock); + reset <= 1'b1; + @(posedge clock); + reset <= 1'b0; + @(posedge clock); + + //test each car/ped individually + button <= 1'b1; + @(posedge clock); + car1 <= 1'b1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + button <= 1'b0; + car1 <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + car2 <= 1'b1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + car2 <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + car3 <= 1'b1; + car4 <= 1'b1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + $finish; + end + +endmodule: test \ No newline at end of file diff --git a/designs/d14_jessief_trafficlight/traffic_light.sim b/designs/d14_jessief_trafficlight/traffic_light.sim new file mode 100644 index 0000000..67a7af4 --- /dev/null +++ b/designs/d14_jessief_trafficlight/traffic_light.sim @@ -0,0 +1,531 @@ +Chronologic VCS simulator copyright 1991-2022 +Contains Synopsys proprietary information. +Compiler version T-2022.06_Full64; Runtime version T-2022.06_Full64; May 5 18:13 2023 + +Warning-[RT-NCMUCS] No condition matches in statement +v1.sv, 177 + No condition matches in 'unique case' statement. 'default' specification is + missing, inside test.control, at time 0s. + + +Warning-[RT-NCMUCS] No condition matches in statement +v1.sv, 240 + No condition matches in 'unique case' statement. 'default' specification is + missing, inside test.control, at time 0s. + + 0 STATE: INIT +_________________________________________________________________________ + |_| red 1 + |_| yellow 0 <-- car 0 + |_| green 0 +- - - - - - - - - - - |_| turn 0 car 0 + red 1 |_| - - - - - - - - - - - - +car 0 --> yellow 0 |_| + green 0 |_| +______________________ ____________________________ + | | red 1 | cross 0 + | yellow 0 | stop 1 + | | green 0 | ^ + | ^ | | + | | | | ped x + | car 0 | + + 2 STATE: INIT +_________________________________________________________________________ + |_| red 1 + |_| yellow 0 <-- car 0 + |_| green 0 +- - - - - - - - - - - |_| turn 0 car 0 + red 1 |_| - - - - - - - - - - - - +car 0 --> yellow 0 |_| + green 0 |_| +______________________ ____________________________ + | | red 1 | cross 0 + | yellow 0 | stop 1 + | | green 0 | ^ + | ^ | | + | | | | ped 0 + | car 0 | + + 6 STATE: INIT +_________________________________________________________________________ + |_| red 1 + |_| yellow 0 <-- car 0 + |_| green 0 +- - - - - - - - - - - |_| turn 0 car 0 + red 1 |_| - - - - - - - - - - - - +car 1 --> yellow 0 |_| + green 0 |_| +______________________ ____________________________ + | | red 1 | cross 0 + | yellow 0 | stop 1 + | | green 0 | ^ + | ^ | | + | | | | ped 1 + | car 0 | + + 7 STATE: CAR1 +_________________________________________________________________________ + |_| red 0 + |_| yellow 0 <-- car 0 + |_| green 1 +- - - - - - - - - - - |_| turn 0 car 0 + red 0 |_| - - - - - - - - - - - - +car 1 --> yellow 0 |_| + green 1 |_| +______________________ ____________________________ + | | red 1 | cross 0 + | yellow 0 | stop 1 + | | green 0 | ^ + | ^ | | + | | | | ped 1 + | car 0 | + + 9 STATE: YELLOW1 +_________________________________________________________________________ + |_| red 0 + |_| yellow 1 <-- car 0 + |_| green 0 +- - - - - - - - - - - |_| turn 0 car 0 + red 0 |_| - - - - - - - - - - - - +car 1 --> yellow 1 |_| + green 0 |_| +______________________ ____________________________ + | | red 1 | cross 0 + | yellow 0 | stop 1 + | | green 0 | ^ + | ^ | | + | | | | ped 1 + | car 0 | + + 11 STATE: PED +_________________________________________________________________________ + |_| red 1 + |_| yellow 0 <-- car 0 + |_| green 0 +- - - - - - - - - - - |_| turn 0 car 0 + red 1 |_| - - - - - - - - - - - - +car 1 --> yellow 0 |_| + green 0 |_| +______________________ ____________________________ + | | red 1 | cross 1 + | yellow 0 | stop 0 + | | green 0 | ^ + | ^ | | + | | | | ped 1 + | car 0 | + + 13 STATE: DELAY +_________________________________________________________________________ + |_| red 1 + |_| yellow 0 <-- car 0 + |_| green 0 +- - - - - - - - - - - |_| turn 0 car 0 + red 1 |_| - - - - - - - - - - - - +car 1 --> yellow 0 |_| + green 0 |_| +______________________ ____________________________ + | | red 1 | cross 0 + | yellow 0 | stop 1 + | | green 0 | ^ + | ^ | | + | | | | ped 1 + | car 0 | + + 14 STATE: DELAY +_________________________________________________________________________ + |_| red 1 + |_| yellow 0 <-- car 0 + |_| green 0 +- - - - - - - - - - - |_| turn 0 car 0 + red 1 |_| - - - - - - - - - - - - +car 0 --> yellow 0 |_| + green 0 |_| +______________________ ____________________________ + | | red 1 | cross 0 + | yellow 0 | stop 1 + | | green 0 | ^ + | ^ | | + | | | | ped 1 + | car 0 | + + 15 STATE: PED +_________________________________________________________________________ + |_| red 1 + |_| yellow 0 <-- car 0 + |_| green 0 +- - - - - - - - - - - |_| turn 0 car 0 + red 1 |_| - - - - - - - - - - - - +car 0 --> yellow 0 |_| + green 0 |_| +______________________ ____________________________ + | | red 1 | cross 1 + | yellow 0 | stop 0 + | | green 0 | ^ + | ^ | | + | | | | ped 1 + | car 0 | + + 16 STATE: PED +_________________________________________________________________________ + |_| red 1 + |_| yellow 0 <-- car 0 + |_| green 0 +- - - - - - - - - - - |_| turn 0 car 0 + red 1 |_| - - - - - - - - - - - - +car 0 --> yellow 0 |_| + green 0 |_| +______________________ ____________________________ + | | red 1 | cross 1 + | yellow 0 | stop 0 + | | green 0 | ^ + | ^ | | + | | | | ped 0 + | car 0 | + + 17 STATE: DELAY +_________________________________________________________________________ + |_| red 1 + |_| yellow 0 <-- car 0 + |_| green 0 +- - - - - - - - - - - |_| turn 0 car 0 + red 1 |_| - - - - - - - - - - - - +car 0 --> yellow 0 |_| + green 0 |_| +______________________ ____________________________ + | | red 1 | cross 0 + | yellow 0 | stop 1 + | | green 0 | ^ + | ^ | | + | | | | ped 0 + | car 0 | + + 18 STATE: PED +_________________________________________________________________________ + |_| red 1 + |_| yellow 0 <-- car 0 + |_| green 0 +- - - - - - - - - - - |_| turn 0 car 0 + red 1 |_| - - - - - - - - - - - - +car 0 --> yellow 0 |_| + green 0 |_| +______________________ ____________________________ + | | red 1 | cross 1 + | yellow 0 | stop 0 + | | green 0 | ^ + | ^ | | + | | | | ped 0 + | car 0 | + + 21 STATE: DELAY +_________________________________________________________________________ + |_| red 1 + |_| yellow 0 <-- car 0 + |_| green 0 +- - - - - - - - - - - |_| turn 0 car 0 + red 1 |_| - - - - - - - - - - - - +car 0 --> yellow 0 |_| + green 0 |_| +______________________ ____________________________ + | | red 1 | cross 0 + | yellow 0 | stop 1 + | | green 0 | ^ + | ^ | | + | | | | ped 0 + | car 0 | + + 22 STATE: DELAY +_________________________________________________________________________ + |_| red 1 + |_| yellow 0 <-- car 0 + |_| green 0 +- - - - - - - - - - - |_| turn 0 car 0 + red 1 |_| - - - - - - - - - - - - +car 0 --> yellow 0 |_| + green 0 |_| +______________________ ____________________________ + | | red 1 | cross 0 + | yellow 0 | stop 1 + | | green 0 | ^ + | ^ | | + | | | | ped 0 + | car 1 | + + 23 STATE: CAR2 +_________________________________________________________________________ + |_| red 1 + |_| yellow 0 <-- car 0 + |_| green 0 +- - - - - - - - - - - |_| turn 0 car 0 + red 1 |_| - - - - - - - - - - - - +car 0 --> yellow 0 |_| + green 0 |_| +______________________ ____________________________ + | | red 0 | cross 0 + | yellow 0 | stop 1 + | | green 1 | ^ + | ^ | | + | | | | ped 0 + | car 1 | + + 25 STATE: YELLOW2 +_________________________________________________________________________ + |_| red 1 + |_| yellow 0 <-- car 0 + |_| green 0 +- - - - - - - - - - - |_| turn 0 car 0 + red 1 |_| - - - - - - - - - - - - +car 0 --> yellow 0 |_| + green 0 |_| +______________________ ____________________________ + | | red 0 | cross 0 + | yellow 1 | stop 1 + | | green 0 | ^ + | ^ | | + | | | | ped 0 + | car 1 | + + 27 STATE: CAR2 +_________________________________________________________________________ + |_| red 1 + |_| yellow 0 <-- car 0 + |_| green 0 +- - - - - - - - - - - |_| turn 0 car 0 + red 1 |_| - - - - - - - - - - - - +car 0 --> yellow 0 |_| + green 0 |_| +______________________ ____________________________ + | | red 0 | cross 0 + | yellow 0 | stop 1 + | | green 1 | ^ + | ^ | | + | | | | ped 0 + | car 1 | + + 28 STATE: CAR2 +_________________________________________________________________________ + |_| red 1 + |_| yellow 0 <-- car 0 + |_| green 0 +- - - - - - - - - - - |_| turn 0 car 0 + red 1 |_| - - - - - - - - - - - - +car 0 --> yellow 0 |_| + green 0 |_| +______________________ ____________________________ + | | red 0 | cross 0 + | yellow 0 | stop 1 + | | green 1 | ^ + | ^ | | + | | | | ped 0 + | car 0 | + + 29 STATE: YELLOW2 +_________________________________________________________________________ + |_| red 1 + |_| yellow 0 <-- car 0 + |_| green 0 +- - - - - - - - - - - |_| turn 0 car 0 + red 1 |_| - - - - - - - - - - - - +car 0 --> yellow 0 |_| + green 0 |_| +______________________ ____________________________ + | | red 0 | cross 0 + | yellow 1 | stop 1 + | | green 0 | ^ + | ^ | | + | | | | ped 0 + | car 0 | + + 31 STATE: PED +_________________________________________________________________________ + |_| red 1 + |_| yellow 0 <-- car 0 + |_| green 0 +- - - - - - - - - - - |_| turn 0 car 0 + red 1 |_| - - - - - - - - - - - - +car 0 --> yellow 0 |_| + green 0 |_| +______________________ ____________________________ + | | red 1 | cross 1 + | yellow 0 | stop 0 + | | green 0 | ^ + | ^ | | + | | | | ped 0 + | car 0 | + + 33 STATE: DELAY +_________________________________________________________________________ + |_| red 1 + |_| yellow 0 <-- car 0 + |_| green 0 +- - - - - - - - - - - |_| turn 0 car 0 + red 1 |_| - - - - - - - - - - - - +car 0 --> yellow 0 |_| + green 0 |_| +______________________ ____________________________ + | | red 1 | cross 0 + | yellow 0 | stop 1 + | | green 0 | ^ + | ^ | | + | | | | ped 0 + | car 0 | + + 34 STATE: PED +_________________________________________________________________________ + |_| red 1 + |_| yellow 0 <-- car 0 + |_| green 0 +- - - - - - - - - - - |_| turn 0 car 0 + red 1 |_| - - - - - - - - - - - - +car 0 --> yellow 0 |_| + green 0 |_| +______________________ ____________________________ + | | red 1 | cross 1 + | yellow 0 | stop 0 + | | green 0 | ^ + | ^ | | + | | | | ped 0 + | car 0 | + + 36 STATE: PED +_________________________________________________________________________ + |_| red 1 + |_| yellow 0 <-- car 1 + |_| green 0 +- - - - - - - - - - - |_| turn 0 car 1 + red 1 |_| - - - - - - - - - - - - +car 0 --> yellow 0 |_| + green 0 |_| +______________________ ____________________________ + | | red 1 | cross 1 + | yellow 0 | stop 0 + | | green 0 | ^ + | ^ | | + | | | | ped 0 + | car 0 | + + 37 STATE: DELAY +_________________________________________________________________________ + |_| red 1 + |_| yellow 0 <-- car 1 + |_| green 0 +- - - - - - - - - - - |_| turn 0 car 1 + red 1 |_| - - - - - - - - - - - - +car 0 --> yellow 0 |_| + green 0 |_| +______________________ ____________________________ + | | red 1 | cross 0 + | yellow 0 | stop 1 + | | green 0 | ^ + | ^ | | + | | | | ped 0 + | car 0 | + + 39 STATE: CAR3_4 +_________________________________________________________________________ + |_| red 0 + |_| yellow 0 <-- car 1 + |_| green 1 +- - - - - - - - - - - |_| turn 1 car 1 + red 1 |_| - - - - - - - - - - - - +car 0 --> yellow 0 |_| + green 0 |_| +______________________ ____________________________ + | | red 1 | cross 0 + | yellow 0 | stop 1 + | | green 0 | ^ + | ^ | | + | | | | ped 0 + | car 0 | + + 41 STATE: YELLOW3 +_________________________________________________________________________ + |_| red 0 + |_| yellow 1 <-- car 1 + |_| green 0 +- - - - - - - - - - - |_| turn 0 car 1 + red 1 |_| - - - - - - - - - - - - +car 0 --> yellow 0 |_| + green 0 |_| +______________________ ____________________________ + | | red 1 | cross 0 + | yellow 0 | stop 1 + | | green 0 | ^ + | ^ | | + | | | | ped 0 + | car 0 | + + 43 STATE: CAR3_4 +_________________________________________________________________________ + |_| red 0 + |_| yellow 0 <-- car 1 + |_| green 1 +- - - - - - - - - - - |_| turn 1 car 1 + red 1 |_| - - - - - - - - - - - - +car 0 --> yellow 0 |_| + green 0 |_| +______________________ ____________________________ + | | red 1 | cross 0 + | yellow 0 | stop 1 + | | green 0 | ^ + | ^ | | + | | | | ped 0 + | car 0 | + + 45 STATE: YELLOW3 +_________________________________________________________________________ + |_| red 0 + |_| yellow 1 <-- car 1 + |_| green 0 +- - - - - - - - - - - |_| turn 0 car 1 + red 1 |_| - - - - - - - - - - - - +car 0 --> yellow 0 |_| + green 0 |_| +______________________ ____________________________ + | | red 1 | cross 0 + | yellow 0 | stop 1 + | | green 0 | ^ + | ^ | | + | | | | ped 0 + | car 0 | + + 47 STATE: CAR3_4 +_________________________________________________________________________ + |_| red 0 + |_| yellow 0 <-- car 1 + |_| green 1 +- - - - - - - - - - - |_| turn 1 car 1 + red 1 |_| - - - - - - - - - - - - +car 0 --> yellow 0 |_| + green 0 |_| +______________________ ____________________________ + | | red 1 | cross 0 + | yellow 0 | stop 1 + | | green 0 | ^ + | ^ | | + | | | | ped 0 + | car 0 | + + 49 STATE: YELLOW3 +_________________________________________________________________________ + |_| red 0 + |_| yellow 1 <-- car 1 + |_| green 0 +- - - - - - - - - - - |_| turn 0 car 1 + red 1 |_| - - - - - - - - - - - - +car 0 --> yellow 0 |_| + green 0 |_| +______________________ ____________________________ + | | red 1 | cross 0 + | yellow 0 | stop 1 + | | green 0 | ^ + | ^ | | + | | | | ped 0 + | car 0 | + +$finish called from file "v1.sv", line 100. +$finish at simulation time 50 + V C S S i m u l a t i o n R e p o r t +Time: 50 +CPU Time: 0.300 seconds; Data structure size: 0.0Mb +Fri May 5 18:13:28 2023 diff --git a/designs/d15_jerryfen_prng/.lastupdated b/designs/d15_jerryfen_prng/.lastupdated new file mode 100644 index 0000000..4d7b8c3 --- /dev/null +++ b/designs/d15_jerryfen_prng/.lastupdated @@ -0,0 +1 @@ +2023-05-14 diff --git a/designs/d15_jerryfen_prng/LICENSE b/designs/d15_jerryfen_prng/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/designs/d15_jerryfen_prng/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/designs/d15_jerryfen_prng/README.md b/designs/d15_jerryfen_prng/README.md new file mode 100644 index 0000000..af26544 --- /dev/null +++ b/designs/d15_jerryfen_prng/README.md @@ -0,0 +1,81 @@ +# Psuedo-Random Number Generator (PRNG) Chip +Jerry Feng +18-224/624 Spring 2023 Final Tapeout Project + +## Overview +The PRNG chip takes an 8-bit seed number as input into the chip and outputs an 8-bit psuedo-random number + +## How it Works +Seeds number is fed as input into the flip-flops of either a Fibonacci or Galois Linear Shift Register, +8 shifts occur, where the output of one of the linear shift register's is stored in a SIPO shift register. +The value of the SIPO shift register is then stored in a normal register, and then fed through an AES S-box to generate the final output. +This is a datapath, which is controlled by a Mealy machine FSM. Block diagram and FSM diagram can be seen below. + +Block Diagram: +![Block Diagram](media/98154_block_diagram.jpg) + +FSM Diagram: +![FSM Diagram](media/98154_FSM.jpg) + +## Inputs/Outputs +My chip does not have a dependency on any certain clock frequency. + + inputs: + - Select bit to select Fibonacci (0) or Galois (1) Linear Shift Register + - Enable + - Input bit 0 + - Input bit 1 + - Input bit 2 + - Input bit 3 + - Input bit 4 + - Input bit 5 + - Input bit 6 + - Input bit 7 + - none + - none + outputs: + - Output bit 0 + - Output bit 1 + - Output bit 2 + - Output bit 3 + - Output bit 4 + - Output bit 5 + - Output bit 6 + - Output bit 7 + - Valid + - none + - none + - none + + +## Design Testing / Bringup +Set reset pin high for one positive clock edge. +Next positive clock edge set reset pin low, enable pin low, and set select and input pins to desired values. +Following positive clock edge set enable pin high, then set enable pin low on the next clock edge. +Step clock until you see valid pin go high, then the output random number will be the psuedo-random number generated. + + Sample Inputs and Outputs for Fibonacci mode (select = 0): + Inputs Outputs + 11001100 -> 10000011 + 00011000 -> 10100011 + 10101010 -> 00101011 + + Sample Inputs and Outputs for Galois mode (select = 1): + Inputs Outputs + 11001100 -> 10100001 + 00011000 -> 00100011 + 10101010 -> 00010010 + + + +## Media +"Fibonacci mode" testbench output: +![Fibonacci Testbench](media/testbench_output_fibo.PNG) + +"Galois mode" testbench output: +![Galois Testbench](media/testbench_output_gal.PNG) + + +## Acknowledgements +A big thanks to Anish Singhani and Professor Nace for all their hardwork in putting together this course and giving me this cool opportunity! +An additional thanks to Anish Singhani for all the debugging help! diff --git a/designs/d15_jerryfen_prng/info.yaml b/designs/d15_jerryfen_prng/info.yaml new file mode 100644 index 0000000..db335dc --- /dev/null +++ b/designs/d15_jerryfen_prng/info.yaml @@ -0,0 +1,9 @@ +--- +project: + source_files: + - toplevel_chip.v + - chip.sv + - decoder.v + - library.sv + top_module: "toplevel_chip" + diff --git a/designs/d15_jerryfen_prng/media/98154_FSM.jpg b/designs/d15_jerryfen_prng/media/98154_FSM.jpg new file mode 100644 index 0000000..0282076 Binary files /dev/null and b/designs/d15_jerryfen_prng/media/98154_FSM.jpg differ diff --git a/designs/d15_jerryfen_prng/media/98154_block_diagram.jpg b/designs/d15_jerryfen_prng/media/98154_block_diagram.jpg new file mode 100644 index 0000000..d46cf76 Binary files /dev/null and b/designs/d15_jerryfen_prng/media/98154_block_diagram.jpg differ diff --git a/designs/d15_jerryfen_prng/media/testbench_output_fibo.PNG b/designs/d15_jerryfen_prng/media/testbench_output_fibo.PNG new file mode 100644 index 0000000..10479c2 Binary files /dev/null and b/designs/d15_jerryfen_prng/media/testbench_output_fibo.PNG differ diff --git a/designs/d15_jerryfen_prng/media/testbench_output_gal.PNG b/designs/d15_jerryfen_prng/media/testbench_output_gal.PNG new file mode 100644 index 0000000..7c1820c Binary files /dev/null and b/designs/d15_jerryfen_prng/media/testbench_output_gal.PNG differ diff --git a/designs/d15_jerryfen_prng/src/chip.sv b/designs/d15_jerryfen_prng/src/chip.sv new file mode 100644 index 0000000..c58ec0a --- /dev/null +++ b/designs/d15_jerryfen_prng/src/chip.sv @@ -0,0 +1,393 @@ +`default_nettype none + +module my_chip ( + input logic [11:0] io_in, // Inputs to your chip + output logic [11:0] io_out, // Outputs from your chip + input logic clock, + input logic reset // Important: Reset is ACTIVE-HIGH +); + + prng_chip prng_chip_one (.reset(reset), .en(io_in[0]), .sel(io_in[1]), .clk(clock), .seed(io_in[9:2]), .valid(io_out[8]), .rand_num(io_out[7:0])); + +endmodule: my_chip + +module prng_chip ( + input logic reset, en, sel, clk, + input logic [7:0] seed, + output logic valid, + output logic [7:0] rand_num +); + + // datapath: + logic serial_input, reg_en, sipo_en, fibo_out, galo_out, + cntr_load, shifted_eight, cnt_en, fib_load, gal_load; + logic [7:0] lsfr_rand_num, reg_rand_num, AES_out_num, shift_cnt; + + fibo_lsfr fibo1 (.clk(clk), .reset(reset), .load(fib_load), .seed(seed), .out_num(fibo_out)); + + galo_lsfr galo1 (.clk(clk), .reset(reset), .load(gal_load), .seed(seed), .out_num(galo_out)); + + Mux2to1 #(1) mux1 (.I0(fibo_out), .I1(galo_out), .S(sel), .Y(serial_input)); + + ShiftRegister_SIPO #(8) sr_sipo1 (.D(8'd0), .serial(serial_input), .en(sipo_en), .left(1'b1), .clock(clk), .Q(lsfr_rand_num)); + + Register #(8) reg1 (.en(reg_en), .clear(reset), .clock(clk), .D(lsfr_rand_num), .Q(reg_rand_num)); + + // Mux2to1 #(8) mux2 (.I0(shift_cnt), .I1(8'd0), .S(cntr_load), .Y(cntr_in)); + + Counter #(8) counter1 (.en(cnt_en), .clear(reset), .load(cntr_load), .up(1'b1), .clock(clk), .D(8'd0), .Q(shift_cnt)); + + MagComp magcomp1 (.A(shift_cnt), .B(8'd8), .AeqB(shifted_eight), .AltB(), .AgtB()); + + AES_Sbox Sbox1 (.input_num(reg_rand_num), .output_num(AES_out_num)); + + control_path ctrl_pth1 (.reset(reset), .shifted_eight(shifted_eight), .enable(en), .clock(clk), + .cntr_load(cntr_load), .fib_load(fib_load), .gal_load(gal_load), + .cnt_en(cnt_en), .sipo_en(sipo_en), .valid(valid), .reg_en(reg_en)); + + assign rand_num = AES_out_num; + + +endmodule: prng_chip + +module control_path +( + input logic reset, shifted_eight, enable, clock, + output logic cntr_load, fib_load, gal_load, + cnt_en, sipo_en, reg_en, valid +); + + enum logic [1:0] {reset_state = 2'b00, init = 2'b01, shift = 2'b10, done = 2'b11} curr_state, next_state; + + always_comb begin + + case(curr_state) + + reset_state: begin + next_state = init; + cntr_load = 0; + fib_load = 0; + gal_load = 0; + cnt_en = 0; + sipo_en = 0; + reg_en = 0; + valid = 0; + end + init: begin + + if(enable == 1) begin + next_state = shift; + cntr_load = 1; + fib_load = 1; + gal_load = 1; + cnt_en = 0; + sipo_en = 0; + reg_en = 0; + valid = 0; + end + else begin + next_state = init; + cntr_load = 0; + fib_load = 0; + gal_load = 0; + cnt_en = 0; + sipo_en = 0; + reg_en = 0; + valid = 0; + end + end + shift: begin + if(shifted_eight == 1) begin + next_state = done; + cntr_load = 0; + fib_load = 0; + gal_load = 0; + cnt_en = 0; + sipo_en = 0; + reg_en = 1; + valid = 0; + end + else begin + next_state = shift; + cntr_load = 0; + fib_load = 0; + gal_load = 0; + cnt_en = 1; + sipo_en = 1; + reg_en = 0; + valid = 0; + end + end + done: begin + next_state = reset_state ? reset_state : done; + cntr_load = 0; + fib_load = 0; + gal_load = 0; + cnt_en = 0; + sipo_en = 0; + reg_en = 0; + valid = 1; + + end + + endcase + end + + always_ff @(posedge clock, posedge reset) begin + + if (reset) begin + curr_state <= reset_state; + end + else begin + curr_state <= next_state; + end + end + + +endmodule: control_path + +module fibo_lsfr +( + input logic clk, reset, load, + input logic [7:0] seed, + output logic out_num +); + + // logic [7:0] state_in; + logic [7:0] state_out; + // logic nextbit, intermed_bit; + + // assign state_in = 8'b0; + + // Mux2to1 M1 (.I0(state_in), .I1(seed), .S(load), .Y({state_out[7], + // state_out[6], + // state_out[5], + // state_out[4], + // state_out[3], + // state_out[2], + // state_out[1], + // nextbit})); + + // width_FlipFlop w_ff (.preset_L(), .reset_L(~reset), .clock(clk), .D(state_in), .Q(state_out)); + + // xor G1(intermed_bit, state_out[4], state_out[6]); + // xor G2(nextbit, state_out[2], intermed_bit); + + logic feedback; + + always_ff @(posedge clk, posedge reset) begin + + if(reset) + state_out <= 8'b0; + else if(load) + state_out <= seed; + else + state_out <= {state_out[6:0], feedback}; + + end + + assign feedback = (state_out[4] ^ state_out[7]) ^ state_out[2]; + + assign out_num = feedback; + +endmodule: fibo_lsfr + + + +module galo_lsfr +( + input logic clk, reset, load, + input logic [7:0] seed, + output logic out_num +); + + // logic [7:0] state_in; + logic [7:0] state_out; + logic feedback; + + // assign state_in = 8'b0; + + // Mux2to1 M1 (.I0(state_in), .I1(seed), .S(load), .Y({state_out[7], + // state_out[6], + // state_out[5], + // state_out[4], + // state_out[3], + // state_out[2], + // state_out[1], + // nextbit})); + + // width_FlipFlop w_ff (.preset_L(), .reset_L(~reset), .clock(clk), .D(state_in), .Q(state_out)); + + // xor G1(state_out[6], state_out[5], nextbit); + // xor G2(state_out[5], state_out[4], nextbit); + // xor G3(state_out[4], state_out[3], nextbit); + + always_ff @(posedge clk, posedge reset) begin + + if(reset) + state_out <= 8'b0000_0000; + else if(load) + state_out <= seed; + else begin + state_out[7] <= state_out[6]; + state_out[6] <= state_out[5] ^ feedback; + state_out[5] <= state_out[4] ^ feedback; + state_out[4] <= state_out[3] ^ feedback; + + state_out[3:0] <= {state_out[2:0], feedback}; + end + end + + assign feedback = state_out[7]; + + // assign out_num[6] = out_num[5] ^ feedback; + // assign out_num[5] = out_num[4] ^ feedback; + // assign out_num[4] = out_num[3] ^ feedback; + + assign out_num = feedback; + +endmodule: galo_lsfr + +module AES_Sbox +( + input logic [7:0] input_num, + output logic [7:0] output_num +); + + logic U0, U1, U2, U3, U4, U5, U6, U7; + + logic S3, S7, S0, S6, S4, S1, S2, S5; + + logic y1, y2, y3, y4, y5, y6, y7, y8, y9, y10, + y11, y12, y13, y14, y15, y16, y17, y18, y19, y20, y21; + + logic z0, z1, z2, z3, z4, z5, z6, z7, z8, z9, z10, + z11, z12, z13, z14, z15, z16, z17; + + logic tc1, tc2, tc3, tc4, tc5, tc6, tc7, tc8, tc9, tc10, + tc11, tc12, tc13, tc14, tc16, tc17, tc18, tc20, tc21, tc26; + + logic t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, + t11, t12, t13, t14, t15, t16, t17, t18, t19, t20, + t21, t22, t23, t24, t25, t26, t27, t28, t29, t30, + t31, t32, t33, t34, t35, t36, t37, t38, t39, t40, + t41, t42, t43, t44, t45; + + assign {U0, U1, U2, U3, U4, U5, U6, U7} = input_num; + assign output_num = {S3, S7, S0, S6, S4, S1, S2, S5}; + + assign y14 = U3 ^ U5; + assign y13 = U0 ^ U6; + assign y9 = U0 ^ U3; + assign y8 = U0 ^ U5; + assign t0 = U1 ^ U2; + assign y1 = t0 ^ U7; + assign y4 = y1 ^ U3; + assign y12 = y13 ^ y14; + assign y2 = y1 ^ U0; + assign y5 = y1 ^ U6; + assign y3 = y5 ^ y8; + assign t1 = U4 ^ y12; + assign y15 = t1 ^ U5; + assign y20 = t1 ^ U1; + assign y6 = y15 ^ U7; + assign y10 = y15 ^ t0; + assign y11 = y20 ^ y9; + assign y7 = U7 ^ y11; + assign y17 = y10 ^ y11; + assign y19 = y10 ^ y8; + assign y16 = t0 ^ y11; + assign y21 = y13 ^ y16; + assign y18 = U0 ^ y16; + assign t2 = y12 & y15; + assign t3 = y3 & y6; + assign t4 = t3 ^ t2; + assign t5 = y4 & U7; + assign t6 = t5 ^ t2; + assign t7 = y13 & y16; + assign t8 = y5 & y1; + assign t9 = t8 ^ t7; + assign t10 = y2 & y7; + assign t11 = t10 ^ t7; + assign t12 = y9 & y11; + assign t13 = y14 & y17; + assign t14 = t13 ^ t12; + assign t15 = y8 & y10; + assign t16 = t15 ^ t12; + assign t17 = t4 ^ y20; + assign t18 = t6 ^ t16; + assign t19 = t9 ^ t14; + assign t20 = t11 ^ t16; + assign t21 = t17 ^ t14; + assign t22 = t18 ^ y19; + assign t23 = t19 ^ y21; + assign t24 = t20 ^ y18; + assign t25 = t21 ^ t22; + assign t26 = t21 & t23; + assign t27 = t24 ^ t26; + assign t28 = t25 & t27; + assign t29 = t28 ^ t22; + assign t30 = t23 ^ t24; + assign t31 = t22 ^ t26; + assign t32 = t31 & t30; + assign t33 = t32 ^ t24; + assign t34 = t23 ^ t33; + assign t35 = t27 ^ t33; + assign t36 = t24 & t35; + assign t37 = t36 ^ t34; + assign t38 = t27 ^ t36; + assign t39 = t29 & t38; + assign t40 = t25 ^ t39; + assign t41 = t40 ^ t37; + assign t42 = t29 ^ t33; + assign t43 = t29 ^ t40; + assign t44 = t33 ^ t37; + assign t45 = t42 ^ t41; + assign z0 = t44 & y15; + assign z1 = t37 & y6; + assign z2 = t33 & U7; + assign z3 = t43 & y16; + assign z4 = t40 & y1; + assign z5 = t29 & y7; + assign z6 = t42 & y11; + assign z7 = t45 & y17; + assign z8 = t41 & y10; + assign z9 = t44 & y12; + assign z10 = t37 & y3; + assign z11 = t33 & y4; + assign z12 = t43 & y13; + assign z13 = t40 & y5; + assign z14 = t29 & y2; + assign z15 = t42 & y9; + assign z16 = t45 & y14; + assign z17 = t41 & y8; + assign tc1 = z15 ^ z16; + assign tc2 = z10 ^ tc1; + assign tc3 = z9 ^ tc2; + assign tc4 = z0 ^ z2; + assign tc5 = z1 ^ z0; + assign tc6 = z3 ^ z4; + assign tc7 = z12 ^ tc4; + assign tc8 = z7 ^ tc6; + assign tc9 = z8 ^ tc7; + assign tc10 = tc8 ^ tc9; + assign tc11 = tc6 ^ tc5; + assign tc12 = z3 ^ z5; + assign tc13 = z13 ^ tc1; + assign tc14 = tc4 ^ tc12; + assign S3 = tc3 ^ tc11; + assign tc16 = z6 ^ tc8; + assign tc17 = z14 ^ tc10; + assign tc18 = tc13 ^ tc14; + assign S7 = ~(z12 ^ tc18); + assign tc20 = z15 ^ tc16; + assign tc21 = tc2 ^ z11; + assign S0 = tc3 ^ tc16; + assign S6 = ~(tc10 ^ tc18); + assign S4 = tc14 ^ S3; + assign S1 = ~(S3 ^ tc16); + assign tc26 = tc17 ^ tc20; + assign S2 = ~(tc26 ^ z17); + assign S5 = tc21 ^ tc17; + +endmodule: AES_Sbox diff --git a/designs/d15_jerryfen_prng/src/config.tcl b/designs/d15_jerryfen_prng/src/config.tcl new file mode 100644 index 0000000..aa589e4 --- /dev/null +++ b/designs/d15_jerryfen_prng/src/config.tcl @@ -0,0 +1,68 @@ +# PLEASE DO NOT EDIT THIS FILE! +# IT WILL MAKE YOUR CHIP UNMANUFACTURABLE +# The only line you may edit is FP_CORE_UTIL +# (may benefit from reducing it slightly) + +# User config +set script_dir [file dirname [file normalize [info script]]] + +# read some user config that is written by the setup.py program. +# - the name of the module is defined +# - the list of source files +source $::env(DESIGN_DIR)/user_config.tcl + +# save some time +set ::env(RUN_KLAYOUT_XOR) 0 +set ::env(RUN_KLAYOUT_DRC) 0 + +# don't put clock buffers on the outputs +set ::env(PL_RESIZER_BUFFER_OUTPUT_PORTS) 0 + +# allow use of specific sky130 cells +set ::env(SYNTH_READ_BLACKBOX_LIB) 1 + +# put all the pins on the left +set ::env(FP_PIN_ORDER_CFG) $::env(DESIGN_DIR)/pin_order.cfg + +# reduce wasted space +set ::env(TOP_MARGIN_MULT) 2 +set ::env(BOTTOM_MARGIN_MULT) 2 + +# absolute die size +set ::env(FP_SIZING) absolute +set ::env(DIE_AREA) "0 0 280 280" + +## THIS IS THE ONLY LINE YOU CAN EDIT +set ::env(FP_CORE_UTIL) 45 + +## set ::env(PL_BASIC_PLACEMENT) {1} + +set ::env(FP_IO_HLENGTH) 2 +set ::env(FP_IO_VLENGTH) 2 + +# use alternative efabless decap cells to solve LI density issue +set ::env(DECAP_CELL) "\ + sky130_fd_sc_hd__decap_3 \ + sky130_fd_sc_hd__decap_4 \ + sky130_fd_sc_hd__decap_6 \ + sky130_fd_sc_hd__decap_8 \ + sky130_ef_sc_hd__decap_12" + +# clock +set ::env(CLOCK_TREE_SYNTH) 1 + +# period is in ns, so 500ns == 2 MHz +set ::env(CLOCK_PERIOD) "500" +set ::env(CLOCK_PORT) {io_in[12]} + +# hold/slack margin +# set ::env(PL_RESIZER_HOLD_SLACK_MARGIN) 0.8 +# set ::env(GLB_RESIZER_HOLD_SLACK_MARGIN) 0.8 + +# don't use power rings or met5 +set ::env(DESIGN_IS_CORE) 0 +set ::env(RT_MAX_LAYER) {met4} + +# connect to first digital rails +set ::env(VDD_NETS) [list {vccd1}] +set ::env(GND_NETS) [list {vssd1}] diff --git a/designs/d15_jerryfen_prng/src/decoder.v b/designs/d15_jerryfen_prng/src/decoder.v new file mode 100644 index 0000000..17cd3b6 --- /dev/null +++ b/designs/d15_jerryfen_prng/src/decoder.v @@ -0,0 +1,37 @@ + +/* + -- 1 -- + | | + 6 2 + | | + -- 7 -- + | | + 5 3 + | | + -- 4 -- +*/ + +module seg7 ( + input wire [3:0] counter, + output reg [6:0] segments +); + + always @(*) begin + case(counter) + // 7654321 + 0: segments = 7'b0111111; + 1: segments = 7'b0000110; + 2: segments = 7'b1011011; + 3: segments = 7'b1001111; + 4: segments = 7'b1100110; + 5: segments = 7'b1101101; + 6: segments = 7'b1111100; + 7: segments = 7'b0000111; + 8: segments = 7'b1111111; + 9: segments = 7'b1100111; + default: + segments = 7'b0000000; + endcase + end + +endmodule diff --git a/designs/d15_jerryfen_prng/src/library.sv b/designs/d15_jerryfen_prng/src/library.sv new file mode 100644 index 0000000..4a3193a --- /dev/null +++ b/designs/d15_jerryfen_prng/src/library.sv @@ -0,0 +1,369 @@ +`default_nettype none + +// a decoder with an enable line that converts a b bit number into +// activating only one line of the 2^b outputs +module Decoder +#(parameter WIDTH = 8) + (input logic en, + input logic [$clog2(WIDTH)-1:0] I, + output logic [WIDTH-1:0] D); + + always_comb + if(en == 1'b0) begin + D = 8'd0; + end + else begin + case (I) + 3'b000 : D = 8'b00000001; + 3'b001 : D = 8'b00000010; + 3'b010 : D = 8'b00000100; + 3'b011 : D = 8'b00001000; + 3'b100 : D = 8'b00010000; + 3'b101 : D = 8'b00100000; + 3'b110 : D = 8'b01000000; + 3'b111 : D = 8'b10000000; + endcase + end + +endmodule : Decoder + +// BarrelShifter takes in a b bit number to be shifted, +// and a clog2(b) bit number +// as input to indicate how much to shift the b bit number left by +module BarrelShifter +#(parameter WIDTH = 16) + (input logic [WIDTH-1:0] V, + input logic [$clog2(WIDTH)-1:0] by, + output logic [WIDTH-1:0] S); + + assign S = (V << by); + +endmodule: BarrelShifter + +// multiplexer takes in an b bit number and a +// clog2(b) bit "select" number as input +// and uses the clog2(b) bit number to select the corresponding +// position's bit in the b bit number as output. +module Multiplexer +#(parameter WIDTH = 8) + (input logic [WIDTH-1:0] I, + input logic [$clog2(WIDTH)-1:0] S, + output logic Y); + + assign Y = I[S]; + +endmodule: Multiplexer + +// takes in two b bit numbers and a 1 bit select number, +// depending on if the select number is 1 or 0, +// one of the two b bit numbers is "selected" as the output. +module Mux2to1 +#(parameter WIDTH = 8) + (input logic [WIDTH-1:0] I0, + input logic [WIDTH-1:0] I1, + input logic S, + output logic [WIDTH-1:0] Y); + + always_comb + case(S) + 1'b0 : Y = I0; + 1'b1 : Y = I1; + endcase + +endmodule: Mux2to1 + +// MagComparator takes in two same width numbers, A and B, +// and outputs a 1 or 0 to AeqB, AltB, or AgtB +// if A == B, A < B, or A > B, respectively +module MagComp +#(parameter WIDTH = 8) + (input logic [WIDTH-1:0] A, + input logic [WIDTH-1:0] B, + output logic AeqB, AltB, AgtB); + + assign AeqB = (A == B); + assign AltB = (A < B); + assign AgtB = (A > B); + +endmodule: MagComp + +// Comparator takes two same width numbers, A and B as input +// and outputs 1 if they are equal, and 0 otherwise +module Comparator +#(parameter WIDTH = 4) + (input logic [WIDTH-1:0] A, B, + output logic AeqB); + + assign AeqB = (A == B); + +endmodule: Comparator + +// Adds two same width numbers and outputs the sum +// and 6th bit carryout +// if a carryout is produced +module Adder +#(parameter WIDTH = 5) + (input logic cin, + input logic [WIDTH-1:0] A, B, + output logic cout, + output logic [WIDTH-1:0] sum); + + always_comb begin + {cout, sum} = A + B + cin; + end + +endmodule: Adder + +// DFlipFlop propagates the D input value to the output +// on a rising edge of a clock +// active low preset sets output to 1 +// and active low reset sets output to 0 +module DFlipFlop + (input logic D, preset_L, reset_L, clock, + output logic Q); + + always_ff @(posedge clock, negedge reset_L) begin + + if(~preset_L) + Q <= 1; + else if(~reset_L) + Q <= 0; + else + Q <= D; + end + +endmodule: DFlipFlop + +// Register loads in value on input +// and stores it on the output Q on a +// rising clock edge +// clear sets output Q to 0 synchronously +module Register +#(parameter WIDTH = 8) + (input logic en, clear, clock, + input logic [WIDTH-1:0] D, + output logic [WIDTH-1:0] Q); + + always_ff @(posedge clock) + + if(en) begin + Q <= D; + end + else if(clear) begin + Q <= {WIDTH {1'b0}}; + end + +endmodule: Register + +// width_FlipFlop loads in value on input +// and stores it on the output Q on a +// rising clock edge +// clear sets output Q to 0 synchronously +module width_FlipFlop +#(parameter WIDTH = 8) + (input logic preset_L, reset_L, clock, + input logic [WIDTH-1:0] D, + output logic [WIDTH-1:0] Q); + + always_ff @(posedge clock, negedge reset_L) begin + + if(~preset_L) + Q <= 8'b1; + else if(~reset_L) + Q <= 8'b0; + else + Q <= D; + end + + +endmodule: width_FlipFlop + +// Counter is a register that +// when enabled adds 1 or subtracts one +// from the value loaded in on the D input +// and outputs the result to output Q +// if load is enabled you just load the value +// clear synchronously sets Q to 0 +module Counter +#(parameter WIDTH = 8) + (input logic en, + input logic clear, + input logic load, + input logic up, + input logic clock, + input logic [WIDTH-1:0] D, + output logic [WIDTH-1:0] Q); + + logic iterator; + always_ff @(posedge clock, posedge clear) + if (clear) begin + Q <= {WIDTH {1'b0}}; + end + else if(load) begin + Q <= D; + end + else if(en & ~load) begin + iterator = up ? 1 : -1; + Q <= Q + iterator; + end + +endmodule: Counter + +// synchronizer takes in an +// asynchronous signal as input +// and synchronizes it to the clock signal +// on output +module Synchronizer +#(parameter WIDTH = 8) + (input logic async, clock, + output logic sync); + + logic intermediate; + + always_ff @(posedge clock) begin + + intermediate <= async; + sync <= intermediate; + end + + +endmodule: Synchronizer + +// ShiftRegister_PIPO is a PIPO register that +// shifts left or right if the +// left control input is 1 or 0 respectively +// and it only shifts when enabled and load is not active. +// load loads in the D value and propogates it to the Q +// value without shifting +module ShiftRegister_PIPO +#(parameter WIDTH = 8) + (input logic [WIDTH-1:0] D, + input logic en, + input logic left, + input logic load, + input logic clock, + output logic [WIDTH-1:0] Q); + + always_ff @(posedge clock) + if (~en & load) begin + Q <= D; + end + else if (en & ~load & left) begin + Q <= Q << 1; + end + else if (en & ~load & ~left) begin + Q <= Q >> 1; + end + +endmodule: ShiftRegister_PIPO + +// ShiftRegister_SIPO is a SIPO register that shifts either left or right +// It will consume the bit on the serial input and place it in either +// the MSB or LSB position of the output depending on the shift direction +// When not enabled, nothing will change. +module ShiftRegister_SIPO +#(parameter WIDTH = 8) + (input logic [WIDTH-1:0] D, + input logic serial, + input logic en, + input logic left, + input logic clock, + output logic [WIDTH-1:0] Q); + + + always_ff @(posedge clock) + if (~en) begin + Q <= D; + end + else if (en & left) begin + Q <= Q << 1; + Q[0] <= serial; + end + else if (en & ~left) begin + Q <= Q >> 1; + Q[WIDTH-1] <= serial; + end + +endmodule: ShiftRegister_SIPO + +// BarrelShiftRegister is a PIPO register that shifts left. +// It shifts left either 0, 1, 2 or 3 +// positions based on the 2-bit by input when enabled +// Load has priority over shifting. +module BarrelShiftRegister +#(parameter WIDTH = 8) + (input logic en, + input logic load, + input logic [$clog2(WIDTH)-1:0] by, + input logic [WIDTH-1:0] D, + input logic clock, + output logic [WIDTH-1:0] Q); + + always_ff @(posedge clock) + if (~en & load) begin + Q <= D; + end + else if (en & ~load) begin + Q <= D << by; + end + +endmodule: BarrelShiftRegister + +// When BusDriver enabled, whatever value +// of data will be driven onto the bus, +// otherwise the bus driver will not drive anything +// code from lecture 7 +module BusDriver +#(parameter WIDTH = 8) + (input logic en, + input logic [WIDTH-1:0] data, + output logic [WIDTH-1:0] buff, + inout tri [WIDTH-1:0] bus); + + assign buff = bus; + assign bus = (en) ? data : 'bz; + +endmodule: BusDriver + +// Memory is a memory module which stores a number of words. +// It is combinational read and sequential write +// and has read and write enable inputs +// code adapted from lecture 14 +module Memory + #(parameter DW = 16, + W = 256, + AW = $clog2(W)) + (input logic re, we, clock, + input logic [AW-1:0] addr, + inout tri [DW-1:0] data); + + logic [DW-1:0] M[W]; + logic [DW-1:0] rData; + assign data = (re) ? rData: 'bz; + always_ff @(posedge clock) + if (we) + M[addr] <= data; + always_comb + rData = M[addr]; + +endmodule: Memory + + +module count +#(parameter WIDTH = 8) + (input logic clock, + input logic reset, + output logic [WIDTH-1:0] out); + + logic iterator; + always_ff @(posedge clock) begin + + if (reset) begin + out <= 0; + end + else begin + out <= out + 1; + end + end + +endmodule: count diff --git a/designs/d15_jerryfen_prng/src/pin_order.cfg b/designs/d15_jerryfen_prng/src/pin_order.cfg new file mode 100644 index 0000000..0b85c63 --- /dev/null +++ b/designs/d15_jerryfen_prng/src/pin_order.cfg @@ -0,0 +1,9 @@ +#N + +#S + +#E + +#W +io_in.* +io_out.* diff --git a/designs/d15_jerryfen_prng/src/toplevel_chip.v b/designs/d15_jerryfen_prng/src/toplevel_chip.v new file mode 100644 index 0000000..a82b427 --- /dev/null +++ b/designs/d15_jerryfen_prng/src/toplevel_chip.v @@ -0,0 +1,18 @@ +`default_nettype none + +// DO NOT EDIT THIS FILE +module toplevel_chip ( + input [13:0] io_in, + output [13:0] io_out +); + + my_chip mchip ( + .io_in(io_in[11:0]), + .io_out(io_out[11:0]), + .clock(io_in[12]), + .reset(io_in[13]) + ); + + assign io_out[13:12] = 2'b00; + +endmodule diff --git a/designs/d16_bgonzale_pll/.lastupdated b/designs/d16_bgonzale_pll/.lastupdated new file mode 100644 index 0000000..4d7b8c3 --- /dev/null +++ b/designs/d16_bgonzale_pll/.lastupdated @@ -0,0 +1 @@ +2023-05-14 diff --git a/designs/d16_bgonzale_pll/LICENSE b/designs/d16_bgonzale_pll/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/designs/d16_bgonzale_pll/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/designs/d16_bgonzale_pll/README.md b/designs/d16_bgonzale_pll/README.md new file mode 100644 index 0000000..dc0c38c --- /dev/null +++ b/designs/d16_bgonzale_pll/README.md @@ -0,0 +1,56 @@ +# Digital Phase-Locked Loop +Brandon Joel Gonzalez + +18-624 Spring 2023 Final Tapeout Project + +## Overview + +This project is a digital phase-locked loop (PLL). A PLL takes in a reference signal and attempts to reconstruct a signal that matches the phase of the input. PLLs are often designed and used in analog circuitry, but digital designs can also achieve this functionality. A PLL can work with sine waves, but this PLL takes in a square wave (i.e. clock signal) and attempts to lock onto its phase. + +## How it Works +A PLL is a feedback loop consisting of the following parts: +- A phase detector which takes the input reference signal and the reconstructed signal, producing a phase error which tells us how out-of-phase the two signals are +- A loop filter which provides some corrective factor +- A numerically-controlled oscillator that uses the error signal to generate an output signal that is fed back into the phase detector + +This can be described by the following system-level block diagram: + +![Phase-locked loop diagram](media/PLL-top-level.jpg) + +For this digital PLL, since we are working with square waves, we can make a few simplifying assumptions: +- The phase detector will only need to compare the rising edges of the two clock signals to determine which changed first; from this, we know whether our reconstructed signal leads or lags the reference input +- The oscillator can just be implemented as a counter that continuously counts by some amount every clock cycle. We can look at the MSB of this counter to generate a square wave of varying frequencies. Depending on the frequency step value (which can be controlled as an input), we will get a different frequency for our reconstructed signal +- The loop filter can just be a control signal that affects the rate at which we increment our counter. If the reconstructed clock is severely lagging the input reference, then we need to speed up the rate at which we count; otherwise, we need to slow down the rate at which we count. This loop gain value is also controlled by user input + +Comments are provided in [chip.sv](src/chip.sv) with further explanation of each submodule described above. + +## Inputs/Outputs +Below are the I/O pins: +- i_sys_clk: the system clock, tested at 1000 kHz +- i_rst: a global reset, which is active high +- i_ref_clk: the input clock signal used as a reference signal +- i_loop_gain: a 3-bit value that can be used to control how quickly the PLL locks to the reference signal +- i_freq_step: an 8-bit value that changes how much the counter increments by, and thus the frequency of the reconstructed clock signal +- o_rec_clk: the reconstructed clock signal +- o_lead_or_lag: 1-bit value that indicates whether the reconstructed signal leads or lags the clock +- o_phase_error: 1-bit value that indicates whether the two clocks are in-phase or out-of-phase + +## Hardware Peripherals +You can test this design by using any clock signal that is below 1000 kHz (which is the frequency of the system clock for the design); I chose a 10 Hz signal in my testbench. If you feed this clock signal as the input to the design, you should get out a reconstructed signal that attempts to match the phase of the input. It is important to try and pick a frequency step value such that the reconstructed signal matches the frequency of the reference signal. With this, you can use a microcontroller to generate a clock signal as the reference input to the design along with the other control signals, and then you can plot the input and output square waves on an oscilloscope for a visualization. + +## Design Testing / Bringup +In testing the PLL, I found it difficult to write a traditional testbench that took in certain inputs and produced a specific output. This is because by its nature, the output of the PLL was a reconstructed clock signal that I would have to compare to the input in order to understand how well the PLL worked. Therefore, to test the PLL, I can feed a clock signal of an arbitary frequency and phase (below 1000 kHz) to the i_ref_clk pin. Then, using GTKWave in simulation or an oscilloscope in real hardware, I can inspect both i_ref_clk and o_rec_clk to determine how closely they match. I can also look at the o_phase_error pin to determine how well the "locking" mechanism of the PLL is working. [PLL_testbench.py](bench/PLL_testbench.py) contains the Python code used for testing; the .vcd file produced was viewed using GTKWave. + +## Media +Below is a screenshot of the .vcd file produced by my testbench, as viewed in GTKWave. We can see how with a careful choice of i_loop_gain and i_freq_step, an output waveform is produced that closely follows the phase of the input waveform: + +![Phase-locked loop waveform](media/PLL-results.png) + +## References + +Here is a list of references that were very helpful in developing my understanding of PLL functionality and design: +- http://info-coach.fr/atari/hardware/_fd-hard/pll-tut-talk.pdf: broad overview of PLL design, though it covers a significant amount of analog PLLs and control theory +- http://www.ece.ualberta.ca/~elliott/ee552/studentAppNotes/1999f/PhaseDetector/: nice explanation of phase detectors for digital systems +- http://zipcpu.com/dsp/2017/12/14/logic-pll.html: thorough introduction to PLL design, specifically those that can be implemented in digital logic +- https://www.george-smart.co.uk/2020/02/experiments-with-phase-frequency-detectors/: very cool demonstration of a PLL on actual hardware with an oscilloscope to measure the signals in the circuit - hoping to emulate something similar once I receive the fabricated chip! +- https://en.wikipedia.org/wiki/Numerically_controlled_oscillator: great explanation of how digital oscillators function (particularly the section labeled "Phase accumulator") diff --git a/designs/d16_bgonzale_pll/bench/Makefile b/designs/d16_bgonzale_pll/bench/Makefile new file mode 100644 index 0000000..3fc08f6 --- /dev/null +++ b/designs/d16_bgonzale_pll/bench/Makefile @@ -0,0 +1,21 @@ +# This file is public domain, it can be freely copied without restrictions. +# SPDX-License-Identifier: CC0-1.0 + +# Makefile + +# defaults +SIM ?= verilator +TOPLEVEL_LANG ?= verilog +EXTRA_ARGS += --trace --trace-structs + +VERILOG_SOURCES += $(PWD)/phase_locked_loop.sv +# use VHDL_SOURCES for VHDL files + +# TOPLEVEL is the name of the toplevel module in your Verilog or VHDL file +TOPLEVEL = phase_locked_loop + +# MODULE is the basename of the Python test file +MODULE = PLL_testbench + +# include cocotb's make rules to take care of the simulator setup +include $(shell cocotb-config --makefiles)/Makefile.sim diff --git a/designs/d16_bgonzale_pll/bench/PLL_testbench.py b/designs/d16_bgonzale_pll/bench/PLL_testbench.py new file mode 100644 index 0000000..0b6b1d7 --- /dev/null +++ b/designs/d16_bgonzale_pll/bench/PLL_testbench.py @@ -0,0 +1,33 @@ +# test_my_design.py (simple) + +import cocotb +from cocotb.triggers import RisingEdge, FallingEdge, Timer +from cocotb.clock import Clock + +# this testbench lets you set the parameters for the PLL +# such as the input reference clock frequency, loop gain, and frequency step +# note that we assume operation at a 1 kHz global clock +# after runnning, you can inspect the resulting waveforms in GTKWave +@cocotb.test() +async def PLL_test(dut): + # set PLL parameters + global_clk = Clock(dut.i_sys_clk, 1, 'ms') # 1 kHz clock + await cocotb.start(global_clk.start()) + + # input reference clock signal + ref_clk = Clock(dut.i_ref_clk, 100, 'ms') # 10 Hz clock + await cocotb.start(ref_clk.start()) + + dut.i_loop_gain.value = 2 # can toggle for different locking speeds + dut.i_freq_step.value = 2 # initial guess for frequency step + + # reset DUT + dut.i_rst.value = 1 + for _ in range(2): + await RisingEdge(dut.i_sys_clk) + dut.i_rst.value = 0 + + # run the system clock for a while and examine outputs of PLL in gtkwave + # it would be nice to log the outputs and visualize using Python + for tick in range(5000): + await RisingEdge(dut.i_sys_clk) diff --git a/designs/d16_bgonzale_pll/bench/README.md b/designs/d16_bgonzale_pll/bench/README.md new file mode 100644 index 0000000..56d057e --- /dev/null +++ b/designs/d16_bgonzale_pll/bench/README.md @@ -0,0 +1,3 @@ +# Testbench + +This directory contains PLL_testbench.py, which is a Python file that uses CocoTB to test and evaluate the PLL. The SystemVerilog code for the PLL is provided in phase_locked_loop.sv (which was eventually integrated into src/chip.sv for tape-out). Also, a Makefile is provided for running the simulator; just type "Make" to run! diff --git a/designs/d16_bgonzale_pll/bench/phase_locked_loop.sv b/designs/d16_bgonzale_pll/bench/phase_locked_loop.sv new file mode 100644 index 0000000..16b1f56 --- /dev/null +++ b/designs/d16_bgonzale_pll/bench/phase_locked_loop.sv @@ -0,0 +1,127 @@ + +// phase-locked loop that takes in a square wave (i.e. reference clock signal) +// and attempts to generate a new square wave that matches the input in phase (i.e. reconstructed clock signal) +// first, a phase detector is used to compare the reference signal to the reconstructed signal +// if the reconstructed signal leads the reference, then it should "slow down" +// if the reconstructed signal lags the reference, then it should "speed up" +// this information is used to alter the output of the digitally-controlled oscillator accordingly +// viewing i_ref_clk and the output signals on an oscilloscope will help determine how well the PLL functions +// for best results, i_freq_step should be set so that o_rec_clk has roughly the same frequency as i_ref_clk +module phase_locked_loop ( + input wire i_sys_clk, // global system clock + input wire i_rst, // global reset + input wire i_ref_clk, // reference clock signal + input wire [2:0] i_loop_gain, // changes the rate at which we lock onto the phase + input wire [7:0] i_freq_step, // changes the rate at which the reconstructed signal changes (i.e. its frequency) + output reg o_rec_clk, // reconstructed clock signal + output wire o_lead_or_lag, // 1 if leading, 0 if lagging + output wire o_phase_error // 1 if out-of-phase, 0 if in-phase + ); + + // detect whether the reference and reconstructed clocks are out of phase and, if so, which is ahead/behind + wire out_of_phase; + reg lead_or_lag; // 1 for lead, 0 for lag + phase_detector phase_det(.i_sys_clk(i_sys_clk), .ref_clk(i_ref_clk), .rec_clk(o_rec_clk), + .lead_or_lag(lead_or_lag), .out_of_phase(out_of_phase)); + + // determine phase correction factor based on loop gain, as controlled by user input + reg [7:0] phase_corr; + loop_filter loop_fil(.i_sys_clk(i_sys_clk), .loop_gain(i_loop_gain), + .phase_corr(phase_corr)); + + // change the generated signal frequency as needed, using the input frequency step and loop gain as defined by the user input + digital_oscillator dig_osc(.i_sys_clk(i_sys_clk), .i_rst(i_rst), .freq_step(i_freq_step), + .phase_corr(phase_corr), .out_of_phase(out_of_phase), .lead_or_lag(lead_or_lag), + .rec_clk(o_rec_clk)); + + // assign outputs - useful for viewing performance of PLL + assign o_phase_error = out_of_phase; + assign o_lead_or_lag = lead_or_lag; + + // comment this out for synthesis + // initial begin + // $dumpfile("dump.vcd"); + // $dumpvars(0, phase_locked_loop); + // end + +endmodule + +// detects phase by using digital logic to evaluate which signal changed first, +// thereby telling us whether we're leading or lagging the reference clock +module phase_detector ( + input wire i_sys_clk, + input wire ref_clk, + input wire rec_clk, + output reg lead_or_lag, + output wire out_of_phase + ); + reg matched; // track whenever the two signals are in-phase + initial matched = 0; + + // determine whether the two clocks are currently matched + always @(posedge i_sys_clk) + begin + if (ref_clk && rec_clk) // both clocks are high + matched <= 1'b1; + else if ((!ref_clk) && (!rec_clk)) // both clocks are low + matched <= 1'b0; + end + + // whenever the reference or generated signals change, we should check which changed first + always @(*) + if (matched) + lead_or_lag = ref_clk && !rec_clk; // we're leading since rec went low before ref + else + lead_or_lag = !ref_clk && rec_clk; // we're lagging since ref went low before rec + + assign out_of_phase = ref_clk != rec_clk; // if the two clocks don't match, we're out of phase + +endmodule + +// applies loop gain factor of 2^(-loop_gain) +// larger loop gains causes the PLL to lock faster, but possibly with more oscillations +// see wiki article on numerically-controlled oscillators for further detail +module loop_filter ( + input wire i_sys_clk, + input wire [2:0] loop_gain, + output reg [7:0] phase_corr + ); + + initial phase_corr = 0; + + always @(posedge i_sys_clk) + phase_corr <= ({8'b10000000} >> loop_gain); + +endmodule + +// uses an internal counter to generate a clock signal +// this clock signal will change frequency based on how out-of-phase it is +// compared to the reference signal at the top-level module +module digital_oscillator ( + input wire i_sys_clk, + input wire i_rst, + input wire [7:0] freq_step, // changes rate at which clock changes + input wire [7:0] phase_corr, // changes how fast the clock changes based on phase error + input wire out_of_phase, // ref_clk not in phase with counter + input wire lead_or_lag, // tells us whether we're leading or lagging + output wire rec_clk // our PLL output + ); + + reg [7:0] ctr; // this is used to generate our square wave output + + always @(posedge i_sys_clk) begin + if (i_rst) begin + ctr <= 0; + end else begin // now use phase error to determine how much we speed up or slow down the counter + if (!out_of_phase) // we're in phase so keep incremening as usual + ctr <= ctr + freq_step; + else if (lead_or_lag && (phase_corr < freq_step)) // we're leading, so slow down the clock with phase correction + ctr <= ctr + freq_step - phase_corr; // but check that we don't decrement the clock value + else // we're lagging, so speed up the clock + ctr <= ctr + freq_step + phase_corr; + end + end + + assign rec_clk = ctr[7]; // take the MSB of our counter as the regenerated clock signal + +endmodule diff --git a/designs/d16_bgonzale_pll/info.yaml b/designs/d16_bgonzale_pll/info.yaml new file mode 100644 index 0000000..71ce048 --- /dev/null +++ b/designs/d16_bgonzale_pll/info.yaml @@ -0,0 +1,7 @@ +--- +project: + source_files: + - toplevel_chip.v + - chip.sv + top_module: "toplevel_chip" + diff --git a/designs/d16_bgonzale_pll/media/PLL-results.png b/designs/d16_bgonzale_pll/media/PLL-results.png new file mode 100644 index 0000000..64c2e6c Binary files /dev/null and b/designs/d16_bgonzale_pll/media/PLL-results.png differ diff --git a/designs/d16_bgonzale_pll/media/PLL-top-level.jpg b/designs/d16_bgonzale_pll/media/PLL-top-level.jpg new file mode 100644 index 0000000..6fbdd30 Binary files /dev/null and b/designs/d16_bgonzale_pll/media/PLL-top-level.jpg differ diff --git a/designs/d16_bgonzale_pll/media/README.md b/designs/d16_bgonzale_pll/media/README.md new file mode 100644 index 0000000..5641d81 --- /dev/null +++ b/designs/d16_bgonzale_pll/media/README.md @@ -0,0 +1,3 @@ +# Media + +This is a directory for photos of the project that appear elsewhere on the Github repository. diff --git a/designs/d16_bgonzale_pll/src/chip.sv b/designs/d16_bgonzale_pll/src/chip.sv new file mode 100644 index 0000000..039a6cf --- /dev/null +++ b/designs/d16_bgonzale_pll/src/chip.sv @@ -0,0 +1,158 @@ +`default_nettype none + +// phase-locked loop that takes in a square wave (i.e. reference clock signal) +// and attempts to generate a new square wave that matches the input in phase (i.e. reconstructed clock signal) +// first, a phase detector is used to compare the reference signal to the reconstructed signal +// if the reconstructed signal leads the reference, then it should "slow down" +// if the reconstructed signal lags the reference, then it should "speed up" +// this information is used to alter the output of the digitally-controlled oscillator accordingly +// viewing i_ref_clk and the output signals on an oscilloscope will help determine how well the PLL functions +// for best results, i_freq_step should be set so that o_rec_clk has roughly the same frequency as i_ref_clk +module phase_locked_loop ( + input wire i_sys_clk, // global system clock + input wire i_rst, // global reset + input wire i_ref_clk, // reference clock signal + input wire [2:0] i_loop_gain, // changes the rate at which we lock onto the phase + input wire [7:0] i_freq_step, // changes the rate at which the reconstructed signal changes (i.e. its frequency) + output reg o_rec_clk, // reconstructed clock signal + output wire o_lead_or_lag, // 1 if leading, 0 if lagging + output wire o_phase_error // 1 if out-of-phase, 0 if in-phase + ); + + // detect whether the reference and reconstructed clocks are out of phase and, if so, which is ahead/behind + wire out_of_phase; + reg lead_or_lag; // 1 for lead, 0 for lag + phase_detector phase_det(.i_sys_clk(i_sys_clk), .ref_clk(i_ref_clk), .rec_clk(o_rec_clk), + .lead_or_lag(lead_or_lag), .out_of_phase(out_of_phase)); + + // determine phase correction factor based on loop gain, as controlled by user input + reg [7:0] phase_corr; + loop_filter loop_fil(.i_sys_clk(i_sys_clk), .loop_gain(i_loop_gain), + .phase_corr(phase_corr)); + + // change the generated signal frequency as needed, using the input frequency step and loop gain as defined by the user input + digital_oscillator dig_osc(.i_sys_clk(i_sys_clk), .i_rst(i_rst), .freq_step(i_freq_step), + .phase_corr(phase_corr), .out_of_phase(out_of_phase), .lead_or_lag(lead_or_lag), + .rec_clk(o_rec_clk)); + + // assign outputs - useful for viewing performance of PLL + assign o_phase_error = out_of_phase; + assign o_lead_or_lag = lead_or_lag; + + initial begin + $dumpfile("dump.vcd"); + $dumpvars(0, phase_locked_loop); + end + +endmodule + +// detects phase by using digital logic to evaluate which signal changed first, +// thereby telling us whether we're leading or lagging the reference clock +module phase_detector ( + input wire i_sys_clk, + input wire ref_clk, + input wire rec_clk, + output reg lead_or_lag, + output wire out_of_phase + ); + reg matched; // track whenever the two signals are in-phase + initial matched = 0; + + // determine whether the two clocks are currently matched + always @(posedge i_sys_clk) + begin + if (ref_clk && rec_clk) // both clocks are high + matched <= 1'b1; + else if ((!ref_clk) && (!rec_clk)) // both clocks are low + matched <= 1'b0; + end + + // whenever the reference or generated signals change, we should check which changed first + always @(*) + if (matched) + lead_or_lag = ref_clk && !rec_clk; // we're leading since rec went low before ref + else + lead_or_lag = !ref_clk && rec_clk; // we're lagging since ref went low before rec + + assign out_of_phase = ref_clk != rec_clk; // if the two clocks don't match, we're out of phase + +endmodule + +// applies loop gain factor of 2^(-loop_gain) +// larger loop gains causes the PLL to lock faster, but possibly with more oscillations +// see wiki article on numerically-controlled oscillators for further detail +module loop_filter ( + input wire i_sys_clk, + input wire [2:0] loop_gain, + output reg [7:0] phase_corr + ); + + initial phase_corr = 0; + + always @(posedge i_sys_clk) + phase_corr <= ({8'b10000000} >> loop_gain); + +endmodule + +// uses an internal counter to generate a clock signal +// this clock signal will change frequency based on how out-of-phase it is +// compared to the reference signal at the top-level module +module digital_oscillator ( + input wire i_sys_clk, + input wire i_rst, + input wire [7:0] freq_step, // changes rate at which clock changes + input wire [7:0] phase_corr, // changes how fast the clock changes based on phase error + input wire out_of_phase, // ref_clk not in phase with counter + input wire lead_or_lag, // tells us whether we're leading or lagging + output wire rec_clk // our PLL output + ); + + reg [7:0] ctr; // this is used to generate our square wave output + + always @(posedge i_sys_clk) begin + if (i_rst) begin + ctr <= 0; + end else begin // now use phase error to determine how much we speed up or slow down the counter + if (!out_of_phase) // we're in phase so keep incremening as usual + ctr <= ctr + freq_step; + else if (lead_or_lag && (phase_corr < freq_step)) // we're leading, so slow down the clock with phase correction + ctr <= ctr + freq_step - phase_corr; // but check that we don't decrement the clock value + else // we're lagging, so speed up the clock + ctr <= ctr + freq_step + phase_corr; + end + end + + assign rec_clk = ctr[7]; // take the MSB of our counter as the regenerated clock signal + +endmodule + +module my_chip ( + input logic [11:0] io_in, // Inputs to your chip + output logic [11:0] io_out, // Outputs from your chip + input logic clock, + input logic reset // Important: Reset is ACTIVE-HIGH +); + + // we run at a 1 kHz clock + reg new_clock; + reg [8:0] counter; + always @(posedge clock) begin + counter <= counter + 1; + if (counter == 500) + begin + counter <= 0; + new_clock <= !new_clock; + end + end + + + phase_locked_loop PLL(.i_sys_clk(new_clock), + .i_rst(!reset), + .i_ref_clk(io_in[0]), + .i_loop_gain(io_in[3:1]), + .i_freq_step(io_in[11:4]), + .o_rec_clk(io_out[0]), + .o_lead_or_lag(io_out[1]), + .o_phase_error(io_out[2])); + +endmodule diff --git a/designs/d16_bgonzale_pll/src/config.tcl b/designs/d16_bgonzale_pll/src/config.tcl new file mode 100644 index 0000000..aa589e4 --- /dev/null +++ b/designs/d16_bgonzale_pll/src/config.tcl @@ -0,0 +1,68 @@ +# PLEASE DO NOT EDIT THIS FILE! +# IT WILL MAKE YOUR CHIP UNMANUFACTURABLE +# The only line you may edit is FP_CORE_UTIL +# (may benefit from reducing it slightly) + +# User config +set script_dir [file dirname [file normalize [info script]]] + +# read some user config that is written by the setup.py program. +# - the name of the module is defined +# - the list of source files +source $::env(DESIGN_DIR)/user_config.tcl + +# save some time +set ::env(RUN_KLAYOUT_XOR) 0 +set ::env(RUN_KLAYOUT_DRC) 0 + +# don't put clock buffers on the outputs +set ::env(PL_RESIZER_BUFFER_OUTPUT_PORTS) 0 + +# allow use of specific sky130 cells +set ::env(SYNTH_READ_BLACKBOX_LIB) 1 + +# put all the pins on the left +set ::env(FP_PIN_ORDER_CFG) $::env(DESIGN_DIR)/pin_order.cfg + +# reduce wasted space +set ::env(TOP_MARGIN_MULT) 2 +set ::env(BOTTOM_MARGIN_MULT) 2 + +# absolute die size +set ::env(FP_SIZING) absolute +set ::env(DIE_AREA) "0 0 280 280" + +## THIS IS THE ONLY LINE YOU CAN EDIT +set ::env(FP_CORE_UTIL) 45 + +## set ::env(PL_BASIC_PLACEMENT) {1} + +set ::env(FP_IO_HLENGTH) 2 +set ::env(FP_IO_VLENGTH) 2 + +# use alternative efabless decap cells to solve LI density issue +set ::env(DECAP_CELL) "\ + sky130_fd_sc_hd__decap_3 \ + sky130_fd_sc_hd__decap_4 \ + sky130_fd_sc_hd__decap_6 \ + sky130_fd_sc_hd__decap_8 \ + sky130_ef_sc_hd__decap_12" + +# clock +set ::env(CLOCK_TREE_SYNTH) 1 + +# period is in ns, so 500ns == 2 MHz +set ::env(CLOCK_PERIOD) "500" +set ::env(CLOCK_PORT) {io_in[12]} + +# hold/slack margin +# set ::env(PL_RESIZER_HOLD_SLACK_MARGIN) 0.8 +# set ::env(GLB_RESIZER_HOLD_SLACK_MARGIN) 0.8 + +# don't use power rings or met5 +set ::env(DESIGN_IS_CORE) 0 +set ::env(RT_MAX_LAYER) {met4} + +# connect to first digital rails +set ::env(VDD_NETS) [list {vccd1}] +set ::env(GND_NETS) [list {vssd1}] diff --git a/designs/d16_bgonzale_pll/src/pin_order.cfg b/designs/d16_bgonzale_pll/src/pin_order.cfg new file mode 100644 index 0000000..0b85c63 --- /dev/null +++ b/designs/d16_bgonzale_pll/src/pin_order.cfg @@ -0,0 +1,9 @@ +#N + +#S + +#E + +#W +io_in.* +io_out.* diff --git a/designs/d16_bgonzale_pll/src/toplevel_chip.v b/designs/d16_bgonzale_pll/src/toplevel_chip.v new file mode 100644 index 0000000..a82b427 --- /dev/null +++ b/designs/d16_bgonzale_pll/src/toplevel_chip.v @@ -0,0 +1,18 @@ +`default_nettype none + +// DO NOT EDIT THIS FILE +module toplevel_chip ( + input [13:0] io_in, + output [13:0] io_out +); + + my_chip mchip ( + .io_in(io_in[11:0]), + .io_out(io_out[11:0]), + .clock(io_in[12]), + .reset(io_in[13]) + ); + + assign io_out[13:12] = 2'b00; + +endmodule diff --git a/designs/d17_njayawar_tetris/.lastupdated b/designs/d17_njayawar_tetris/.lastupdated new file mode 100644 index 0000000..4d7b8c3 --- /dev/null +++ b/designs/d17_njayawar_tetris/.lastupdated @@ -0,0 +1 @@ +2023-05-14 diff --git a/designs/d17_njayawar_tetris/DesignOverview.png b/designs/d17_njayawar_tetris/DesignOverview.png new file mode 100644 index 0000000..899a4ab Binary files /dev/null and b/designs/d17_njayawar_tetris/DesignOverview.png differ diff --git a/designs/d17_njayawar_tetris/GameExample.png b/designs/d17_njayawar_tetris/GameExample.png new file mode 100644 index 0000000..722a196 Binary files /dev/null and b/designs/d17_njayawar_tetris/GameExample.png differ diff --git a/designs/d17_njayawar_tetris/LICENSE b/designs/d17_njayawar_tetris/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/designs/d17_njayawar_tetris/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/designs/d17_njayawar_tetris/Modules.png b/designs/d17_njayawar_tetris/Modules.png new file mode 100644 index 0000000..19e3697 Binary files /dev/null and b/designs/d17_njayawar_tetris/Modules.png differ diff --git a/designs/d17_njayawar_tetris/Modules2.png b/designs/d17_njayawar_tetris/Modules2.png new file mode 100644 index 0000000..1b13a3e Binary files /dev/null and b/designs/d17_njayawar_tetris/Modules2.png differ diff --git a/designs/d17_njayawar_tetris/README.md b/designs/d17_njayawar_tetris/README.md new file mode 100644 index 0000000..50e58db --- /dev/null +++ b/designs/d17_njayawar_tetris/README.md @@ -0,0 +1,66 @@ +# ModifiedTetrisV2 + +Navod Jayawardhane +18-224/624 Spring 2023 Final Tapeout Project + +## Overview + +My design is a mix of a Tetris/Stacker game. The game is played on a 8x9 LED matrix, with blocks +of 1 pixel in size. The top bar of the game will be dedicated to the dropper, which will consist of a +single pixel bouncing across the row. +Whenever the player presses a buƩon, the bouncing pixel will stop, and a dropping animation +will start, where a stream of green pixels light up in the corresponding column, and when the +pixel hits the boƩom, a steady blue pixel will light up. The bouncing pixel resumes and the player +keeps placing blocks. +Whenever a full row of blocks is placed, the row is eliminated and the game shifts down. The +score, shown on 3 7-segment displays, is incremented. AŌer a certain score, the bouncing will +speed up to increase the difficulty. If the stack of blocks reaches the top row, the game will end. +A single status LED will illuminate green or red based on whether the game is in play, and a reset +buƩon will act as the start game buƩon. + +## How it Works + +The top bar of the game is a simple counter/FSM design controlling whether the pixel is moving left or right, with pausing functionality. +When the drop button is pressed, the main game FSM pauses the top bar, and starts a counter causing the pixel to fall down the row. Another counter keeps track of the current column stack so when the dropping counter equals the current column stack, the current column stack is incremented and the game continues. The game checks whether all of the columns have >0 blocks to decrement the stacks and increase the score, or if any blocks reach the max height to end the game. +The 100KHz clock is split into slower enables to control the bouncing pixel speed and dropping speed. The bouncing pixel speed is increased as the score increases to increase the difficulty of the game. + +![](DesignOverview.png) +![](Modules.png) +![](Modules2.png) + + +## Inputs/Outputs + +Outputs: +Pin 1 – Game Status (0 = Stopped, 1 = Playing) +Pin 2-4 – Bouncing Pixel location (routed directly to the display) +Pin 5-12 – Update value (value corresponding to the state of the column or points score – MUXed as +requested by the microcontroller) + +Inputs: +Pin 1 – Drop block (buƩon input) +Pin 2 – Reset/Start Game +Pin 3-8 – IniƟal Speed/Difficulty (staƟcally set by the microcontroller to set the iniƟal game clock) +Pin 9-12 – Update Request LocaƟon (set by the microcontroller to MUX the outputs to update the game +state on the microcontroller – locaƟons include the 8 columns and point score) + +A 100KHz clock is required to keep game timing. + +## Hardware Peripherals + +72 RGB LEDs +Microcontroller to decode the game state +Decoder to display the bounding pixel locaƟon +I2C GPIO expander to drive all LEDs from the microcontroller (ex. PCA9555) +4-digit I2C 7 Segment display +Reset and Drop buttons +All misc power electronics required to drive the LEDs as needed +PCB to mount all of the components + +## Design Testing / Bringup + +To test the design, simply connect a clock, drop and new game buttons, and play. To view the game as it is in progress, setup a Raspberry Pi to quickly cycle through all of the possible request locations and display the game state. A CocoTB program was also used to test the game, where the drop button was asserted randomly, and the state of columns were tracked. + +## Media + +![](GameExample.png) diff --git a/designs/d17_njayawar_tetris/info.yaml b/designs/d17_njayawar_tetris/info.yaml new file mode 100644 index 0000000..71ce048 --- /dev/null +++ b/designs/d17_njayawar_tetris/info.yaml @@ -0,0 +1,7 @@ +--- +project: + source_files: + - toplevel_chip.v + - chip.sv + top_module: "toplevel_chip" + diff --git a/designs/d17_njayawar_tetris/src/chip.sv b/designs/d17_njayawar_tetris/src/chip.sv new file mode 100644 index 0000000..1338d4e --- /dev/null +++ b/designs/d17_njayawar_tetris/src/chip.sv @@ -0,0 +1,358 @@ +`default_nettype none + +module my_chip ( + input logic [11:0] io_in, // Inputs to your chip + output logic [11:0] io_out, // Outputs from your chip + input logic clock, + input logic reset // Important: Reset is ACTIVE-HIGH +); + + ModifiedTetris chip_design(.clock, .reset, .inputs(io_in), .outputs(io_out)); + +endmodule: my_chip + + +module ModifiedTetris( + input logic clock, reset, + input logic [11:0] inputs, + output logic [11:0] outputs +); + + logic drop_btn; + logic new_game_btn; + logic [5:0] initial_game_speed; + logic [3:0] update_request_location; + + assign drop_btn = inputs[0]; + assign new_game_btn = inputs[1]; + assign update_request_location = inputs[5:2]; + assign initial_game_speed = inputs[11:6]; + + logic game_running; + logic [2:0] bounce_pos; + logic [7:0] update_value; + + assign outputs[0] = game_running; + assign outputs[3:1] = bounce_pos; + assign outputs[11:4] = update_value; + + logic new_game_int, new_game, drop_int, drop_button; + + logic prev_drop_button, start_drop; + + logic [7:0] score; + + //Synchronize Inputs + always_ff @(posedge clock) begin + new_game_int <= new_game_btn; + new_game <= new_game_int; + drop_int <= drop_btn; + drop_button <= drop_int; + prev_drop_button <= drop_button; + end + + assign start_drop = drop_button && ~prev_drop_button; + + logic bounce_clock, drop_clock; + + ClockGenerator timing(.clock, .reset, .initial_game_speed, .score, .drop_clock, .bounce_clock); + + //Bouncing Pixel + logic pause_bounce; + + BouncingPixel bounce(.*); + + //8 Columns + logic [7:0] drop; + logic [3:0] drop_pos[7:0]; + logic stack_dec; + logic game_cl; + logic [3:0] stack_pos[7:0]; + logic [7:0] drop_done; + + genvar i; + for(i = 4'b0; i < 4'd8; i++) begin + SingleColumn col(.clock, .reset, .drop_clock, + .drop(drop[i]), + .stack_dec, + .stack_cl(game_cl), + .drop_pos(drop_pos[i]), + .stack_pos(stack_pos[i]), + .drop_done(drop_done[i])); + end + + + //Row Elimination Logic + logic [7:0] col_not_zero; + + genvar j; + for(j = 4'b0; j < 4'd8; j++) begin + assign col_not_zero[j] = |stack_pos[j]; + end + + assign stack_dec = &col_not_zero; + + + //Game Over Logic + logic game_over; + + assign game_over = stack_pos[0][3] | stack_pos[1][3] | stack_pos[2][3] | stack_pos[3][3] | stack_pos[4][3] | stack_pos[5][3] | stack_pos[6][3] | stack_pos[7][3]; + + + //Scoreboard Logic + always_ff @(posedge clock) begin + if(reset || game_cl) + score <= 8'b0; + else if(stack_dec) + score <= score + 1'b1; + end + + + //Game FSM + enum logic [1:0] {INIT, PLAY, DROP, OVER} state, nextState; + + always_comb begin + nextState = INIT; + game_cl = 1'b0; + game_running = 1'b0; + pause_bounce = 1'b0; + drop = 8'b0; + + case(state) + INIT: begin + if(new_game) + nextState = PLAY; + else + nextState = INIT; + + game_cl = 1'b1; + game_running = new_game; + end + PLAY: begin + if(game_over && ~new_game) begin + nextState = OVER; + game_running = 1'b0; + end + else if(start_drop && ~game_over && ~new_game) begin + nextState = DROP; + game_running = 1'b1; + pause_bounce = 1'b1; + drop[bounce_pos] = 1'b1; + end + else begin + nextState = PLAY; + game_running = 1'b1; + end + + game_cl = new_game; + end + DROP: begin + if(|drop_done) + nextState = PLAY; + else + nextState = DROP; + + pause_bounce = 1'b1; + game_running = 1'b1; + end + OVER: begin + if(new_game) + nextState = PLAY; + else + nextState = OVER; + + game_cl = new_game; + game_running = new_game; + end + endcase + end + + always_ff @(posedge clock) begin + if(reset) + state <= INIT; + else + state <= nextState; + end + + + //Output Multiplexer + logic [7:0] col_encoded; + assign col_encoded[3:0] = stack_pos[update_request_location[2:0]]; + assign col_encoded[7:4] = drop_pos[update_request_location[2:0]]; + + assign update_value = (update_request_location[3]) ? score : col_encoded; + +endmodule: ModifiedTetris + + +module BouncingPixel( + input logic clock, reset, + input logic bounce_clock, + input logic game_running, + input logic pause_bounce, + output logic [2:0] bounce_pos); + + logic up; + + enum logic {LEFT, RIGHT} state, nextState; + + always_comb begin + nextState = state; + up = (state == RIGHT) ? 1'b1 : 1'b0; + if(state == RIGHT && &bounce_pos) begin + nextState = LEFT; + up = 1'b0; + end + if(state == LEFT && ~|bounce_pos) begin + nextState = RIGHT; + up = 1'b1; + end + end + + always_ff @(posedge clock) begin + if(reset) begin + bounce_pos <= 3'b0; + end + else if(bounce_clock && game_running && ~pause_bounce) begin + if(up) + bounce_pos <= bounce_pos + 1'b1; + else + bounce_pos <= bounce_pos - 1'b1; + end + end + + always_ff @(posedge clock) begin + if(reset) + state <= RIGHT; + else + state <= nextState; + end + +endmodule: BouncingPixel + + +module SingleColumn( + input logic clock, reset, + input logic drop_clock, + input logic drop, + input logic stack_dec, + input logic stack_cl, + output logic [3:0] drop_pos, + output logic [3:0] stack_pos, + output logic drop_done); + + enum logic {WAIT, DROP} state, nextState; + + logic drop_init; + logic drop_en; + logic stack_incr; + assign drop_done = stack_incr; + + always_comb begin + nextState = WAIT; + drop_init = 1'b0; + drop_en = 1'b0; + stack_incr = 1'b0; + unique case (state) + WAIT: begin + if(drop) + nextState = DROP; + else + nextState = WAIT; + drop_init = 1'b1; + end + DROP: begin + if (drop_pos == (stack_pos + 1'b1)) begin + nextState = WAIT; + stack_incr = 1'b1; + drop_init = 1'b1; + end + else begin + nextState = DROP; + drop_en = 1'b1; + end + end + endcase + end + + always_ff @(posedge clock) begin + if(reset) + state <= WAIT; + else + state <= nextState; + end + + //Drop Counter + always_ff @(posedge clock) begin + if(reset || drop_init) + drop_pos <= 4'd9; + else if(drop_clock && drop_en) + drop_pos <= drop_pos - 1'b1; + end + + //Stack Counter + always_ff @(posedge clock) begin + if(reset || stack_cl) + stack_pos <= 4'd0; + else if(stack_dec) + stack_pos <= stack_pos - 1'b1; + else if(stack_incr) + stack_pos <= stack_pos + 1'b1; + end + +endmodule: SingleColumn + + +module ClockGenerator( + input logic clock, reset, + input logic [5:0] initial_game_speed, + input logic [7:0] score, + output logic drop_clock, bounce_clock); + + + logic [26:0] drop_max_val; + logic [26:0] bounce_max_val; + + logic [26:0] initial_game_speed_base, score_base; + + assign drop_max_val = 27'd5000; + + always_comb begin + initial_game_speed_base = 27'd40000 - (initial_game_speed * 600); + end + + always_comb begin + score_base = 27'd0 + (score * 300); + end + + assign bounce_max_val = initial_game_speed_base - score_base; + + //Drop Clock + logic [26:0] drop_cnt; + + always_ff @(posedge clock) begin + if(reset) + drop_cnt <= 27'b0; + else begin + drop_cnt <= drop_cnt + 1'b1; + if(drop_cnt == (drop_max_val + 1'b1)) + drop_cnt <= 27'b0; + end + end + assign drop_clock = (drop_cnt == drop_max_val); + + //Bounce Clock + logic [26:0] bounce_cnt; + + always_ff @(posedge clock) begin + if(reset) + bounce_cnt <= 27'b0; + else begin + bounce_cnt <= bounce_cnt + 1'b1; + if(bounce_cnt == (bounce_max_val + 1'b1)) + bounce_cnt <= 27'b0; + end + end + assign bounce_clock = (bounce_cnt == bounce_max_val); + +endmodule: ClockGenerator diff --git a/designs/d17_njayawar_tetris/src/config.tcl b/designs/d17_njayawar_tetris/src/config.tcl new file mode 100644 index 0000000..aa589e4 --- /dev/null +++ b/designs/d17_njayawar_tetris/src/config.tcl @@ -0,0 +1,68 @@ +# PLEASE DO NOT EDIT THIS FILE! +# IT WILL MAKE YOUR CHIP UNMANUFACTURABLE +# The only line you may edit is FP_CORE_UTIL +# (may benefit from reducing it slightly) + +# User config +set script_dir [file dirname [file normalize [info script]]] + +# read some user config that is written by the setup.py program. +# - the name of the module is defined +# - the list of source files +source $::env(DESIGN_DIR)/user_config.tcl + +# save some time +set ::env(RUN_KLAYOUT_XOR) 0 +set ::env(RUN_KLAYOUT_DRC) 0 + +# don't put clock buffers on the outputs +set ::env(PL_RESIZER_BUFFER_OUTPUT_PORTS) 0 + +# allow use of specific sky130 cells +set ::env(SYNTH_READ_BLACKBOX_LIB) 1 + +# put all the pins on the left +set ::env(FP_PIN_ORDER_CFG) $::env(DESIGN_DIR)/pin_order.cfg + +# reduce wasted space +set ::env(TOP_MARGIN_MULT) 2 +set ::env(BOTTOM_MARGIN_MULT) 2 + +# absolute die size +set ::env(FP_SIZING) absolute +set ::env(DIE_AREA) "0 0 280 280" + +## THIS IS THE ONLY LINE YOU CAN EDIT +set ::env(FP_CORE_UTIL) 45 + +## set ::env(PL_BASIC_PLACEMENT) {1} + +set ::env(FP_IO_HLENGTH) 2 +set ::env(FP_IO_VLENGTH) 2 + +# use alternative efabless decap cells to solve LI density issue +set ::env(DECAP_CELL) "\ + sky130_fd_sc_hd__decap_3 \ + sky130_fd_sc_hd__decap_4 \ + sky130_fd_sc_hd__decap_6 \ + sky130_fd_sc_hd__decap_8 \ + sky130_ef_sc_hd__decap_12" + +# clock +set ::env(CLOCK_TREE_SYNTH) 1 + +# period is in ns, so 500ns == 2 MHz +set ::env(CLOCK_PERIOD) "500" +set ::env(CLOCK_PORT) {io_in[12]} + +# hold/slack margin +# set ::env(PL_RESIZER_HOLD_SLACK_MARGIN) 0.8 +# set ::env(GLB_RESIZER_HOLD_SLACK_MARGIN) 0.8 + +# don't use power rings or met5 +set ::env(DESIGN_IS_CORE) 0 +set ::env(RT_MAX_LAYER) {met4} + +# connect to first digital rails +set ::env(VDD_NETS) [list {vccd1}] +set ::env(GND_NETS) [list {vssd1}] diff --git a/designs/d17_njayawar_tetris/src/pin_order.cfg b/designs/d17_njayawar_tetris/src/pin_order.cfg new file mode 100644 index 0000000..0b85c63 --- /dev/null +++ b/designs/d17_njayawar_tetris/src/pin_order.cfg @@ -0,0 +1,9 @@ +#N + +#S + +#E + +#W +io_in.* +io_out.* diff --git a/designs/d17_njayawar_tetris/src/toplevel_chip.v b/designs/d17_njayawar_tetris/src/toplevel_chip.v new file mode 100644 index 0000000..a82b427 --- /dev/null +++ b/designs/d17_njayawar_tetris/src/toplevel_chip.v @@ -0,0 +1,18 @@ +`default_nettype none + +// DO NOT EDIT THIS FILE +module toplevel_chip ( + input [13:0] io_in, + output [13:0] io_out +); + + my_chip mchip ( + .io_in(io_in[11:0]), + .io_out(io_out[11:0]), + .clock(io_in[12]), + .reset(io_in[13]) + ); + + assign io_out[13:12] = 2'b00; + +endmodule diff --git a/designs/d18_nikhildj_mac/.lastupdated b/designs/d18_nikhildj_mac/.lastupdated new file mode 100644 index 0000000..4d7b8c3 --- /dev/null +++ b/designs/d18_nikhildj_mac/.lastupdated @@ -0,0 +1 @@ +2023-05-14 diff --git a/designs/d18_nikhildj_mac/Figure1.jpg b/designs/d18_nikhildj_mac/Figure1.jpg new file mode 100644 index 0000000..5148c8b Binary files /dev/null and b/designs/d18_nikhildj_mac/Figure1.jpg differ diff --git a/designs/d18_nikhildj_mac/Figure10.jpg b/designs/d18_nikhildj_mac/Figure10.jpg new file mode 100644 index 0000000..0d1f416 Binary files /dev/null and b/designs/d18_nikhildj_mac/Figure10.jpg differ diff --git a/designs/d18_nikhildj_mac/Figure2.jpg b/designs/d18_nikhildj_mac/Figure2.jpg new file mode 100644 index 0000000..b7fe0df Binary files /dev/null and b/designs/d18_nikhildj_mac/Figure2.jpg differ diff --git a/designs/d18_nikhildj_mac/Figure3.jpg b/designs/d18_nikhildj_mac/Figure3.jpg new file mode 100644 index 0000000..74c8441 Binary files /dev/null and b/designs/d18_nikhildj_mac/Figure3.jpg differ diff --git a/designs/d18_nikhildj_mac/Figure4.jpg b/designs/d18_nikhildj_mac/Figure4.jpg new file mode 100644 index 0000000..14d1d71 Binary files /dev/null and b/designs/d18_nikhildj_mac/Figure4.jpg differ diff --git a/designs/d18_nikhildj_mac/Figure5.jpg b/designs/d18_nikhildj_mac/Figure5.jpg new file mode 100644 index 0000000..c7c0d1c Binary files /dev/null and b/designs/d18_nikhildj_mac/Figure5.jpg differ diff --git a/designs/d18_nikhildj_mac/Figure6.jpg b/designs/d18_nikhildj_mac/Figure6.jpg new file mode 100644 index 0000000..4a955d8 Binary files /dev/null and b/designs/d18_nikhildj_mac/Figure6.jpg differ diff --git a/designs/d18_nikhildj_mac/Figure7.jpg b/designs/d18_nikhildj_mac/Figure7.jpg new file mode 100644 index 0000000..316fd50 Binary files /dev/null and b/designs/d18_nikhildj_mac/Figure7.jpg differ diff --git a/designs/d18_nikhildj_mac/Figure8.jpg b/designs/d18_nikhildj_mac/Figure8.jpg new file mode 100644 index 0000000..8d2e61c Binary files /dev/null and b/designs/d18_nikhildj_mac/Figure8.jpg differ diff --git a/designs/d18_nikhildj_mac/Figure9.jpg b/designs/d18_nikhildj_mac/Figure9.jpg new file mode 100644 index 0000000..69f5d82 Binary files /dev/null and b/designs/d18_nikhildj_mac/Figure9.jpg differ diff --git a/designs/d18_nikhildj_mac/LICENSE b/designs/d18_nikhildj_mac/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/designs/d18_nikhildj_mac/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/designs/d18_nikhildj_mac/README.md b/designs/d18_nikhildj_mac/README.md new file mode 100644 index 0000000..2f3e023 --- /dev/null +++ b/designs/d18_nikhildj_mac/README.md @@ -0,0 +1,233 @@ +# 8-bit Multiplier - Accumulator + +Nikhil Dinkar Joshi +18-224/624 Spring 2023 Final Tapeout Project + +## 1. Overview + +The multiply-accumulate (MAC) or multiply-add (MAD) operation is a frequent operation in computing, particularly in digital signal processing, that calculates the product of two numbers and adds that product to an accumulator. +A multiplier-accumulator (MAC) unit is the hardware component that executes the function, which is also sometimes referred to as a MAC or MAD operation. +Mathematical equivalent of this operations can be given by: + +Equation 1 + +$$\sum_{k=0}^n Ak * Bk $$ + + + +## 2. Project Description + +In this Project, an 8-bit unsigned MAC unit will be implemented. Ak and Bk are 8-bit unsigned operands, and S is the result of their multiplier and addition. At the beginning of each multiplication cycle operands will be loaded in A and B registers and the result of each multiplication operation will be added to the previous value present in accumulator register S. The process will be repeated ten times. i.e. n= 9 in Equation 1 +Overall architecture is given in Figure 1 + + +![](Figure1.jpg) + +Figure 1 + +## 3. Submodule Description: + +### 3.1 MAC Controller Module: + +Control Signals: + +Inputs: + +1) Reset: asynchronous reset. Resets all the registers, multiplier, and add-accumulator modules. +2) Start: Begins MAC operation +3) Clock +4) End_mul: end of every multiplication cycle. + +Outputs: + +1) Load_op: signals Reg A and Reg B to load next pair of operands. +2) Begin_mul: signals multiplier to begin multiplication operation. +3) Add: signals add and accumulator module to add and accumulate the result of + multiplication operation. +4) Finish: Signals each multiplier and accumulate cycle is done. +5) Reset_cmd : Resets all the registers, multiplier, and add-accumulator modules at the start of each computation cycle. + + +A controller's Finite State Machine (FSM) is shown in Figure 2. Upon receiving an active Start signal, the FSM moves from the Idle state to the Initialize state. +A Reset command is generated in the Initialize stage to reset all functional units and registers. +Following one clock cycle, the FSM transitions to the Load state, at which point it instructs the input registers to load a pair of operands. + +The FSM moves to the Run state to begin multiplication as soon as the operands are loaded. +Following one clock cycle, the FSM transitions to the Test state and waits for the multiplier unit to finish its operation. +The FSM moves from the Test state to the Add state upon receiving an active End_Mul signal from the multiplier unit. + +The controller instructs the add-accumulator unit to add and accumulate the product of the multiplication in the Add state. +In addition, it decrements a counter that keeps track of the number of cycles of operand pairs. +Ten pairs of operands have to be cycled. If the number of operand pairs is less than 10, the FSM transitions to the Load state to load the next pair of operands. +If there are ten pairs of operands, the FSM enters the Idle state and waits for the next ten pairs. + +![](Figure2.jpg) + +Figure 2 + + +### 3.2 Multiplier Module: + +8 bit multiplier module using shift/add multiplier. The multiplier module will consist it own controller , multiplicand unit, adder unit and multiplication result unit. +Shift and add methods are used in the Shift/Add Multiplier to perform multiplication. +According to the multiplier's LSB bit value, a multiplicand value is added and accumulated. +At each clock cycle, the multiplier is moved one bit to the right and the LSB value of the multiplier is evaluated. +It executes a shift operation if the LSB value is 0. The multiplicand is moved one bit to the right and added to the accumulator if the LSB value is 0. +Carry select adder is chosen to implement the adder unit. multiplication result unit stores the accumulated output of the adder and multiplier. + + +![](Figure3.jpg) + +Figure 3 + + +#### 3.2.1. Controller Multiplier Module: + +This controller is similar to the controller described above and is used to control the shift/add multiplier. + +Control Signals: + +Inputs: +1) Reset +2) Start +3) Clock +4) LSB +Outputs: +1) do_Add +2) do_Shift +3) Load_Mul +4) End_Mul + +FSM: + +The FSM has five states Idle, Init, Check, Add, and Shift. +The FSM moves between states depending on the current state and the input signals. +When the FSM receives a Reset signal, it goes to the Idle state, and the counter is set to 0. +If the current state is Idle, and the Start signal is active, the FSM transitions to the Init state. +In the Init state, the FSM sets the Load_Mul signal to load a pair of operands. +In the Check state, the FSM checks the LSB signal and transitions to the Shift state if it is 0, or the Add state if it is 1. +In the Add state, the FSM sets the do_Add signal to command the add-accumulator unit to add and accumulate the result of multiplication. +It also decrements a counter that keeps track of the number of operand pairs cycled. The output of the adder and multiplier are stored in the multiplier block. +It comprises of a shift register with 17 bits and a multiplexer for shift-right operation. +In the Shift state, the FSM checks the counter and transitions back to the Check state if it is less than "7." If the counter equals "7," the FSM resets the counter and goes back to the Idle state and generate End_Mul signal. + + +### 3.3 Add and Accumulate module: + +The Add accumulate unit has one input which is 16-bit wide (output of multiplier module). +This input is added to the existing value present in the accumulator register. +The result of this addition is then stored in the accumulator register. +The operand provided to the add accumulator's input is a 16-bit value, whereas the add- accumulator's output is a 20-bit value. + +The add-accumulator accepts 10 pairs of operands, each of which (after multiplication) produces a 16-bit wide result. +10 is represented in binary as 1010, which is a 4-bit value. +Given that we are adding the operand 10 times, we are essentially multiplying the operand by ten. +The effect of multiplying a 16-bit value by a 4-bit value is 16+4 = 20 bits of accumulator register storage. +To convert a 16-bit value to a 20-bit value, the inputs of the register's top four bits are linked to zeros. + + +![](Figure4.jpg) + +Figure 4 + + +#### 3.3.1 20 bit carry select adder: + + +The carry-select adder contains several 4-bit Ripple Carry Adders and some multiplexers. +A carry-select adder may be subdivided into 4 bit sections. +20-Bit Carry-Select adder is shown in Figure 5 as a block diagram. +The carry-select adder is used for addition process in multiplier block and add-accumulator block. + + + +![](Figure5.jpg) + +Figure 5 + + + + + +## 4. Inputs/Outputs + +### 4.1 Inputs: + +1) Clock +2) Reset +3) Start +4) Operand A: 8 bit +5) Operand B: 8 bit +6) Input_done. + +Operand A and Operand B are taken in serially at every clock edge and saved in 8-bit input register. Once 8-bits of both operands is taken in, the Input_done flag is set. + +### 4.2 Outputs: + +1) Finish +2) S (Result) : 20 bit +3) Carry_out: 1 bit +4) End_Mul +5) Output_done + +20-bit result is outputted serially when Finish is asserted. Once all 20-bits are outputted, Output_done flag is set. + +End_mul is used for verification purposes. + + + +## 5. Design Testing / Bringup + +Test bench files : +1) 8 bit multiplier : top_multiplier_tb.sv +2) 20_bit_carry_select_adder.sv: 20 bit adder +3) 8_bit_carry_select_adder.sv: 8 bit adder +4) 20 bit add-accumulate: add_accumulate_tb.sv +5) MAC (top module): mac_tb.sv and max_mac_tb.sv + +### 5.1 Verification Methodology + +A. Mac (multiplier accumulator) is the top module. Two test benches do verification of this top module, and both are self-checking. + +a.Max_mac_tb.sv : This test bench verifies that the accumulator register can hold the maximum possible value. 10 pairs of operands A and B with value 255 are inputted. The maximum possible value in the case will be 255 x 255 x 10 = 650250. The output of this test bench is shown in the figure below. + +![](Figure6.jpg) + +Figure 6 + + +![](Figure7.jpg) + +Figure 7 + + +b. mac_tb.sv : This test bench provides ascending and descending inputs to the module. Operand A increases from 0 to 9 and operand B decreases from 255 to 246. The output for this test bench is shown in the figure below. +This test bench verifies the timing of all the control signals and and synchronizes the input operand change with the control signals. +Every new operand and Start signal is asserted once End_Mul is high (Finish of 1 multiplication Cycle). + + + +![](Figure8.jpg) + +Figure 8 + + + + +![](Figure9.jpg) + +Figure 9 + + + + +## GDS Layout + +![](Figure10.jpg) + +Figure 10 + + +## References + +1] Ramos, J. J. (n.d.). 8-by-8 bit multiplier accumulator http://www.mass-talent.ca/uploads/3/9/3/0/3930953/multiply_acccumulator_design.pdf diff --git a/designs/d18_nikhildj_mac/info.yaml b/designs/d18_nikhildj_mac/info.yaml new file mode 100644 index 0000000..97b31b2 --- /dev/null +++ b/designs/d18_nikhildj_mac/info.yaml @@ -0,0 +1,23 @@ +--- +project: + source_files: + - toplevel_chip.v + - chip.sv + - 8_bit_adder.sv + - DFF.sv + - add_accumulate.sv + - adder_20.sv + - carry_select4.sv + - fulladder.sv + - mac_controller.sv + - multiplicand.sv + - multiplier.sv + - multiplier_controller.sv + - register20.sv + - register8.sv + - ripple_carry_adder.sv + - top_multiplier.sv + + + top_module: "toplevel_chip" + diff --git a/designs/d18_nikhildj_mac/src/8_bit_adder.sv b/designs/d18_nikhildj_mac/src/8_bit_adder.sv new file mode 100644 index 0000000..59cace4 --- /dev/null +++ b/designs/d18_nikhildj_mac/src/8_bit_adder.sv @@ -0,0 +1,30 @@ + +module carry_select8( + input logic [7:0] a, b, + input logic carry_in, + output logic [7:0] sum, + output logic carry_out +); +logic temp_carry; + + + carry_select4 S0 (.a(a[3:0]), .b(b[3:0]), .carry_in(carry_in), .sum(sum[3:0]), .carry_out(temp_carry)); + carry_select4 S1 (.a(a[7:4]), .b(b[7:4]), .carry_in(temp_carry), .sum(sum[7:4]), .carry_out(carry_out)); + + + +endmodule + + + + + + + + + + + + + + diff --git a/designs/d18_nikhildj_mac/src/DFF.sv b/designs/d18_nikhildj_mac/src/DFF.sv new file mode 100644 index 0000000..c6a4da2 --- /dev/null +++ b/designs/d18_nikhildj_mac/src/DFF.sv @@ -0,0 +1,14 @@ +module DFF ( + input logic reset, + input logic clk, + input logic D, + output logic Q +); + always_ff @(posedge clk, negedge reset) begin + if (!reset) begin + Q <= 0; // Clear the register + end else begin + Q <= D; // Load the register + end + end +endmodule diff --git a/designs/d18_nikhildj_mac/src/add_accumulate.sv b/designs/d18_nikhildj_mac/src/add_accumulate.sv new file mode 100644 index 0000000..fa8b950 --- /dev/null +++ b/designs/d18_nikhildj_mac/src/add_accumulate.sv @@ -0,0 +1,53 @@ +module add_accumulate ( + + input logic [15:0] mult_res_in, + input logic add, + input logic reset, + output logic [19:0] result, + output logic result_carry_out + +); + +logic [19:0] temp_mult_res_in; +logic [19:0] mult_res_out; +logic [19:0] add_out; +logic [19:0] add_in; +logic [19:0] temp_result; +assign temp_result = result; +assign add_in = temp_result; + +assign temp_mult_res_in[19:0] = {4'b0000, mult_res_in}; + + +register20 i0 ( + .in(temp_mult_res_in), + .add(add), + .reset(reset), + .out(mult_res_out) + +); + +carry_select20 adder ( + .a(mult_res_out), + .b(add_in), + .carry_in(1'b0), + .sum(add_out), + .carry_out(result_carry_out) + + +); +register20 accmulate ( + .in(add_out), + .add(!add), + .reset(reset), + .out(result) + +); + +endmodule + + + + + + diff --git a/designs/d18_nikhildj_mac/src/adder_20.sv b/designs/d18_nikhildj_mac/src/adder_20.sv new file mode 100644 index 0000000..6966f78 --- /dev/null +++ b/designs/d18_nikhildj_mac/src/adder_20.sv @@ -0,0 +1,26 @@ + +module carry_select20( + input logic [19:0] a, b, + input logic carry_in, + output logic [19:0] sum, + output logic carry_out +); +wire temp_carry1,temp_carry2,temp_carry3,temp_carry4; + + + carry_select4 S0 (.a(a[3:0]), .b(b[3:0]), .carry_in(carry_in), .sum(sum[3:0]), .carry_out(temp_carry1)); + carry_select4 S1 (.a(a[7:4]), .b(b[7:4]), .carry_in(temp_carry1), .sum(sum[7:4]), .carry_out(temp_carry2)); + carry_select4 S2 (.a(a[11:8]), .b(b[11:8]), .carry_in(temp_carry2), .sum(sum[11:8]), .carry_out(temp_carry3)); + carry_select4 S3 (.a(a[15:12]), .b(b[15:12]), .carry_in(temp_carry3), .sum(sum[15:12]), .carry_out(temp_carry4)); + carry_select4 S4 (.a(a[19:16]), .b(b[19:16]), .carry_in(temp_carry4), .sum(sum[19:16]), .carry_out(carry_out)); + + + +endmodule + + + + + + + diff --git a/designs/d18_nikhildj_mac/src/carry_select4.sv b/designs/d18_nikhildj_mac/src/carry_select4.sv new file mode 100644 index 0000000..f7af27f --- /dev/null +++ b/designs/d18_nikhildj_mac/src/carry_select4.sv @@ -0,0 +1,22 @@ +module carry_select4( + input logic [3:0] a, b, + input logic carry_in, + output logic [3:0] sum, + output logic carry_out +); +logic [3:0] SUM0, SUM1; +logic carry0, carry1; + + + ripple_carry_adder S0 (.a(a), .b(b), .carry_in(1'b0), .sum(SUM0), .carry_out(carry0)); + ripple_carry_adder S1 (.a(a), .b(b), .carry_in(1'b1), .sum(SUM1), .carry_out(carry1)); + + + + + +assign sum = (carry_in == 1'b0) ? SUM0 : + (carry_in == 1'b1) ? SUM1 : 4'bx; +assign carry_out = (carry_in & carry1) | carry0; + +endmodule \ No newline at end of file diff --git a/designs/d18_nikhildj_mac/src/chip.sv b/designs/d18_nikhildj_mac/src/chip.sv new file mode 100644 index 0000000..acf716b --- /dev/null +++ b/designs/d18_nikhildj_mac/src/chip.sv @@ -0,0 +1,147 @@ +`default_nettype none + +module my_chip ( + input logic [11:0] io_in, // Inputs to your chip + output logic [11:0] io_out, // Outputs from your chip + input logic clock, + input logic reset // Important: Reset is ACTIVE-HIGH +); + + + logic reset_n; + logic START; + logic [7:0] op_a_in; + logic [7:0] op_b_in; + logic [19:0] mac_res; + logic mac_carry_out; + logic Finish; + logic End_mul; + bit input_done = 1'b0; + bit output_done = 1'b0; + +assign reset_n = !reset; +assign START = io_in[11]; +assign mac_carry_out = io_out[11]; +assign Finish = io_out[10]; + assign input_done = io_in[8]; + assign output_done = io_out[8]; + assign End_mul = io_out[7]; + + assign io_in[7:0] = 8'd0; + assign io_out[6:0] = 8'd0; + + +integer i,j; + + + + always@(posedge clock) begin + + for (i=0;i<8;i = i+1) begin + op_a_in[i] <= io_in[10]; + op_b_in[i] <= io_in[9]; + end + + if (i == 8) begin + input_done <= 1'b1; + end + + else begin + input_done <= 1'b0; + end + + if (Finish) begin + for (j=0;j<20;j=j+1) begin + io_out[9] <= mac_res[j]; + end + end + else begin + io_out[9] <= 1'b0; + end + + + if (j == 20) begin + output_done <= 1'b1; + end + + else begin + output_done <= 1'b0; + end + + + end + + + + + +// MAC_controller +logic control_reset; +logic Begin_mul; +logic add; +logic Load_op; + + +//Operands +logic [7:0] op_a_out; +logic [7:0] op_b_out; + +//multiplier +logic [15:0] mult_res; + + +CONTROLLER_MAC control ( + + .reset(reset_n), + .clk(clock), + .START(START), + .End_mul(End_mul), + .Finish(Finish), + .RESET_cmd(control_reset), + .Load_op(Load_op), + .Begin_mul(Begin_mul), + .add(add) +); + +register8 opa ( + .in(op_a_in), + .Load_op(Load_op), + + .reset(control_reset), + .out(op_a_out) +); + +register8 opb ( + .in(op_b_in), + .Load_op(Load_op), + + .reset(control_reset), + .out(op_b_out) +); + +top_multiplier mult ( + + .a_in(op_a_out), + .b_in(op_b_out), + .reset(control_reset), + .clk(clock), + .Begin_mul(Begin_mul), + .mult_out(mult_res), + .End_mul(End_mul) +); + +add_accumulate aa ( + + .mult_res_in(mult_res), + .add(add), + + .reset(control_reset), + .result(mac_res), + .result_carry_out(mac_carry_out) +); + + + + + +endmodule diff --git a/designs/d18_nikhildj_mac/src/config.tcl b/designs/d18_nikhildj_mac/src/config.tcl new file mode 100644 index 0000000..aa589e4 --- /dev/null +++ b/designs/d18_nikhildj_mac/src/config.tcl @@ -0,0 +1,68 @@ +# PLEASE DO NOT EDIT THIS FILE! +# IT WILL MAKE YOUR CHIP UNMANUFACTURABLE +# The only line you may edit is FP_CORE_UTIL +# (may benefit from reducing it slightly) + +# User config +set script_dir [file dirname [file normalize [info script]]] + +# read some user config that is written by the setup.py program. +# - the name of the module is defined +# - the list of source files +source $::env(DESIGN_DIR)/user_config.tcl + +# save some time +set ::env(RUN_KLAYOUT_XOR) 0 +set ::env(RUN_KLAYOUT_DRC) 0 + +# don't put clock buffers on the outputs +set ::env(PL_RESIZER_BUFFER_OUTPUT_PORTS) 0 + +# allow use of specific sky130 cells +set ::env(SYNTH_READ_BLACKBOX_LIB) 1 + +# put all the pins on the left +set ::env(FP_PIN_ORDER_CFG) $::env(DESIGN_DIR)/pin_order.cfg + +# reduce wasted space +set ::env(TOP_MARGIN_MULT) 2 +set ::env(BOTTOM_MARGIN_MULT) 2 + +# absolute die size +set ::env(FP_SIZING) absolute +set ::env(DIE_AREA) "0 0 280 280" + +## THIS IS THE ONLY LINE YOU CAN EDIT +set ::env(FP_CORE_UTIL) 45 + +## set ::env(PL_BASIC_PLACEMENT) {1} + +set ::env(FP_IO_HLENGTH) 2 +set ::env(FP_IO_VLENGTH) 2 + +# use alternative efabless decap cells to solve LI density issue +set ::env(DECAP_CELL) "\ + sky130_fd_sc_hd__decap_3 \ + sky130_fd_sc_hd__decap_4 \ + sky130_fd_sc_hd__decap_6 \ + sky130_fd_sc_hd__decap_8 \ + sky130_ef_sc_hd__decap_12" + +# clock +set ::env(CLOCK_TREE_SYNTH) 1 + +# period is in ns, so 500ns == 2 MHz +set ::env(CLOCK_PERIOD) "500" +set ::env(CLOCK_PORT) {io_in[12]} + +# hold/slack margin +# set ::env(PL_RESIZER_HOLD_SLACK_MARGIN) 0.8 +# set ::env(GLB_RESIZER_HOLD_SLACK_MARGIN) 0.8 + +# don't use power rings or met5 +set ::env(DESIGN_IS_CORE) 0 +set ::env(RT_MAX_LAYER) {met4} + +# connect to first digital rails +set ::env(VDD_NETS) [list {vccd1}] +set ::env(GND_NETS) [list {vssd1}] diff --git a/designs/d18_nikhildj_mac/src/decoder.v b/designs/d18_nikhildj_mac/src/decoder.v new file mode 100644 index 0000000..8d6310e --- /dev/null +++ b/designs/d18_nikhildj_mac/src/decoder.v @@ -0,0 +1,38 @@ + +/* + -- 1 -- + | | + 6 2 + | | + -- 7 -- + | | + 5 3 + | | + -- 4 -- +*/ + +module seg7 ( + input wire [3:0] counter, + output reg [6:0] segments +); + + always @(*) begin + case(counter) + // 7654321 + 0: segments = 7'b0111111; + 1: segments = 7'b0000110; + 2: segments = 7'b1011011; + 3: segments = 7'b1001111; + 4: segments = 7'b1100110; + 5: segments = 7'b1101101; + 6: segments = 7'b1111100; + 7: segments = 7'b0000111; + 8: segments = 7'b1111111; + 9: segments = 7'b1100111; + default: + segments = 7'b0000000; + endcase + end + +endmodule + diff --git a/designs/d18_nikhildj_mac/src/fulladder.sv b/designs/d18_nikhildj_mac/src/fulladder.sv new file mode 100644 index 0000000..f534b07 --- /dev/null +++ b/designs/d18_nikhildj_mac/src/fulladder.sv @@ -0,0 +1,14 @@ +module fulladder( +input a,b,carry_in, +output sum, carry_out + +); + + wire w1,w2,w3; + + assign w1 = a ^ b; + assign sum = w1 ^ carry_in; + assign w2 = a&b; + assign w3 = w1 & carry_in; + assign carry_out = w2 | w3; +endmodule \ No newline at end of file diff --git a/designs/d18_nikhildj_mac/src/mac_controller.sv b/designs/d18_nikhildj_mac/src/mac_controller.sv new file mode 100644 index 0000000..c0a6e70 --- /dev/null +++ b/designs/d18_nikhildj_mac/src/mac_controller.sv @@ -0,0 +1,72 @@ +module CONTROLLER_MAC ( + input logic reset, + input logic clk, + input logic START, + input logic End_mul, + output logic Finish, + output logic RESET_cmd, + output logic Load_op, + output logic Begin_mul, + output logic add +); + + logic [3:0] temp_count; + enum logic [2:0] {IDLE, INIT, LOAD, RUN, TEST, ADD} state; + + always_ff @(posedge clk or negedge reset) begin + if (!reset) begin + state <= IDLE; + temp_count <= 4'b1001; + end + else begin + case (state) + IDLE: begin + if (START) begin + state <= INIT; + end + else begin + state <= IDLE; + end + end + INIT: begin + state <= LOAD; + end + LOAD: begin + state <= RUN; + end + RUN: begin + state <= TEST; + end + TEST: begin + if (!End_mul) begin + state <= TEST; + end + else begin + state <= ADD; + end + end + ADD: begin + if (temp_count == 4'b0000) begin + temp_count <= 4'b1001; + state <= IDLE; + end + else begin + temp_count <= temp_count - 1; + state <= LOAD; + end + end + default: begin + state <= IDLE; + end + endcase + end + end + + assign Finish = (state == IDLE); + assign Load_op = (state == LOAD); + assign Begin_mul = (state == RUN); + assign add = (state == ADD); + assign RESET_cmd = (state == INIT || reset == 1'b0) ? 1'b0 : 1'b1; + +endmodule + diff --git a/designs/d18_nikhildj_mac/src/multiplicand.sv b/designs/d18_nikhildj_mac/src/multiplicand.sv new file mode 100644 index 0000000..5accf52 --- /dev/null +++ b/designs/d18_nikhildj_mac/src/multiplicand.sv @@ -0,0 +1,18 @@ +module multiplicand ( + input logic [7:0]a_in, + input logic Load_mul, + input logic reset, + output logic [7:0]a_out + +); + + +register8 r1 ( + + .reset(reset), + .Load_op(Load_mul), + .in(a_in), + .out(a_out) +); +endmodule + diff --git a/designs/d18_nikhildj_mac/src/multiplier.sv b/designs/d18_nikhildj_mac/src/multiplier.sv new file mode 100644 index 0000000..23c19d7 --- /dev/null +++ b/designs/d18_nikhildj_mac/src/multiplier.sv @@ -0,0 +1,51 @@ +module MULTIPLIER_RESULT ( + input logic reset, + input logic clk, + input logic [7:0] b_in, + input logic Load_mul, + input logic do_shift, + input logic do_add, + input logic [7:0] sum_out, + input logic carry_out, + output logic [15:0] mult_out, + output logic LSB, + output logic [7:0] b_out +); + + logic [16:0] temp_register; + logic temp_Add; + + always_ff @(posedge clk or negedge reset) begin + if (!reset) begin + temp_register <= '0; + temp_Add <= 1'b0; + end + else begin + if (Load_mul) begin + temp_register[16:8] <= '0; + temp_register[7:0] <= b_in; + end + else begin + if (do_add) begin + temp_Add <= 1'b1; + end + + if (do_shift) begin + if (temp_Add) begin + temp_Add <= 1'b0; + temp_register <= {1'b0, carry_out, sum_out, temp_register[7:1]}; + end + else begin + temp_register <= {1'b0, temp_register[16:1]}; + end + end + end + end + end + + assign b_out = temp_register[15:8]; + assign LSB = temp_register[0]; + assign mult_out = temp_register[15:0]; + +endmodule + diff --git a/designs/d18_nikhildj_mac/src/multiplier_controller.sv b/designs/d18_nikhildj_mac/src/multiplier_controller.sv new file mode 100644 index 0000000..8764159 --- /dev/null +++ b/designs/d18_nikhildj_mac/src/multiplier_controller.sv @@ -0,0 +1,66 @@ +module CONTROLLER ( + input logic reset, + input logic clk, + input logic Begin_mul, + input logic LSB, + output logic do_add, + output logic do_shift, + output logic Load_mul, + output logic End_mul +); + + logic [2:0] temp_count; + enum logic [3:0] {IDLE, INIT, TEST, ADD, SHIFT} state; + + always_ff @(posedge clk or negedge reset) begin + if (!reset) begin + state <= IDLE; + temp_count <= 3'b000; + end + else begin + case (state) + IDLE: begin + if (Begin_mul) begin + state <= INIT; + end + else begin + state <= IDLE; + end + end + INIT: begin + state <= TEST; + end + TEST: begin + if (!LSB) begin + state <= SHIFT; + end + else begin + state <= ADD; + end + end + ADD: begin + state <= SHIFT; + end + SHIFT: begin + if (temp_count == 3'b111) begin + temp_count <= 3'b000; + state <= IDLE; + end + else begin + temp_count <= temp_count + 1; + state <= TEST; + end + end + default: begin + state <= IDLE; + end + endcase + end + end + + assign End_mul = (state == IDLE); + assign do_add = (state == ADD); + assign do_shift = (state == SHIFT); + assign Load_mul = (state == INIT); +endmodule + diff --git a/designs/d18_nikhildj_mac/src/pin_order.cfg b/designs/d18_nikhildj_mac/src/pin_order.cfg new file mode 100644 index 0000000..0b85c63 --- /dev/null +++ b/designs/d18_nikhildj_mac/src/pin_order.cfg @@ -0,0 +1,9 @@ +#N + +#S + +#E + +#W +io_in.* +io_out.* diff --git a/designs/d18_nikhildj_mac/src/register20.sv b/designs/d18_nikhildj_mac/src/register20.sv new file mode 100644 index 0000000..10812f5 --- /dev/null +++ b/designs/d18_nikhildj_mac/src/register20.sv @@ -0,0 +1,27 @@ +module register20( + input logic [19:0]in, + input logic add, + input logic reset, + output logic [19:0]out + +); + +logic [19:0] temp_out; + +genvar i; + +generate + for (i=0; i<20; i=i+1 ) begin : dff_gen + DFF d2 ( + .reset(reset), + .clk(add), + .D(in[i]), + .Q(temp_out[i]) + ); + end + +endgenerate + +assign out = temp_out; + +endmodule diff --git a/designs/d18_nikhildj_mac/src/register8.sv b/designs/d18_nikhildj_mac/src/register8.sv new file mode 100644 index 0000000..57f0880 --- /dev/null +++ b/designs/d18_nikhildj_mac/src/register8.sv @@ -0,0 +1,27 @@ +module register8( + input logic [7:0]in, + input logic Load_op, + input logic reset, + output logic [7:0]out + +); + +logic [7:0] temp_out; + +genvar i; + +generate + for (i=0; i<8; i=i+1 ) begin : dff_gen + DFF d1 ( + .reset(reset), + .clk(Load_op), + .D(in[i]), + .Q(temp_out[i]) + ); + end + +endgenerate + +assign out = temp_out; + +endmodule diff --git a/designs/d18_nikhildj_mac/src/ripple_carry_adder.sv b/designs/d18_nikhildj_mac/src/ripple_carry_adder.sv new file mode 100644 index 0000000..c4161eb --- /dev/null +++ b/designs/d18_nikhildj_mac/src/ripple_carry_adder.sv @@ -0,0 +1,15 @@ +module ripple_carry_adder ( + input logic [3:0] a, + input logic [3:0] b, + input logic carry_in, + output logic [3:0] sum, + output logic carry_out +); + + wire w1, w2, w3; + fulladder fa0(a[0], b[0], carry_in, sum[0],w1); + fulladder fa1(a[1], b[1], w1, sum[1], w2); + fulladder fa2(a[2], b[2], w2, sum[2], w3); + fulladder fa3(a[3], b[3], w3, sum[3], carry_out); + +endmodule \ No newline at end of file diff --git a/designs/d18_nikhildj_mac/src/top_multiplier.sv b/designs/d18_nikhildj_mac/src/top_multiplier.sv new file mode 100644 index 0000000..5737fab --- /dev/null +++ b/designs/d18_nikhildj_mac/src/top_multiplier.sv @@ -0,0 +1,70 @@ +module top_multiplier ( + input logic [7:0] a_in, + input logic [7:0] b_in, + input logic reset, + input logic clk, + input logic Begin_mul, + output logic [15:0] mult_out, + output logic End_mul + +); +logic do_add; +logic do_shift; +logic LSB; +logic Load_mul; +logic [7:0] sum_out; +logic carry_out; +logic [7:0] b_out; +logic [7:0]a_out; + + + + + + +CONTROLLER i0 ( + .reset(reset), + .clk(clk), + .Begin_mul(Begin_mul), + .LSB(LSB), + .do_add(do_add), + .do_shift(do_shift), + .Load_mul(Load_mul), + .End_mul(End_mul) + +); + +multiplicand i1 ( + .a_in(a_in), + .Load_mul(Load_mul), + + .reset(reset), + .a_out(a_out) +); + +carry_select8 i2 ( + .a(a_out), + .b(b_out), + .carry_in(1'b0), + .sum(sum_out), + .carry_out(carry_out) +); + +MULTIPLIER_RESULT i3 ( + .reset(reset), + .clk(clk), + .b_in(b_in), + .Load_mul(Load_mul), + .do_shift(do_shift), + .do_add(do_add), + .sum_out(sum_out), + .carry_out(carry_out), + .mult_out(mult_out), + .LSB(LSB), + .b_out(b_out) + +); + +endmodule + + diff --git a/designs/d18_nikhildj_mac/src/toplevel_chip.v b/designs/d18_nikhildj_mac/src/toplevel_chip.v new file mode 100644 index 0000000..a82b427 --- /dev/null +++ b/designs/d18_nikhildj_mac/src/toplevel_chip.v @@ -0,0 +1,18 @@ +`default_nettype none + +// DO NOT EDIT THIS FILE +module toplevel_chip ( + input [13:0] io_in, + output [13:0] io_out +); + + my_chip mchip ( + .io_in(io_in[11:0]), + .io_out(io_out[11:0]), + .clock(io_in[12]), + .reset(io_in[13]) + ); + + assign io_out[13:12] = 2'b00; + +endmodule diff --git a/designs/d19_rdkapur_encryptor/.lastupdated b/designs/d19_rdkapur_encryptor/.lastupdated new file mode 100644 index 0000000..4d7b8c3 --- /dev/null +++ b/designs/d19_rdkapur_encryptor/.lastupdated @@ -0,0 +1 @@ +2023-05-14 diff --git a/designs/d19_rdkapur_encryptor/LICENSE b/designs/d19_rdkapur_encryptor/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/designs/d19_rdkapur_encryptor/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/designs/d19_rdkapur_encryptor/README.md b/designs/d19_rdkapur_encryptor/README.md new file mode 100644 index 0000000..7186ac0 --- /dev/null +++ b/designs/d19_rdkapur_encryptor/README.md @@ -0,0 +1,30 @@ +# NoFish + +Roman Kapur +18-224/624 Spring 2023 Final Tapeout Project + +## Overview + +Cryptographic accelator for a example algorithem. The algorithem uses substitution boxes and was an intro to cryptography for myself, loosely based off blowfish. Key and word size are both limited to 16 bits. Entry to key and intxt register are SIPO interfaces. Output is single hexadecimal value from one of 4 16 bit types (key, intxt, decrypt intext, encrypt intext) + +## How it Works + +Combinational calculation of sbox and P keys done through xor. + +## Inputs/Outputs + +2 bit input - mode select +4 bit input - hexidecimal output select +1 bit input - 0/1 for key/intxt entry +1 bit input - key ready, this tells selected SIPO register to shift in a bit + +8 bits of output for 7 segment display + +## Hardware Peripherals + +Dip switches to control input +7 Segment display output + +## Design Testing / Bringup + +Inputting a key of BEEF and intxt of BEEF will produce the out text of 6301 diff --git a/designs/d19_rdkapur_encryptor/info.yaml b/designs/d19_rdkapur_encryptor/info.yaml new file mode 100644 index 0000000..b106438 --- /dev/null +++ b/designs/d19_rdkapur_encryptor/info.yaml @@ -0,0 +1,7 @@ +--- +project: + source_files: + - toplevel_chip.v + - chip.sv + - coding.sv + top_module: "toplevel_chip" diff --git a/designs/d19_rdkapur_encryptor/src/chip.sv b/designs/d19_rdkapur_encryptor/src/chip.sv new file mode 100644 index 0000000..d0a0793 --- /dev/null +++ b/designs/d19_rdkapur_encryptor/src/chip.sv @@ -0,0 +1,12 @@ +`default_nettype none +module my_chip ( + input logic [11:0] io_in, // Inputs to your chip + output logic [11:0] io_out, // Outputs from your chip + input logic clock, + input logic reset // Important: Reset is ACTIVE-HIGH +); + + mychip_wrapper wrapper (.mode_sel(io_in[1:0]),.display_sel(io_in[5:2]),.in_bit(io_in[6]),.ready(io_in[7]), .hex_out(io_out[7:0]), .clock(clock), .reset(reset)); + assign io_out [11:8] = 4'b0000; + +endmodule diff --git a/designs/d19_rdkapur_encryptor/src/coding.sv b/designs/d19_rdkapur_encryptor/src/coding.sv new file mode 100644 index 0000000..82d98a7 --- /dev/null +++ b/designs/d19_rdkapur_encryptor/src/coding.sv @@ -0,0 +1,469 @@ +`default_nettype none + +module mychip_wrapper( + input logic [1:0] mode_sel, + input logic [3:0] display_sel, + input logic in_bit, + input logic ready, + input logic clock, + input logic reset, + + output logic [7:0] hex_out +); + + logic [15:0] key; + logic [15:0] intxt; + logic [15:0] outtxt_de, outtxt; + + logic key_en, intxt_en; + logic key_load, intxt_load; + + logic FSMen; + //Key Register + ShiftRegister_SIPO #(16) keyReg(.serial(in_bit), .en(key_en & FSMen), .left(1'b1), .clock(clock), .Q(key)); + + //intxt Register + ShiftRegister_SIPO #(16) intxtReg(.serial(in_bit), .en(intxt_en & FSMen), .left(1'b1), .clock(clock), .Q(intxt)); + + decrypt de(.intxt(intxt), .KEY(key), .outputtxt(outtxt)); + encrypt en(.intxt(intxt), .KEY(key), .outputtxt(outtxt_de)); + + //take bit FSM + enum logic {IDLE = 1'b1, TAKE = 1'b0} currState, nextState; + //nextState assignment + always_comb begin + case(currState) + IDLE: nextState = ready ? TAKE : IDLE; + TAKE: nextState = ready ? TAKE : IDLE; + default: nextState = IDLE; + endcase + end + + //control point assignment + always_comb begin + case(currState) + IDLE: FSMen = ready; + TAKE: FSMen = 1'b0; + endcase + end + + always_ff @(posedge clock) begin + if(reset) + currState <= IDLE; + else + currState <= nextState; + end + + //mode select + always_comb begin + case (mode_sel) + 2'b01: begin + key_en = 1'b1; + intxt_en = 1'b0; + end + 2'b10: begin + key_en = 1'b0; + intxt_en = 1'b1; + end + default: begin + key_en = 1'b0; + intxt_en = 1'b0; + end + endcase + end + + + //FSM for inputting + + + logic [7:0] intxt_hex1, intxt_hex2, intxt_hex3, intxt_hex4; + logic [7:0] key_hex1, key_hex2, key_hex3, key_hex4; + logic [7:0] outtxt_hex1, outtxt_hex2, outtxt_hex3, outtxt_hex4; + logic [7:0] outtxt_de_hex1, outtxt_de_hex2, outtxt_de_hex3, outtxt_de_hex4; + + //hex assignment + hex_to_sevenseg i1(intxt[3:0], intxt_hex1), + i2(intxt[7:4], intxt_hex2), + i3(intxt[11:8], intxt_hex3), + i4(intxt[15:12], intxt_hex4), + i5(key[3:0], key_hex1), + i6(key[7:4], key_hex2), + i7(key[11:8], key_hex3), + i8(key[15:12], key_hex4), + i9(outtxt[3:0], outtxt_hex1), + i10(outtxt[7:4], outtxt_hex2), + i11(outtxt[11:8], outtxt_hex3), + i12(outtxt[15:12], outtxt_hex4), + i13(outtxt_de[3:0], outtxt_de_hex1), + i14(outtxt_de[7:4], outtxt_de_hex2), + i15(outtxt_de[11:8], outtxt_de_hex3), + i16(outtxt_de[15:12], outtxt_de_hex4); + + + //assign hex output + always_comb begin + case(display_sel) + //intxt display + 4'b0000: hex_out = intxt_hex1; + 4'b0001: hex_out = intxt_hex2; + 4'b0010: hex_out = intxt_hex3; + 4'b0011: hex_out = intxt_hex4; + //key display + 4'b0100: hex_out = key_hex1; + 4'b0101: hex_out = key_hex2; + 4'b0110: hex_out = key_hex3; + 4'b0111: hex_out = key_hex4; + //outxt display + 4'b1000: hex_out = outtxt_hex1; + 4'b1001: hex_out = outtxt_hex2; + 4'b1010: hex_out = outtxt_hex3; + 4'b1011: hex_out = outtxt_hex4; + //decrypt out display + 4'b1100: hex_out = outtxt_de_hex1; + 4'b1101: hex_out = outtxt_de_hex2; + 4'b1110: hex_out = outtxt_de_hex3; + 4'b1111: hex_out = outtxt_de_hex4; + endcase + end + +endmodule : mychip_wrapper + +module hex_to_sevenseg ( + input logic [3:0] hexdigit, + output logic [7:0] seg +); + + always_comb begin + seg = '1; + if (hexdigit == 4'h0) seg = 8'b1100_0000; + if (hexdigit == 4'h1) seg = 8'b1111_1001; + if (hexdigit == 4'h2) seg = 8'b1010_0100; + if (hexdigit == 4'h3) seg = 8'b1011_0000; + if (hexdigit == 4'h4) seg = 8'b1001_1001; + if (hexdigit == 4'h5) seg = 8'b1001_0010; + if (hexdigit == 4'h6) seg = 8'b1000_0010; + if (hexdigit == 4'h7) seg = 8'b1111_1000; + if (hexdigit == 4'h8) seg = 8'b1000_0000; + if (hexdigit == 4'h9) seg = 8'b1001_0000; + if (hexdigit == 4'hA) seg = 8'b1000_1000; + if (hexdigit == 4'hB) seg = 8'b1000_0011; + if (hexdigit == 4'hC) seg = 8'b1100_0110; + if (hexdigit == 4'hD) seg = 8'b1010_0001; + if (hexdigit == 4'hE) seg = 8'b1000_0110; + if (hexdigit == 4'hF) seg = 8'b1000_1110; + end + +endmodule + + +module encrypt( + input logic [15:0] intxt, + input logic [15:0] KEY, + output logic[15:0] outputtxt +); + + logic [7:0] P1, P2, P3, P4, P5, P6, P7, P8; + logic [7:0] p1start, p2start, p3start, p4start, p5start, p6start, p7start, p8start; + + assign p1start = 8'b0010_0100; + assign p2start = 8'b0011_1111; + assign p3start = 8'b0110_1010; + assign p4start = 8'b1000_1000; + assign p5start = 8'b1000_0101; + assign p6start = 8'b1010_0011; + assign p7start = 8'b0000_1000; + assign p8start = 8'b1101_0011; + + //Set P keys + always_comb begin + P1 = p1start ^ KEY [7:0]; + P2 = p2start ^ KEY [15:8] ^ P1; + P3 = p3start ^ KEY [7:0] ^ P2; + P4 = p4start ^ KEY [15:8] ^ P3; + P5 = p5start ^ KEY [7:0] ^ P4; + P6 = p6start ^ KEY [15:8] ^ P5; + P7 = p7start ^ KEY [7:0] ^ P6; + P8 = p8start ^ KEY [15:8] ^ P7; + end + + logic [7:0] s11, s12, s13, s14, s21, s22, s23, s24, s31, s32, s33, s34, s41, s42, s43, s44; + //Set S Boxes + always_comb begin + s11 = 8'b0001_0011 ^ KEY [7:0]; + s12 = 8'b0001_1001 ^ KEY [15:8] ^ s11; + s13 = 8'b1000_1010 ^ KEY [7:0] ^ s12; + s14 = 8'b1000_1010 ^ KEY [15:8] ^ s13; + + s21 = 8'b0000_0011 ^ KEY [7:0] ^ s14; + s22 = 8'b0111_0000 ^ KEY [15:8] ^ s21; + s23 = KEY [7:0] ^ s22 ^ 8'b0111_0011; + s24 = KEY [15:8] ^ s23 ^ 8'b0100_0100; + + s31 = KEY [7:0] ^ s24 ^ 8'b1010_0100; + s32 = KEY [15:8] ^ s31 ^ 8'b0000_1001; + s33 = KEY [7:0] ^ s32 ^ 8'b0011_1000; + s34 = KEY [15:8] ^ s33 ^ 8'b0010_0010; + + s41 = KEY [7:0] ^ s34 ^ 8'b0010_1001; + s42 = KEY [15:8] ^ s41 ^ 8'b1001_1111; + s43 = KEY [7:0] ^ s42 ^ 8'b0011_0001; + s44 = KEY [15:8] ^ s43 ^ 8'b1101_0000; + + end + + //Set output + logic [15:0] temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8; + + + + //s box selection + logic [7:0] sub11, sub12, sub13, sub14, sub21, sub22, sub23, sub24, sub31, sub32, sub33, sub34, sub41, sub42, sub43, sub44, sub51, sub52, sub53, sub54, sub61, sub62, sub63, sub64, sub71, sub72, sub73, sub74, sub81, sub82, sub83, sub84; + + Mux41 sub1(intxt[15:14], s11, s12, s13, s14, sub11), + sub2(intxt[13:12], s21, s22, s23, s24, sub12), + sub3(intxt[11:10], s31, s32, s33, s34, sub13), + sub4(intxt[9:8], s41, s42, s43, s44, sub14), + + sub5(temp1[15:14], s11, s12, s13, s14, sub21), + sub6(temp1[13:12], s21, s22, s23, s24, sub22), + sub7(temp1[11:10], s31, s32, s33, s34, sub23), + sub8(temp1[9:8], s41, s42, s43, s44, sub24), + + sub9(temp2[15:14], s11, s12, s13, s14, sub31), + sub10(temp2[13:12], s21, s22, s23, s24, sub32), + sub15(temp2[11:10], s31, s32, s33, s34, sub33), + sub16(temp2[9:8], s41, s42, s43, s44, sub34), + + sub17(temp3[15:14], s11, s12, s13, s14, sub41), + sub18(temp3[13:12], s21, s22, s23, s24, sub42), + sub19(temp3[11:10], s31, s32, s33, s34, sub43), + sub20(temp3[9:8], s41, s42, s43, s44, sub44), + + sub25(temp4[15:14], s11, s12, s13, s14, sub51), + sub26(temp4[13:12], s21, s22, s23, s24, sub52), + sub27(temp4[11:10], s31, s32, s33, s34, sub53), + sub28(temp4[9:8], s41, s42, s43, s44, sub54), + + sub29(temp5[15:14], s11, s12, s13, s14, sub61), + sub30(temp5[13:12], s21, s22, s23, s24, sub62), + sub35(temp5[11:10], s31, s32, s33, s34, sub63), + sub36(temp5[9:8], s41, s42, s43, s44, sub64), + + sub37(temp6[15:14], s11, s12, s13, s14, sub71), + sub38(temp6[13:12], s21, s22, s23, s24, sub72), + sub39(temp6[11:10], s31, s32, s33, s34, sub73), + sub40(temp6[9:8], s41, s42, s43, s44, sub74), + + sub45(temp7[15:14], s11, s12, s13, s14, sub81), + sub46(temp7[13:12], s21, s22, s23, s24, sub82), + sub47(temp7[11:10], s31, s32, s33, s34, sub83), + sub48(temp7[9:8], s41, s42, s43, s44, sub84); + + always_comb begin + temp1 = {(sub11^sub12^sub13^sub14)^intxt[7:0], intxt[15:8]} ^ {P1, P2}; + temp2 = {(sub21^sub22^sub23^sub24)^temp1[7:0], temp1[15:8]} ^ {P3, P4}; + temp3 = {(sub31^sub32^sub33^sub34)^temp2[7:0], temp2[15:8]} ^ {P5, P6}; + temp4 = {(sub41^sub42^sub43^sub44)^temp3[7:0], temp3[15:8]} ^ {P7, P8}; + temp5 = {(sub51^sub52^sub53^sub54)^temp4[7:0], temp4[15:8]} ^ {P1, P2}; + temp6 = {(sub61^sub62^sub63^sub64)^temp5[7:0], temp5[15:8]} ^ {P3, P4}; + temp7 = {(sub71^sub72^sub73^sub74)^temp6[7:0], temp6[15:8]} ^ {P5, P6}; + temp8 = {(sub81^sub82^sub83^sub84)^temp7[7:0], temp7[15:8]} ^ {P7, P8}; + outputtxt = temp8; + end + +endmodule : encrypt + + + + + + + + + + + + +module decrypt( + input logic [15:0] intxt, + input logic [15:0] KEY, + output logic[15:0] outputtxt +); + + logic [7:0] P1, P2, P3, P4, P5, P6, P7, P8; + logic [7:0] p1start, p2start, p3start, p4start, p5start, p6start, p7start, p8start; + + assign p1start = 8'b0010_0100; + assign p2start = 8'b0011_1111; + assign p3start = 8'b0110_1010; + assign p4start = 8'b1000_1000; + assign p5start = 8'b1000_0101; + assign p6start = 8'b1010_0011; + assign p7start = 8'b0000_1000; + assign p8start = 8'b1101_0011; + + //Set P keys + always_comb begin + P1 = p1start ^ KEY [7:0]; + P2 = p2start ^ KEY [15:8] ^ P1; + P3 = p3start ^ KEY [7:0] ^ P2; + P4 = p4start ^ KEY [15:8] ^ P3; + P5 = p5start ^ KEY [7:0] ^ P4; + P6 = p6start ^ KEY [15:8] ^ P5; + P7 = p7start ^ KEY [7:0] ^ P6; + P8 = p8start ^ KEY [15:8] ^ P7; + end + + logic [7:0] s11, s12, s13, s14, s21, s22, s23, s24, s31, s32, s33, s34, s41, s42, s43, s44; + //Set S Boxes + always_comb begin + s11 = 8'b0001_0011 ^ KEY [7:0]; + s12 = 8'b0001_1001 ^ KEY [15:8] ^ s11; + s13 = 8'b1000_1010 ^ KEY [7:0] ^ s12; + s14 = 8'b1000_1010 ^ KEY [15:8] ^ s13; + + s21 = 8'b0000_0011 ^ KEY [7:0] ^ s14; + s22 = 8'b0111_0000 ^ KEY [15:8] ^ s21; + s23 = KEY [7:0] ^ s22 ^ 8'b0111_0011; + s24 = KEY [15:8] ^ s23 ^ 8'b0100_0100; + + s31 = KEY [7:0] ^ s24 ^ 8'b1010_0100; + s32 = KEY [15:8] ^ s31 ^ 8'b0000_1001; + s33 = KEY [7:0] ^ s32 ^ 8'b0011_1000; + s34 = KEY [15:8] ^ s33 ^ 8'b0010_0010; + + s41 = KEY [7:0] ^ s34 ^ 8'b0010_1001; + s42 = KEY [15:8] ^ s41 ^ 8'b1001_1111; + s43 = KEY [7:0] ^ s42 ^ 8'b0011_0001; + s44 = KEY [15:8] ^ s43 ^ 8'b1101_0000; + + end + + //Set output + logic [15:0] temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp11, temp12, temp; + logic [15:0] temp1int, temp2int, temp3int, temp4int, temp5int, temp6int, temp7int, temp8int; + logic [15:0] temp1int2, temp2int2, temp3int2, temp4int2, temp5int2, temp6int2, temp7int2, temp8int2; + + + //s box selection + logic [7:0] sub11, sub12, sub13, sub14, sub21, sub22, sub23, sub24, sub31, sub32, sub33, sub34, sub41, sub42, sub43, sub44, sub51, sub52, sub53, sub54, sub61, sub62, sub63, sub64, sub71, sub72, sub73, sub74, sub81, sub82, sub83, sub84; + + Mux41 sub1(temp1int[7:6], s11, s12, s13, s14, sub11), + sub2(temp1int[5:4], s21, s22, s23, s24, sub12), + sub3(temp1int[3:2], s31, s32, s33, s34, sub13), + sub4(temp1int[1:0], s41, s42, s43, s44, sub14), + + sub5(temp2int[7:6], s11, s12, s13, s14, sub21), + sub6(temp2int[5:4], s21, s22, s23, s24, sub22), + sub7(temp2int[3:2], s31, s32, s33, s34, sub23), + sub8(temp2int[1:0], s41, s42, s43, s44, sub24), + + sub9(temp3int[7:6], s11, s12, s13, s14, sub31), + sub10(temp3int[5:4], s21, s22, s23, s24, sub32), + sub15(temp3int[3:2], s31, s32, s33, s34, sub33), + sub16(temp3int[1:0], s41, s42, s43, s44, sub34), + + sub17(temp4int[7:6], s11, s12, s13, s14, sub41), + sub18(temp4int[5:4], s21, s22, s23, s24, sub42), + sub19(temp4int[3:2], s31, s32, s33, s34, sub43), + sub20(temp4int[1:0], s41, s42, s43, s44, sub44), + + sub25(temp5int[7:6], s11, s12, s13, s14, sub51), + sub26(temp5int[5:4], s21, s22, s23, s24, sub52), + sub27(temp5int[3:2], s31, s32, s33, s34, sub53), + sub28(temp5int[1:0], s41, s42, s43, s44, sub54), + + sub29(temp6int[7:6], s11, s12, s13, s14, sub61), + sub30(temp6int[5:4], s21, s22, s23, s24, sub62), + sub35(temp6int[3:2], s31, s32, s33, s34, sub63), + sub36(temp6int[1:0], s41, s42, s43, s44, sub64), + + sub37(temp7int[7:6], s11, s12, s13, s14, sub71), + sub38(temp7int[5:4], s21, s22, s23, s24, sub72), + sub39(temp7int[3:2], s31, s32, s33, s34, sub73), + sub40(temp7int[1:0], s41, s42, s43, s44, sub74), + + sub45(temp8int[7:6], s11, s12, s13, s14, sub81), + sub46(temp8int[5:4], s21, s22, s23, s24, sub82), + sub47(temp8int[3:2], s31, s32, s33, s34, sub83), + sub48(temp8int[1:0], s41, s42, s43, s44, sub84); + + always_comb begin + temp8 = intxt; + temp8int = temp8 ^ {P7,P8}; + temp8int2 = {temp8int[15:8]^sub84^sub83^sub82^sub81, temp8int[7:0]}; + + temp7 = {temp8int2[7:0], temp8int2[15:8]}; + temp7int = temp7 ^ {P5,P6}; + temp7int2 = {temp7int[15:8]^sub74^sub73^sub72^sub71, temp7int[7:0]}; + + temp6 = {temp7int2[7:0], temp7int2[15:8]}; + temp6int = temp6 ^ {P3, P4}; + temp6int2 = {temp6int[15:8]^sub64^sub63^sub62^sub61, temp6int[7:0]}; + + temp5 = {temp6int2[7:0], temp6int2[15:8]}; + temp5int = temp5 ^ {P1, P2}; + temp5int2 = {temp5int[15:8]^sub54^sub53^sub52^sub51, temp5int[7:0]}; + + + temp4 = {temp5int2[7:0], temp5int2[15:8]}; + temp4int = temp4 ^ {P7, P8}; + temp4int2 = {temp4int[15:8]^sub44^sub43^sub42^sub41, temp4int[7:0]}; + + + temp3 = {temp4int2[7:0], temp4int2[15:8]}; + temp3int = temp3 ^ {P5, P6}; + temp3int2 = {temp3int[15:8]^sub34^sub33^sub32^sub31, temp3int[7:0]}; + + + temp2 = {temp3int2[7:0], temp3int2[15:8]}; + temp2int = temp2 ^ {P3, P4}; + temp2int2 = {temp2int[15:8]^sub24^sub23^sub22^sub21, temp2int[7:0]}; + + + temp1 = {temp2int2[7:0], temp2int2[15:8]}; + temp1int = temp1 ^ {P1, P2}; + temp1int2 = {temp1int[15:8]^sub14^sub13^sub12^sub11, temp1int[7:0]}; + + outputtxt = {temp1int2[7:0], temp1int2[15:8]}; + + end + +endmodule : decrypt + + +module Mux41 + (input logic [1:0] sel, + input logic [7:0] s1, + input logic [7:0] s2, + input logic [7:0] s3, + input logic [7:0] s4, + + output logic [7:0] out); + + always_comb begin + case(sel) + 2'b00: out = s1; + 2'b01: out = s2; + 2'b10: out = s3; + 2'b11: out = s4; + endcase + end +endmodule : Mux41 + + // A SIPO Shift Register, with controllable shift direction +// Load has priority over shifting. +module ShiftRegister_SIPO + #(parameter WIDTH=8) + (input logic serial, + input logic en, left, clock, + output logic [WIDTH-1:0] Q); + + always_ff @(posedge clock) + if (en) + if (left) + Q <= {Q[WIDTH-2:0], serial}; + else + Q <= {serial, Q[WIDTH-1:1]}; + +endmodule : ShiftRegister_SIPO diff --git a/designs/d19_rdkapur_encryptor/src/config.tcl b/designs/d19_rdkapur_encryptor/src/config.tcl new file mode 100644 index 0000000..aa589e4 --- /dev/null +++ b/designs/d19_rdkapur_encryptor/src/config.tcl @@ -0,0 +1,68 @@ +# PLEASE DO NOT EDIT THIS FILE! +# IT WILL MAKE YOUR CHIP UNMANUFACTURABLE +# The only line you may edit is FP_CORE_UTIL +# (may benefit from reducing it slightly) + +# User config +set script_dir [file dirname [file normalize [info script]]] + +# read some user config that is written by the setup.py program. +# - the name of the module is defined +# - the list of source files +source $::env(DESIGN_DIR)/user_config.tcl + +# save some time +set ::env(RUN_KLAYOUT_XOR) 0 +set ::env(RUN_KLAYOUT_DRC) 0 + +# don't put clock buffers on the outputs +set ::env(PL_RESIZER_BUFFER_OUTPUT_PORTS) 0 + +# allow use of specific sky130 cells +set ::env(SYNTH_READ_BLACKBOX_LIB) 1 + +# put all the pins on the left +set ::env(FP_PIN_ORDER_CFG) $::env(DESIGN_DIR)/pin_order.cfg + +# reduce wasted space +set ::env(TOP_MARGIN_MULT) 2 +set ::env(BOTTOM_MARGIN_MULT) 2 + +# absolute die size +set ::env(FP_SIZING) absolute +set ::env(DIE_AREA) "0 0 280 280" + +## THIS IS THE ONLY LINE YOU CAN EDIT +set ::env(FP_CORE_UTIL) 45 + +## set ::env(PL_BASIC_PLACEMENT) {1} + +set ::env(FP_IO_HLENGTH) 2 +set ::env(FP_IO_VLENGTH) 2 + +# use alternative efabless decap cells to solve LI density issue +set ::env(DECAP_CELL) "\ + sky130_fd_sc_hd__decap_3 \ + sky130_fd_sc_hd__decap_4 \ + sky130_fd_sc_hd__decap_6 \ + sky130_fd_sc_hd__decap_8 \ + sky130_ef_sc_hd__decap_12" + +# clock +set ::env(CLOCK_TREE_SYNTH) 1 + +# period is in ns, so 500ns == 2 MHz +set ::env(CLOCK_PERIOD) "500" +set ::env(CLOCK_PORT) {io_in[12]} + +# hold/slack margin +# set ::env(PL_RESIZER_HOLD_SLACK_MARGIN) 0.8 +# set ::env(GLB_RESIZER_HOLD_SLACK_MARGIN) 0.8 + +# don't use power rings or met5 +set ::env(DESIGN_IS_CORE) 0 +set ::env(RT_MAX_LAYER) {met4} + +# connect to first digital rails +set ::env(VDD_NETS) [list {vccd1}] +set ::env(GND_NETS) [list {vssd1}] diff --git a/designs/d19_rdkapur_encryptor/src/pin_order.cfg b/designs/d19_rdkapur_encryptor/src/pin_order.cfg new file mode 100644 index 0000000..0b85c63 --- /dev/null +++ b/designs/d19_rdkapur_encryptor/src/pin_order.cfg @@ -0,0 +1,9 @@ +#N + +#S + +#E + +#W +io_in.* +io_out.* diff --git a/designs/d19_rdkapur_encryptor/src/toplevel_chip.v b/designs/d19_rdkapur_encryptor/src/toplevel_chip.v new file mode 100644 index 0000000..a82b427 --- /dev/null +++ b/designs/d19_rdkapur_encryptor/src/toplevel_chip.v @@ -0,0 +1,18 @@ +`default_nettype none + +// DO NOT EDIT THIS FILE +module toplevel_chip ( + input [13:0] io_in, + output [13:0] io_out +); + + my_chip mchip ( + .io_in(io_in[11:0]), + .io_out(io_out[11:0]), + .clock(io_in[12]), + .reset(io_in[13]) + ); + + assign io_out[13:12] = 2'b00; + +endmodule diff --git a/designs/d20_rashik_tetris/.lastupdated b/designs/d20_rashik_tetris/.lastupdated new file mode 100644 index 0000000..4d7b8c3 --- /dev/null +++ b/designs/d20_rashik_tetris/.lastupdated @@ -0,0 +1 @@ +2023-05-14 diff --git a/designs/d20_rashik_tetris/LICENSE b/designs/d20_rashik_tetris/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/designs/d20_rashik_tetris/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/designs/d20_rashik_tetris/README.md b/designs/d20_rashik_tetris/README.md new file mode 100644 index 0000000..a04c142 --- /dev/null +++ b/designs/d20_rashik_tetris/README.md @@ -0,0 +1,19 @@ +# Tetris + +Rashi Kejriwal +18-224/624 Spring 2023 Final Tapeout Project + +## Overview +A simplified implementation of Tetris in SystemVerilog. This will include a 8 x 16 matrix of 1 bit registers that will maintain the game state with pseudo-random tetromino generation, one direction rotation, and right (wrap around) movement. + +## How it Works +The Datapath will include the game state matrix. This will contain the pieces that have fallen and have collided with the board edges or with another piece. The game will wait for the start_game button to be pressed. Once this is pressed, the state will transition, and a random piece will appear on the top, right corner of the board. Then, state will transition again. The x and y position of one block of the piece will be maintained in registers and the random piece selected will also be saved in a register to obtain the location of the other blocks. Then the state will transition again, and the y position will increase based on the clock, and x and y based on the other inputs. Once the collision is detected which will be checked every cycle with the game state matrix the piece will update the matrix. Lastly, there will be a transition back to the falling piece state and this will continue until a collision with the top board has been detected and then the game will be over. When a row is cleared, the matrix will be shifted accordingly with logic. The FSM will have 5 states including Start, New Piece, Falling Piece, Collision, and Game Over. Each of these states will maintain how the game state matrix can be modified. + +## Inputs/Outputs +Inputs: Left, Right, Read_gs, Clock, Reset +Outputs: Game state + +## Hardware Peripherals +The external hardware peripherals are up to the user. The chip will output the Tetris game state 8 bits at a time. This +should be read serially by a microcontroller and then can be hooked up with any form of matrix display such as an LED matrix. + diff --git a/designs/d20_rashik_tetris/info.yaml b/designs/d20_rashik_tetris/info.yaml new file mode 100644 index 0000000..ca5aeac --- /dev/null +++ b/designs/d20_rashik_tetris/info.yaml @@ -0,0 +1,8 @@ +--- +project: + source_files: + - toplevel_chip.v + - chip.sv + - decoder.v + top_module: "toplevel_chip" + diff --git a/designs/d20_rashik_tetris/src/chip.sv b/designs/d20_rashik_tetris/src/chip.sv new file mode 100644 index 0000000..a0dce2d --- /dev/null +++ b/designs/d20_rashik_tetris/src/chip.sv @@ -0,0 +1,155 @@ +`default_nettype none + +module random_tetromino ( + input logic clk, reset, new_piece_en, + output logic [15:0] rand_piece); + + logic [2:0] rand_num; + logic [3:0] block0, block1, block2, block3; + assign rand_num = 0; + + always_comb begin + case (rand_num) + // I + 3'd0: begin + block0 = 4'b00_00; + block1 = 4'b01_00; + block2 = 4'b10_00; + block3 = 4'b11_00; + end + // O + 3'd1: begin + block0 = 4'b00_00; + block1 = 4'b01_00; + block2 = 4'b00_01; + block3 = 4'b01_01; + end + // T + 3'd2: begin + block0 = 4'b00_00; + block1 = 4'b01_00; + block2 = 4'b10_00; + block3 = 4'b01_01; + end + // J + 3'd3: begin + block0 = 4'b01_00; + block1 = 4'b01_01; + block2 = 4'b01_10; + block3 = 4'b00_01; + end + // L + 3'd4: begin + block0 = 4'b00_00; + block1 = 4'b00_01; + block2 = 4'b00_10; + block3 = 4'b01_10; + end + // S + 3'd5: begin + block0 = 4'b01_00; + block1 = 4'b10_00; + block2 = 4'b00_01; + block3 = 4'b01_01; + end + // Z + 3'd6: begin + block0 = 4'b00_00; + block1 = 4'b01_00; + block2 = 4'b01_01; + block3 = 4'b10_01; + end + default: begin + block0 = 4'b00_00; + block1 = 4'b00_00; + block2 = 4'b00_00; + block3 = 4'b00_00; + end + endcase + end + + always_ff @(posedge clk) + if (reset) begin + rand_piece = 16'd0; + end + else if (new_piece_en) + rand_piece <= {block0, block1, block2, block3}; + else + rand_piece <= rand_piece; + +endmodule: random_tetromino + +module my_chip ( + input logic [11:0] io_in, // Inputs to your chip + output logic [11:0] io_out, // Outputs from your chip + input logic clock, + input logic reset // Important: Reset is ACTIVE-HIGH +); + logic clk, read_gs, left, right; + assign {left, right, read_gs} = io_in[3:0]; + assign clk = clock; + + logic [127:0] game_state; + + // Control points + logic new_piece_en; + + logic [6:0] x; + logic [6:0] y; + logic [15:0] rand_piece; // each block of the teromino is [3:0], [7:4], [11:8], [15:12] + + // Generate random tetromino and update the the piece state of the falling tetromino + // random_tetromino (.clk, .reset, .new_piece_en, .rand_piece); + assign rand_piece = {4'b00_00, 4'b00_01, 4'b00_10, 4'b01_10}; + + logic [127:0] piece_state, fallen_state; + + always_comb begin + piece_state = 128'd0; + piece_state[(x + {5'd0, rand_piece[3:2]}) + ((y + {5'd0, rand_piece[1:0]}) << 3)] = 1'b1; + piece_state[(x + {5'd0, rand_piece[7:6]}) + ((y + {5'd0, rand_piece[5:4]}) << 3)] = 1'b1; + piece_state[(x + {5'd0, rand_piece[11:10]}) + ((y + {5'd0, rand_piece[9:8]}) << 3)] = 1'b1; + piece_state[(x + {5'd0, rand_piece[15:14]}) + ((y + {5'd0, rand_piece[13:12]}) << 3)] = 1'b1; + end + + // Collision detection + // Check bottom of the board + // logic collision; + // always_comb begin + // if (y == 7'd16) begin + // collision = 1'b1; + // end + // end + + // Fallen pieces register. When a collision occurs this is updated. + always_ff @(posedge clk) + if (reset) fallen_state <= 128'd0; + else fallen_state <= fallen_state; + + // Y position register. Y position is incremented on every clock edge. + always_ff @(posedge clk) + if (reset) y <= 7'd0; + else y <= y + 7'd1; + + // X position register. Update x position depending on left and right button inputs + always_ff @(posedge clk) + if (reset) x <= 4'd0; + else if (left) x <= x + 7'd1; + else if (right) x <= x - 7'd1; + else x <= x; + + assign game_state = fallen_state | piece_state; + + // Shift out + logic [6:0] idx; + logic [7:0] iout; + assign iout = game_state >> idx; + + always_ff @(posedge clk) + if (reset) idx <= 7'd0; + else if (read_gs) begin + io_out[8:0] <= iout; + idx <= idx + 7'd8; + end + +endmodule diff --git a/designs/d20_rashik_tetris/src/config.tcl b/designs/d20_rashik_tetris/src/config.tcl new file mode 100644 index 0000000..aa589e4 --- /dev/null +++ b/designs/d20_rashik_tetris/src/config.tcl @@ -0,0 +1,68 @@ +# PLEASE DO NOT EDIT THIS FILE! +# IT WILL MAKE YOUR CHIP UNMANUFACTURABLE +# The only line you may edit is FP_CORE_UTIL +# (may benefit from reducing it slightly) + +# User config +set script_dir [file dirname [file normalize [info script]]] + +# read some user config that is written by the setup.py program. +# - the name of the module is defined +# - the list of source files +source $::env(DESIGN_DIR)/user_config.tcl + +# save some time +set ::env(RUN_KLAYOUT_XOR) 0 +set ::env(RUN_KLAYOUT_DRC) 0 + +# don't put clock buffers on the outputs +set ::env(PL_RESIZER_BUFFER_OUTPUT_PORTS) 0 + +# allow use of specific sky130 cells +set ::env(SYNTH_READ_BLACKBOX_LIB) 1 + +# put all the pins on the left +set ::env(FP_PIN_ORDER_CFG) $::env(DESIGN_DIR)/pin_order.cfg + +# reduce wasted space +set ::env(TOP_MARGIN_MULT) 2 +set ::env(BOTTOM_MARGIN_MULT) 2 + +# absolute die size +set ::env(FP_SIZING) absolute +set ::env(DIE_AREA) "0 0 280 280" + +## THIS IS THE ONLY LINE YOU CAN EDIT +set ::env(FP_CORE_UTIL) 45 + +## set ::env(PL_BASIC_PLACEMENT) {1} + +set ::env(FP_IO_HLENGTH) 2 +set ::env(FP_IO_VLENGTH) 2 + +# use alternative efabless decap cells to solve LI density issue +set ::env(DECAP_CELL) "\ + sky130_fd_sc_hd__decap_3 \ + sky130_fd_sc_hd__decap_4 \ + sky130_fd_sc_hd__decap_6 \ + sky130_fd_sc_hd__decap_8 \ + sky130_ef_sc_hd__decap_12" + +# clock +set ::env(CLOCK_TREE_SYNTH) 1 + +# period is in ns, so 500ns == 2 MHz +set ::env(CLOCK_PERIOD) "500" +set ::env(CLOCK_PORT) {io_in[12]} + +# hold/slack margin +# set ::env(PL_RESIZER_HOLD_SLACK_MARGIN) 0.8 +# set ::env(GLB_RESIZER_HOLD_SLACK_MARGIN) 0.8 + +# don't use power rings or met5 +set ::env(DESIGN_IS_CORE) 0 +set ::env(RT_MAX_LAYER) {met4} + +# connect to first digital rails +set ::env(VDD_NETS) [list {vccd1}] +set ::env(GND_NETS) [list {vssd1}] diff --git a/designs/d20_rashik_tetris/src/decoder.v b/designs/d20_rashik_tetris/src/decoder.v new file mode 100644 index 0000000..8d6310e --- /dev/null +++ b/designs/d20_rashik_tetris/src/decoder.v @@ -0,0 +1,38 @@ + +/* + -- 1 -- + | | + 6 2 + | | + -- 7 -- + | | + 5 3 + | | + -- 4 -- +*/ + +module seg7 ( + input wire [3:0] counter, + output reg [6:0] segments +); + + always @(*) begin + case(counter) + // 7654321 + 0: segments = 7'b0111111; + 1: segments = 7'b0000110; + 2: segments = 7'b1011011; + 3: segments = 7'b1001111; + 4: segments = 7'b1100110; + 5: segments = 7'b1101101; + 6: segments = 7'b1111100; + 7: segments = 7'b0000111; + 8: segments = 7'b1111111; + 9: segments = 7'b1100111; + default: + segments = 7'b0000000; + endcase + end + +endmodule + diff --git a/designs/d20_rashik_tetris/src/pin_order.cfg b/designs/d20_rashik_tetris/src/pin_order.cfg new file mode 100644 index 0000000..0b85c63 --- /dev/null +++ b/designs/d20_rashik_tetris/src/pin_order.cfg @@ -0,0 +1,9 @@ +#N + +#S + +#E + +#W +io_in.* +io_out.* diff --git a/designs/d20_rashik_tetris/src/toplevel_chip.v b/designs/d20_rashik_tetris/src/toplevel_chip.v new file mode 100644 index 0000000..a82b427 --- /dev/null +++ b/designs/d20_rashik_tetris/src/toplevel_chip.v @@ -0,0 +1,18 @@ +`default_nettype none + +// DO NOT EDIT THIS FILE +module toplevel_chip ( + input [13:0] io_in, + output [13:0] io_out +); + + my_chip mchip ( + .io_in(io_in[11:0]), + .io_out(io_out[11:0]), + .clock(io_in[12]), + .reset(io_in[13]) + ); + + assign io_out[13:12] = 2'b00; + +endmodule diff --git a/designs/d21_varunk2_motorctrl/.lastupdated b/designs/d21_varunk2_motorctrl/.lastupdated new file mode 100644 index 0000000..4d7b8c3 --- /dev/null +++ b/designs/d21_varunk2_motorctrl/.lastupdated @@ -0,0 +1 @@ +2023-05-14 diff --git a/designs/d21_varunk2_motorctrl/CHIPIO.png b/designs/d21_varunk2_motorctrl/CHIPIO.png new file mode 100644 index 0000000..d3bf3cb Binary files /dev/null and b/designs/d21_varunk2_motorctrl/CHIPIO.png differ diff --git a/designs/d21_varunk2_motorctrl/LICENSE b/designs/d21_varunk2_motorctrl/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/designs/d21_varunk2_motorctrl/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/designs/d21_varunk2_motorctrl/PWM.jpg b/designs/d21_varunk2_motorctrl/PWM.jpg new file mode 100644 index 0000000..7cae19c Binary files /dev/null and b/designs/d21_varunk2_motorctrl/PWM.jpg differ diff --git a/designs/d21_varunk2_motorctrl/README.md b/designs/d21_varunk2_motorctrl/README.md new file mode 100644 index 0000000..3e884d9 --- /dev/null +++ b/designs/d21_varunk2_motorctrl/README.md @@ -0,0 +1,39 @@ +# CL_0000_MESIC: Motor Encoder and Servo/PWM Driver ASIC + +Varun Kumar's 18-224/624 Spring 2023 Final Tapeout Project + +## Overview: + +The CL_0000_MESIC is a Motor Encoder and PWM driver IC. It outputs PWM (Pulse Width Modulation) from 4 outputs, and takes in A and B inputs from a Quadrature Encoder to deliver speed and direction information about the currently operating motor. + +## The Internals: + +In order to save some inputs, every input is serial. On every clock cycle of the input microcontroller, each value on the serial lines is stored in a register, 8 bits for the servo and 16 bits for the general PWM. This register is constantly connected to the PWM output module, but only updates every time the register is "filled". The module ensures that the PWM output stays at HIGH for the appropriate amount of time, such that the receiving device operates as expected. + +For the quadrature encoded module, the system is much simpler. The module counts how many clock cycles in which A is HIGH and B is LOW and outputs this difference serially as it goes. For direction determination, depending on which wave sees a positive edge first, the module outputs a 1 or a 0. + +## Inputs/Outputs + +The Clock Speed of the CL_0000_MESIC is exactly 1 MHz, as the PWM outputs are determined on the basis of clock cycles. + +The I/O is pictured here: + +![](CHIPIO.png) + +## Hardware Peripherals + +In order to use the MESIC, have your desired hardware connected (Servo, DC Motor, or Encoder) and a 5V source for correct operation. + +## How to Work With the CL_0000_MESIC (Design Testing/Bringup): + +This chip is designed to be used in conjunction with a microcontroller. Ensure that whatever clock your microcontroller is using is connected to the SCL input of the chip; this way, no matter what the microcontroller's clock speed is, the chip will output what your system needs. + +All inputs are serial. In order to output something serially from a microcontroller, use the shiftOut function for Arduino. For servos, input a number corresponding to the extent of motion you desire serially, and the chip will output the appropriate PWM for the servo. In order to use general PWM, you must first input the period and the duty cycle of your desired wave, in terms of clock cycles. Keep in mind, the clock frequency of the chip is 1 MHz, so each clock cycle is 1 microsecond. + +For the encoder inputs, connect the A and B inputs to their respective inputs for a single motor. The chip will output the difference between the positive edges of the A and B signals serially from one of its outputs, and the direction that the motor is rotating as a 1 or a 0. + +## Media: + +CL_0000_MESIC outputting a 2 ms PWM Signal! + +![](PWM.jpg) diff --git a/designs/d21_varunk2_motorctrl/info.yaml b/designs/d21_varunk2_motorctrl/info.yaml new file mode 100644 index 0000000..ca5aeac --- /dev/null +++ b/designs/d21_varunk2_motorctrl/info.yaml @@ -0,0 +1,8 @@ +--- +project: + source_files: + - toplevel_chip.v + - chip.sv + - decoder.v + top_module: "toplevel_chip" + diff --git a/designs/d21_varunk2_motorctrl/src/chip.sv b/designs/d21_varunk2_motorctrl/src/chip.sv new file mode 100644 index 0000000..9129568 --- /dev/null +++ b/designs/d21_varunk2_motorctrl/src/chip.sv @@ -0,0 +1,172 @@ +/* CL_0000_MESIC: System Verilog Code for the Motor Encoder and Servo IC. + INPUTS: SCL: clock of microcontroller coming in. + PERIOD: 16-Bit Input, X*10^-6 seconds for period of PWM signal. + DUTY: 16-Bit Input, X*10^-6 seconds for duty cycle of PWM signal. + S_IN: 8-Bit Input, extent of servo's rotation; input 128 for + 1.5 ms duty cycle. + A: A Wave of Quadrature Motor Encoder + B: B Wave of Quadrature Motor Encoder + OUTPUTS: PWM for 2 servos, 2 general outputs. + Speed and direction output for two Motor Encoders.*/ +`default_nettype none + +module my_chip ( + input logic [11:0] io_in, // Inputs to your chip + output logic [11:0] io_out, // Outputs from your chip + input logic clock, + input logic reset // Important: Reset is ACTIVE-HIGH +); + general_pwm PWM_1 (.PWM_PERIOD (io_in[0]), .PWM_DUTY (io_in[1]), + .SCL (io_in[11]), .CLK (clock), .reset (reset), .M_OUT (io_out [0])); + general_pwm PWM_2 (.PWM_PERIOD (io_in[2]), .PWM_DUTY (io_in[3]), + .SCL (io_in[11]), .CLK (clock), .reset (reset), .M_OUT (io_out [1])); + servo_pwm SERVO_1 (.S_IN (io_in[4]), .SCL (io_in[11]), .CLK (clock), + .reset (reset), .S_OUT (io_out[2])); + servo_pwm SERVO_2 (.S_IN (io_in[5]), .SCL (io_in[11]), .CLK (clock), + .reset (reset), .S_OUT (io_out[3])); + decode_module DECODE_1 (.A (io_in[6]), .B (io_in[7]), .clock (clock), + .reset (reset), .p (io_out[4]), .dir (io_out[5])); + decode_module DECODE_2 (.A (io_in[8]), .B (io_in[9]), .clock (clock), + .reset (reset), .p (io_out[6]), .dir (io_out[7])); +endmodule +// General PWM Module, to get the PWM output. +module general_pwm (input logic PWM_PERIOD, + input logic PWM_DUTY, + input logic SCL, + input logic CLK, reset, + output logic M_OUT); + logic [15:0] period_reg, duty_reg, period, duty_cycle; + logic [4:0] twelve_count; + + logic last_in_clk, in_clk_rose; + assign in_clk_rose = (SCL && !last_in_clk); + + always_ff @(posedge CLK) begin + last_in_clk <= SCL; + if (reset) twelve_count <= 0; + else begin + if (in_clk_rose) begin + period_reg <= {period_reg[10:0], PWM_PERIOD}; + duty_reg <= {duty_reg[10:0], PWM_DUTY}; + end + if (twelve_count == 'd12) begin + period <= period_reg; + duty_cycle <= duty_reg; + twelve_count = 0; + end + else twelve_count = twelve_count + 1; + end + end + +endmodule + +// generates the PWM signals. +module general_pwm_generator ( + input logic clk, + input logic rst, + input logic [15:0] period, duty_cycle, + output logic pwm_out + ); + + logic [15:0] ctr_d; + always @(posedge clk) begin + if (rst) begin + ctr_d <= 1'b0; + pwm_out <= 1; + end else begin + if (ctr_d == period) begin + ctr_d = 0; + end + if (ctr_d < duty_cycle) + pwm_out <= 1; + else + pwm_out <= 0; + ctr_d = ctr_d + 1; + end + end + +endmodule + +// Takes in the clock of the servo and a number from 0 to 255 serially, +// then outputs a PWM signal +module servo_pwm (input logic S_IN, + input logic SCL, + input logic CLK, reset, + output logic S_OUT); + logic [7:0] shreg, position; + logic [3:0] eight_count; + // detect the rising edge of the clock, store values into shreg + logic last_in_clk, in_clk_rose; + assign in_clk_rose = (SCL && !last_in_clk); + + always_ff @(posedge CLK) begin + last_in_clk <= SCL; + if (reset) eight_count <= 0; + else begin + if (in_clk_rose) shreg <= {shreg[6:0], S_IN}; + if (eight_count == 'd8) begin + position <= shreg; + eight_count = 0; + end + else eight_count = eight_count + 1; + end + end + servo_pwm_generator pwm (.clk (CLK), .servo (S_OUT), .rst (reset), .*); +endmodule: servo_pwm + +// Takes a degree in parallel and outputs a PWM signal +module servo_pwm_generator ( + input clk, + input rst, + input [7:0] position, + output logic servo + ); + + reg pwm_d, pwm_q; + reg [19:0] ctr_d, ctr_q; + logic [19:0] temp_val; + assign temp_val = 1000 + (position << 2) - 12; + always_ff @(posedge clk) begin + if (rst) begin + ctr_d <= 1'b0; + end else begin + if (ctr_d == 20000) begin + ctr_d = 0; + end + if (ctr_d < (temp_val)) + servo <= 1; + else + servo <= 0; + ctr_d = ctr_d + 1; + end + end + +endmodule + +module decode_module (input logic A, B, clock, reset, + output logic p, dir); + + logic [5:0] diff_count; + logic A_prev, B_prev; + always @(posedge clock) begin + if (reset) begin + p <= 0; + dir <= 0; + end else begin + // Dir Calcs + if (A & ~A_prev & ~B) begin + dir <= 1; + end else if (B & ~B_prev & ~A) begin + dir <= 0; + end + + if (A & ~B) begin + p <= 1; + end else begin + p <= 0; + end + end + A_prev <= A; + B_prev <= B; + end +endmodule diff --git a/designs/d21_varunk2_motorctrl/src/config.tcl b/designs/d21_varunk2_motorctrl/src/config.tcl new file mode 100644 index 0000000..aa589e4 --- /dev/null +++ b/designs/d21_varunk2_motorctrl/src/config.tcl @@ -0,0 +1,68 @@ +# PLEASE DO NOT EDIT THIS FILE! +# IT WILL MAKE YOUR CHIP UNMANUFACTURABLE +# The only line you may edit is FP_CORE_UTIL +# (may benefit from reducing it slightly) + +# User config +set script_dir [file dirname [file normalize [info script]]] + +# read some user config that is written by the setup.py program. +# - the name of the module is defined +# - the list of source files +source $::env(DESIGN_DIR)/user_config.tcl + +# save some time +set ::env(RUN_KLAYOUT_XOR) 0 +set ::env(RUN_KLAYOUT_DRC) 0 + +# don't put clock buffers on the outputs +set ::env(PL_RESIZER_BUFFER_OUTPUT_PORTS) 0 + +# allow use of specific sky130 cells +set ::env(SYNTH_READ_BLACKBOX_LIB) 1 + +# put all the pins on the left +set ::env(FP_PIN_ORDER_CFG) $::env(DESIGN_DIR)/pin_order.cfg + +# reduce wasted space +set ::env(TOP_MARGIN_MULT) 2 +set ::env(BOTTOM_MARGIN_MULT) 2 + +# absolute die size +set ::env(FP_SIZING) absolute +set ::env(DIE_AREA) "0 0 280 280" + +## THIS IS THE ONLY LINE YOU CAN EDIT +set ::env(FP_CORE_UTIL) 45 + +## set ::env(PL_BASIC_PLACEMENT) {1} + +set ::env(FP_IO_HLENGTH) 2 +set ::env(FP_IO_VLENGTH) 2 + +# use alternative efabless decap cells to solve LI density issue +set ::env(DECAP_CELL) "\ + sky130_fd_sc_hd__decap_3 \ + sky130_fd_sc_hd__decap_4 \ + sky130_fd_sc_hd__decap_6 \ + sky130_fd_sc_hd__decap_8 \ + sky130_ef_sc_hd__decap_12" + +# clock +set ::env(CLOCK_TREE_SYNTH) 1 + +# period is in ns, so 500ns == 2 MHz +set ::env(CLOCK_PERIOD) "500" +set ::env(CLOCK_PORT) {io_in[12]} + +# hold/slack margin +# set ::env(PL_RESIZER_HOLD_SLACK_MARGIN) 0.8 +# set ::env(GLB_RESIZER_HOLD_SLACK_MARGIN) 0.8 + +# don't use power rings or met5 +set ::env(DESIGN_IS_CORE) 0 +set ::env(RT_MAX_LAYER) {met4} + +# connect to first digital rails +set ::env(VDD_NETS) [list {vccd1}] +set ::env(GND_NETS) [list {vssd1}] diff --git a/designs/d21_varunk2_motorctrl/src/decoder.v b/designs/d21_varunk2_motorctrl/src/decoder.v new file mode 100644 index 0000000..8d6310e --- /dev/null +++ b/designs/d21_varunk2_motorctrl/src/decoder.v @@ -0,0 +1,38 @@ + +/* + -- 1 -- + | | + 6 2 + | | + -- 7 -- + | | + 5 3 + | | + -- 4 -- +*/ + +module seg7 ( + input wire [3:0] counter, + output reg [6:0] segments +); + + always @(*) begin + case(counter) + // 7654321 + 0: segments = 7'b0111111; + 1: segments = 7'b0000110; + 2: segments = 7'b1011011; + 3: segments = 7'b1001111; + 4: segments = 7'b1100110; + 5: segments = 7'b1101101; + 6: segments = 7'b1111100; + 7: segments = 7'b0000111; + 8: segments = 7'b1111111; + 9: segments = 7'b1100111; + default: + segments = 7'b0000000; + endcase + end + +endmodule + diff --git a/designs/d21_varunk2_motorctrl/src/pin_order.cfg b/designs/d21_varunk2_motorctrl/src/pin_order.cfg new file mode 100644 index 0000000..0b85c63 --- /dev/null +++ b/designs/d21_varunk2_motorctrl/src/pin_order.cfg @@ -0,0 +1,9 @@ +#N + +#S + +#E + +#W +io_in.* +io_out.* diff --git a/designs/d21_varunk2_motorctrl/src/toplevel_chip.v b/designs/d21_varunk2_motorctrl/src/toplevel_chip.v new file mode 100644 index 0000000..a82b427 --- /dev/null +++ b/designs/d21_varunk2_motorctrl/src/toplevel_chip.v @@ -0,0 +1,18 @@ +`default_nettype none + +// DO NOT EDIT THIS FILE +module toplevel_chip ( + input [13:0] io_in, + output [13:0] io_out +); + + my_chip mchip ( + .io_in(io_in[11:0]), + .io_out(io_out[11:0]), + .clock(io_in[12]), + .reset(io_in[13]) + ); + + assign io_out[13:12] = 2'b00; + +endmodule diff --git a/designs/d21_varunk2_motorctrl/testbenches/testbenches.sv b/designs/d21_varunk2_motorctrl/testbenches/testbenches.sv new file mode 100644 index 0000000..995f8fa --- /dev/null +++ b/designs/d21_varunk2_motorctrl/testbenches/testbenches.sv @@ -0,0 +1,194 @@ +// TB +module general_pwm_testbench ( + input logic clk, + input logic rst, + input logic [15:0] period, duty_cycle, ctr_d, + input logic pwm_out + ); + always @(posedge clk) begin + if (rst) begin + + end else begin + #1; + if (ctr_d == period) begin + assert (ctr_d == 0) else $error ("COUNTERROR"); + end + else if (ctr_d <= duty_cycle) + assert (pwm_out == 1) else $error ("PWM ERROR_1"); + else + assert (pwm_out == 0) else $error ("PWM ERROR_0; CTR_D: %d PWM_OUT: %d", ctr_d, pwm_out); + end + end + +endmodule + +module general_pwm_test (); + logic clk, rst, pwm_out; + logic [15:0] period, duty_cycle; + + initial begin + clk = 0; + forever #1 clk = ~clk; + end + + general_pwm_generator mut (.*); + general_pwm_testbench cut (.ctr_d (mut.ctr_d), .*); + + initial begin + $monitor ($time, "PWM_OUT: %b period: %d duty_cycle: %d", pwm_out, period, duty_cycle); + @(posedge clk); + rst <= 1; + @(posedge clk); + rst <= 0; + period <= 20000; + duty_cycle <= 1000; + @(posedge clk); + + @(posedge clk); + @(posedge clk); + @(posedge clk); + @(posedge clk); + @(posedge clk); + @(posedge clk); + @(posedge clk); + @(posedge clk); + @(posedge clk); + #20000; + $finish; + end +endmodule + +module decode_vals_test (input logic A, B, clock, reset, p, dir); + logic [5:0] diff_count; + logic A_prev, B_prev; + always @(posedge clock) begin + // Dir Calcs + #1; + if (~reset) begin + if (A & ~A_prev & ~B) begin + assert (dir == 1) else $error ("DIR ERROR!"); + end else if (B & ~B_prev & ~A) begin + assert (dir == 0) else $error ("DIR ERROR!"); + end + + if (A & ~B) begin + assert (p == 1) else $error ("PULSE ERROR"); + end else begin + assert (p == 0) else $error ("PULSE ERROR"); + end + A_prev <= A; + B_prev <= B; + end + end +endmodule + +module decode_testbench (); + logic A, B, reset, p, dir, clock, A_prev, B_prev; + logic [4:0] speed_ct; + logic [11:0] speed_reg; + decode_module dec (.*); + decode_vals_test testor (.*); + + initial begin + clock=0; + forever #5 clock = ~clock; + end + initial begin + B = 0; + forever #40 B = ~B; + end + + initial begin + A = 0; + #20; + forever #40 A = ~A; + end + + initial begin + $monitor ("speed_ser: %b, CW: %b", p, dir); + speed_ct = 12; + reset <=1; + @(posedge clock); + reset <= 0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + $finish; + end +endmodule + +module servo_testbench (); + logic clk, rst, servo; + logic [7:0] position; + + servo_tb dut (.*); + pwm_generator mut (.*); + + initial begin + clk = 0; + forever #1 clk = ~clk; + end + + initial begin + @(posedge clock); + rst <= 1; + position <= 8'd128; + @(posedge clock); + rst <= 0; + #50000; + $finish; + end +endmodule + +module servo_tb ( + input clk, + input rst, + input [7:0] position, + input logic servo + ); + + reg pwm_d, pwm_q; + reg [19:0] ctr_q; + logic [19:0] temp_val; + assign temp_val = 1000 + (position << 2) - 12; + always_ff @(posedge clk) begin + #1; // delay for servo vals to set in. + if (rst) begin + ctr_d <= 1'b0; + end else begin + if (ctr_d == 20000) begin + ctr_d = 0; + end + if (ctr_d < (temp_val)) + assert (servo == 1) else $error ("SERVO_ERR#1"); + else + assert (servo == 0) else $error ("SERVO_ERR#0"); + ctr_d = ctr_d + 1; + end + end + +endmodule diff --git a/designs/d22_yushuanl_convolution/.lastupdated b/designs/d22_yushuanl_convolution/.lastupdated new file mode 100644 index 0000000..4d7b8c3 --- /dev/null +++ b/designs/d22_yushuanl_convolution/.lastupdated @@ -0,0 +1 @@ +2023-05-14 diff --git a/designs/d22_yushuanl_convolution/FSM Final.jpg b/designs/d22_yushuanl_convolution/FSM Final.jpg new file mode 100644 index 0000000..7aebc69 Binary files /dev/null and b/designs/d22_yushuanl_convolution/FSM Final.jpg differ diff --git a/designs/d22_yushuanl_convolution/LICENSE b/designs/d22_yushuanl_convolution/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/designs/d22_yushuanl_convolution/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/designs/d22_yushuanl_convolution/README.md b/designs/d22_yushuanl_convolution/README.md new file mode 100644 index 0000000..f36cff8 --- /dev/null +++ b/designs/d22_yushuanl_convolution/README.md @@ -0,0 +1,35 @@ +# 98154 - Convolutor Tape Out + +Yushuang Liu +98154 Spring 2023 Final Tapeout Project + +## Overview + +This device takes in two 6-bit inputs and returns their convolution result. To accomodate chip manufacturing requirements, the two inputs are combined into one 12-bit input io_in. + +## How it Works + +The input signals are passed into shift registers to get the LSB's on every rising clock edge. The LSB's are then input into a one-bit multiplier (implemented simply as anding). An adder sums together all the products. One of the inputs is the new product, and the other is either the existing sum or zero, selected by a Mux. The final output is stored to a register. All devices are controlled by an FSM with 8 states. + +Here are the RTL and FSM for the design: +RTL: +![](https://github.com/yushuang-liu/98154-Convolutor/blob/main/RTL%20Final.jpg) +FSM: +![](https://github.com/yushuang-liu/98154-Convolutor/blob/main/FSM%20Final.jpg) + +## Inputs/Outputs + +Despite the designated pins used for clock and reset, the 12-bit input is divided into even halves to create two inputs for the convolution. The output is the lower 4 bits of the 12 pins. + +## Hardware Peripherals + +No additional hardware peripherals is used. + +## Design Testing / Bringup + +This design was tested with a testbench written in SystemVerilog. After manufacturing, input a random 12 bit number to the 12 input pins (by switches, for instance), and collect the output at the lower 4 output pins. If for testing purpose only, the collection can be done by measuring the voltage difference between the pins and the voltage rails. An example of input is 12'b110111110101, the output should be 4'b0100. + +## Media + +For full SystemVerilog code for the design and testbench, please go to EDAPlayground at the following link: +https://edaplayground.com/x/CgaV diff --git a/designs/d22_yushuanl_convolution/RTL Final.jpg b/designs/d22_yushuanl_convolution/RTL Final.jpg new file mode 100644 index 0000000..ae228ef Binary files /dev/null and b/designs/d22_yushuanl_convolution/RTL Final.jpg differ diff --git a/designs/d22_yushuanl_convolution/info.yaml b/designs/d22_yushuanl_convolution/info.yaml new file mode 100644 index 0000000..71ce048 --- /dev/null +++ b/designs/d22_yushuanl_convolution/info.yaml @@ -0,0 +1,7 @@ +--- +project: + source_files: + - toplevel_chip.v + - chip.sv + top_module: "toplevel_chip" + diff --git a/designs/d22_yushuanl_convolution/src/chip.sv b/designs/d22_yushuanl_convolution/src/chip.sv new file mode 100644 index 0000000..fd513a0 --- /dev/null +++ b/designs/d22_yushuanl_convolution/src/chip.sv @@ -0,0 +1,160 @@ +//Shift Register +module shiftReg + (input logic [5:0] In, + input logic en, load, clk, + output logic [5:0] Shifted); + always_ff @(posedge clk) + if (load) + Shifted <= In; + else if (en) + Shifted <= {1'b0, Shifted[5:1]}; +endmodule + +//Multiplier +module Multiplier + (input logic First, Second, + output logic Out); + assign Out = First & Second; +endmodule + +//Adder +module Adder + (input logic First, + input logic [3:0] Second, + output logic [3:0] Out); + assign Out = {3'b0, First} + Second; +endmodule + +//Mux +module Mux + (input logic [3:0] A, B, + input logic sel, + output logic [3:0] Out); + assign Out = (sel) ? A: B; +endmodule + +//Register +module Reg + (input logic [3:0] In, + input logic clk, en, + output logic [3:0] Out); + always_ff @(posedge clk) + if (en) + Out <= In; +endmodule + +//Convolutor +module my_chip + (input logic [11:0] io_in, + input clock, reset, + output logic [3:0] io_out); + //RTL + logic en, load, enRT, enRO; + logic [5:0] Shifted_A, Shifted_B; + logic newTerm; + logic sel; + logic [3:0] inReg, oldSum, choice; + shiftReg shiftA(.In(io_in[5:0]), .en, .load, + .clk(clock), .Shifted(Shifted_A)); + shiftReg shiftB(.In(io_in[11:6]), .en, .load, + .clk(clock), .Shifted(Shifted_B)); + Multiplier mul(.First(Shifted_A[0]), + .Second(Shifted_B[0]), + .Out(newTerm)); + Mux mux(.A(oldSum), .B(4'b0), .sel, .Out(choice)); + Adder add(.First(newTerm), .Second(choice), .Out(inReg)); + Reg registerTemp(.In(inReg), .clk(clock), .en(enRT), .Out(oldSum)); + Reg registerOut(.In(oldSum), .clk(clock), .en(enRO), .Out(io_out)); + //FSM Output + enum logic [2:0] {Start = 3'b000, Wait = 3'b001, + Shift1 = 3'b010, Shift2 = 3'b011, + Shift3 = 3'b100, Shift4 = 3'b101, + Shift5 = 3'b110, End = 3'b111} + curState, nextState; + always_comb begin + case (curState) + Start: begin + load = 1; + en = 0; + sel = 0; + enRT = 1; + enRO = 0; + end + Wait: begin + load = 0; + en = 1; + sel = 1; + enRT = 0; + enRO = 0; + end + Shift1: begin + load = 0; + en = 1; + sel = 1; + enRT = 1; + enRO = 0; + end + Shift2: begin + load = 0; + en = 1; + sel = 1; + enRT = 1; + enRO = 0; + end + Shift3: begin + load = 0; + en = 1; + sel = 1; + enRT = 1; + enRO = 0; + end + Shift4: begin + load = 0; + en = 1; + sel = 1; + enRT = 1; + enRO = 0; + end + Shift5: begin + load = 0; + en = 1; + sel = 1; + enRT = 1; + enRO = 0; + end + End: begin + load = 0; + en = 0; + sel = 0; + enRT = 0; + enRO = 1; + end + default: begin + load = 1; + en = 0; + sel = 0; + enRT = 1; + enRO = 0; + end + endcase + end + //FSM Transfer + always_comb begin + case (curState) + Start: nextState = Wait; + Wait: nextState = Shift1; + Shift1: nextState = Shift2; + Shift2: nextState = Shift3; + Shift3: nextState = Shift4; + Shift4: nextState = Shift5; + Shift5: nextState = End; + End: nextState = End; + default: nextState = Start; + endcase + end + always_ff @(posedge clock, posedge reset) + if (reset) + curState <= Start; + else + curState <= nextState; +endmodule \ No newline at end of file diff --git a/designs/d22_yushuanl_convolution/src/config.tcl b/designs/d22_yushuanl_convolution/src/config.tcl new file mode 100644 index 0000000..aa589e4 --- /dev/null +++ b/designs/d22_yushuanl_convolution/src/config.tcl @@ -0,0 +1,68 @@ +# PLEASE DO NOT EDIT THIS FILE! +# IT WILL MAKE YOUR CHIP UNMANUFACTURABLE +# The only line you may edit is FP_CORE_UTIL +# (may benefit from reducing it slightly) + +# User config +set script_dir [file dirname [file normalize [info script]]] + +# read some user config that is written by the setup.py program. +# - the name of the module is defined +# - the list of source files +source $::env(DESIGN_DIR)/user_config.tcl + +# save some time +set ::env(RUN_KLAYOUT_XOR) 0 +set ::env(RUN_KLAYOUT_DRC) 0 + +# don't put clock buffers on the outputs +set ::env(PL_RESIZER_BUFFER_OUTPUT_PORTS) 0 + +# allow use of specific sky130 cells +set ::env(SYNTH_READ_BLACKBOX_LIB) 1 + +# put all the pins on the left +set ::env(FP_PIN_ORDER_CFG) $::env(DESIGN_DIR)/pin_order.cfg + +# reduce wasted space +set ::env(TOP_MARGIN_MULT) 2 +set ::env(BOTTOM_MARGIN_MULT) 2 + +# absolute die size +set ::env(FP_SIZING) absolute +set ::env(DIE_AREA) "0 0 280 280" + +## THIS IS THE ONLY LINE YOU CAN EDIT +set ::env(FP_CORE_UTIL) 45 + +## set ::env(PL_BASIC_PLACEMENT) {1} + +set ::env(FP_IO_HLENGTH) 2 +set ::env(FP_IO_VLENGTH) 2 + +# use alternative efabless decap cells to solve LI density issue +set ::env(DECAP_CELL) "\ + sky130_fd_sc_hd__decap_3 \ + sky130_fd_sc_hd__decap_4 \ + sky130_fd_sc_hd__decap_6 \ + sky130_fd_sc_hd__decap_8 \ + sky130_ef_sc_hd__decap_12" + +# clock +set ::env(CLOCK_TREE_SYNTH) 1 + +# period is in ns, so 500ns == 2 MHz +set ::env(CLOCK_PERIOD) "500" +set ::env(CLOCK_PORT) {io_in[12]} + +# hold/slack margin +# set ::env(PL_RESIZER_HOLD_SLACK_MARGIN) 0.8 +# set ::env(GLB_RESIZER_HOLD_SLACK_MARGIN) 0.8 + +# don't use power rings or met5 +set ::env(DESIGN_IS_CORE) 0 +set ::env(RT_MAX_LAYER) {met4} + +# connect to first digital rails +set ::env(VDD_NETS) [list {vccd1}] +set ::env(GND_NETS) [list {vssd1}] diff --git a/designs/d22_yushuanl_convolution/src/pin_order.cfg b/designs/d22_yushuanl_convolution/src/pin_order.cfg new file mode 100644 index 0000000..0b85c63 --- /dev/null +++ b/designs/d22_yushuanl_convolution/src/pin_order.cfg @@ -0,0 +1,9 @@ +#N + +#S + +#E + +#W +io_in.* +io_out.* diff --git a/designs/d22_yushuanl_convolution/src/toplevel_chip.v b/designs/d22_yushuanl_convolution/src/toplevel_chip.v new file mode 100644 index 0000000..a82b427 --- /dev/null +++ b/designs/d22_yushuanl_convolution/src/toplevel_chip.v @@ -0,0 +1,18 @@ +`default_nettype none + +// DO NOT EDIT THIS FILE +module toplevel_chip ( + input [13:0] io_in, + output [13:0] io_out +); + + my_chip mchip ( + .io_in(io_in[11:0]), + .io_out(io_out[11:0]), + .clock(io_in[12]), + .reset(io_in[13]) + ); + + assign io_out[13:12] = 2'b00; + +endmodule diff --git a/designs/d23_zhiyingm_turing/.lastupdated b/designs/d23_zhiyingm_turing/.lastupdated new file mode 100644 index 0000000..4d7b8c3 --- /dev/null +++ b/designs/d23_zhiyingm_turing/.lastupdated @@ -0,0 +1 @@ +2023-05-14 diff --git a/designs/d23_zhiyingm_turing/LICENSE b/designs/d23_zhiyingm_turing/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/designs/d23_zhiyingm_turing/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/designs/d23_zhiyingm_turing/README.md b/designs/d23_zhiyingm_turing/README.md new file mode 100644 index 0000000..bb890a1 --- /dev/null +++ b/designs/d23_zhiyingm_turing/README.md @@ -0,0 +1,51 @@ +# Turing Machine +Zhiying Meng 18-224/624 Spring 2023 Final Tapeout Project +## Overview +This chip takes in a Turing Machine style state transition table and initial tape values, then displays the computation process. Only support tape with values 1 and 0. +## Inputs/Outputs +Inputs: +- 6 switches used for input data (number of states + state transition table + tape start address + initial tape values) +- 3 buttons for controlling the computation process + +Outputs: +- 11 LEDs for displaying the tape values +- 1 LED for indicating "Halt" or reach end of memory + +![](media/IO.jpg) +## How it Works +The chip initially stores all the inputs into a 4$\times$64 memory. It takes the bit at the tape head and look for the corresponding actions in the state transition table (default state is 1). + +For instance, in the above example, the first bit in the tape would be 1, so it will go to state 1 with input 1 which has instruction 1 R q1. During the process, it displays the new tape value, rewrites it with 1, moves the tape head to the right, and goes to state 1. + +After it has processed all the values on the tape, it will either go to "Halt" state where the tape stops moving, or it will reach the end of the tape and stops. + +The diagram below is the RTL design to achieve this function. +![](media/Datapath.jpg) +![](media/FSM.jpg) +## Design Testing / Bringup +When testing the chip, input a valid Turing Machine state transition table and a initial tape value using the switches. Press the "Next" button to indicate the input can be taken, and press the "Done" button to indicate the end of the inputs. + +The chip will then start to compute. The tape will move by 1 index after the "Next" button is pressed and the 11 LEDs will display the corresponding tape values. It will continue the process until the 12th LED lights up to indicate it finishes computing. + +With the example provided before, the expected outputs from the LEDs are as below: + +``` +00000000000 +00000000001 +00000000011 +00000000111 +00000001111 +00000011110 +00000011111 +00000111111 +00001111111 +00011111111 +00011111110 +00011111110 +compute done +``` + +## Media +Testing using FPGA: +![](media/FPGA1.jpg) +![](media/FPGA2.jpg) diff --git a/designs/d23_zhiyingm_turing/TuringMachine/240FPGA.qsf b/designs/d23_zhiyingm_turing/TuringMachine/240FPGA.qsf new file mode 100644 index 0000000..8cff6ab --- /dev/null +++ b/designs/d23_zhiyingm_turing/TuringMachine/240FPGA.qsf @@ -0,0 +1,338 @@ +#============================================================ +# Build by Altera University Program +#============================================================ +set_global_assignment -name FAMILY "Cyclone IV E" +set_global_assignment -name DEVICE EP4CE115F29C8 +set_global_assignment -name USE_GENERATED_PHYSICAL_CONSTRAINTS OFF -section_id eda_blast_fpga +set_global_assignment -name CYCLONEII_RESERVE_NCEO_AFTER_CONFIGURATION "USE AS REGULAR IO" + +#============================================================ +# CLOCK +#============================================================ +set_location_assignment PIN_Y2 -to CLOCK_50 +set_location_assignment PIN_AG14 -to CLOCK2_50 +set_location_assignment PIN_AG15 -to CLOCK3_50 +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to CLOCK_50 +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to CLOCK2_50 +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to CLOCK3_50 + +#============================================================ +# LED +#============================================================ +set_location_assignment PIN_E21 -to LEDG[0] +set_location_assignment PIN_E22 -to LEDG[1] +set_location_assignment PIN_E25 -to LEDG[2] +set_location_assignment PIN_E24 -to LEDG[3] +set_location_assignment PIN_H21 -to LEDG[4] +set_location_assignment PIN_G20 -to LEDG[5] +set_location_assignment PIN_G22 -to LEDG[6] +set_location_assignment PIN_G21 -to LEDG[7] +set_location_assignment PIN_F17 -to LEDG[8] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDG[0] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDG[1] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDG[2] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDG[3] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDG[4] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDG[5] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDG[6] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDG[7] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDG[8] + +set_location_assignment PIN_G19 -to LEDR[0] +set_location_assignment PIN_E19 -to LEDR[2] +set_location_assignment PIN_F19 -to LEDR[1] +set_location_assignment PIN_F21 -to LEDR[3] +set_location_assignment PIN_F18 -to LEDR[4] +set_location_assignment PIN_E18 -to LEDR[5] +set_location_assignment PIN_J19 -to LEDR[6] +set_location_assignment PIN_H19 -to LEDR[7] +set_location_assignment PIN_J17 -to LEDR[8] +set_location_assignment PIN_G17 -to LEDR[9] +set_location_assignment PIN_J15 -to LEDR[10] +set_location_assignment PIN_H16 -to LEDR[11] +set_location_assignment PIN_J16 -to LEDR[12] +set_location_assignment PIN_H17 -to LEDR[13] +set_location_assignment PIN_F15 -to LEDR[14] +set_location_assignment PIN_G15 -to LEDR[15] +set_location_assignment PIN_G16 -to LEDR[16] +set_location_assignment PIN_H15 -to LEDR[17] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[0] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[1] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[3] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[4] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[5] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[6] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[7] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[8] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[9] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[10] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[11] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[12] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[13] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[14] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[15] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[16] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[17] + +#============================================================ +# KEY +#============================================================ +set_location_assignment PIN_M23 -to KEY[0] +set_location_assignment PIN_M21 -to KEY[1] +set_location_assignment PIN_N21 -to KEY[2] +set_location_assignment PIN_R24 -to KEY[3] +set_instance_assignment -name IO_STANDARD "2.5 V" -to KEY[0] +set_instance_assignment -name IO_STANDARD "2.5 V" -to KEY[1] +set_instance_assignment -name IO_STANDARD "2.5 V" -to KEY[2] +set_instance_assignment -name IO_STANDARD "2.5 V" -to KEY[3] + +#============================================================ +# SW +#============================================================ +set_location_assignment PIN_AB28 -to SW[0] +set_location_assignment PIN_AC28 -to SW[1] +set_location_assignment PIN_AC27 -to SW[2] +set_location_assignment PIN_AD27 -to SW[3] +set_location_assignment PIN_AB27 -to SW[4] +set_location_assignment PIN_AC26 -to SW[5] +set_location_assignment PIN_AD26 -to SW[6] +set_location_assignment PIN_AB26 -to SW[7] +set_location_assignment PIN_AC25 -to SW[8] +set_location_assignment PIN_AB25 -to SW[9] +set_location_assignment PIN_AC24 -to SW[10] +set_location_assignment PIN_AB24 -to SW[11] +set_location_assignment PIN_AB23 -to SW[12] +set_location_assignment PIN_AA24 -to SW[13] +set_location_assignment PIN_AA23 -to SW[14] +set_location_assignment PIN_AA22 -to SW[15] +set_location_assignment PIN_Y24 -to SW[16] +set_location_assignment PIN_Y23 -to SW[17] +set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[0] +set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[1] +set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[2] +set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[3] +set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[4] +set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[5] +set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[6] +set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[7] +set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[8] +set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[9] +set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[10] +set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[11] +set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[12] +set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[13] +set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[14] +set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[15] +set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[16] +set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[17] + +#============================================================ +# SEG7 +#============================================================ +set_location_assignment PIN_G18 -to HEX0[0] +set_location_assignment PIN_F22 -to HEX0[1] +set_location_assignment PIN_E17 -to HEX0[2] +set_location_assignment PIN_L26 -to HEX0[3] +set_location_assignment PIN_L25 -to HEX0[4] +set_location_assignment PIN_J22 -to HEX0[5] +set_location_assignment PIN_H22 -to HEX0[6] +set_location_assignment PIN_M24 -to HEX1[0] +set_location_assignment PIN_Y22 -to HEX1[1] +set_location_assignment PIN_W21 -to HEX1[2] +set_location_assignment PIN_W22 -to HEX1[3] +set_location_assignment PIN_W25 -to HEX1[4] +set_location_assignment PIN_U23 -to HEX1[5] +set_location_assignment PIN_U24 -to HEX1[6] +set_location_assignment PIN_AA25 -to HEX2[0] +set_location_assignment PIN_AA26 -to HEX2[1] +set_location_assignment PIN_Y25 -to HEX2[2] +set_location_assignment PIN_W26 -to HEX2[3] +set_location_assignment PIN_Y26 -to HEX2[4] +set_location_assignment PIN_W27 -to HEX2[5] +set_location_assignment PIN_W28 -to HEX2[6] +set_location_assignment PIN_V21 -to HEX3[0] +set_location_assignment PIN_U21 -to HEX3[1] +set_location_assignment PIN_AB20 -to HEX3[2] +set_location_assignment PIN_AA21 -to HEX3[3] +set_location_assignment PIN_AD24 -to HEX3[4] +set_location_assignment PIN_AF23 -to HEX3[5] +set_location_assignment PIN_Y19 -to HEX3[6] +set_location_assignment PIN_AB19 -to HEX4[0] +set_location_assignment PIN_AA19 -to HEX4[1] +set_location_assignment PIN_AG21 -to HEX4[2] +set_location_assignment PIN_AH21 -to HEX4[3] +set_location_assignment PIN_AE19 -to HEX4[4] +set_location_assignment PIN_AF19 -to HEX4[5] +set_location_assignment PIN_AE18 -to HEX4[6] +set_location_assignment PIN_AD18 -to HEX5[0] +set_location_assignment PIN_AC18 -to HEX5[1] +set_location_assignment PIN_AB18 -to HEX5[2] +set_location_assignment PIN_AH19 -to HEX5[3] +set_location_assignment PIN_AG19 -to HEX5[4] +set_location_assignment PIN_AF18 -to HEX5[5] +set_location_assignment PIN_AH18 -to HEX5[6] +set_location_assignment PIN_AA17 -to HEX6[0] +set_location_assignment PIN_AB16 -to HEX6[1] +set_location_assignment PIN_AA16 -to HEX6[2] +set_location_assignment PIN_AB17 -to HEX6[3] +set_location_assignment PIN_AB15 -to HEX6[4] +set_location_assignment PIN_AA15 -to HEX6[5] +set_location_assignment PIN_AC17 -to HEX6[6] +set_location_assignment PIN_AD17 -to HEX7[0] +set_location_assignment PIN_AE17 -to HEX7[1] +set_location_assignment PIN_AG17 -to HEX7[2] +set_location_assignment PIN_AH17 -to HEX7[3] +set_location_assignment PIN_AF17 -to HEX7[4] +set_location_assignment PIN_AG18 -to HEX7[5] +set_location_assignment PIN_AA14 -to HEX7[6] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX0[0] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX0[1] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX0[2] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX0[3] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX0[4] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX0[5] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX0[6] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX1[0] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX1[1] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX1[2] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX1[3] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX1[4] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX1[5] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX1[6] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX2[0] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX2[1] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX2[2] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX2[3] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX2[4] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX2[5] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX2[6] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX3[0] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX3[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX3[2] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX3[3] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX3[4] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX3[5] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX3[6] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX4[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX4[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX4[2] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX4[3] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX4[4] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX4[5] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX4[6] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX5[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX5[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX5[2] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX5[3] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX5[4] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX5[5] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX5[6] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX6[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX6[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX6[2] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX6[3] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX6[4] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX6[5] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX6[6] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX7[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX7[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX7[2] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX7[3] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX7[4] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX7[5] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX7[6] + +#============================================================ +# VGA +#============================================================ +set_location_assignment PIN_D12 -to VGA_B[7] +set_location_assignment PIN_D11 -to VGA_B[6] +set_location_assignment PIN_C12 -to VGA_B[5] +set_location_assignment PIN_A11 -to VGA_B[4] +set_location_assignment PIN_B11 -to VGA_B[3] +set_location_assignment PIN_C11 -to VGA_B[2] +set_location_assignment PIN_A10 -to VGA_B[1] +set_location_assignment PIN_B10 -to VGA_B[0] +set_location_assignment PIN_C9 -to VGA_G[7] +set_location_assignment PIN_F10 -to VGA_G[6] +set_location_assignment PIN_B8 -to VGA_G[5] +set_location_assignment PIN_C8 -to VGA_G[4] +set_location_assignment PIN_H12 -to VGA_G[3] +set_location_assignment PIN_F8 -to VGA_G[2] +set_location_assignment PIN_G11 -to VGA_G[1] +set_location_assignment PIN_G8 -to VGA_G[0] +set_location_assignment PIN_H10 -to VGA_R[7] +set_location_assignment PIN_H8 -to VGA_R[6] +set_location_assignment PIN_J12 -to VGA_R[5] +set_location_assignment PIN_G10 -to VGA_R[4] +set_location_assignment PIN_F12 -to VGA_R[3] +set_location_assignment PIN_D10 -to VGA_R[2] +set_location_assignment PIN_E11 -to VGA_R[1] +set_location_assignment PIN_E12 -to VGA_R[0] +set_location_assignment PIN_A12 -to VGA_CLK +set_location_assignment PIN_F11 -to VGA_BLANK_N +set_location_assignment PIN_C10 -to VGA_SYNC_N +set_location_assignment PIN_G13 -to VGA_HS +set_location_assignment PIN_C13 -to VGA_VS +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_HS +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_VS +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_SYNC_N +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_CLK +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_BLANK_N +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_R[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_R[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_R[2] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_R[3] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_R[4] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_R[5] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_R[6] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_R[7] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_G[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_G[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_G[2] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_G[3] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_G[4] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_G[5] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_G[6] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_G[7] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_B[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_B[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_B[2] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_B[3] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_B[4] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_B[5] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_B[6] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_B[7] + +#============================================================ +# End of pin assignments by Altera University Program +#============================================================ + + +set_instance_assignment -name IO_MAXIMUM_TOGGLE_RATE "0 MHz" -to HEX2 +set_instance_assignment -name IO_MAXIMUM_TOGGLE_RATE "0 MHz" -to HEX0 +set_instance_assignment -name IO_MAXIMUM_TOGGLE_RATE "0 MHz" -to HEX1 +set_instance_assignment -name IO_MAXIMUM_TOGGLE_RATE "0 MHz" -to KEY +set_instance_assignment -name IO_MAXIMUM_TOGGLE_RATE "0 MHz" -to SW +set_instance_assignment -name IO_MAXIMUM_TOGGLE_RATE "0 MHz" -to HEX3[1] +set_instance_assignment -name IO_MAXIMUM_TOGGLE_RATE "0 MHz" -to HEX3[0] + +set_global_assignment -name DEVICE_FILTER_PACKAGE FBGA +set_global_assignment -name USE_CONFIGURATION_DEVICE ON +set_global_assignment -name CYCLONEIII_CONFIGURATION_DEVICE EPCS64 + + +set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top +set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top +set_global_assignment -name LL_ROOT_REGION ON -section_id "Root Region" +set_global_assignment -name LL_MEMBER_STATE LOCKED -section_id "Root Region" + +set_instance_assignment -name FAST_INPUT_REGISTER ON -to * +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to * +set_instance_assignment -name TSU_REQUIREMENT "10 ns" -from * -to * + + + + + +set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top diff --git a/designs/d23_zhiyingm_turing/TuringMachine/ChipInterface.qsf b/designs/d23_zhiyingm_turing/TuringMachine/ChipInterface.qsf new file mode 100644 index 0000000..d6a2e7e --- /dev/null +++ b/designs/d23_zhiyingm_turing/TuringMachine/ChipInterface.qsf @@ -0,0 +1,345 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 2017 Intel Corporation. All rights reserved. +# Your use of Intel Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Intel Program License +# Subscription Agreement, the Intel Quartus Prime License Agreement, +# the Intel MegaCore Function License Agreement, or other +# applicable license agreement, including, without limitation, +# that your use is for the sole purpose of programming logic +# devices manufactured by Intel and sold by Intel or its +# authorized distributors. Please refer to the applicable +# agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus Prime +# Version 16.1.2 Build 203 01/18/2017 SJ Standard Edition +# Date created = 13:21:19 May 06, 2023 +# +# -------------------------------------------------------------------------- # +# +# Notes: +# +# 1) The default values for assignments are stored in the file: +# ChipInterface_assignment_defaults.qdf +# If this file doesn't exist, see file: +# assignment_defaults.qdf +# +# 2) Altera recommends that you do not modify this file. This +# file is updated automatically by the Quartus Prime software +# and any changes you make may be lost or overwritten. +# +# -------------------------------------------------------------------------- # + + +set_global_assignment -name FAMILY "Cyclone IV E" +set_global_assignment -name DEVICE EP4CE115F29C7 +set_global_assignment -name TOP_LEVEL_ENTITY ChipInterface +set_global_assignment -name ORIGINAL_QUARTUS_VERSION 16.1.2 +set_global_assignment -name PROJECT_CREATION_TIME_DATE "13:21:19 MAY 06, 2023" +set_global_assignment -name LAST_QUARTUS_VERSION "16.1.2 Standard Edition" +set_global_assignment -name SYSTEMVERILOG_FILE TuringMachine.sv +set_global_assignment -name SYSTEMVERILOG_FILE library.sv +set_global_assignment -name SYSTEMVERILOG_FILE ChipInterface.sv +set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files +set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0 +set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85 +set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR 1 +set_global_assignment -name NOMINAL_CORE_SUPPLY_VOLTAGE 1.2V +set_global_assignment -name EDA_SIMULATION_TOOL "ModelSim-Altera (Verilog)" +set_global_assignment -name EDA_TIME_SCALE "1 ps" -section_id eda_simulation +set_global_assignment -name EDA_OUTPUT_DATA_FORMAT "VERILOG HDL" -section_id eda_simulation +set_location_assignment PIN_Y2 -to CLOCK_50 +set_location_assignment PIN_AG14 -to CLOCK2_50 +set_location_assignment PIN_AG15 -to CLOCK3_50 +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to CLOCK_50 +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to CLOCK2_50 +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to CLOCK3_50 +set_location_assignment PIN_E21 -to LEDG[0] +set_location_assignment PIN_E22 -to LEDG[1] +set_location_assignment PIN_E25 -to LEDG[2] +set_location_assignment PIN_E24 -to LEDG[3] +set_location_assignment PIN_H21 -to LEDG[4] +set_location_assignment PIN_G20 -to LEDG[5] +set_location_assignment PIN_G22 -to LEDG[6] +set_location_assignment PIN_G21 -to LEDG[7] +set_location_assignment PIN_F17 -to LEDG[8] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDG[0] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDG[1] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDG[2] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDG[3] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDG[4] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDG[5] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDG[6] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDG[7] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDG[8] +set_location_assignment PIN_G19 -to LEDR[0] +set_location_assignment PIN_E19 -to LEDR[2] +set_location_assignment PIN_F19 -to LEDR[1] +set_location_assignment PIN_F21 -to LEDR[3] +set_location_assignment PIN_F18 -to LEDR[4] +set_location_assignment PIN_E18 -to LEDR[5] +set_location_assignment PIN_J19 -to LEDR[6] +set_location_assignment PIN_H19 -to LEDR[7] +set_location_assignment PIN_J17 -to LEDR[8] +set_location_assignment PIN_G17 -to LEDR[9] +set_location_assignment PIN_J15 -to LEDR[10] +set_location_assignment PIN_H16 -to LEDR[11] +set_location_assignment PIN_J16 -to LEDR[12] +set_location_assignment PIN_H17 -to LEDR[13] +set_location_assignment PIN_F15 -to LEDR[14] +set_location_assignment PIN_G15 -to LEDR[15] +set_location_assignment PIN_G16 -to LEDR[16] +set_location_assignment PIN_H15 -to LEDR[17] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[0] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[1] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[3] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[4] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[5] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[6] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[7] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[8] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[9] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[10] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[11] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[12] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[13] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[14] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[15] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[16] +set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[17] +set_location_assignment PIN_M23 -to KEY[0] +set_location_assignment PIN_M21 -to KEY[1] +set_location_assignment PIN_N21 -to KEY[2] +set_location_assignment PIN_R24 -to KEY[3] +set_instance_assignment -name IO_STANDARD "2.5 V" -to KEY[0] +set_instance_assignment -name IO_STANDARD "2.5 V" -to KEY[1] +set_instance_assignment -name IO_STANDARD "2.5 V" -to KEY[2] +set_instance_assignment -name IO_STANDARD "2.5 V" -to KEY[3] +set_location_assignment PIN_AB28 -to SW[0] +set_location_assignment PIN_AC28 -to SW[1] +set_location_assignment PIN_AC27 -to SW[2] +set_location_assignment PIN_AD27 -to SW[3] +set_location_assignment PIN_AB27 -to SW[4] +set_location_assignment PIN_AC26 -to SW[5] +set_location_assignment PIN_AD26 -to SW[6] +set_location_assignment PIN_AB26 -to SW[7] +set_location_assignment PIN_AC25 -to SW[8] +set_location_assignment PIN_AB25 -to SW[9] +set_location_assignment PIN_AC24 -to SW[10] +set_location_assignment PIN_AB24 -to SW[11] +set_location_assignment PIN_AB23 -to SW[12] +set_location_assignment PIN_AA24 -to SW[13] +set_location_assignment PIN_AA23 -to SW[14] +set_location_assignment PIN_AA22 -to SW[15] +set_location_assignment PIN_Y24 -to SW[16] +set_location_assignment PIN_Y23 -to SW[17] +set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[0] +set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[1] +set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[2] +set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[3] +set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[4] +set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[5] +set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[6] +set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[7] +set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[8] +set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[9] +set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[10] +set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[11] +set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[12] +set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[13] +set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[14] +set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[15] +set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[16] +set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[17] +set_location_assignment PIN_G18 -to HEX0[0] +set_location_assignment PIN_F22 -to HEX0[1] +set_location_assignment PIN_E17 -to HEX0[2] +set_location_assignment PIN_L26 -to HEX0[3] +set_location_assignment PIN_L25 -to HEX0[4] +set_location_assignment PIN_J22 -to HEX0[5] +set_location_assignment PIN_H22 -to HEX0[6] +set_location_assignment PIN_M24 -to HEX1[0] +set_location_assignment PIN_Y22 -to HEX1[1] +set_location_assignment PIN_W21 -to HEX1[2] +set_location_assignment PIN_W22 -to HEX1[3] +set_location_assignment PIN_W25 -to HEX1[4] +set_location_assignment PIN_U23 -to HEX1[5] +set_location_assignment PIN_U24 -to HEX1[6] +set_location_assignment PIN_AA25 -to HEX2[0] +set_location_assignment PIN_AA26 -to HEX2[1] +set_location_assignment PIN_Y25 -to HEX2[2] +set_location_assignment PIN_W26 -to HEX2[3] +set_location_assignment PIN_Y26 -to HEX2[4] +set_location_assignment PIN_W27 -to HEX2[5] +set_location_assignment PIN_W28 -to HEX2[6] +set_location_assignment PIN_V21 -to HEX3[0] +set_location_assignment PIN_U21 -to HEX3[1] +set_location_assignment PIN_AB20 -to HEX3[2] +set_location_assignment PIN_AA21 -to HEX3[3] +set_location_assignment PIN_AD24 -to HEX3[4] +set_location_assignment PIN_AF23 -to HEX3[5] +set_location_assignment PIN_Y19 -to HEX3[6] +set_location_assignment PIN_AB19 -to HEX4[0] +set_location_assignment PIN_AA19 -to HEX4[1] +set_location_assignment PIN_AG21 -to HEX4[2] +set_location_assignment PIN_AH21 -to HEX4[3] +set_location_assignment PIN_AE19 -to HEX4[4] +set_location_assignment PIN_AF19 -to HEX4[5] +set_location_assignment PIN_AE18 -to HEX4[6] +set_location_assignment PIN_AD18 -to HEX5[0] +set_location_assignment PIN_AC18 -to HEX5[1] +set_location_assignment PIN_AB18 -to HEX5[2] +set_location_assignment PIN_AH19 -to HEX5[3] +set_location_assignment PIN_AG19 -to HEX5[4] +set_location_assignment PIN_AF18 -to HEX5[5] +set_location_assignment PIN_AH18 -to HEX5[6] +set_location_assignment PIN_AA17 -to HEX6[0] +set_location_assignment PIN_AB16 -to HEX6[1] +set_location_assignment PIN_AA16 -to HEX6[2] +set_location_assignment PIN_AB17 -to HEX6[3] +set_location_assignment PIN_AB15 -to HEX6[4] +set_location_assignment PIN_AA15 -to HEX6[5] +set_location_assignment PIN_AC17 -to HEX6[6] +set_location_assignment PIN_AD17 -to HEX7[0] +set_location_assignment PIN_AE17 -to HEX7[1] +set_location_assignment PIN_AG17 -to HEX7[2] +set_location_assignment PIN_AH17 -to HEX7[3] +set_location_assignment PIN_AF17 -to HEX7[4] +set_location_assignment PIN_AG18 -to HEX7[5] +set_location_assignment PIN_AA14 -to HEX7[6] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX0[0] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX0[1] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX0[2] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX0[3] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX0[4] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX0[5] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX0[6] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX1[0] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX1[1] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX1[2] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX1[3] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX1[4] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX1[5] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX1[6] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX2[0] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX2[1] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX2[2] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX2[3] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX2[4] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX2[5] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX2[6] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX3[0] +set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX3[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX3[2] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX3[3] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX3[4] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX3[5] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX3[6] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX4[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX4[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX4[2] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX4[3] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX4[4] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX4[5] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX4[6] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX5[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX5[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX5[2] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX5[3] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX5[4] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX5[5] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX5[6] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX6[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX6[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX6[2] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX6[3] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX6[4] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX6[5] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX6[6] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX7[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX7[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX7[2] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX7[3] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX7[4] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX7[5] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX7[6] +set_location_assignment PIN_D12 -to VGA_B[7] +set_location_assignment PIN_D11 -to VGA_B[6] +set_location_assignment PIN_C12 -to VGA_B[5] +set_location_assignment PIN_A11 -to VGA_B[4] +set_location_assignment PIN_B11 -to VGA_B[3] +set_location_assignment PIN_C11 -to VGA_B[2] +set_location_assignment PIN_A10 -to VGA_B[1] +set_location_assignment PIN_B10 -to VGA_B[0] +set_location_assignment PIN_C9 -to VGA_G[7] +set_location_assignment PIN_F10 -to VGA_G[6] +set_location_assignment PIN_B8 -to VGA_G[5] +set_location_assignment PIN_C8 -to VGA_G[4] +set_location_assignment PIN_H12 -to VGA_G[3] +set_location_assignment PIN_F8 -to VGA_G[2] +set_location_assignment PIN_G11 -to VGA_G[1] +set_location_assignment PIN_G8 -to VGA_G[0] +set_location_assignment PIN_H10 -to VGA_R[7] +set_location_assignment PIN_H8 -to VGA_R[6] +set_location_assignment PIN_J12 -to VGA_R[5] +set_location_assignment PIN_G10 -to VGA_R[4] +set_location_assignment PIN_F12 -to VGA_R[3] +set_location_assignment PIN_D10 -to VGA_R[2] +set_location_assignment PIN_E11 -to VGA_R[1] +set_location_assignment PIN_E12 -to VGA_R[0] +set_location_assignment PIN_A12 -to VGA_CLK +set_location_assignment PIN_F11 -to VGA_BLANK_N +set_location_assignment PIN_C10 -to VGA_SYNC_N +set_location_assignment PIN_G13 -to VGA_HS +set_location_assignment PIN_C13 -to VGA_VS +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_HS +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_VS +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_SYNC_N +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_CLK +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_BLANK_N +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_R[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_R[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_R[2] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_R[3] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_R[4] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_R[5] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_R[6] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_R[7] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_G[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_G[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_G[2] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_G[3] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_G[4] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_G[5] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_G[6] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_G[7] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_B[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_B[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_B[2] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_B[3] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_B[4] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_B[5] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_B[6] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_B[7] +set_instance_assignment -name IO_MAXIMUM_TOGGLE_RATE "0 MHz" -to HEX2 +set_instance_assignment -name IO_MAXIMUM_TOGGLE_RATE "0 MHz" -to HEX0 +set_instance_assignment -name IO_MAXIMUM_TOGGLE_RATE "0 MHz" -to HEX1 +set_instance_assignment -name IO_MAXIMUM_TOGGLE_RATE "0 MHz" -to KEY +set_instance_assignment -name IO_MAXIMUM_TOGGLE_RATE "0 MHz" -to SW +set_instance_assignment -name IO_MAXIMUM_TOGGLE_RATE "0 MHz" -to HEX3[1] +set_instance_assignment -name IO_MAXIMUM_TOGGLE_RATE "0 MHz" -to HEX3[0] +set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top +set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top +set_global_assignment -name LL_ROOT_REGION ON -section_id "Root Region" +set_global_assignment -name LL_MEMBER_STATE LOCKED -section_id "Root Region" +set_instance_assignment -name FAST_INPUT_REGISTER ON -to * +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to * +set_instance_assignment -name TSU_REQUIREMENT "10 ns" -from * -to * +set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top +set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file diff --git a/designs/d23_zhiyingm_turing/TuringMachine/ChipInterface.qws b/designs/d23_zhiyingm_turing/TuringMachine/ChipInterface.qws new file mode 100644 index 0000000..2d00f56 Binary files /dev/null and b/designs/d23_zhiyingm_turing/TuringMachine/ChipInterface.qws differ diff --git a/designs/d23_zhiyingm_turing/TuringMachine/ChipInterface.sv b/designs/d23_zhiyingm_turing/TuringMachine/ChipInterface.sv new file mode 100644 index 0000000..fa1b535 --- /dev/null +++ b/designs/d23_zhiyingm_turing/TuringMachine/ChipInterface.sv @@ -0,0 +1,73 @@ +module hex_to_sevenseg ( + input logic [3:0] hexdigit, + output logic [7:0] seg +); + + always_comb begin + seg = '1; + if (hexdigit == 4'h0) seg = 8'b1100_0000; + if (hexdigit == 4'h1) seg = 8'b1111_1001; + if (hexdigit == 4'h2) seg = 8'b1010_0100; + if (hexdigit == 4'h3) seg = 8'b1011_0000; + if (hexdigit == 4'h4) seg = 8'b1001_1001; + if (hexdigit == 4'h5) seg = 8'b1001_0010; + if (hexdigit == 4'h6) seg = 8'b1000_0010; + if (hexdigit == 4'h7) seg = 8'b1111_1000; + if (hexdigit == 4'h8) seg = 8'b1000_0000; + if (hexdigit == 4'h9) seg = 8'b1001_0000; + if (hexdigit == 4'hA) seg = 8'b1000_1000; + if (hexdigit == 4'hB) seg = 8'b1000_0011; + if (hexdigit == 4'hC) seg = 8'b1100_0110; + if (hexdigit == 4'hD) seg = 8'b1010_0001; + if (hexdigit == 4'hE) seg = 8'b1000_0110; + if (hexdigit == 4'hF) seg = 8'b1000_1110; + end + +endmodule + + +module ChipInterface ( + input logic CLOCK_50, + input logic [3:0] KEY, + input logic [17:0] SW, + output logic [6:0] HEX0, HEX1, HEX2, HEX3, HEX4, HEX5, HEX6, HEX7, + output logic [17:0] LEDR, + output logic [7:0] LEDG +); + + logic [5:0] input_data; + logic clock, reset, Next, Done; + logic [10:0] display_out; + logic Compute_done; + + logic [3:0] state; + logic tape_reg_out, data_reg_out; + logic [1:0] direction_out; + logic [5:0] next_state_out, tape_addr_out; + + // Synchronizer sync0 (.async(btn[2]), .sync(clock), .clock(clk)); + Synchronizer sync1 (.async(~KEY[0]), .sync(Next), .clock); + Synchronizer sync2 (.async(~KEY[1]), .sync(Done), .clock); + Synchronizer sync3 (.async(SW[0]), .sync(input_data[0]), .clock); + Synchronizer sync4 (.async(SW[1]), .sync(input_data[1]), .clock); + Synchronizer sync5 (.async(SW[2]), .sync(input_data[2]), .clock); + Synchronizer sync6 (.async(SW[3]), .sync(input_data[3]), .clock); + Synchronizer sync7 (.async(SW[4]), .sync(input_data[4]), .clock); + Synchronizer sync8 (.async(SW[5]), .sync(input_data[5]), .clock); + + TuringMachine TM (.*); + + assign clock = CLOCK_50; + assign reset = ~KEY[2]; + assign LEDR[10:0] = display_out; + assign LEDR[11] = Compute_done; + assign LEDR[17:12] = tape_addr_out; + + hex_to_sevenseg hex(.hexdigit(state), .seg(HEX0)); + + assign LEDG[0] = tape_reg_out; + assign LEDG[1] = data_reg_out; + assign LEDG[4:3] = direction_out; + assign LEDG[7:5] = next_state_out; + +endmodule \ No newline at end of file diff --git a/designs/d23_zhiyingm_turing/TuringMachine/TuringMachine.qpf b/designs/d23_zhiyingm_turing/TuringMachine/TuringMachine.qpf new file mode 100644 index 0000000..24524c5 --- /dev/null +++ b/designs/d23_zhiyingm_turing/TuringMachine/TuringMachine.qpf @@ -0,0 +1,31 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 2017 Intel Corporation. All rights reserved. +# Your use of Intel Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Intel Program License +# Subscription Agreement, the Intel Quartus Prime License Agreement, +# the Intel MegaCore Function License Agreement, or other +# applicable license agreement, including, without limitation, +# that your use is for the sole purpose of programming logic +# devices manufactured by Intel and sold by Intel or its +# authorized distributors. Please refer to the applicable +# agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus Prime +# Version 16.1.2 Build 203 01/18/2017 SJ Standard Edition +# Date created = 13:21:19 May 06, 2023 +# +# -------------------------------------------------------------------------- # + +QUARTUS_VERSION = "16.1" +DATE = "13:21:19 May 06, 2023" + +# Revisions + +PROJECT_REVISION = "ChipInterface" diff --git a/designs/d23_zhiyingm_turing/TuringMachine/TuringMachine.sv b/designs/d23_zhiyingm_turing/TuringMachine/TuringMachine.sv new file mode 100644 index 0000000..901675d --- /dev/null +++ b/designs/d23_zhiyingm_turing/TuringMachine/TuringMachine.sv @@ -0,0 +1,230 @@ +`default_nettype none + +module TuringMachine + #(parameter dw = 4, // size of each word + w = 64, // number of words + aw = $clog2(w)) + (input logic [aw-1:0] input_data, + input logic clock, reset, Next, Done, + output logic [10:0] display_out, + output logic [3:0] state, + output logic tape_reg_out, data_reg_out, + output logic [1:0] direction_out, + output logic [aw-1:0] next_state_out, tape_addr_out, + output logic Compute_done); + + // control points + logic Init, NextState_en, InputAddr_en, StateAddr_ld, StateAddr_en, TapeAddr_ld, TapeAddr_en, Write_en, Read_en, ReadInput, + PrevTape_en, TapeReg_en, DataReg_en, Direction_en, Display_en, Display_rewrite; + logic [1:0] Addr_sel, Data_sel; + + // status points + logic Data_eq, Halt, Left, Tape_start, Memory_end, Tape_end; + + // connecting wires + // logic [aw-1:0] input_addr_out, memory_addr, next_state_prep, next_state_in, next_state_out, state_addr_in, state_addr_out, + // tape_addr_out, tape_min_addr_in, tape_min_addr_out, tape_init_addr, prev_tape_addr; + logic [dw-1:0] write_data, read_data; + // logic [1:0] direction_in, direction_out; + // logic tape_in, tape_reg_in, tape_reg_out, prev_tape_in, prev_tape_out, data_reg_in, data_reg_out, display_in; + logic [aw-1:0] input_addr_out, memory_addr, next_state_prep, next_state_in, state_addr_in, state_addr_out, + tape_min_addr_in, tape_min_addr_out, tape_init_addr, prev_tape_addr; + logic [1:0] direction_in; + logic tape_in, tape_reg_in, prev_tape_in, prev_tape_out, data_reg_in, display_in; + + // datapath modules & connections + Mux2to1 #(dw) mux_input_calculate (.I0(data_reg_out), .I1(input_data), .S(ReadInput), .Y(write_data)); + Counter #(aw) input_addr (.en(InputAddr_en), .clear(Init), .load(1'b0), .up(1'b1), .clock, .D(), .Q(input_addr_out)); + + assign Tape_start = input_addr_out >= tape_init_addr; + assign Memory_end = input_addr_out >= w-1; + assign Tape_end = (tape_addr_out >= w-1) || (tape_addr_out < tape_min_addr_out); + + assign state_addr_in = ((next_state_out + next_state_out + next_state_out - 'd3) << 1'b1) + (tape_in + tape_in + tape_in); + assign tape_min_addr_in = ((input_data + input_data + input_data) << 1'b1) + 1'b1; + + Mux2to1 #(aw) mux_next_state (.I0(next_state_prep), .I1(1'b1), .S(Init), .Y(next_state_in)); + Register #(aw) next_state (.en(NextState_en), .clear(1'b0), .clock, .D(next_state_in), .Q(next_state_out)); + + Counter #(aw) state_addr (.en(StateAddr_en), .clear(1'b0), .load(StateAddr_ld), .up(1'b1), .clock, .D(state_addr_in), .Q(state_addr_out)); + Counter #(aw) tape_addr (.en(TapeAddr_en), .clear(1'b0), .load(TapeAddr_ld), .up(~Left), .clock, .D(input_data), .Q(tape_addr_out)); + Register #(aw) tape_addr_init (.en(TapeAddr_ld), .clear(1'b0), .clock, .D(input_data), .Q(tape_init_addr)); + Register #(aw) tape_addr_min (.en(Init), .clear(1'b0), .clock, .D(tape_min_addr_in), .Q(tape_min_addr_out)); + assign prev_tape_addr = tape_addr_out - 'd11; + + Mux4to1 #(aw) mux_state_tape_addr (.I0(state_addr_out), .I1(tape_addr_out), .I2(prev_tape_addr), .I3(input_addr_out), .S(Addr_sel), .Y(memory_addr)); + Memory_synth #(dw, w, aw) memory (.re(Read_en), .we(Write_en), .clock, .addr(memory_addr), .data_in(write_data), .data_out(read_data)); + + Demux1to4 #(dw) demux (.I(read_data), .S(Data_sel), .Y0(data_reg_in), .Y1(direction_in), .Y2(next_state_prep), .Y3(tape_in)); + + Mux2to1 #(1) mux_tape_reg (.I0(tape_in), .I1(display_out[1]), .S(Left), .Y(tape_reg_in)); + Register #(1) tape_reg (.en(TapeReg_en), .clear(Init), .clock, .D(tape_reg_in), .Q(tape_reg_out)); + + Mux2to1 #(1) mux_prev_tape (.I0(tape_in), .I1(1'b0), .S(prev_tape_addr < tape_init_addr), .Y(prev_tape_in)); + Register #(1) prev_tape_reg (.en(PrevTape_en), .clear(Init), .clock, .D(prev_tape_in), .Q(prev_tape_out)); + + Mux2to1 #(aw) mux_display (.I0(tape_reg_out), .I1(prev_tape_out), .S(Left), .Y(display_in)); + ShiftRegister_SIPO_wRewrite #(11) display_reg (.en(Display_en), .clear(Init), .left(~Left), .rewrite(Display_rewrite), .clock, .serial(display_in), .Q(display_out)); + + Register #(1) data_reg (.en(DataReg_en), .clear(Init), .clock, .D(data_reg_in), .Q(data_reg_out)); + assign Data_eq = tape_reg_out == data_reg_out; + + Register #(aw) direction_reg (.en(Direction_en), .clear(Init), .clock, .D(direction_in), .Q(direction_out)); + assign Left = direction_out[0]; + assign Halt = direction_out[1]; + + assign Compute_done = Tape_end | Halt; + + // finite state machine + FSM fsm (.*); + +endmodule: TuringMachine + + +module FSM ( + input logic clock, reset, Next, Done, + input logic Data_eq, Halt, Left, Tape_start, Memory_end, Tape_end, + output logic Init, NextState_en, InputAddr_en, StateAddr_ld, StateAddr_en, TapeAddr_ld, TapeAddr_en, Write_en, Read_en, ReadInput, + PrevTape_en, TapeReg_en, DataReg_en, Direction_en, Display_en, Display_rewrite, + output logic [1:0] Addr_sel, Data_sel, + output logic [3:0] state); + + enum logic [3:0] {START, STATE_NUM, WAIT1, WRITE_STATE, TAPE_ADDR, FILL_TAPE1, WAIT2, WRITE_TAPE, FILL_TAPE2, READ_TAPE, READ_DATA, REWRITE_TAPE, READ_DIRECTION, READ_STATE, STOP} currState, nextState; + assign state = currState; + + // next state logic + always_comb + case (currState) + START: nextState = Next ? STATE_NUM : START; + STATE_NUM: nextState = (~Next) ? WAIT1 : STATE_NUM; + WAIT1: nextState = Next ? WRITE_STATE : (Done ? TAPE_ADDR : WAIT1); + WRITE_STATE: nextState = (~Next) ? WAIT1 : WRITE_STATE; + TAPE_ADDR: nextState = Next ? FILL_TAPE1 : TAPE_ADDR; + FILL_TAPE1: nextState = ((~Next) & Tape_start) ? WAIT2 : FILL_TAPE1; + WAIT2: nextState = Next ? WRITE_TAPE : (Done ? FILL_TAPE2 : WAIT2); + WRITE_TAPE: nextState = (~Next) ? WAIT2 : WRITE_TAPE; + FILL_TAPE2: nextState = Memory_end ? READ_TAPE : FILL_TAPE2; + READ_TAPE: nextState = READ_DATA; + READ_DATA: nextState = Next ? (Data_eq ? READ_DIRECTION : REWRITE_TAPE) : READ_DATA; + REWRITE_TAPE: nextState = READ_DIRECTION; + READ_DIRECTION: nextState = (~Next) ? READ_STATE : READ_DIRECTION; + READ_STATE: nextState = Tape_end ? STOP : READ_TAPE; + STOP: nextState = STOP; + default: nextState = currState; + endcase + + // output logic + always_comb begin + Init = 1'b0; + NextState_en = 1'b0; StateAddr_ld = 1'b0; StateAddr_en = 1'b0; + InputAddr_en = 1'b0; TapeAddr_ld = 1'b0; TapeAddr_en = 1'b0; + Addr_sel = 2'b00; Write_en = 1'b0; Read_en = 1'b1; + ReadInput = 1'b0; Data_sel = 2'b00; + PrevTape_en = 1'b0; TapeReg_en = 1'b0; DataReg_en = 1'b0; Direction_en = 1'b0; + Display_en = 1'b0; Display_rewrite = 1'b0; + case (currState) + START: + begin + Init = 1'b1; + NextState_en = 1'b1; + end + WAIT1: + if (Next) begin + ReadInput = 1'b1; + Write_en = 1'b1; + InputAddr_en = 1'b1; + Addr_sel = 2'b11; + end + TAPE_ADDR: + if (Next) begin + TapeAddr_ld = 1'b1; + end + FILL_TAPE1: + if (~Tape_start) begin + Write_en = 1'b1; + InputAddr_en = 1'b1; + Addr_sel = 2'b11; + end + WAIT2: + if (Next) begin + ReadInput = 1'b1; + Write_en = 1'b1; + InputAddr_en = 1'b1; + Addr_sel = 2'b11; + end + FILL_TAPE2: + if (Memory_end) begin + StateAddr_ld = 1'b1; + Addr_sel = 2'b01; + Read_en = 1'b1; + Data_sel = 2'b11; + TapeReg_en = 1'b1; + end else begin + Write_en = 1'b1; + InputAddr_en = 1'b1; + Addr_sel = 2'b11; + end + READ_TAPE: + begin + StateAddr_en = 1'b1; + Read_en = 1'b1; + Data_sel = 2'b00; + DataReg_en = 1'b1; + Display_en = ~Halt; + end + READ_DATA: + if (Next) begin + if (Data_eq) begin + StateAddr_en = 1'b1; + Read_en = 1'b1; + Data_sel = 2'b01; + Direction_en = 1'b1; + end else begin + Addr_sel = 2'b01; + Write_en = 1'b1; + Display_rewrite = 1'b1; + end + end + REWRITE_TAPE: + begin + StateAddr_en = 1'b1; + Read_en = 1'b1; + Data_sel = 2'b01; + Direction_en = 1'b1; + end + READ_DIRECTION: + if (~Next) begin + Read_en = 1'b1; + Data_sel = 2'b10; + NextState_en = 1'b1; + TapeAddr_en = ~Halt; + end + READ_STATE: + if (~Tape_end) begin + if (Left) begin + StateAddr_ld = 1'b1; + Addr_sel = 2'b10; + Read_en = 1'b1; + Data_sel = 2'b11; + PrevTape_en = 1'b1; + TapeReg_en = 1'b1; + end else begin + StateAddr_ld = 1'b1; + Addr_sel = 2'b01; + Read_en = 1'b1; + Data_sel = 2'b11; + TapeReg_en = 1'b1; + end + end + // STOP outputs nothing + endcase + end + + // Asynchronous state reset + always_ff @(posedge clock, posedge reset) + if (reset) + currState <= START; + else + currState <= nextState; + +endmodule: FSM \ No newline at end of file diff --git a/designs/d23_zhiyingm_turing/TuringMachine/TuringMachineFPGA_test.sv b/designs/d23_zhiyingm_turing/TuringMachine/TuringMachineFPGA_test.sv new file mode 100644 index 0000000..4ad21ab --- /dev/null +++ b/designs/d23_zhiyingm_turing/TuringMachine/TuringMachineFPGA_test.sv @@ -0,0 +1,466 @@ +`default_nettype none + +module TuringMachine_test(); + logic clock, reset_n; + + logic [7:0] base_led; + logic [23:0] led; + + logic [23:0] sw; + logic [4:0] btn; + + logic [3:0] display_sel; + logic [7:0] display; + + m_design dut (.clk100(clock), .*); + + initial begin + clock = 1'b0; + forever #5 clock = ~clock; + end + + initial begin + $monitor($time,, "input_data = %d, next = %b, done = %b, display = %b, Compute_done = %b\n", + sw[3:0], btn[0], btn[1], led[10:0], led[11]); + reset_n <= 1'b0; + btn[1:0] <= 2'b0; + @(posedge clock); + reset_n <= 1'b1; + sw <= 3; + @(posedge clock); + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b1; + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b0; + @(posedge clock); + @(posedge clock); + + sw <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b1; + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b0; + @(posedge clock); + @(posedge clock); + + sw <= 0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b1; + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b0; + @(posedge clock); + @(posedge clock); + + sw <= 2; + @(posedge clock); + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b1; + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b0; + @(posedge clock); + @(posedge clock); + + sw <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b1; + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b0; + @(posedge clock); + @(posedge clock); + + sw <= 0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b1; + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b0; + @(posedge clock); + @(posedge clock); + + sw <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b1; + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b0; + @(posedge clock); + @(posedge clock); + + sw <= 0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b1; + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b0; + @(posedge clock); + @(posedge clock); + + sw <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b1; + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b0; + @(posedge clock); + @(posedge clock); + + sw <= 3; + @(posedge clock); + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b1; + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b0; + @(posedge clock); + @(posedge clock); + + sw <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b1; + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b0; + @(posedge clock); + @(posedge clock); + + sw <= 0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b1; + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b0; + @(posedge clock); + @(posedge clock); + + sw <= 2; + @(posedge clock); + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b1; + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b0; + @(posedge clock); + @(posedge clock); + + sw <= 0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b1; + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b0; + @(posedge clock); + @(posedge clock); + + sw <= 2; + @(posedge clock); + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b1; + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b0; + @(posedge clock); + @(posedge clock); + + sw <= 3; + @(posedge clock); + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b1; + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b0; + @(posedge clock); + @(posedge clock); + + sw <= 0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b1; + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b0; + @(posedge clock); + @(posedge clock); + + sw <= 2; + @(posedge clock); + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b1; + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b0; + @(posedge clock); + @(posedge clock); + + sw <= 3; + @(posedge clock); + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b1; + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b0; + @(posedge clock); + @(posedge clock); + + sw <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b1; + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b0; + @(posedge clock); + @(posedge clock); + + sw <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b1; + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b0; + @(posedge clock); + @(posedge clock); + + sw <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b1; + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b0; + @(posedge clock); + @(posedge clock); + + sw <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b1; + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b0; + @(posedge clock); + @(posedge clock); + + sw <= 0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b1; + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b0; + @(posedge clock); + @(posedge clock); + + sw <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b1; + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b0; + @(posedge clock); + @(posedge clock); + + sw <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b1; + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b0; + @(posedge clock); + @(posedge clock); + + sw <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b1; + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b0; + @(posedge clock); + @(posedge clock); + + sw <= 0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b1; + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b0; + @(posedge clock); + @(posedge clock); + + btn[1] <= 1'b1; + @(posedge clock); + @(posedge clock); + btn[1] <= 1'b0; + @(posedge clock); + @(posedge clock); + + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b1; + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b1; + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b1; + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b1; + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b1; + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b1; + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b1; + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b1; + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b1; + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b1; + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b1; + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b1; + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b1; + @(posedge clock); + @(posedge clock); + btn[0] <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + #1 $finish; + end + +endmodule: TuringMachine_test \ No newline at end of file diff --git a/designs/d23_zhiyingm_turing/TuringMachine/TuringMachine_test.sv b/designs/d23_zhiyingm_turing/TuringMachine/TuringMachine_test.sv new file mode 100644 index 0000000..2730306 --- /dev/null +++ b/designs/d23_zhiyingm_turing/TuringMachine/TuringMachine_test.sv @@ -0,0 +1,555 @@ +`default_nettype none + +module TuringMachine_test(); + logic [5:0] input_data; + logic clock, reset, Next, Done, Compute_done; + logic [10:0] display; + logic [3:0] state; + logic tape_reg_out, data_reg_out; + logic [1:0] direction_out; + logic [5:0] next_state_out, tape_addr_out; + + TuringMachine #(4, 64) dut (.display_out(display), .*); + + initial begin + clock = 1'b0; + forever #5 clock = ~clock; + end + + initial begin + $monitor($time,, "input_data = %d, next = %b, done = %b, display = %b, Compute_done = %b\n", + input_data, Next, Done, display, Compute_done); + reset <= 1'b1; + Next <= 1'b0; Done <= 1'b0; + @(posedge clock); + reset <= 1'b0; + input_data <= 3; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 2; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 3; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 2; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 2; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 3; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 2; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 3; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + Done <= 1'b1; + @(posedge clock); + @(posedge clock); + Done <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 32; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + + input_data <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + Done <= 1'b1; + @(posedge clock); + @(posedge clock); + Done <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + + @(posedge clock); + @(posedge clock); + if ((display != 11'b00000_0_00001) || Compute_done) + $display("error\n"); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + if ((display != 11'b00000_0_00011) || Compute_done) + $display("error\n"); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + if ((display != 11'b00000_0_00111) || Compute_done) + $display("error\n"); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + if ((display != 11'b00000_0_01111) || Compute_done) + $display("error\n"); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + if ((display != 11'b00000_0_11110) || Compute_done) + $display("error\n"); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + if ((display != 11'b00000_0_11111) || Compute_done) + $display("error\n"); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + if ((display != 11'b00000_1_11111) || Compute_done) + $display("error\n"); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + if ((display != 11'b00001_1_11111) || Compute_done) + $display("error\n"); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + if ((display != 11'b00011_1_11111) || Compute_done) + $display("error\n"); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + if ((display != 11'b00111_1_11110) || Compute_done) + $display("error\n"); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + if ((display != 11'b00011_1_11111) || Compute_done) + $display("error\n"); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + if ((display != 11'b00011_1_11110) || Compute_done) + $display("error\n"); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + if ((display != 11'b00011_1_11110) || (~Compute_done)) + $display("error\n"); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + if ((display != 11'b00011_1_11110) || (~Compute_done)) + $display("error\n"); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + if ((display != 11'b00011_1_11110) || (~Compute_done)) + $display("error\n"); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + if ((display != 11'b00011_1_11110) || (~Compute_done)) + $display("error\n"); + #1 $finish; + end + +endmodule: TuringMachine_test \ No newline at end of file diff --git a/designs/d23_zhiyingm_turing/TuringMachine/TuringMachine_test1.sv b/designs/d23_zhiyingm_turing/TuringMachine/TuringMachine_test1.sv new file mode 100644 index 0000000..857bfca --- /dev/null +++ b/designs/d23_zhiyingm_turing/TuringMachine/TuringMachine_test1.sv @@ -0,0 +1,415 @@ +`default_nettype none + +module TuringMachine_test(); + logic [5:0] input_data; + logic clock, reset, Next, Done, Compute_done; + logic [10:0] display; + logic [3:0] currState; + logic tape_reg_out, data_reg_out; + logic [1:0] direction_out; + logic [5:0] next_state_out, tape_addr_out; + + TuringMachine #(4, 64) dut (.display_out(display), .*); + + initial begin + clock = 1'b0; + forever #5 clock = ~clock; + end + + initial begin + $monitor($time,, "input_data = %d, next = %b, done = %b, display = %b, Compute_done = %b\n", + input_data, Next, Done, display, Compute_done); + reset <= 1'b1; + Next <= 1'b0; Done <= 1'b0; + @(posedge clock); + reset <= 1'b0; + input_data <= 3; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 2; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 3; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 2; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 2; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 2; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 3; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + Done <= 1'b1; + @(posedge clock); + @(posedge clock); + Done <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 32; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + + input_data <= 0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + Done <= 1'b1; + @(posedge clock); + @(posedge clock); + Done <= 1'b0; + @(posedge clock); + @(posedge clock); + + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + #1 $finish; + end + +endmodule: TuringMachine_test \ No newline at end of file diff --git a/designs/d23_zhiyingm_turing/TuringMachine/TuringMachine_test2.sv b/designs/d23_zhiyingm_turing/TuringMachine/TuringMachine_test2.sv new file mode 100644 index 0000000..96d7dd5 --- /dev/null +++ b/designs/d23_zhiyingm_turing/TuringMachine/TuringMachine_test2.sv @@ -0,0 +1,369 @@ +`default_nettype none + +module TuringMachine_test(); + logic [5:0] input_data; + logic clock, reset, Next, Done, Compute_done; + logic [10:0] display; + logic [3:0] state; + logic tape_reg_out, data_reg_out; + logic [1:0] direction_out; + logic [5:0] next_state_out, tape_addr_out; + + TuringMachine #(4, 64) dut (.display_out(display), .*); + + initial begin + clock = 1'b0; + forever #5 clock = ~clock; + end + + initial begin + $monitor($time,, "input_data = %d, next = %b, done = %b, display = %b, Compute_done = %b\n", + input_data, Next, Done, display, Compute_done); + reset <= 1'b1; + Next <= 1'b0; Done <= 1'b0; + @(posedge clock); + reset <= 1'b0; + input_data <= 2; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 2; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 2; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 2; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 2; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + Done <= 1'b1; + @(posedge clock); + @(posedge clock); + Done <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 32; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + + input_data <= 0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + Done <= 1'b1; + @(posedge clock); + @(posedge clock); + Done <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + #1 $finish; + end + +endmodule: TuringMachine_test \ No newline at end of file diff --git a/designs/d23_zhiyingm_turing/TuringMachine/TuringMachine_test_inputs.txt b/designs/d23_zhiyingm_turing/TuringMachine/TuringMachine_test_inputs.txt new file mode 100644 index 0000000..97182d1 --- /dev/null +++ b/designs/d23_zhiyingm_turing/TuringMachine/TuringMachine_test_inputs.txt @@ -0,0 +1,78 @@ +3 +1 +0 +2 +1 +0 +1 +0 +1 +3 +1 +0 +2 +0 +2 +3 +0 +2 +3 +32 +1 +1 +1 +1 +0 +1 +1 +1 +0 + +3 +1 +0 +2 +0 +1 +1 +0 +1 +1 +1 +1 +1 +0 +2 +3 +0 +2 +3 +0 +0 +0 +0 +0 +0 +0 +0 +1 + +3 +1 +0 +2 +0 +1 +3 +0 +0 +2 +1 +0 +2 +1 +0 +2 +0 +1 +3 \ No newline at end of file diff --git a/designs/d23_zhiyingm_turing/TuringMachine/constrain.py b/designs/d23_zhiyingm_turing/TuringMachine/constrain.py new file mode 100644 index 0000000..f64f358 --- /dev/null +++ b/designs/d23_zhiyingm_turing/TuringMachine/constrain.py @@ -0,0 +1,7 @@ +ctx.createRectangularRegion("region", 1, 1, 1, 40) + +for cell, cellinfo in ctx.cells: + print("Floorplan", cell) + if "TuringMachine" in str(cell): + print("Constrain", cell) + ctx.constrainCellToRegion(cell, "region") diff --git a/designs/d23_zhiyingm_turing/TuringMachine/constraints.pcf b/designs/d23_zhiyingm_turing/TuringMachine/constraints.pcf new file mode 100644 index 0000000..e5ce147 --- /dev/null +++ b/designs/d23_zhiyingm_turing/TuringMachine/constraints.pcf @@ -0,0 +1,84 @@ +set_io clk100 P7 +set_io reset_n P8 + +set_io base_led[0] J11 +set_io base_led[1] K11 +set_io base_led[2] K12 +set_io base_led[3] K14 +set_io base_led[4] L12 +set_io base_led[5] L14 +set_io base_led[6] M12 +set_io base_led[7] N14 + +set_io urx P14 +set_io utx M9 + +set_io led[0] G14 +set_io led[1] F14 +set_io led[2] E12 +set_io led[3] E14 +set_io led[4] D14 +set_io led[5] C14 +set_io led[6] B14 +set_io led[7] A12 +set_io led[8] C10 +set_io led[9] C9 +set_io led[10] A11 +set_io led[11] A10 +set_io led[12] A7 +set_io led[13] A6 +set_io led[14] A4 +set_io led[15] A3 +set_io led[16] A2 +set_io led[17] A1 +set_io led[18] C3 +set_io led[19] D3 +set_io led[20] B1 +set_io led[21] C1 +set_io led[22] D1 +set_io led[23] E1 + +set_io sw[0] G12 +set_io sw[1] F12 +set_io sw[2] F11 +set_io sw[3] E11 +set_io sw[4] D12 +set_io sw[5] D11 +set_io sw[6] C12 +set_io sw[7] C11 +set_io sw[8] D10 +set_io sw[9] D9 +set_io sw[10] D7 +set_io sw[11] D6 +set_io sw[12] C7 +set_io sw[13] C6 +set_io sw[14] A5 +set_io sw[15] C5 +set_io sw[16] D5 +set_io sw[17] C4 +set_io sw[18] D4 +set_io sw[19] E4 +set_io sw[20] F4 +set_io sw[21] F3 +set_io sw[22] H4 +set_io sw[23] G4 + +set_io btn[0] G11 +set_io btn[1] H11 +set_io btn[2] H12 +set_io btn[3] J12 +set_io btn[4] P2 + +set_io display_sel[0] G3 +set_io display_sel[1] G1 +set_io display_sel[2] H1 +set_io display_sel[3] H3 + +set_io display[0] J1 +set_io display[1] J3 +set_io display[2] N1 +set_io display[3] K4 +set_io display[4] K3 +set_io display[5] L1 +set_io display[6] M1 +set_io display[7] P1 diff --git a/designs/d23_zhiyingm_turing/TuringMachine/library.sv b/designs/d23_zhiyingm_turing/TuringMachine/library.sv new file mode 100644 index 0000000..7d3a79d --- /dev/null +++ b/designs/d23_zhiyingm_turing/TuringMachine/library.sv @@ -0,0 +1,155 @@ +`default_nettype none + +module Demux1to4 // choose 1 from 4 outputs to get the input + #(parameter w = 8) + (input logic [w-1:0] I, + input logic [1:0] S, + output logic [w-1:0] Y0, Y1, Y2, Y3); + + always_comb begin + Y0 = w'('b0); Y1 = w'('b0); Y2 = w'('b0); Y3 = w'('b0); + case (S) + 2'b00: Y0 = I; + 2'b01: Y1 = I; + 2'b10: Y2 = I; + 2'b11: Y3 = I; + endcase + end + +endmodule: Demux1to4 + + +module Mux2to1 // choose 1 from 2 inputs + #(parameter w = 7) + (input logic [w-1:0] I0, I1, + input logic S, + output logic [w-1:0] Y); + + assign Y = S ? I1 : I0; + +endmodule: Mux2to1 + + +module Mux4to1 // choose 1 from 4 inputs + #(parameter w = 7) + (input logic [w-1:0] I0, I1, I2, I3, + input logic [1:0] S, + output logic [w-1:0] Y); + + always_comb begin + if (S[1]) Y = S[0] ? I3 : I2; + else Y = S[0] ? I1 : I0; + end + +endmodule: Mux4to1 + + +module DFlipFlop // stores 1 bit value + (input logic D, + input logic clock, reset_L, preset_L, + output logic Q); + + always_ff @(posedge clock, negedge reset_L, negedge preset_L) begin + // asynchronous reset and preset, active low + if (~reset_L) + Q <= 1'b0; + else if (~preset_L) + Q <= 1'b1; + else + Q <= D; + end + +endmodule: DFlipFlop + + +module Register // stores the value D + #(parameter w = 8) + (input logic en, clear, clock, + input logic [w-1:0] D, + output logic [w-1:0] Q); + + always_ff @(posedge clock) begin // synchronous clear, active high + if (en) + Q <= D; + else if (clear) + Q <= w'('b0); + end + +endmodule: Register + + +/* enable counting, clearning, loading a value from the D inputs and + determine the direction of count (up or down) */ +module Counter + #(parameter w = 8) + (input logic en, clear, load, up, clock, + input logic [w-1:0] D, + output logic [w-1:0] Q); + + always_ff @(posedge clock) begin // synchronous clear, active high + if (clear) + Q <= w'('b0); + else if (load) + Q <= D; + else if (en && up) + Q <= Q + 1'b1; + else if (en && (!up)) + Q <= Q - 1'b1; + end + +endmodule: Counter + + +module Synchronizer // protects FSM / HW from asynchronous input signal + (input logic async, clock, + output logic sync); + + logic async1; + // synchronize input through DFF twice + always_ff @(posedge clock) + async1 <= async; + + always_ff @(posedge clock) + sync <= async1; + +endmodule: Synchronizer + + +module ShiftRegister_SIPO_wRewrite + #(parameter w = 8) + (input logic en, clear, serial, left, rewrite, clock, + output logic [w-1:0] Q); + + always_ff @(posedge clock) begin + if (clear) + Q <= w'('b0); + else if (rewrite) + Q <= {Q[w-1:1], ~Q[0]}; + else if (en && left) + Q <= {Q[w-2:0], serial}; + else if (en && (~left)) + Q <= {serial, Q[w-1:1]}; + end + +endmodule: ShiftRegister_SIPO_wRewrite + + +module Memory_synth // stores a number of words, conbinational read, sequential write + #(parameter dw = 8, // size of each word + w = 16, // number of words + aw = $clog2(w)) // address width + (input logic re, we, clock, + input logic [aw-1:0] addr, + input logic [dw-1:0] data_in, + output logic [dw-1:0] data_out); + + logic [dw-1:0] M[w]; + + assign data_out = (re) ? M[addr] : 'b0; // put the read data on the bus + + always_ff @(posedge clock) begin + if (we) + M[addr] <= data_in; // synchronized write + end + +endmodule: Memory_synth \ No newline at end of file diff --git a/designs/d23_zhiyingm_turing/TuringMachine/m_design.sv b/designs/d23_zhiyingm_turing/TuringMachine/m_design.sv new file mode 100644 index 0000000..e1a8dbd --- /dev/null +++ b/designs/d23_zhiyingm_turing/TuringMachine/m_design.sv @@ -0,0 +1,100 @@ +module hex_to_sevenseg ( + input logic [3:0] hexdigit, + output logic [7:0] seg +); + + always_comb begin + seg = '1; + if (hexdigit == 4'h0) seg = 8'b1100_0000; + if (hexdigit == 4'h1) seg = 8'b1111_1001; + if (hexdigit == 4'h2) seg = 8'b1010_0100; + if (hexdigit == 4'h3) seg = 8'b1011_0000; + if (hexdigit == 4'h4) seg = 8'b1001_1001; + if (hexdigit == 4'h5) seg = 8'b1001_0010; + if (hexdigit == 4'h6) seg = 8'b1000_0010; + if (hexdigit == 4'h7) seg = 8'b1111_1000; + if (hexdigit == 4'h8) seg = 8'b1000_0000; + if (hexdigit == 4'h9) seg = 8'b1001_0000; + if (hexdigit == 4'hA) seg = 8'b1000_1000; + if (hexdigit == 4'hB) seg = 8'b1000_0011; + if (hexdigit == 4'hC) seg = 8'b1100_0110; + if (hexdigit == 4'hD) seg = 8'b1010_0001; + if (hexdigit == 4'hE) seg = 8'b1000_0110; + if (hexdigit == 4'hF) seg = 8'b1000_1110; + end + +endmodule + +module m_design ( + input logic clk100, // 100MHz clock + input logic reset_n, // Active-low reset + + output logic [7:0] base_led, // LEDs on the far right side of the board + output logic [23:0] led, // LEDs in the middle of the board + + input logic [23:0] sw, // The tiny slide-switches + input logic [4:0] btn, // The buttons + + output logic [3:0] display_sel, // Select between the 4 segments + output logic [7:0] display // Seven-segment display +); + + logic clk; // 25MHz, generated by PLL + + // 100MHz -> 25MHz + SB_PLL40_CORE #( + .FEEDBACK_PATH("SIMPLE"), + .DIVR(4'b0000), // DIVR = 0 + .DIVF(7'b0000111), // DIVF = 7 + .DIVQ(3'b101), // DIVQ = 5 + .FILTER_RANGE(3'b101) // FILTER_RANGE = 5 + ) pll ( + .LOCK(), + .RESETB(1'b1), + .BYPASS(1'b0), + .REFERENCECLK(clk100), + .PLLOUTCORE(clk) + ); + + logic [5:0] input_data; + logic clock, reset, Next, Done; + logic [10:0] display_out; + logic Compute_done; + + logic [3:0] state; + logic tape_reg_out, data_reg_out; + logic [1:0] direction_out; + logic [5:0] next_state_out, tape_addr_out; + + // Synchronizer sync0 (.async(btn[2]), .sync(clock), .clock(clk)); + Synchronizer sync1 (.async(btn[0]), .sync(Next), .clock(clk)); + Synchronizer sync2 (.async(btn[1]), .sync(Done), .clock(clk)); + Synchronizer sync3 (.async(sw[0]), .sync(input_data[0]), .clock(clk)); + Synchronizer sync4 (.async(sw[1]), .sync(input_data[1]), .clock(clk)); + Synchronizer sync5 (.async(sw[2]), .sync(input_data[2]), .clock(clk)); + Synchronizer sync6 (.async(sw[3]), .sync(input_data[3]), .clock(clk)); + Synchronizer sync7 (.async(sw[4]), .sync(input_data[4]), .clock(clk)); + Synchronizer sync8 (.async(sw[5]), .sync(input_data[5]), .clock(clk)); + + TuringMachine TM (.*); + + assign clock = clk; + assign reset = ~reset_n; + // assign input_data = sw[3:0]; + assign led[10:0] = display_out; + assign led[11] = Compute_done; + + hex_to_sevenseg hex(.hexdigit(state), .seg(display)); + assign display_sel = 4'b1110; + + assign base_led[0] = tape_reg_out; + assign base_led[1] = data_reg_out; + assign base_led[4:3] = direction_out; + assign base_led[7:5] = next_state_out; + assign led[23:18] = tape_addr_out; + + // assign led[15] = clock; + assign led[14] = Done; + assign led[13] = Next; + +endmodule \ No newline at end of file diff --git a/designs/d23_zhiyingm_turing/info.yaml b/designs/d23_zhiyingm_turing/info.yaml new file mode 100644 index 0000000..61d6426 --- /dev/null +++ b/designs/d23_zhiyingm_turing/info.yaml @@ -0,0 +1,9 @@ +--- +project: + source_files: + - toplevel_chip.v + - chip.sv + - TuringMachine.sv + - library.sv + top_module: "toplevel_chip" + diff --git a/designs/d23_zhiyingm_turing/media/Datapath.jpg b/designs/d23_zhiyingm_turing/media/Datapath.jpg new file mode 100644 index 0000000..798da66 Binary files /dev/null and b/designs/d23_zhiyingm_turing/media/Datapath.jpg differ diff --git a/designs/d23_zhiyingm_turing/media/FPGA1.jpg b/designs/d23_zhiyingm_turing/media/FPGA1.jpg new file mode 100644 index 0000000..e5d8b72 Binary files /dev/null and b/designs/d23_zhiyingm_turing/media/FPGA1.jpg differ diff --git a/designs/d23_zhiyingm_turing/media/FPGA2.jpg b/designs/d23_zhiyingm_turing/media/FPGA2.jpg new file mode 100644 index 0000000..9aa9b92 Binary files /dev/null and b/designs/d23_zhiyingm_turing/media/FPGA2.jpg differ diff --git a/designs/d23_zhiyingm_turing/media/FSM.jpg b/designs/d23_zhiyingm_turing/media/FSM.jpg new file mode 100644 index 0000000..03be7a7 Binary files /dev/null and b/designs/d23_zhiyingm_turing/media/FSM.jpg differ diff --git a/designs/d23_zhiyingm_turing/media/IO.jpg b/designs/d23_zhiyingm_turing/media/IO.jpg new file mode 100644 index 0000000..c8d8c76 Binary files /dev/null and b/designs/d23_zhiyingm_turing/media/IO.jpg differ diff --git a/designs/d23_zhiyingm_turing/src/TuringMachine.sv b/designs/d23_zhiyingm_turing/src/TuringMachine.sv new file mode 100644 index 0000000..b3a2953 --- /dev/null +++ b/designs/d23_zhiyingm_turing/src/TuringMachine.sv @@ -0,0 +1,220 @@ +`default_nettype none + +module TuringMachine + #(parameter dw = 4, // size of each word + w = 64, // number of words + aw = $clog2(w)) + (input logic [aw-1:0] input_data, + input logic clock, reset, Next, Done, + output logic [10:0] display_out, + output logic Compute_done); + + // control points + logic Init, NextState_en, InputAddr_en, StateAddr_ld, StateAddr_en, TapeAddr_ld, TapeAddr_en, Write_en, Read_en, ReadInput, + PrevTape_en, TapeReg_en, DataReg_en, Direction_en, Display_en, Display_rewrite; + logic [1:0] Addr_sel, Data_sel; + + // status points + logic Data_eq, Halt, Left, Tape_start, Memory_end, Tape_end; + + // connecting wires + logic [aw-1:0] input_addr_out, memory_addr, next_state_prep, next_state_in, next_state_out, state_addr_in, state_addr_out, + tape_addr_out, tape_min_addr_in, tape_min_addr_out, tape_init_addr, prev_tape_addr; + logic [dw-1:0] write_data, read_data; + logic [1:0] direction_in, direction_out; + logic tape_in, tape_reg_in, tape_reg_out, prev_tape_in, prev_tape_out, data_reg_in, data_reg_out, display_in; + + // datapath modules & connections + Mux2to1 #(dw) mux_input_calculate (.I0(data_reg_out), .I1(input_data), .S(ReadInput), .Y(write_data)); + Counter #(aw) input_addr (.en(InputAddr_en), .clear(Init), .load(1'b0), .up(1'b1), .clock, .D(), .Q(input_addr_out)); + + assign Tape_start = input_addr_out >= tape_init_addr; + assign Memory_end = input_addr_out >= w-1; + assign Tape_end = (tape_addr_out >= w-1) || (tape_addr_out < tape_min_addr_out); + + assign state_addr_in = ((next_state_out + next_state_out + next_state_out - 'd3) << 1'b1) + (tape_in + tape_in + tape_in); + assign tape_min_addr_in = ((input_data + input_data + input_data) << 1'b1) + 1'b1; + + Mux2to1 #(aw) mux_next_state (.I0(next_state_prep), .I1(1'b1), .S(Init), .Y(next_state_in)); + Register #(aw) next_state (.en(NextState_en), .clear(1'b0), .clock, .D(next_state_in), .Q(next_state_out)); + + Counter #(aw) state_addr (.en(StateAddr_en), .clear(1'b0), .load(StateAddr_ld), .up(1'b1), .clock, .D(state_addr_in), .Q(state_addr_out)); + Counter #(aw) tape_addr (.en(TapeAddr_en), .clear(1'b0), .load(TapeAddr_ld), .up(~Left), .clock, .D(input_data), .Q(tape_addr_out)); + Register #(aw) tape_addr_init (.en(TapeAddr_ld), .clear(1'b0), .clock, .D(input_data), .Q(tape_init_addr)); + Register #(aw) tape_addr_min (.en(Init), .clear(1'b0), .clock, .D(tape_min_addr_in), .Q(tape_min_addr_out)); + assign prev_tape_addr = tape_addr_out - 'd11; + + Mux4to1 #(aw) mux_state_tape_addr (.I0(state_addr_out), .I1(tape_addr_out), .I2(prev_tape_addr), .I3(input_addr_out), .S(Addr_sel), .Y(memory_addr)); + Memory_synth #(dw, w, aw) memory (.re(Read_en), .we(Write_en), .clock, .addr(memory_addr), .data_in(write_data), .data_out(read_data)); + + Demux1to4 #(dw) demux (.I(read_data), .S(Data_sel), .Y0(data_reg_in), .Y1(direction_in), .Y2(next_state_prep), .Y3(tape_in)); + + Mux2to1 #(1) mux_tape_reg (.I0(tape_in), .I1(display_out[1]), .S(Left), .Y(tape_reg_in)); + Register #(1) tape_reg (.en(TapeReg_en), .clear(Init), .clock, .D(tape_reg_in), .Q(tape_reg_out)); + + Mux2to1 #(1) mux_prev_tape (.I0(tape_in), .I1(1'b0), .S(prev_tape_addr < tape_init_addr), .Y(prev_tape_in)); + Register #(1) prev_tape_reg (.en(PrevTape_en), .clear(Init), .clock, .D(prev_tape_in), .Q(prev_tape_out)); + + Mux2to1 #(aw) mux_display (.I0(tape_reg_out), .I1(prev_tape_out), .S(Left), .Y(display_in)); + ShiftRegister_SIPO_wRewrite #(11) display_reg (.en(Display_en), .clear(Init), .left(~Left), .rewrite(Display_rewrite), .clock, .serial(display_in), .Q(display_out)); + + Register #(1) data_reg (.en(DataReg_en), .clear(Init), .clock, .D(data_reg_in), .Q(data_reg_out)); + assign Data_eq = tape_reg_out == data_reg_out; + + Register #(aw) direction_reg (.en(Direction_en), .clear(Init), .clock, .D(direction_in), .Q(direction_out)); + assign Left = direction_out[0]; + assign Halt = direction_out[1]; + + assign Compute_done = Tape_end | Halt; + + // finite state machine + FSM fsm (.*); + +endmodule: TuringMachine + + +module FSM ( + input logic clock, reset, Next, Done, + input logic Data_eq, Halt, Left, Tape_start, Memory_end, Tape_end, + output logic Init, NextState_en, InputAddr_en, StateAddr_ld, StateAddr_en, TapeAddr_ld, TapeAddr_en, Write_en, Read_en, ReadInput, + PrevTape_en, TapeReg_en, DataReg_en, Direction_en, Display_en, Display_rewrite, + output logic [1:0] Addr_sel, Data_sel); + + enum logic [3:0] {START, STATE_NUM, WAIT1, WRITE_STATE, TAPE_ADDR, FILL_TAPE1, WAIT2, WRITE_TAPE, FILL_TAPE2, READ_TAPE, READ_DATA, REWRITE_TAPE, READ_DIRECTION, READ_STATE, STOP} currState, nextState; + + // next state logic + always_comb + case (currState) + START: nextState = Next ? STATE_NUM : START; + STATE_NUM: nextState = (~Next) ? WAIT1 : STATE_NUM; + WAIT1: nextState = Next ? WRITE_STATE : (Done ? TAPE_ADDR : WAIT1); + WRITE_STATE: nextState = (~Next) ? WAIT1 : WRITE_STATE; + TAPE_ADDR: nextState = Next ? FILL_TAPE1 : TAPE_ADDR; + FILL_TAPE1: nextState = ((~Next) & Tape_start) ? WAIT2 : FILL_TAPE1; + WAIT2: nextState = Next ? WRITE_TAPE : (Done ? FILL_TAPE2 : WAIT2); + WRITE_TAPE: nextState = (~Next) ? WAIT2 : WRITE_TAPE; + FILL_TAPE2: nextState = Memory_end ? READ_TAPE : FILL_TAPE2; + READ_TAPE: nextState = READ_DATA; + READ_DATA: nextState = Next ? (Data_eq ? READ_DIRECTION : REWRITE_TAPE) : READ_DATA; + REWRITE_TAPE: nextState = READ_DIRECTION; + READ_DIRECTION: nextState = (~Next) ? READ_STATE : READ_DIRECTION; + READ_STATE: nextState = Tape_end ? STOP : READ_TAPE; + STOP: nextState = STOP; + default: nextState = currState; + endcase + + // output logic + always_comb begin + Init = 1'b0; + NextState_en = 1'b0; StateAddr_ld = 1'b0; StateAddr_en = 1'b0; + InputAddr_en = 1'b0; TapeAddr_ld = 1'b0; TapeAddr_en = 1'b0; + Addr_sel = 2'b00; Write_en = 1'b0; Read_en = 1'b1; + ReadInput = 1'b0; Data_sel = 2'b00; + PrevTape_en = 1'b0; TapeReg_en = 1'b0; DataReg_en = 1'b0; Direction_en = 1'b0; + Display_en = 1'b0; Display_rewrite = 1'b0; + case (currState) + START: + begin + Init = 1'b1; + NextState_en = 1'b1; + end + WAIT1: + if (Next) begin + ReadInput = 1'b1; + Write_en = 1'b1; + InputAddr_en = 1'b1; + Addr_sel = 2'b11; + end + TAPE_ADDR: + if (Next) begin + TapeAddr_ld = 1'b1; + end + FILL_TAPE1: + if (~Tape_start) begin + Write_en = 1'b1; + InputAddr_en = 1'b1; + Addr_sel = 2'b11; + end + WAIT2: + if (Next) begin + ReadInput = 1'b1; + Write_en = 1'b1; + InputAddr_en = 1'b1; + Addr_sel = 2'b11; + end + FILL_TAPE2: + if (Memory_end) begin + StateAddr_ld = 1'b1; + Addr_sel = 2'b01; + Read_en = 1'b1; + Data_sel = 2'b11; + TapeReg_en = 1'b1; + end else begin + Write_en = 1'b1; + InputAddr_en = 1'b1; + Addr_sel = 2'b11; + end + READ_TAPE: + begin + StateAddr_en = 1'b1; + Read_en = 1'b1; + Data_sel = 2'b00; + DataReg_en = 1'b1; + Display_en = ~Halt; + end + READ_DATA: + if (Next) begin + if (Data_eq) begin + StateAddr_en = 1'b1; + Read_en = 1'b1; + Data_sel = 2'b01; + Direction_en = 1'b1; + end else begin + Addr_sel = 2'b01; + Write_en = 1'b1; + Display_rewrite = 1'b1; + end + end + REWRITE_TAPE: + begin + StateAddr_en = 1'b1; + Read_en = 1'b1; + Data_sel = 2'b01; + Direction_en = 1'b1; + end + READ_DIRECTION: + if (~Next) begin + Read_en = 1'b1; + Data_sel = 2'b10; + NextState_en = 1'b1; + TapeAddr_en = ~Halt; + end + READ_STATE: + if (~Tape_end) begin + if (Left) begin + StateAddr_ld = 1'b1; + Addr_sel = 2'b10; + Read_en = 1'b1; + Data_sel = 2'b11; + PrevTape_en = 1'b1; + TapeReg_en = 1'b1; + end else begin + StateAddr_ld = 1'b1; + Addr_sel = 2'b01; + Read_en = 1'b1; + Data_sel = 2'b11; + TapeReg_en = 1'b1; + end + end + // STOP outputs nothing + endcase + end + + // Asynchronous state reset + always_ff @(posedge clock, posedge reset) + if (reset) + currState <= START; + else + currState <= nextState; + +endmodule: FSM \ No newline at end of file diff --git a/designs/d23_zhiyingm_turing/src/TuringMachine_test.sv b/designs/d23_zhiyingm_turing/src/TuringMachine_test.sv new file mode 100644 index 0000000..d8616cb --- /dev/null +++ b/designs/d23_zhiyingm_turing/src/TuringMachine_test.sv @@ -0,0 +1,498 @@ +`default_nettype none + +module TuringMachine_test(); + logic [3:0] input_data; + logic clock, reset, Next, Done, Compute_done; + logic [10:0] display; + logic [3:0] currState; + logic display_in, tape_reg_out, data_reg_out; + logic [5:0] next_state_out, tape_addr_out; + + TuringMachine #(4, 64) dut (.display_out(display), .*); + + initial begin + clock = 1'b0; + forever #5 clock = ~clock; + end + + initial begin + $monitor($time,, "input_data = %d, next = %b, done = %b, display = %b, Compute_done = %b\n", + input_data, Next, Done, display, Compute_done); + reset <= 1'b1; + Next <= 1'b0; Done <= 1'b0; + @(posedge clock); + reset <= 1'b0; + input_data <= 3; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 2; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 3; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 2; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 2; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 3; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 2; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 3; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + input_data <= 0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + + Done <= 1'b1; + @(posedge clock); + @(posedge clock); + Done <= 1'b0; + @(posedge clock); + @(posedge clock); + + @(posedge clock); + @(posedge clock); + if ((display != 11'b00000_0_00001) || Compute_done) + $display("error\n"); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + if ((display != 11'b00000_0_00011) || Compute_done) + $display("error\n"); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + if ((display != 11'b00000_0_00111) || Compute_done) + $display("error\n"); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + if ((display != 11'b00000_0_01111) || Compute_done) + $display("error\n"); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + if ((display != 11'b00000_0_11110) || Compute_done) + $display("error\n"); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + if ((display != 11'b00000_0_11111) || Compute_done) + $display("error\n"); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + if ((display != 11'b00000_1_11111) || Compute_done) + $display("error\n"); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + if ((display != 11'b00001_1_11111) || Compute_done) + $display("error\n"); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + if ((display != 11'b00011_1_11111) || Compute_done) + $display("error\n"); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + if ((display != 11'b00111_1_11110) || Compute_done) + $display("error\n"); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + if ((display != 11'b00011_1_11111) || Compute_done) + $display("error\n"); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + if ((display != 11'b00011_1_11110) || Compute_done) + $display("error\n"); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + if ((display != 11'b00011_1_11110) || (~Compute_done)) + $display("error\n"); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + if ((display != 11'b00011_1_11110) || (~Compute_done)) + $display("error\n"); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + if ((display != 11'b00011_1_11110) || (~Compute_done)) + $display("error\n"); + Next <= 1'b1; + @(posedge clock); + @(posedge clock); + Next <= 1'b0; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + if ((display != 11'b00011_1_11110) || (~Compute_done)) + $display("error\n"); + #1 $finish; + end + +endmodule: TuringMachine_test \ No newline at end of file diff --git a/designs/d23_zhiyingm_turing/src/chip.sv b/designs/d23_zhiyingm_turing/src/chip.sv new file mode 100644 index 0000000..8f61020 --- /dev/null +++ b/designs/d23_zhiyingm_turing/src/chip.sv @@ -0,0 +1,24 @@ +`default_nettype none + +module my_chip ( + input logic [11:0] io_in, // Inputs to your chip + output logic [11:0] io_out, // Outputs from your chip + input logic clock, + input logic reset // Important: Reset is ACTIVE-HIGH +); + logic [6:0] input_data; + logic Next, Done; + + Synchronizer sync1 (.async(io_in[1]), .sync(Next), .clock); + Synchronizer sync2 (.async(io_in[0]), .sync(Done), .clock); + Synchronizer sync3 (.async(io_in[2]), .sync(input_data[0]), .clock); + Synchronizer sync4 (.async(io_in[3]), .sync(input_data[1]), .clock); + Synchronizer sync5 (.async(io_in[4]), .sync(input_data[2]), .clock); + Synchronizer sync6 (.async(io_in[5]), .sync(input_data[3]), .clock); + Synchronizer sync7 (.async(io_in[6]), .sync(input_data[4]), .clock); + Synchronizer sync8 (.async(io_in[7]), .sync(input_data[5]), .clock); + + TuringMachine #(5, 128) dut (.clock, .reset, .input_data, .Next, .Done, + .display_out(io_out[11:1]), .Compute_done(io_out[0])); + +endmodule diff --git a/designs/d23_zhiyingm_turing/src/config.tcl b/designs/d23_zhiyingm_turing/src/config.tcl new file mode 100644 index 0000000..aa589e4 --- /dev/null +++ b/designs/d23_zhiyingm_turing/src/config.tcl @@ -0,0 +1,68 @@ +# PLEASE DO NOT EDIT THIS FILE! +# IT WILL MAKE YOUR CHIP UNMANUFACTURABLE +# The only line you may edit is FP_CORE_UTIL +# (may benefit from reducing it slightly) + +# User config +set script_dir [file dirname [file normalize [info script]]] + +# read some user config that is written by the setup.py program. +# - the name of the module is defined +# - the list of source files +source $::env(DESIGN_DIR)/user_config.tcl + +# save some time +set ::env(RUN_KLAYOUT_XOR) 0 +set ::env(RUN_KLAYOUT_DRC) 0 + +# don't put clock buffers on the outputs +set ::env(PL_RESIZER_BUFFER_OUTPUT_PORTS) 0 + +# allow use of specific sky130 cells +set ::env(SYNTH_READ_BLACKBOX_LIB) 1 + +# put all the pins on the left +set ::env(FP_PIN_ORDER_CFG) $::env(DESIGN_DIR)/pin_order.cfg + +# reduce wasted space +set ::env(TOP_MARGIN_MULT) 2 +set ::env(BOTTOM_MARGIN_MULT) 2 + +# absolute die size +set ::env(FP_SIZING) absolute +set ::env(DIE_AREA) "0 0 280 280" + +## THIS IS THE ONLY LINE YOU CAN EDIT +set ::env(FP_CORE_UTIL) 45 + +## set ::env(PL_BASIC_PLACEMENT) {1} + +set ::env(FP_IO_HLENGTH) 2 +set ::env(FP_IO_VLENGTH) 2 + +# use alternative efabless decap cells to solve LI density issue +set ::env(DECAP_CELL) "\ + sky130_fd_sc_hd__decap_3 \ + sky130_fd_sc_hd__decap_4 \ + sky130_fd_sc_hd__decap_6 \ + sky130_fd_sc_hd__decap_8 \ + sky130_ef_sc_hd__decap_12" + +# clock +set ::env(CLOCK_TREE_SYNTH) 1 + +# period is in ns, so 500ns == 2 MHz +set ::env(CLOCK_PERIOD) "500" +set ::env(CLOCK_PORT) {io_in[12]} + +# hold/slack margin +# set ::env(PL_RESIZER_HOLD_SLACK_MARGIN) 0.8 +# set ::env(GLB_RESIZER_HOLD_SLACK_MARGIN) 0.8 + +# don't use power rings or met5 +set ::env(DESIGN_IS_CORE) 0 +set ::env(RT_MAX_LAYER) {met4} + +# connect to first digital rails +set ::env(VDD_NETS) [list {vccd1}] +set ::env(GND_NETS) [list {vssd1}] diff --git a/designs/d23_zhiyingm_turing/src/decoder.v b/designs/d23_zhiyingm_turing/src/decoder.v new file mode 100644 index 0000000..8d6310e --- /dev/null +++ b/designs/d23_zhiyingm_turing/src/decoder.v @@ -0,0 +1,38 @@ + +/* + -- 1 -- + | | + 6 2 + | | + -- 7 -- + | | + 5 3 + | | + -- 4 -- +*/ + +module seg7 ( + input wire [3:0] counter, + output reg [6:0] segments +); + + always @(*) begin + case(counter) + // 7654321 + 0: segments = 7'b0111111; + 1: segments = 7'b0000110; + 2: segments = 7'b1011011; + 3: segments = 7'b1001111; + 4: segments = 7'b1100110; + 5: segments = 7'b1101101; + 6: segments = 7'b1111100; + 7: segments = 7'b0000111; + 8: segments = 7'b1111111; + 9: segments = 7'b1100111; + default: + segments = 7'b0000000; + endcase + end + +endmodule + diff --git a/designs/d23_zhiyingm_turing/src/library.sv b/designs/d23_zhiyingm_turing/src/library.sv new file mode 100644 index 0000000..7d3a79d --- /dev/null +++ b/designs/d23_zhiyingm_turing/src/library.sv @@ -0,0 +1,155 @@ +`default_nettype none + +module Demux1to4 // choose 1 from 4 outputs to get the input + #(parameter w = 8) + (input logic [w-1:0] I, + input logic [1:0] S, + output logic [w-1:0] Y0, Y1, Y2, Y3); + + always_comb begin + Y0 = w'('b0); Y1 = w'('b0); Y2 = w'('b0); Y3 = w'('b0); + case (S) + 2'b00: Y0 = I; + 2'b01: Y1 = I; + 2'b10: Y2 = I; + 2'b11: Y3 = I; + endcase + end + +endmodule: Demux1to4 + + +module Mux2to1 // choose 1 from 2 inputs + #(parameter w = 7) + (input logic [w-1:0] I0, I1, + input logic S, + output logic [w-1:0] Y); + + assign Y = S ? I1 : I0; + +endmodule: Mux2to1 + + +module Mux4to1 // choose 1 from 4 inputs + #(parameter w = 7) + (input logic [w-1:0] I0, I1, I2, I3, + input logic [1:0] S, + output logic [w-1:0] Y); + + always_comb begin + if (S[1]) Y = S[0] ? I3 : I2; + else Y = S[0] ? I1 : I0; + end + +endmodule: Mux4to1 + + +module DFlipFlop // stores 1 bit value + (input logic D, + input logic clock, reset_L, preset_L, + output logic Q); + + always_ff @(posedge clock, negedge reset_L, negedge preset_L) begin + // asynchronous reset and preset, active low + if (~reset_L) + Q <= 1'b0; + else if (~preset_L) + Q <= 1'b1; + else + Q <= D; + end + +endmodule: DFlipFlop + + +module Register // stores the value D + #(parameter w = 8) + (input logic en, clear, clock, + input logic [w-1:0] D, + output logic [w-1:0] Q); + + always_ff @(posedge clock) begin // synchronous clear, active high + if (en) + Q <= D; + else if (clear) + Q <= w'('b0); + end + +endmodule: Register + + +/* enable counting, clearning, loading a value from the D inputs and + determine the direction of count (up or down) */ +module Counter + #(parameter w = 8) + (input logic en, clear, load, up, clock, + input logic [w-1:0] D, + output logic [w-1:0] Q); + + always_ff @(posedge clock) begin // synchronous clear, active high + if (clear) + Q <= w'('b0); + else if (load) + Q <= D; + else if (en && up) + Q <= Q + 1'b1; + else if (en && (!up)) + Q <= Q - 1'b1; + end + +endmodule: Counter + + +module Synchronizer // protects FSM / HW from asynchronous input signal + (input logic async, clock, + output logic sync); + + logic async1; + // synchronize input through DFF twice + always_ff @(posedge clock) + async1 <= async; + + always_ff @(posedge clock) + sync <= async1; + +endmodule: Synchronizer + + +module ShiftRegister_SIPO_wRewrite + #(parameter w = 8) + (input logic en, clear, serial, left, rewrite, clock, + output logic [w-1:0] Q); + + always_ff @(posedge clock) begin + if (clear) + Q <= w'('b0); + else if (rewrite) + Q <= {Q[w-1:1], ~Q[0]}; + else if (en && left) + Q <= {Q[w-2:0], serial}; + else if (en && (~left)) + Q <= {serial, Q[w-1:1]}; + end + +endmodule: ShiftRegister_SIPO_wRewrite + + +module Memory_synth // stores a number of words, conbinational read, sequential write + #(parameter dw = 8, // size of each word + w = 16, // number of words + aw = $clog2(w)) // address width + (input logic re, we, clock, + input logic [aw-1:0] addr, + input logic [dw-1:0] data_in, + output logic [dw-1:0] data_out); + + logic [dw-1:0] M[w]; + + assign data_out = (re) ? M[addr] : 'b0; // put the read data on the bus + + always_ff @(posedge clock) begin + if (we) + M[addr] <= data_in; // synchronized write + end + +endmodule: Memory_synth \ No newline at end of file diff --git a/designs/d23_zhiyingm_turing/src/pin_order.cfg b/designs/d23_zhiyingm_turing/src/pin_order.cfg new file mode 100644 index 0000000..0b85c63 --- /dev/null +++ b/designs/d23_zhiyingm_turing/src/pin_order.cfg @@ -0,0 +1,9 @@ +#N + +#S + +#E + +#W +io_in.* +io_out.* diff --git a/designs/d23_zhiyingm_turing/src/toplevel_chip.v b/designs/d23_zhiyingm_turing/src/toplevel_chip.v new file mode 100644 index 0000000..a82b427 --- /dev/null +++ b/designs/d23_zhiyingm_turing/src/toplevel_chip.v @@ -0,0 +1,18 @@ +`default_nettype none + +// DO NOT EDIT THIS FILE +module toplevel_chip ( + input [13:0] io_in, + output [13:0] io_out +); + + my_chip mchip ( + .io_in(io_in[11:0]), + .io_out(io_out[11:0]), + .clock(io_in[12]), + .reset(io_in[13]) + ); + + assign io_out[13:12] = 2'b00; + +endmodule diff --git a/designs/d24_mnguyen2_tpu/.lastupdated b/designs/d24_mnguyen2_tpu/.lastupdated new file mode 100644 index 0000000..4d7b8c3 --- /dev/null +++ b/designs/d24_mnguyen2_tpu/.lastupdated @@ -0,0 +1 @@ +2023-05-14 diff --git a/designs/d24_mnguyen2_tpu/LICENSE b/designs/d24_mnguyen2_tpu/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/designs/d24_mnguyen2_tpu/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/designs/d24_mnguyen2_tpu/Makefile b/designs/d24_mnguyen2_tpu/Makefile new file mode 100644 index 0000000..0c28a2a --- /dev/null +++ b/designs/d24_mnguyen2_tpu/Makefile @@ -0,0 +1,20 @@ +SV_FILES = src/*.sv +V_FILES = src/verilog/top.v +VH_FILES = src/*.vh +INCLUDES_DIR = src/ + +SYNTH = yosys +SYNTH_FLAGS = + +.PHONY: synth synth.verilog clean + +synth: $(SV_FILES) $(VH_FILES) + $(SYNTH) $(SYNTH_FLAGS) -c tcl/synth.tcl + +synth.verilog: $(V_FILES) + $(SYNTH) $(SYNTH_FLAGS) -c tcl/synth_verilog.tcl + +$(V_FILES): $(SV_FILES) $(VH_FILES) + sv2v -I $(INCLUDES_DIR) $(SV_FILES) > $(V_FILES) +clean: + rm $(V_FILES) diff --git a/designs/d24_mnguyen2_tpu/README.md b/designs/d24_mnguyen2_tpu/README.md new file mode 100644 index 0000000..b4b4540 --- /dev/null +++ b/designs/d24_mnguyen2_tpu/README.md @@ -0,0 +1,5 @@ +# Tensor Co-Processor + +M Nguyen Final Project, CMU 18-624: Open Source Chip Design + +- a TPU for Skywater130 diff --git a/designs/d24_mnguyen2_tpu/info.yaml b/designs/d24_mnguyen2_tpu/info.yaml new file mode 100644 index 0000000..2b2a63f --- /dev/null +++ b/designs/d24_mnguyen2_tpu/info.yaml @@ -0,0 +1,12 @@ +--- +project: + source_files: + - toplevel_chip.v + - chip.sv + - tpu.sv + - register.sv + - counter.sv + - mac.sv + - matrix.sv + top_module: "toplevel_chip" + diff --git a/designs/d24_mnguyen2_tpu/src/chip.sv b/designs/d24_mnguyen2_tpu/src/chip.sv new file mode 100644 index 0000000..0640b71 --- /dev/null +++ b/designs/d24_mnguyen2_tpu/src/chip.sv @@ -0,0 +1,20 @@ +`default_nettype none + +module my_chip ( + input logic [11:0] io_in, // Inputs to your chip + output logic [11:0] io_out, // Outputs from your chip + input logic clock, + input logic reset // Important: Reset is ACTIVE-HIGH +); + + tpu TPU(.clk(clock), .rst(reset), + .insert_kernal(io_in[0]), + .write(io_in[1]), + .write_mode(io_in[2]), + .ready(io_in[3]), + .data_in(io_in[11:4]), + .done(io_out[0]), + .data_out(io_out[11:4]) + ); + +endmodule diff --git a/designs/d24_mnguyen2_tpu/src/config.tcl b/designs/d24_mnguyen2_tpu/src/config.tcl new file mode 100644 index 0000000..aa589e4 --- /dev/null +++ b/designs/d24_mnguyen2_tpu/src/config.tcl @@ -0,0 +1,68 @@ +# PLEASE DO NOT EDIT THIS FILE! +# IT WILL MAKE YOUR CHIP UNMANUFACTURABLE +# The only line you may edit is FP_CORE_UTIL +# (may benefit from reducing it slightly) + +# User config +set script_dir [file dirname [file normalize [info script]]] + +# read some user config that is written by the setup.py program. +# - the name of the module is defined +# - the list of source files +source $::env(DESIGN_DIR)/user_config.tcl + +# save some time +set ::env(RUN_KLAYOUT_XOR) 0 +set ::env(RUN_KLAYOUT_DRC) 0 + +# don't put clock buffers on the outputs +set ::env(PL_RESIZER_BUFFER_OUTPUT_PORTS) 0 + +# allow use of specific sky130 cells +set ::env(SYNTH_READ_BLACKBOX_LIB) 1 + +# put all the pins on the left +set ::env(FP_PIN_ORDER_CFG) $::env(DESIGN_DIR)/pin_order.cfg + +# reduce wasted space +set ::env(TOP_MARGIN_MULT) 2 +set ::env(BOTTOM_MARGIN_MULT) 2 + +# absolute die size +set ::env(FP_SIZING) absolute +set ::env(DIE_AREA) "0 0 280 280" + +## THIS IS THE ONLY LINE YOU CAN EDIT +set ::env(FP_CORE_UTIL) 45 + +## set ::env(PL_BASIC_PLACEMENT) {1} + +set ::env(FP_IO_HLENGTH) 2 +set ::env(FP_IO_VLENGTH) 2 + +# use alternative efabless decap cells to solve LI density issue +set ::env(DECAP_CELL) "\ + sky130_fd_sc_hd__decap_3 \ + sky130_fd_sc_hd__decap_4 \ + sky130_fd_sc_hd__decap_6 \ + sky130_fd_sc_hd__decap_8 \ + sky130_ef_sc_hd__decap_12" + +# clock +set ::env(CLOCK_TREE_SYNTH) 1 + +# period is in ns, so 500ns == 2 MHz +set ::env(CLOCK_PERIOD) "500" +set ::env(CLOCK_PORT) {io_in[12]} + +# hold/slack margin +# set ::env(PL_RESIZER_HOLD_SLACK_MARGIN) 0.8 +# set ::env(GLB_RESIZER_HOLD_SLACK_MARGIN) 0.8 + +# don't use power rings or met5 +set ::env(DESIGN_IS_CORE) 0 +set ::env(RT_MAX_LAYER) {met4} + +# connect to first digital rails +set ::env(VDD_NETS) [list {vccd1}] +set ::env(GND_NETS) [list {vssd1}] diff --git a/designs/d24_mnguyen2_tpu/src/counter.sv b/designs/d24_mnguyen2_tpu/src/counter.sv new file mode 100644 index 0000000..1d7a820 --- /dev/null +++ b/designs/d24_mnguyen2_tpu/src/counter.sv @@ -0,0 +1,16 @@ +`default_nettype none + +module counter +#(parameter DATA_WIDTH = 8, + parameter MAX = {DATA_WIDTH{1'b1}}) + (input logic clk, rst, en, + output logic [DATA_WIDTH-1:0] Q); + + logic [DATA_WIDTH-1:0] Q_next; + assign Q_next = (Q == MAX) ? 'b0 : Q + 'b1; + always_ff @(posedge clk) + if (rst) + Q <= 'b0; + else if (en) + Q <= Q_next; +endmodule : counter diff --git a/designs/d24_mnguyen2_tpu/src/deadcode/sram.sv b/designs/d24_mnguyen2_tpu/src/deadcode/sram.sv new file mode 100644 index 0000000..b13e404 --- /dev/null +++ b/designs/d24_mnguyen2_tpu/src/deadcode/sram.sv @@ -0,0 +1,23 @@ +`default_nettype none + +module sram +#(parameter DATA_WIDTH = 8, + parameter NUM_ELEM = 8) + (input logic clk, rst, we, re, + input logic [$clog2(NUM_ELEM)-1:0] addr, + input logic [DATA_WIDTH-1:0] data_in, + output logic [DATA_WIDTH-1:0] data_out); + + logic [NUM_ELEM-1:0][DATA_WIDTH-1:0] mem; + + always_ff @(posedge clk) + if (rst) + mem <= 'b0; + else if (we) + mem[addr] <= data_in; + + always_latch + if (re) + data_out = mem[addr]; + +endmodule : sram diff --git a/designs/d24_mnguyen2_tpu/src/defines.vh b/designs/d24_mnguyen2_tpu/src/defines.vh new file mode 100644 index 0000000..1970c00 --- /dev/null +++ b/designs/d24_mnguyen2_tpu/src/defines.vh @@ -0,0 +1,8 @@ +`ifndef DEFINES_H +`define DEFINES_H + +`define DATA_WIDTH 8 + +typedef logic [`DATA_WIDTH-1:0] data_t; + +`endif diff --git a/designs/d24_mnguyen2_tpu/src/mac.sv b/designs/d24_mnguyen2_tpu/src/mac.sv new file mode 100644 index 0000000..787ba04 --- /dev/null +++ b/designs/d24_mnguyen2_tpu/src/mac.sv @@ -0,0 +1,14 @@ +`default_nettype none + +module mac +#(parameter IN_WIDTH=4, + parameter OUT_WIDTH=4) + (input logic clk, rst, en, input logic [IN_WIDTH-1:0] a, b, + output logic [OUT_WIDTH-1:0] sum); + + logic [OUT_WIDTH-1:0] new_sum, prod; + assign prod = a * b; + assign new_sum = prod + sum; + register #(OUT_WIDTH) sum_reg(.clk, .rst, .we(en), + .D(new_sum), .Q(sum)); +endmodule : mac diff --git a/designs/d24_mnguyen2_tpu/src/matrix.sv b/designs/d24_mnguyen2_tpu/src/matrix.sv new file mode 100644 index 0000000..0dc40d6 --- /dev/null +++ b/designs/d24_mnguyen2_tpu/src/matrix.sv @@ -0,0 +1,21 @@ +`default_nettype none +`include "defines.vh" + +module matrix +#(parameter MATRIX_DIM=16, + parameter LENGTH=MATRIX_DIM*MATRIX_DIM) + (input logic clk, rst, we, + input data_t D, + input logic [$clog2(LENGTH)-1:0] addr, + output data_t Q); + + data_t [LENGTH-1:0] data; + assign Q = data[addr]; + always_ff @(posedge clk) begin + if (rst) + data <= 'b0; + else if (we) + data[addr] <= D; + end + +endmodule : matrix diff --git a/designs/d24_mnguyen2_tpu/src/pin_order.cfg b/designs/d24_mnguyen2_tpu/src/pin_order.cfg new file mode 100644 index 0000000..0b85c63 --- /dev/null +++ b/designs/d24_mnguyen2_tpu/src/pin_order.cfg @@ -0,0 +1,9 @@ +#N + +#S + +#E + +#W +io_in.* +io_out.* diff --git a/designs/d24_mnguyen2_tpu/src/register.sv b/designs/d24_mnguyen2_tpu/src/register.sv new file mode 100644 index 0000000..e44fba0 --- /dev/null +++ b/designs/d24_mnguyen2_tpu/src/register.sv @@ -0,0 +1,14 @@ +`default_nettype none + +module register +#(parameter DATA_WIDTH=8) + (input logic clk, rst, we, + input logic [DATA_WIDTH-1:0] D, + output logic [DATA_WIDTH-1:0] Q); + + always_ff @(posedge clk) + if (rst) + Q <= 'b0; + else if (we) + Q <= D; +endmodule : register diff --git a/designs/d24_mnguyen2_tpu/src/toplevel_chip.v b/designs/d24_mnguyen2_tpu/src/toplevel_chip.v new file mode 100644 index 0000000..a82b427 --- /dev/null +++ b/designs/d24_mnguyen2_tpu/src/toplevel_chip.v @@ -0,0 +1,18 @@ +`default_nettype none + +// DO NOT EDIT THIS FILE +module toplevel_chip ( + input [13:0] io_in, + output [13:0] io_out +); + + my_chip mchip ( + .io_in(io_in[11:0]), + .io_out(io_out[11:0]), + .clock(io_in[12]), + .reset(io_in[13]) + ); + + assign io_out[13:12] = 2'b00; + +endmodule diff --git a/designs/d24_mnguyen2_tpu/src/tpu.sv b/designs/d24_mnguyen2_tpu/src/tpu.sv new file mode 100644 index 0000000..854c45c --- /dev/null +++ b/designs/d24_mnguyen2_tpu/src/tpu.sv @@ -0,0 +1,104 @@ +`default_nettype none +`include "defines.vh" + +module tpu +#(parameter MATRIX_DIM=32, + parameter CONV_DIM=3) + (input logic clk, rst, + input logic insert_kernal, write_mode, write, ready, + input data_t data_in, + output logic done, + output data_t data_out); + + typedef struct packed { + logic [$clog2(MATRIX_DIM)-1:0] x,y; + } base_coord_t; + + typedef struct packed { + logic [$clog2(MATRIX_DIM):0] x,y; + } matrix_coord_t; + + typedef struct packed { + logic [$clog2(CONV_DIM)-1:0] x,y; + } conv_coord_t; + + // KERNAL LOGIC + // HACK: Yosys doesn't support packed arrays https://github.com/YosysHQ/yosys/issues/340 + data_t kernal_data; + conv_coord_t kernal_addr; + logic [($clog2(CONV_DIM*CONV_DIM))-1:0] kernal_data_sel; + always_comb begin + kernal_data_sel = kernal_addr.y * CONV_DIM + + {{$clog2(CONV_DIM){1'b0}},kernal_addr.x}; + end + + matrix #(.MATRIX_DIM(CONV_DIM)) + KERNAL_MAT(.clk, .rst, .we(insert_kernal & write), + .D(data_in), .Q(kernal_data), + .addr(kernal_data_sel)); + // MATRIX LOGIC + // HACK: Yosys doesn't support packed arrays https://github.com/YosysHQ/yosys/issues/340 + data_t matrix_data; + matrix_coord_t matrix_addr; + logic [($clog2(MATRIX_DIM*MATRIX_DIM))-1:0] matrix_data_sel; + always_comb begin + if (write_mode & ~insert_kernal) + matrix_data_sel = base_addr.y[$clog2(MATRIX_DIM)-1:0] * MATRIX_DIM + + {{$clog2(MATRIX_DIM){1'b0}}, base_addr.x[$clog2(MATRIX_DIM)-1:0]}; + else + matrix_data_sel = matrix_addr.y[$clog2(MATRIX_DIM)-1:0] * MATRIX_DIM + + {{$clog2(MATRIX_DIM){1'b0}}, matrix_addr.x[$clog2(MATRIX_DIM)-1:0]}; + end + matrix #(.MATRIX_DIM(MATRIX_DIM)) + MATRIX_MAT(.clk, .rst, .we(~insert_kernal & write), + .D(data_in), .Q(matrix_data), + .addr(matrix_data_sel)); + + + // CONVOLUTION CONTROL + base_coord_t base_addr; + + logic kernal_y_incr, kernal_x_incr; + assign kernal_x_incr = (write_mode & write & insert_kernal & ready) | ~(write_mode); + assign kernal_y_incr = kernal_addr.x == CONV_DIM-1; + counter #($bits(kernal_addr.x), CONV_DIM-1) + kernal_addr_x_counter(.clk, .rst, .en(kernal_x_incr), .Q(kernal_addr.x)); + counter #($bits(kernal_addr.y), CONV_DIM-1) + kernal_addr_y_counter(.clk, .rst, .en(kernal_y_incr), .Q(kernal_addr.y)); + + logic base_y_incr, base_x_incr; + assign base_x_incr = ((& kernal_y_incr) & ~write_mode) | + (write_mode & write & ~insert_kernal); + assign base_y_incr = base_addr.x == MATRIX_DIM-1; + counter #($bits(base_addr.x)) base_addr_x_counter(.clk, .rst, .en(base_x_incr), .Q(base_addr.x)); + counter #($bits(base_addr.y)) base_addr_y_counter(.clk, .rst, .en(base_y_incr), .Q(base_addr.y)); + + parameter DIFF = $clog2(MATRIX_DIM)-$clog2(CONV_DIM); + assign matrix_addr.x = base_addr.x + {{DIFF{1'b0}}, kernal_addr.x}; + assign matrix_addr.y = base_addr.y + {{DIFF{1'b0}}, kernal_addr.y}; + + // MAC LOGIC + // TODO: double check reset logic and its interaction with Done/Ready + logic mac_en, mac_rst; + assign mac_rst = (base_x_incr & ready) | rst; + assign done = mac_rst & ~rst; + assign mac_en = ~matrix_addr.x[$clog2(MATRIX_DIM)] & ~matrix_addr.y[$clog2(MATRIX_DIM)] & ~write_mode; + mac #(`DATA_WIDTH,`DATA_WIDTH) + conv_mac (.clk, .rst(mac_rst), .en(mac_en), + .a(kernal_data), + .b(matrix_data), + .sum(data_out)); + // github synthesis workflow seems to break when it sees assertions +`ifdef SIMULATION + assertKernalData : assert property + (isKnown(kernal_data, rst, (mac_en & ~write_mode), clk)) + else $error("kernal data is unknown"); + assertmatrixData : assert property + (isKnown(matrix_data, rst, (mac_en & ~write_mode), clk)) + else $error("matrix data is unknown"); + + property isKnown(signal, reset, en, clock); + @(posedge clock) (!reset && en)|-> !$isunknown(signal); + endproperty : isKnown +`endif //SIMULATION +endmodule : tpu diff --git a/designs/d24_mnguyen2_tpu/src/verilog/top.v b/designs/d24_mnguyen2_tpu/src/verilog/top.v new file mode 100644 index 0000000..6264b91 --- /dev/null +++ b/designs/d24_mnguyen2_tpu/src/verilog/top.v @@ -0,0 +1,186 @@ +`default_nettype none +module counter ( + clk, + rst, + en, + Q +); + parameter DATA_WIDTH = 0; + input wire clk; + input wire rst; + input wire en; + output reg [DATA_WIDTH - 1:0] Q; + always @(posedge clk) + if (rst) + Q <= 'b0; + else if (en) + Q <= Q + 'b1; +endmodule +`default_nettype none +module mac ( + clk, + rst, + en, + a, + b, + sum +); + parameter IN_WIDTH = 4; + parameter OUT_WIDTH = 4; + input wire clk; + input wire rst; + input wire en; + input wire [IN_WIDTH - 1:0] a; + input wire [IN_WIDTH - 1:0] b; + output wire [OUT_WIDTH - 1:0] sum; + wire [OUT_WIDTH - 1:0] new_sum; + wire [OUT_WIDTH - 1:0] prod; + assign prod = a * b; + assign new_sum = prod + sum; + register #(.DATA_WIDTH(OUT_WIDTH)) sum_reg( + .clk(clk), + .rst(rst), + .we(en), + .D(new_sum), + .Q(sum) + ); +endmodule +`default_nettype none +module register ( + clk, + rst, + we, + D, + Q +); + parameter DATA_WIDTH = 8; + input wire clk; + input wire rst; + input wire we; + input wire [DATA_WIDTH - 1:0] D; + output reg [DATA_WIDTH - 1:0] Q; + always @(posedge clk) + if (rst) + Q <= 'b0; + else if (we) + Q <= D; +endmodule +`default_nettype none +module tpu ( + clk, + rst, + insert_kernal, + insert_matrix, + ready, + data_in, + done, + data_out +); + parameter MATRIX_DIM = 16; + parameter CONV_DIM = 3; + input wire clk; + input wire rst; + input wire insert_kernal; + input wire insert_matrix; + input wire ready; + input wire [7:0] data_in; + output wire done; + output wire [7:0] data_out; + wire [((CONV_DIM * CONV_DIM) * 8) - 1:0] kernal_data; + wire [($clog2(CONV_DIM) + $clog2(CONV_DIM)) - 1:0] kernal_addr; + reg [(CONV_DIM * CONV_DIM) - 1:0] kernal_we; + reg [$clog2(CONV_DIM * CONV_DIM) - 1:0] kernal_data_sel; + always @(*) begin + kernal_we = 'b0; + kernal_data_sel = (kernal_addr[$clog2(CONV_DIM) + ($clog2(CONV_DIM) - 1)-:(($clog2(CONV_DIM) + ($clog2(CONV_DIM) - 1)) >= $clog2(CONV_DIM) ? (($clog2(CONV_DIM) + ($clog2(CONV_DIM) - 1)) - $clog2(CONV_DIM)) + 1 : ($clog2(CONV_DIM) - ($clog2(CONV_DIM) + ($clog2(CONV_DIM) - 1))) + 1)] * CONV_DIM) + {{$clog2(CONV_DIM) {1'b0}}, kernal_addr[$clog2(CONV_DIM) - 1-:$clog2(CONV_DIM)]}; + kernal_we[kernal_data_sel] = insert_kernal; + end + genvar i; + generate + for (i = 0; i < CONV_DIM; i = i + 1) begin : outer_loop_kernal + genvar j; + for (j = 0; j < CONV_DIM; j = j + 1) begin : inner_loop_kernal + register #(.DATA_WIDTH(8)) kernal_reg( + .clk(clk), + .rst(rst), + .we(kernal_we[(i * CONV_DIM) + j]), + .D(data_in), + .Q(kernal_data[((i * CONV_DIM) + j) * 8+:8]) + ); + end + end + endgenerate + wire [((MATRIX_DIM * MATRIX_DIM) * 8) - 1:0] matrix_data; + wire [(($clog2(MATRIX_DIM) >= 0 ? $clog2(MATRIX_DIM) + 1 : 1 - $clog2(MATRIX_DIM)) + ($clog2(MATRIX_DIM) >= 0 ? $clog2(MATRIX_DIM) + 1 : 1 - $clog2(MATRIX_DIM))) - 1:0] matrix_addr; + reg [(MATRIX_DIM * MATRIX_DIM) - 1:0] matrix_we; + reg [$clog2(MATRIX_DIM * MATRIX_DIM) - 1:0] matrix_data_sel; + always @(*) begin + matrix_we = 'b0; + matrix_data_sel = (matrix_addr[($clog2(MATRIX_DIM) >= 0 ? (($clog2(MATRIX_DIM) >= 0 ? $clog2(MATRIX_DIM) + 1 : 1 - $clog2(MATRIX_DIM)) + (($clog2(MATRIX_DIM) >= 0 ? $clog2(MATRIX_DIM) + 1 : 1 - $clog2(MATRIX_DIM)) - 1)) - ($clog2(MATRIX_DIM) - ($clog2(MATRIX_DIM) - 1)) : ($clog2(MATRIX_DIM) >= 0 ? $clog2(MATRIX_DIM) + 1 : 1 - $clog2(MATRIX_DIM)) + (1 - $clog2(MATRIX_DIM))):($clog2(MATRIX_DIM) >= 0 ? (($clog2(MATRIX_DIM) >= 0 ? $clog2(MATRIX_DIM) + 1 : 1 - $clog2(MATRIX_DIM)) + (($clog2(MATRIX_DIM) >= 0 ? $clog2(MATRIX_DIM) + 1 : 1 - $clog2(MATRIX_DIM)) - 1)) - $clog2(MATRIX_DIM) : ($clog2(MATRIX_DIM) >= 0 ? $clog2(MATRIX_DIM) + 1 : 1 - $clog2(MATRIX_DIM)))] * MATRIX_DIM) + {{$clog2(MATRIX_DIM) {1'b0}}, matrix_addr[($clog2(MATRIX_DIM) >= 0 ? (($clog2(MATRIX_DIM) >= 0 ? $clog2(MATRIX_DIM) + 1 : 1 - $clog2(MATRIX_DIM)) - 1) - ($clog2(MATRIX_DIM) - ($clog2(MATRIX_DIM) - 1)) : 1 - $clog2(MATRIX_DIM)):($clog2(MATRIX_DIM) >= 0 ? (($clog2(MATRIX_DIM) >= 0 ? $clog2(MATRIX_DIM) + 1 : 1 - $clog2(MATRIX_DIM)) - 1) - $clog2(MATRIX_DIM) : 0)]}; + matrix_we[matrix_data_sel] = insert_matrix; + end + generate + for (i = 0; i < MATRIX_DIM; i = i + 1) begin : outer_loop_matrix + genvar j; + for (j = 0; j < MATRIX_DIM; j = j + 1) begin : inner_loop_matrix + register #(.DATA_WIDTH(8)) matrix_reg( + .clk(clk), + .rst(rst), + .we(matrix_we[(i * MATRIX_DIM) + j]), + .D(data_in), + .Q(matrix_data[((i * MATRIX_DIM) + j) * 8+:8]) + ); + end + end + endgenerate + wire [($clog2(MATRIX_DIM) + $clog2(MATRIX_DIM)) - 1:0] base_addr; + wire kernal_y_incr; + assign kernal_y_incr = &kernal_addr[$clog2(CONV_DIM) + ($clog2(CONV_DIM) - 1)-:(($clog2(CONV_DIM) + ($clog2(CONV_DIM) - 1)) >= $clog2(CONV_DIM) ? (($clog2(CONV_DIM) + ($clog2(CONV_DIM) - 1)) - $clog2(CONV_DIM)) + 1 : ($clog2(CONV_DIM) - ($clog2(CONV_DIM) + ($clog2(CONV_DIM) - 1))) + 1)]; + counter #(.DATA_WIDTH((($clog2(CONV_DIM) + ($clog2(CONV_DIM) - 1)) >= $clog2(CONV_DIM) ? (($clog2(CONV_DIM) + ($clog2(CONV_DIM) - 1)) - $clog2(CONV_DIM)) + 1 : ($clog2(CONV_DIM) - ($clog2(CONV_DIM) + ($clog2(CONV_DIM) - 1))) + 1))) kernal_addr_x_counter( + .clk(clk), + .rst(rst), + .en(1'b1), + .Q(kernal_addr[$clog2(CONV_DIM) + ($clog2(CONV_DIM) - 1)-:(($clog2(CONV_DIM) + ($clog2(CONV_DIM) - 1)) >= $clog2(CONV_DIM) ? (($clog2(CONV_DIM) + ($clog2(CONV_DIM) - 1)) - $clog2(CONV_DIM)) + 1 : ($clog2(CONV_DIM) - ($clog2(CONV_DIM) + ($clog2(CONV_DIM) - 1))) + 1)]) + ); + counter #(.DATA_WIDTH($clog2(CONV_DIM))) kernal_addr_y_counter( + .clk(clk), + .rst(rst), + .en(kernal_y_incr), + .Q(kernal_addr[$clog2(CONV_DIM) - 1-:$clog2(CONV_DIM)]) + ); + wire base_y_incr; + wire base_x_incr; + assign base_x_incr = &kernal_y_incr; + assign base_y_incr = &base_addr[$clog2(MATRIX_DIM) + ($clog2(MATRIX_DIM) - 1)-:(($clog2(MATRIX_DIM) + ($clog2(MATRIX_DIM) - 1)) >= $clog2(MATRIX_DIM) ? (($clog2(MATRIX_DIM) + ($clog2(MATRIX_DIM) - 1)) - $clog2(MATRIX_DIM)) + 1 : ($clog2(MATRIX_DIM) - ($clog2(MATRIX_DIM) + ($clog2(MATRIX_DIM) - 1))) + 1)]; + counter #(.DATA_WIDTH((($clog2(MATRIX_DIM) + ($clog2(MATRIX_DIM) - 1)) >= $clog2(MATRIX_DIM) ? (($clog2(MATRIX_DIM) + ($clog2(MATRIX_DIM) - 1)) - $clog2(MATRIX_DIM)) + 1 : ($clog2(MATRIX_DIM) - ($clog2(MATRIX_DIM) + ($clog2(MATRIX_DIM) - 1))) + 1))) base_addr_x_counter( + .clk(clk), + .rst(rst), + .en(base_x_incr), + .Q(base_addr[$clog2(MATRIX_DIM) + ($clog2(MATRIX_DIM) - 1)-:(($clog2(MATRIX_DIM) + ($clog2(MATRIX_DIM) - 1)) >= $clog2(MATRIX_DIM) ? (($clog2(MATRIX_DIM) + ($clog2(MATRIX_DIM) - 1)) - $clog2(MATRIX_DIM)) + 1 : ($clog2(MATRIX_DIM) - ($clog2(MATRIX_DIM) + ($clog2(MATRIX_DIM) - 1))) + 1)]) + ); + counter #(.DATA_WIDTH($clog2(MATRIX_DIM))) base_addr_y_counter( + .clk(clk), + .rst(rst), + .en(base_y_incr), + .Q(base_addr[$clog2(MATRIX_DIM) - 1-:$clog2(MATRIX_DIM)]) + ); + parameter DIFF = $clog2(MATRIX_DIM) - $clog2(CONV_DIM); + assign matrix_addr[($clog2(MATRIX_DIM) >= 0 ? $clog2(MATRIX_DIM) + 1 : 1 - $clog2(MATRIX_DIM)) + (($clog2(MATRIX_DIM) >= 0 ? $clog2(MATRIX_DIM) + 1 : 1 - $clog2(MATRIX_DIM)) - 1)-:((($clog2(MATRIX_DIM) >= 0 ? $clog2(MATRIX_DIM) + 1 : 1 - $clog2(MATRIX_DIM)) + (($clog2(MATRIX_DIM) >= 0 ? $clog2(MATRIX_DIM) + 1 : 1 - $clog2(MATRIX_DIM)) - 1)) >= ($clog2(MATRIX_DIM) >= 0 ? $clog2(MATRIX_DIM) + 1 : 1 - $clog2(MATRIX_DIM)) ? ((($clog2(MATRIX_DIM) >= 0 ? $clog2(MATRIX_DIM) + 1 : 1 - $clog2(MATRIX_DIM)) + (($clog2(MATRIX_DIM) >= 0 ? $clog2(MATRIX_DIM) + 1 : 1 - $clog2(MATRIX_DIM)) - 1)) - ($clog2(MATRIX_DIM) >= 0 ? $clog2(MATRIX_DIM) + 1 : 1 - $clog2(MATRIX_DIM))) + 1 : (($clog2(MATRIX_DIM) >= 0 ? $clog2(MATRIX_DIM) + 1 : 1 - $clog2(MATRIX_DIM)) - (($clog2(MATRIX_DIM) >= 0 ? $clog2(MATRIX_DIM) + 1 : 1 - $clog2(MATRIX_DIM)) + (($clog2(MATRIX_DIM) >= 0 ? $clog2(MATRIX_DIM) + 1 : 1 - $clog2(MATRIX_DIM)) - 1))) + 1)] = base_addr[$clog2(MATRIX_DIM) + ($clog2(MATRIX_DIM) - 1)-:(($clog2(MATRIX_DIM) + ($clog2(MATRIX_DIM) - 1)) >= $clog2(MATRIX_DIM) ? (($clog2(MATRIX_DIM) + ($clog2(MATRIX_DIM) - 1)) - $clog2(MATRIX_DIM)) + 1 : ($clog2(MATRIX_DIM) - ($clog2(MATRIX_DIM) + ($clog2(MATRIX_DIM) - 1))) + 1)] + {{DIFF {1'b0}}, kernal_addr[$clog2(CONV_DIM) + ($clog2(CONV_DIM) - 1)-:(($clog2(CONV_DIM) + ($clog2(CONV_DIM) - 1)) >= $clog2(CONV_DIM) ? (($clog2(CONV_DIM) + ($clog2(CONV_DIM) - 1)) - $clog2(CONV_DIM)) + 1 : ($clog2(CONV_DIM) - ($clog2(CONV_DIM) + ($clog2(CONV_DIM) - 1))) + 1)]}; + assign matrix_addr[($clog2(MATRIX_DIM) >= 0 ? $clog2(MATRIX_DIM) + 1 : 1 - $clog2(MATRIX_DIM)) - 1-:($clog2(MATRIX_DIM) >= 0 ? $clog2(MATRIX_DIM) + 1 : 1 - $clog2(MATRIX_DIM))] = base_addr[$clog2(MATRIX_DIM) - 1-:$clog2(MATRIX_DIM)] + {{DIFF {1'b0}}, kernal_addr[$clog2(CONV_DIM) - 1-:$clog2(CONV_DIM)]}; + wire mac_en; + wire mac_rst; + assign mac_rst = base_x_incr & ready; + assign done = mac_rst; + assign mac_en = 1'b1; + mac #( + .IN_WIDTH(8), + .OUT_WIDTH(8) + ) conv_mac( + .clk(clk), + .rst(mac_rst), + .en(mac_en), + .a(kernal_data[kernal_data_sel * 8+:8]), + .b(matrix_data[matrix_data_sel * 8+:8]), + .sum(data_out) + ); +endmodule diff --git a/designs/d24_mnguyen2_tpu/tb/test_inputs/16x16.hex b/designs/d24_mnguyen2_tpu/tb/test_inputs/16x16.hex new file mode 100644 index 0000000..718ac41 --- /dev/null +++ b/designs/d24_mnguyen2_tpu/tb/test_inputs/16x16.hex @@ -0,0 +1,256 @@ +7f +93 +38 +53 +f7 +0b +5a +5a +9e +5c +c7 +f3 +94 +50 +53 +dd +75 +b0 +3a +05 +81 +ff +d8 +c6 +19 +a3 +12 +31 +7a +ec +67 +31 +2c +e5 +8f +8e +0d +03 +23 +05 +31 +6b +7b +63 +3a +43 +93 +78 +a1 +39 +1b +23 +5d +10 +16 +5f +8c +92 +fc +76 +6a +f2 +10 +13 +32 +23 +e3 +96 +fd +e3 +89 +90 +99 +57 +2d +80 +de +15 +b7 +d5 +f3 +19 +31 +d0 +d7 +3c +c8 +b5 +cb +d9 +11 +c8 +e3 +d2 +ea +fe +7f +4f +b6 +ff +aa +aa +5e +b7 +c5 +7f +3f +f0 +43 +ef +b1 +b4 +e0 +4f +b5 +37 +d3 +0e +c6 +3e +76 +e7 +1d +b9 +26 +32 +1d +1e +73 +1e +c0 +af +fe +9f +a5 +15 +a0 +25 +7d +08 +79 +c7 +43 +e7 +2e +16 +d8 +8c +46 +09 +49 +86 +67 +48 +53 +d0 +0b +18 +a4 +72 +e0 +3f +b1 +cb +69 +83 +af +a9 +d2 +7e +b9 +19 +6a +a8 +b2 +06 +48 +3a +4d +ce +f0 +bb +72 +0e +82 +cb +a6 +3e +53 +ab +58 +83 +60 +a4 +c0 +8b +b9 +77 +94 +b2 +4b +1f +f9 +61 +b8 +9c +5f +91 +b2 +f9 +cd +84 +f0 +c5 +fb +1b +09 +1b +28 +01 +76 +31 +39 +ad +91 +f9 +8b +a4 +77 +77 +c6 +55 +60 +0f +69 +f2 +6d +89 +d5 +32 +3b +c5 +6c +3b +a9 +42 +90 +20 +ca +a1 +59 +aa +09 +90 +28 +9c diff --git a/designs/d24_mnguyen2_tpu/tb/test_inputs/3x3.hex b/designs/d24_mnguyen2_tpu/tb/test_inputs/3x3.hex new file mode 100644 index 0000000..3938517 --- /dev/null +++ b/designs/d24_mnguyen2_tpu/tb/test_inputs/3x3.hex @@ -0,0 +1,9 @@ +d8 +9b +b1 +7f +39 +4e +07 +33 +33 diff --git a/designs/d24_mnguyen2_tpu/tb/tpu_tb.sv b/designs/d24_mnguyen2_tpu/tb/tpu_tb.sv new file mode 100644 index 0000000..938c55f --- /dev/null +++ b/designs/d24_mnguyen2_tpu/tb/tpu_tb.sv @@ -0,0 +1,91 @@ +`default_nettype none +`include "defines.vh" + +`ifndef TEST_INPUT_DIR + `define TEST_INPUT_DIR "tb/test_inputs/" +`endif + +`define TIME_OUT 10000 + +module tpu_tb(); + parameter MATRIX_DIM = 16; + parameter CONV_DIM = 3; + parameter MATRIX_LENGTH = MATRIX_DIM*MATRIX_DIM; + parameter CONV_LENGTH = CONV_DIM*CONV_DIM; + + logic clk, rst, insert_kernal, ready, done, write_mode, write; + data_t data_in, data_out; + tpu dut(.*); + + data_t kernal_data[CONV_LENGTH-1:0]; + data_t matrix_data[MATRIX_LENGTH-1:0]; + data_t result_data[MATRIX_LENGTH-1:0]; + initial begin + clk = 1'b0; + forever #5 clk = ~clk; + end + + initial begin + for (int i = 0; i < `TIME_OUT; i++) begin + @(posedge clk); + end + $fatal("Timed out"); + end + + initial begin + init(); + insert_kernal <= 1'b1; + send_data(kernal_data); + insert_kernal <= 1'b0; + @(posedge clk); + send_data(matrix_data); + + recv_data(); + fini(); + end + + task init(); + $readmemh({`TEST_INPUT_DIR, "16x16.hex"}, matrix_data); + $readmemh({`TEST_INPUT_DIR, "3x3.hex"}, kernal_data); + $display({`TEST_INPUT_DIR, "3x3.hex"}); + $display({`TEST_INPUT_DIR, "16x16.hex"}); + insert_kernal <= 1'b0; + write <= 1'b0; + write_mode <= 1'b0; + ready <= 1'b0; + data_in <= 1'b0; + rst <= 1'b1; + @(posedge clk); + rst <= 1'b0; + @(posedge clk); + endtask + + task fini(); + $writememh("out.hex", result_data); + $finish; + endtask + task send_data(data_t data[]); + write <= 1'b1; + write_mode <= 1'b1; + for (int i = 0; i < data.size(); i++) begin + data_in <= data[i]; + @(posedge clk); + end + @(posedge clk); + write <= 1'b0; + @(posedge clk); + endtask + + int idx; + task recv_data(); + write_mode <= 1'b0; + ready <= 1'b1; + idx = 0; + while (idx < MATRIX_LENGTH) begin + @(posedge clk); + if (done) begin + result_data[idx++] <= data_out; + end + end + endtask +endmodule : tpu_tb diff --git a/designs/d24_mnguyen2_tpu/tcl/synth.tcl b/designs/d24_mnguyen2_tpu/tcl/synth.tcl new file mode 100644 index 0000000..1b4f2fe --- /dev/null +++ b/designs/d24_mnguyen2_tpu/tcl/synth.tcl @@ -0,0 +1,5 @@ +yosys -import +read_verilog -sv src/*.sv src/*.vh +procs; opt; +synth -top tpu -flatten +stat -tech cmos diff --git a/designs/d24_mnguyen2_tpu/tcl/synth_verilog.tcl b/designs/d24_mnguyen2_tpu/tcl/synth_verilog.tcl new file mode 100644 index 0000000..a94546c --- /dev/null +++ b/designs/d24_mnguyen2_tpu/tcl/synth_verilog.tcl @@ -0,0 +1,5 @@ +yosys -import +read_verilog src/verilog/top.v +procs; opt; +synth -top tpu -flatten +stat -tech cmos diff --git a/designs/d25_araghave_huffman/.lastupdated b/designs/d25_araghave_huffman/.lastupdated new file mode 100644 index 0000000..4d7b8c3 --- /dev/null +++ b/designs/d25_araghave_huffman/.lastupdated @@ -0,0 +1 @@ +2023-05-14 diff --git a/designs/d25_araghave_huffman/LICENSE b/designs/d25_araghave_huffman/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/designs/d25_araghave_huffman/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/designs/d25_araghave_huffman/README.md b/designs/d25_araghave_huffman/README.md new file mode 100644 index 0000000..1c9752f --- /dev/null +++ b/designs/d25_araghave_huffman/README.md @@ -0,0 +1,85 @@ +# huffman_encoder + +Anusha Raghavendra +18-224/624 Spring 2023 Final Tapeout Project + +## Overview + +//Algorithm +1. Read the characters(leaf node) and their corresponding frequencies array +2. First sort the input node list, find 1st and 2nd minimum. If tied, sort according to the ascii value +3. Allocate them to huff_tree, assign only is_leaf_node, child nodes (not parent node) +4. Merge nodes--> create internal node- sort and then add to huff tree -repeat until only 1 node is left +5. Iterate until the root node +6. Start from i=count-1, left_node=2i, right_node=2i+1 (i decrementing from count-1 to 0), where count is the number of unique character count +7. Traverse the entire array to assign the parent node and level in the binary tree +8. Traverse again to assign the encodings to each character + +## How it Works + +1. This design primarily comprises of a module huff_encoder, which can take one character as an input(io_in[7:0]-ascii value of characters), its corresponding frequency(io_in[10:8]) and data enable signal(io_in[11]) in a serial fashion until all 3 characters are read and collected in a register. A state machine is created with DATA_COLLECT as reset state. In total, there are 7 states. Each state takes one or more clock cycles. Hence, output encodings along with the mask value will be available after certain clock cycles. Once the output is ready, io_out[8] is asserted to represent done signal. In the first cycle after output encodings are available, io_out[7:0] represents character, and in the second cycle after this, io[5:0] represents {output_mask, output_value}. This repeat until all the outputs are read out. +2. After reset is asserted down, FSM goes to DATA_COLLECT state. +3. 2nd state would be NODE_CREATE state, where character and frequency array is sent to node_create module to create a node list containing node and its correspinding frequency each of node_t type. This module returns the initial node. +4. Then it goes to 3rd state: SORT, where list of nodes is being fed as input to a node_sorter module. Output is sorted list as per their frequencies. In case of tie, it sorts according to their ascii values. This tie breaker logic differentiates the Huffman encodings. +5. 4th state is MERGE, where a module merge_nodes select the first and second minimum from the sorted list, and creates a new node with a frequency equal to the sum of their frequencies. Other fields in the struct are set accordingly such as right and left nodes, which holds the ascii values of the merged nodes. This newly created node is added to the node list +6. Steps 3 and 4 are repeated until only 1 node is left +7. State 5 is the BUILD_TREE, where Huffman tree (array of nodes of type huff_tree_node_t) is created. +8. State 6 is ENCODE, where it's traversing the tree to assign parent and level in Huffman tree +9. It then goes to ENCODE_VALUE state, where tree is traversed again to assign encodings based on parent encodings and level +10. Final state is SEND_OUTPUT, where it just extracts the encodings and mask value for those input characters in the order of character input and serially sends it out with out_valid signal in io_out[8] bit. + + + +![](image1.png) + +## Inputs/Outputs + +io[7:0] - ascii_value of character (only character 'a' to 'o') +io[10:8] - frequency of each of character (only 2 bits, hence range [1:3]) +io[11] - data enable signal + +![](input_vector.jpg) +![](expected_out.jpg) + +## Design Testing / Bringup + + +![](input_output.jpg) + + +**Verification:** +In the project repo, huff_enc_tb.sv is the system verilog testbench which parses the inputs (characters and frequency) from “input_vector.txt” and generates output encodings along with the mask value in a serial fashion, which are then compared with the values (expected_out.txt) generated from golden model (huff_test.py). Assertions are added in this testbench to compare against the golden model outputs. +Python model huff_test.py sparse the same input file (input_vector.txt) and output the encodings to “expected_out.txt”, which are later used by system Verilog testbench to compare against its generated output. +**Input characters are to be between character ‘a’ and ‘o’, with corresponding frequencies within the range of 3 (only 2 bits) due to gate count constraints. + +Steps for using iverilog (or) simply run ./run_script.sh + source /afs/club.cc.cmu.edu/projects/stuco-open-eda/bashrc + Add more vectors in the input_vector.txt (characters, frequencies), update the vector number in the huff_enc_tb.sv +`define VECTOR_NUM 5 //change as per the vectors in input_vector.txt + sv2v huff_enc.sv > huff_enc.v + sv2v huff_enc_tb.sv > huff_enc_tb.v + python3 huff_test.py + iverilog -o sim huff_enc_tb.v huff_enc.v + . /sim +Or + ./run_script.sh +Or using VCS: + vcs -sverilog -R -top tb_top -debug_access+all huff_enc.sv huff_enc_tb.sv + +![](passing_output.jpg) + + +**##Testing** +1. Set io_in[11:0] = {1'b1, freq_in, data_in} +where, freq_in = frequency of character, data_in- ascii value of that character +Send this input for three cycles (as only maximum 3 characters) can be encoded with this module +2. Deassert data enable signal (io_in[11]) after 3 clock cycles to indicate that three characters are fed to the module. +3. As soon as io_out[8] is asserted, start reading the values which represents ascii_value in the first cycle and {encoded_mask, encoded_value} in the consecutive cycle. This repeats until all three encodings are recieved. +4. Once this vector testing is done, repeat the same procedure for next set of vectors + + +**##Enhancements** +1. Expand the input range to all characters +2. Instead of feeding in characters and frequencies, design the module to take input string, calculate the frequency of each unique character and encode it +3. Increase the MAX_CHAR_COUNT from 3 to a larger number (as of now, only 3 characters are encoded with this module) +4. If less than 3 chars are fed, it gives erroneous outputs diff --git a/designs/d25_araghave_huffman/expected_out.jpg b/designs/d25_araghave_huffman/expected_out.jpg new file mode 100644 index 0000000..5fc3009 Binary files /dev/null and b/designs/d25_araghave_huffman/expected_out.jpg differ diff --git a/designs/d25_araghave_huffman/info.yaml b/designs/d25_araghave_huffman/info.yaml new file mode 100644 index 0000000..9595784 --- /dev/null +++ b/designs/d25_araghave_huffman/info.yaml @@ -0,0 +1,9 @@ +--- +project: + source_files: + - toplevel_chip.v + - chip.sv + - decoder.v + - huff_enc.v + top_module: "toplevel_chip" + diff --git a/designs/d25_araghave_huffman/input_output.jpg b/designs/d25_araghave_huffman/input_output.jpg new file mode 100644 index 0000000..2fb5699 Binary files /dev/null and b/designs/d25_araghave_huffman/input_output.jpg differ diff --git a/designs/d25_araghave_huffman/input_vector.jpg b/designs/d25_araghave_huffman/input_vector.jpg new file mode 100644 index 0000000..343ca84 Binary files /dev/null and b/designs/d25_araghave_huffman/input_vector.jpg differ diff --git a/designs/d25_araghave_huffman/passing_output.jpg b/designs/d25_araghave_huffman/passing_output.jpg new file mode 100644 index 0000000..fad00ae Binary files /dev/null and b/designs/d25_araghave_huffman/passing_output.jpg differ diff --git a/designs/d25_araghave_huffman/src/chip.sv b/designs/d25_araghave_huffman/src/chip.sv new file mode 100644 index 0000000..b5319e7 --- /dev/null +++ b/designs/d25_araghave_huffman/src/chip.sv @@ -0,0 +1,50 @@ +`default_nettype none + +module my_chip ( + input logic [11:0] io_in, // Inputs to your chip + output logic [11:0] io_out, // Outputs from your chip + input logic clock, + input logic reset // Important: Reset is ACTIVE-HIGH +); + + huff_encoder DUT(.clk(clock), .reset(reset), .io_in(io_in), .io_out(io_out)); + + + // Basic counter design as an example + +/* + wire [6:0] led_out; + assign io_out[6:0] = led_out; + + // external clock is 1000Hz, so need 10 bit counter + reg [9:0] second_counter; + reg [3:0] digit; + + always @(posedge clock) begin + // if reset, set counter to 0 + if (reset) begin + second_counter <= 0; + digit <= 0; + end else begin + // if up to 16e6 + if (second_counter == 1000) begin + // reset + second_counter <= 0; + + // increment digit + digit <= digit + 1'b1; + + // only count from 0 to 9 + if (digit == 9) + digit <= 0; + + end else + // increment counter + second_counter <= second_counter + 1'b1; + end + end + + // instantiate segment display + seg7 seg7(.counter(digit), .segments(led_out)); +*/ +endmodule diff --git a/designs/d25_araghave_huffman/src/config.tcl b/designs/d25_araghave_huffman/src/config.tcl new file mode 100644 index 0000000..aa589e4 --- /dev/null +++ b/designs/d25_araghave_huffman/src/config.tcl @@ -0,0 +1,68 @@ +# PLEASE DO NOT EDIT THIS FILE! +# IT WILL MAKE YOUR CHIP UNMANUFACTURABLE +# The only line you may edit is FP_CORE_UTIL +# (may benefit from reducing it slightly) + +# User config +set script_dir [file dirname [file normalize [info script]]] + +# read some user config that is written by the setup.py program. +# - the name of the module is defined +# - the list of source files +source $::env(DESIGN_DIR)/user_config.tcl + +# save some time +set ::env(RUN_KLAYOUT_XOR) 0 +set ::env(RUN_KLAYOUT_DRC) 0 + +# don't put clock buffers on the outputs +set ::env(PL_RESIZER_BUFFER_OUTPUT_PORTS) 0 + +# allow use of specific sky130 cells +set ::env(SYNTH_READ_BLACKBOX_LIB) 1 + +# put all the pins on the left +set ::env(FP_PIN_ORDER_CFG) $::env(DESIGN_DIR)/pin_order.cfg + +# reduce wasted space +set ::env(TOP_MARGIN_MULT) 2 +set ::env(BOTTOM_MARGIN_MULT) 2 + +# absolute die size +set ::env(FP_SIZING) absolute +set ::env(DIE_AREA) "0 0 280 280" + +## THIS IS THE ONLY LINE YOU CAN EDIT +set ::env(FP_CORE_UTIL) 45 + +## set ::env(PL_BASIC_PLACEMENT) {1} + +set ::env(FP_IO_HLENGTH) 2 +set ::env(FP_IO_VLENGTH) 2 + +# use alternative efabless decap cells to solve LI density issue +set ::env(DECAP_CELL) "\ + sky130_fd_sc_hd__decap_3 \ + sky130_fd_sc_hd__decap_4 \ + sky130_fd_sc_hd__decap_6 \ + sky130_fd_sc_hd__decap_8 \ + sky130_ef_sc_hd__decap_12" + +# clock +set ::env(CLOCK_TREE_SYNTH) 1 + +# period is in ns, so 500ns == 2 MHz +set ::env(CLOCK_PERIOD) "500" +set ::env(CLOCK_PORT) {io_in[12]} + +# hold/slack margin +# set ::env(PL_RESIZER_HOLD_SLACK_MARGIN) 0.8 +# set ::env(GLB_RESIZER_HOLD_SLACK_MARGIN) 0.8 + +# don't use power rings or met5 +set ::env(DESIGN_IS_CORE) 0 +set ::env(RT_MAX_LAYER) {met4} + +# connect to first digital rails +set ::env(VDD_NETS) [list {vccd1}] +set ::env(GND_NETS) [list {vssd1}] diff --git a/designs/d25_araghave_huffman/src/decoder.v b/designs/d25_araghave_huffman/src/decoder.v new file mode 100644 index 0000000..8d6310e --- /dev/null +++ b/designs/d25_araghave_huffman/src/decoder.v @@ -0,0 +1,38 @@ + +/* + -- 1 -- + | | + 6 2 + | | + -- 7 -- + | | + 5 3 + | | + -- 4 -- +*/ + +module seg7 ( + input wire [3:0] counter, + output reg [6:0] segments +); + + always @(*) begin + case(counter) + // 7654321 + 0: segments = 7'b0111111; + 1: segments = 7'b0000110; + 2: segments = 7'b1011011; + 3: segments = 7'b1001111; + 4: segments = 7'b1100110; + 5: segments = 7'b1101101; + 6: segments = 7'b1111100; + 7: segments = 7'b0000111; + 8: segments = 7'b1111111; + 9: segments = 7'b1100111; + default: + segments = 7'b0000000; + endcase + end + +endmodule + diff --git a/designs/d25_araghave_huffman/src/expected_out.txt b/designs/d25_araghave_huffman/src/expected_out.txt new file mode 100644 index 0000000..cee4892 --- /dev/null +++ b/designs/d25_araghave_huffman/src/expected_out.txt @@ -0,0 +1,40 @@ +000101100001 +000100001001 +000101101110 +000100011001 +000101101101 +000100011000 + + +000101100001 +000100011000 +000101100010 +000100011001 +000101100011 +000100001001 + + +000101101010 +000100011011 +000101100101 +000100011010 +000101101111 +000100001000 + + +000101101100 +000100011011 +000101101001 +000100011010 +000101101101 +000100001000 + + +000101100111 +000100001000 +000101100001 +000100011010 +000101100010 +000100011011 + + diff --git a/designs/d25_araghave_huffman/src/huff.tcl b/designs/d25_araghave_huffman/src/huff.tcl new file mode 100644 index 0000000..3b5db1c --- /dev/null +++ b/designs/d25_araghave_huffman/src/huff.tcl @@ -0,0 +1,77 @@ +if {[file exists /proc/cpuinfo]} { + sh grep "model name" /proc/cpuinfo + sh grep "cpu MHz" /proc/cpuinfo +} + +puts "Hostname : [info hostname]" + +############################################################################## +## Set global variables and attributes +############################################################################## + +set _REPORTS_PATH reports + +#45nm +set LIB_FILE /afs/ece.cmu.edu/usr/araghave/nv_small/hw/tubgemm/NangateOpenCellLibrary_typical_ccs.db + +#set_app_var search_path {/afs/ece.cmu.edu/usr/araghave/nv_small/hw/tubgemm/nv_small_DWYES/vmod/} +#set RTL_SEARCH_PATH "/afs/ece.cmu.edu/usr/araghave/nv_small/hw/tubgemm/nv_small_DWYES/vmod/" + +set_app_var search_path {/afs/ece.cmu.edu/usr/araghave/18624/project/} +set RTL_SEARCH_PATH "/afs/ece.cmu.edu/usr/araghave/18624/project/" + +set RTL_EXTENSIONS {.sv} + + +set RTL_FILES {huff_enc.sv} + + +#set RTL_FILES {temporal_mac_8.sv} +set DESIGN huff_encoder +#set DESIGN temporal_mac + +############################################################### +## Library setup +############################################################### + +define_design_lib work -path ./work + +set_app_var target_library $LIB_FILE +set_app_var link_library $LIB_FILE + +#################################################################### +## Load Design +#################################################################### + +analyze -format sverilog $RTL_FILES +elaborate $DESIGN + +#################################################################### +## Constraints Setup +#################################################################### + +set_fix_multiple_port_nets -all -buffer_constants +create_clock -period 2.5 -waveform {0 1.25} clk + +if {![file exists ${_REPORTS_PATH}]} { + file mkdir ${_REPORTS_PATH} + puts "Creating directory ${_REPORTS_PATH}" +} + +##################################################################################################### +### Synthesize +##################################################################################################### + +uniquify +check_design +compile + +###################################################################################################### +## Write Reports +###################################################################################################### + +redirect ${_REPORTS_PATH}/area.rpt { report_area -hierarchy } +redirect ${_REPORTS_PATH}/power.rpt { report_power -hierarchy } +redirect ${_REPORTS_PATH}/timing.rpt { report_timing -path full -delay max -max_paths 1 -nworst 1 } + +quit diff --git a/designs/d25_araghave_huffman/src/huff_enc.sv b/designs/d25_araghave_huffman/src/huff_enc.sv new file mode 100644 index 0000000..0764f31 --- /dev/null +++ b/designs/d25_araghave_huffman/src/huff_enc.sv @@ -0,0 +1,296 @@ +/*********Author: Anusha Raghavendra********/ +//Project : Huffman Encoder + + +//Algorithm +// Read the characters(leaf node) and their corresponding frequencies array +// First sort the input node list, find 1st and 2nd minimum. If tied, sort according to the ascii value +// Allocate them to huff_tree, assign only is_leaf_node, child nodes (not parent node) +// Merge nodes--> create internal node- sort and then add to huff tree -repeat until only 1 node is left +// Iterate until the root node +// Start from i=count-1, left_node=2i, right_node=2i+1 (i decrementing from count-1 to 0), where count is the number of unique character count +// Traverse the entire array to assign the parent node and level in the binary tree +// Traverse again to assign the encodings to each character + + +//Optimizations +//1. Use only minimal subset of characters - like from a ('h61) to 0 ('h6F) + + +`timescale 1us/1ps + +`define MAX_CHAR_COUNT 3 //fixed as increasing to 5 increases gates by 4 times +`define BIT_WIDTH 2 + + +`define DATA_COLLECT 3'b001 +`define NODE_CREATE 3'b010 +`define SORT 3'b011 +`define MERGE_BUILD 3'b100 +`define ENCODE 3'b101 +`define ENCODE_VALUE 3'b110 +`define SEND_OUTPUT 3'b111 + + +//left and right nodes are 0 for leaf nodes +typedef struct { + logic [4:0] ascii_char; //4 max + 1 + logic [2:0] frequency; //only 2 bits+1 + logic is_leaf_node; + logic [4:0] left_node; //stores the index + logic [4:0] right_node; //stores the index +} node_t; + +typedef struct { + logic [4:0] ascii_char; + logic is_leaf_node; + logic [4:0] left_node; //stores the index + logic [4:0] right_node; //stores the index + logic [`BIT_WIDTH-1:0] parent; + logic [`BIT_WIDTH-1:0] level; +} huff_tree_node_t; + +//main encoder module +module huff_encoder (input logic clk, input logic reset, input logic [11:0] io_in, output logic [11:0] io_out); + +logic [0:`MAX_CHAR_COUNT-1][7:0] data_in; +logic [0:`MAX_CHAR_COUNT-1][2:0] freq_in; +logic [`BIT_WIDTH-1:0] count; +logic [`BIT_WIDTH+1:0] odd_idx, even_idx; +node_t initial_node[`MAX_CHAR_COUNT]; +logic [2:0] state; +huff_tree_node_t huff_tree[`MAX_CHAR_COUNT*2]; +node_t in_huff_tree[0:`MAX_CHAR_COUNT-1]; +node_t out_huff_tree[0:`MAX_CHAR_COUNT]; +node_t merged_node; +logic [0:`MAX_CHAR_COUNT-1][`MAX_CHAR_COUNT-1:0] encoded_value; +logic [0:`MAX_CHAR_COUNT-1][`MAX_CHAR_COUNT-1:0] encoded_mask; +logic done; + +logic [0:`MAX_CHAR_COUNT-1][4:0] character; + +logic [`MAX_CHAR_COUNT-1:0] encoded_value_h[2*`MAX_CHAR_COUNT]; +logic [`MAX_CHAR_COUNT-1:0] a, b, c; + +logic [`MAX_CHAR_COUNT-1:0] encoded_value_l; +logic [`MAX_CHAR_COUNT-1:0] encoded_value_r; +logic is_n_odd; + + + node_create node_create_ins(.data_in(data_in), .freq_in(freq_in), .node(initial_node)); + node_sorter node_sorter_ins(.clk(clk), .input_node(in_huff_tree[0:`MAX_CHAR_COUNT-1]), .output_node(out_huff_tree[0:`MAX_CHAR_COUNT-1])); + merge_nodes merge_nodes_ins(.min_node(out_huff_tree[0]), .second_min_node(out_huff_tree[1]), .merged_node(merged_node)); + +always_ff @(posedge clk) begin : huffman_enc + if (reset) begin //active high reset + state <= `DATA_COLLECT; + a <= 3'd0; + b <= 3'b0; + c <= 3'b0; + done = 'b0; + for (int i=0; i< `MAX_CHAR_COUNT; i++) begin + encoded_value[i] = 'b0; + encoded_mask[i] = 'b0; + in_huff_tree[i].ascii_char = 'b0; + in_huff_tree[i].frequency = 'b0; + in_huff_tree[i].is_leaf_node = 'b0; + in_huff_tree[i].left_node = 'b0; + in_huff_tree[i].right_node = 'b0; + character[i] = 'b0; + end + + + for (int i=0; i < (2*`MAX_CHAR_COUNT); i++) begin + encoded_value_h[i] = 'b0; + huff_tree[i].ascii_char = 'b0; + huff_tree[i].is_leaf_node = 1'b0; + huff_tree[i].parent = 'b0; + huff_tree[i].left_node = 'b0; + huff_tree[i].right_node = 'b0; + huff_tree[i].level = 'b0; + end + + encoded_value_l = 'b0; + encoded_value_r = 'b0; + + + end + + else begin + case (state) + + `DATA_COLLECT: begin + done = 'b0; + io_out <= 'b0; + a <= 'b0; + b <= 'b0; + if (io_in[11]== 1'b1) begin //data_en + data_in[c] <= io_in[7:0]; + freq_in[c] <= io_in[10:8]; + c <= c + 1'b1; + end + state <= (c == `MAX_CHAR_COUNT)? `NODE_CREATE : `DATA_COLLECT; + end + + `NODE_CREATE: begin + count = `MAX_CHAR_COUNT; + for (int i=0; i< `MAX_CHAR_COUNT; i++) begin + in_huff_tree[i] = initial_node[i]; + end + state <= `SORT; + end + + `SORT : begin //state=3 + state <= `MERGE_BUILD; + end + + `MERGE_BUILD : begin //state=4 + in_huff_tree[0] = merged_node; + in_huff_tree[1:`MAX_CHAR_COUNT-1] = out_huff_tree[2:`MAX_CHAR_COUNT]; + + + count = count - 1'b1; + even_idx = (count << 1'b1); + odd_idx = even_idx + 1'b1; + //assigning child nodes and leaf node fields + + huff_tree[even_idx].ascii_char = out_huff_tree[0].ascii_char; + huff_tree[odd_idx].ascii_char = out_huff_tree[1].ascii_char; + huff_tree[even_idx].is_leaf_node = out_huff_tree[0].is_leaf_node; + huff_tree[odd_idx].is_leaf_node = out_huff_tree[1].is_leaf_node; + huff_tree[even_idx].left_node = out_huff_tree[0].left_node; + huff_tree[odd_idx].left_node = out_huff_tree[1].left_node; + huff_tree[even_idx].right_node = out_huff_tree[0].right_node; + huff_tree[odd_idx].right_node = out_huff_tree[1].right_node; + + //assigning root node + huff_tree[1].ascii_char = out_huff_tree[0].ascii_char; + huff_tree[1].is_leaf_node = out_huff_tree[0].is_leaf_node; + huff_tree[1].left_node = out_huff_tree[0].left_node; + huff_tree[1].right_node = out_huff_tree[0].right_node; + + if (!(count[0] | count[1])) begin + state <= `ENCODE; + end + else begin + state <= `SORT; + end + end + + + `ENCODE: begin //state=6 + //assigning parent field for a node if that node is present as a child node either in left or right node + for (int l=(2*`MAX_CHAR_COUNT)-1; l > 1; l--) begin + for (int n=1; n< (2*`MAX_CHAR_COUNT); n++) begin + if ((huff_tree[n].is_leaf_node == 'b0) && (huff_tree[n].left_node == huff_tree[l].ascii_char || huff_tree[n].right_node == huff_tree[l].ascii_char)) begin + huff_tree[l].parent = n; + end + end + end + + for (int n=2; n < (2*`MAX_CHAR_COUNT); n++) begin + huff_tree[n].level = huff_tree[huff_tree[n].parent].level + 1'b1; + end + state <= `ENCODE_VALUE; + + end + + `ENCODE_VALUE: begin + + + for (int n=2; n < (2*`MAX_CHAR_COUNT); n++) begin //1-root node + encoded_value_l = encoded_value_h[huff_tree[n].parent] << 1'b1; + encoded_value_r = (encoded_value_h[huff_tree[n].parent] << 1'b1) | 1'b1; + is_n_odd = n[0]; + if (huff_tree[n].parent != 1'b1) begin + encoded_value_h[n] = (is_n_odd) ? encoded_value_r: encoded_value_l; + end + else if (huff_tree[n].parent == 1'b1) begin + encoded_value_h[n][0] = (is_n_odd) ? {1'b1}: {1'b0}; + end + end + + foreach(data_in[i]) begin + for (int n=1; n< (2*`MAX_CHAR_COUNT); n++) begin + if (huff_tree[n].ascii_char == data_in[i][3:0] && (huff_tree[n].is_leaf_node == 'b1)) begin + encoded_mask[i] = (1'b1 << huff_tree[n].level)-1'b1; + encoded_value[i] = encoded_value_h[n]; + character[i] = huff_tree[n].ascii_char; + end //if loop + end //for loop + end + state <= `SEND_OUTPUT; + end + + + //extract only encodings for unique characters + `SEND_OUTPUT: begin //state=7 + c <= 'b0; + done = 1'b1; + io_out[8:0] <= (b[0] == 1'b0) ? {done, 3'b011, character[a]} : {done, 2'b0, encoded_mask[a], encoded_value[a]}; + b <= b + 1'b1; + a <= (b[0] == 1'b1)? a+1: a; // 1 cycle delay + state <= (a > `MAX_CHAR_COUNT-1)? `DATA_COLLECT : `SEND_OUTPUT; + end + + default : begin + + state <= `DATA_COLLECT; + end + + endcase + end + +end //posedge_clk + +endmodule + + +module node_create(input logic [0:`MAX_CHAR_COUNT-1][7:0] data_in, input logic [0:`MAX_CHAR_COUNT-1][2:0] freq_in, output node_t node[`MAX_CHAR_COUNT]); + +always_comb begin + for (int i=0; i< `MAX_CHAR_COUNT; i++) begin + // if (data_in[i] != 0) begin //if commented this, you have to ensure all 3 char are always present + node[i].ascii_char = data_in[i]; + node[i].frequency = freq_in[i]; + node[i].left_node = 'b0; //ascii valud of null + node[i].right_node = 'b0; + node[i].is_leaf_node = 1'b1; + // end + end +end + +endmodule + + +module node_sorter(input logic clk, input node_t input_node[`MAX_CHAR_COUNT], output node_t output_node[`MAX_CHAR_COUNT]); + +node_t temp_node; + always_ff @(posedge clk) begin + for (int i=0; i< `MAX_CHAR_COUNT; i++) begin + output_node = input_node; + end + //sorting logic + for(int j=0; j< `MAX_CHAR_COUNT-1; j++) begin + for (int k= 0; k< `MAX_CHAR_COUNT-1; k++) begin + if (((output_node[k].frequency == output_node[k+1].frequency) && (output_node[k].ascii_char > output_node[k+1].ascii_char)) || (output_node[k].frequency > output_node[k+1].frequency)) begin + temp_node = output_node[k]; + output_node[k] = output_node[k+1]; + output_node[k+1] = temp_node; + end + + end + end +end +endmodule + + + +module merge_nodes(input node_t min_node, input node_t second_min_node, output node_t merged_node); + assign merged_node.ascii_char = min_node.ascii_char + second_min_node.ascii_char; + assign merged_node.frequency = min_node.frequency + second_min_node.frequency; + assign merged_node.left_node = min_node.ascii_char; + assign merged_node.right_node = second_min_node.ascii_char; + assign merged_node.is_leaf_node = 1'b0; +endmodule + diff --git a/designs/d25_araghave_huffman/src/huff_enc.v b/designs/d25_araghave_huffman/src/huff_enc.v new file mode 100644 index 0000000..efae6e4 --- /dev/null +++ b/designs/d25_araghave_huffman/src/huff_enc.v @@ -0,0 +1,254 @@ +module huff_encoder ( + clk, + reset, + io_in, + io_out +); + input wire clk; + input wire reset; + input wire [11:0] io_in; + output reg [11:0] io_out; + reg [23:0] data_in; + reg [8:0] freq_in; + reg [1:0] count; + reg [3:0] odd_idx; + reg [3:0] even_idx; + wire [56:0] initial_node; + reg [2:0] state; + reg [19:0] huff_tree [0:5]; + reg [56:0] in_huff_tree; + wire [75:0] out_huff_tree; + wire [18:0] merged_node; + reg [8:0] encoded_value; + reg [8:0] encoded_mask; + reg done; + reg [14:0] character; + reg [2:0] encoded_value_h [0:5]; + reg [2:0] a; + reg [2:0] b; + reg [2:0] c; + reg [2:0] encoded_value_l; + reg [2:0] encoded_value_r; + reg is_n_odd; + freq_calc freq_calc_ins( + .data_in(data_in), + .freq_in(freq_in), + .node(initial_node) + ); + node_sorter node_sorter_ins( + .clk(clk), + .input_node(in_huff_tree[0+:57]), + .output_node(out_huff_tree[19+:57]) + ); + merge_nodes merge_nodes_ins( + .min_node(out_huff_tree[57+:19]), + .second_min_node(out_huff_tree[38+:19]), + .merged_node(merged_node) + ); + always @(posedge clk) begin : huffman_enc + if (reset) begin + state <= 3'b001; + a <= 3'd0; + b <= 3'b000; + c <= 3'b000; + done = 'b0; + begin : sv2v_autoblock_1 + reg signed [31:0] i; + for (i = 0; i < 3; i = i + 1) + begin + encoded_value[(2 - i) * 3+:3] = 'b0; + encoded_mask[(2 - i) * 3+:3] = 'b0; + in_huff_tree[((2 - i) * 19) + 18-:5] = 'b0; + in_huff_tree[((2 - i) * 19) + 13-:3] = 'b0; + in_huff_tree[((2 - i) * 19) + 10] = 'b0; + in_huff_tree[((2 - i) * 19) + 9-:5] = 'b0; + in_huff_tree[((2 - i) * 19) + 4-:5] = 'b0; + character[(2 - i) * 5+:5] = 'b0; + end + end + begin : sv2v_autoblock_2 + reg signed [31:0] i; + for (i = 0; i < 6; i = i + 1) + begin + encoded_value_h[i] = 'b0; + huff_tree[i][19-:5] = 'b0; + huff_tree[i][14] = 1'b0; + huff_tree[i][3-:2] = 'b0; + huff_tree[i][13-:5] = 'b0; + huff_tree[i][8-:5] = 'b0; + huff_tree[i][1-:2] = 'b0; + end + end + encoded_value_l = 'b0; + encoded_value_r = 'b0; + end + else + case (state) + 3'b001: begin + done = 'b0; + io_out <= 'b0; + a <= 'b0; + b <= 'b0; + if (io_in[11] == 1'b1) begin + data_in[(2 - c) * 8+:8] <= io_in[7:0]; + freq_in[(2 - c) * 3+:3] <= io_in[10:8]; + c <= c + 1'b1; + end + state <= (c == 3 ? 3'b010 : 3'b001); + end + 3'b010: begin + count = 3; + begin : sv2v_autoblock_3 + reg signed [31:0] i; + for (i = 0; i < 3; i = i + 1) + in_huff_tree[(2 - i) * 19+:19] = initial_node[(2 - i) * 19+:19]; + end + state <= 3'b011; + end + 3'b011: state <= 3'b100; + 3'b100: begin + in_huff_tree[38+:19] = merged_node; + in_huff_tree[0+:38] = out_huff_tree[0+:38]; + count = count - 1'b1; + even_idx = count << 1'b1; + odd_idx = even_idx + 1'b1; + huff_tree[even_idx][19-:5] = out_huff_tree[75-:5]; + huff_tree[odd_idx][19-:5] = out_huff_tree[56-:5]; + huff_tree[even_idx][14] = out_huff_tree[67]; + huff_tree[odd_idx][14] = out_huff_tree[48]; + huff_tree[even_idx][13-:5] = out_huff_tree[66-:5]; + huff_tree[odd_idx][13-:5] = out_huff_tree[47-:5]; + huff_tree[even_idx][8-:5] = out_huff_tree[61-:5]; + huff_tree[odd_idx][8-:5] = out_huff_tree[42-:5]; + huff_tree[1][19-:5] = out_huff_tree[75-:5]; + huff_tree[1][14] = out_huff_tree[67]; + huff_tree[1][13-:5] = out_huff_tree[66-:5]; + huff_tree[1][8-:5] = out_huff_tree[61-:5]; + if (!(count[0] | count[1])) + state <= 3'b101; + else + state <= 3'b011; + end + 3'b101: begin + begin : sv2v_autoblock_4 + reg signed [31:0] l; + for (l = 5; l > 1; l = l - 1) + begin : sv2v_autoblock_5 + reg signed [31:0] n; + for (n = 1; n < 6; n = n + 1) + if ((huff_tree[n][14] == 'b0) && ((huff_tree[n][13-:5] == huff_tree[l][19-:5]) || (huff_tree[n][8-:5] == huff_tree[l][19-:5]))) + huff_tree[l][3-:2] = n; + end + end + begin : sv2v_autoblock_6 + reg signed [31:0] n; + for (n = 2; n < 6; n = n + 1) + huff_tree[n][1-:2] = huff_tree[huff_tree[n][3-:2]][1-:2] + 1'b1; + end + state <= 3'b110; + end + 3'b110: begin + begin : sv2v_autoblock_7 + reg signed [31:0] n; + for (n = 2; n < 6; n = n + 1) + begin + encoded_value_l = encoded_value_h[huff_tree[n][3-:2]] << 1'b1; + encoded_value_r = (encoded_value_h[huff_tree[n][3-:2]] << 1'b1) | 1'b1; + is_n_odd = n[0]; + if (huff_tree[n][3-:2] != 1'b1) + encoded_value_h[n] = (is_n_odd ? encoded_value_r : encoded_value_l); + else if (huff_tree[n][3-:2] == 1'b1) + encoded_value_h[n][0] = (is_n_odd ? 1'b1 : 1'b0); + end + end + begin : sv2v_autoblock_8 + integer i; + for (i = 0; i <= 2; i = i + 1) + begin : sv2v_autoblock_9 + reg signed [31:0] n; + for (n = 1; n < 6; n = n + 1) + if ((huff_tree[n][19-:5] == data_in[((2 - i) * 8) + 3-:4]) && (huff_tree[n][14] == 'b1)) begin + encoded_mask[(2 - i) * 3+:3] = (1'b1 << huff_tree[n][1-:2]) - 1'b1; + encoded_value[(2 - i) * 3+:3] = encoded_value_h[n]; + character[(2 - i) * 5+:5] = huff_tree[n][19-:5]; + end + end + end + state <= 3'b111; + end + 3'b111: begin + c <= 'b0; + done = 1'b1; + io_out[8:0] <= (b[0] == 1'b0 ? {done, 3'b011, character[(2 - a) * 5+:5]} : {done, 2'b00, encoded_mask[(2 - a) * 3+:3], encoded_value[(2 - a) * 3+:3]}); + b <= b + 1'b1; + a <= (b[0] == 1'b1 ? a + 1 : a); + state <= (a > 2 ? 3'b001 : 3'b111); + end + default: state <= 3'b001; + endcase + end +endmodule +module freq_calc ( + data_in, + freq_in, + node +); + input wire [23:0] data_in; + input wire [8:0] freq_in; + output reg [56:0] node; + always @(*) begin : sv2v_autoblock_1 + reg signed [31:0] i; + for (i = 0; i < 3; i = i + 1) + begin + node[((2 - i) * 19) + 18-:5] = data_in[(2 - i) * 8+:8]; + node[((2 - i) * 19) + 13-:3] = freq_in[(2 - i) * 3+:3]; + node[((2 - i) * 19) + 9-:5] = 'b0; + node[((2 - i) * 19) + 4-:5] = 'b0; + node[((2 - i) * 19) + 10] = 1'b1; + end + end +endmodule +module node_sorter ( + clk, + input_node, + output_node +); + input wire clk; + input wire [56:0] input_node; + output reg [56:0] output_node; + reg [18:0] temp_node; + always @(posedge clk) begin + begin : sv2v_autoblock_1 + reg signed [31:0] i; + for (i = 0; i < 3; i = i + 1) + output_node = input_node; + end + begin : sv2v_autoblock_2 + reg signed [31:0] j; + for (j = 0; j < 2; j = j + 1) + begin : sv2v_autoblock_3 + reg signed [31:0] k; + for (k = 0; k < 2; k = k + 1) + if (((output_node[((2 - k) * 19) + 13-:3] == output_node[((2 - (k + 1)) * 19) + 13-:3]) && (output_node[((2 - k) * 19) + 18-:5] > output_node[((2 - (k + 1)) * 19) + 18-:5])) || (output_node[((2 - k) * 19) + 13-:3] > output_node[((2 - (k + 1)) * 19) + 13-:3])) begin + temp_node = output_node[(2 - k) * 19+:19]; + output_node[(2 - k) * 19+:19] = output_node[(2 - (k + 1)) * 19+:19]; + output_node[(2 - (k + 1)) * 19+:19] = temp_node; + end + end + end + end +endmodule +module merge_nodes ( + min_node, + second_min_node, + merged_node +); + input wire [18:0] min_node; + input wire [18:0] second_min_node; + output wire [18:0] merged_node; + assign merged_node[18-:5] = min_node[18-:5] + second_min_node[18-:5]; + assign merged_node[13-:3] = min_node[13-:3] + second_min_node[13-:3]; + assign merged_node[9-:5] = min_node[18-:5]; + assign merged_node[4-:5] = second_min_node[18-:5]; + assign merged_node[10] = 1'b0; +endmodule diff --git a/designs/d25_araghave_huffman/src/huff_enc_tb.sv b/designs/d25_araghave_huffman/src/huff_enc_tb.sv new file mode 100644 index 0000000..563d44f --- /dev/null +++ b/designs/d25_araghave_huffman/src/huff_enc_tb.sv @@ -0,0 +1,175 @@ +`define DEBUG 0 +`define MAX_CHAR_COUNT 3 //fixed as increasing to 5 increases gates by 4 times +`define BIT_WIDTH 2 +`define VECTOR_NUM 5 //number of test vectors + +`define assert(signal, value) \ + if (signal !== value) begin \ + $error("ASSERTION FAILED in %m: signal=%b != value=%b", signal, value); \ + end + +module tb_top; + +logic [0:`MAX_CHAR_COUNT-1][7:0] data_in[0:`VECTOR_NUM-1]; +reg [2:0] freq[0:`VECTOR_NUM-1]; +reg [23:0] temp; +reg [40:0] input_string; + +logic [0:`MAX_CHAR_COUNT-1][2:0] freq_in[0:`VECTOR_NUM-1]; + +logic data_en; +logic clk, reset, done; +integer i; +logic [11:0] io_out, io_in; +reg [11:0] temp1; +logic [0:2*`MAX_CHAR_COUNT-1][11:0] expected_out[0:`VECTOR_NUM-1]; +integer j, vector_num, num, test_num; +int f, f1; +logic vector_done; + +int line, iter, line1, line2, line3, line4; + + +//DUT instantiation + huff_encoder DUT(.clk(clk), .reset(reset), .io_in(io_in), .io_out(io_out)); + + initial begin + clk = 0; + reset = 1; + vector_num = 0; + done = 1'b0; + num = 0; + test_num = 0; + + + f = $fopen("input_vector.txt", "r"); + f1 = $fopen("expected_out.txt", "rb"); + + while (!$feof(f1)) begin + line1 = $fscanf(f1, "%b", temp1); + if (line1 == 1) begin + expected_out[test_num][num] = temp1; + if (`DEBUG) begin + $display("expected_out[%0d][%0d]=%b, num=%0d\n", test_num, num, temp1, num); + end + test_num = (num == 'd5)? test_num + 1: test_num; + num = (num < 'd5) ? num+1 : 'd0; + end + end + + + while (!$feof(f)) begin + line1 = $fgets(input_string, f); //line = 3 + if (line1 == 5) begin + line2 = $sscanf(input_string, "%3d,%3d,%3d\n", freq[0], freq[1], freq[2]); + freq_in[vector_num][0] = freq[0]; + freq_in[vector_num][1] = freq[1]; + freq_in[vector_num][2] = freq[2]; + end + else if (line1 == 4) begin + line2 = $sscanf(input_string, "%s\n", temp); + data_in[vector_num] = temp; + if (`DEBUG) begin + $display("data_in=%h, freq0:%0d, freq1:%0d, freq2:%0d\n", temp, freq[0], freq[1], freq[2]); + end + vector_num = vector_num+1; + end + end + + + $fclose(f); + $fclose(f1); + + #5 reset = 0; + #200; //increase if you increase the string length + $finish; + end + + +//input assignment + always_ff @(posedge clk) begin + if(reset) begin + i <= 'b0; + io_in = 'b0; + iter = 'd0; + data_en = 'b1; + end + else begin + if ((i< `MAX_CHAR_COUNT)) begin + io_in[11:0] = {1'b1, freq_in[iter][i], data_in[iter][i]}; + $display("INPUTS: io_in:%b\n", io_in); + end + else begin + io_in[11] = 1'b0; + end + + i <= (vector_done)? 'b0 : (i + 1'b1); + iter = vector_done ? iter + 1: iter; + if (`DEBUG) begin + $display("iter:%d, i:%d, state:%d\n", iter, i, DUT.state); + end + if (vector_done) begin + $display("******************************************"); + $display("\nvector starting with num:%d", iter); + end + if(iter == `VECTOR_NUM) begin + $finish; + end + end + end + + always @(posedge clk) begin + if( reset) begin + j <= 'b0; + vector_done <= 'b0; + end + else if (io_out[8] && !vector_done) begin + $display("io_out:%b, expected_out[%0d][%0d]=%b\n", io_out, iter, j, expected_out[iter][j]); + `assert(io_out[8:0],expected_out[iter][j]) + j <= (j == 2*`MAX_CHAR_COUNT-1)? 'b0 : j + 1; + if (`DEBUG) begin + $display("j:%d, vector_done=%b\n", j, vector_done); + end + end + vector_done <= (j == 2*`MAX_CHAR_COUNT-1)? 'b1 : 'b0; + end + + always begin + #0.5 clk = ~clk; //1MHz + end + + always begin + #150; + if (`DEBUG) begin + $display("time:%t, Input data: state:%0d\n", $time, DUT.state); + $display("INPUT datain:%x\n", DUT.data_in); + $display("INPUT freqin0:%x, freqin1:%x, freqin2:%x\n", DUT.freq_in[0], DUT.freq_in[1], DUT.freq_in[2]); + $display("Initial node:%p\n", DUT.initial_node); + $display("in_huff_tree:%p\n\n", DUT.in_huff_tree); + $display("out_huff_tree:%p\n\n", DUT.out_huff_tree); + + + for (int i=0; i< 2*`MAX_CHAR_COUNT; i++) begin + $display("binary_tree: huff_tree[%0d]:%p, encoded_values_h[%0d]:%b\n", i, DUT.huff_tree[i], i, DUT.encoded_value_h[i]); + end + + for (int i=0; i< `MAX_CHAR_COUNT; i++) begin + $display("OUTPUT: character[%0d]:%h, encoded mask[%0d]:%b, encoded values[%0d]:%b\n", i, {3'b011,DUT.character[i]}, i, DUT.encoded_mask[i], i, DUT.encoded_value[i]); + end + + $display("state:%p\n", DUT.state); + end //`DEBUG + + if (io_out[8]) begin + for (int i=0; i< `MAX_CHAR_COUNT; i++) begin + $display("OUTPUT: character[%0d]:%2h(%s), encoded mask[%0d]:%b, encoded values[%0d]:%b\n", i, {3'b011,DUT.character[i]}, {3'b011,DUT.character[i]}, i, DUT.encoded_mask[i], i, DUT.encoded_value[i]); + end + end + $finish; + end + + + +endmodule + + diff --git a/designs/d25_araghave_huffman/src/huff_enc_tb.v b/designs/d25_araghave_huffman/src/huff_enc_tb.v new file mode 100644 index 0000000..7b37184 --- /dev/null +++ b/designs/d25_araghave_huffman/src/huff_enc_tb.v @@ -0,0 +1,112 @@ +module tb_top; + reg [23:0] data_in [0:4]; + reg [2:0] freq [0:4]; + reg [23:0] temp; + reg [40:0] input_string; + reg [8:0] freq_in [0:4]; + reg data_en; + reg clk; + reg reset; + reg done; + integer i; + wire [11:0] io_out; + reg [11:0] io_in; + reg [11:0] temp1; + reg [71:0] expected_out [0:4]; + integer j; + integer vector_num; + integer num; + integer test_num; + reg signed [31:0] f; + reg signed [31:0] f1; + reg vector_done; + wire signed [31:0] line; + reg signed [31:0] iter; + reg signed [31:0] line1; + reg signed [31:0] line2; + wire signed [31:0] line3; + wire signed [31:0] line4; + huff_encoder DUT( + .clk(clk), + .reset(reset), + .io_in(io_in), + .io_out(io_out) + ); + initial begin + clk = 0; + reset = 1; + vector_num = 0; + done = 1'b0; + num = 0; + test_num = 0; + f = $fopen("input_vector.txt", "r"); + f1 = $fopen("expected_out.txt", "rb"); + while (!$feof(f1)) begin + line1 = $fscanf(f1, "%b", temp1); + if (line1 == 1) begin + expected_out[test_num][(5 - num) * 12+:12] = temp1; + test_num = (num == 'd5 ? test_num + 1 : test_num); + num = (num < 'd5 ? num + 1 : 'd0); + end + end + while (!$feof(f)) begin + line1 = $fgets(input_string, f); + if (line1 == 5) begin + line2 = $sscanf(input_string, "%3d,%3d,%3d\n", freq[0], freq[1], freq[2]); + freq_in[vector_num][6+:3] = freq[0]; + freq_in[vector_num][3+:3] = freq[1]; + freq_in[vector_num][0+:3] = freq[2]; + end + else if (line1 == 4) begin + line2 = $sscanf(input_string, "%s\n", temp); + data_in[vector_num] = temp; + vector_num = vector_num + 1; + end + end + $fclose(f); + $fclose(f1); + #(5) reset = 0; + #(150) + ; + $finish; + end + always @(posedge clk) + if (reset) begin + i <= 'b0; + io_in = 'b0; + iter = 'd0; + data_en = 'b1; + end + else begin + if (i < 3) + io_in[11:0] = {1'b1, freq_in[iter][(2 - i) * 3+:3], data_in[iter][(2 - i) * 8+:8]}; + else + io_in[11] = 1'b0; + i <= (vector_done ? 'b0 : i + 1'b1); + iter = (vector_done ? iter + 1 : iter); + if (vector_done) begin + $display("******************************************"); + $display("\nvector starting with num:%d", iter); + end + if (iter == 5) + $finish; + end + always @(posedge clk) begin + if (reset) begin + j <= 'b0; + vector_done <= 'b0; + end + else if (io_out[8] && !vector_done) begin + if (io_out[8:0] !== expected_out[iter][(5 - j) * 12+:12]) + $error("ASSERTION FAILED in %m: signal=%b != value=%b", io_out[8:0], expected_out[iter][(5 - j) * 12+:12]); + j <= (j == 5 ? 'b0 : j + 1); + end + vector_done <= (j == 5 ? 'b1 : 'b0); + end + always #(0.5) clk = ~clk; + always if (io_out[8]) begin : sv2v_autoblock_1 + reg signed [31:0] i; + for (i = 0; i < 3; i = i + 1) + $display("OUTPUT: character[%0d]:%2h(%s), encoded mask[%0d]:%b, encoded values[%0d]:%b\n", i, {3'b011, DUT.character[i]}, {3'b011, DUT.character[i]}, i, DUT.encoded_mask[i], i, DUT.encoded_value[i]); + end +endmodule diff --git a/designs/d25_araghave_huffman/src/huff_test.py b/designs/d25_araghave_huffman/src/huff_test.py new file mode 100644 index 0000000..3e1bec3 --- /dev/null +++ b/designs/d25_araghave_huffman/src/huff_test.py @@ -0,0 +1,117 @@ +#Reference: +#source : Geeks for geek/Internet(some piece of code) +# A Huffman Encoder - GOLDEN MODEL +import heapq + + +class node: + def __init__(self, freq, symbol, left=None, right=None): + # frequency of symbol + self.freq = freq + + # symbol name (character) + self.symbol = symbol + + # node left of current node + self.left = left + + # node right of current node + self.right = right + + # tree direction (0/1) + self.huff = '' + + def __lt__(self, nxt): + if self.freq == nxt.freq: + return self.symbol < nxt.symbol + return self.freq < nxt.freq + + + +# creating Huffman tree +def printNodes(node, val=''): + + # huffman code for current node + newVal = val + str(node.huff) + #node_values = {} + + # if node is not an edge node + # then traverse inside it + if(node.left): + printNodes(node.left, newVal) + if(node.right): + printNodes(node.right, newVal) + + # if node is edge node then + # display its huffman code + if(not node.left and not node.right): + char_b = bin(ord(node.symbol)) + char_b = '00010'+char_b[2:] + + mask_length = len(newVal) + mask = bin((1< 1: + + # sort all the nodes in ascending order + # based on their frequency and in case of tie, sort using ascii value + left = heapq.heappop(nodes) + right = heapq.heappop(nodes) + + # assign directional value to these nodes + left.huff = 0 + right.huff = 1 + + # combine the 2 smallest nodes to create + # new node as their parent + newNode = node(left.freq+right.freq, left.symbol+right.symbol, left, right) + heapq.heappush(nodes, newNode) + + #use for loop to print to output + + printNodes(nodes[0]) + #use for loop to print to output + for c in chars: + if c in node_values: + print(node_values[c][0], file=output_file) + print(node_values[c][1], file=output_file) + + print("\n", file=output_file) + + + + + diff --git a/designs/d25_araghave_huffman/src/input_vector.txt b/designs/d25_araghave_huffman/src/input_vector.txt new file mode 100644 index 0000000..daf12b3 --- /dev/null +++ b/designs/d25_araghave_huffman/src/input_vector.txt @@ -0,0 +1,10 @@ +3,1,1 +anm +1,2,3 +abc +2,2,2 +jeo +1,1,1 +lim +3,3,3 +gab diff --git a/designs/d25_araghave_huffman/src/pin_order.cfg b/designs/d25_araghave_huffman/src/pin_order.cfg new file mode 100644 index 0000000..0b85c63 --- /dev/null +++ b/designs/d25_araghave_huffman/src/pin_order.cfg @@ -0,0 +1,9 @@ +#N + +#S + +#E + +#W +io_in.* +io_out.* diff --git a/designs/d25_araghave_huffman/src/toplevel_chip.v b/designs/d25_araghave_huffman/src/toplevel_chip.v new file mode 100644 index 0000000..a82b427 --- /dev/null +++ b/designs/d25_araghave_huffman/src/toplevel_chip.v @@ -0,0 +1,18 @@ +`default_nettype none + +// DO NOT EDIT THIS FILE +module toplevel_chip ( + input [13:0] io_in, + output [13:0] io_out +); + + my_chip mchip ( + .io_in(io_in[11:0]), + .io_out(io_out[11:0]), + .clock(io_in[12]), + .reset(io_in[13]) + ); + + assign io_out[13:12] = 2'b00; + +endmodule diff --git a/designs/d26_cjstange_perceptron/.lastupdated b/designs/d26_cjstange_perceptron/.lastupdated new file mode 100644 index 0000000..4d7b8c3 --- /dev/null +++ b/designs/d26_cjstange_perceptron/.lastupdated @@ -0,0 +1 @@ +2023-05-14 diff --git a/designs/d26_cjstange_perceptron/LICENSE b/designs/d26_cjstange_perceptron/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/designs/d26_cjstange_perceptron/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/designs/d26_cjstange_perceptron/README.md b/designs/d26_cjstange_perceptron/README.md new file mode 100644 index 0000000..4dcbe9d --- /dev/null +++ b/designs/d26_cjstange_perceptron/README.md @@ -0,0 +1,49 @@ +# Perceptron + +18-224/624 Spring 2023 Final Tapeout Project +Chris Stange + +## Overview + +The perceptron is one of the earliest machine learning models and acts as a binary classifier for linearly separable functions. The perceptron can run both training and inference. + +## How it Works + +At the implementation level, the perceptron is a pipelined MAC unit with some fancy control logic. The perceptron uses a 6-bit (3.3) fixed point number representation which means numbers in the range of -4 to 3.875 can be used with a precision of .125. Arbitrary weights, learning rates, and values can loaded onto the perceptron. Weights can be read out combinationally after training. + +![Computation](/docs/computation.png) + +![Datapath](/docs/Perceptron_datapath.pdf) + +![FSM](/docs/Perceptron_fsm.pdf) + +## Inputs/Outputs + +All signals are 1-bit unless otherwise stated. + +### Input signals: +* go - Used to control the loading of input values. Set to 1 to load in_val and move to next state. +* update - Set to 0 if running inference. Set to 1 if running training. +* correct - The correct classification of the inputs. Used for training. +* sel_out - 2-bit input select line for out_val. Used to read weights combinationally. 0 -> output of the adder, 1 -> W2, 2 -> W1, 3 -> W0. +* in_val - Where all 6-bit inputs are loaded. Used to loads weights, learning rate, and input values. + +### Output signal: +* done - Notifies when the computation is finished. Classification will be valid on next clock edge if running inference, weights already available if running training. +* classification - The perceptrons classification of the inputs. +* sync - Set high after successfully loading an input. Allows synchronization of hardware thread with external drivers. +* out_val - Where weights can be read out of the perceptron. Output selected by sel_out. + +## Design Testing / Bringup + +* Simulation: In order to run the testbench ensure that the oss-cad-suite is enabled and that you are running on an x86 machine. Use the command "make -f perceptron.mk" in the terminal. The expected output can be seen below in the media section. The testbench initializes the weights of the perceptron, runs inference, runs training, and then re-runs inference. This is done for the logical functions OR, AND, and XOR. This demonstrates the perceptrons ability to learn linearly separable functions (OR and AND) but also demonstrates its limitations in learning non-linearly separable functions (XOR). + +* Testing after fabrication: In order to test after fabrication, I believe running a simple test on inference should be done. The correct weights for the AND operation can be taken from output of the testbench below and loaded into the perceptron using the control sequence from the FSM or the initialize function in perceptronTester.py. From here different variations of the inputs 0b000000 (0.0) and 0b001000 (1.0) can be loaded into the perceptron using the control sequence from the FSM or the inference function in perceptronTester.py. The update signal should be set to 0 to ensure inference is being run. The output of the perceptron will be available on the classification signal the cycle after done is asserted. This can be compared to the expected outputs of the AND operation for correctness. The same process can be repeated for the OR, XOR or any other function of your choice. Setting update to 1 and following the control sequence from the FSM for training or the training function in perceptronTester.py will allow for training to be tested. + +## Media +### Testbench output: +![Testbench output](/docs/test.png) + +## Further development + +I plan to continue to development of the perceptron on my free time for fun. I believe that an interesting next step would be to add a non-linearity in order to create a complete artificial neuron. From here I aim to create a single layer artificial neural network in hardware. diff --git a/designs/d26_cjstange_perceptron/docs/Perceptron_datapath.pdf b/designs/d26_cjstange_perceptron/docs/Perceptron_datapath.pdf new file mode 100644 index 0000000..7cc2cd5 Binary files /dev/null and b/designs/d26_cjstange_perceptron/docs/Perceptron_datapath.pdf differ diff --git a/designs/d26_cjstange_perceptron/docs/Perceptron_fsm.pdf b/designs/d26_cjstange_perceptron/docs/Perceptron_fsm.pdf new file mode 100644 index 0000000..6c3cf53 Binary files /dev/null and b/designs/d26_cjstange_perceptron/docs/Perceptron_fsm.pdf differ diff --git a/designs/d26_cjstange_perceptron/docs/computation.png b/designs/d26_cjstange_perceptron/docs/computation.png new file mode 100644 index 0000000..2e436a8 Binary files /dev/null and b/designs/d26_cjstange_perceptron/docs/computation.png differ diff --git a/designs/d26_cjstange_perceptron/docs/test.png b/designs/d26_cjstange_perceptron/docs/test.png new file mode 100644 index 0000000..e73fd8b Binary files /dev/null and b/designs/d26_cjstange_perceptron/docs/test.png differ diff --git a/designs/d26_cjstange_perceptron/info.yaml b/designs/d26_cjstange_perceptron/info.yaml new file mode 100644 index 0000000..7794852 --- /dev/null +++ b/designs/d26_cjstange_perceptron/info.yaml @@ -0,0 +1,8 @@ +--- +project: + source_files: + - toplevel_chip.v + - chip.sv + - perceptron.sv + - lib.v + top_module: "toplevel_chip" diff --git a/designs/d26_cjstange_perceptron/perceptron.mk b/designs/d26_cjstange_perceptron/perceptron.mk new file mode 100644 index 0000000..da244b0 --- /dev/null +++ b/designs/d26_cjstange_perceptron/perceptron.mk @@ -0,0 +1,5 @@ +TOPLEVEL_LANG = verilog +VERILOG_SOURCES = $(shell pwd)/src/perceptron.sv src/lib.v +TOPLEVEL = perceptron +MODULE = perceptronTester +include $(shell cocotb-config --makefiles)/Makefile.sim \ No newline at end of file diff --git a/designs/d26_cjstange_perceptron/perceptronTester.py b/designs/d26_cjstange_perceptron/perceptronTester.py new file mode 100644 index 0000000..882380f --- /dev/null +++ b/designs/d26_cjstange_perceptron/perceptronTester.py @@ -0,0 +1,188 @@ +from pathlib import Path +import cocotb +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge, FallingEdge + +def parse_vectors(filepath): + vectors = [] + with open(filepath) as f: + for line in f: + x1, x2, correct = [eval(x) for x in line.strip().split(";")] + vectors.append((x1, x2, correct)) + + return vectors + +async def reset_l(dut): + dut.reset_l.value = 0 + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + dut.reset_l.value = 1 + +#used for debuging +def resolveStateEnum(state): + enum = {0b0000: "INIT", + 0b0001: "W0", + 0b0010: "W1", + 0b0011: "W2", + 0b0100: "N", + 0b0101: "X1", + 0b0110: "X2", + 0b0111: "COMPI", + 0b1000: "CHECK", + 0b1001: "T1", + 0b1010: "T2"} + return enum.get(state, "Invalid State") + +#helper function for initializing weights +async def initialize(dut, w0, w1, w2, n): + #load enable + dut.go.value = 1 + + #LOAD W0 + dut.in_val.value = w0 + await RisingEdge(dut.clk) + + #LOAD W1 + dut.in_val.value = w1 + await RisingEdge(dut.clk) + + #LOAD W2 + dut.in_val.value = w2 + await RisingEdge(dut.clk) + + #LOAD N + dut.in_val.value = n + await RisingEdge(dut.clk) + + #disable load + dut.go.value = 0 + + await FallingEdge(dut.clk) + +#helper function for running inference +async def inference(dut, x1, x2, classification): + #turn off updating the weights + dut.update.value = 0 + + #load enable + dut.go.value = 1 + + #LOAD X1 + dut.in_val.value = x1 + await RisingEdge(dut.clk) + + #LOAD X2 + dut.in_val.value = x2 + await RisingEdge(dut.clk) + + #disable load + dut.go.value = 0 + + #wait for end of computation + await RisingEdge(dut.done) + + #get ready to run again + await RisingEdge(dut.clk) + await FallingEdge(dut.clk) + + #grab classification + classification[0] = dut.classification.value + +#helper function for doing training +async def training(dut, x1, x2, correct): + #turn on updating the weights + dut.update.value = 1 + + #load enable + dut.go.value = 1 + + #correct output + dut.correct.value = correct + + #LOAD X1 + dut.in_val.value = x1 + await RisingEdge(dut.clk) + + #LOAD X2 + dut.in_val.value = x2 + await RisingEdge(dut.clk) + + #disable load + dut.go.value = 0 + + #wait for end of computation + await RisingEdge(dut.done) + + #get ready to run again + await RisingEdge(dut.clk) + await FallingEdge(dut.clk) + +#Run series of training and inference +async def run_test(dut, training_data, inference_data): + # Reset DUT + dut.go.value = 0 + await reset_l(dut) + + #initialize weights and training rate + w0 = 0b000010 + w1 = 0b000001 + w2 = 0b000001 + n = 0b000111 + await initialize(dut, w0, w1, w2, n) + print("Weights before training:") + print("W0:", dut.data.w0.value) + print("W1:", dut.data.w1.value) + print("W2:", dut.data.w2.value, "\n") + + #run inference before training + total = 0 + yes = 0 + print("Inference before training:") + for (x1, x2, correct) in inference_data: + classification = [2] #invalid value, we know if error occurs, should be 0 or 1 + await inference(dut, x1, x2, classification) + total += 1 + if (classification[0] == correct): yes += 1 + print("Guess:", classification[0], "Correct", correct) + print("Accuracy:", yes/total, "\n") + + #do training and print updated weights + for (x1, x2, correct) in training_data: + await training(dut, x1, x2, correct) + print("Weights after training:") + print("W0:", dut.data.w0.value) + print("W1:", dut.data.w1.value) + print("W2:", dut.data.w2.value, "\n") + + #run inference after training + total = 0 + yes = 0 + print("Inference after training:") + for (x1, x2, correct) in inference_data: + classification = [2] #invalid value, we know if error occurs, should be 0 or 1 + await inference(dut, x1, x2, classification) + total += 1 + if (classification[0] == correct): yes += 1 + print("Guess:", classification[0], "Correct", correct) + print("Accuracy:", yes/total, "\n") + + +@cocotb.test() +async def test_perceptron(dut): + # Automatic clock (timescale is for VCD files) + cocotb.start_soon(Clock(dut.clk, 10, units="ns").start()) + + print("\nTEST ON LOGICAL AND") + training_data = parse_vectors("tests/and_training.txt") + inference_data = parse_vectors("tests/and_inference.txt") + await run_test(dut, training_data, inference_data) + + print("\nTEST ON LOGICAL OR") + training_data = parse_vectors("tests/or_training.txt") + inference_data = parse_vectors("tests/or_inference.txt") + await run_test(dut, training_data, inference_data) + + print("\nTEST ON XOR (Should fail)") + training_data = parse_vectors("tests/xor_training.txt") + inference_data = parse_vectors("tests/xor_inference.txt") + await run_test(dut, training_data, inference_data) \ No newline at end of file diff --git a/designs/d26_cjstange_perceptron/src/chip.sv b/designs/d26_cjstange_perceptron/src/chip.sv new file mode 100644 index 0000000..bfe27ee --- /dev/null +++ b/designs/d26_cjstange_perceptron/src/chip.sv @@ -0,0 +1,21 @@ +`default_nettype none + +module my_chip ( + input logic [11:0] io_in, // Inputs to your chip + output logic [11:0] io_out, // Outputs from your chip + input logic clock, + input logic reset); // Important: Reset is ACTIVE-HIGH + + perceptron learning(.clk(clock), + .reset_l(~reset), + .go(io_in[10]), + .update(io_in[9]), + .correct(io_in[8]), + .sel_out(io_in[7:6]), + .in_val(io_in[5:0]), + .done(io_out[8]), + .classification(io_out[7]), + .sync(io_out[6]), + .out_val(io_out[5:0])); + +endmodule diff --git a/designs/d26_cjstange_perceptron/src/config.tcl b/designs/d26_cjstange_perceptron/src/config.tcl new file mode 100644 index 0000000..aa589e4 --- /dev/null +++ b/designs/d26_cjstange_perceptron/src/config.tcl @@ -0,0 +1,68 @@ +# PLEASE DO NOT EDIT THIS FILE! +# IT WILL MAKE YOUR CHIP UNMANUFACTURABLE +# The only line you may edit is FP_CORE_UTIL +# (may benefit from reducing it slightly) + +# User config +set script_dir [file dirname [file normalize [info script]]] + +# read some user config that is written by the setup.py program. +# - the name of the module is defined +# - the list of source files +source $::env(DESIGN_DIR)/user_config.tcl + +# save some time +set ::env(RUN_KLAYOUT_XOR) 0 +set ::env(RUN_KLAYOUT_DRC) 0 + +# don't put clock buffers on the outputs +set ::env(PL_RESIZER_BUFFER_OUTPUT_PORTS) 0 + +# allow use of specific sky130 cells +set ::env(SYNTH_READ_BLACKBOX_LIB) 1 + +# put all the pins on the left +set ::env(FP_PIN_ORDER_CFG) $::env(DESIGN_DIR)/pin_order.cfg + +# reduce wasted space +set ::env(TOP_MARGIN_MULT) 2 +set ::env(BOTTOM_MARGIN_MULT) 2 + +# absolute die size +set ::env(FP_SIZING) absolute +set ::env(DIE_AREA) "0 0 280 280" + +## THIS IS THE ONLY LINE YOU CAN EDIT +set ::env(FP_CORE_UTIL) 45 + +## set ::env(PL_BASIC_PLACEMENT) {1} + +set ::env(FP_IO_HLENGTH) 2 +set ::env(FP_IO_VLENGTH) 2 + +# use alternative efabless decap cells to solve LI density issue +set ::env(DECAP_CELL) "\ + sky130_fd_sc_hd__decap_3 \ + sky130_fd_sc_hd__decap_4 \ + sky130_fd_sc_hd__decap_6 \ + sky130_fd_sc_hd__decap_8 \ + sky130_ef_sc_hd__decap_12" + +# clock +set ::env(CLOCK_TREE_SYNTH) 1 + +# period is in ns, so 500ns == 2 MHz +set ::env(CLOCK_PERIOD) "500" +set ::env(CLOCK_PORT) {io_in[12]} + +# hold/slack margin +# set ::env(PL_RESIZER_HOLD_SLACK_MARGIN) 0.8 +# set ::env(GLB_RESIZER_HOLD_SLACK_MARGIN) 0.8 + +# don't use power rings or met5 +set ::env(DESIGN_IS_CORE) 0 +set ::env(RT_MAX_LAYER) {met4} + +# connect to first digital rails +set ::env(VDD_NETS) [list {vccd1}] +set ::env(GND_NETS) [list {vssd1}] diff --git a/designs/d26_cjstange_perceptron/src/lib.sv b/designs/d26_cjstange_perceptron/src/lib.sv new file mode 100644 index 0000000..fb477b9 --- /dev/null +++ b/designs/d26_cjstange_perceptron/src/lib.sv @@ -0,0 +1,66 @@ +//counter +module counter + #(parameter WIDTH=0) + (input logic clk, reset_l, en, clr, + output logic [WIDTH-1:0] count); + + always_ff @(posedge clk, negedge reset_l) begin + if (!reset_l) + count <= 'b0; + else if (clr) + count <= 'b0; + else if (en) + count <= count + 1; + + end +endmodule: counter + +//register +module register + #(parameter WIDTH=0) + (input logic clk, en, reset_l, + input logic [WIDTH-1:0] D, + output logic [WIDTH-1:0] Q); + + always_ff @(posedge clk, negedge reset_l) begin + if (!reset_l) + Q <= 'b0; + else if (en) + Q <= D; + end +endmodule: register + +//mux +module mux + #(parameter INPUTS=0, WIDTH=0) + (input logic [INPUTS-1:0][WIDTH-1:0] in, + input logic [$clog2(INPUTS)-1:0] sel, + output logic [WIDTH-1:0] out); + + assign out = in[sel]; +endmodule: mux + +//6-bit fixed point multplier -- paramatrize this +module mult + (input logic [5:0] A, B, + output logic [5:0] M); + + logic [11:0] tmp; + assign tmp = A*B; + + //required for fixed point...add documentation to explain + //want middle 6 bits + //12 11 10 9 8 7 6 5 4 3 2 1 0 + assign M = tmp[9:3]; +endmodule: mult + +//adder +module adder + #(parameter WIDTH=0) + (input logic cin, + input logic [WIDTH-1:0] A, B, + output logic cout, + output logic [WIDTH-1:0] sum); + + assign {cout, sum} = A + B + cin; +endmodule: adder \ No newline at end of file diff --git a/designs/d26_cjstange_perceptron/src/lib.v b/designs/d26_cjstange_perceptron/src/lib.v new file mode 100644 index 0000000..f6166ac --- /dev/null +++ b/designs/d26_cjstange_perceptron/src/lib.v @@ -0,0 +1,78 @@ +module counter (clk, + reset_l, + en, + clr, + count); + parameter WIDTH = 0; + input wire clk; + input wire reset_l; + input wire en; + input wire clr; + output reg [WIDTH - 1:0] count; + + always @(posedge clk or negedge reset_l) + if (!reset_l) + count <= 'b0; + else if (clr) + count <= 'b0; + else if (en) + count <= count + 1; +endmodule + +module register (clk, + en, + reset_l, + D, + Q); + parameter WIDTH = 0; + input wire clk; + input wire en; + input wire reset_l; + input wire [WIDTH - 1:0] D; + output reg [WIDTH - 1:0] Q; + + always @(posedge clk or negedge reset_l) + if (!reset_l) + Q <= 'b0; + else if (en) + Q <= D; +endmodule + +module mux (in, + sel, + out); + parameter INPUTS = 0; + parameter WIDTH = 0; + input wire [(INPUTS * WIDTH) - 1:0] in; + input wire [$clog2(INPUTS) - 1:0] sel; + output wire [WIDTH - 1:0] out; + + assign out = in[sel * WIDTH+:WIDTH]; +endmodule + +module mult (A, + B, + M); + input wire [5:0] A; + input wire [5:0] B; + output wire [5:0] M; + wire [11:0] tmp; + + assign tmp = A * B; + assign M = tmp[9:3]; +endmodule + +module adder (cin, + A, + B, + cout, + sum); + parameter WIDTH = 0; + input wire cin; + input wire [WIDTH - 1:0] A; + input wire [WIDTH - 1:0] B; + output wire cout; + output wire [WIDTH - 1:0] sum; + + assign {cout, sum} = (A + B) + cin; +endmodule \ No newline at end of file diff --git a/designs/d26_cjstange_perceptron/src/perceptron.sv b/designs/d26_cjstange_perceptron/src/perceptron.sv new file mode 100644 index 0000000..cdf474b --- /dev/null +++ b/designs/d26_cjstange_perceptron/src/perceptron.sv @@ -0,0 +1,381 @@ +`default_nettype none + +module perceptron + (input logic clk, reset_l, + input logic go, update, correct, + input logic [1:0] sel_out, + input logic [5:0] in_val, + output logic done, classification, sync, + output logic [5:0] out_val); + + //define internal signal + logic en_w0, en_w1, en_w2, ext_w0, ext_w1, ext_w2, sel_add_A; + logic en_n, en_x1, en_x2, en_add, en_mult, en_count, clr_count; + logic [1:0] count, sel_add_B, sel_mult_A, sel_mult_B; + + fsm control(.*); + + datapath data(.*); +endmodule + +module datapath + (input logic clk, reset_l, + input logic en_w0, en_w1, en_w2, en_n, clr_count, + input logic en_x1, en_x2, en_count, en_mult, correct, + input logic en_add, ext_w0, ext_w1, ext_w2, sel_add_A, + input logic [1:0] sel_out, sel_add_B, + input logic [1:0] sel_mult_A, sel_mult_B, + input logic [5:0] in_val, + output logic classification, + output logic [1:0] count, + output logic [5:0] out_val); + + //define internal signals + logic [5:0] w0, w1, w2, n, x1, x2, d; + logic [5:0] add_out_reg, mult_out_reg, add_out, mult_out; + logic [5:0] add_A, add_B, mult_A, mult_B; + + //input mux + mux #(4, 6) input_mux(.in({w0, w1, w2, add_out_reg}), + .sel(sel_out), + .out(out_val)); + + //w0 reg + register #(6) w0_reg(.clk, + .reset_l, + .en(en_w0), + .D((ext_w0) ? in_val : add_out), + .Q(w0)); + + //w1 reg + register #(6) w1_reg(.clk, + .reset_l, + .en(en_w1), + .D((ext_w1) ? in_val : add_out), + .Q(w1)); + + //w2 reg + register #(6) w2_reg(.clk, + .reset_l, + .en(en_w2), + .D((ext_w2) ? in_val : add_out), + .Q(w2)); + + //n reg + register #(6) n_reg(.clk, + .reset_l, + .en(en_n), + .D(in_val), + .Q(n)); + + //x1 reg + register #(6) x1_reg(.clk, + .reset_l, + .en(en_x1), + .D(in_val), + .Q(x1)); + + //x2 reg + register #(6) x2_reg(.clk, + .reset_l, + .en(en_x2), + .D(in_val), + .Q(x2)); + + //counter + counter #(2) counter(.clk, + .reset_l, + .en(en_count), + .clr(clr_count), + .count); + + //mult reg + register #(6) mult_reg(.clk, + .reset_l, + .en(en_mult), + .D(mult_out), + .Q(mult_out_reg)); + + //mult + mult mult(.A(mult_A), + .B(mult_B), + .M(mult_out)); + + //mult_A mux + mux #(4, 6) mult_A_mux(.in({w1, w2, n, mult_out_reg}), + .sel(sel_mult_A), + .out(mult_A)); + + //mult_B mux + mux #(4, 6) mult_B_mux(.in({x1, x2, 6'd1, d}), + .sel(sel_mult_B), + .out(mult_B)); + + //add reg + register #(6) add_reg(.clk, + .reset_l, + .en(en_add), + .D(add_out), + .Q(add_out_reg)); + + //add + adder #(6) add(.cin(1'd0), + .A(add_A), + .B(add_B), + .cout(), + .sum(add_out)); + + //add_A mux + mux #(2, 6) add_A_mux(.in({6'd0, mult_out_reg}), + .sel(sel_add_A), + .out(add_A)); + + //add_B mux + mux #(4, 6) add_B_mux(.in({w0, add_out_reg, w1, w2}), + .sel(sel_add_B), + .out(add_B)); + + //non module logic + //Need to think about these comparions in terms of + always_comb begin + //only look at non decimal bits? + //Correctness needs to be tested + if ($signed(add_out_reg[5:3]) > 0) + classification = 1'd1; + else + classification = 1'd0; + + if (correct) + d = 6'b001000; //d = 1 + else + d = 6'b100000; //d = -1 + end +endmodule + +module fsm + (input logic clk, reset_l, + input logic go, update, correct, classification, + input logic [1:0] count, + output logic done, sync, //external to user + output logic en_w0, en_w1, en_w2, ext_w0, ext_w1, ext_w2, sel_add_A, + output logic en_n, en_x1, en_x2, en_add, en_mult, en_count, clr_count, + output logic [1:0] sel_add_B, sel_mult_A, sel_mult_B); + + enum logic [3:0] {INIT, W0, W1, W2, N, X1, X2, COMPI, CHECK, T1, T2} state, nextState; + + //nextState logic + always_comb begin + case (state) + INIT: begin + if (go) + nextState = W0; + else + nextState = INIT; + end + + W0: begin + if (go) + nextState = W1; + else + nextState = W0; + end + + W1: begin + if (go) + nextState = W2; + else + nextState = W1; + end + + W2: begin + if (go) + nextState = N; + else + nextState = W2; + end + + N: begin + if (go) + nextState = X1; + else + nextState = N; + end + + X1: begin + if (go) + nextState = X2; + else + nextState = X1; + end + + X2: nextState = COMPI; + + COMPI: begin + if (update) + nextState = CHECK; + else + nextState = N; + end + + CHECK: begin + if ((correct == classification) || (count > 2)) + nextState = N; + else + nextState = T1; + end + + T1: nextState = T2; + + T2: nextState = CHECK; + + default: nextState = INIT; + endcase + end + + //output logic + always_comb begin + //initialize output values + done = 1'd0; + // classification = 1'd0; + sync = 1'd0; + en_w0 = 1'd0; + ext_w0 = 1'd0; + en_w1 = 1'd0; + ext_w1 = 1'd0; + en_w2 = 1'd0; + ext_w2 = 1'd0; + en_n = 1'd0; + en_x1 = 1'd0; + en_x2 = 1'd0; + sel_add_A = 1'd0; + sel_add_B = 2'd0; + en_add = 1'd0; + sel_mult_B = 2'd0; + sel_mult_A = 2'd0; + en_mult = 1'd0; + en_count = 1'd0; + clr_count = 1'd0; + + case (state) + INIT: begin + if (go) begin + en_w0 = 1'd1; + ext_w0 = 1'd1; + sync = 1'd1; + end + end + + W0: begin + if (go) begin + en_w1 = 1'd1; + ext_w1 = 1'd1; + sync = 1'd1; + end + end + + W1: begin + if (go) begin + en_w2 = 1'd1; + ext_w2 = 1'd1; + sync = 1'd1; + end + end + + W2: begin + if (go) begin + en_n = 1'd1; + sync = 1'd1; + end + end + + N: begin + if (go) begin + en_x1 = 1'd1; + sel_add_A = 1'd1; //0 + sel_add_B = 2'd3; //w0 + en_add = 1'd1; + sync = 1'd1; + end + end + + X1: begin + if (go) begin + en_x2 = 1'd1; + sel_mult_A = 2'd3; //w1 + sel_mult_B = 2'd3; //x1 + en_mult = 1'd1; + end + end + + + X2: begin + sel_add_A = 1'd0; //mult_out_reg + sel_add_B = 2'd2; //add_out_reg + en_add = 1'd1; + sel_mult_A = 2'd2; //w2 + sel_mult_B = 2'd2; //x2 + en_mult = 1'd1; + end + + COMPI: begin + sel_add_A = 1'd0; //mult_out_reg + sel_add_B = 2'd2; //add_out_reg + en_add = 1'd1; + if (update) + clr_count = 1'd1; + else begin + done= 1'd1; + end + end + + CHECK: begin + if ((correct == classification) || (count > 2)) + done = 1'd1; + else begin + sel_mult_A = 2'd1; //n + en_mult = 1'd1; + case (count) + 2'd0: sel_mult_B = 2'd1; //1 + 2'd1: sel_mult_B = 2'd3; //x1 + default: sel_mult_B = 2'd2; //x2 + endcase + end + end + + T1: begin + sel_mult_A = 2'd0; //mult_out_reg + sel_mult_B = 2'd0; //d + en_mult = 1'd1; + end + + T2: begin + en_count = 1'd1; + sel_add_A = 1'd0; // mult_out_reg + case (count) + 2'd0: begin + en_w0 = 1'd1; + sel_add_B = 2'd3; //w0 + end + + 2'd1: begin + en_w1 = 1'd1; + sel_add_B = 2'd1; //w1 + end + + default: begin + //count == 2 + en_w2 = 1'd1; + sel_add_B = 2'd0; //w2 + end + endcase + end + endcase + end + + always_ff @(posedge clk, negedge reset_l) begin + if (!reset_l) + state <= INIT; + else + state <= nextState; + end +endmodule \ No newline at end of file diff --git a/designs/d26_cjstange_perceptron/src/pin_order.cfg b/designs/d26_cjstange_perceptron/src/pin_order.cfg new file mode 100644 index 0000000..0b85c63 --- /dev/null +++ b/designs/d26_cjstange_perceptron/src/pin_order.cfg @@ -0,0 +1,9 @@ +#N + +#S + +#E + +#W +io_in.* +io_out.* diff --git a/designs/d26_cjstange_perceptron/src/toplevel_chip.v b/designs/d26_cjstange_perceptron/src/toplevel_chip.v new file mode 100644 index 0000000..a82b427 --- /dev/null +++ b/designs/d26_cjstange_perceptron/src/toplevel_chip.v @@ -0,0 +1,18 @@ +`default_nettype none + +// DO NOT EDIT THIS FILE +module toplevel_chip ( + input [13:0] io_in, + output [13:0] io_out +); + + my_chip mchip ( + .io_in(io_in[11:0]), + .io_out(io_out[11:0]), + .clock(io_in[12]), + .reset(io_in[13]) + ); + + assign io_out[13:12] = 2'b00; + +endmodule diff --git a/designs/d26_cjstange_perceptron/tests/and_inference.txt b/designs/d26_cjstange_perceptron/tests/and_inference.txt new file mode 100644 index 0000000..8e59319 --- /dev/null +++ b/designs/d26_cjstange_perceptron/tests/and_inference.txt @@ -0,0 +1,4 @@ +0b000000; 0b000000; 0 +0b000000; 0b001000; 0 +0b001000; 0b000000; 0 +0b001000; 0b001000; 1 \ No newline at end of file diff --git a/designs/d26_cjstange_perceptron/tests/and_training.txt b/designs/d26_cjstange_perceptron/tests/and_training.txt new file mode 100644 index 0000000..fef9fff --- /dev/null +++ b/designs/d26_cjstange_perceptron/tests/and_training.txt @@ -0,0 +1,40 @@ +0b000000; 0b000000; 0 +0b000000; 0b001000; 0 +0b001000; 0b000000; 0 +0b001000; 0b001000; 1 +0b000000; 0b000000; 0 +0b000000; 0b001000; 0 +0b001000; 0b000000; 0 +0b001000; 0b001000; 1 +0b000000; 0b000000; 0 +0b000000; 0b001000; 0 +0b001000; 0b000000; 0 +0b001000; 0b001000; 1 +0b000000; 0b000000; 0 +0b000000; 0b001000; 0 +0b001000; 0b000000; 0 +0b001000; 0b001000; 1 +0b000000; 0b000000; 0 +0b000000; 0b001000; 0 +0b001000; 0b000000; 0 +0b001000; 0b001000; 1 +0b000000; 0b000000; 0 +0b000000; 0b001000; 0 +0b001000; 0b000000; 0 +0b001000; 0b001000; 1 +0b000000; 0b000000; 0 +0b000000; 0b001000; 0 +0b001000; 0b000000; 0 +0b001000; 0b001000; 1 +0b000000; 0b000000; 0 +0b000000; 0b001000; 0 +0b001000; 0b000000; 0 +0b001000; 0b001000; 1 +0b000000; 0b000000; 0 +0b000000; 0b001000; 0 +0b001000; 0b000000; 0 +0b001000; 0b001000; 1 +0b000000; 0b000000; 0 +0b000000; 0b001000; 0 +0b001000; 0b000000; 0 +0b001000; 0b001000; 1 \ No newline at end of file diff --git a/designs/d26_cjstange_perceptron/tests/or_inference.txt b/designs/d26_cjstange_perceptron/tests/or_inference.txt new file mode 100644 index 0000000..aef23c5 --- /dev/null +++ b/designs/d26_cjstange_perceptron/tests/or_inference.txt @@ -0,0 +1,4 @@ +0b000000; 0b000000; 0 +0b000000; 0b001000; 1 +0b001000; 0b000000; 1 +0b001000; 0b001000; 1 \ No newline at end of file diff --git a/designs/d26_cjstange_perceptron/tests/or_training.txt b/designs/d26_cjstange_perceptron/tests/or_training.txt new file mode 100644 index 0000000..27b060f --- /dev/null +++ b/designs/d26_cjstange_perceptron/tests/or_training.txt @@ -0,0 +1,40 @@ +0b000000; 0b000000; 0 +0b000000; 0b001000; 1 +0b001000; 0b000000; 1 +0b001000; 0b001000; 1 +0b000000; 0b000000; 0 +0b000000; 0b001000; 1 +0b001000; 0b000000; 1 +0b001000; 0b001000; 1 +0b000000; 0b000000; 0 +0b000000; 0b001000; 1 +0b001000; 0b000000; 1 +0b001000; 0b001000; 1 +0b000000; 0b000000; 0 +0b000000; 0b001000; 1 +0b001000; 0b000000; 1 +0b001000; 0b001000; 1 +0b000000; 0b000000; 0 +0b000000; 0b001000; 1 +0b001000; 0b000000; 1 +0b001000; 0b001000; 1 +0b000000; 0b000000; 0 +0b000000; 0b001000; 1 +0b001000; 0b000000; 1 +0b001000; 0b001000; 1 +0b000000; 0b000000; 0 +0b000000; 0b001000; 1 +0b001000; 0b000000; 1 +0b001000; 0b001000; 1 +0b000000; 0b000000; 0 +0b000000; 0b001000; 1 +0b001000; 0b000000; 1 +0b001000; 0b001000; 1 +0b000000; 0b000000; 0 +0b000000; 0b001000; 1 +0b001000; 0b000000; 1 +0b001000; 0b001000; 1 +0b000000; 0b000000; 0 +0b000000; 0b001000; 1 +0b001000; 0b000000; 1 +0b001000; 0b001000; 1 \ No newline at end of file diff --git a/designs/d26_cjstange_perceptron/tests/xor_inference.txt b/designs/d26_cjstange_perceptron/tests/xor_inference.txt new file mode 100644 index 0000000..663de78 --- /dev/null +++ b/designs/d26_cjstange_perceptron/tests/xor_inference.txt @@ -0,0 +1,4 @@ +0b000000; 0b000000; 0 +0b000000; 0b001000; 1 +0b001000; 0b000000; 1 +0b001000; 0b001000; 0 \ No newline at end of file diff --git a/designs/d26_cjstange_perceptron/tests/xor_training.txt b/designs/d26_cjstange_perceptron/tests/xor_training.txt new file mode 100644 index 0000000..6133cb5 --- /dev/null +++ b/designs/d26_cjstange_perceptron/tests/xor_training.txt @@ -0,0 +1,45 @@ +0b000000; 0b000000; 0 +0b000000; 0b001000; 1 +0b001000; 0b000000; 1 +0b001000; 0b001000; 0 +0b000000; 0b000000; 0 +0b001000; 0b000000; 1 +0b000000; 0b001000; 1 +0b001000; 0b000000; 1 +0b001000; 0b000000; 1 +0b001000; 0b001000; 0 +0b001000; 0b001000; 0 +0b000000; 0b000000; 0 +0b000000; 0b001000; 1 +0b001000; 0b000000; 1 +0b001000; 0b001000; 0 +0b000000; 0b000000; 0 +0b001000; 0b001000; 0 +0b000000; 0b000000; 0 +0b001000; 0b001000; 0 +0b000000; 0b000000; 0 +0b000000; 0b001000; 1 +0b000000; 0b001000; 1 +0b001000; 0b000000; 1 +0b001000; 0b000000; 1 +0b001000; 0b001000; 0 +0b000000; 0b000000; 0 +0b000000; 0b001000; 1 +0b001000; 0b000000; 1 +0b001000; 0b000000; 1 +0b001000; 0b001000; 0 +0b000000; 0b000000; 0 +0b000000; 0b001000; 1 +0b001000; 0b001000; 0 +0b001000; 0b001000; 0 +0b001000; 0b000000; 1 +0b001000; 0b001000; 0 +0b000000; 0b000000; 0 +0b000000; 0b001000; 1 +0b001000; 0b000000; 1 +0b001000; 0b000000; 1 +0b001000; 0b001000; 0 +0b000000; 0b000000; 0 +0b000000; 0b001000; 1 +0b001000; 0b000000; 1 +0b001000; 0b001000; 0 \ No newline at end of file diff --git a/designs/d27_svemulap_fpu/.lastupdated b/designs/d27_svemulap_fpu/.lastupdated new file mode 100644 index 0000000..4d7b8c3 --- /dev/null +++ b/designs/d27_svemulap_fpu/.lastupdated @@ -0,0 +1 @@ +2023-05-14 diff --git a/designs/d27_svemulap_fpu/LICENSE b/designs/d27_svemulap_fpu/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/designs/d27_svemulap_fpu/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/designs/d27_svemulap_fpu/Picture1.png b/designs/d27_svemulap_fpu/Picture1.png new file mode 100644 index 0000000..0c35352 Binary files /dev/null and b/designs/d27_svemulap_fpu/Picture1.png differ diff --git a/designs/d27_svemulap_fpu/Picture2.png b/designs/d27_svemulap_fpu/Picture2.png new file mode 100644 index 0000000..458afd3 Binary files /dev/null and b/designs/d27_svemulap_fpu/Picture2.png differ diff --git a/designs/d27_svemulap_fpu/Picture3.png b/designs/d27_svemulap_fpu/Picture3.png new file mode 100644 index 0000000..250c1ea Binary files /dev/null and b/designs/d27_svemulap_fpu/Picture3.png differ diff --git a/designs/d27_svemulap_fpu/README.md b/designs/d27_svemulap_fpu/README.md new file mode 100644 index 0000000..b9ec739 --- /dev/null +++ b/designs/d27_svemulap_fpu/README.md @@ -0,0 +1,95 @@ +# 16-Bit Floating Point Unit + +By: Sri Lakshmi +18-224/624 Spring 2023 Final Tapeout Project + +## Overview + +A 16-bit Floating point Unit (Adder and Multiplier) follows FP-16 (half-precision) format. A select signal is used to choose between Addition and Multiplication of two 16-bit Input Floating Point Numbers. The 16-bit signals use 1 bit for the sign, 5 bits for the exponent, and 10 bits for the significand or mantissa. +Along with two 16-bit input signals, select and control signals are given as inputs. The resultant output is a 16-bit result and a valid signal. + +* Format: Sign - 1 bit Exponent - 5 bits Mantissa - 10 bit +* Exception Encoding + * NaN 0 11111 1111111111 + * +∞ 0 11111 0000000000 + * −∞ 1 11111 0000000000 + * Underflow 0 00000 0000000000 + +## How it Works + +An FSM is used in the top-level to control all the inputs, outputs, and control signals. The select signal is set to high for Addition and low for multiplication. The control signal is set to high when the inputs are given to the system and is low for the rest of the operations. Each Sub Module (Adder and Multiplier) takes in 2 16-bit data input values and results in One 16-bit Result and a valid signal. The Sub Modules are Combinational. The 16-bit inputs take in 4 cycles to fully obtain. And the 16-bit outputs take in 2 cycles to be generated out. + + +Block Diagram: + +![](Picture2.png) + +Detailed I/O Description: + +![](Picture1.png) + + +## Inputs/Outputs + +Inputs: + +To give in two 16-bit Inputs, we are doing it in 4 cycles. 10 of the 12 available ports are used. + + +* IO_IN [3:0] - Input for Signal A +* IO_IN [7:4] - Input for Signal B +* IO_IN [8] - Select Signal +* IO_IN [9] - Control Signal +* IO_IN [11:10] - Not Used + +Output: + +To receive a 16-bit output along with the valid signal, we do it in 2 cycles. 9 of the 12 available ports are used. + + +* IO_OUT [7:0] - Output Data. +* IO_OUT [8] - Valid Signal. +* IO_OUT [11:9] - Not Used + +## Design Testing + +For the testing of the design, the FSM is configured from a test bench. +The inputs are given in 4 different clock cycles. The control signal is set high along with configuring the select signal. In the next 4 consecutive clock cycle, the inputs are passed through the above-mentioned configuration. Once the inputs are passed, the control signal goes low, and the results are populated in the next two consecutive clock cycles along with the valid signal. + +Module fpu_16_tb has the testbench used for testing the design. It also contains the checker scripts and validates the received results with the expected ones. + +For Example: + +Inputs: +If Inputs A = 16'h4D3D and B = 16'h48EA +Select would be high for Addition. Expected Result would be: 16'h4FB2 + +In this configuration the test bench would be something very similar to: +1. In first clock cycle: +io_in[8] = 1 - Making select high for addition. +io_in[9] = 1 - Making Control signal high to give inputs. +2. In the next consecutive clock cycles, the input data is given as below. +* Clock Cycle 1: + io_in[3:0] = D + io_in[7:4] = A +* Clock Cycle 2: + io_in[3:0] = 3 + io_in[7:4] = E +* Clock Cycle 3: + io_in[3:0] = D + io_in[7:4] = 8 +* Clock Cycle 4: + io_in[3:0] = 4 + io_in[7:4] = 4 +3. In the next clock cycle, the control signal io_in[9] is made low. +4. In the next 2 clock cycles, the output is generated out through the io_out port as below: +* First Clock Cycle: + io_out[7:0] - 'B2 + io_out[8] - 1 +* Next Clock Cycle: + io_out[7:0] - '4F + io_out[8] - 1 +## Simulation Results: + +![](Picture3.png) + diff --git a/designs/d27_svemulap_fpu/info.yaml b/designs/d27_svemulap_fpu/info.yaml new file mode 100644 index 0000000..6e86fda --- /dev/null +++ b/designs/d27_svemulap_fpu/info.yaml @@ -0,0 +1,9 @@ +--- +project: + source_files: + - toplevel_chip.v + - chip.sv + - mul_16.sv + - add_16.sv + top_module: "toplevel_chip" + diff --git a/designs/d27_svemulap_fpu/src/add_16.sv b/designs/d27_svemulap_fpu/src/add_16.sv new file mode 100644 index 0000000..3ab44b9 --- /dev/null +++ b/designs/d27_svemulap_fpu/src/add_16.sv @@ -0,0 +1,162 @@ +/* +Floating point Adder: 16 - bit: +Algorithm: Add the exponent of the smaller number from the exponent of the larger number, and +shift the mantissa of the smaller number to align with the larger number. Then Add the mantissas of the aligned numbers together +Check if the result needs to be normalized, if yes, shift correspondingly and calculate the normalized result +*/ + +`timescale 1ns/1ps +`default_nettype none + +module add(input_a, input_b, add_out,add_valid); + //Ports + input logic [15:0] input_a, input_b; // Input Ports + output logic [15:0] add_out; // Output Ports + output logic add_valid; // Output Valid Signal + + // Internal Logic Signals. + logic [15:0] value_2, value_1; + logic [4:0] exp_2, exp_1; + logic [10:0] max_diff, min_diff; + logic [10:0] sing_1, shift_1; + logic [4:0] diff_expon; + logic [9:0] shifted_value; + logic [3:0] to_shift; + logic [9:0] shift_ext; + logic [9:0] shift_ext_1; + logic [9:0] dec_2, dec_1; + logic [4:0] temp_2, temp_1,temp_3; + logic sign_2, sign_1; + logic overflow; + logic NaN; + logic [10:0] sum; + logic sum_carry; + logic sign_equal; + logic is_zero; + logic is_inf; + logic [4:0] temp_exp, temp_exp_check; + + assign NaN = (&input_a[14:10] & |input_a[9:0]) | (&input_b[14:10] & |input_b[9:0]); + assign is_inf = (&input_a[14:10] & ~|input_a[9:0]) | (&input_b[14:10] & ~|input_b[9:0]); + assign overflow = ((&exp_2[4:1] & ~exp_2[0]) & sum_carry & sign_equal) | is_inf; + assign add_out[15] = sign_2; + assign temp_exp = exp_2 + {4'd0, (~is_zero & sum_carry & sign_equal)} - {4'd0,({1'b0,add_out[9:0]} == sum)}; + assign temp_exp_check = (temp_3 | (to_shift == 4'd10)) ? 5'd0 : (~to_shift + exp_2 + 5'd1); + assign add_out[14:10] = ((sign_equal) ? temp_exp : temp_exp_check) | {5{overflow}}; + assign add_out[9:0] = ((is_zero) ? dec_2 : ((sign_equal) ? ((sum_carry) ? sum[10:1] : sum[9:0]) : ((temp_3) ? 10'd0 : shifted_value))) & {10{~overflow}}; + + assign {sign_2, temp_2, dec_2} = value_2; + assign {sign_1, temp_1, dec_1} = value_1; + assign sign_equal = (sign_2 == sign_1); + assign is_zero = ~(|exp_1 | |dec_1); + assign exp_2 = temp_2 + {4'd0, ~|temp_2}; + assign exp_1 = temp_1 + {4'd0, ~|temp_1}; + + assign max_diff = {|temp_2, dec_2}; + assign min_diff = {|temp_1, dec_1}; + assign diff_expon = exp_2 - exp_1; + assign {sum_carry, sum} = sing_1 + max_diff; + assign shift_ext_1 = shift_ext; + + always @(*) begin + if(NaN) + add_valid = 0; + else add_valid = 1; + end + +// Assigning the input values based of which is greater for further computation. + always @(*) begin + if(input_b[14:10] > input_a[14:10]) + begin + value_2 = input_b; + value_1 = input_a; + end + else if(input_b[14:10] == input_a[14:10]) + begin + if(input_b[9:0] > input_a[9:0]) + begin + value_2 = input_b; + value_1 = input_a; + end + else + begin + value_2 = input_a; + value_1 = input_b; + end + end + else + begin + value_2 = input_a; + value_1 = input_b; + end + end + + assign temp_3 = (exp_2 < to_shift); + +// To determine the value after shifting. + always @(*) begin + case (to_shift) + 4'd0: shifted_value = sum[9:0]; + 4'd1: shifted_value = {sum[8:0],shift_ext_1[9]}; + 4'd2: shifted_value = {sum[7:0],shift_ext_1[9:8]}; + 4'd3: shifted_value = {sum[6:0],shift_ext_1[9:7]}; + 4'd4: shifted_value = {sum[5:0],shift_ext_1[9:6]}; + 4'd5: shifted_value = {sum[4:0],shift_ext_1[9:5]}; + 4'd6: shifted_value = {sum[3:0],shift_ext_1[9:4]}; + 4'd7: shifted_value = {sum[2:0],shift_ext_1[9:3]}; + 4'd8: shifted_value = {sum[1:0],shift_ext_1[9:2]}; + 4'd9: shifted_value = {sum[0], shift_ext_1[9:1]}; + default: shifted_value = shift_ext_1; + endcase + end + + always @(*) begin + case (diff_expon) + 5'h0: {shift_1,shift_ext} = {min_diff,10'd0}; + 5'h1: {shift_1,shift_ext} = {min_diff,9'd0}; + 5'h2: {shift_1,shift_ext} = {min_diff,8'd0}; + 5'h3: {shift_1,shift_ext} = {min_diff,7'd0}; + 5'h4: {shift_1,shift_ext} = {min_diff,6'd0}; + 5'h5: {shift_1,shift_ext} = {min_diff,5'd0}; + 5'h6: {shift_1,shift_ext} = {min_diff,4'd0}; + 5'h7: {shift_1,shift_ext} = {min_diff,3'd0}; + 5'h8: {shift_1,shift_ext} = {min_diff,2'd0}; + 5'h9: {shift_1,shift_ext} = {min_diff,1'd0}; + 5'ha: {shift_1,shift_ext} = min_diff; + 5'hb: {shift_1,shift_ext} = min_diff[10:1]; + 5'hc: {shift_1,shift_ext} = min_diff[10:2]; + 5'hd: {shift_1,shift_ext} = min_diff[10:3]; + 5'he: {shift_1,shift_ext} = min_diff[10:4]; + 5'hf: {shift_1,shift_ext} = min_diff[10:5]; + 5'h10: {shift_1,shift_ext} = min_diff[10:5]; + 5'h11: {shift_1,shift_ext} = min_diff[10:6]; + 5'h12: {shift_1,shift_ext} = min_diff[10:7]; + 5'h13: {shift_1,shift_ext} = min_diff[10:8]; + 5'h14: {shift_1,shift_ext} = min_diff[10:9]; + 5'h15: {shift_1,shift_ext} = min_diff[10]; + 5'h16: {shift_1,shift_ext} = 0; + default: begin shift_1 = 0; + shift_ext = 0; + end + endcase + end + +assign sing_1 = sign_equal? shift_1 : ~shift_1 + 11'b1; +// To determine how much is to be shifted + always @(*) begin + casex(sum) + 11'b1??????????: to_shift = 4'd0; + 11'b01?????????: to_shift = 4'd1; + 11'b001????????: to_shift = 4'd2; + 11'b0001???????: to_shift = 4'd3; + 11'b00001??????: to_shift = 4'd4; + 11'b000001?????: to_shift = 4'd5; + 11'b0000001????: to_shift = 4'd6; + 11'b00000001???: to_shift = 4'd7; + 11'b000000001??: to_shift = 4'd8; + 11'b0000000001?: to_shift = 4'd9; + default: to_shift = 4'd10; + endcase + end + +endmodule \ No newline at end of file diff --git a/designs/d27_svemulap_fpu/src/chip.sv b/designs/d27_svemulap_fpu/src/chip.sv new file mode 100644 index 0000000..d202b7c --- /dev/null +++ b/designs/d27_svemulap_fpu/src/chip.sv @@ -0,0 +1,115 @@ +/* Top Module - 16 - bit Floating Point Unit + Sub-Modules - FPU Adder and FPU Multiplier +Description: +Each Sub Module(Adder and Multiplier) takes in 2 16-bit data input values and +results in One 16-bit Result and a valid signal. The Sub Modules are Combinational. +The 16-bit inputs takes in 4 cycles to fully obtain. And the 16-bit outputs take in +2 cycels to be generated out. +Input Ports: Out of the 12 available ports, we are using 10 of the ports + io_in[3:0] - Input A + io_in[7:4] - Input B + io_in[8] - Select Signal + io_in[9] - Control Signal +Output Ports: 9 of the 12 available ports are used + io_out[7:0] - Output Result + io_out[8] - Valid Signal. +*/ +`timescale 1ns/1ps +`default_nettype none + +module my_chip ( + input logic [11:0] io_in, + output logic [11:0] io_out, + input logic clock, + input logic reset +); + + // Local Declarations + reg [15:0] value_A,value_B; // Inputs to Adder and Multiplier + reg [15:0] tmp_input_A, tmp_input_B; // Temporary storage of inputs in each cycle + reg [15:0] result; // Final result to be sent out to io_out + reg [15:0] temp_result_add; // Results from Add Block + reg [15:0] temp_result_mul; // Results from Mul Block + reg temp_valid_mul, temp_valid_add; // Valid Output from Mul and Add block + reg select; // Select takes the value to io_in[8] port and decides to take in Multiplier or Adder Output + reg valid; // Final validity of result goes to io_out[8] + reg [3:0] count; // Count is used as a counter to keep a track of each input rounds as inputs are given in 4 cycles. + reg [1:0] i; // Used for Iteration + integer j; // Used to keep a count of input iteration assignment. + +// To select between Multiplier and Adder. Input port (io_in[8]) is assigned +assign select = io_in[8]; + + always @(posedge clock) begin + // Input Controls. + if(reset) begin + tmp_input_A <= 0; + tmp_input_B <= 0; + count <= 1; + j <= 0; + i <= 0; + io_out[8:0] <= 'h0; + result <= 'h0; + valid <= 'h0; + end + // io_in[9] is an input signal which is enabled when the inputs are given. + else if (io_in[9]) begin + // Assigning the stored inputs to the inputs to the adder/multiplier module. + if(count == 6) begin + value_A <= tmp_input_A; + value_B <= tmp_input_B; + end + // Iterating till all the inputs are received. + else begin + tmp_input_A[j-:4] <= io_in[3:0]; + tmp_input_B[j-:4] <= io_in[7:4]; + count <= count +1; + j <= (4*count) -1; + end + end + // Output Controls. + else if(!io_in[9]) begin + case(i) + 2'd0: begin // Decides which result should be taken based on the select signal. + result <= select ? temp_result_add : temp_result_mul; + valid <= select ? temp_valid_add : temp_valid_mul; + i <= 2'd1; + end + 2'd1: begin // Assigns 8 bits starting from LSB to the output port + io_out[7:0] <= result[7:0]; + io_out[8] <= valid; + count <=1; + i <= 2'd2; + end + 2'd2: begin // Assigning the next 8 bits to the output port. + io_out[7:0] <= result[15:8]; + i <= 2'd3; + end + 2'd3: begin // Idle State + i <= 2'd0; + io_out[8] <= 'h0; + end + default: begin i <= 2'd0; + io_out[8] <= 'h0; + end + endcase + end + end + //Adder and Multiplier Modules + add inst_add( + .input_a(value_A), + .input_b(value_B), + .add_valid(temp_valid_add), + .add_out(temp_result_add) + ); + + mul inst_mul( + .input_a(value_A), + .input_b(value_B), + .mul_valid(temp_valid_mul), + .mul_out(temp_result_mul) + ); + +endmodule + + diff --git a/designs/d27_svemulap_fpu/src/config.tcl b/designs/d27_svemulap_fpu/src/config.tcl new file mode 100644 index 0000000..aa589e4 --- /dev/null +++ b/designs/d27_svemulap_fpu/src/config.tcl @@ -0,0 +1,68 @@ +# PLEASE DO NOT EDIT THIS FILE! +# IT WILL MAKE YOUR CHIP UNMANUFACTURABLE +# The only line you may edit is FP_CORE_UTIL +# (may benefit from reducing it slightly) + +# User config +set script_dir [file dirname [file normalize [info script]]] + +# read some user config that is written by the setup.py program. +# - the name of the module is defined +# - the list of source files +source $::env(DESIGN_DIR)/user_config.tcl + +# save some time +set ::env(RUN_KLAYOUT_XOR) 0 +set ::env(RUN_KLAYOUT_DRC) 0 + +# don't put clock buffers on the outputs +set ::env(PL_RESIZER_BUFFER_OUTPUT_PORTS) 0 + +# allow use of specific sky130 cells +set ::env(SYNTH_READ_BLACKBOX_LIB) 1 + +# put all the pins on the left +set ::env(FP_PIN_ORDER_CFG) $::env(DESIGN_DIR)/pin_order.cfg + +# reduce wasted space +set ::env(TOP_MARGIN_MULT) 2 +set ::env(BOTTOM_MARGIN_MULT) 2 + +# absolute die size +set ::env(FP_SIZING) absolute +set ::env(DIE_AREA) "0 0 280 280" + +## THIS IS THE ONLY LINE YOU CAN EDIT +set ::env(FP_CORE_UTIL) 45 + +## set ::env(PL_BASIC_PLACEMENT) {1} + +set ::env(FP_IO_HLENGTH) 2 +set ::env(FP_IO_VLENGTH) 2 + +# use alternative efabless decap cells to solve LI density issue +set ::env(DECAP_CELL) "\ + sky130_fd_sc_hd__decap_3 \ + sky130_fd_sc_hd__decap_4 \ + sky130_fd_sc_hd__decap_6 \ + sky130_fd_sc_hd__decap_8 \ + sky130_ef_sc_hd__decap_12" + +# clock +set ::env(CLOCK_TREE_SYNTH) 1 + +# period is in ns, so 500ns == 2 MHz +set ::env(CLOCK_PERIOD) "500" +set ::env(CLOCK_PORT) {io_in[12]} + +# hold/slack margin +# set ::env(PL_RESIZER_HOLD_SLACK_MARGIN) 0.8 +# set ::env(GLB_RESIZER_HOLD_SLACK_MARGIN) 0.8 + +# don't use power rings or met5 +set ::env(DESIGN_IS_CORE) 0 +set ::env(RT_MAX_LAYER) {met4} + +# connect to first digital rails +set ::env(VDD_NETS) [list {vccd1}] +set ::env(GND_NETS) [list {vssd1}] diff --git a/designs/d27_svemulap_fpu/src/fpu_16_tb.sv b/designs/d27_svemulap_fpu/src/fpu_16_tb.sv new file mode 100644 index 0000000..b8a789b --- /dev/null +++ b/designs/d27_svemulap_fpu/src/fpu_16_tb.sv @@ -0,0 +1,267 @@ +/// TestBench //// + +`timescale 1ns/1ps +`default_nettype none +module fpu_16_tb; + +logic [15:0] input_1; +logic [15:0] input_2; +logic [15:0] result; +logic valid; +logic [15:0] expected_result; +logic [11:0] io_in,io_out; +logic reset; +logic result_en,temp; +logic clock; + +logic [15:0] received_result; +integer counter; +always #0.5 clock = ~clock; + +my_chip inst_fpu1 ( + .io_in(io_in), + .io_out(io_out), + .reset(reset), + .clock(clock) + ); + +// Select = 1 ---- Addition +// Select = 0 ---- Multiplication +initial begin + clock = 0; + reset = 1; + counter = 0; + repeat(10) @(negedge clock); + reset = 0; + // Addition + input_en(1); + select(1); + write(16'h5051,16'h5051); + expected_result = 16'h5451; + input_en(0); + read(); + // Multiplication + input_en(1); + select(0); + write(16'h5007,16'h5007); + expected_result = 16'h640E; + input_en(0); + read(); + // Addition + input_en(1); + select(1); + write(16'h5051,16'hD051); + expected_result = 16'h0000; + input_en(0); + read(); + // Multiplication + input_en(1); + select(0); + write(16'h5007,16'hD007); + expected_result = 16'hE40E; + input_en(0); + read(); + // Addition + input_en(1); + select(1); + write(16'h4D3D,16'h48EA); + expected_result = 16'h4FB2; + input_en(0); + read(); + // Multiplication + input_en(1); + select(0); + write(16'h4976,16'h426C); + expected_result = 16'h5062; + input_en(0); + read(); + // Addition + input_en(1); + select(1); + write(16'hCD3D,16'hC8EA); + expected_result = 16'hCFB2; + input_en(0); + read(); + // Multiplication + input_en(1); + select(0); + write(16'hC976,16'hC26C); + expected_result = 16'h5062; + input_en(0); + read(); + // Addition + input_en(1); + select(1); + write(16'h4D86,16'hC91C); + expected_result = 16'h49F0; + input_en(0); + read(); + // Multiplication + input_en(1); + select(0); + write(16'hC976,16'h426C); + expected_result = 16'hD062; + input_en(0); + read(); + // Addition + input_en(1); + select(1); + write(16'hCD86,16'h491C); + expected_result = 16'hC9F0; + input_en(0); + read(); + // Multiplication + input_en(1); + select(0); + write(16'h426C,16'hC976); + expected_result = 16'hD062; + input_en(0); + read(); + // Addition + input_en(1); + select(1); + write(16'h03FF,16'h0001); + expected_result = 16'h0400; + input_en(0); + read(); + // Multiplication + input_en(1); + select(0); + write(16'h03FF,16'h0001); + expected_result = 16'h0000; + input_en(0); + read(); + // Addition + input_en(1); + select(1); + write(16'h03FF,16'h03FF); + expected_result = 16'h07FE; + input_en(0); + read(); + // Multiplication + input_en(1); + select(0); + write(16'h03FF,16'h03FF); + expected_result = 16'h0000; + input_en(0); + read(); + // Addition + input_en(1); + select(1); + write(16'h7BFF,16'h7BFF); + expected_result = 16'h7C00; + input_en(0); + read(); + // Multiplication + input_en(1); + select(0); + write(16'h7BFF,16'h7BFF); + expected_result = 16'h7C00; + input_en(0); + read(); + // Addition + input_en(1); + select(1); + write(16'h7C00,16'h3666); + expected_result = 16'h7C00; + input_en(0); + read(); + // Multiplication + input_en(1); + select(0); + write(16'h7C00,16'h3666); + expected_result = 16'h7C00; + input_en(0); + read(); + // Addition + input_en(1); + select(1); + write(16'hFC00,16'h0015); + expected_result = 16'hFC00; + input_en(0); + read(); + // Multiplication + input_en(1); + select(0); + write(16'hFFFF,16'h7BFF); + expected_result = 16'hFFFF; + input_en(0); + read(); + // Addition + input_en(1); + select(1); + write(16'hFFFF,16'h7BFF); + expected_result = 16'hFFFF; + input_en(0); + read(); + + +#500; +$finish; +end + +// Example 8'hDA -- D is for value 1 and A is for Value 2 + +task automatic write(input [15:0] a, input [15:0] b); +begin + + repeat(1) @(negedge clock); + io_in[3:0] = a[3:0]; + io_in[7:4] = b[3:0]; + repeat(1) @(negedge clock); + io_in[3:0] = a[7:4]; + io_in[7:4] = b[7:4]; + repeat(1) @(negedge clock); + io_in[3:0] = a[11:8]; + io_in[7:4] = b[11:8]; + repeat(1) @(negedge clock); + io_in[3:0] = a[15:12]; + io_in[7:4] = b[15:12]; + repeat(2) @(negedge clock); +end +endtask + +task automatic read(); +begin + repeat(2) @(negedge clock); + received_result[7:0] = io_out[7:0]; + repeat(1) @(negedge clock); + received_result[15:8] = io_out[7:0]; + repeat(1) @(negedge clock); + counter = counter +1; +end +endtask + +// Select Signal to chose between Adder and Multiplier +task automatic select(input logic n); +begin + io_in[8] = n; +end +endtask + +// Control Signal to tell the module that input is coming +task automatic input_en(input logic n); +begin + io_in[9] = n; +end +endtask + +always @(posedge clock) begin + temp <= io_out[8]; +end + +always @(posedge clock) begin + result_en <= temp && io_out[8]; +end + +// Checker Script +always @(posedge clock) begin + if(result_en) begin + $display("Hello - No Error - Yaaaaay - Count - %d",counter); + if((received_result != expected_result)) begin + $display("Oh Shit Error --- Expected Result: %h, Achieved Result: %h",expected_result,received_result); + end + + end +end +endmodule diff --git a/designs/d27_svemulap_fpu/src/mul_16.sv b/designs/d27_svemulap_fpu/src/mul_16.sv new file mode 100644 index 0000000..27d0835 --- /dev/null +++ b/designs/d27_svemulap_fpu/src/mul_16.sv @@ -0,0 +1,187 @@ +/* +Floating Point Multiplier: + +*/ + +`timescale 1ns/1ps +`default_nettype none + +module mul(input_a, input_b, mul_out, mul_valid); + input logic [15:0] input_a, input_b; // INput Ports + output logic [15:0] mul_out; // Output Port + output logic mul_valid; // Output Valid Port + +// Internal Logic Signals + logic [4:0] expo_1, expo_2, expo_final; + logic [4:0] expo_1_temp, expo_2_temp, expo_final_temp; + logic [4:0] expo_diff; + logic [4:0] temp1; + logic check_1; + logic [9:0] frac_1, frac_2, frac_final; + logic [9:0] frac_diff, frac_diff_final; + logic [20:0] temp_f_1; + logic [10:0] temp_f_2; + logic expo_sign; + logic [6:0] expo_temp1; + logic [5:0] expo_bias_1, expo_bias_final; + logic [11:0] temp_4, temp_4_before; + logic [9:0] frac_temp; + logic [9:0] dummy; + logic [21:0] final_value; + logic [21:0] before_value; + logic [20:0] temp_value[10:0]; + logic sign_1, sign_2, sign_final; + logic is_inf; + logic overflow; + logic is_zero; + logic NaN; + logic subnormal_value; + + + always @(*) begin + if(NaN) + mul_valid = 0; + else mul_valid = 1; + end + + assign check_1 = {1'b0,expo_diff} > expo_bias_final; + assign is_zero = (~(|input_a[14:0] & |input_b[14:0])) | ((subnormal_value & (frac_diff == 10'd0)) | (expo_sign & (~|final_value[20:11]))); + assign expo_temp1 = expo_bias_1 - 7'd15; + assign expo_bias_1 = {1'b0,expo_1} + {1'b0,expo_2}; + assign expo_bias_final = (expo_sign) ? (~expo_temp1[5:0] + 6'd1) : expo_temp1[5:0]; + assign {sign_1, expo_1_temp, frac_1} = input_a; + assign {sign_2, expo_2_temp, frac_2} = input_b; + assign expo_1 = expo_1_temp + {4'd0, ~|expo_1_temp}; + assign expo_2 = expo_2_temp + {4'd0, ~|expo_2_temp}; + assign expo_sign = expo_temp1[6]; + assign NaN = (&input_a[14:10] & |input_a[9:0]) | (&input_b[14:10] & |input_b[9:0]); + assign is_inf = (&input_a[14:10] & ~|input_a[9:0]) | (&input_b[14:10] & ~|input_b[9:0]); + assign overflow = is_inf | (~expo_temp1[6] & expo_temp1[5]); + assign subnormal_value = ~|temp_4[11:10]; + + assign mul_out = {sign_final, expo_final, frac_final}; + assign temp_f_1 = {|expo_1_temp, frac_1, 10'd0}; + assign temp_f_2 = {|expo_2_temp, frac_2}; + assign sign_final = (sign_1 ^ sign_2); + assign expo_final_temp = expo_temp1[4:0] + {4'd0, temp_4[11]} + (~expo_diff & {5{subnormal_value}}) + {4'd0, subnormal_value}; + assign expo_final = (expo_final_temp | {5{overflow}}) & {5{~(is_zero | expo_sign | check_1)}}; + assign frac_final = ((expo_sign) ? final_value[20:11] :((subnormal_value) ? frac_diff_final : frac_temp)) & {10{~(is_zero | overflow)}} ; + assign frac_temp = (temp_4[11]) ? temp_4[10:1] : temp_4[9:0]; + assign temp_4 = temp_4_before + {10'd0,dummy[9]}; + assign {temp_4_before, dummy} = before_value; + assign before_value = temp_value[0] + temp_value[1] + temp_value[2] + temp_value[3] + temp_value[4] + temp_value[5] + temp_value[6] + temp_value[7] + temp_value[8] + temp_value[9] + temp_value[10]; + assign temp1 = expo_diff - expo_bias_final[4:0]; + + always @(*) + begin + if(expo_sign) + case(expo_bias_final) + 6'h0: final_value = before_value; + 6'h1: final_value = (before_value >> 1); + 6'h2: final_value = (before_value >> 2); + 6'h3: final_value = (before_value >> 3); + 6'h4: final_value = (before_value >> 4); + 6'h5: final_value = (before_value >> 5); + 6'h6: final_value = (before_value >> 6); + 6'h7: final_value = (before_value >> 7); + 6'h8: final_value = (before_value >> 8); + 6'h9: final_value = (before_value >> 9); + 6'ha: final_value = (before_value >> 10); + 6'hb: final_value = (before_value >> 11); + 6'hc: final_value = (before_value >> 12); + 6'hd: final_value = (before_value >> 13); + 6'he: final_value = (before_value >> 14); + 6'hf: final_value = (before_value >> 15); + default: final_value = (before_value >> 16); + endcase + else + final_value = before_value; + end + always @(*) + begin + if(check_1) + case(temp1) + 5'h0: frac_diff_final = frac_diff; + 5'h1: frac_diff_final = (frac_diff >> 1); + 5'h2: frac_diff_final = (frac_diff >> 2); + 5'h3: frac_diff_final = (frac_diff >> 3); + 5'h4: frac_diff_final = (frac_diff >> 4); + 5'h5: frac_diff_final = (frac_diff >> 5); + 5'h6: frac_diff_final = (frac_diff >> 6); + 5'h7: frac_diff_final = (frac_diff >> 7); + 5'h8: frac_diff_final = (frac_diff >> 8); + 5'h9: frac_diff_final = (frac_diff >> 9); + default: frac_diff_final = 10'h0; + endcase + else + frac_diff_final = frac_diff; + end + + always @(*) + begin + temp_value[0] = (temp_f_1 >> 10) & {21{temp_f_2[0]}}; + temp_value[1] = (temp_f_1 >> 9) & {21{temp_f_2[1]}}; + temp_value[2] = (temp_f_1 >> 8) & {21{temp_f_2[2]}}; + temp_value[3] = (temp_f_1 >> 7) & {21{temp_f_2[3]}}; + temp_value[4] = (temp_f_1 >> 6) & {21{temp_f_2[4]}}; + temp_value[5] = (temp_f_1 >> 5) & {21{temp_f_2[5]}}; + temp_value[6] = (temp_f_1 >> 4) & {21{temp_f_2[6]}}; + temp_value[7] = (temp_f_1 >> 3) & {21{temp_f_2[7]}}; + temp_value[8] = (temp_f_1 >> 2) & {21{temp_f_2[8]}}; + temp_value[9] = (temp_f_1 >> 1) & {21{temp_f_2[9]}}; + temp_value[10] = temp_f_1 & {21{temp_f_2[10]}}; + end + +// To determine the fraction coefficient + always @(*) + begin + case(final_value) + 22'b001???????????????????: frac_diff = final_value[18:9]; + 22'b0001??????????????????: frac_diff = final_value[17:8]; + 22'b00001?????????????????: frac_diff = final_value[16:7]; + 22'b000001????????????????: frac_diff = final_value[15:6]; + 22'b0000001???????????????: frac_diff = final_value[14:5]; + 22'b00000001??????????????: frac_diff = final_value[13:4]; + 22'b000000001?????????????: frac_diff = final_value[12:3]; + 22'b0000000001????????????: frac_diff = final_value[11:2]; + 22'b00000000001???????????: frac_diff = final_value[10:1]; + 22'b000000000001??????????: frac_diff = final_value[9:0]; + 22'b0000000000001?????????: frac_diff = {final_value[8:0], 1'd0}; + 22'b00000000000001????????: frac_diff = {final_value[7:0], 2'd0}; + 22'b000000000000001???????: frac_diff = {final_value[6:0], 3'd0}; + 22'b0000000000000001??????: frac_diff = {final_value[5:0], 4'd0}; + 22'b00000000000000001?????: frac_diff = {final_value[4:0], 5'd0}; + 22'b000000000000000001????: frac_diff = {final_value[3:0], 6'd0}; + 22'b0000000000000000001???: frac_diff = {final_value[2:0], 7'd0}; + 22'b00000000000000000001??: frac_diff = {final_value[1:0], 8'd0}; + 22'b000000000000000000001?: frac_diff = {final_value[0], 9'd0}; + default: frac_diff = 10'd0; + endcase + end +// To shift the exponent value + always @(*) + begin + case(final_value) + 22'b001???????????????????: expo_diff = 5'd1; + 22'b0001??????????????????: expo_diff = 5'd2; + 22'b00001?????????????????: expo_diff = 5'd3; + 22'b000001????????????????: expo_diff = 5'd4; + 22'b0000001???????????????: expo_diff = 5'd5; + 22'b00000001??????????????: expo_diff = 5'd6; + 22'b000000001?????????????: expo_diff = 5'd7; + 22'b0000000001????????????: expo_diff = 5'd8; + 22'b00000000001???????????: expo_diff = 5'd9; + 22'b000000000001??????????: expo_diff = 5'd10; + 22'b0000000000001?????????: expo_diff = 5'd11; + 22'b00000000000001????????: expo_diff = 5'd12; + 22'b000000000000001???????: expo_diff = 5'd13; + 22'b0000000000000001??????: expo_diff = 5'd14; + 22'b00000000000000001?????: expo_diff = 5'd15; + 22'b000000000000000001????: expo_diff = 5'd16; + 22'b0000000000000000001???: expo_diff = 5'd17; + 22'b00000000000000000001??: expo_diff = 5'd18; + 22'b000000000000000000001?: expo_diff = 5'd19; + default: expo_diff = 5'd0; + endcase + end +endmodule diff --git a/designs/d27_svemulap_fpu/src/pin_order.cfg b/designs/d27_svemulap_fpu/src/pin_order.cfg new file mode 100644 index 0000000..0b85c63 --- /dev/null +++ b/designs/d27_svemulap_fpu/src/pin_order.cfg @@ -0,0 +1,9 @@ +#N + +#S + +#E + +#W +io_in.* +io_out.* diff --git a/designs/d27_svemulap_fpu/src/toplevel_chip.v b/designs/d27_svemulap_fpu/src/toplevel_chip.v new file mode 100644 index 0000000..a82b427 --- /dev/null +++ b/designs/d27_svemulap_fpu/src/toplevel_chip.v @@ -0,0 +1,18 @@ +`default_nettype none + +// DO NOT EDIT THIS FILE +module toplevel_chip ( + input [13:0] io_in, + output [13:0] io_out +); + + my_chip mchip ( + .io_in(io_in[11:0]), + .io_out(io_out[11:0]), + .clock(io_in[12]), + .reset(io_in[13]) + ); + + assign io_out[13:12] = 2'b00; + +endmodule diff --git a/designs/d28_gvenkata_ucpu/.lastupdated b/designs/d28_gvenkata_ucpu/.lastupdated new file mode 100644 index 0000000..4d7b8c3 --- /dev/null +++ b/designs/d28_gvenkata_ucpu/.lastupdated @@ -0,0 +1 @@ +2023-05-14 diff --git a/designs/d28_gvenkata_ucpu/LICENSE b/designs/d28_gvenkata_ucpu/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/designs/d28_gvenkata_ucpu/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/designs/d28_gvenkata_ucpu/README.md b/designs/d28_gvenkata_ucpu/README.md new file mode 100644 index 0000000..62d273c --- /dev/null +++ b/designs/d28_gvenkata_ucpu/README.md @@ -0,0 +1,29 @@ +# Micro-programmed 8-bit CPU, with horizontal control store + +Ganesh Venkatachalam +18-224/624 Spring 2023 Final Tapeout Project + +## Overview + +The goal of this project is to design an 8-bit CPU with a microprogrammed control unit instead of a hardwired control unit. A hardwired control unit takes an +instruction, decodes it and generates control signals that direct the flow of data between the CPU’s registers, ALU units and data memory. This is established by the +use of hardware multiplexers that are built at RTL design time and are responsible for selecting among various input operands to various functional and memory units in +the CPU. This design paradigm is highly efficient in terms of performance and power but comes at the cost of flexibility since interconnections between the various +units in a CPU are determined and hardwired at design time and cannot be changed later after the CPU has been fabricated. Introducing new instructions/modified +functionality for existing instructions in the ISA is not possible. +A microprogrammed CPU solves this problem by introducing another level of abstraction on top of the instructions in the ISA. A microprogrammed CPU decomposes an instruction into a series of micro-instructions/microcodes that are typically simple operations carried out in succession to realize the effect of the original instruction. + + +## How it Works +Each instruction is decomposed into a set of template-micro-instructions (micro-ops) which are stored in an External data memory. The CPU's FSM will fetch each micro-instruction corresponding to an instruction and executes them to completion. + + +## Inputs/Outputs + +1. System clock - Input system clock/external clock. +2. System reset - Input system reset. +3. Instruction address - Output pin that sends out the address of the next instruction to be executed ( address bits are sent synchronous with respect to the system clock). +4. Micro-Instruction address - Output pin that sends out the address of the next micro-instruction to be fetched and executed ( address bits are sent synchronous with respect to the system clock). +5. Instruction stream - Input pin that receives instruction address bits serially. +6. Micro-instruction stream - Input pin that receives micro-instruction address bits serially. + diff --git a/designs/d28_gvenkata_ucpu/decoder.v b/designs/d28_gvenkata_ucpu/decoder.v new file mode 100644 index 0000000..8d6310e --- /dev/null +++ b/designs/d28_gvenkata_ucpu/decoder.v @@ -0,0 +1,38 @@ + +/* + -- 1 -- + | | + 6 2 + | | + -- 7 -- + | | + 5 3 + | | + -- 4 -- +*/ + +module seg7 ( + input wire [3:0] counter, + output reg [6:0] segments +); + + always @(*) begin + case(counter) + // 7654321 + 0: segments = 7'b0111111; + 1: segments = 7'b0000110; + 2: segments = 7'b1011011; + 3: segments = 7'b1001111; + 4: segments = 7'b1100110; + 5: segments = 7'b1101101; + 6: segments = 7'b1111100; + 7: segments = 7'b0000111; + 8: segments = 7'b1111111; + 9: segments = 7'b1100111; + default: + segments = 7'b0000000; + endcase + end + +endmodule + diff --git a/designs/d28_gvenkata_ucpu/info.yaml b/designs/d28_gvenkata_ucpu/info.yaml new file mode 100644 index 0000000..3078799 --- /dev/null +++ b/designs/d28_gvenkata_ucpu/info.yaml @@ -0,0 +1,13 @@ +--- +project: + source_files: + - toplevel_chip.v + - chip.sv + - mcpu.sv + - micro_reg.sv + - alu.v + - inst_mem.sv + - shared_bus.sv + - decode.sv + top_module: "toplevel_chip" + diff --git a/designs/d28_gvenkata_ucpu/src/alu.v b/designs/d28_gvenkata_ucpu/src/alu.v new file mode 100644 index 0000000..5425e9d --- /dev/null +++ b/designs/d28_gvenkata_ucpu/src/alu.v @@ -0,0 +1,157 @@ +`include "defines.vh" + +module alu_unit_interface ( + sys_clk, + sys_reset, + cpu_state, + A_bus, B_bus, + alu_en_A_reg, alu_en_B_reg, + alu_op, + cc_greater, + cc_equal, + alu_result, + A_reg, + B_reg + ); + + input sys_clk, sys_reset; + input alu_en_A_reg, alu_en_B_reg; + input [$clog2(`CPU_STATES)-1:0] cpu_state; + input [$clog2(`ALU_OPS)-1:0] alu_op; + input [`ALU_WIDTH-1:0] A_bus, B_bus; + + wire alu_en; + + /*Registered ALU outputs*/ + output reg cc_greater, cc_equal; + output reg [`ALU_WIDTH-1:0] alu_result; + + output reg [`ALU_WIDTH-1:0] A_reg, B_reg; + + /*Control signals for loading from A_bus and B_bus*/ + // wire A_reg_en, B_reg_en, alu_result_load; + + assign alu_en = alu_en_A_reg || alu_en_B_reg; + // assign A_reg_en = (alu_en == 1'b1 && reg_src == A_REG_MAP && cpu_state == `EXECUTE1); + // assign B_reg_en = (alu_en == 1'b1 && reg_src == B_REG_MAP && cpu_state == `EXECUTE1); + // assign alu_result_load = (alu_en && cpu_state == `EXECUTE2); + + logic [`ALU_WIDTH-1:0] alu_result_out; + logic cc_greater_out, cc_equal_out; + + /*Control signal to load ALU micro-registers*/ + + always @(posedge sys_clk) begin + if(sys_reset) begin + A_reg <= 0; + B_reg <= 0; + alu_result <= 0; + cc_greater <= 0; + cc_equal <= 0; + end + else begin + if(alu_en_A_reg && cpu_state == `EXECUTE1) begin + A_reg <= A_bus; + end + if(alu_en_B_reg && cpu_state == `EXECUTE1) begin + B_reg <= B_bus; + end + if(alu_en && cpu_state == `EXECUTE2) begin + alu_result <= alu_result_out; + cc_greater <= cc_greater_out; + cc_equal <= cc_equal_out; + end + end + end + + /*carry in*/ + wire carry_in; + assign carry_in = 1'b0; + + //ALU module + alu_unit alu(.A(A_reg), .B(B_reg), .carry_in(carry_in), + .alu_op(alu_op), .alu_result(alu_result_out), + .greater(cc_greater_out), .equal(cc_equal_out)); + +endmodule + +module alu_unit ( + A, + B, + carry_in, + alu_op, + alu_result, + greater, + equal +); + input [`ALU_WIDTH-1:0] A,B; + input carry_in; + input [$clog2(`ALU_OPS)-1:0] alu_op; + output [`ALU_WIDTH-1:0] alu_result; + output greater, equal; + + reg [`ALU_WIDTH-1:0] alu_result_tmp; + + assign alu_result = alu_result_tmp; + + /* + alu_op_md + 0000 - nop + 0001 - add + 0010 - sub + 0011 - or + 0100 - and + 0101 - not + 0110 - lsl + 0111 - lsr + 1000 - asr + 1001 - cmp + */ + + wire [`ALU_WIDTH-1:0] zero, a_plus_b, a_minus_b, a_or_b, a_and_b, a_negated; + wire [`ALU_WIDTH-1:0] a_lfs, a_rfs, a_arfs; + + assign a_plus_b = A + B; + assign a_minus_b = A - B; + assign a_or_b = A | B; + assign a_and_b = A & B; + assign a_negated = ~A; + assign a_lfs = A << B; + assign a_rfs = A >> B; + assign a_arfs = A >>> B; + assign zero = {`ALU_WIDTH{1'b0}}; + + always @(*) begin + case (alu_op) + // 4'b0000: alu_result = {`ALU_WIDTH{1'b0}}; + 4'b0000: alu_result_tmp = zero; + 4'b0001: alu_result_tmp = a_plus_b; + 4'b0010: alu_result_tmp = a_minus_b; + 4'b0011: alu_result_tmp = a_or_b; + 4'b0100: alu_result_tmp = a_and_b; + 4'b0101: alu_result_tmp = a_negated; + 4'b0110: alu_result_tmp = a_lfs; + 4'b0111: alu_result_tmp = a_rfs; + 4'b1000: alu_result_tmp = a_arfs; + default: alu_result_tmp = zero; + endcase + end + + reg a_greater_b, a_equal_b; + assign greater = a_greater_b; + assign equal = a_equal_b; + + always @(*) begin + case (alu_op) + 4'b1001: begin + a_greater_b = (A>B); + a_equal_b = (A==B); + end + default: begin + a_greater_b = 1'b0; + a_equal_b = 1'b0; + end + endcase + end +endmodule + diff --git a/designs/d28_gvenkata_ucpu/src/chip.sv b/designs/d28_gvenkata_ucpu/src/chip.sv new file mode 100644 index 0000000..6a239ff --- /dev/null +++ b/designs/d28_gvenkata_ucpu/src/chip.sv @@ -0,0 +1,65 @@ +`default_nettype none + +module my_chip ( + input logic [11:0] io_in, // Inputs to your chip + output logic [11:0] io_out, // Outputs from your chip + input logic clock, + input logic reset // Important: Reset is ACTIVE-HIGH +); + + // Basic counter design as an example + /* + module top_cpu( + sys_clk, + sys_reset, + instr_in, + m_instr_in, + inst_addr_stream, + m_inst_addr_stream + + ); + */ + + top_cpu micro_coded_cpu(.sys_clk(clock), + .sys_reset(reset), + .instr_in(io_in[0]), + .m_instr_in(io_in[1]), + .inst_addr_stream(io_out[0]), + .m_inst_addr_stream(io_out[1]) + ); + /* + wire [6:0] led_out; + assign io_out[6:0] = led_out; + + // external clock is 1000Hz, so need 10 bit counter + reg [9:0] second_counter; + reg [3:0] digit; + + always @(posedge clock) begin + // if reset, set counter to 0 + if (reset) begin + second_counter <= 0; + digit <= 0; + end else begin + // if up to 16e6 + if (second_counter == 1000) begin + // reset + second_counter <= 0; + + // increment digit + digit <= digit + 1'b1; + + // only count from 0 to 9 + if (digit == 9) + digit <= 0; + + end else + // increment counter + second_counter <= second_counter + 1'b1; + end + end + + // instantiate segment display + seg7 seg7(.counter(digit), .segments(led_out)); + */ +endmodule diff --git a/designs/d28_gvenkata_ucpu/src/config.tcl b/designs/d28_gvenkata_ucpu/src/config.tcl new file mode 100644 index 0000000..aa589e4 --- /dev/null +++ b/designs/d28_gvenkata_ucpu/src/config.tcl @@ -0,0 +1,68 @@ +# PLEASE DO NOT EDIT THIS FILE! +# IT WILL MAKE YOUR CHIP UNMANUFACTURABLE +# The only line you may edit is FP_CORE_UTIL +# (may benefit from reducing it slightly) + +# User config +set script_dir [file dirname [file normalize [info script]]] + +# read some user config that is written by the setup.py program. +# - the name of the module is defined +# - the list of source files +source $::env(DESIGN_DIR)/user_config.tcl + +# save some time +set ::env(RUN_KLAYOUT_XOR) 0 +set ::env(RUN_KLAYOUT_DRC) 0 + +# don't put clock buffers on the outputs +set ::env(PL_RESIZER_BUFFER_OUTPUT_PORTS) 0 + +# allow use of specific sky130 cells +set ::env(SYNTH_READ_BLACKBOX_LIB) 1 + +# put all the pins on the left +set ::env(FP_PIN_ORDER_CFG) $::env(DESIGN_DIR)/pin_order.cfg + +# reduce wasted space +set ::env(TOP_MARGIN_MULT) 2 +set ::env(BOTTOM_MARGIN_MULT) 2 + +# absolute die size +set ::env(FP_SIZING) absolute +set ::env(DIE_AREA) "0 0 280 280" + +## THIS IS THE ONLY LINE YOU CAN EDIT +set ::env(FP_CORE_UTIL) 45 + +## set ::env(PL_BASIC_PLACEMENT) {1} + +set ::env(FP_IO_HLENGTH) 2 +set ::env(FP_IO_VLENGTH) 2 + +# use alternative efabless decap cells to solve LI density issue +set ::env(DECAP_CELL) "\ + sky130_fd_sc_hd__decap_3 \ + sky130_fd_sc_hd__decap_4 \ + sky130_fd_sc_hd__decap_6 \ + sky130_fd_sc_hd__decap_8 \ + sky130_ef_sc_hd__decap_12" + +# clock +set ::env(CLOCK_TREE_SYNTH) 1 + +# period is in ns, so 500ns == 2 MHz +set ::env(CLOCK_PERIOD) "500" +set ::env(CLOCK_PORT) {io_in[12]} + +# hold/slack margin +# set ::env(PL_RESIZER_HOLD_SLACK_MARGIN) 0.8 +# set ::env(GLB_RESIZER_HOLD_SLACK_MARGIN) 0.8 + +# don't use power rings or met5 +set ::env(DESIGN_IS_CORE) 0 +set ::env(RT_MAX_LAYER) {met4} + +# connect to first digital rails +set ::env(VDD_NETS) [list {vccd1}] +set ::env(GND_NETS) [list {vssd1}] diff --git a/designs/d28_gvenkata_ucpu/src/decode.sv b/designs/d28_gvenkata_ucpu/src/decode.sv new file mode 100644 index 0000000..348371c --- /dev/null +++ b/designs/d28_gvenkata_ucpu/src/decode.sv @@ -0,0 +1,147 @@ +`include "defines.vh" +/* + Instruction format + Branch + __________ + |27:31|0:26| + |__________| + + Register 3 operand + _______________________________ + |27:31|26|22:25|18:21|14:17|13:0| + |_______________________________| + + Immediate 3 operand + _________________________ + |27:31|26|22:25|18:21|0:17| + |_________________________| +*/ +module instruction_decoder( + instr_in, + is_imm_active_id, + inst_type, + reg_dst_id, + reg_src_1_id, + reg_src_2_id, + imm_id, + branch_target_id + ); + input [31:0] instr_in; + output is_imm_active_id; + output [3:0] reg_src_1_id, reg_src_2_id, reg_dst_id; + output [7:0] imm_id; + output [7:0] branch_target_id; + output [4:0] inst_type; + + assign inst_type = instr_in[31:27]; + assign is_imm_active_id = instr_in[26]; + assign reg_dst_id = instr_in[25:22]; + assign reg_src_1_id = instr_in[21:18]; + assign reg_src_2_id = instr_in[17:14]; + assign branch_target_id = instr_in[7:0]; + assign imm_id = instr_in[7:0]; + +endmodule + +/* + Micro-instruction format + _________________________________ + |43:41|40:36|35:31|30:20|19:10|9:0| + |_________________________________| + Fields: + 43:41 - Micro-instruction type + 40:36 - Source register + 35:31 - Destination register + 30:20 - Immediate value (consider only 27:20) + 19:10 - Branch target micro PC ( consider only 10:17 ) + 9:0 - Bus arguments + +*/ +module micro_inst_decoder ( + minstr_in, + minstr_type, + reg_src_md, + reg_dst_md, + imm_md, + mbranch_target_md, + is_imm_active_md, + reg_file_en_md, + reg_file_rw_md, + alu_en_A_md, + alu_en_B_md, + alu_op_md, + // mem_en_md, + // mem_rw_md, + is_branch_md + ); + //localparam MREG_SPEC_WIDTH = $clog2(`MREG_COUNT); + //localparam MINST_TYPE_WIDTH = $clog2(`MINST_COUNT); + + /*Inputs*/ + //Input micro-instruction + input [`MINST_WIDTH-1:0] minstr_in; + + /*Outputs*/ + /*Micro instruction type*/ + output [`MINST_TYPE_WIDTH-1:0] minstr_type; + //Microinstruction source and destination register mapping + output [`MREG_SPEC_WIDTH-1:0] reg_src_md, reg_dst_md; + //Immediate value + output [`IMM_WIDTH-1:0] imm_md; + //Branch target value + output [`MBRANCH_ADDR_WIDTH-1:0] mbranch_target_md; + + /*Output control signals*/ + output alu_en_A_md, alu_en_B_md; + output [$clog2(`ALU_OPS)-1:0] alu_op_md; + output is_imm_active_md; + output reg_file_en_md, reg_file_rw_md; + //output mem_en_md, mem_rw_md; + output is_branch_md; + + + + /*Args Field in the instruction*/ + wire [`BUS_ARGS-1:0] m_args; + + /*Extract the fields*/ + assign minstr_type = minstr_in[43:41]; + assign reg_src_md = minstr_in[40:36]; + assign reg_dst_md = minstr_in[35:31]; + assign imm_md = minstr_in[27:20]; + assign mbranch_target_md = minstr_in[17:10]; + assign m_args = minstr_in[9:0]; + + /*ALU operation field*/ + /* + alu_op_md + 0000 - nop + 0001 - add + 0010 - sub + 0011 - or + 0100 - and + 0101 - not + 0110 - lsl + 0111 - lsr + 1000 - asr + 1001 - cmp + */ + //ALU Enable + assign alu_en_A_md = m_args[0]; + assign alu_en_B_md = m_args[8]; + + //ALU operation + assign alu_op_md = m_args[3:1]; + /*Determine if immediate bit is active*/ + assign is_imm_active_md = (minstr_type == 3'b001) || + (minstr_type == 3'b010) || + (minstr_type == 3'b011); + //Reg file enable and reg file read/write signal + assign reg_file_en_md = m_args[4]; + assign reg_file_rw_md = m_args[5]; + //Data memory enable read/write signal + // assign mem_en_md = m_args[6]; + // assign mem_rw_md = m_args[7]; + //Is branch signal + assign is_branch_md = (minstr_type == 3'b100) || (minstr_type == 3'b011); +endmodule \ No newline at end of file diff --git a/designs/d28_gvenkata_ucpu/src/defines.vh b/designs/d28_gvenkata_ucpu/src/defines.vh new file mode 100644 index 0000000..91181bf --- /dev/null +++ b/designs/d28_gvenkata_ucpu/src/defines.vh @@ -0,0 +1,75 @@ +/*CPU States*/ +`define CPU_STATES 10 +`define SEND_PC 4'd0 +`define FETCH 4'd1 +`define DECODE 4'd2 +`define SEND_MPC 4'd3 +`define FETCH_MINST 4'd4 +`define DECODE_MINST 4'd5 +`define EXECUTE1 4'd6 +`define EXECUTE2 4'd7 +`define SET_MAR 4'd8 +`define SET_MDR 4'd9 +//No. of micro registers +`define MREG_COUNT 'd18 +`define MREG_SPEC_WIDTH 'd5 +/*Micro-registers Mapping*/ +`define A_REG_MAP 5'd0 +`define B_REG_MAP 5'd1 +`define ALU_RESULT_MAP 5'd2 +`define CC_GREATER_MAP 5'd3 +`define CC_EQUAL_MAP 5'd4 +`define REG_SEL_MAP 5'd5 +`define REG_WR_DATA_MAP 5'd6 +`define REG_RD_DATA_MAP 5'd7 +`define IS_IMM_MAP 5'd8 +`define IMM_MAP 5'd9 +`define REG_SRC_MAP 5'd10 +`define REG_DST_MAP 5'd11 +`define MBRANCH_TARGET_MAP 5'd12 +`define M_PC_MAP 5'd13 +`define RS1_MAP 5'd14 +`define RS2_MAP 5'd15 +`define RD_MAP 5'd16 +`define BRANCH_TARGET_MAP 5'd17 +/*Register Widths*/ +`define INST_WIDTH 32 +//No of micro-instructions +`define MINST_COUNT 8 +//micro-instruction opcode width +`define MINST_TYPE_WIDTH 3 +//Micro-instruction width +`define MINST_WIDTH 44 +// +`define M_INST_ADDR_WIDTH 9 + + +//PC Register Width +`define PC_WIDTH 8 +//Micro-PC +`define MPC_WIDTH 8 +//Branch target +`define MBRANCH_ADDR_WIDTH 8 +//Immediate value +`define IMM_WIDTH 8 +//Shared write bus +`define WRITE_WIDTH 8 +// +`define ADDR_WIDTH 5 +// +`define DATA_WIDTH 8 +//Register file depth +`define REG_FILE_DEPTH 4 +`define DATA_WIDTH 8 +//log2(REG_FILE_DEPTH) +`define REG_SPEC_WIDTH 2 +`define REG_FILE_READ 1'b0 +`define REG_FILE_WRITE 1'b1 +//No of ALU operations +`define ALU_OPS 8 +//ALU width +`define ALU_WIDTH 8 +//parameter MEM_ADR 13 +//parameter MEM_DATA 14 +//parameter LD_DATA 15 +`define BUS_ARGS 10 \ No newline at end of file diff --git a/designs/d28_gvenkata_ucpu/src/inst_mem.sv b/designs/d28_gvenkata_ucpu/src/inst_mem.sv new file mode 100644 index 0000000..e398f07 --- /dev/null +++ b/designs/d28_gvenkata_ucpu/src/inst_mem.sv @@ -0,0 +1,227 @@ +`include "defines.vh" + +module inst_addr_serialise ( + sys_clk, + sys_reset, + cpu_state, + //Input instruction addr + inst_addr, + //Output micro-instruction stream + inst_addr_stream +); + + input sys_clk, sys_reset; + input [$clog2(`CPU_STATES)-1:0] cpu_state; + input [`PC_WIDTH-1:0] inst_addr; + output inst_addr_stream; + + reg [$clog2(`PC_WIDTH)-1:0] current_bit_index; + + assign inst_addr_stream = (sys_reset == 1'b1) ? 1'b0 : (( cpu_state == `SEND_PC ) ? inst_addr[current_bit_index] : 1'b0); + + always @(posedge sys_clk) begin + if(sys_reset) begin + current_bit_index <= (1<<$clog2(`PC_WIDTH)) -1; + end + else begin + //Begin sending the address bits in a serial fashion + if(cpu_state == `SEND_PC) begin + current_bit_index <= current_bit_index - 1'b1; + end + end + end +endmodule + +/* + Module accepts 32 bits of instruction serially + Order of bits: most significant bit first +*/ +module instr_reg_interface ( + sys_clk, + instr_in, + instr_reg, + sys_reset, + enable +); + input instr_in, sys_clk, sys_reset, enable; + output reg [`INST_WIDTH-1:0] instr_reg; + + always @(posedge sys_clk) begin + if(sys_reset == 1'b1) begin + instr_reg <= 32'b0; + end + else begin + if(enable) begin + instr_reg <= {instr_reg[30:0], instr_in}; + end + end + end +endmodule + +/* + Micro-instruction address generator +*/ +module m_inst_addr_gen #( + parameter M_INST_ADDR_WIDTH = 9, + parameter M_INST_START_ADDR = 0, + parameter INSTR_TYPE = 5 +) ( + instr_in, + m_inst_addr_base +); + input [`INST_WIDTH-1:0] instr_in; + output [M_INST_ADDR_WIDTH-1:0] m_inst_addr_base; + wire [INSTR_TYPE-1:0] instr_type; + reg [M_INST_ADDR_WIDTH-1:0] offset; + assign instr_type = instr_in[31:27]; + always @(*) begin + case (instr_type) + /*3 address format ALU instructions*/ + /*add, sub, and, or, lsl, lsr, asr*/ + 5'b00000: offset = 0; + 5'b00001: offset = 32; + 5'b00110: offset = 64; + 5'b00111: offset = 96; + 5'b01001: offset = 128; + 5'b01010: offset = 160; + 5'b01011: offset = 192; + 5'b01100: offset = 224; + /*2 address format ALU instructions*/ + /*cmp, not*/ + 5'b00101: offset = 256; + 5'b01000: offset = 288; + /*Branch - beq, bgt, b*/ + 5'b10000: offset = 320; + 5'b10001: offset = 352; + 5'b10010: offset = 384; + /*nop*/ + 5'b01101: offset = 416; + /*ld,st*/ + 5'b01110: offset = 448; + 5'b01111: offset = 480; + default: offset = 0; + endcase + end + assign m_inst_addr_base = offset; +endmodule + +/* + This module blindly sends out the address bits + to the output port on every clock edge when + 1. reset is off + 2. cpu_state == FETCH + + Order: MSb First +*/ + +module m_inst_addr_serialise #( + + parameter M_INST_ADDR_WIDTH = 9 +) ( + sys_clk, + sys_reset, + cpu_state, + //Input micro-instruction addr + m_inst_addr, + //Output micro-instruction stream + m_inst_addr_stream +); + + input sys_clk, sys_reset; + input [$clog2(`CPU_STATES)-1:0] cpu_state; + input [M_INST_ADDR_WIDTH-1:0] m_inst_addr; + output m_inst_addr_stream; + + reg [$clog2(M_INST_ADDR_WIDTH)-1:0] current_bit_index; + + assign m_inst_addr_stream = (sys_reset == 1'b1) ? 1'b0 : (( cpu_state == `SEND_MPC ) ? m_inst_addr[current_bit_index] : 1'b0); + + always @(posedge sys_clk) begin + if(sys_reset) begin + //m_inst_addr_stream <= 1'b0; + //TODO: parametrize + current_bit_index <= (M_INST_ADDR_WIDTH) - 1'b1; + // current_bit_index <= (1<<$clog2(M_INST_ADDR_WIDTH)) - 1'b1; + end + else begin + //Begin sending the address bits in a serial fashion + if(cpu_state == `SEND_MPC) begin + current_bit_index <= current_bit_index - 1'b1; + end + else begin + current_bit_index <= (M_INST_ADDR_WIDTH) - 1'b1; + end + end + end +endmodule + +module m_instr_reg ( + sys_clk, + minstr_in, + m_instr_reg, + sys_reset, + enable +); + input minstr_in, sys_clk, sys_reset, enable; + output reg [`MINST_WIDTH-1:0] m_instr_reg; + + always @(posedge sys_clk) begin + if(sys_reset == 1'b1) begin + //Hardcoded width + m_instr_reg <= 44'b0; + end + else begin + if(enable) begin + m_instr_reg <= {m_instr_reg[42:0], minstr_in}; + end + end + end +endmodule + +module m_pc_reg ( + sys_clk, + sys_reset, + load_m_pc_en, + next_m_pc, + m_pc +); + input sys_clk, sys_reset; + input load_m_pc_en; + input [`MPC_WIDTH-1:0] next_m_pc; + output reg [`MPC_WIDTH-1:0] m_pc; + always @(posedge sys_clk) begin + if(sys_reset == 1'b1) begin + //Hardcoded width + m_pc <= 8'b0; + end + else begin + if(load_m_pc_en) begin + m_pc <= next_m_pc; + end + end + end +endmodule + +module pc_reg ( + sys_clk, + sys_reset, + load_pc_en, + next_pc, + pc +); + input sys_clk, sys_reset; + input load_pc_en; + input [`PC_WIDTH-1:0] next_pc; + output reg [`PC_WIDTH-1:0] pc; + always @(posedge sys_clk) begin + if(sys_reset == 1'b1) begin + //Hardcoded width + pc <= 8'b0; + end + else begin + if(load_pc_en) begin + pc <= next_pc; + end + end + end +endmodule diff --git a/designs/d28_gvenkata_ucpu/src/mcpu.sv b/designs/d28_gvenkata_ucpu/src/mcpu.sv new file mode 100644 index 0000000..3295a7b --- /dev/null +++ b/designs/d28_gvenkata_ucpu/src/mcpu.sv @@ -0,0 +1,420 @@ +`include "defines.vh" + +module cpu_fsm( + sys_clk, + sys_reset, + cpu_state, + //pc, + //mpc, + is_nop, + is_micro_nop + ); + + /*Internal FSM counter to keep track of states*/ + input sys_clk, sys_reset; + input is_nop, is_micro_nop; + reg [5:0] fsm_assist; + reg [4:0] current_minst; + + output reg [$clog2(`CPU_STATES)-1:0] cpu_state; + + parameter M_INST_ADDR_WIDTH = 9; + + always @(posedge sys_clk) begin + if(sys_reset) begin + cpu_state <= `SEND_PC; + fsm_assist <= 6'b0; + current_minst <= 5'b0; + end + else begin + if(cpu_state == `SEND_PC) begin + if(fsm_assist == `PC_WIDTH-1) begin + cpu_state <= `FETCH; + fsm_assist <= 6'b0; + end + else begin + fsm_assist <= fsm_assist + 6'b1; + end + end + else if(cpu_state == `FETCH) begin + if(fsm_assist == `INST_WIDTH-1) begin + cpu_state <= `DECODE; + fsm_assist <= 6'b0; + end + else begin + fsm_assist <= fsm_assist + 6'b1; + end + end + else if(cpu_state == `DECODE) begin + if(is_nop) begin + cpu_state <= `FETCH; + end + else begin + cpu_state <= `SEND_MPC; + end + fsm_assist <= 6'b0; + end + else if(cpu_state == `SEND_MPC) begin + if(fsm_assist == M_INST_ADDR_WIDTH-1) begin + cpu_state <= `FETCH_MINST; + fsm_assist <= 6'b0; + end + else begin + fsm_assist <= fsm_assist + 6'b1; + end + end + else if(cpu_state == `FETCH_MINST) begin + if(fsm_assist == `MINST_WIDTH-1) begin + cpu_state <= `DECODE_MINST; + fsm_assist <= 6'b0; + end + else begin + fsm_assist <= fsm_assist + 6'b1; + end + end + else if(cpu_state == `DECODE_MINST) begin + if(is_micro_nop) begin + cpu_state <= `FETCH_MINST; + current_minst <= current_minst + 5'b1; + end + else begin + cpu_state <= `EXECUTE1; + end + end + else if(cpu_state == `EXECUTE1) begin + cpu_state <= `EXECUTE2; + end + else if(cpu_state == `EXECUTE2) begin + if(current_minst == 5'd31) begin + current_minst <= 5'b0; + cpu_state <= `FETCH; + end + else begin + current_minst <= current_minst + 5'b1; + cpu_state <= `SEND_MPC; + end + end + end + end +endmodule + + +module top_cpu( + sys_clk, + sys_reset, + instr_in, + m_instr_in, + inst_addr_stream, + m_inst_addr_stream + +); + input sys_clk, sys_reset; + //Instruction sequence + input instr_in; + //Micro-instruction sequence + input m_instr_in; + //Instruction address sequence + output inst_addr_stream; + //Micro-instruction address sequence + output m_inst_addr_stream; + + // Register to Track CPU FSM state + reg [$clog2(`CPU_STATES)-1:0] cpu_state; + + //Signal to track if current instruction/micro-instruction is a NOP + + wire is_current_inst_nop, is_current_micro_inst_nop; + assign is_current_inst_nop = 1'b0; + assign is_current_micro_inst_nop = 1'b0; + //Instantiate CPU FSM + cpu_fsm cpu_fsm_top( .sys_clk(sys_clk), + .sys_reset(sys_reset), + .cpu_state(cpu_state), + .is_nop(is_current_micro_inst_nop), + .is_micro_nop(is_current_micro_inst_nop) + ); + + /* + Instantiate PC register and associated signals + 1. load_pc_en - PC register load enable + 2. next_pc - Next PC value + 3. pc - Current PC value, registered + */ + wire load_pc_en; + wire [`PC_WIDTH-1:0] pc, next_pc; + assign load_pc_en = (cpu_state == `EXECUTE2 && cpu_fsm_top.current_minst == 5'd31) ? 1'b1 : 1'b0; + pc_reg pc_top(.sys_clk(sys_clk), .sys_reset(sys_reset), + .load_pc_en(load_pc_en), + .next_pc(next_pc), + .pc(pc)); + + /* + Instantiate instruction address serialiser + 1. cpu_state - Current CPU state + 2. pc - Current PC value, registered + */ + inst_addr_serialise inst_to_bit(.sys_clk(sys_clk), .sys_reset(sys_reset), + .cpu_state(cpu_state), + .inst_addr(pc), + .inst_addr_stream(inst_addr_stream)); + + /* + Instantiate Instruction register + 1. instr_in - Input instruction stream + 2. instr_reg - Current CPU instruction under execution + */ + wire [`INST_WIDTH-1:0] instr_reg; + wire instr_reg_en = (cpu_state == `FETCH) ? 1'b1: 1'b0; + instr_reg_interface instr_reg_top(.sys_clk(sys_clk), .sys_reset(sys_reset), + .instr_in(instr_in), + .instr_reg(instr_reg), + .enable(instr_reg_en) + ); + + /* + Instantiate Instruction decoder and declare related decode field signals + + */ + + wire [4:0] inst_type; + wire is_imm_active_id; + wire [3:0] reg_src_1_id, reg_src_2_id, reg_dst_id; + wire [7:0] imm_id; + wire [7:0] branch_target_id; + instruction_decoder ir_decode_top( + .instr_in(instr_reg), + .inst_type(inst_type), + .is_imm_active_id(is_imm_active_id), + .reg_dst_id(reg_dst_id), + .reg_src_1_id(reg_src_1_id), + .reg_src_2_id(reg_src_2_id), + .imm_id(imm_id), + .branch_target_id(branch_target_id) + ); + + //Micro-instruction sequence + /* + Instantiate address offset generator for microinstruction + 1. instr_reg - Instruction + 2. m_inst_addr_offset - offset for micro-instruction + */ + wire [`M_INST_ADDR_WIDTH-1:0] m_inst_addr_offset; + m_inst_addr_gen m_inst_addr_offset_gen(.instr_in(instr_reg), + .m_inst_addr_base(m_inst_addr_offset) + ); + + wire should_branch; + wire [`MBRANCH_ADDR_WIDTH-1:0] mbranch_target; + + + //Instantiate Instruction and micro-instruction register + + //Instantiate micro-PC register + /* + Instantiate PC register and associated signals + 1. load_m_pc_en - micro-PC register load enable + 2. next_m_pc - Next micro-PC value + 3. m_pc - Current micro-PC value, registered + */ + wire load_m_pc_en; + wire [`MPC_WIDTH-1:0] m_pc, next_m_pc; + assign load_m_pc_en = (cpu_state == `DECODE) ? 1'b1 : ((cpu_state == `EXECUTE1 && should_branch) ? 1'b1 : 1'b0); + assign next_m_pc = (cpu_state == `DECODE) ? {`MPC_WIDTH{1'b0}} : (cpu_state == `EXECUTE1 && should_branch) ? mbranch_target : m_pc + 8'b1; + m_pc_reg m_pc_top(.sys_clk(sys_clk), .sys_reset(sys_reset), .load_m_pc_en(load_m_pc_en), + .next_m_pc(next_m_pc), .m_pc(m_pc)); + wire [`M_INST_ADDR_WIDTH-1:0] mpc_offset; + assign mpc_offset = m_inst_addr_offset+m_pc; + //Instantiate micro-instruction address serialiser + m_inst_addr_serialise m_inst_to_bit(.sys_clk(sys_clk), .sys_reset(sys_reset), + .cpu_state(cpu_state), + .m_inst_addr(mpc_offset), + .m_inst_addr_stream(m_inst_addr_stream) + ); + /* + Instantiate Micro-Instruction register + 1. m_instr_in - Input micro-instruction stream + 2. minstr_reg - Current CPU micro-instruction under execution + */ + wire [`MINST_WIDTH-1:0] m_instr_reg; + wire m_instr_reg_en = (cpu_state == `FETCH_MINST) ? 1'b1: 1'b0; + m_instr_reg m_instr_reg_top(.sys_clk(sys_clk), .sys_reset(sys_reset), + .enable(m_instr_reg_en), + .minstr_in(m_instr_in), + .m_instr_reg(m_instr_reg) + ); + + /* + Micro-instruction decoder and associated signals + */ + + //Microinstruction source and destination register mapping + wire [`MREG_SPEC_WIDTH-1:0] reg_src_md, reg_dst_md; + //Immediate value + wire [`IMM_WIDTH-1:0] imm_md; + //Branch target value + wire [`MBRANCH_ADDR_WIDTH-1:0] mbranch_target_md; + + /*Output control signals*/ + wire alu_en_md; + wire [$clog2(`ALU_OPS)-1:0] alu_op_md; + wire is_imm_active_md; + wire reg_file_en_md, reg_file_rw_md; + //wire mem_en_md, mem_rw_md; + wire is_branch_md; + + /*Micro instruction type*/ + wire [`MINST_TYPE_WIDTH-1:0] minstr_type; + + micro_inst_decoder m_inst_decode_top( + .minstr_in(m_instr_reg), + .minstr_type(minstr_type), + .reg_src_md(reg_src_md), + .reg_dst_md(reg_dst_md), + .imm_md(imm_md), + .mbranch_target_md(mbranch_target_md), + .is_imm_active_md(is_imm_active_md), + .reg_file_en_md(reg_file_en_md), + .reg_file_rw_md(reg_file_rw_md), + .alu_en_A_md(alu_en_A_md), + .alu_en_B_md(alu_en_B_md), + .alu_op_md(alu_op_md), + //.mem_en_md(mem_en_md), + //.mem_rw_md(mem_rw_md), + .is_branch_md(is_branch_md) + ); + + wire [7:0] shared_write_bus; + + wire [`MREG_SPEC_WIDTH-1:0] reg_dst, reg_src; + wire [`IMM_WIDTH-1:0] imm; + // wire [`MBRANCH_ADDR_WIDTH-1:0] mbranch_target; + + /*Registered control signals*/ + wire is_imm_active; + + /*Registered args*/ + wire alu_en; + wire [$clog2(`ALU_OPS)-1:0] alu_op; + wire reg_file_en, reg_file_rw; + //wire wire mem_en, mem_rw; + wire is_branch; + + mdecode_reg mdecode_reg_top( + .sys_clk(sys_clk), .sys_reset(sys_reset), + /*Decode fields*/ + .is_imm_active_md(is_imm_active_md), + .reg_dst_md(reg_dst_md), + .reg_src_md(reg_src_md), + .imm_md(imm_md), + .mbranch_target_md(mbranch_target_md), + /*Flags*/ + .alu_en_A_md(alu_en_A_md), + .alu_en_B_md(alu_en_B_md), + .alu_op_md(alu_op_md), + .reg_file_en_md(reg_file_en_md), + .reg_file_rw_md(reg_file_rw_md), + .is_branch_md(is_branch_md), + /*Registered Decode fields*/ + .is_imm_active(is_imm_active), + .reg_dst(reg_dst), + .reg_src(reg_src), + .imm(imm), + .mbranch_target(mbranch_target), + /*Registered Flags*/ + .alu_en_A(alu_en_A), + .alu_en_B(alu_en_B), + .alu_op(alu_op), + .reg_file_en(reg_file_en), + .reg_file_rw(reg_file_rw), + .is_branch(is_branch) + ); + + + //Instantiate micro-branch detector + reg_src_dst_cmp reg_src_dst_cmp_branch( + .reg_dst(reg_dst), + .imm(imm), + .A(A_reg), + .B(B_Reg), + .cc_greater(cc_greater), + .cc_equal(cc_equal), + .alu_result(alu_result), + .is_imm_active(is_imm_active), + .should_branch(should_branch) + ); + + /* + ALU and associated signals - Reads from the shared write bus + */ + wire cc_greater, cc_equal; + wire [`ALU_WIDTH-1:0] alu_result; + wire [`ALU_WIDTH-1:0] A_reg, B_reg; + + //Instantiate alu unit + alu_unit_interface alu_top( + .sys_clk(sys_clk), .sys_reset(sys_reset), + .cpu_state(cpu_state), + .A_bus(shared_write_bus), + .B_bus(shared_write_bus), + .alu_en_A_reg(alu_en_A), + .alu_en_B_reg(alu_en_B), + .alu_op(alu_op), + .cc_greater(cc_greater), + .cc_equal(cc_equal), + .alu_result(alu_result), + .A_reg(A_reg), + .B_reg(B_reg) + ); + + + + //wire [`REG_SPEC_WIDTH-1:0] reg_sel; + //wire [`DATA_WIDTH-1:0] reg_wr_data; + wire [`DATA_WIDTH-1:0] reg_rd_data; + + + //Instantiate Register File + micro_reg_file reg_file_interface( + .sys_clk(sys_clk), .sys_reset(sys_reset), + .cpu_state(cpu_state), + .reg_file_en(reg_file_en), + .reg_file_rw(reg_file_rw), + .reg_dst(reg_dst_id), + .shared_write_bus(shared_write_bus), + .reg_rd_data(reg_rd_data) + ); + + + + write_bus shared_mcpu_bus( + .minstr_type(minstr_type), + //fields in IR + .rs1(reg_src_1_id), + .rs2(reg_src_2_id), + //source register + .reg_src(reg_src), + //destination register + .reg_dst(reg_dst), + //bus args + // .is_imm_active(is_imm_active), + // .reg_file_en(reg_file_en), + // .reg_file_rw(reg_file_rw), + // .alu_en_A(alu_en_A), + // .alu_en_B(alu_en_B), + // alu_op, + // is_branch, + .should_branch(should_branch), + //producer - micro-decode registers + .imm(imm), + .m_pc(m_pc), + .mbranch_target(mbranch_target), + //producer - ALU operations + .alu_result(alu_result), + .cc_greater(cc_greater), + .cc_equal(cc_equal), + //producer - register file + .reg_rd_data(reg_rd_data), + .write_bus_out(shared_write_bus) + ); + +endmodule diff --git a/designs/d28_gvenkata_ucpu/src/micro_reg.sv b/designs/d28_gvenkata_ucpu/src/micro_reg.sv new file mode 100644 index 0000000..1d39bc8 --- /dev/null +++ b/designs/d28_gvenkata_ucpu/src/micro_reg.sv @@ -0,0 +1,219 @@ +`include "defines.vh" +/* + Micro-instruction format: + _________________________________ + |43:41|40:36|35:31|30:20|19:10|9:0| + |_________________________________| +*/ + +module decode_reg ( + sys_clk, + sys_reset, + is_imm_active_id, + reg_dst_id, + reg_src_1_id, + reg_src_2_id, + imm_id, + branch_target_id, + is_imm_active, + reg_dst, + reg_src_1, + reg_src_2, + imm, + branch_target +); + + input sys_clk, sys_reset, is_imm_active_id; + input [3:0] reg_src_1_id, reg_src_2_id, reg_dst_id; + input [10:0] imm_id; + input [9:0] branch_target_id; + + output reg is_imm_active; + output reg [3:0] reg_src_1, reg_src_2, reg_dst; + output reg [10:0] imm; + output reg [9:0] branch_target; + + always @(posedge sys_clk) begin + if(sys_reset) begin + is_imm_active <= 1'b0; + reg_src_1 <= 0; + reg_src_2 <= 0; + reg_dst <= 0; + imm <= 0; + branch_target <= 0; + end + else begin + is_imm_active <= is_imm_active_id; + reg_src_1 <= reg_src_1_id; + reg_src_2 <= reg_src_2_id; + reg_dst <= reg_dst_id; + imm <= imm_id; + branch_target <= branch_target_id; + end + end + +endmodule + +module mdecode_reg ( + sys_clk, + sys_reset, + /*Decode fields*/ + is_imm_active_md, + reg_dst_md, + reg_src_md, + imm_md, + mbranch_target_md, + /*Flags*/ + alu_en_A_md, + alu_en_B_md, + alu_op_md, + reg_file_en_md, + reg_file_rw_md, + is_branch_md, + /*Registered Decode fields*/ + is_imm_active, + reg_src, + reg_dst, + imm, + mbranch_target, + + /*Registered Flags*/ + alu_en_A, + alu_en_B, + alu_op, + reg_file_en, + reg_file_rw, + is_branch +); + /*Fields from decoder unit*/ + input sys_clk, sys_reset; + input [`MREG_SPEC_WIDTH-1:0] reg_src_md, reg_dst_md; + input [`IMM_WIDTH-1:0] imm_md; + input [`MBRANCH_ADDR_WIDTH-1:0] mbranch_target_md; + /*Control signals and bus args*/ + input is_imm_active_md; + input alu_en_A_md, alu_en_B_md; + input [$clog2(`ALU_OPS)-1:0] alu_op_md; + input reg_file_en_md, reg_file_rw_md; + input is_branch_md; + + /*Declare registers*/ + output reg [`MREG_SPEC_WIDTH-1:0] reg_src, reg_dst; + output reg [`IMM_WIDTH-1:0] imm; + output reg [`MBRANCH_ADDR_WIDTH-1:0] mbranch_target; + + /*Registered control signals*/ + output reg is_imm_active; + + /*Registered args*/ + output reg alu_en_A, alu_en_B; + output reg [$clog2(`ALU_OPS)-1:0] alu_op; + output reg reg_file_en, reg_file_rw; + //output wire mem_en, mem_rw; + output reg is_branch; + + /*Register all fields, control signals and args*/ + /*Yet to implement sys_reset*/ + always @(posedge sys_clk) begin + if(sys_reset) begin + reg_src <= 0; + reg_dst <= 0; + imm <= 0; + mbranch_target <= 0; + is_imm_active <= 0; + alu_en_A <= 0; + alu_en_B <= 0; + alu_op <= 0; + reg_file_en <= 0; + reg_file_rw <= 0; + is_branch <= 0; + end + else begin + reg_src <= reg_src_md; + reg_dst <= reg_dst_md; + imm <= imm_md; + mbranch_target <= mbranch_target_md; + is_imm_active <= is_imm_active_md; + alu_en_A <= alu_en_A_md; + alu_en_B <= alu_en_B_md; + alu_op <= alu_op_md; + reg_file_en <= reg_file_en_md; + reg_file_rw <= reg_file_rw_md; + is_branch <= is_branch_md; + end + end + +endmodule + +module micro_reg_file ( + //sys clk + input sys_clk, + //System reset + input sys_reset, + //cpu_state + input [$clog2(`CPU_STATES)-1:0] cpu_state, + /* Register file enable signal */ + input reg_file_en, + /* Register file R/W signal */ + input reg_file_rw, + /* Register destination signal - either REG_SEL or REG_WR_DATA */ + input [3:0] reg_dst, + /* Shared write bus data*/ + input [`DATA_WIDTH-1:0] shared_write_bus, + /* Reg file register select */ + //input [`REG_SPEC_WIDTH-1:0] reg_dst, + /* Reg file register write value */ + //input [`DATA_WIDTH-1:0] reg_wr_data, + /* Reg file register read value */ + output [`DATA_WIDTH-1:0] reg_rd_data +); + + /*Registered reg file addr select*/ + reg [`REG_SPEC_WIDTH-1:0] reg_sel_in; + + /*Registered reg file write data*/ + reg [`DATA_WIDTH-1:0] reg_wr_data_in; + + /*Registered reg file read data*/ + reg [`DATA_WIDTH-1:0] reg_rd_data_out; + + /*Declare register file*/ + reg [`DATA_WIDTH-1:0] mreg_file[`REG_FILE_DEPTH-1:0]; + + /*reg_rd_data output*/ + assign reg_rd_data = reg_rd_data_out; + + /*Register file writes are synchronous*/ + always @(posedge sys_clk) begin + if(sys_reset) begin + reg_sel_in <= {`REG_SPEC_WIDTH{1'b0}}; + reg_wr_data_in <= {`DATA_WIDTH{1'b0}}; + reg_rd_data_out <= {`DATA_WIDTH{1'b0}}; + end + else begin + if(reg_file_en) begin + if(cpu_state == `EXECUTE1) begin + if (reg_dst == `REG_SEL_MAP) begin + reg_sel_in <= shared_write_bus[`REG_SPEC_WIDTH-1:0]; + end + if (reg_dst == `REG_WR_DATA_MAP) begin + reg_wr_data_in <= shared_write_bus; + end + /* + if(reg_file_rw == `REG_FILE_WRITE) begin + reg_wr_data_in <= reg_wr_data; + end + */ + end + else if(cpu_state == `EXECUTE2) begin + if(reg_file_rw == `REG_FILE_READ) begin + reg_rd_data_out <= mreg_file[reg_sel_in]; + end + else if(reg_file_rw == `REG_FILE_WRITE) begin + mreg_file[reg_sel_in] <= reg_wr_data_in; + end + end + end + end + end +endmodule \ No newline at end of file diff --git a/designs/d28_gvenkata_ucpu/src/pin_order.cfg b/designs/d28_gvenkata_ucpu/src/pin_order.cfg new file mode 100644 index 0000000..0b85c63 --- /dev/null +++ b/designs/d28_gvenkata_ucpu/src/pin_order.cfg @@ -0,0 +1,9 @@ +#N + +#S + +#E + +#W +io_in.* +io_out.* diff --git a/designs/d28_gvenkata_ucpu/src/shared_bus.sv b/designs/d28_gvenkata_ucpu/src/shared_bus.sv new file mode 100644 index 0000000..b79217a --- /dev/null +++ b/designs/d28_gvenkata_ucpu/src/shared_bus.sv @@ -0,0 +1,245 @@ +`include "defines.vh" + +module reg_src_dst_cmp( + reg_dst, + imm, + A, + B, + cc_greater, + cc_equal, + alu_result, + is_imm_active, + + should_branch +); + input [`ADDR_WIDTH-1:0] reg_dst; + input [`IMM_WIDTH-1:0] imm; + input [`DATA_WIDTH-1:0] A, B; + input cc_greater, cc_equal; + input [`DATA_WIDTH-1:0] alu_result; + input is_imm_active; + output should_branch; + reg [`DATA_WIDTH-1:0] reg_dst_content; + + always_comb begin + if(reg_dst == `CC_GREATER_MAP) begin + reg_dst_content = {7'b0, cc_greater}; + end + else if(reg_dst == `CC_EQUAL_MAP) begin + reg_dst_content = {7'b0, cc_equal}; + end + else if(reg_dst == `A_REG_MAP) begin + reg_dst_content = A; + end + else if(reg_dst == `B_REG_MAP) begin + reg_dst_content = B; + end + else if(reg_dst == `ALU_RESULT_MAP) begin + reg_dst_content = alu_result; + end + else if(reg_dst == `IS_IMM_MAP) begin + reg_dst_content = {7'b0, is_imm_active}; + end + else begin + reg_dst_content = 8'b0; + end + end + + assign should_branch = (reg_dst_content == imm) ? 1'b1 : 1'b0; + +endmodule + +module write_bus ( + minstr_type, + //fields in IR + rs1, + rs2, + //source register + reg_src, + //destination register + reg_dst, + //bus args + // is_imm_active, + // reg_file_en, + // reg_file_rw, + // alu_en, + // alu_op, + // is_branch, + should_branch, + //producer - micro-decode registers + imm, + m_pc, + mbranch_target, + //producer - ALU operations + alu_result, + cc_greater, + cc_equal, + //producer - register file + reg_rd_data, + write_bus_out +); + + localparam MINST_TYPE_WIDTH = $clog2(`MINST_COUNT); + parameter BRANCH_ADDR_WIDTH = 8; + + input [`ADDR_WIDTH-1:0] reg_src, reg_dst; + input [$clog2(`REG_FILE_DEPTH)-1:0] rs1, rs2; + input [`ALU_WIDTH-1:0] alu_result; + input [MINST_TYPE_WIDTH-1:0] minstr_type; + input [`DATA_WIDTH-1:0] reg_rd_data; + //bus args + // input logic is_imm_active, reg_file_en, reg_file_rw, alu_en, is_branch, should_branch; + input should_branch; + + //input logic [$clog2(`ALU_OPS)-1:0] alu_op; + + //Other registers + input cc_greater, cc_equal; + + //producer - micro-decode registers + input [`MPC_WIDTH-1:0] m_pc; + input [`IMM_WIDTH-1:0] imm; + input [BRANCH_ADDR_WIDTH-1:0] mbranch_target; + + /* + Micro Registers which are producers + - m_pc + - imm + - mbranch_target + + Data path registers which are producers + - alu_result + - reg_rd_data + - cc_greater + - cc_equal + - ld_data (to be implemented) + */ + + output reg [`WRITE_WIDTH-1:0] write_bus_out; + + always_comb begin + //Fetching RS1 or RS2 from the register file + if(minstr_type == 3'b011 ) begin + write_bus_out = (should_branch == 1'b1) ? mbranch_target: m_pc; + end + else if (minstr_type == 3'b100) begin + write_bus_out = mbranch_target; + end + else begin + if(reg_src == `RS1_MAP) begin + write_bus_out = rs1; + end + else if(reg_src == `RS2_MAP) begin + write_bus_out = rs2; + end + //Immediate value register + else if(reg_src == `IMM_MAP) begin + write_bus_out = imm; + end + //Return instruction + else if(reg_src == `M_PC_MAP) begin + write_bus_out = m_pc; + end + //Branch instruction + else if(reg_src == `BRANCH_TARGET_MAP) begin + write_bus_out = mbranch_target; + end + //Result of ALU operation + else if(reg_src == `ALU_RESULT_MAP) begin + write_bus_out = alu_result; + end + //Value from Register file + else if(reg_src == `REG_RD_DATA_MAP) begin + write_bus_out = reg_rd_data; + end + else begin + write_bus_out = 8'b0; + end + end + + end + +endmodule + +/* +module read_bus #( + `A_REG_MAP = 0, + `B_REG_MAP = 1, + `REG_SEL_MAP = 5, + `REG_WR_DATA_MAP = 6, + `REG_SRC_MAP = 9, + `REG_DST_MAP = 10, + `M_PC_MAP = 12, + `RS1_MAP = 13, + `RS2_MAP = 14, + `RD_MAP = 15, + //widths + `BRANCH_ADDR_WIDTH = 10, + `IMM_WIDTH = 11, + `WRITE_WIDTH = 8, + `MINST_COUNT = 8, + `ADDR_WIDTH = 5, + `ALU_WIDTH = 8, + //No of ALU operations + `ALU_OPS = 8 + //`MEM_ADR = 13, + //`MEM_DATA = 14, + //`LD_DATA = 15 +) ( + sys_clk, + //Shared Write bus + write_bus, + // Shared read bus + //instruction type + minstr_type, + //ALU operand 1 and 2 + a_reg, + b_reg, + //Micro-Reg file select register + reg_sel, + //Micro-reg file write data register + reg_wr_data, + //source register + reg_src, + //destination register + reg_dst, + //bus args + is_imm_active, + reg_file_en, + reg_file_rw, + alu_en, + alu_op, + is_branch, + //consumer - micro-decode registers + imm, + m_pc, + + // + read_bus +); + + input + + always_comb begin + if(reg_dst == A_REG_MAP) begin + read_bus = alu_en ? write_bus : 8'b0; + end + else if(reg_dst == B_REG_MAP) begin + read_bus = alu_en ? write_bus : 8'b0; + end + else if(reg_dst == REG_SEL_MAP) begin + read_bus = reg_file_en ? write_bus : 8'b0; + end + else if(reg_dst == REG_WR_DATA_MAP) begin + read_bus = (reg_file_en && reg_file_rw) ? write_bus : 8'b0; + end + else if(reg_dst == M_PC_MAP) begin + read_bus = (is_branch) ? write_bus : 8'b0; + end + else begin + read_bus = 8'b0; + end + end + +endmodule +*/ \ No newline at end of file diff --git a/designs/d28_gvenkata_ucpu/src/toplevel_chip.v b/designs/d28_gvenkata_ucpu/src/toplevel_chip.v new file mode 100644 index 0000000..a82b427 --- /dev/null +++ b/designs/d28_gvenkata_ucpu/src/toplevel_chip.v @@ -0,0 +1,18 @@ +`default_nettype none + +// DO NOT EDIT THIS FILE +module toplevel_chip ( + input [13:0] io_in, + output [13:0] io_out +); + + my_chip mchip ( + .io_in(io_in[11:0]), + .io_out(io_out[11:0]), + .clock(io_in[12]), + .reset(io_in[13]) + ); + + assign io_out[13:12] = 2'b00; + +endmodule diff --git a/designs/d29_bwilhelm_i8008/.lastupdated b/designs/d29_bwilhelm_i8008/.lastupdated new file mode 100644 index 0000000..4d7b8c3 --- /dev/null +++ b/designs/d29_bwilhelm_i8008/.lastupdated @@ -0,0 +1 @@ +2023-05-14 diff --git a/designs/d29_bwilhelm_i8008/LICENSE b/designs/d29_bwilhelm_i8008/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/designs/d29_bwilhelm_i8008/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/designs/d29_bwilhelm_i8008/README.md b/designs/d29_bwilhelm_i8008/README.md new file mode 100644 index 0000000..0556ecb --- /dev/null +++ b/designs/d29_bwilhelm_i8008/README.md @@ -0,0 +1,136 @@ +# Intel 8008-like Chip +Brendan Wilhelm +18-224/624 Spring 2023 Final Tapeout Project + +## Overview +![](docs/Block_diagram2.png) +This project implements the Intel 8008 instruction set and microarchitecture +as specified in the User Manual. It uses an accumulator register for any +operations carried out, and possesses a register file, program stack, +and no on-chip memory. Each cycle the instruction or data is passed into +the chip, where it may then take up to 15 states to execute. + +## How it Works +The 8008 uses an FSM which moves through up to 3 memory read/write cycles +per instruction. Each memory cycle consists of up to 5 stages. T1/T1I and T2 +output the lower 8 bits, and upper 6 bits of the memory address and two bits +of the data access type, respectively. WAIT occurs until the READY signal +propogates (takes 2 cycles), and then the 8 Data_in bits are written into +the instruction register (CYCLE1), or read into the register file or stack. +If it's a HALT instruction, it will move to the STOPPED state. Other +instructions may move to the T4 and T5 states for data movement and ALU ops, +and they may behave differently on different cycles. There is a python simulator +which can be used to input custom instruction streams. +The 8008 has 7 data registers, with the 0th being the accumulator, and 5th and 6th +used for Low and High bits of data memory accesses. The stack has 8 registers +with 14-bit width which can be pushed or popped with CAL and RET. Look over +the attached manual (docs/8008UM.pdf) for more instructions, and the test bench +for how to input them. +![](docs/Internal_state_diagram.png) +Here is the diagram describing the internal state and transitions based off of +the current instruction. A simplified diagram can be found at docs/State_diagram.png. + +## Inputs/Outputs +![](docs/Pin_config.png) + +(This is the original 8008 pin config, but similar to what the 8008-like uses) + + inputs: + + - Data_in: + + 8 bits (Pins 7:0) of data with 0 being the smallest bit + + - INTR: + + Interrupt (Pin 8) used to exit STOPPED state + + - READY: + + Data ready (Pin 9) used to exit the WAIT state and input the byte to the internal bus + + - Pins 10 and 11 unused + + outputs: + + - Data_out: + + 8 bits (Pins 7:0) of data with 0 being the smallest bit + + - State: + + Outputs encoding of the processor FSM state (Pins 10:8) (T1 = 3'b010, T1I = 3'b110, T2 = 3'b100, WAIT = 3'b000, T3 = 3'b001, STOPPED = 3'b011, T4 = 3'b111, T5 = 3'b101) + + - Sync: + + Indicates if there is data on the Data_out pins (Pin 11) + +## Hardware Peripherals +The only necessary peripheral is something to simulate memory for the +processor. I plan to use a raspberry pi since the test bench is +written in python and should be easily modified for actual use. + +## Design Testing / Bringup +To test the design, I recommend looking at the tests directory. For a quick +summary, I recommend pushing rst high while cycling the clock a couple times. +Then it will output address 14'd0, and expect an instruction to be fed into +the D_in pins along with the READY signal high. You can pull READY low after +just one cycle, but leave the instruction on the input pins until the +processor enters state T3. Monitor the state output pins, because every +time you see T1/T1I and T2, this is the next memory address to be +written to or read from depending on the upper two bits in T2. I +recommend looking at the example programs or User Manual for what +instructions to input on a sample case. + +![](docs/Successful_tb.png) +A successful test bench output will look something like this. + +The clock speed is arbitrary, as long as there is time for instructions to +propogate in every state. To test the project, you can look at the example +tests in the tests/i8008_tb.py file. Or, you can run the existing tests by +running "make" in the tests directory. Every cycle is simulated by the python +simulator as the design executes, so you can update the python simulation, +and then call the check_state function to ensure it is in line with the +python simulation. I'm still working on a test bench for the final chip, +but it will involve running a script very similar to the i8008_tb.py file +since this handles memory management, and processor state casing already. + +If you want to make changes to the system verilog, then you can update +the verilog implementation by running the build.sh script. + +To aid with debugging, you can enable state printing for both the python +and verilog implementations by setting verbose = True in the failing +testcase. + + +## Unimplemented 8008 Features +I don't believe that the interrupt feature behaves quite right. +Unfortunately I didn't have time to fix the interrupt functionality. +Currently its only use is to exit from a halt instruction, which +puts the processor in the STOPPED state indefinitely. + +Due to concerns over signals stabilizing, the READY and INTR signals +take two cycles to propagate into the processor. This should give +enough time for these signals and the D_in value to stabilize +before being read. + +## Final Comments +The 8008 FSM can be confusing when you first look at it. I recommend +looking through the internal state transition diagram, and reading +through the part of the User Manual which details specific execution +of all the instruction types by cycle and state. Another good tool +is the python model I created to test bench the verilog, and as far +as I can tell it executes exactly the same as the verilog, but only +updates the state after each instruction instead of going through the +whole FSM logic in multiple cycles. + +For the tapeout and synthesis I used sv2v to convert the system verilog +to verilog since yosys had trouble with some of the system verilog I +was using. Because of that I've included both the system verilog and +verilog files in case there were any differences which I didn't catch. +This also made debugging a pain since I couldn't use any of the defines +that I had built up during the creation of the processor. + +Again due to time constraints I was not able to test every possible +instruction, but I've verified enough of them that you should be +able to write some programs like in the testbench. diff --git a/designs/d29_bwilhelm_i8008/build.sh b/designs/d29_bwilhelm_i8008/build.sh new file mode 100644 index 0000000..e88c52b --- /dev/null +++ b/designs/d29_bwilhelm_i8008/build.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +# Create verilog representations of system verilog +sv2v $(pwd)/original_sv/i8008_isa.vh $(pwd)/original_sv/internal_defines.vh $(pwd)/original_sv/i8008_core.sv > $(pwd)/src/i8008_core.v \ No newline at end of file diff --git a/designs/d29_bwilhelm_i8008/chip_test.sh b/designs/d29_bwilhelm_i8008/chip_test.sh new file mode 100644 index 0000000..f2f2704 --- /dev/null +++ b/designs/d29_bwilhelm_i8008/chip_test.sh @@ -0,0 +1,28 @@ +#!/bin/sh + +# Delete the old build folder +rm -r build + +# Make a build folder +mkdir build + +# Create verilog representations of system verilog +sv2v $(pwd)/original_sv/hex_to_sevenseg.sv $(pwd)/original_sv/debugbus.sv $(pwd)/original_sv/i8008_isa.vh $(pwd)/original_sv/internal_defines.vh $(pwd)/original_sv/i8008_core.sv > $(pwd)/src/i8008_core.v + +# Synthesis (can add more SV files, space-separated, if desired) +yosys -p 'read_verilog -sv src/i8008_core.v; synth_ice40 -json build/synthesis.json -top top' > output.txt + +# Place-and-route +nextpnr-ice40 --hx8k --json build/synthesis.json --asc build/pnr.asc --package cb132 --pcf constraints.pcf --freq 32 + +# Compress the bitstream +icepack build/pnr.asc build/bitstream.bit + +# Load the bitstream +iceprog build/bitstream.bit + +# move to the test directory +cd $(pwd)/tests + +# run the tests +make \ No newline at end of file diff --git a/designs/d29_bwilhelm_i8008/constraints.pcf b/designs/d29_bwilhelm_i8008/constraints.pcf new file mode 100644 index 0000000..9333215 --- /dev/null +++ b/designs/d29_bwilhelm_i8008/constraints.pcf @@ -0,0 +1,84 @@ +set_io clk100 P7 +set_io reset_n P8 + +set_io base_led[0] J11 +set_io base_led[1] K11 +set_io base_led[2] K12 +set_io base_led[3] K14 +set_io base_led[4] L12 +set_io base_led[5] L14 +set_io base_led[6] M12 +set_io base_led[7] N14 + +set_io uart_rx P14 +set_io uart_tx M9 + +set_io led[0] G14 +set_io led[1] F14 +set_io led[2] E12 +set_io led[3] E14 +set_io led[4] D14 +set_io led[5] C14 +set_io led[6] B14 +set_io led[7] A12 +set_io led[8] C10 +set_io led[9] C9 +set_io led[10] A11 +set_io led[11] A10 +set_io led[12] A7 +set_io led[13] A6 +set_io led[14] A4 +set_io led[15] A3 +set_io led[16] A2 +set_io led[17] A1 +set_io led[18] C3 +set_io led[19] D3 +set_io led[20] B1 +set_io led[21] C1 +set_io led[22] D1 +set_io led[23] E1 + +set_io sw[0] G12 +set_io sw[1] F12 +set_io sw[2] F11 +set_io sw[3] E11 +set_io sw[4] D12 +set_io sw[5] D11 +set_io sw[6] C12 +set_io sw[7] C11 +set_io sw[8] D10 +set_io sw[9] D9 +set_io sw[10] D7 +set_io sw[11] D6 +set_io sw[12] C7 +set_io sw[13] C6 +set_io sw[14] A5 +set_io sw[15] C5 +set_io sw[16] D5 +set_io sw[17] C4 +set_io sw[18] D4 +set_io sw[19] E4 +set_io sw[20] F4 +set_io sw[21] F3 +set_io sw[22] H4 +set_io sw[23] G4 + +set_io btn[0] G11 +set_io btn[1] H11 +set_io btn[2] H12 +set_io btn[3] J12 +set_io btn[4] P2 + +set_io display_sel[0] G3 +set_io display_sel[1] G1 +set_io display_sel[2] H1 +set_io display_sel[3] H3 + +set_io display[0] J1 +set_io display[1] J3 +set_io display[2] N1 +set_io display[3] K4 +set_io display[4] K3 +set_io display[5] L1 +set_io display[6] M1 +set_io display[7] P1 diff --git a/designs/d29_bwilhelm_i8008/docs/8008UM.pdf b/designs/d29_bwilhelm_i8008/docs/8008UM.pdf new file mode 100644 index 0000000..4f01990 Binary files /dev/null and b/designs/d29_bwilhelm_i8008/docs/8008UM.pdf differ diff --git a/designs/d29_bwilhelm_i8008/docs/8008_model.png b/designs/d29_bwilhelm_i8008/docs/8008_model.png new file mode 100644 index 0000000..4b7eb21 Binary files /dev/null and b/designs/d29_bwilhelm_i8008/docs/8008_model.png differ diff --git a/designs/d29_bwilhelm_i8008/docs/Block_diagram1.png b/designs/d29_bwilhelm_i8008/docs/Block_diagram1.png new file mode 100644 index 0000000..521d980 Binary files /dev/null and b/designs/d29_bwilhelm_i8008/docs/Block_diagram1.png differ diff --git a/designs/d29_bwilhelm_i8008/docs/Block_diagram2.png b/designs/d29_bwilhelm_i8008/docs/Block_diagram2.png new file mode 100644 index 0000000..2f6dfaf Binary files /dev/null and b/designs/d29_bwilhelm_i8008/docs/Block_diagram2.png differ diff --git a/designs/d29_bwilhelm_i8008/docs/Block_diagram_simple.png b/designs/d29_bwilhelm_i8008/docs/Block_diagram_simple.png new file mode 100644 index 0000000..e2c992f Binary files /dev/null and b/designs/d29_bwilhelm_i8008/docs/Block_diagram_simple.png differ diff --git a/designs/d29_bwilhelm_i8008/docs/Internal_state_desc.png b/designs/d29_bwilhelm_i8008/docs/Internal_state_desc.png new file mode 100644 index 0000000..2d31697 Binary files /dev/null and b/designs/d29_bwilhelm_i8008/docs/Internal_state_desc.png differ diff --git a/designs/d29_bwilhelm_i8008/docs/Internal_state_diagram.png b/designs/d29_bwilhelm_i8008/docs/Internal_state_diagram.png new file mode 100644 index 0000000..6075c2e Binary files /dev/null and b/designs/d29_bwilhelm_i8008/docs/Internal_state_diagram.png differ diff --git a/designs/d29_bwilhelm_i8008/docs/Microcomputer_Design.pdf b/designs/d29_bwilhelm_i8008/docs/Microcomputer_Design.pdf new file mode 100644 index 0000000..57b50b7 Binary files /dev/null and b/designs/d29_bwilhelm_i8008/docs/Microcomputer_Design.pdf differ diff --git a/designs/d29_bwilhelm_i8008/docs/Pin_config.png b/designs/d29_bwilhelm_i8008/docs/Pin_config.png new file mode 100644 index 0000000..9e2381a Binary files /dev/null and b/designs/d29_bwilhelm_i8008/docs/Pin_config.png differ diff --git a/designs/d29_bwilhelm_i8008/docs/State_diagram.png b/designs/d29_bwilhelm_i8008/docs/State_diagram.png new file mode 100644 index 0000000..419fcc1 Binary files /dev/null and b/designs/d29_bwilhelm_i8008/docs/State_diagram.png differ diff --git a/designs/d29_bwilhelm_i8008/docs/State_encoding.png b/designs/d29_bwilhelm_i8008/docs/State_encoding.png new file mode 100644 index 0000000..cf3d696 Binary files /dev/null and b/designs/d29_bwilhelm_i8008/docs/State_encoding.png differ diff --git a/designs/d29_bwilhelm_i8008/docs/Successful_tb.png b/designs/d29_bwilhelm_i8008/docs/Successful_tb.png new file mode 100644 index 0000000..3667123 Binary files /dev/null and b/designs/d29_bwilhelm_i8008/docs/Successful_tb.png differ diff --git a/designs/d29_bwilhelm_i8008/info.yaml b/designs/d29_bwilhelm_i8008/info.yaml new file mode 100644 index 0000000..48b01e2 --- /dev/null +++ b/designs/d29_bwilhelm_i8008/info.yaml @@ -0,0 +1,8 @@ +--- +project: + source_files: + - i8008_core.v + - toplevel_chip.v + - chip.sv + - decoder.v + top_module: "toplevel_chip" diff --git a/designs/d29_bwilhelm_i8008/original_sv/debugbus.sv b/designs/d29_bwilhelm_i8008/original_sv/debugbus.sv new file mode 100644 index 0000000..c9f1f51 --- /dev/null +++ b/designs/d29_bwilhelm_i8008/original_sv/debugbus.sv @@ -0,0 +1,1924 @@ +/* Generated by Yosys 0.25+83 (git sha1 755b753e1, aarch64-apple-darwin20.2-clang 10.0.0-4ubuntu1 -fPIC -Os) */ + +module debug_harness(uart_rx, uart_tx, chip_inputs, chip_outputs, chip_clock, chip_reset, clk100); + wire _0000_; + wire [11:0] _0001_; + wire _0002_; + wire [31:0] _0003_; + wire [2:0] _0004_; + wire _0005_; + wire [31:0] _0006_; + wire [31:0] _0007_; + wire [31:0] _0008_; + wire [31:0] _0009_; + wire [31:0] _0010_; + wire [31:0] _0011_; + wire [35:0] _0012_; + wire _0013_; + wire [35:0] _0014_; + wire _0015_; + wire _0016_; + wire _0017_; + wire [25:0] _0018_; + wire _0019_; + wire _0020_; + wire _0021_; + wire _0022_; + wire _0023_; + wire _0024_; + wire _0025_; + wire _0026_; + wire [39:0] _0027_; + wire [2:0] _0028_; + wire _0029_; + wire [35:0] _0030_; + wire _0031_; + wire [39:0] _0032_; + wire [2:0] _0033_; + wire [7:0] _0034_; + wire _0035_; + wire _0036_; + wire [35:0] _0037_; + wire _0038_; + wire _0039_; + wire _0040_; + wire [25:0] _0041_; + wire _0042_; + wire _0043_; + wire _0044_; + wire _0045_; + wire _0046_; + wire _0047_; + wire _0048_; + wire _0049_; + wire [39:0] _0050_; + wire [2:0] _0051_; + wire _0052_; + wire [35:0] _0053_; + wire _0054_; + wire [39:0] _0055_; + wire [2:0] _0056_; + wire _0057_; + wire [31:0] _0058_; + wire [31:0] _0059_; + wire _0060_; + wire _0061_; + wire _0062_; + wire _0063_; + wire _0064_; + wire _0065_; + wire _0066_; + wire _0067_; + wire _0068_; + wire _0069_; + wire _0070_; + wire _0071_; + wire _0072_; + wire _0073_; + wire _0074_; + wire _0075_; + wire _0076_; + wire _0077_; + wire _0078_; + wire _0079_; + wire _0080_; + wire _0081_; + wire _0082_; + wire _0083_; + wire _0084_; + wire _0085_; + wire _0086_; + wire _0087_; + wire _0088_; + wire _0089_; + wire _0090_; + wire _0091_; + wire _0092_; + wire _0093_; + wire _0094_; + wire _0095_; + wire _0096_; + wire _0097_; + wire _0098_; + wire _0099_; + wire _0100_; + wire _0101_; + wire _0102_; + wire _0103_; + wire _0104_; + wire _0105_; + wire _0106_; + wire [31:0] _0107_; + wire [3:0] _0108_; + wire [35:0] _0109_; + wire [35:0] _0110_; + wire [4:0] _0111_; + wire [35:0] _0112_; + wire _0113_; + wire [3:0] _0114_; + wire [3:0] _0115_; + wire [3:0] _0116_; + wire [35:0] _0117_; + wire [35:0] _0118_; + wire [4:0] _0119_; + wire _0120_; + wire [3:0] _0121_; + wire [3:0] _0122_; + wire [3:0] _0123_; + wire [35:0] _0124_; + wire [35:0] _0125_; + wire [31:0] _0126_; + wire [31:0] _0127_; + wire [31:0] _0128_; + wire _0129_; + wire _0130_; + wire _0131_; + wire _0132_; + wire _0133_; + wire _0134_; + wire [35:0] _0135_; + reg [3:0] _0136_; + reg [35:0] _0137_; + reg [35:0] _0138_; + wire _0139_; + wire _0140_; + wire _0141_; + wire _0142_; + wire _0143_; + wire [31:0] _0144_; + wire [3:0] _0145_; + wire [35:0] _0146_; + wire [35:0] _0147_; + wire [4:0] _0148_; + wire [35:0] _0149_; + wire _0150_; + wire [3:0] _0151_; + wire [3:0] _0152_; + wire [3:0] _0153_; + wire [35:0] _0154_; + wire [35:0] _0155_; + wire [4:0] _0156_; + wire _0157_; + wire [3:0] _0158_; + wire [3:0] _0159_; + wire [3:0] _0160_; + wire [35:0] _0161_; + wire [35:0] _0162_; + wire [31:0] _0163_; + wire [31:0] _0164_; + wire [31:0] _0165_; + wire _0166_; + wire _0167_; + wire _0168_; + wire _0169_; + wire _0170_; + wire _0171_; + wire [35:0] _0172_; + reg [3:0] _0173_; + reg [35:0] _0174_; + reg [35:0] _0175_; + wire _0176_; + wire _0177_; + wire _0178_; + wire _0179_; + wire _0180_; + wire [31:0] _0181_; + wire [7:0] _0182_; + wire [7:0] _0183_; + wire [31:0] _0184_; + wire [7:0] _0185_; + wire [9:0] _0186_; + wire [7:0] _0187_; + wire _0188_; + wire [3:0] _0189_; + wire [7:0] _0190_; + wire [7:0] _0191_; + wire [31:0] _0192_; + wire [7:0] _0193_; + wire [3:0] _0194_; + wire [7:0] _0195_; + wire [7:0] _0196_; + wire [31:0] _0197_; + wire [7:0] _0198_; + wire [7:0] _0199_; + wire [7:0] _0200_; + wire [31:0] _0201_; + wire [7:0] _0202_; + wire [31:0] _0203_; + wire [7:0] _0204_; + wire [7:0] _0205_; + reg [7:0] _0206_; + reg [7:0] _0207_; + reg [31:0] _0208_; + wire _0209_; + wire _0210_; + wire _0211_; + wire _0212_; + wire _0213_; + reg [7:0] _0214_; + wire [32:0] _0215_; + wire [32:0] _0216_; + wire [7:0] _0217_; + wire [7:0] _0218_; + wire [7:0] _0219_; + wire [7:0] _0220_; + wire [32:0] _0221_; + wire [32:0] _0222_; + wire [31:0] _0223_; + wire [31:0] _0224_; + wire [9:0] _0225_; + wire [7:0] _0226_; + wire _0227_; + wire [3:0] _0228_; + wire _0229_; + wire [3:0] _0230_; + wire _0231_; + wire _0232_; + wire [31:0] _0233_; + wire _0234_; + wire _0235_; + wire _0236_; + wire _0237_; + wire _0238_; + wire _0239_; + wire _0240_; + wire _0241_; + wire _0242_; + wire [31:0] _0243_; + wire [31:0] _0244_; + wire _0245_; + wire [35:0] _0246_; + wire _0247_; + wire [31:0] _0248_; + wire _0249_; + wire [31:0] _0250_; + wire _0251_; + wire _0252_; + wire _0253_; + wire _0254_; + wire [31:0] _0255_; + wire _0256_; + wire [31:0] _0257_; + wire _0258_; + wire _0259_; + wire [31:0] _0260_; + wire _0261_; + wire _0262_; + wire _0263_; + wire _0264_; + wire _0265_; + wire _0266_; + wire _0267_; + wire _0268_; + wire _0269_; + wire _0270_; + wire _0271_; + wire _0272_; + wire _0273_; + wire _0274_; + wire _0275_; + wire _0276_; + wire _0277_; + wire _0278_; + wire _0279_; + wire _0280_; + wire _0281_; + wire _0282_; + wire _0283_; + wire _0284_; + wire _0285_; + wire _0286_; + wire _0287_; + wire [35:0] _0288_; + wire _0289_; + wire _0290_; + wire _0291_; + wire _0292_; + wire _0293_; + wire _0294_; + wire _0295_; + wire _0296_; + wire _0297_; + wire _0298_; + wire _0299_; + wire _0300_; + wire _0301_; + wire _0302_; + wire _0303_; + wire _0304_; + wire _0305_; + wire _0306_; + wire _0307_; + wire _0308_; + wire _0309_; + wire _0310_; + wire _0311_; + wire _0312_; + wire _0313_; + wire _0314_; + wire _0315_; + wire _0316_; + wire _0317_; + wire _0318_; + wire _0319_; + wire _0320_; + wire _0321_; + wire _0322_; + wire _0323_; + wire _0324_; + wire _0325_; + wire _0326_; + wire _0327_; + wire _0328_; + wire _0329_; + wire _0330_; + wire _0331_; + wire _0332_; + wire _0333_; + wire _0334_; + wire _0335_; + wire _0336_; + wire _0337_; + wire _0338_; + wire _0339_; + wire _0340_; + wire _0341_; + wire _0342_; + wire _0343_; + wire _0344_; + wire _0345_; + wire _0346_; + wire _0347_; + wire [2:0] _0348_; + wire _0349_; + wire [2:0] _0350_; + wire _0351_; + wire [2:0] _0352_; + wire _0353_; + wire [2:0] _0354_; + wire _0355_; + wire [2:0] _0356_; + wire _0357_; + wire [2:0] _0358_; + wire _0359_; + wire [2:0] _0360_; + wire _0361_; + wire [2:0] _0362_; + wire _0363_; + wire [2:0] _0364_; + wire _0365_; + wire [39:0] _0366_; + wire _0367_; + wire [39:0] _0368_; + wire _0369_; + wire [39:0] _0370_; + wire _0371_; + wire [39:0] _0372_; + wire _0373_; + wire [39:0] _0374_; + wire _0375_; + wire [39:0] _0376_; + wire _0377_; + wire [39:0] _0378_; + wire _0379_; + wire [7:0] _0380_; + wire _0381_; + wire _0382_; + wire _0383_; + wire _0384_; + wire _0385_; + wire [7:0] _0386_; + wire _0387_; + wire [7:0] _0388_; + wire _0389_; + wire [7:0] _0390_; + wire _0391_; + wire [7:0] _0392_; + wire _0393_; + wire [7:0] _0394_; + wire _0395_; + wire [7:0] _0396_; + wire _0397_; + wire [7:0] _0398_; + wire _0399_; + wire [7:0] _0400_; + wire _0401_; + wire [7:0] _0402_; + wire _0403_; + wire [7:0] _0404_; + wire _0405_; + wire [7:0] _0406_; + wire _0407_; + wire [7:0] _0408_; + wire _0409_; + wire _0410_; + wire _0411_; + wire _0412_; + wire _0413_; + wire _0414_; + wire _0415_; + wire [25:0] _0416_; + wire _0417_; + wire [25:0] _0418_; + wire _0419_; + wire [2:0] _0420_; + wire _0421_; + wire [2:0] _0422_; + wire _0423_; + wire [2:0] _0424_; + wire _0425_; + wire [2:0] _0426_; + wire _0427_; + wire _0428_; + wire _0429_; + wire _0430_; + wire _0431_; + wire _0432_; + wire _0433_; + wire _0434_; + wire _0435_; + wire [35:0] _0436_; + wire _0437_; + wire [35:0] _0438_; + wire _0439_; + wire [35:0] _0440_; + wire _0441_; + wire [35:0] _0442_; + wire _0443_; + wire _0444_; + wire _0445_; + wire _0446_; + wire _0447_; + wire [35:0] _0448_; + wire _0449_; + wire [35:0] _0450_; + wire _0451_; + wire [35:0] _0452_; + wire _0453_; + wire [35:0] _0454_; + wire _0455_; + wire [35:0] _0456_; + wire _0457_; + wire [3:0] _0458_; + wire _0459_; + wire [3:0] _0460_; + wire _0461_; + wire [35:0] _0462_; + wire _0463_; + wire [35:0] _0464_; + wire _0465_; + wire [3:0] _0466_; + wire _0467_; + wire [3:0] _0468_; + wire _0469_; + wire [3:0] _0470_; + wire _0471_; + wire _0472_; + wire _0473_; + wire _0474_; + wire _0475_; + wire [3:0] _0476_; + wire _0477_; + wire [3:0] _0478_; + wire _0479_; + wire [35:0] _0480_; + wire _0481_; + wire [35:0] _0482_; + wire _0483_; + wire [4:0] _0484_; + wire _0485_; + wire [4:0] _0486_; + wire _0487_; + wire [4:0] _0488_; + wire _0489_; + wire [35:0] _0490_; + wire _0491_; + wire [35:0] _0492_; + wire _0493_; + wire [35:0] _0494_; + wire _0495_; + wire [35:0] _0496_; + wire _0497_; + wire [3:0] _0498_; + wire _0499_; + wire [3:0] _0500_; + wire _0501_; + wire [35:0] _0502_; + wire _0503_; + wire [35:0] _0504_; + wire _0505_; + wire [3:0] _0506_; + wire _0507_; + wire [3:0] _0508_; + wire _0509_; + wire [3:0] _0510_; + wire _0511_; + wire _0512_; + wire _0513_; + wire _0514_; + wire _0515_; + wire [3:0] _0516_; + wire _0517_; + wire [3:0] _0518_; + wire _0519_; + wire [35:0] _0520_; + wire _0521_; + wire [35:0] _0522_; + wire _0523_; + wire [4:0] _0524_; + wire _0525_; + wire [4:0] _0526_; + wire _0527_; + wire [4:0] _0528_; + wire _0529_; + wire [7:0] _0530_; + wire _0531_; + wire [7:0] _0532_; + wire _0533_; + wire [7:0] _0534_; + wire _0535_; + wire [31:0] _0536_; + wire _0537_; + wire [31:0] _0538_; + wire _0539_; + wire [31:0] _0540_; + wire _0541_; + wire [7:0] _0542_; + wire _0543_; + wire [7:0] _0544_; + wire _0545_; + wire [7:0] _0546_; + wire _0547_; + wire [7:0] _0548_; + wire _0549_; + wire [7:0] _0550_; + wire _0551_; + wire [7:0] _0552_; + wire _0553_; + wire [7:0] _0554_; + wire _0555_; + wire [7:0] _0556_; + wire _0557_; + wire [31:0] _0558_; + wire _0559_; + wire [31:0] _0560_; + wire _0561_; + wire [7:0] _0562_; + wire _0563_; + wire [7:0] _0564_; + wire _0565_; + wire [7:0] _0566_; + wire _0567_; + wire [7:0] _0568_; + wire _0569_; + wire [7:0] _0570_; + wire _0571_; + wire [31:0] _0572_; + wire _0573_; + wire [7:0] _0574_; + wire _0575_; + wire [7:0] _0576_; + wire _0577_; + wire [9:0] _0578_; + wire _0579_; + wire [9:0] _0580_; + wire _0581_; + wire [9:0] _0582_; + wire _0583_; + wire [9:0] _0584_; + wire _0585_; + wire _0586_; + wire _0587_; + wire _0588_; + wire _0589_; + wire _0590_; + wire _0591_; + wire _0592_; + wire _0593_; + wire [3:0] _0594_; + wire _0595_; + wire [3:0] _0596_; + wire _0597_; + wire [3:0] _0598_; + wire _0599_; + wire [3:0] _0600_; + wire _0601_; + wire _0602_; + wire _0603_; + wire _0604_; + wire _0605_; + wire _0606_; + wire _0607_; + wire _0608_; + wire _0609_; + wire _0610_; + wire _0611_; + wire _0612_; + wire _0613_; + wire [9:0] _0614_; + wire _0615_; + wire [9:0] _0616_; + wire _0617_; + wire [9:0] _0618_; + wire _0619_; + wire [9:0] _0620_; + wire _0621_; + wire [9:0] _0622_; + wire _0623_; + wire [7:0] _0624_; + wire _0625_; + wire [7:0] _0626_; + wire _0627_; + wire [3:0] _0628_; + wire _0629_; + wire [3:0] _0630_; + wire _0631_; + wire [3:0] _0632_; + wire _0633_; + wire [3:0] _0634_; + wire _0635_; + wire _0636_; + wire _0637_; + wire _0638_; + wire _0639_; + wire _0640_; + wire _0641_; + wire _0642_; + wire _0643_; + wire _0644_; + wire _0645_; + wire _0646_; + wire _0647_; + wire _0648_; + wire _0649_; + wire _0650_; + wire _0651_; + wire _0652_; + wire _0653_; + wire _0654_; + wire _0655_; + wire _0656_; + wire _0657_; + wire _0658_; + wire _0659_; + wire [31:0] _0660_; + wire _0661_; + wire [31:0] _0662_; + wire _0663_; + wire [31:0] _0664_; + wire _0665_; + wire _0666_; + wire _0667_; + wire [31:0] _0668_; + wire _0669_; + wire _0670_; + wire _0671_; + wire _0672_; + wire _0673_; + wire _0674_; + wire _0675_; + wire _0676_; + wire _0677_; + wire [35:0] _0678_; + wire _0679_; + wire [35:0] _0680_; + wire _0681_; + wire [35:0] _0682_; + wire _0683_; + wire [35:0] _0684_; + wire _0685_; + wire [35:0] _0686_; + wire _0687_; + wire _0688_; + wire _0689_; + wire [31:0] _0690_; + wire _0691_; + wire [31:0] _0692_; + wire _0693_; + wire _0694_; + wire _0695_; + wire _0696_; + wire _0697_; + wire _0698_; + wire _0699_; + wire _0700_; + wire _0701_; + wire [11:0] _0702_; + wire _0703_; + wire [11:0] _0704_; + wire _0705_; + output chip_clock; + reg chip_clock; + output [11:0] chip_inputs; + reg [11:0] chip_inputs; + input [11:0] chip_outputs; + wire [11:0] chip_outputs; + output chip_reset; + reg chip_reset; + wire clk; + input clk100; + wire clk100; + reg [31:0] data_in; + wire [31:0] data_out; + input uart_rx; + wire uart_rx; + reg [2:0] uart_rx_sync; + output uart_tx; + wire uart_tx; + reg wb_ack; + wire wb_cyc; + wire wb_stb; + wire wb_we; + reg [35:0] \wbdbg.cmd_data ; + wire \wbdbg.cmd_fifo.i_clk ; + wire \wbdbg.cmd_fifo.i_rd_en ; + wire \wbdbg.cmd_fifo.i_rst ; + wire [35:0] \wbdbg.cmd_fifo.i_wr_data ; + wire \wbdbg.cmd_fifo.i_wr_en ; + reg [4:0] \wbdbg.cmd_fifo.len = 5'h00; + wire \wbdbg.cmd_fifo.o_empty ; + wire \wbdbg.cmd_fifo.o_full ; + reg [35:0] \wbdbg.cmd_fifo.o_rd_data ; + reg \wbdbg.cmd_fifo.o_rd_valid = 1'h0; + reg [3:0] \wbdbg.cmd_fifo.rd_ptr = 4'h0; + reg [3:0] \wbdbg.cmd_fifo.wr_ptr = 4'h0; + wire \wbdbg.cmd_fifo_empty ; + wire \wbdbg.cmd_fifo_full ; + wire [35:0] \wbdbg.cmd_fifo_rd_data ; + reg \wbdbg.cmd_fifo_rd_en = 1'h0; + wire \wbdbg.cmd_fifo_rd_valid ; + reg [35:0] \wbdbg.cmd_fifo_wr_data = 36'h000000000; + reg \wbdbg.cmd_fifo_wr_en = 1'h0; + wire \wbdbg.cmd_ready ; + reg \wbdbg.cmd_reset = 1'h0; + reg \wbdbg.cmd_valid = 1'h0; + reg [25:0] \wbdbg.drop_timer = 26'h17d7840; + wire \wbdbg.i_clk ; + wire \wbdbg.i_interrupt_1 ; + wire \wbdbg.i_interrupt_2 ; + wire \wbdbg.i_interrupt_3 ; + wire \wbdbg.i_interrupt_4 ; + wire \wbdbg.i_rx ; + wire \wbdbg.i_wb_ack ; + wire [31:0] \wbdbg.i_wb_data ; + wire \wbdbg.i_wb_err ; + wire \wbdbg.i_wb_stall ; + reg \wbdbg.interrupt_1_last = 1'h0; + reg \wbdbg.interrupt_1_rising = 1'h0; + reg \wbdbg.interrupt_2_last = 1'h0; + reg \wbdbg.interrupt_2_rising = 1'h0; + reg \wbdbg.interrupt_3_last = 1'h0; + reg \wbdbg.interrupt_3_rising = 1'h0; + reg \wbdbg.interrupt_4_last = 1'h0; + reg \wbdbg.interrupt_4_rising = 1'h0; + wire \wbdbg.o_tx ; + wire [31:0] \wbdbg.o_wb_addr ; + wire \wbdbg.o_wb_cyc ; + wire [31:0] \wbdbg.o_wb_data ; + wire \wbdbg.o_wb_stb ; + wire \wbdbg.o_wb_we ; + reg [39:0] \wbdbg.recieve_data = 40'h0000000000; + reg [2:0] \wbdbg.recieve_state = 3'h0; + wire [35:0] \wbdbg.resp_data ; + wire \wbdbg.resp_fifo.i_clk ; + wire \wbdbg.resp_fifo.i_rd_en ; + wire \wbdbg.resp_fifo.i_rst ; + wire [35:0] \wbdbg.resp_fifo.i_wr_data ; + wire \wbdbg.resp_fifo.i_wr_en ; + reg [4:0] \wbdbg.resp_fifo.len = 5'h00; + wire \wbdbg.resp_fifo.o_empty ; + wire \wbdbg.resp_fifo.o_full ; + reg [35:0] \wbdbg.resp_fifo.o_rd_data ; + reg \wbdbg.resp_fifo.o_rd_valid = 1'h0; + reg [3:0] \wbdbg.resp_fifo.rd_ptr = 4'h0; + reg [3:0] \wbdbg.resp_fifo.wr_ptr = 4'h0; + wire \wbdbg.resp_fifo_empty ; + wire \wbdbg.resp_fifo_full ; + wire [35:0] \wbdbg.resp_fifo_rd_data ; + reg \wbdbg.resp_fifo_rd_en = 1'h0; + wire \wbdbg.resp_fifo_rd_valid ; + reg [35:0] \wbdbg.resp_fifo_wr_data = 36'h000000000; + reg \wbdbg.resp_fifo_wr_en = 1'h0; + wire \wbdbg.resp_valid ; + reg [39:0] \wbdbg.transmit_data = 40'h0000000000; + reg [2:0] \wbdbg.transmit_state = 3'h0; + reg [9:0] \wbdbg.uart_rx.counter ; + wire \wbdbg.uart_rx.i_clk ; + wire \wbdbg.uart_rx.i_in ; + reg [7:0] \wbdbg.uart_rx.o_data ; + reg \wbdbg.uart_rx.o_valid ; + reg [3:0] \wbdbg.uart_rx.state = 4'h0; + wire [7:0] \wbdbg.uart_rx_data ; + wire \wbdbg.uart_rx_valid ; + reg [9:0] \wbdbg.uart_tx.counter ; + reg [7:0] \wbdbg.uart_tx.data_send ; + wire \wbdbg.uart_tx.i_clk ; + wire [7:0] \wbdbg.uart_tx.i_data ; + wire \wbdbg.uart_tx.i_valid ; + wire \wbdbg.uart_tx.o_out ; + wire \wbdbg.uart_tx.o_ready ; + reg [3:0] \wbdbg.uart_tx.state = 4'h0; + reg [7:0] \wbdbg.uart_tx_data ; + wire \wbdbg.uart_tx_ready ; + reg \wbdbg.uart_tx_valid = 1'h0; + reg \wbdbg.wbdbgbusmaster.addr_inc = 1'h0; + wire [31:0] \wbdbg.wbdbgbusmaster.cmd_data ; + wire [3:0] \wbdbg.wbdbgbusmaster.cmd_inst ; + wire \wbdbg.wbdbgbusmaster.cmd_recv ; + wire \wbdbg.wbdbgbusmaster.i_clk ; + wire [35:0] \wbdbg.wbdbgbusmaster.i_cmd_data ; + wire \wbdbg.wbdbgbusmaster.i_cmd_reset ; + wire \wbdbg.wbdbgbusmaster.i_cmd_valid ; + wire \wbdbg.wbdbgbusmaster.i_wb_ack ; + wire [31:0] \wbdbg.wbdbgbusmaster.i_wb_data ; + wire \wbdbg.wbdbgbusmaster.i_wb_err ; + wire \wbdbg.wbdbgbusmaster.i_wb_stall ; + wire \wbdbg.wbdbgbusmaster.o_cmd_ready ; + reg [35:0] \wbdbg.wbdbgbusmaster.o_resp_data ; + reg \wbdbg.wbdbgbusmaster.o_resp_valid = 1'h0; + reg [31:0] \wbdbg.wbdbgbusmaster.o_wb_addr = 32'd0; + reg \wbdbg.wbdbgbusmaster.o_wb_cyc = 1'h0; + reg [31:0] \wbdbg.wbdbgbusmaster.o_wb_data = 32'd0; + reg \wbdbg.wbdbgbusmaster.o_wb_stb = 1'h0; + reg \wbdbg.wbdbgbusmaster.o_wb_we = 1'h0; + reg [35:0] \wbdbg.cmd_fifo.ram [15:0]; + always @(posedge \wbdbg.cmd_fifo.i_clk ) begin + if (_0118_[0]) + \wbdbg.cmd_fifo.ram [_0116_][0:0] <= _0117_[0]; + if (_0118_[1]) + \wbdbg.cmd_fifo.ram [_0116_][1:1] <= _0117_[1]; + if (_0118_[2]) + \wbdbg.cmd_fifo.ram [_0116_][2:2] <= _0117_[2]; + if (_0118_[3]) + \wbdbg.cmd_fifo.ram [_0116_][3:3] <= _0117_[3]; + if (_0118_[4]) + \wbdbg.cmd_fifo.ram [_0116_][4:4] <= _0117_[4]; + if (_0118_[5]) + \wbdbg.cmd_fifo.ram [_0116_][5:5] <= _0117_[5]; + if (_0118_[6]) + \wbdbg.cmd_fifo.ram [_0116_][6:6] <= _0117_[6]; + if (_0118_[7]) + \wbdbg.cmd_fifo.ram [_0116_][7:7] <= _0117_[7]; + if (_0118_[8]) + \wbdbg.cmd_fifo.ram [_0116_][8:8] <= _0117_[8]; + if (_0118_[9]) + \wbdbg.cmd_fifo.ram [_0116_][9:9] <= _0117_[9]; + if (_0118_[10]) + \wbdbg.cmd_fifo.ram [_0116_][10:10] <= _0117_[10]; + if (_0118_[11]) + \wbdbg.cmd_fifo.ram [_0116_][11:11] <= _0117_[11]; + if (_0118_[12]) + \wbdbg.cmd_fifo.ram [_0116_][12:12] <= _0117_[12]; + if (_0118_[13]) + \wbdbg.cmd_fifo.ram [_0116_][13:13] <= _0117_[13]; + if (_0118_[14]) + \wbdbg.cmd_fifo.ram [_0116_][14:14] <= _0117_[14]; + if (_0118_[15]) + \wbdbg.cmd_fifo.ram [_0116_][15:15] <= _0117_[15]; + if (_0118_[16]) + \wbdbg.cmd_fifo.ram [_0116_][16:16] <= _0117_[16]; + if (_0118_[17]) + \wbdbg.cmd_fifo.ram [_0116_][17:17] <= _0117_[17]; + if (_0118_[18]) + \wbdbg.cmd_fifo.ram [_0116_][18:18] <= _0117_[18]; + if (_0118_[19]) + \wbdbg.cmd_fifo.ram [_0116_][19:19] <= _0117_[19]; + if (_0118_[20]) + \wbdbg.cmd_fifo.ram [_0116_][20:20] <= _0117_[20]; + if (_0118_[21]) + \wbdbg.cmd_fifo.ram [_0116_][21:21] <= _0117_[21]; + if (_0118_[22]) + \wbdbg.cmd_fifo.ram [_0116_][22:22] <= _0117_[22]; + if (_0118_[23]) + \wbdbg.cmd_fifo.ram [_0116_][23:23] <= _0117_[23]; + if (_0118_[24]) + \wbdbg.cmd_fifo.ram [_0116_][24:24] <= _0117_[24]; + if (_0118_[25]) + \wbdbg.cmd_fifo.ram [_0116_][25:25] <= _0117_[25]; + if (_0118_[26]) + \wbdbg.cmd_fifo.ram [_0116_][26:26] <= _0117_[26]; + if (_0118_[27]) + \wbdbg.cmd_fifo.ram [_0116_][27:27] <= _0117_[27]; + if (_0118_[28]) + \wbdbg.cmd_fifo.ram [_0116_][28:28] <= _0117_[28]; + if (_0118_[29]) + \wbdbg.cmd_fifo.ram [_0116_][29:29] <= _0117_[29]; + if (_0118_[30]) + \wbdbg.cmd_fifo.ram [_0116_][30:30] <= _0117_[30]; + if (_0118_[31]) + \wbdbg.cmd_fifo.ram [_0116_][31:31] <= _0117_[31]; + if (_0118_[32]) + \wbdbg.cmd_fifo.ram [_0116_][32:32] <= _0117_[32]; + if (_0118_[33]) + \wbdbg.cmd_fifo.ram [_0116_][33:33] <= _0117_[33]; + if (_0118_[34]) + \wbdbg.cmd_fifo.ram [_0116_][34:34] <= _0117_[34]; + if (_0118_[35]) + \wbdbg.cmd_fifo.ram [_0116_][35:35] <= _0117_[35]; + end + assign _0135_ = \wbdbg.cmd_fifo.ram [\wbdbg.cmd_fifo.rd_ptr ]; + reg [35:0] \wbdbg.resp_fifo.ram [15:0]; + always @(posedge \wbdbg.resp_fifo.i_clk ) begin + if (_0155_[0]) + \wbdbg.resp_fifo.ram [_0153_][0:0] <= _0154_[0]; + if (_0155_[1]) + \wbdbg.resp_fifo.ram [_0153_][1:1] <= _0154_[1]; + if (_0155_[2]) + \wbdbg.resp_fifo.ram [_0153_][2:2] <= _0154_[2]; + if (_0155_[3]) + \wbdbg.resp_fifo.ram [_0153_][3:3] <= _0154_[3]; + if (_0155_[4]) + \wbdbg.resp_fifo.ram [_0153_][4:4] <= _0154_[4]; + if (_0155_[5]) + \wbdbg.resp_fifo.ram [_0153_][5:5] <= _0154_[5]; + if (_0155_[6]) + \wbdbg.resp_fifo.ram [_0153_][6:6] <= _0154_[6]; + if (_0155_[7]) + \wbdbg.resp_fifo.ram [_0153_][7:7] <= _0154_[7]; + if (_0155_[8]) + \wbdbg.resp_fifo.ram [_0153_][8:8] <= _0154_[8]; + if (_0155_[9]) + \wbdbg.resp_fifo.ram [_0153_][9:9] <= _0154_[9]; + if (_0155_[10]) + \wbdbg.resp_fifo.ram [_0153_][10:10] <= _0154_[10]; + if (_0155_[11]) + \wbdbg.resp_fifo.ram [_0153_][11:11] <= _0154_[11]; + if (_0155_[12]) + \wbdbg.resp_fifo.ram [_0153_][12:12] <= _0154_[12]; + if (_0155_[13]) + \wbdbg.resp_fifo.ram [_0153_][13:13] <= _0154_[13]; + if (_0155_[14]) + \wbdbg.resp_fifo.ram [_0153_][14:14] <= _0154_[14]; + if (_0155_[15]) + \wbdbg.resp_fifo.ram [_0153_][15:15] <= _0154_[15]; + if (_0155_[16]) + \wbdbg.resp_fifo.ram [_0153_][16:16] <= _0154_[16]; + if (_0155_[17]) + \wbdbg.resp_fifo.ram [_0153_][17:17] <= _0154_[17]; + if (_0155_[18]) + \wbdbg.resp_fifo.ram [_0153_][18:18] <= _0154_[18]; + if (_0155_[19]) + \wbdbg.resp_fifo.ram [_0153_][19:19] <= _0154_[19]; + if (_0155_[20]) + \wbdbg.resp_fifo.ram [_0153_][20:20] <= _0154_[20]; + if (_0155_[21]) + \wbdbg.resp_fifo.ram [_0153_][21:21] <= _0154_[21]; + if (_0155_[22]) + \wbdbg.resp_fifo.ram [_0153_][22:22] <= _0154_[22]; + if (_0155_[23]) + \wbdbg.resp_fifo.ram [_0153_][23:23] <= _0154_[23]; + if (_0155_[24]) + \wbdbg.resp_fifo.ram [_0153_][24:24] <= _0154_[24]; + if (_0155_[25]) + \wbdbg.resp_fifo.ram [_0153_][25:25] <= _0154_[25]; + if (_0155_[26]) + \wbdbg.resp_fifo.ram [_0153_][26:26] <= _0154_[26]; + if (_0155_[27]) + \wbdbg.resp_fifo.ram [_0153_][27:27] <= _0154_[27]; + if (_0155_[28]) + \wbdbg.resp_fifo.ram [_0153_][28:28] <= _0154_[28]; + if (_0155_[29]) + \wbdbg.resp_fifo.ram [_0153_][29:29] <= _0154_[29]; + if (_0155_[30]) + \wbdbg.resp_fifo.ram [_0153_][30:30] <= _0154_[30]; + if (_0155_[31]) + \wbdbg.resp_fifo.ram [_0153_][31:31] <= _0154_[31]; + if (_0155_[32]) + \wbdbg.resp_fifo.ram [_0153_][32:32] <= _0154_[32]; + if (_0155_[33]) + \wbdbg.resp_fifo.ram [_0153_][33:33] <= _0154_[33]; + if (_0155_[34]) + \wbdbg.resp_fifo.ram [_0153_][34:34] <= _0154_[34]; + if (_0155_[35]) + \wbdbg.resp_fifo.ram [_0153_][35:35] <= _0154_[35]; + end + assign _0172_ = \wbdbg.resp_fifo.ram [\wbdbg.resp_fifo.rd_ptr ]; + assign _0058_ = \wbdbg.transmit_state + 32'd1; + assign _0059_ = \wbdbg.recieve_state + 32'd1; + assign _0060_ = ! \wbdbg.transmit_state ; + assign _0062_ = \wbdbg.transmit_state == 3'h5; + assign _0063_ = \wbdbg.recieve_state == 3'h4; + assign _0064_ = \wbdbg.recieve_data [35:32] == 4'hf; + assign _0065_ = \wbdbg.drop_timer == 26'h0000001; + assign _0066_ = \wbdbg.recieve_state > 32'd0; + assign _0067_ = \wbdbg.resp_valid && _0087_; + assign _0072_ = _0060_ && _0092_; + assign _0073_ = _0072_ && _0093_; + assign _0074_ = _0073_ && _0094_; + assign _0075_ = _0074_ && _0095_; + assign _0076_ = _0075_ && _0096_; + assign _0077_ = _0076_ && _0097_; + assign _0078_ = _0077_ && _0098_; + assign _0079_ = \wbdbg.uart_tx_ready && _0099_; + assign _0080_ = _0101_ && \wbdbg.cmd_ready ; + assign _0081_ = _0080_ && _0102_; + assign _0082_ = _0081_ && _0103_; + assign _0083_ = _0082_ && _0104_; + assign _0084_ = _0083_ && _0105_; + assign _0085_ = \wbdbg.cmd_ready && \wbdbg.cmd_fifo_rd_valid ; + assign _0086_ = _0085_ && _0106_; + assign _0087_ = ~ \wbdbg.resp_fifo_full ; + assign _0088_ = ~ \wbdbg.interrupt_1_last ; + assign _0089_ = ~ \wbdbg.interrupt_2_last ; + assign _0090_ = ~ \wbdbg.interrupt_3_last ; + assign _0091_ = ~ \wbdbg.interrupt_4_last ; + assign _0092_ = ~ \wbdbg.resp_fifo_empty ; + assign _0093_ = ~ \wbdbg.resp_fifo_rd_valid ; + assign _0094_ = ~ \wbdbg.resp_fifo_rd_en ; + assign _0095_ = ~ \wbdbg.interrupt_1_rising ; + assign _0096_ = ~ \wbdbg.interrupt_2_rising ; + assign _0097_ = ~ \wbdbg.interrupt_3_rising ; + assign _0098_ = ~ \wbdbg.interrupt_4_rising ; + assign _0099_ = ~ \wbdbg.uart_tx_valid ; + assign _0100_ = ~ \wbdbg.cmd_fifo_full ; + assign _0101_ = ~ \wbdbg.cmd_reset ; + assign _0102_ = ~ \wbdbg.cmd_fifo_empty ; + assign _0103_ = ~ \wbdbg.cmd_fifo_rd_en ; + assign _0104_ = ~ \wbdbg.cmd_fifo_rd_valid ; + assign _0105_ = ~ \wbdbg.cmd_valid ; + assign _0107_ = \wbdbg.drop_timer - 32'd1; + assign _0126_ = \wbdbg.cmd_fifo.wr_ptr + 32'd1; + assign _0127_ = \wbdbg.cmd_fifo.rd_ptr + 32'd1; + assign _0128_ = \wbdbg.cmd_fifo.len + 32'd1; + assign _0129_ = ! \wbdbg.cmd_fifo.len ; + assign _0130_ = \wbdbg.cmd_fifo.len == 5'h10; + assign _0131_ = \wbdbg.cmd_fifo.i_rd_en && _0140_; + assign _0132_ = _0131_ && _0141_; + assign _0133_ = \wbdbg.cmd_fifo.i_wr_en && _0142_; + assign _0134_ = _0133_ && _0143_; + assign _0140_ = ~ \wbdbg.cmd_fifo.i_wr_en ; + assign _0144_ = \wbdbg.cmd_fifo.len - 32'd1; + assign _0163_ = \wbdbg.resp_fifo.wr_ptr + 32'd1; + assign _0164_ = \wbdbg.resp_fifo.rd_ptr + 32'd1; + assign _0165_ = \wbdbg.resp_fifo.len + 32'd1; + assign _0166_ = ! \wbdbg.resp_fifo.len ; + assign _0167_ = \wbdbg.resp_fifo.len == 5'h10; + assign _0168_ = \wbdbg.resp_fifo.i_rd_en && _0177_; + assign _0169_ = _0168_ && _0178_; + assign _0170_ = \wbdbg.resp_fifo.i_wr_en && _0179_; + assign _0171_ = _0170_ && _0180_; + assign _0177_ = ~ \wbdbg.resp_fifo.i_wr_en ; + assign _0181_ = \wbdbg.resp_fifo.len - 32'd1; + assign _0203_ = \wbdbg.uart_rx.state + 32'd1; + assign _0205_ = \wbdbg.uart_rx.o_data & _0217_; + assign _0209_ = ! \wbdbg.uart_rx.state ; + assign _0210_ = ~ \wbdbg.uart_rx.i_in ; + assign _0211_ = ! \wbdbg.uart_rx.counter ; + assign _0212_ = \wbdbg.uart_rx.state == 4'h9; + assign _0216_ = - $signed(_0222_); + assign _0217_ = ~ _0219_; + assign _0218_ = _0205_ | _0220_; + assign _0219_ = $signed(_0215_) < 0 ? 1'h1 << - _0215_ : 1'h1 >> _0215_; + assign _0220_ = $signed(_0216_) < 0 ? uart_rx_sync[2] << - _0216_ : uart_rx_sync[2] >> _0216_; + assign _0222_ = + $signed({ 1'h0, _0223_ }); + assign _0223_ = \wbdbg.uart_rx.state - 32'd1; + assign _0224_ = \wbdbg.uart_rx.counter - 32'd1; + assign _0233_ = \wbdbg.uart_tx.state + 32'd1; + assign _0236_ = ! \wbdbg.uart_tx.counter ; + assign _0239_ = ! \wbdbg.uart_tx.state ; + assign _0240_ = \wbdbg.uart_tx.state == 4'h1; + assign _0241_ = \wbdbg.uart_tx.state == 4'ha; + wire [7:0] _1087_ = \wbdbg.uart_tx.data_send ; + assign _0242_ = _1087_[$signed(_0244_) +: 1]; + assign _0243_ = \wbdbg.uart_tx.counter - 32'd1; + assign _0244_ = \wbdbg.uart_tx.state - 32'd2; + assign _0260_ = \wbdbg.wbdbgbusmaster.o_wb_addr + \wbdbg.wbdbgbusmaster.addr_inc ; + assign _0261_ = \wbdbg.wbdbgbusmaster.cmd_inst == 4'h1; + assign _0266_ = \wbdbg.wbdbgbusmaster.cmd_inst == 4'h2; + assign _0267_ = \wbdbg.wbdbgbusmaster.cmd_inst == 4'h3; + assign _0268_ = \wbdbg.wbdbgbusmaster.cmd_inst == 4'h7; + assign _0269_ = \wbdbg.wbdbgbusmaster.i_cmd_valid && \wbdbg.wbdbgbusmaster.o_cmd_ready ; + assign _0270_ = \wbdbg.wbdbgbusmaster.cmd_recv && _0278_; + assign _0272_ = \wbdbg.wbdbgbusmaster.cmd_recv && _0266_; + assign _0274_ = \wbdbg.wbdbgbusmaster.o_wb_cyc && \wbdbg.wbdbgbusmaster.i_wb_ack ; + assign _0275_ = \wbdbg.wbdbgbusmaster.cmd_recv && _0280_; + assign _0278_ = _0261_ || _0262_; + assign _0280_ = _0267_ || _0268_; + assign _0283_ = ~ \wbdbg.wbdbgbusmaster.o_wb_cyc ; + assign _0285_ = wb_cyc && wb_stb; + always @(posedge \wbdbg.i_clk ) + \wbdbg.interrupt_1_last <= 1'h0; + always @(posedge \wbdbg.i_clk ) + \wbdbg.interrupt_2_last <= 1'h0; + always @(posedge \wbdbg.i_clk ) + \wbdbg.interrupt_3_last <= 1'h0; + always @(posedge \wbdbg.i_clk ) + \wbdbg.interrupt_4_last <= 1'h0; + always @(posedge \wbdbg.i_clk ) + \wbdbg.resp_fifo_wr_en <= _0286_; + always @(posedge \wbdbg.i_clk ) + \wbdbg.resp_fifo_wr_data <= _0288_; + always @(posedge \wbdbg.i_clk ) + \wbdbg.uart_tx_data <= _0388_; + always @(posedge \wbdbg.i_clk ) + \wbdbg.uart_tx_valid <= _0294_; + always @(posedge \wbdbg.i_clk ) + \wbdbg.resp_fifo_rd_en <= _0290_; + always @(posedge \wbdbg.i_clk ) + \wbdbg.transmit_data <= _0378_; + always @(posedge \wbdbg.i_clk ) + \wbdbg.transmit_state <= _0364_; + always @(posedge \wbdbg.i_clk ) + \wbdbg.interrupt_1_rising <= _0346_; + always @(posedge \wbdbg.i_clk ) + \wbdbg.interrupt_2_rising <= _0336_; + always @(posedge \wbdbg.i_clk ) + \wbdbg.interrupt_3_rising <= _0324_; + always @(posedge \wbdbg.i_clk ) + \wbdbg.interrupt_4_rising <= _0310_; + always @(posedge \wbdbg.i_clk ) + \wbdbg.cmd_reset <= _0414_; + always @(posedge \wbdbg.i_clk ) + \wbdbg.cmd_fifo_wr_en <= _0434_; + always @(posedge \wbdbg.i_clk ) + \wbdbg.cmd_fifo_wr_data <= _0442_; + always @(posedge \wbdbg.i_clk ) + \wbdbg.recieve_data <= { _0408_, _0404_, _0400_, _0392_, _0396_ }; + always @(posedge \wbdbg.i_clk ) + \wbdbg.recieve_state <= _0426_; + always @(posedge \wbdbg.i_clk ) + \wbdbg.drop_timer <= _0418_; + always @(posedge \wbdbg.i_clk ) + \wbdbg.cmd_valid <= _0446_; + always @(posedge \wbdbg.i_clk ) + \wbdbg.cmd_data <= _0448_; + always @(posedge \wbdbg.i_clk ) + \wbdbg.cmd_fifo_rd_en <= _0444_; + always @(posedge \wbdbg.cmd_fifo.i_clk ) + \wbdbg.cmd_fifo.wr_ptr <= _0470_; + always @(posedge \wbdbg.cmd_fifo.i_clk ) + _0136_ <= _0466_; + always @(posedge \wbdbg.cmd_fifo.i_clk ) + _0137_ <= _0464_; + always @(posedge \wbdbg.cmd_fifo.i_clk ) + _0138_ <= _0462_; + always @(posedge \wbdbg.cmd_fifo.i_clk ) + \wbdbg.cmd_fifo.o_rd_data <= _0482_; + always @(posedge \wbdbg.cmd_fifo.i_clk ) + \wbdbg.cmd_fifo.o_rd_valid <= _0474_; + always @(posedge \wbdbg.cmd_fifo.i_clk ) + \wbdbg.cmd_fifo.rd_ptr <= _0478_; + always @(posedge \wbdbg.cmd_fifo.i_clk ) + \wbdbg.cmd_fifo.len <= _0488_; + always @(posedge \wbdbg.resp_fifo.i_clk ) + \wbdbg.resp_fifo.wr_ptr <= _0510_; + always @(posedge \wbdbg.resp_fifo.i_clk ) + _0173_ <= _0506_; + always @(posedge \wbdbg.resp_fifo.i_clk ) + _0174_ <= _0504_; + always @(posedge \wbdbg.resp_fifo.i_clk ) + _0175_ <= _0502_; + always @(posedge \wbdbg.resp_fifo.i_clk ) + \wbdbg.resp_fifo.o_rd_data <= _0522_; + always @(posedge \wbdbg.resp_fifo.i_clk ) + \wbdbg.resp_fifo.o_rd_valid <= _0514_; + always @(posedge \wbdbg.resp_fifo.i_clk ) + \wbdbg.resp_fifo.rd_ptr <= _0518_; + always @(posedge \wbdbg.resp_fifo.i_clk ) + \wbdbg.resp_fifo.len <= _0528_; + always @(posedge \wbdbg.uart_rx.i_clk ) + \wbdbg.uart_rx.o_data <= _0570_; + always @(posedge \wbdbg.uart_rx.i_clk ) + \wbdbg.uart_rx.o_valid <= _0592_; + always @(posedge \wbdbg.uart_rx.i_clk ) + \wbdbg.uart_rx.counter <= _0584_; + always @(posedge \wbdbg.uart_rx.i_clk ) + \wbdbg.uart_rx.state <= _0600_; + always @(posedge \wbdbg.uart_rx.i_clk ) + _0207_ <= 8'hxx; + always @(posedge \wbdbg.uart_rx.i_clk ) + _0206_ <= 8'hxx; + always @(posedge \wbdbg.uart_rx.i_clk ) + _0208_ <= 32'hxxxxxxxx; + always @(posedge \wbdbg.uart_rx.i_clk ) + _0214_ <= 8'hxx; + always @(posedge \wbdbg.uart_tx.i_clk ) + \wbdbg.uart_tx.counter <= _0622_; + always @(posedge \wbdbg.uart_tx.i_clk ) + \wbdbg.uart_tx.state <= _0634_; + always @(posedge \wbdbg.uart_tx.i_clk ) + \wbdbg.uart_tx.data_send <= _0626_; + always @(posedge \wbdbg.wbdbgbusmaster.i_clk ) + \wbdbg.wbdbgbusmaster.o_wb_cyc <= _0654_; + always @(posedge \wbdbg.wbdbgbusmaster.i_clk ) + \wbdbg.wbdbgbusmaster.o_wb_stb <= _0644_; + always @(posedge \wbdbg.wbdbgbusmaster.i_clk ) + \wbdbg.wbdbgbusmaster.o_wb_addr <= _0664_; + always @(posedge \wbdbg.wbdbgbusmaster.i_clk ) + \wbdbg.wbdbgbusmaster.addr_inc <= _0658_; + always @(posedge \wbdbg.wbdbgbusmaster.i_clk ) + \wbdbg.wbdbgbusmaster.o_wb_we <= _0666_; + always @(posedge \wbdbg.wbdbgbusmaster.i_clk ) + \wbdbg.wbdbgbusmaster.o_wb_data <= _0668_; + always @(posedge \wbdbg.wbdbgbusmaster.i_clk ) + \wbdbg.wbdbgbusmaster.o_resp_valid <= _0676_; + always @(posedge \wbdbg.wbdbgbusmaster.i_clk ) + \wbdbg.wbdbgbusmaster.o_resp_data <= _0686_; + always @(posedge clk) + uart_rx_sync <= { uart_rx_sync[1:0], uart_rx }; + always @(posedge clk) + chip_inputs <= _0704_; + always @(posedge clk) + chip_clock <= _0700_; + always @(posedge clk) + chip_reset <= _0696_; + always @(posedge clk) + wb_ack <= _0688_; + always @(posedge clk) + data_in <= _0692_; + assign _0286_ = _0287_ ? 1'h1 : 1'h0; + assign _0288_ = _0289_ ? \wbdbg.wbdbgbusmaster.o_resp_data : \wbdbg.resp_fifo_wr_data ; + assign _0290_ = _0291_ ? 1'h1 : 1'h0; + assign _0292_ = _0293_ ? 1'h1 : 1'h0; + assign _0294_ = _0295_ ? 1'h0 : _0292_; + assign _0298_ = _0299_ ? 1'h0 : _0296_; + assign _0300_ = _0301_ ? _0296_ : _0298_; + assign _0302_ = _0303_ ? _0296_ : _0300_; + assign _0304_ = _0305_ ? _0296_ : _0302_; + assign _0306_ = _0307_ ? _0296_ : _0304_; + assign _0308_ = _0309_ ? _0296_ : _0306_; + assign _0310_ = _0311_ ? _0308_ : _0296_; + assign _0314_ = _0315_ ? 1'h0 : _0312_; + assign _0316_ = _0317_ ? _0312_ : _0314_; + assign _0318_ = _0319_ ? _0312_ : _0316_; + assign _0320_ = _0321_ ? _0312_ : _0318_; + assign _0322_ = _0323_ ? _0312_ : _0320_; + assign _0324_ = _0325_ ? _0322_ : _0312_; + assign _0328_ = _0329_ ? 1'h0 : _0326_; + assign _0330_ = _0331_ ? _0326_ : _0328_; + assign _0332_ = _0333_ ? _0326_ : _0330_; + assign _0334_ = _0335_ ? _0326_ : _0332_; + assign _0336_ = _0337_ ? _0334_ : _0326_; + assign _0340_ = _0341_ ? 1'h0 : _0338_; + assign _0342_ = _0343_ ? _0338_ : _0340_; + assign _0344_ = _0345_ ? _0338_ : _0342_; + assign _0346_ = _0347_ ? _0344_ : _0338_; + assign _0348_ = _0349_ ? 3'h0 : _0058_[2:0]; + assign _0350_ = _0351_ ? _0348_ : \wbdbg.transmit_state ; + assign _0352_ = _0353_ ? 3'h1 : \wbdbg.transmit_state ; + assign _0354_ = _0355_ ? 3'h1 : _0352_; + assign _0356_ = _0357_ ? 3'h1 : _0354_; + assign _0358_ = _0359_ ? 3'h1 : _0356_; + assign _0360_ = _0361_ ? \wbdbg.transmit_state : _0358_; + assign _0362_ = _0363_ ? 3'h1 : _0360_; + assign _0364_ = _0365_ ? _0362_ : _0350_; + assign _0366_ = _0367_ ? 40'h0b00000000 : \wbdbg.transmit_data ; + assign _0368_ = _0369_ ? 40'h0a00000000 : _0366_; + assign _0370_ = _0371_ ? 40'h0900000000 : _0368_; + assign _0372_ = _0373_ ? 40'h0800000000 : _0370_; + assign _0374_ = _0375_ ? \wbdbg.transmit_data : _0372_; + assign _0376_ = _0377_ ? { 4'h0, \wbdbg.resp_fifo.o_rd_data } : _0374_; + assign _0378_ = _0379_ ? _0376_ : \wbdbg.transmit_data ; + function [7:0] _0920_; + input [7:0] a; + input [39:0] b; + input [4:0] s; + casez (s) // synopsys parallel_case + 5'b????1: + _0920_ = b[7:0]; + 5'b???1?: + _0920_ = b[15:8]; + 5'b??1??: + _0920_ = b[23:16]; + 5'b?1???: + _0920_ = b[31:24]; + 5'b1????: + _0920_ = b[39:32]; + default: + _0920_ = a; + endcase + endfunction + assign _0380_ = _0920_(8'h00, \wbdbg.transmit_data , { _0385_, _0384_, _0383_, _0382_, _0381_ }); + assign _0381_ = \wbdbg.transmit_state == 3'h5; + assign _0382_ = \wbdbg.transmit_state == 3'h4; + assign _0383_ = \wbdbg.transmit_state == 3'h3; + assign _0384_ = \wbdbg.transmit_state == 3'h2; + assign _0385_ = \wbdbg.transmit_state == 3'h1; + assign _0386_ = _0387_ ? _0380_ : \wbdbg.uart_tx_data ; + assign _0388_ = _0389_ ? \wbdbg.uart_tx_data : _0386_; + assign _0390_ = _0391_ ? \wbdbg.uart_rx.o_data : \wbdbg.recieve_data [15:8]; + assign _0391_ = \wbdbg.recieve_state == 3'h3; + assign _0392_ = _0393_ ? _0390_ : \wbdbg.recieve_data [15:8]; + assign _0394_ = _0395_ ? \wbdbg.uart_rx.o_data : \wbdbg.recieve_data [7:0]; + assign _0395_ = \wbdbg.recieve_state == 3'h4; + assign _0396_ = _0397_ ? _0394_ : \wbdbg.recieve_data [7:0]; + assign _0398_ = _0399_ ? \wbdbg.uart_rx.o_data : \wbdbg.recieve_data [23:16]; + assign _0399_ = \wbdbg.recieve_state == 3'h2; + assign _0400_ = _0401_ ? _0398_ : \wbdbg.recieve_data [23:16]; + assign _0402_ = _0403_ ? \wbdbg.uart_rx.o_data : \wbdbg.recieve_data [31:24]; + assign _0403_ = \wbdbg.recieve_state == 3'h1; + assign _0404_ = _0405_ ? _0402_ : \wbdbg.recieve_data [31:24]; + assign _0406_ = _0407_ ? \wbdbg.uart_rx.o_data : \wbdbg.recieve_data [39:32]; + assign _0407_ = ! \wbdbg.recieve_state ; + assign _0408_ = _0409_ ? _0406_ : \wbdbg.recieve_data [39:32]; + assign _0410_ = _0411_ ? 1'h1 : 1'h0; + assign _0412_ = _0413_ ? _0410_ : 1'h0; + assign _0414_ = _0415_ ? _0412_ : 1'h0; + assign _0416_ = _0417_ ? _0107_[25:0] : \wbdbg.drop_timer ; + assign _0418_ = _0419_ ? 26'h17d7840 : _0416_; + assign _0420_ = _0421_ ? 3'h0 : \wbdbg.recieve_state ; + assign _0422_ = _0423_ ? _0420_ : \wbdbg.recieve_state ; + assign _0424_ = _0425_ ? 3'h0 : _0059_[2:0]; + assign _0426_ = _0427_ ? _0424_ : _0422_; + assign _0428_ = _0130_ ? 1'h0 : 1'h1; + assign _0430_ = _0431_ ? 1'h0 : _0428_; + assign _0432_ = _0433_ ? _0430_ : 1'h0; + assign _0434_ = _0435_ ? _0432_ : 1'h0; + assign _0436_ = _0130_ ? \wbdbg.cmd_fifo_wr_data : { \wbdbg.recieve_data [35:8], \wbdbg.uart_rx.o_data }; + assign _0438_ = _0439_ ? \wbdbg.cmd_fifo_wr_data : _0436_; + assign _0440_ = _0441_ ? _0438_ : \wbdbg.cmd_fifo_wr_data ; + assign _0442_ = _0443_ ? _0440_ : \wbdbg.cmd_fifo_wr_data ; + assign _0444_ = _0445_ ? 1'h1 : 1'h0; + assign _0446_ = _0447_ ? 1'h1 : 1'h0; + assign _0448_ = _0449_ ? \wbdbg.cmd_fifo.o_rd_data : \wbdbg.cmd_data ; + assign _0450_ = _0451_ ? 36'hfffffffff : 36'h000000000; + assign _0452_ = _0453_ ? 36'hxxxxxxxxx : _0450_; + assign _0454_ = _0455_ ? \wbdbg.cmd_fifo_wr_data : 36'hxxxxxxxxx; + assign _0456_ = _0457_ ? 36'hxxxxxxxxx : _0454_; + assign _0458_ = _0459_ ? \wbdbg.cmd_fifo.wr_ptr : 4'hx; + assign _0460_ = _0461_ ? 4'hx : _0458_; + assign _0462_ = _0463_ ? 36'h000000000 : _0125_; + assign _0464_ = _0465_ ? 36'hxxxxxxxxx : _0124_; + assign _0466_ = _0467_ ? 4'hx : _0123_; + assign _0468_ = _0469_ ? _0126_[3:0] : \wbdbg.cmd_fifo.wr_ptr ; + assign _0470_ = _0471_ ? 4'h0 : _0468_; + assign _0472_ = _0473_ ? _0102_ : 1'h0; + assign _0474_ = _0475_ ? 1'h0 : _0472_; + assign _0476_ = _0477_ ? _0127_[3:0] : \wbdbg.cmd_fifo.rd_ptr ; + assign _0478_ = _0479_ ? 4'h0 : _0476_; + assign _0480_ = _0481_ ? _0135_ : \wbdbg.cmd_fifo.o_rd_data ; + assign _0482_ = _0483_ ? \wbdbg.cmd_fifo.o_rd_data : _0480_; + assign _0484_ = _0485_ ? _0128_[4:0] : \wbdbg.cmd_fifo.len ; + assign _0486_ = _0487_ ? _0144_[4:0] : _0484_; + assign _0488_ = _0489_ ? 5'h00 : _0486_; + assign _0490_ = _0491_ ? 36'hfffffffff : 36'h000000000; + assign _0492_ = _0493_ ? 36'hxxxxxxxxx : _0490_; + assign _0494_ = _0495_ ? \wbdbg.resp_fifo_wr_data : 36'hxxxxxxxxx; + assign _0496_ = _0497_ ? 36'hxxxxxxxxx : _0494_; + assign _0498_ = _0499_ ? \wbdbg.resp_fifo.wr_ptr : 4'hx; + assign _0500_ = _0501_ ? 4'hx : _0498_; + assign _0502_ = _0503_ ? 36'h000000000 : _0162_; + assign _0504_ = _0505_ ? 36'hxxxxxxxxx : _0161_; + assign _0506_ = _0507_ ? 4'hx : _0160_; + assign _0508_ = _0509_ ? _0163_[3:0] : \wbdbg.resp_fifo.wr_ptr ; + assign _0510_ = _0511_ ? 4'h0 : _0508_; + assign _0512_ = _0513_ ? _0092_ : 1'h0; + assign _0514_ = _0515_ ? 1'h0 : _0512_; + assign _0516_ = _0517_ ? _0164_[3:0] : \wbdbg.resp_fifo.rd_ptr ; + assign _0518_ = _0519_ ? 4'h0 : _0516_; + assign _0520_ = _0521_ ? _0172_ : \wbdbg.resp_fifo.o_rd_data ; + assign _0522_ = _0523_ ? \wbdbg.resp_fifo.o_rd_data : _0520_; + assign _0524_ = _0525_ ? _0165_[4:0] : \wbdbg.resp_fifo.len ; + assign _0526_ = _0527_ ? _0181_[4:0] : _0524_; + assign _0528_ = _0529_ ? 5'h00 : _0526_; + assign _0530_ = _0531_ ? \wbdbg.uart_rx.o_data : _0218_; + assign _0532_ = _0533_ ? _0530_ : 8'hxx; + assign _0534_ = _0535_ ? 8'hxx : _0532_; + assign _0536_ = _0537_ ? _0208_ : _0223_; + assign _0538_ = _0539_ ? _0536_ : 32'hxxxxxxxx; + assign _0540_ = _0541_ ? 32'hxxxxxxxx : _0538_; + assign _0542_ = _0543_ ? _0206_ : _0220_; + assign _0544_ = _0545_ ? _0542_ : 8'hxx; + assign _0546_ = _0547_ ? 8'hxx : _0544_; + assign _0548_ = _0549_ ? _0207_ : _0219_; + assign _0550_ = _0551_ ? _0548_ : 8'hxx; + assign _0552_ = _0553_ ? 8'hxx : _0550_; + assign _0554_ = _0555_ ? _0202_ : \wbdbg.uart_rx.o_data ; + assign _0556_ = _0557_ ? 8'hxx : _0554_; + assign _0558_ = _0559_ ? _0201_ : _0208_; + assign _0560_ = _0561_ ? 32'hxxxxxxxx : _0558_; + assign _0562_ = _0563_ ? _0199_ : _0206_; + assign _0564_ = _0565_ ? 8'hxx : _0562_; + assign _0566_ = _0567_ ? _0200_ : _0207_; + assign _0568_ = _0569_ ? 8'hxx : _0566_; + assign _0570_ = _0571_ ? \wbdbg.uart_rx.o_data : _0198_; + assign _0572_ = _0573_ ? _0208_ : _0197_; + assign _0574_ = _0575_ ? _0206_ : _0195_; + assign _0576_ = _0577_ ? _0207_ : _0196_; + assign _0578_ = _0579_ ? 10'h00a : 10'h08b; + assign _0580_ = _0581_ ? _0578_ : _0224_[9:0]; + assign _0582_ = uart_rx_sync[2] ? 10'h00a : 10'h0d0; + assign _0584_ = _0585_ ? _0582_ : _0580_; + assign _0586_ = _0587_ ? 1'h1 : 1'h0; + assign _0588_ = _0589_ ? _0586_ : 1'h0; + assign _0590_ = _0591_ ? _0588_ : 1'h0; + assign _0592_ = _0593_ ? 1'h0 : _0590_; + assign _0594_ = _0595_ ? 4'h0 : _0203_[3:0]; + assign _0596_ = _0597_ ? _0594_ : \wbdbg.uart_rx.state ; + assign _0598_ = uart_rx_sync[2] ? \wbdbg.uart_rx.state : 4'h1; + assign _0600_ = _0601_ ? _0598_ : _0596_; + assign _0602_ = _0603_ ? 1'h1 : _0242_; + assign _0604_ = _0605_ ? 1'hx : _0602_; + assign _0606_ = _0607_ ? 1'hx : _0604_; + assign _0608_ = _0609_ ? 1'h0 : _0232_; + assign _0610_ = _0611_ ? 1'hx : _0608_; + assign _0612_ = _0613_ ? 1'h1 : _0231_; + assign _0614_ = _0615_ ? 10'h08a : 10'h08b; + assign _0616_ = _0617_ ? 10'h00a : _0614_; + assign _0618_ = _0619_ ? _0616_ : _0243_[9:0]; + assign _0620_ = _0621_ ? 10'h08b : 10'h00a; + assign _0622_ = _0623_ ? _0620_ : _0618_; + assign _0624_ = _0625_ ? \wbdbg.uart_tx_data : \wbdbg.uart_tx.data_send ; + assign _0626_ = _0627_ ? _0624_ : \wbdbg.uart_tx.data_send ; + assign _0628_ = _0629_ ? 4'h0 : _0233_[3:0]; + assign _0630_ = _0631_ ? _0628_ : \wbdbg.uart_tx.state ; + assign _0632_ = _0633_ ? 4'h1 : \wbdbg.uart_tx.state ; + assign _0634_ = _0635_ ? _0632_ : _0630_; + assign _0636_ = _0637_ ? 1'h1 : \wbdbg.wbdbgbusmaster.o_wb_stb ; + assign _0638_ = _0639_ ? \wbdbg.wbdbgbusmaster.o_wb_stb : _0636_; + assign _0642_ = _0643_ ? 1'h0 : _0638_; + assign _0644_ = _0645_ ? 1'h0 : _0642_; + assign _0646_ = _0647_ ? 1'h1 : \wbdbg.wbdbgbusmaster.o_wb_cyc ; + assign _0648_ = _0649_ ? 1'h0 : \wbdbg.wbdbgbusmaster.o_wb_cyc ; + assign _0650_ = _0651_ ? _0648_ : _0646_; + assign _0652_ = _0653_ ? \wbdbg.wbdbgbusmaster.o_wb_cyc : _0650_; + assign _0654_ = _0655_ ? 1'h0 : _0652_; + assign _0656_ = _0657_ ? _0268_ : \wbdbg.wbdbgbusmaster.addr_inc ; + assign _0658_ = _0659_ ? _0656_ : \wbdbg.wbdbgbusmaster.addr_inc ; + assign _0660_ = _0661_ ? _0260_ : \wbdbg.wbdbgbusmaster.o_wb_addr ; + assign _0662_ = _0663_ ? \wbdbg.cmd_data [31:0] : \wbdbg.wbdbgbusmaster.o_wb_addr ; + assign _0664_ = _0665_ ? _0662_ : _0660_; + assign _0666_ = \wbdbg.wbdbgbusmaster.o_wb_cyc ? \wbdbg.wbdbgbusmaster.o_wb_we : _0272_; + assign _0670_ = _0671_ ? 1'h1 : 1'h0; + assign _0672_ = _0673_ ? 1'h1 : _0670_; + assign _0676_ = _0677_ ? 1'h1 : _0674_; + assign _0678_ = _0679_ ? 36'h300000000 : \wbdbg.wbdbgbusmaster.o_resp_data ; + assign _0680_ = _0681_ ? 36'h200000000 : { 24'h100000, chip_outputs }; + assign _0682_ = _0683_ ? _0680_ : _0678_; + assign _0686_ = _0687_ ? 36'h500000000 : _0684_; + assign _0688_ = _0689_ ? 1'h1 : 1'h0; + assign _0690_ = _0691_ ? data_in : { 20'h00000, chip_outputs }; + assign _0692_ = _0693_ ? _0690_ : data_in; + assign _0694_ = _0695_ ? \wbdbg.wbdbgbusmaster.o_wb_data [12] : chip_reset; + assign _0696_ = _0697_ ? _0694_ : chip_reset; + assign _0698_ = _0699_ ? \wbdbg.wbdbgbusmaster.o_wb_data [13] : chip_clock; + assign _0700_ = _0701_ ? _0698_ : chip_clock; + assign _0702_ = _0703_ ? \wbdbg.wbdbgbusmaster.o_wb_data [11:0] : chip_inputs; + assign _0704_ = _0705_ ? _0702_ : chip_inputs; + SB_PLL40_CORE #( + .DIVF(7'h28), + .DIVQ(3'h6), + .DIVR(4'h3), + .FEEDBACK_PATH("SIMPLE"), + .FILTER_RANGE(3'h2) + ) uut ( + .BYPASS(1'h0), + .PLLOUTCORE(clk), + .REFERENCECLK(clk100), + .RESETB(1'h1) + ); + assign _0006_ = 32'd0; + assign _0007_ = 32'd0; + assign _0008_ = 32'd0; + assign _0009_ = 32'd0; + assign _0010_ = 32'd0; + assign _0011_ = 32'd0; + assign \wbdbg.uart_rx.i_clk = \wbdbg.i_clk ; + assign \wbdbg.uart_rx.i_in = \wbdbg.i_rx ; + assign \wbdbg.uart_rx_valid = \wbdbg.uart_rx.o_valid ; + assign \wbdbg.uart_rx_data = \wbdbg.uart_rx.o_data ; + assign \wbdbg.uart_tx.o_ready = _0234_; + assign \wbdbg.uart_tx.i_clk = \wbdbg.i_clk ; + assign \wbdbg.uart_tx.i_valid = \wbdbg.uart_tx_valid ; + assign \wbdbg.uart_tx.i_data = \wbdbg.uart_tx_data ; + assign \wbdbg.o_tx = \wbdbg.uart_tx.o_out ; + assign \wbdbg.uart_tx_ready = \wbdbg.uart_tx.o_ready ; + assign \wbdbg.wbdbgbusmaster.o_cmd_ready = _0281_; + assign \wbdbg.wbdbgbusmaster.cmd_recv = _0269_; + assign \wbdbg.wbdbgbusmaster.cmd_inst = \wbdbg.wbdbgbusmaster.i_cmd_data [35:32]; + assign \wbdbg.wbdbgbusmaster.cmd_data = \wbdbg.wbdbgbusmaster.i_cmd_data [31:0]; + assign \wbdbg.wbdbgbusmaster.i_clk = \wbdbg.i_clk ; + assign \wbdbg.wbdbgbusmaster.i_wb_data = \wbdbg.i_wb_data ; + assign \wbdbg.wbdbgbusmaster.i_wb_stall = \wbdbg.i_wb_stall ; + assign \wbdbg.wbdbgbusmaster.i_wb_err = \wbdbg.i_wb_err ; + assign \wbdbg.wbdbgbusmaster.i_wb_ack = \wbdbg.i_wb_ack ; + assign \wbdbg.o_wb_data = \wbdbg.wbdbgbusmaster.o_wb_data ; + assign \wbdbg.o_wb_addr = \wbdbg.wbdbgbusmaster.o_wb_addr ; + assign \wbdbg.o_wb_we = \wbdbg.wbdbgbusmaster.o_wb_we ; + assign \wbdbg.o_wb_stb = \wbdbg.wbdbgbusmaster.o_wb_stb ; + assign \wbdbg.o_wb_cyc = \wbdbg.wbdbgbusmaster.o_wb_cyc ; + assign \wbdbg.resp_data = \wbdbg.wbdbgbusmaster.o_resp_data ; + assign \wbdbg.resp_valid = \wbdbg.wbdbgbusmaster.o_resp_valid ; + assign \wbdbg.wbdbgbusmaster.i_cmd_data = \wbdbg.cmd_data ; + assign \wbdbg.cmd_ready = \wbdbg.wbdbgbusmaster.o_cmd_ready ; + assign \wbdbg.wbdbgbusmaster.i_cmd_valid = \wbdbg.cmd_valid ; + assign \wbdbg.wbdbgbusmaster.i_cmd_reset = \wbdbg.cmd_reset ; + assign \wbdbg.cmd_fifo.o_empty = _0129_; + assign \wbdbg.cmd_fifo.o_full = _0130_; + assign \wbdbg.cmd_fifo.i_rst = \wbdbg.cmd_reset ; + assign \wbdbg.cmd_fifo.i_clk = \wbdbg.i_clk ; + assign \wbdbg.cmd_fifo_full = \wbdbg.cmd_fifo.o_full ; + assign \wbdbg.cmd_fifo_empty = \wbdbg.cmd_fifo.o_empty ; + assign \wbdbg.cmd_fifo.i_wr_data = \wbdbg.cmd_fifo_wr_data ; + assign \wbdbg.cmd_fifo.i_wr_en = \wbdbg.cmd_fifo_wr_en ; + assign \wbdbg.cmd_fifo_rd_valid = \wbdbg.cmd_fifo.o_rd_valid ; + assign \wbdbg.cmd_fifo_rd_data = \wbdbg.cmd_fifo.o_rd_data ; + assign \wbdbg.cmd_fifo.i_rd_en = \wbdbg.cmd_fifo_rd_en ; + assign \wbdbg.resp_fifo.o_empty = _0166_; + assign \wbdbg.resp_fifo.o_full = _0167_; + assign \wbdbg.resp_fifo.i_rst = \wbdbg.cmd_reset ; + assign \wbdbg.resp_fifo.i_clk = \wbdbg.i_clk ; + assign \wbdbg.resp_fifo_full = \wbdbg.resp_fifo.o_full ; + assign \wbdbg.resp_fifo_empty = \wbdbg.resp_fifo.o_empty ; + assign \wbdbg.resp_fifo.i_wr_data = \wbdbg.resp_fifo_wr_data ; + assign \wbdbg.resp_fifo.i_wr_en = \wbdbg.resp_fifo_wr_en ; + assign \wbdbg.resp_fifo_rd_valid = \wbdbg.resp_fifo.o_rd_valid ; + assign \wbdbg.resp_fifo_rd_data = \wbdbg.resp_fifo.o_rd_data ; + assign \wbdbg.resp_fifo.i_rd_en = \wbdbg.resp_fifo_rd_en ; + assign \wbdbg.i_clk = clk; + assign \wbdbg.i_interrupt_4 = _0011_[0]; + assign \wbdbg.i_interrupt_3 = _0010_[0]; + assign \wbdbg.i_interrupt_2 = _0009_[0]; + assign \wbdbg.i_interrupt_1 = _0008_[0]; + assign \wbdbg.i_wb_data = { 20'h00000, chip_outputs }; + assign \wbdbg.i_wb_stall = _0007_[0]; + assign \wbdbg.i_wb_err = _0006_[0]; + assign \wbdbg.i_wb_ack = wb_ack; + assign data_out = \wbdbg.o_wb_data ; + assign wb_we = \wbdbg.o_wb_we ; + assign wb_stb = \wbdbg.o_wb_stb ; + assign wb_cyc = \wbdbg.o_wb_cyc ; + assign \wbdbg.i_rx = uart_rx_sync[2]; + assign uart_tx = \wbdbg.o_tx ; + assign _0277_ = \wbdbg.cmd_reset ; + assign _0276_ = 1'h1; + assign _0282_ = 1'h1; + assign _0271_ = \wbdbg.wbdbgbusmaster.o_wb_stb ; + assign _0273_ = 1'h0; + assign _0284_ = 1'h1; + assign _0213_ = \wbdbg.uart_rx.i_in ; + assign _0204_ = { 7'h00, uart_rx_sync[2] }; + assign _0071_ = 1'h0; + assign _0070_ = 1'h0; + assign _0069_ = 1'h0; + assign _0068_ = 1'h0; + assign _0061_ = _0060_; + assign _0106_ = _0101_; + assign _0221_ = _0222_; + assign _0238_ = _0241_; + assign _0237_ = _0241_; + assign _0235_ = _0239_; + assign _0265_ = _0268_; + assign _0264_ = _0268_; + assign _0263_ = _0267_; + assign _0262_ = _0266_; + assign _0281_ = _0283_; + assign _0234_ = _0239_; + assign _0143_ = _0100_; + assign _0142_ = _0103_; + assign _0141_ = _0102_; + assign _0139_ = _0102_; + assign _0180_ = _0087_; + assign _0179_ = _0094_; + assign _0178_ = _0092_; + assign _0176_ = _0092_; + assign _0215_ = _0216_; + assign _0279_ = _0280_; + assign _0057_ = 1'h0; + assign _0039_ = 1'h0; + assign _0040_ = 1'h0; + assign _0036_ = 1'h0; + assign _0038_ = 1'h0; + assign _0037_ = 36'h000000000; + assign _0052_ = 1'h0; + assign _0054_ = 1'h0; + assign _0053_ = 36'h000000000; + assign _0055_ = 40'h0000000000; + assign _0056_ = 3'h0; + assign _0042_ = 1'h0; + assign _0044_ = 1'h0; + assign _0046_ = 1'h0; + assign _0048_ = 1'h0; + assign _0043_ = 1'h0; + assign _0045_ = 1'h0; + assign _0047_ = 1'h0; + assign _0049_ = 1'h0; + assign _0025_ = 1'h0; + assign _0023_ = 1'h0; + assign _0021_ = 1'h0; + assign _0019_ = 1'h0; + assign _0050_ = 40'h0000000000; + assign _0051_ = 3'h0; + assign _0041_ = 26'h17d7840; + assign _0120_ = 1'h0; + assign _0122_ = 4'h0; + assign _0121_ = 4'h0; + assign _0119_ = 5'h00; + assign _0110_ = _0118_; + assign _0109_ = _0117_; + assign _0108_ = _0116_; + assign _0157_ = 1'h0; + assign _0159_ = 4'h0; + assign _0158_ = 4'h0; + assign _0156_ = 5'h00; + assign _0147_ = _0155_; + assign _0146_ = _0154_; + assign _0145_ = _0153_; + assign _0194_ = 4'h0; + assign _0187_ = _0193_; + assign _0185_ = _0193_; + assign _0184_ = _0192_; + assign _0182_ = _0190_; + assign _0183_ = _0191_; + assign _0227_ = _0229_; + assign _0230_ = 4'h0; + assign _0254_ = 1'h0; + assign _0256_ = 1'h0; + assign _0258_ = 1'h0; + assign _0259_ = 1'h0; + assign _0255_ = 32'd0; + assign _0257_ = 32'd0; + assign _0253_ = 1'h0; + assign _0004_ = { uart_rx_sync[1:0], uart_rx }; + assign _0287_ = _0067_; + assign _0031_ = _0286_; + assign _0289_ = _0067_; + assign _0030_ = _0288_; + assign _0291_ = _0078_; + assign _0029_ = _0290_; + assign _0293_ = _0079_; + assign _0295_ = _0061_; + assign _0035_ = _0294_; + assign _0297_ = _0071_; + assign _0299_ = \wbdbg.interrupt_4_rising ; + assign _0301_ = \wbdbg.interrupt_3_rising ; + assign _0303_ = \wbdbg.interrupt_2_rising ; + assign _0305_ = \wbdbg.interrupt_1_rising ; + assign _0307_ = \wbdbg.resp_fifo_rd_en ; + assign _0309_ = \wbdbg.resp_fifo_rd_valid ; + assign _0311_ = _0061_; + assign _0026_ = _0310_; + assign _0313_ = _0070_; + assign _0315_ = \wbdbg.interrupt_3_rising ; + assign _0317_ = \wbdbg.interrupt_2_rising ; + assign _0319_ = \wbdbg.interrupt_1_rising ; + assign _0321_ = \wbdbg.resp_fifo_rd_en ; + assign _0323_ = \wbdbg.resp_fifo_rd_valid ; + assign _0325_ = _0061_; + assign _0024_ = _0324_; + assign _0327_ = _0069_; + assign _0329_ = \wbdbg.interrupt_2_rising ; + assign _0331_ = \wbdbg.interrupt_1_rising ; + assign _0333_ = \wbdbg.resp_fifo_rd_en ; + assign _0335_ = \wbdbg.resp_fifo_rd_valid ; + assign _0337_ = _0061_; + assign _0022_ = _0336_; + assign _0339_ = _0068_; + assign _0341_ = \wbdbg.interrupt_1_rising ; + assign _0343_ = \wbdbg.resp_fifo_rd_en ; + assign _0345_ = \wbdbg.resp_fifo_rd_valid ; + assign _0347_ = _0061_; + assign _0020_ = _0346_; + assign _0349_ = _0062_; + assign _0351_ = _0079_; + assign _0353_ = \wbdbg.interrupt_4_rising ; + assign _0355_ = \wbdbg.interrupt_3_rising ; + assign _0357_ = \wbdbg.interrupt_2_rising ; + assign _0359_ = \wbdbg.interrupt_1_rising ; + assign _0361_ = \wbdbg.resp_fifo_rd_en ; + assign _0363_ = \wbdbg.resp_fifo_rd_valid ; + assign _0365_ = _0061_; + assign _0033_ = _0364_; + assign _0367_ = \wbdbg.interrupt_4_rising ; + assign _0369_ = \wbdbg.interrupt_3_rising ; + assign _0371_ = \wbdbg.interrupt_2_rising ; + assign _0373_ = \wbdbg.interrupt_1_rising ; + assign _0375_ = \wbdbg.resp_fifo_rd_en ; + assign _0377_ = \wbdbg.resp_fifo_rd_valid ; + assign _0379_ = _0061_; + assign _0032_ = _0378_; + assign _0387_ = _0079_; + assign _0389_ = _0061_; + assign _0034_ = _0388_; + assign _0393_ = \wbdbg.uart_rx_valid ; + assign _0027_[15:8] = _0392_; + assign _0397_ = \wbdbg.uart_rx_valid ; + assign _0027_[7:0] = _0396_; + assign _0401_ = \wbdbg.uart_rx_valid ; + assign _0027_[23:16] = _0400_; + assign _0405_ = \wbdbg.uart_rx_valid ; + assign _0027_[31:24] = _0404_; + assign _0409_ = \wbdbg.uart_rx_valid ; + assign _0027_[39:32] = _0408_; + assign _0411_ = _0064_; + assign _0413_ = _0063_; + assign _0415_ = \wbdbg.uart_rx_valid ; + assign _0016_ = _0414_; + assign _0417_ = _0066_; + assign _0419_ = \wbdbg.uart_rx_valid ; + assign _0018_ = _0418_; + assign _0421_ = _0065_; + assign _0423_ = _0066_; + assign _0425_ = _0063_; + assign _0427_ = \wbdbg.uart_rx_valid ; + assign _0028_ = _0426_; + assign _0429_ = _0100_; + assign _0431_ = _0064_; + assign _0433_ = _0063_; + assign _0435_ = \wbdbg.uart_rx_valid ; + assign _0015_ = _0434_; + assign _0437_ = _0100_; + assign _0439_ = _0064_; + assign _0441_ = _0063_; + assign _0443_ = \wbdbg.uart_rx_valid ; + assign _0014_ = _0442_; + assign _0445_ = _0084_; + assign _0013_ = _0444_; + assign _0447_ = _0086_; + assign _0017_ = _0446_; + assign _0449_ = _0086_; + assign _0012_ = _0448_; + assign _0451_ = \wbdbg.cmd_fifo.i_wr_en ; + assign _0453_ = \wbdbg.cmd_fifo.i_rst ; + assign _0125_ = _0452_; + assign _0455_ = \wbdbg.cmd_fifo.i_wr_en ; + assign _0457_ = \wbdbg.cmd_fifo.i_rst ; + assign _0124_ = _0456_; + assign _0459_ = \wbdbg.cmd_fifo.i_wr_en ; + assign _0461_ = \wbdbg.cmd_fifo.i_rst ; + assign _0123_ = _0460_; + assign _0463_ = \wbdbg.cmd_fifo.i_rst ; + assign _0118_ = _0462_; + assign _0465_ = \wbdbg.cmd_fifo.i_rst ; + assign _0117_ = _0464_; + assign _0467_ = \wbdbg.cmd_fifo.i_rst ; + assign _0116_ = _0466_; + assign _0469_ = \wbdbg.cmd_fifo.i_wr_en ; + assign _0471_ = \wbdbg.cmd_fifo.i_rst ; + assign _0115_ = _0470_; + assign _0473_ = \wbdbg.cmd_fifo.i_rd_en ; + assign _0475_ = \wbdbg.cmd_fifo.i_rst ; + assign _0113_ = _0474_; + assign _0477_ = \wbdbg.cmd_fifo.i_rd_en ; + assign _0479_ = \wbdbg.cmd_fifo.i_rst ; + assign _0114_ = _0478_; + assign _0481_ = \wbdbg.cmd_fifo.i_rd_en ; + assign _0483_ = \wbdbg.cmd_fifo.i_rst ; + assign _0112_ = _0482_; + assign _0485_ = _0134_; + assign _0487_ = _0132_; + assign _0489_ = \wbdbg.cmd_fifo.i_rst ; + assign _0111_ = _0488_; + assign _0491_ = \wbdbg.resp_fifo.i_wr_en ; + assign _0493_ = \wbdbg.resp_fifo.i_rst ; + assign _0162_ = _0492_; + assign _0495_ = \wbdbg.resp_fifo.i_wr_en ; + assign _0497_ = \wbdbg.resp_fifo.i_rst ; + assign _0161_ = _0496_; + assign _0499_ = \wbdbg.resp_fifo.i_wr_en ; + assign _0501_ = \wbdbg.resp_fifo.i_rst ; + assign _0160_ = _0500_; + assign _0503_ = \wbdbg.resp_fifo.i_rst ; + assign _0155_ = _0502_; + assign _0505_ = \wbdbg.resp_fifo.i_rst ; + assign _0154_ = _0504_; + assign _0507_ = \wbdbg.resp_fifo.i_rst ; + assign _0153_ = _0506_; + assign _0509_ = \wbdbg.resp_fifo.i_wr_en ; + assign _0511_ = \wbdbg.resp_fifo.i_rst ; + assign _0152_ = _0510_; + assign _0513_ = \wbdbg.resp_fifo.i_rd_en ; + assign _0515_ = \wbdbg.resp_fifo.i_rst ; + assign _0150_ = _0514_; + assign _0517_ = \wbdbg.resp_fifo.i_rd_en ; + assign _0519_ = \wbdbg.resp_fifo.i_rst ; + assign _0151_ = _0518_; + assign _0521_ = \wbdbg.resp_fifo.i_rd_en ; + assign _0523_ = \wbdbg.resp_fifo.i_rst ; + assign _0149_ = _0522_; + assign _0525_ = _0171_; + assign _0527_ = _0169_; + assign _0529_ = \wbdbg.resp_fifo.i_rst ; + assign _0148_ = _0528_; + assign _0531_ = _0212_; + assign _0533_ = _0211_; + assign _0535_ = _0209_; + assign _0202_ = _0534_; + assign _0537_ = _0212_; + assign _0539_ = _0211_; + assign _0541_ = _0209_; + assign _0201_ = _0540_; + assign _0543_ = _0212_; + assign _0545_ = _0211_; + assign _0547_ = _0209_; + assign _0199_ = _0546_; + assign _0549_ = _0212_; + assign _0551_ = _0211_; + assign _0553_ = _0209_; + assign _0200_ = _0552_; + assign _0555_ = _0211_; + assign _0557_ = _0209_; + assign _0198_ = _0556_; + assign _0559_ = _0211_; + assign _0561_ = _0209_; + assign _0197_ = _0560_; + assign _0563_ = _0211_; + assign _0565_ = _0209_; + assign _0195_ = _0564_; + assign _0567_ = _0211_; + assign _0569_ = _0209_; + assign _0196_ = _0568_; + assign _0571_ = _0209_; + assign _0193_ = _0570_; + assign _0573_ = _0209_; + assign _0192_ = _0572_; + assign _0575_ = _0209_; + assign _0190_ = _0574_; + assign _0577_ = _0209_; + assign _0191_ = _0576_; + assign _0579_ = _0212_; + assign _0581_ = _0211_; + assign _0583_ = _0210_; + assign _0585_ = _0209_; + assign _0186_ = _0584_; + assign _0587_ = _0213_; + assign _0589_ = _0212_; + assign _0591_ = _0211_; + assign _0593_ = _0209_; + assign _0188_ = _0592_; + assign _0595_ = _0212_; + assign _0597_ = _0211_; + assign _0599_ = _0210_; + assign _0601_ = _0209_; + assign _0189_ = _0600_; + assign _0603_ = _0241_; + assign _0605_ = _0240_; + assign _0607_ = _0239_; + assign _0232_ = _0606_; + assign _0609_ = _0240_; + assign _0611_ = _0239_; + assign _0231_ = _0610_; + assign _0613_ = _0239_; + assign _0229_ = _0612_; + assign _0615_ = _0238_; + assign _0617_ = _0237_; + assign _0619_ = _0236_; + assign _0621_ = \wbdbg.uart_tx.i_valid ; + assign _0623_ = _0235_; + assign _0225_ = _0622_; + assign _0625_ = \wbdbg.uart_tx.i_valid ; + assign _0627_ = _0235_; + assign _0226_ = _0626_; + assign _0629_ = _0237_; + assign _0631_ = _0236_; + assign _0633_ = \wbdbg.uart_tx.i_valid ; + assign _0635_ = _0235_; + assign _0228_ = _0634_; + assign _0637_ = _0270_; + assign _0639_ = \wbdbg.wbdbgbusmaster.o_wb_cyc ; + assign _0641_ = _0276_; + assign _0643_ = \wbdbg.wbdbgbusmaster.o_wb_stb ; + assign _0645_ = _0277_; + assign _0251_ = _0644_; + assign _0647_ = _0270_; + assign _0649_ = \wbdbg.wbdbgbusmaster.i_wb_ack ; + assign _0651_ = \wbdbg.wbdbgbusmaster.o_wb_cyc ; + assign _0653_ = \wbdbg.wbdbgbusmaster.o_wb_stb ; + assign _0655_ = _0277_; + assign _0249_ = _0654_; + assign _0657_ = _0279_; + assign _0659_ = \wbdbg.wbdbgbusmaster.cmd_recv ; + assign _0245_ = _0658_; + assign _0661_ = _0271_; + assign _0663_ = _0279_; + assign _0665_ = \wbdbg.wbdbgbusmaster.cmd_recv ; + assign _0248_ = _0664_; + assign _0667_ = _0283_; + assign _0252_ = _0666_; + assign _0669_ = _0284_; + assign _0250_ = _0668_; + assign _0671_ = _0275_; + assign _0673_ = _0274_; + assign _0675_ = \wbdbg.wbdbgbusmaster.i_wb_err ; + assign _0677_ = \wbdbg.wbdbgbusmaster.i_cmd_reset ; + assign _0247_ = _0676_; + assign _0679_ = _0275_; + assign _0681_ = \wbdbg.wbdbgbusmaster.o_wb_we ; + assign _0683_ = _0274_; + assign _0685_ = \wbdbg.wbdbgbusmaster.i_wb_err ; + assign _0687_ = \wbdbg.wbdbgbusmaster.i_cmd_reset ; + assign _0246_ = _0686_; + assign _0689_ = _0285_; + assign _0005_ = _0688_; + assign _0691_ = wb_we; + assign _0693_ = _0285_; + assign _0003_ = _0692_; + assign _0695_ = wb_we; + assign _0697_ = _0285_; + assign _0002_ = _0696_; + assign _0699_ = wb_we; + assign _0701_ = _0285_; + assign _0000_ = _0700_; + assign _0703_ = wb_we; + assign _0705_ = _0285_; + assign _0001_ = _0704_; + assign \wbdbg.uart_tx.o_out = _0612_; + assign _0296_ = \wbdbg.interrupt_4_rising ; + assign _0312_ = \wbdbg.interrupt_3_rising ; + assign _0326_ = \wbdbg.interrupt_2_rising ; + assign _0338_ = \wbdbg.interrupt_1_rising ; + assign _0668_ = \wbdbg.cmd_data [31:0]; + assign _0674_ = _0672_; + assign _0684_ = _0682_; + assign _0640_ = 1'h0; +endmodule diff --git a/designs/d29_bwilhelm_i8008/original_sv/hex_to_sevenseg.sv b/designs/d29_bwilhelm_i8008/original_sv/hex_to_sevenseg.sv new file mode 100644 index 0000000..fbacaef --- /dev/null +++ b/designs/d29_bwilhelm_i8008/original_sv/hex_to_sevenseg.sv @@ -0,0 +1,26 @@ +module hex_to_sevenseg ( + input logic [3:0] hexdigit, + output logic [7:0] seg +); + + always_comb begin + seg = '1; + if (hexdigit == 4'h0) seg = 8'b1100_0000; + if (hexdigit == 4'h1) seg = 8'b1111_1001; + if (hexdigit == 4'h2) seg = 8'b1010_0100; + if (hexdigit == 4'h3) seg = 8'b1011_0000; + if (hexdigit == 4'h4) seg = 8'b1001_1001; + if (hexdigit == 4'h5) seg = 8'b1001_0010; + if (hexdigit == 4'h6) seg = 8'b1000_0010; + if (hexdigit == 4'h7) seg = 8'b1111_1000; + if (hexdigit == 4'h8) seg = 8'b1000_0000; + if (hexdigit == 4'h9) seg = 8'b1001_0000; + if (hexdigit == 4'hA) seg = 8'b1000_1000; + if (hexdigit == 4'hB) seg = 8'b1000_0011; + if (hexdigit == 4'hC) seg = 8'b1100_0110; + if (hexdigit == 4'hD) seg = 8'b1010_0001; + if (hexdigit == 4'hE) seg = 8'b1000_0110; + if (hexdigit == 4'hF) seg = 8'b1000_1110; + end + +endmodule diff --git a/designs/d29_bwilhelm_i8008/original_sv/i8008_core.sv b/designs/d29_bwilhelm_i8008/original_sv/i8008_core.sv new file mode 100644 index 0000000..5cba101 --- /dev/null +++ b/designs/d29_bwilhelm_i8008/original_sv/i8008_core.sv @@ -0,0 +1,944 @@ +`include "internal_defines.vh" +`include "i8008_isa.vh" + +`default_nettype none + +module top ( + input logic clk100, // 100MHz clock + input logic reset_n, // Active-low reset + + input logic uart_rx, + output logic uart_tx, + + output logic [7:0] base_led, // LEDs on the far right side of the board + output logic [23:0] led, // LEDs in the middle of the board + + input logic [23:0] sw, // The tiny slide-switches + + output logic [3:0] display_sel, // Select between the 4 segments + output logic [7:0] display // Seven-segment display +); + + logic clk, rst; + logic [11:0] chip_inputs, chip_outputs; + logic [7:0] D_in, D_out; + logic INTR, READY, Sync; + state_t state; + logic [1:0] display_cnt; + logic [3:0] disp_arr [4]; + + debug_harness dbg ( + .uart_rx, .uart_tx, + + .chip_inputs, + .chip_outputs, + + .chip_clock(clk), + .chip_reset(rst), + + .clk100 + ); + + // // 100MHz -> 25MHz + // SB_PLL40_CORE #( + // .FEEDBACK_PATH("SIMPLE"), + // .DIVR(4'b0000), // DIVR = 0 + // .DIVF(7'b0000111), // DIVF = 7 + // .DIVQ(3'b100), // DIVQ = 4 + // .FILTER_RANGE(3'b101) // FILTER_RANGE = 5 + // ) pll ( + // .LOCK(), + // .RESETB(1'b1), + // .BYPASS(1'b0), + // .REFERENCECLK(clk100), + // .PLLOUTCORE(clk) + // ); + + always_ff @(posedge clk0) begin + if (rst) + display_cnt <= 2'd0; + else + display_cnt <= display_cnt + 1; + end + + assign display_sel = ~(1 << display_cnt); + + hex_to_sevenseg convert (.hexdigit(disp_arr[display_cnt]), .seg(display)); + assign disp_arr[0] = chip_inputs[3:0]; + assign disp_arr[1] = chip_inputs[7:4]; + assign disp_arr[2] = chip_outputs[3:0]; + assign disp_arr[3] = chip_outputs[7:4]; + + // assign D_in = sw[7:0]; + // assign INTR = sw[8]; + // assign READY = sw[9]; + //assign clk = sw[10]; + //assign rst = ~reset_n; + //assign rst = sw[11]; + + assign chip_outputs[7:0] = D_out; + assign chip_outputs[10:8] = state; + assign chip_outputs[11] = Sync; + assign D_in = chip_inputs[7:0]; + assign INTR = chip_inputs[8]; + assign READY = chip_inputs[9]; + + + i8008_core #(.WIDTH(8), .STACK_HEIGHT(8)) DUT (.D_in(D_in), .INTR(INTR), .READY(READY), .clk(clk), .rst(rst), .D_out(D_out), .Sync(Sync), .state(state)); + + // Mirror the chip inputs and outputs to the LEDs for debugging convenience + assign led = {rst, clk, chip_inputs[9:8], chip_outputs[10:0], chip_inputs[7:0]}; +endmodule: top + +module i8008_core + #(parameter WIDTH = 8, + STACK_HEIGHT = 8) + (input logic [7:0] D_in, + input logic INTR, READY, clk, rst, + output logic [7:0] D_out, + output logic Sync, + output state_t state); + + logic [7:0] bus; + logic [7:0] instr; + logic enable_SP, Ready, tempR, Intr, S_Intr, A_rst, B_rst, IR_rst, SP_rst, IR_en, A_en; + logic [7:0] A_in, A_out, B_in, B_out, ALU_out, DBR_out, DBR_in, PC_out, rf_out, ACC; + ctrl_signals_t ctrl_signals; + flags_t flags; + logic [2:0] sel_Stack; + cycle_t cycle; + + always_ff @(posedge clk) begin + if (rst) begin + Ready <= 1'b0; + tempR <= 1'b0; + end + else begin + tempR <= READY; + Ready <= tempR; + end + + if (rst) begin + Intr <= 1'b0; + S_Intr <= 1'b0; + end + else if (state != T1I) begin + S_Intr <= INTR; + Intr <= Intr | S_Intr; + end + else begin + Intr <= 1'b0; + S_Intr <= 1'b0; + end + end + + + assign Sync = ctrl_signals.DBR.we; + + assign D_out = bus; + + always_comb begin + if (ctrl_signals.Stack_ctrl.re_Stack) begin + bus = PC_out | + (ctrl_signals.Stack_ctrl.lower ? 8'd0 : (ctrl_signals.Stack_ctrl.cycle_ctrl << 6)); // cycle ctrl should only be set on T2 + end + else if (ctrl_signals.rf_ctrl.re) begin + bus = rf_out | (ctrl_signals.Stack_ctrl.cycle_ctrl << 6); + end + else if (ctrl_signals.ALU.re) begin + bus = ALU_out; + end + else if (ctrl_signals.flags.re) begin + bus[7:4] = 4'd0; + bus[3:0] = flags; + end + else if (ctrl_signals.A.re) begin + bus = A_out; + end + else if (ctrl_signals.B.re) begin + bus = B_out | (ctrl_signals.Stack_ctrl.cycle_ctrl << 6); + end + else if (ctrl_signals.DBR.re) begin + bus = D_in; + end + else begin + bus = 8'd0; + end + end + + assign IR_rst = ctrl_signals.IR.clr | rst; + assign IR_en = ctrl_signals.IR.we | (Ready && cycle == CYCLE1); + Register #(.WIDTH(WIDTH)) IR (.d(D_in), .Q(instr), .clk, .en(IR_en), .clear(IR_rst)); + + assign A_rst = ctrl_signals.A.clr | rst; + assign B_rst = ctrl_signals.B.clr | rst; + assign A_en = ctrl_signals.A.we; + assign A_in = (cycle == CYCLE1 && (state == T1 || state == T1I)) ? ACC : bus; + Register #(.WIDTH(WIDTH)) regA (.d(A_in), .Q(A_out), .clk, .en(A_en), .clear(A_rst)); + Register #(.WIDTH(WIDTH)) regB (.d(bus), .Q(B_out), .clk, .en(ctrl_signals.B.we), .clear(B_rst)); + + ALU Unit (.clk, .rst, .a(A_out), .b(B_out), .ALU_ctrl(ctrl_signals.ALU), .d(ALU_out), .flags); + + reg_file #(.WIDTH(WIDTH), .HEIGHT(7)) rf (.clk, .rst, .bus, .ACC, .rf_out, .rf_ctrl(ctrl_signals.rf_ctrl)); + + assign enable_SP = ctrl_signals.SP_ctrl.en_SP & + ~((sel_Stack == 3'd0) & ~ctrl_signals.SP_ctrl.inc_SP) & + ~((sel_Stack == 3'd7) & ctrl_signals.SP_ctrl.inc_SP); + assign SP_rst = ctrl_signals.SP_ctrl.clr_SP | rst; + Counter #(.WIDTH(3)) SP_SEL + (.load(1'd0), .clk, .d(3'd0), .Q(sel_Stack), + .en(enable_SP), + .clear(SP_rst), + .up(ctrl_signals.SP_ctrl.inc_SP)); + + stack #(.WIDTH(14), .HEIGHT(STACK_HEIGHT)) Stack + (.clk, .rst, .PC_out, .bus, .sel(sel_Stack), + .Stack_ctrl(ctrl_signals.Stack_ctrl)); + + fsm_decoder Brain (.clk, .Ready, .Intr, .rst, .instr(instr_t'(instr)), .flags, .ctrl_signals, .state, .cycle); + +endmodule: i8008_core + +module ALU + #(parameter WIDTH = 8) + (input logic [7:0] a, b, + input ALU_ctrl_t ALU_ctrl, + input clk, rst, + output logic [7:0] d, + output flags_t flags); + + logic [7:0] add_tmp; + logic [7:0] art_tmp; + flags_t flag_in; + + logic [7:0] NA; + + logic Flag_rst; + assign Flag_rst = rst | ALU_ctrl.clr_Flag; + + FlagRegister #(.WIDTH(4)) + flag_reg (.d(flag_in), .Q(flags), .clk, .en(ALU_ctrl.en_Flag), .clear(Flag_rst)); + + always_comb begin + flag_in[0] = 1'b0; + NA = 'd0; + d = 'd0; + if (ALU_ctrl.ARITH) begin + unique case (ALU_ctrl.arith_op) + ADD1_op: begin + d = a + 1; + flag_in[0] = flags[0]; + end + SUB1_op: begin + d = a - 1; + flag_in[0] = flags[0]; + end + RLC_op: begin + d = {a[6:0], a[7]}; + flag_in[0] = a[7]; + end + RRC_op: begin + d = {a[0], a[7:1]}; + flag_in[0] = a[0]; + end + RAL_op: begin + d = {a[6:0], flags[0]}; + flag_in[0] = a[7]; + end + RAR_op: begin + d = {flags[0], a[7:1]}; + flag_in[0] = a[0]; + end + endcase + end + else begin + d = 'd0; + unique case (ALU_ctrl.alu_op) + ADD_op: begin + {flag_in[0], d} = a + b; + end + ADDC_op: begin + {flag_in[0], d} = a + b + flags[0]; + end + SUB_op: begin + {flag_in[0], d} = a - b; + end + SUBC_op: begin + {flag_in[0], d} = a - b - flags[0]; + end + AND_op: d = a & b; + OR_op: d = a | b; + XOR_op: d = a ^ b; + CMP_op: begin + {flag_in[0], NA} = a - b; // Will set borrow bit on some subtractions + d = a; + end + default: d = 'b0; + endcase + end + + if (ALU_ctrl.ARITH) begin + flag_in[1] = (ALU_ctrl.arith_op == ADD1_op || ALU_ctrl.arith_op == SUB1_op) ? + (~(|d)) : flags[1]; + flag_in[2] = (ALU_ctrl.arith_op == ADD1_op || ALU_ctrl.arith_op == SUB1_op) ? + d[7] : flags[2]; + flag_in[3] = (ALU_ctrl.arith_op == ADD1_op || ALU_ctrl.arith_op == SUB1_op) ? + ~(^d) : flags[3]; + end + else begin + flag_in[1] = (ALU_ctrl.alu_op != CMP_op) ? (~(|d)) : (~(|NA)); + flag_in[2] = (ALU_ctrl.alu_op != CMP_op) ? d[7] : NA[7]; + flag_in[3] = (ALU_ctrl.alu_op != CMP_op) ? ~(^d) : ~(^NA); + end + + end +endmodule: ALU + +module fsm_decoder + (input logic clk, Ready, Intr, rst, + input instr_t instr, + input flags_t flags, + output ctrl_signals_t ctrl_signals, + output state_t state, + output cycle_t cycle); + + logic [2:0] SSS, DDD; + logic [2:0] D5_3; + + assign SSS = instr[2:0]; + assign DDD = instr[5:3]; + assign D5_3 = instr[5:3]; + cycle_t next_cycle; + state_t next_state; + + logic CF; + + // Should flags be one hot, or fully encoded? + always_comb begin + unique case (instr[4:3]) + Ca: CF = ~flags[0]; + Ze: CF = ~flags[1]; + Si: CF = ~flags[2]; + Pa: CF = ~flags[3]; // Parity of result is even + default: CF = 1'b1; + endcase + end + + always_comb begin + next_cycle = cycle; + ctrl_signals = 'd0; // Should these be initialized to X's? No, apparently doesn't minimize logic + unique case (cycle) + CYCLE1: begin + unique case (state) + T1, T1I: begin // INCR PC?? + next_state = T2; + + ctrl_signals.DBR.we = 1'b1; + ctrl_signals.Stack_ctrl.re_Stack = 1'b1; + ctrl_signals.Stack_ctrl.lower = PC_L; + + ctrl_signals.A.we = 1'b1; + end + T2: begin + next_state = Ready ? T3 : WAIT; + + ctrl_signals.DBR.we = 1'b1; + ctrl_signals.Stack_ctrl.re_Stack = 1'b1; + ctrl_signals.Stack_ctrl.lower = PC_H; + + ctrl_signals.Stack_ctrl.cycle_ctrl = PCI; + + ctrl_signals.Stack_ctrl.inc_PC = 1'b1; // Increment PC here and not T1 so it doesn't affect PC_H + end + WAIT: begin + next_state = Ready ? T3 : WAIT; + end + T3, STOPPED: begin + if (instr == RST) begin // TODO: Replace with anything or is this fine? + ctrl_signals.B.we = 1'b1; + ctrl_signals.A.clr = 1'b1; + ctrl_signals.SP_ctrl.inc_SP = 1'b1; + ctrl_signals.SP_ctrl.en_SP = 1'b1; + ctrl_signals.DBR.re = 1'b1; + end + else begin + ctrl_signals.B.we = 1'b1; + ctrl_signals.DBR.re = 1'b1; + end + + unique casez (instr) + HLT0, HLT1, LrM: begin + if (instr[7] && D5_3 != 3'b111) begin + next_cycle = CYCLE2; + next_state = T1; + end + else begin + if (Intr) begin + next_state = T1I; // Go to "T1I" next + next_cycle = CYCLE1; + end + else begin + next_state = STOPPED; // STOPPED STATE + end + end + end + RFc, RTc: begin // Conditional return only? + if ((instr[5] & ~CF) | (~instr[5] & CF)) begin + next_state = T4; // WAIT state + end + else begin + next_cycle = CYCLE1; + next_state = T1; + end + end + ALUM, ALUI, INP, OUT, LrI, JMP, JFc, JTc, CAL, CTc, CFc: begin + next_cycle = CYCLE2; + next_state = T1; + end + default: begin + next_state = T4; + end + endcase + end + T4: begin + unique casez (instr) + Lr1r2, LMr, ALU_op: begin + // Deal with LrM case? No, it shouldn't get here + // Deal with other ALU cases? Nope, shouldn't get here + // if (SSS != 3'b111) begin + ctrl_signals.B.we = 1'b1; + ctrl_signals.rf_ctrl.re = 1'b1; + ctrl_signals.rf_ctrl.sel = SSS; + // ctrl_signals.DBR.we = 1'b1; + // end + end + INr, DCr: begin + // Deal with HALT case and mem case for INr/DCr? No, shouldn't get here + ctrl_signals.rf_ctrl.re = 1'b1; + ctrl_signals.rf_ctrl.sel = DDD; + ctrl_signals.A.we = 1'b1; + end + RLC, RRC, RAL, RAR: begin + // read Accum into A alu reg + // TODO: Remove A.we, should already be there + ctrl_signals.rf_ctrl.re = 1'b1; + ctrl_signals.rf_ctrl.sel = Acc; + ctrl_signals.A.we = 1'b1; + end + RET, RFc, RTc: begin // Pop stack + ctrl_signals.SP_ctrl.inc_SP = 1'b0; + ctrl_signals.SP_ctrl.en_SP = 1'b1; + end + RST: begin + ctrl_signals.A.re = 1'b1; + ctrl_signals.Stack_ctrl.lower = 1'b0; + ctrl_signals.Stack_ctrl.we_Stack = 1'b1; + end + default: begin + // Do nothing! + // if (instr[7:6] == 2'b10) begin + // ctrl_signals.B.we = 1'b1; + // ctrl_signals.rf_ctrl.re = 1'b1; + // ctrl_signals.rf_ctrl.sel = SSS; + // end + end + endcase + + if (instr[7:3] == 5'b11_111) begin // LMr case + next_state = T1; + next_cycle = CYCLE2; + end + else begin + next_state = T5; + end + end + T5: begin + unique casez (instr) + Lr1r2: begin + ctrl_signals.B.re = 1'b1; + ctrl_signals.rf_ctrl.we = 1'b1; + ctrl_signals.rf_ctrl.sel = DDD; + end + RST: begin + ctrl_signals.B.re = 1'b1; + ctrl_signals.Stack_ctrl.we_Stack = 1'b1; + ctrl_signals.Stack_ctrl.lower = 1'b1; // What to do here since only want D5-3? + ctrl_signals.Stack_ctrl.D5_3 = 1'b1; + end + INr, DCr: begin + ctrl_signals.rf_ctrl.we = 1'b1; + ctrl_signals.rf_ctrl.sel = DDD; + ctrl_signals.ALU.arith_op = (instr[2:0] == 3'b000) ? ADD1_op : SUB1_op; + ctrl_signals.ALU.ARITH = 1'b1; + ctrl_signals.ALU.re = 1'b1; + ctrl_signals.ALU.en_Flag = 1'b1; + end + ALU_op: begin + ctrl_signals.rf_ctrl.we = 1'b1; + ctrl_signals.rf_ctrl.sel = Acc; + ctrl_signals.ALU.alu_op = alu_op_t'(D5_3); // Enter ops for ALU commands + //ctrl_signals.ALU.alu_op = D5_3; // Enter ops for ALU commands + ctrl_signals.ALU.ARITH = 1'b0; + ctrl_signals.ALU.re = 1'b1; + ctrl_signals.ALU.en_Flag = 1'b1; + end + RLC, RRC, RAL, RAR: begin + ctrl_signals.rf_ctrl.we = 1'b1; + ctrl_signals.rf_ctrl.sel = Acc; + ctrl_signals.ALU.arith_op = arith_op_t'(D5_3); // Enter ops for rotate commands + //ctrl_signals.ALU.arith_op = D5_3; // Enter ops for rotate commands + ctrl_signals.ALU.ARITH = 1'b1; + ctrl_signals.ALU.re = 1'b1; + ctrl_signals.ALU.en_Flag = 1'b1; + end + //RET, RFc, RTc: // do nothing! + default: begin // do nothing! + end + endcase + + next_state = T1; + next_cycle = CYCLE1; + end + default: begin + next_state = T1; + next_cycle = CYCLE1; + end + endcase + end + CYCLE2: begin + unique case (state) + T1, T1I: begin + next_state = T2; + + unique casez (instr) + LMI, LrI, ALUI, JMP, JFc, JTc, CAL, CTc, CFc: begin + ctrl_signals.Stack_ctrl.re_Stack = 1'b1; + ctrl_signals.Stack_ctrl.lower = 1'b1; + ctrl_signals.DBR.we = 1'b1; + end + LrM, LMr, ALUM: begin + ctrl_signals.rf_ctrl.re = 1'b1; + ctrl_signals.rf_ctrl.sel = Lo; + ctrl_signals.DBR.we = 1'b1; + end + INP, OUT: begin + ctrl_signals.A.re = 1'b1; + ctrl_signals.DBR.we = 1'b1; + end + default: begin + end + endcase + end + T2: begin + next_state = Ready ? T3 : WAIT; + + unique casez (instr) + LMI, LrI, ALUI, JMP, JFc, JTc, CAL, CTc, CFc: begin + ctrl_signals.Stack_ctrl.re_Stack = 1'b1; + ctrl_signals.DBR.we = 1'b1; + ctrl_signals.Stack_ctrl.cycle_ctrl = PCR; + ctrl_signals.Stack_ctrl.lower = 1'b0; + ctrl_signals.Stack_ctrl.inc_PC = 1'b1; // Increment PC here and not T1 so it doesn't affect PC_H + end + LrM, LMr, ALUM: begin + ctrl_signals.rf_ctrl.re = 1'b1; + ctrl_signals.rf_ctrl.sel = Hi; + ctrl_signals.Stack_ctrl.cycle_ctrl = (instr[7:3] == 5'b11_111) ? PCW : PCR; // LMr case + ctrl_signals.Stack_ctrl.lower = 1'b0; + ctrl_signals.DBR.we = 1'b1; + end + INP, OUT: begin + ctrl_signals.Stack_ctrl.cycle_ctrl = PCC; + ctrl_signals.Stack_ctrl.lower = 1'b0; + ctrl_signals.B.re = 1'b1; + ctrl_signals.DBR.we = 1'b1; + end + default: begin + end + endcase + end + WAIT: begin + next_state = Ready ? T3 : WAIT; + end + T3, STOPPED: begin + unique casez (instr) + OUT, LMr: begin + next_cycle = CYCLE1; + next_state = T1; + end + LMI, JMP, JFc, JTc, CAL, CTc, CFc: begin + next_state = T1; + next_cycle = CYCLE3; + end + default: begin + next_state = T4; // WAIT state + end + endcase + + unique casez (instr) + INP, ALUM, ALUI, LrM, LMI, LrI, JMP, JFc, JTc, CAL, CTc, CFc: begin + // For control flow instructions, this is the lower address + ctrl_signals.DBR.re = 1'b1; + ctrl_signals.B.we = 1'b1; + end + LMr: begin + ctrl_signals.DBR.we = 1'b1; + ctrl_signals.B.re = 1'b1; + end + // OUT: begin + // // do nothing! + // end + default: begin // do nothing! + end + endcase + end + T4: begin + next_state = T5; + + if (instr[7:4] == 4'b0100 && instr[0]) begin // INP case + ctrl_signals.DBR.we = 1'b1; + ctrl_signals.flags.re = 1'b1; // Write flags into output + end + // else do nothing! + end + T5: begin + next_state = T1; + next_cycle = CYCLE1; + + unique casez (instr) + LrM, LrI, INP: begin + ctrl_signals.B.re = 1'b1; + ctrl_signals.rf_ctrl.sel = (instr[7:4] == 4'b0100 && instr[0]) ? Acc : DDD; // INP case + ctrl_signals.rf_ctrl.we = 1'b1; + end + ALUM, ALUI: begin + // Execute alu op and affect flags + ctrl_signals.rf_ctrl.sel = Acc; + ctrl_signals.rf_ctrl.we = 1'b1; + ctrl_signals.ALU.alu_op = alu_op_t'(D5_3); // Set alu op based on instruction, add arith op? + //ctrl_signals.ALU.alu_op = D5_3; // Set alu op based on instruction, add arith op? + ctrl_signals.ALU.ARITH = 1'b0; + ctrl_signals.ALU.re = 1'b1; + ctrl_signals.ALU.en_Flag = 1'b1; + end + default: begin + end + endcase + end + default: begin + next_cycle = CYCLE1; + next_state = T1; + end + endcase + end + CYCLE3: begin + unique case (state) + T1, T1I: begin + next_state = T2; + + unique casez (instr) + LMI: begin + ctrl_signals.rf_ctrl.sel = Lo; + ctrl_signals.rf_ctrl.re = 1'b1; + ctrl_signals.DBR.we = 1'b1; + end + JMP, JFc, JTc, CAL, CTc, CFc: begin + ctrl_signals.Stack_ctrl.re_Stack = 1'b1; + ctrl_signals.Stack_ctrl.lower = 1'b1; + ctrl_signals.DBR.we = 1'b1; + end + default: begin + end + endcase + end + T2: begin + next_state = Ready ? T3 : WAIT; + + unique casez (instr) + LMI: begin + ctrl_signals.rf_ctrl.sel = Hi; + ctrl_signals.rf_ctrl.re = 1'b1; + ctrl_signals.DBR.we = 1'b1; + ctrl_signals.Stack_ctrl.cycle_ctrl = PCW; + ctrl_signals.Stack_ctrl.lower = 1'b0; + end + JMP, JFc, JTc, CAL, CTc, CFc: begin + ctrl_signals.Stack_ctrl.re_Stack = 1'b1; + ctrl_signals.Stack_ctrl.lower = 1'b0; + ctrl_signals.DBR.we = 1'b1; + ctrl_signals.Stack_ctrl.cycle_ctrl = PCR; + ctrl_signals.Stack_ctrl.inc_PC = 1'b1; // Increment PC here and not T1 so it doesn't affect PC_H + end + default: begin + end + endcase + end + WAIT: begin + next_state = Ready ? T3 : WAIT; + end + T3, STOPPED: begin + unique casez (instr) + LMI: begin + next_state = T1; + next_cycle = CYCLE1; + end + CAL: begin + ctrl_signals.SP_ctrl.inc_SP = 1'b1; + ctrl_signals.SP_ctrl.en_SP = 1'b1; + next_state = T4; + end + JFc, CFc: begin + if (~CF) begin + next_state = T1; + next_cycle = CYCLE1; + end + else begin + if (instr[7:5] == 3'b010 && instr[2:0] == 3'b010) begin // CFc case + ctrl_signals.SP_ctrl.inc_SP = 1'b1; + ctrl_signals.SP_ctrl.en_SP = 1'b1; + end + next_state = T4; + end + end + JTc, CTc: begin + if (CF) begin + next_state = T1; + next_cycle = CYCLE1; + end + else begin + if (instr[7:5] == 3'b011 && instr[2:0] == 3'b010) begin // CTc case + ctrl_signals.SP_ctrl.inc_SP = 1'b1; + ctrl_signals.SP_ctrl.en_SP = 1'b1; + end + next_state = T4; + end + end + default: next_state = T4; + endcase + + unique casez (instr) + LMI: begin + ctrl_signals.B.re = 1'b1; + ctrl_signals.DBR.we = 1'b1; + end + JMP, JFc, JTc, CAL, CTc, CFc: begin + ctrl_signals.A.we = 1'b1; + ctrl_signals.DBR.re = 1'b1; + end + default: begin + end + endcase + end + T4: begin + next_state = T5; + + unique casez (instr) + CAL, CTc, CFc: begin // Is there an issue where the stack isn't pushed early enough? + ctrl_signals.A.re = 1'b1; + ctrl_signals.Stack_ctrl.we_Stack = 1'b1; + // ((instr[7:6] == 2'b01 && instr[2:0] == 3'b110) | // CAL case + // ((instr[7:5] == 3'b011 && instr[2:0] == 3'b010) & ~CF) | // CTc case + // ((instr[7:5] == 3'b010 && instr[2:0] == 3'b010) & CF)); // CFc case + ctrl_signals.Stack_ctrl.lower = 1'b0; + + // ((instr[7:6] == 2'b01 && instr[2:0] == 3'b110) | // CAL case + // ((instr[7:5] == 3'b011 && instr[2:0] == 3'b010) & ~CF) | // CTc case + // ((instr[7:5] == 3'b010 && instr[2:0] == 3'b010) & CF)); // CFc case + end + JMP, JFc, JTc: begin + ctrl_signals.A.re = 1'b1; + ctrl_signals.Stack_ctrl.we_Stack = 1'b1; + // ((instr[7:6] == 2'b01 && instr[2:0] == 3'b100) | // JMP case + // ((instr[7:5] == 3'b011 && instr[2:0] == 3'b000) & ~CF) | // JTc case + // ((instr[7:5] == 3'b010 && instr[2:0] == 3'b000) & CF)); // JFc case + ctrl_signals.Stack_ctrl.lower = 1'b0; + end + default: begin + end + endcase + end + T5: begin + next_state = T1; + next_cycle = CYCLE1; + + unique casez (instr) + CAL, CTc, CFc, JMP, JFc, JTc: begin // Is there an issue where the stack isn't pushed early enough? + ctrl_signals.B.re = 1'b1; + ctrl_signals.Stack_ctrl.we_Stack = 1'b1; + ctrl_signals.Stack_ctrl.lower = 1'b1; + end + default: begin + end + endcase + end + default: begin + next_state = T1; + next_cycle = CYCLE1; + end + endcase + end + default: begin + next_state = T1; + next_cycle = CYCLE1; + ctrl_signals = 'd0; + end + endcase + end + + + always_ff @(posedge clk) begin + if (rst) begin + cycle <= CYCLE1; + state <= T1; + end + else begin + cycle <= next_cycle; + state <= next_state; + end + end + +endmodule: fsm_decoder + +// Module for storing large amounts of information +module reg_file +#(parameter WIDTH = 8, + HEIGHT = 7, + SEL = $clog2(HEIGHT)) +(input logic [7:0] bus, + input logic clk, rst, + input rf_ctrl_t rf_ctrl, + output logic [7:0] rf_out, ACC); + + logic [7:0] rf[7]; + logic [7:0] rs; + + logic [2:0] sel; + assign sel = rf_ctrl.sel == 3'b111 ? 3'd0 : rf_ctrl.sel; + + assign rf_out = rs; + assign ACC = rf[0]; + + always_ff @(posedge clk) begin + if (rst) begin + rf[3'd0] <= 8'd0; + rf[3'd1] <= 8'd0; + rf[3'd2] <= 8'd0; + rf[3'd3] <= 8'd0; + rf[3'd4] <= 8'd0; + rf[3'd5] <= 8'd0; + rf[3'd6] <= 8'd0; + end + else if (rf_ctrl.we && rf_ctrl.sel != 3'b111) + rf[rf_ctrl.sel] <= bus; + end + + always_comb + rs = rf[sel]; + +endmodule: reg_file + +module stack +#(parameter WIDTH = 14, + BUS_WIDTH = 8, + HEIGHT = 8, + SEL = $clog2(HEIGHT)) +(input logic [7:0] bus, + input logic [2:0] sel, + input logic clk, rst, + input Stack_ctrl_t Stack_ctrl, + output logic [7:0] PC_out); + + logic [13:0] rf[8]; // TODO: may have to make 1D array + logic [13:0] rs; + logic [7:0] upper, RST_AAA; + + assign upper = {2'd0, rs[13:8]}; + assign PC_out = (Stack_ctrl.lower ? rs[7:0] : upper); + + assign RST_AAA[5:3] = bus[5:3]; + assign RST_AAA[2:0] = 3'd0; + assign RST_AAA[7:6] = 2'd0; + + always_ff @(posedge clk) begin + if (rst) begin + rf[3'd0] <= 14'd0; + rf[3'd1] <= 14'd0; + rf[3'd2] <= 14'd0; + rf[3'd3] <= 14'd0; + rf[3'd4] <= 14'd0; + rf[3'd5] <= 14'd0; + rf[3'd6] <= 14'd0; + rf[3'd7] <= 14'd0; + end + else if (Stack_ctrl.we_Stack && Stack_ctrl.lower) + rf[sel] <= Stack_ctrl.D5_3 ? {8'd0, RST_AAA} : {rf[sel][13:8], bus}; + else if (Stack_ctrl.we_Stack && ~Stack_ctrl.lower) + rf[sel] <= {bus[5:0], rf[sel][7:0]}; + else if (Stack_ctrl.inc_PC) + rf[sel] <= rf[sel] + 1; + end + + always_comb begin + rs = rf[sel]; + end + +endmodule: stack + +module Register + #(parameter WIDTH = 8) + (input logic en, clear, clk, + input logic [7:0] d, + output logic [7:0] Q); + + always_ff @(posedge clk) begin + if (clear) + Q <= 'd0; + else if (en) + Q <= d; + end +endmodule: Register + +module FlagRegister + #(parameter WIDTH = 4) + (input logic en, clear, clk, + input logic [3:0] d, + output logic [3:0] Q); + + always_ff @(posedge clk) begin + if (clear) + Q <= 'd0; + else if (en) + Q <= d; + end +endmodule: FlagRegister + +module Counter + #(parameter WIDTH = 3) + (input logic en, clear, load, up, clk, + input logic [2:0] d, + output logic [2:0] Q); + + always_ff @(posedge clk) begin + if (clear) + Q <= 'd0; + else if (load) + Q <= d; + else if (en && up) + Q <= Q + 1; + else if (en && ~up) + Q <= Q - 1; + end +endmodule: Counter + +module Stabilizer + (input logic D, clk, + output logic Q); + logic temp; + + always_ff @(posedge clk) begin + temp <= D; + Q <= temp; + end +endmodule: Stabilizer + +`default_nettype wire diff --git a/designs/d29_bwilhelm_i8008/original_sv/i8008_isa.vh b/designs/d29_bwilhelm_i8008/original_sv/i8008_isa.vh new file mode 100644 index 0000000..4188aee --- /dev/null +++ b/designs/d29_bwilhelm_i8008/original_sv/i8008_isa.vh @@ -0,0 +1,148 @@ + + +`ifndef I8008_ISA_VH_ +`define I8008_ISA_VH_ + +/*---------------------------------------------------------------------------- + * Opcodes (All Instruction Types) + *----------------------------------------------------------------------------*/ + + // typedef enum logic [2:0] { + // Lo_MEM = 3'b111, + // Lo_IMM_CAL = 3'b110, + // Lo_MACH = 3'b00x, + // Lo_DC = 3'bxxx + // } D2_0_t; + + // typedef enum logic [2:0] { + // Lo_JXc = 3'b000, + // Lo_CXc = 3'b010, + // Lo_JMP = 3'b100, + // Lo_CAL = 3'b110, + // Lo_IO = 3'bxx1 + // } IO_CTRL_Lo_t; + + // typedef enum logic [2:0] { + // Lo_INr = 3'b000, + // Lo_DCr = 3'b001, + // Lo_ROT = 3'b010, + // Lo_RXc = 3'b011, + // Lo_ALU = 3'b100, + // Lo_RST = 3'b101, + // Lo_LOAD = 3'b110, + // Lo_RET = 3'b111 + // } IMM_MISC_Lo_t; + + // typedef enum logic [2:0] { + // Hi_RLC = 3'b000, + // Hi_RRC = 3'b001, + // Hi_RAL = 3'b010, + // Hi_RAR = 3'b011 + // } IMM_MISC_Hi_t; + + // typedef enum logic [2:0] { + // } LOAD_Lo_t; + + // typedef enum logic [2:0] { + // } ALU_IND_MEM_Lo_t; + + // typedef enum logic [2:0] { + // ADx = 3'b000, + // ACx = 3'b001, + // SUx = 3'b010, + // SBx = 3'b011, + // NDx = 3'b100, + // XRx = 3'b101, + // ORx = 3'b110, + // CPx = 3'b111 + // } ALU_IND_MEM_Hi_t; + + // typedef enum logic [2:0] { + // Hi_MEM = 3'b111, + // Hi_MACH = 3'b000, + // Hi_DC = 3'bxxx + // } D5_3_t; + + // typedef enum logic [1:0] { + // LOAD = 2'b11, + // ALU_IND_MEM = 2'b10, + // IO_CTRL = 2'b01, + // IMM_MISC = 2'b00 + // } D7_6_t; + + typedef enum logic [7:0] { + // Index register instructions + Lr1r2 = 8'b11_???_???, // Load r1 with r2 + LrM = 8'b11_???_111, // Load r with Mem + LMr = 8'b11_111_???, // Load Mem with r + LrI = 8'b00_???_110, // Load r with Immediate + LMI = 8'b00_111_110, // Load Mem with Immediate + INr = 8'b00_???_000, // Increment r (r != A) + DCr = 8'b00_???_001, // Decrement r (r != A) + + ALU_op = 8'b10_???_???, + ALUM = 8'b10_???_111, + ALUI = 8'b00_???_100, + + // Accumulator group instructions + ADr = 8'b10_000_???, // Add contents to A, set carry + ADM = 8'b10_000_111, + ADI = 8'b00_000_100, + + ACr = 8'b10_001_???, // Add contents + carry to A + ACM = 8'b10_001_111, + ACI = 8'b00_001_100, + + SUr = 8'b10_010_???, // Subtract contents from A, set carry + SUM = 8'b10_010_111, + SUI = 8'b00_010_100, + + SBr = 8'b10_011_???, // Subtract contents from A, subtract borrow, set carry + SBM = 8'b10_011_111, + SBI = 8'b00_011_100, + + NDr = 8'b10_100_???, // Logical AND of contents with accumulator + NDM = 8'b10_100_111, + NDI = 8'b00_100_100, + + XRr = 8'b10_101_???, // Logical XOR of contents with accumulator + XRM = 8'b10_101_111, + XRI = 8'b00_101_100, + + ORr = 8'b10_110_???, // Logical OR of contents with accumulator + ORM = 8'b10_110_111, + ORI = 8'b00_110_100, + + CPr = 8'b10_111_???, // Compare contents with accumulator, accumulator unaffected. Sub sets flags + CPM = 8'b10_111_111, + CPI = 8'b00_111_100, + + RLC = 8'b00_000_010, // Rotate accumulator left + RRC = 8'b00_001_010, // Rotate accumulator right + RAL = 8'b00_010_010, // Rotate accumulator left through carry + RAR = 8'b00_011_010, // Rotate accumulator right through carry + + // = 8'bPC and stack control instructions + JMP = 8'b01_???_100, + JFc = 8'b01_0??_000, // Jump to B3B2 if false, else continue + JTc = 8'b01_1??_000, + CAL = 8'b01_???_110, + CFc = 8'b01_0??_010, // Call subroutine at B3B2 if false, move up in stack, else continue + CTc = 8'b01_1??_010, + RET = 8'b00_???_111, + RFc = 8'b00_0??_011, // Return down a level of the stack if false, else continue + RTc = 8'b00_1??_011, + RST = 8'b00_???_101, + + // = 8'bI/O instructions + INP = 8'b01_00?_??1, // Read contents of input port into accumulator + OUT = 8'b01_???_??1, // Write accumulator into output port, RRMMM, RR != 0 + + // = 8'bMachine + HLT0 = 8'b00_000_00?, // Enter stopped state until interrupted + HLT1 = 8'b11_111_111, // Enter stopped state until interrupted + + INVALID = 'bx // Instruction unrecognized + } instr_t; + +`endif \ No newline at end of file diff --git a/designs/d29_bwilhelm_i8008/original_sv/internal_defines.vh b/designs/d29_bwilhelm_i8008/original_sv/internal_defines.vh new file mode 100644 index 0000000..e63c142 --- /dev/null +++ b/designs/d29_bwilhelm_i8008/original_sv/internal_defines.vh @@ -0,0 +1,144 @@ +`ifndef INTERNAL_DEFINES_VH_ +`define INTERNAL_DEFINES_VH_ + +`define DATA_WIDTH = 8; + +// The current state of proc, also to be output +typedef enum logic [2:0] { + T1 = 3'b010, + T1I = 3'b110, + T2 = 3'b100, + WAIT = 3'b000, + T3 = 3'b001, + STOPPED = 3'b011, + T4 = 3'b111, + T5 = 3'b101, + INVALID_STATE = 3'bxxx +} state_t; + +// The memory cycle number, needed to determine state transitions +typedef enum logic [1:0] { + CYCLE1 = 2'b00, + CYCLE2 = 2'b01, + CYCLE3 = 2'b10 +} cycle_t; + +typedef enum logic [1:0] { + PCI = 2'b00, // Designates the address is for a memory read (first byte of instruction) + PCR = 2'b01, // Designates the address is for a memory read data (additional bytes of instruction or data) + PCC = 2'b10, // Designates the data as a command I/O operation + PCW = 2'b11 // Designates the address is for a memory write data +} cycle_ctrl_t; + +typedef enum logic [2:0] { + Acc = 3'd0, + //B = 3'd1, + //C = 3'd2, + //D = 3'd3, + //E = 3'd4, + Hi = 3'd5, // Upper 6 bits of external register stored here + Lo = 3'd6, // Lower 8 bits of external register stored here + ILLEGAL = 3'd7 // Cannot use this, reserved for instructions +} reg_t; + +typedef struct packed { + logic CARRY; + logic ZERO; + logic SIGN; + logic PARITY; +} flags_t; + +typedef enum logic [3:0] { + CARRY_bit = 4'b0001, + ZERO_bit = 4'b0010, + SIGN_bit = 4'b0100, + PARITY_bit = 4'b1000 +} flag_bit_t; + +typedef enum logic [1:0] { + Ca = 2'b00, + Ze = 2'b01, + Si = 2'b10, + Pa = 2'b11 +} flag_enc_t; + +typedef enum logic { + PC_L = 1'b1, + PC_H = 1'b0 +} PC_t; + +typedef enum logic [2:0] { + ADD_op = 3'b000, // Addition + ADDC_op = 3'b001, // Addition + SUB_op = 3'b010, // Subtraction + SUBC_op = 3'b011, // Subtraction + AND_op = 3'b100, // Logical And + XOR_op = 3'b101, // Exclusive Or + OR_op = 3'b110, // Inclusive Or + CMP_op = 3'b111 +} alu_op_t; + +typedef enum logic [2:0] { + RLC_op = 3'b000, + RRC_op = 3'b001, + RAL_op = 3'b010, + RAR_op = 3'b011, + ADD1_op = 3'b100, + SUB1_op = 3'b101 +} arith_op_t; + +typedef struct packed { + logic re; // + logic we; // + logic clr; +} reg_ctrl_t; + +typedef struct packed { + logic re; // + alu_op_t alu_op; // Operation for ALU to perform + arith_op_t arith_op; + logic ARITH; + logic en_Flag; + logic clr_Flag; +} ALU_ctrl_t; + +typedef struct packed { + logic [2:0] sel; // + logic re; // + logic we; // +} rf_ctrl_t; + +typedef struct packed { + logic en_SP; // + logic clr_SP; // + logic inc_SP; // +} SP_ctrl_t; + +typedef struct packed { + logic we_Stack; // + logic re_Stack; // + logic lower; + logic inc_PC; + logic D5_3; + + cycle_ctrl_t cycle_ctrl; +} Stack_ctrl_t; + +typedef struct packed { + reg_ctrl_t DBR; + + reg_ctrl_t IR; + + reg_ctrl_t A; + reg_ctrl_t B; + reg_ctrl_t flags; + + ALU_ctrl_t ALU; + + rf_ctrl_t rf_ctrl; + + SP_ctrl_t SP_ctrl; + Stack_ctrl_t Stack_ctrl; +} ctrl_signals_t; + +`endif diff --git a/designs/d29_bwilhelm_i8008/sim_test.sh b/designs/d29_bwilhelm_i8008/sim_test.sh new file mode 100644 index 0000000..4d49f34 --- /dev/null +++ b/designs/d29_bwilhelm_i8008/sim_test.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +# move to the test directory +cd $(pwd)/tests + +# run the tests +make \ No newline at end of file diff --git a/designs/d29_bwilhelm_i8008/src/chip.sv b/designs/d29_bwilhelm_i8008/src/chip.sv new file mode 100644 index 0000000..bffdb97 --- /dev/null +++ b/designs/d29_bwilhelm_i8008/src/chip.sv @@ -0,0 +1,23 @@ +`default_nettype none + +module my_chip ( + input logic [11:0] io_in, // Inputs to your chip + output logic [11:0] io_out, // Outputs from your chip + input logic clock, + input logic reset // Important: Reset is ACTIVE-HIGH +); + + i8008_core my_core ( + .clk(clock), + .rst(reset), + + .D_in(io_in[7:0]), + .INTR(io_in[8]), + .READY(io_in[9]), + + .D_out(io_out[7:0]), + .state(io_out[10:8]), + .Sync(io_out[11]) + ); + +endmodule diff --git a/designs/d29_bwilhelm_i8008/src/config.tcl b/designs/d29_bwilhelm_i8008/src/config.tcl new file mode 100644 index 0000000..aa589e4 --- /dev/null +++ b/designs/d29_bwilhelm_i8008/src/config.tcl @@ -0,0 +1,68 @@ +# PLEASE DO NOT EDIT THIS FILE! +# IT WILL MAKE YOUR CHIP UNMANUFACTURABLE +# The only line you may edit is FP_CORE_UTIL +# (may benefit from reducing it slightly) + +# User config +set script_dir [file dirname [file normalize [info script]]] + +# read some user config that is written by the setup.py program. +# - the name of the module is defined +# - the list of source files +source $::env(DESIGN_DIR)/user_config.tcl + +# save some time +set ::env(RUN_KLAYOUT_XOR) 0 +set ::env(RUN_KLAYOUT_DRC) 0 + +# don't put clock buffers on the outputs +set ::env(PL_RESIZER_BUFFER_OUTPUT_PORTS) 0 + +# allow use of specific sky130 cells +set ::env(SYNTH_READ_BLACKBOX_LIB) 1 + +# put all the pins on the left +set ::env(FP_PIN_ORDER_CFG) $::env(DESIGN_DIR)/pin_order.cfg + +# reduce wasted space +set ::env(TOP_MARGIN_MULT) 2 +set ::env(BOTTOM_MARGIN_MULT) 2 + +# absolute die size +set ::env(FP_SIZING) absolute +set ::env(DIE_AREA) "0 0 280 280" + +## THIS IS THE ONLY LINE YOU CAN EDIT +set ::env(FP_CORE_UTIL) 45 + +## set ::env(PL_BASIC_PLACEMENT) {1} + +set ::env(FP_IO_HLENGTH) 2 +set ::env(FP_IO_VLENGTH) 2 + +# use alternative efabless decap cells to solve LI density issue +set ::env(DECAP_CELL) "\ + sky130_fd_sc_hd__decap_3 \ + sky130_fd_sc_hd__decap_4 \ + sky130_fd_sc_hd__decap_6 \ + sky130_fd_sc_hd__decap_8 \ + sky130_ef_sc_hd__decap_12" + +# clock +set ::env(CLOCK_TREE_SYNTH) 1 + +# period is in ns, so 500ns == 2 MHz +set ::env(CLOCK_PERIOD) "500" +set ::env(CLOCK_PORT) {io_in[12]} + +# hold/slack margin +# set ::env(PL_RESIZER_HOLD_SLACK_MARGIN) 0.8 +# set ::env(GLB_RESIZER_HOLD_SLACK_MARGIN) 0.8 + +# don't use power rings or met5 +set ::env(DESIGN_IS_CORE) 0 +set ::env(RT_MAX_LAYER) {met4} + +# connect to first digital rails +set ::env(VDD_NETS) [list {vccd1}] +set ::env(GND_NETS) [list {vssd1}] diff --git a/designs/d29_bwilhelm_i8008/src/decoder.v b/designs/d29_bwilhelm_i8008/src/decoder.v new file mode 100644 index 0000000..8d6310e --- /dev/null +++ b/designs/d29_bwilhelm_i8008/src/decoder.v @@ -0,0 +1,38 @@ + +/* + -- 1 -- + | | + 6 2 + | | + -- 7 -- + | | + 5 3 + | | + -- 4 -- +*/ + +module seg7 ( + input wire [3:0] counter, + output reg [6:0] segments +); + + always @(*) begin + case(counter) + // 7654321 + 0: segments = 7'b0111111; + 1: segments = 7'b0000110; + 2: segments = 7'b1011011; + 3: segments = 7'b1001111; + 4: segments = 7'b1100110; + 5: segments = 7'b1101101; + 6: segments = 7'b1111100; + 7: segments = 7'b0000111; + 8: segments = 7'b1111111; + 9: segments = 7'b1100111; + default: + segments = 7'b0000000; + endcase + end + +endmodule + diff --git a/designs/d29_bwilhelm_i8008/src/i8008_core.v b/designs/d29_bwilhelm_i8008/src/i8008_core.v new file mode 100644 index 0000000..af7ef3f --- /dev/null +++ b/designs/d29_bwilhelm_i8008/src/i8008_core.v @@ -0,0 +1,934 @@ +`default_nettype none +module top ( + clk100, + reset_n, + uart_rx, + uart_tx, + base_led, + led, + sw, + display_sel, + display +); + input wire clk100; + input wire reset_n; + input wire uart_rx; + output wire uart_tx; + output wire [7:0] base_led; + output wire [23:0] led; + input wire [23:0] sw; + output wire [3:0] display_sel; + output wire [7:0] display; + wire clk; + wire rst; + wire [11:0] chip_inputs; + wire [11:0] chip_outputs; + wire [7:0] D_in; + wire [7:0] D_out; + wire INTR; + wire READY; + wire Sync; + wire [2:0] state; + reg [1:0] display_cnt; + wire [3:0] disp_arr [0:3]; + debug_harness dbg( + .uart_rx(uart_rx), + .uart_tx(uart_tx), + .chip_inputs(chip_inputs), + .chip_outputs(chip_outputs), + .chip_clock(clk), + .chip_reset(rst), + .clk100(clk100) + ); + always @(posedge clk0) + if (rst) + display_cnt <= 2'd0; + else + display_cnt <= display_cnt + 1; + assign display_sel = ~(1 << display_cnt); + hex_to_sevenseg convert( + .hexdigit(disp_arr[display_cnt]), + .seg(display) + ); + assign disp_arr[0] = chip_inputs[3:0]; + assign disp_arr[1] = chip_inputs[7:4]; + assign disp_arr[2] = chip_outputs[3:0]; + assign disp_arr[3] = chip_outputs[7:4]; + assign chip_outputs[7:0] = D_out; + assign chip_outputs[10:8] = state; + assign chip_outputs[11] = Sync; + assign D_in = chip_inputs[7:0]; + assign INTR = chip_inputs[8]; + assign READY = chip_inputs[9]; + i8008_core #( + .WIDTH(8), + .STACK_HEIGHT(8) + ) DUT( + .D_in(D_in), + .INTR(INTR), + .READY(READY), + .clk(clk), + .rst(rst), + .D_out(D_out), + .Sync(Sync), + .state(state) + ); + assign led = {rst, clk, chip_inputs[9:8], chip_outputs[10:0], chip_inputs[7:0]}; +endmodule +module i8008_core ( + D_in, + INTR, + READY, + clk, + rst, + D_out, + Sync, + state +); + parameter WIDTH = 8; + parameter STACK_HEIGHT = 8; + input wire [7:0] D_in; + input wire INTR; + input wire READY; + input wire clk; + input wire rst; + output wire [7:0] D_out; + output wire Sync; + output wire [2:0] state; + reg [7:0] bus; + wire [7:0] instr; + wire enable_SP; + reg Ready; + reg tempR; + reg Intr; + reg S_Intr; + wire A_rst; + wire B_rst; + wire IR_rst; + wire SP_rst; + wire IR_en; + wire A_en; + wire [7:0] A_in; + wire [7:0] A_out; + wire [7:0] B_in; + wire [7:0] B_out; + wire [7:0] ALU_out; + wire [7:0] DBR_out; + wire [7:0] DBR_in; + wire [7:0] PC_out; + wire [7:0] rf_out; + wire [7:0] ACC; + wire [39:0] ctrl_signals; + wire [3:0] flags; + wire [2:0] sel_Stack; + wire [1:0] cycle; + always @(posedge clk) begin + if (rst) begin + Ready <= 1'b0; + tempR <= 1'b0; + end + else begin + tempR <= READY; + Ready <= tempR; + end + if (rst) begin + Intr <= 1'b0; + S_Intr <= 1'b0; + end + else if (state != 3'b110) begin + S_Intr <= INTR; + Intr <= Intr | S_Intr; + end + else begin + Intr <= 1'b0; + S_Intr <= 1'b0; + end + end + assign Sync = ctrl_signals[38]; + assign D_out = bus; + always @(*) + if (ctrl_signals[5]) + bus = PC_out | (ctrl_signals[4] ? 8'd0 : ctrl_signals[1-:2] << 6); + else if (ctrl_signals[11]) + bus = rf_out | (ctrl_signals[1-:2] << 6); + else if (ctrl_signals[24]) + bus = ALU_out; + else if (ctrl_signals[27]) begin + bus[7:4] = 4'd0; + bus[3:0] = flags; + end + else if (ctrl_signals[33]) + bus = A_out; + else if (ctrl_signals[30]) + bus = B_out | (ctrl_signals[1-:2] << 6); + else if (ctrl_signals[39]) + bus = D_in; + else + bus = 8'd0; + assign IR_rst = ctrl_signals[34] | rst; + assign IR_en = ctrl_signals[35] | (Ready && (cycle == 2'b00)); + Register #(.WIDTH(WIDTH)) IR( + .d(D_in), + .Q(instr), + .clk(clk), + .en(IR_en), + .clear(IR_rst) + ); + assign A_rst = ctrl_signals[31] | rst; + assign B_rst = ctrl_signals[28] | rst; + assign A_en = ctrl_signals[32]; + assign A_in = ((cycle == 2'b00) && ((state == 3'b010) || (state == 3'b110)) ? ACC : bus); + Register #(.WIDTH(WIDTH)) regA( + .d(A_in), + .Q(A_out), + .clk(clk), + .en(A_en), + .clear(A_rst) + ); + Register #(.WIDTH(WIDTH)) regB( + .d(bus), + .Q(B_out), + .clk(clk), + .en(ctrl_signals[29]), + .clear(B_rst) + ); + ALU Unit( + .clk(clk), + .rst(rst), + .a(A_out), + .b(B_out), + .ALU_ctrl(ctrl_signals[24-:10]), + .d(ALU_out), + .flags(flags) + ); + reg_file #( + .WIDTH(WIDTH), + .HEIGHT(7) + ) rf( + .clk(clk), + .rst(rst), + .bus(bus), + .ACC(ACC), + .rf_out(rf_out), + .rf_ctrl(ctrl_signals[14-:5]) + ); + assign enable_SP = (ctrl_signals[9] & ~((sel_Stack == 3'd0) & ~ctrl_signals[7])) & ~((sel_Stack == 3'd7) & ctrl_signals[7]); + assign SP_rst = ctrl_signals[8] | rst; + Counter #(.WIDTH(3)) SP_SEL( + .load(1'd0), + .clk(clk), + .d(3'd0), + .Q(sel_Stack), + .en(enable_SP), + .clear(SP_rst), + .up(ctrl_signals[7]) + ); + stack #( + .WIDTH(14), + .HEIGHT(STACK_HEIGHT) + ) Stack( + .clk(clk), + .rst(rst), + .PC_out(PC_out), + .bus(bus), + .sel(sel_Stack), + .Stack_ctrl(ctrl_signals[6-:7]) + ); + fsm_decoder Brain( + .clk(clk), + .Ready(Ready), + .Intr(Intr), + .rst(rst), + .instr(instr), + .flags(flags), + .ctrl_signals(ctrl_signals), + .state(state), + .cycle(cycle) + ); +endmodule +module ALU ( + a, + b, + ALU_ctrl, + clk, + rst, + d, + flags +); + parameter WIDTH = 8; + input wire [7:0] a; + input wire [7:0] b; + input wire [9:0] ALU_ctrl; + input clk; + input rst; + output reg [7:0] d; + output wire [3:0] flags; + wire [7:0] add_tmp; + wire [7:0] art_tmp; + reg [3:0] flag_in; + reg [7:0] NA; + wire Flag_rst; + assign Flag_rst = rst | ALU_ctrl[0]; + FlagRegister #(.WIDTH(4)) flag_reg( + .d(flag_in), + .Q(flags), + .clk(clk), + .en(ALU_ctrl[1]), + .clear(Flag_rst) + ); + always @(*) begin + flag_in[0] = 1'b0; + NA = 'd0; + d = 'd0; + if (ALU_ctrl[2]) + case (ALU_ctrl[5-:3]) + 3'b100: begin + d = a + 1; + flag_in[0] = flags[0]; + end + 3'b101: begin + d = a - 1; + flag_in[0] = flags[0]; + end + 3'b000: begin + d = {a[6:0], a[7]}; + flag_in[0] = a[7]; + end + 3'b001: begin + d = {a[0], a[7:1]}; + flag_in[0] = a[0]; + end + 3'b010: begin + d = {a[6:0], flags[0]}; + flag_in[0] = a[7]; + end + 3'b011: begin + d = {flags[0], a[7:1]}; + flag_in[0] = a[0]; + end + endcase + else begin + d = 'd0; + case (ALU_ctrl[8-:3]) + 3'b000: {flag_in[0], d} = a + b; + 3'b001: {flag_in[0], d} = (a + b) + flags[0]; + 3'b010: {flag_in[0], d} = a - b; + 3'b011: {flag_in[0], d} = (a - b) - flags[0]; + 3'b100: d = a & b; + 3'b110: d = a | b; + 3'b101: d = a ^ b; + 3'b111: begin + {flag_in[0], NA} = a - b; + d = a; + end + default: d = 'b0; + endcase + end + if (ALU_ctrl[2]) begin + flag_in[1] = ((ALU_ctrl[5-:3] == 3'b100) || (ALU_ctrl[5-:3] == 3'b101) ? ~(|d) : flags[1]); + flag_in[2] = ((ALU_ctrl[5-:3] == 3'b100) || (ALU_ctrl[5-:3] == 3'b101) ? d[7] : flags[2]); + flag_in[3] = ((ALU_ctrl[5-:3] == 3'b100) || (ALU_ctrl[5-:3] == 3'b101) ? ~(^d) : flags[3]); + end + else begin + flag_in[1] = (ALU_ctrl[8-:3] != 3'b111 ? ~(|d) : ~(|NA)); + flag_in[2] = (ALU_ctrl[8-:3] != 3'b111 ? d[7] : NA[7]); + flag_in[3] = (ALU_ctrl[8-:3] != 3'b111 ? ~(^d) : ~(^NA)); + end + end +endmodule +module fsm_decoder ( + clk, + Ready, + Intr, + rst, + instr, + flags, + ctrl_signals, + state, + cycle +); + input wire clk; + input wire Ready; + input wire Intr; + input wire rst; + input wire [7:0] instr; + input wire [3:0] flags; + output reg [39:0] ctrl_signals; + output reg [2:0] state; + output reg [1:0] cycle; + wire [2:0] SSS; + wire [2:0] DDD; + wire [2:0] D5_3; + assign SSS = instr[2:0]; + assign DDD = instr[5:3]; + assign D5_3 = instr[5:3]; + reg [1:0] next_cycle; + reg [2:0] next_state; + reg CF; + always @(*) + case (instr[4:3]) + 2'b00: CF = ~flags[0]; + 2'b01: CF = ~flags[1]; + 2'b10: CF = ~flags[2]; + 2'b11: CF = ~flags[3]; + default: CF = 1'b1; + endcase + always @(*) begin + next_cycle = cycle; + ctrl_signals = 'd0; + case (cycle) + 2'b00: + case (state) + 3'b010, 3'b110: begin + next_state = 3'b100; + ctrl_signals[38] = 1'b1; + ctrl_signals[5] = 1'b1; + ctrl_signals[4] = 1'b1; + ctrl_signals[32] = 1'b1; + end + 3'b100: begin + next_state = (Ready ? 3'b001 : 3'b000); + ctrl_signals[38] = 1'b1; + ctrl_signals[5] = 1'b1; + ctrl_signals[4] = 1'b0; + ctrl_signals[1-:2] = 2'b00; + ctrl_signals[3] = 1'b1; + end + 3'b000: next_state = (Ready ? 3'b001 : 3'b000); + 3'b001, 3'b011: begin + if (instr == 8'b00zzz101) begin + ctrl_signals[29] = 1'b1; + ctrl_signals[31] = 1'b1; + ctrl_signals[7] = 1'b1; + ctrl_signals[9] = 1'b1; + ctrl_signals[39] = 1'b1; + end + else begin + ctrl_signals[29] = 1'b1; + ctrl_signals[39] = 1'b1; + end + casez (instr) + 8'b0000000z, 8'b11111111, 8'b11zzz111: + if (instr[7] && (D5_3 != 3'b111)) begin + next_cycle = 2'b01; + next_state = 3'b010; + end + else if (Intr) begin + next_state = 3'b110; + next_cycle = 2'b00; + end + else + next_state = 3'b011; + 8'b000zz011, 8'b001zz011: + if ((instr[5] & ~CF) | (~instr[5] & CF)) + next_state = 3'b111; + else begin + next_cycle = 2'b00; + next_state = 3'b010; + end + 8'b10zzz111, 8'b00zzz100, 8'b0100zzz1, 8'b01zzzzz1, 8'b00zzz110, 8'b01zzz100, 8'b010zz000, 8'b011zz000, 8'b01zzz110, 8'b011zz010, 8'b010zz010: begin + next_cycle = 2'b01; + next_state = 3'b010; + end + default: next_state = 3'b111; + endcase + end + 3'b111: begin + casez (instr) + 8'b11zzzzzz, 8'b11111zzz, 8'b10zzzzzz: begin + ctrl_signals[29] = 1'b1; + ctrl_signals[11] = 1'b1; + ctrl_signals[14-:3] = SSS; + end + 8'b00zzz000, 8'b00zzz001: begin + ctrl_signals[11] = 1'b1; + ctrl_signals[14-:3] = DDD; + ctrl_signals[32] = 1'b1; + end + 8'b00000010, 8'b00001010, 8'b00010010, 8'b00011010: begin + ctrl_signals[11] = 1'b1; + ctrl_signals[14-:3] = 3'd0; + ctrl_signals[32] = 1'b1; + end + 8'b00zzz111, 8'b000zz011, 8'b001zz011: begin + ctrl_signals[7] = 1'b0; + ctrl_signals[9] = 1'b1; + end + 8'b00zzz101: begin + ctrl_signals[33] = 1'b1; + ctrl_signals[4] = 1'b0; + ctrl_signals[6] = 1'b1; + end + default: + ; + endcase + if (instr[7:3] == 5'b11111) begin + next_state = 3'b010; + next_cycle = 2'b01; + end + else + next_state = 3'b101; + end + 3'b101: begin + casez (instr) + 8'b11zzzzzz: begin + ctrl_signals[30] = 1'b1; + ctrl_signals[10] = 1'b1; + ctrl_signals[14-:3] = DDD; + end + 8'b00zzz101: begin + ctrl_signals[30] = 1'b1; + ctrl_signals[6] = 1'b1; + ctrl_signals[4] = 1'b1; + ctrl_signals[2] = 1'b1; + end + 8'b00zzz000, 8'b00zzz001: begin + ctrl_signals[10] = 1'b1; + ctrl_signals[14-:3] = DDD; + ctrl_signals[20-:3] = (instr[2:0] == 3'b000 ? 3'b100 : 3'b101); + ctrl_signals[17] = 1'b1; + ctrl_signals[24] = 1'b1; + ctrl_signals[16] = 1'b1; + end + 8'b10zzzzzz: begin + ctrl_signals[10] = 1'b1; + ctrl_signals[14-:3] = 3'd0; + ctrl_signals[23-:3] = D5_3; + ctrl_signals[17] = 1'b0; + ctrl_signals[24] = 1'b1; + ctrl_signals[16] = 1'b1; + end + 8'b00000010, 8'b00001010, 8'b00010010, 8'b00011010: begin + ctrl_signals[10] = 1'b1; + ctrl_signals[14-:3] = 3'd0; + ctrl_signals[20-:3] = D5_3; + ctrl_signals[17] = 1'b1; + ctrl_signals[24] = 1'b1; + ctrl_signals[16] = 1'b1; + end + default: + ; + endcase + next_state = 3'b010; + next_cycle = 2'b00; + end + default: begin + next_state = 3'b010; + next_cycle = 2'b00; + end + endcase + 2'b01: + case (state) + 3'b010, 3'b110: begin + next_state = 3'b100; + casez (instr) + 8'b00111110, 8'b00zzz110, 8'b00zzz100, 8'b01zzz100, 8'b010zz000, 8'b011zz000, 8'b01zzz110, 8'b011zz010, 8'b010zz010: begin + ctrl_signals[5] = 1'b1; + ctrl_signals[4] = 1'b1; + ctrl_signals[38] = 1'b1; + end + 8'b11zzz111, 8'b11111zzz, 8'b10zzz111: begin + ctrl_signals[11] = 1'b1; + ctrl_signals[14-:3] = 3'd6; + ctrl_signals[38] = 1'b1; + end + 8'b0100zzz1, 8'b01zzzzz1: begin + ctrl_signals[33] = 1'b1; + ctrl_signals[38] = 1'b1; + end + default: + ; + endcase + end + 3'b100: begin + next_state = (Ready ? 3'b001 : 3'b000); + casez (instr) + 8'b00111110, 8'b00zzz110, 8'b00zzz100, 8'b01zzz100, 8'b010zz000, 8'b011zz000, 8'b01zzz110, 8'b011zz010, 8'b010zz010: begin + ctrl_signals[5] = 1'b1; + ctrl_signals[38] = 1'b1; + ctrl_signals[1-:2] = 2'b01; + ctrl_signals[4] = 1'b0; + ctrl_signals[3] = 1'b1; + end + 8'b11zzz111, 8'b11111zzz, 8'b10zzz111: begin + ctrl_signals[11] = 1'b1; + ctrl_signals[14-:3] = 3'd5; + ctrl_signals[1-:2] = (instr[7:3] == 5'b11111 ? 2'b11 : 2'b01); + ctrl_signals[4] = 1'b0; + ctrl_signals[38] = 1'b1; + end + 8'b0100zzz1, 8'b01zzzzz1: begin + ctrl_signals[1-:2] = 2'b10; + ctrl_signals[4] = 1'b0; + ctrl_signals[30] = 1'b1; + ctrl_signals[38] = 1'b1; + end + default: + ; + endcase + end + 3'b000: next_state = (Ready ? 3'b001 : 3'b000); + 3'b001, 3'b011: begin + casez (instr) + 8'b01zzzzz1, 8'b11111zzz: begin + next_cycle = 2'b00; + next_state = 3'b010; + end + 8'b00111110, 8'b01zzz100, 8'b010zz000, 8'b011zz000, 8'b01zzz110, 8'b011zz010, 8'b010zz010: begin + next_state = 3'b010; + next_cycle = 2'b10; + end + default: next_state = 3'b111; + endcase + casez (instr) + 8'b0100zzz1, 8'b10zzz111, 8'b00zzz100, 8'b11zzz111, 8'b00111110, 8'b00zzz110, 8'b01zzz100, 8'b010zz000, 8'b011zz000, 8'b01zzz110, 8'b011zz010, 8'b010zz010: begin + ctrl_signals[39] = 1'b1; + ctrl_signals[29] = 1'b1; + end + 8'b11111zzz: begin + ctrl_signals[38] = 1'b1; + ctrl_signals[30] = 1'b1; + end + default: + ; + endcase + end + 3'b111: begin + next_state = 3'b101; + if ((instr[7:4] == 4'b0100) && instr[0]) begin + ctrl_signals[38] = 1'b1; + ctrl_signals[27] = 1'b1; + end + end + 3'b101: begin + next_state = 3'b010; + next_cycle = 2'b00; + casez (instr) + 8'b11zzz111, 8'b00zzz110, 8'b0100zzz1: begin + ctrl_signals[30] = 1'b1; + ctrl_signals[14-:3] = ((instr[7:4] == 4'b0100) && instr[0] ? 3'd0 : DDD); + ctrl_signals[10] = 1'b1; + end + 8'b10zzz111, 8'b00zzz100: begin + ctrl_signals[14-:3] = 3'd0; + ctrl_signals[10] = 1'b1; + ctrl_signals[23-:3] = D5_3; + ctrl_signals[17] = 1'b0; + ctrl_signals[24] = 1'b1; + ctrl_signals[16] = 1'b1; + end + default: + ; + endcase + end + default: begin + next_cycle = 2'b00; + next_state = 3'b010; + end + endcase + 2'b10: + case (state) + 3'b010, 3'b110: begin + next_state = 3'b100; + casez (instr) + 8'b00111110: begin + ctrl_signals[14-:3] = 3'd6; + ctrl_signals[11] = 1'b1; + ctrl_signals[38] = 1'b1; + end + 8'b01zzz100, 8'b010zz000, 8'b011zz000, 8'b01zzz110, 8'b011zz010, 8'b010zz010: begin + ctrl_signals[5] = 1'b1; + ctrl_signals[4] = 1'b1; + ctrl_signals[38] = 1'b1; + end + default: + ; + endcase + end + 3'b100: begin + next_state = (Ready ? 3'b001 : 3'b000); + casez (instr) + 8'b00111110: begin + ctrl_signals[14-:3] = 3'd5; + ctrl_signals[11] = 1'b1; + ctrl_signals[38] = 1'b1; + ctrl_signals[1-:2] = 2'b11; + ctrl_signals[4] = 1'b0; + end + 8'b01zzz100, 8'b010zz000, 8'b011zz000, 8'b01zzz110, 8'b011zz010, 8'b010zz010: begin + ctrl_signals[5] = 1'b1; + ctrl_signals[4] = 1'b0; + ctrl_signals[38] = 1'b1; + ctrl_signals[1-:2] = 2'b01; + ctrl_signals[3] = 1'b1; + end + default: + ; + endcase + end + 3'b000: next_state = (Ready ? 3'b001 : 3'b000); + 3'b001, 3'b011: begin + casez (instr) + 8'b00111110: begin + next_state = 3'b010; + next_cycle = 2'b00; + end + 8'b01zzz110: begin + ctrl_signals[7] = 1'b1; + ctrl_signals[9] = 1'b1; + next_state = 3'b111; + end + 8'b010zz000, 8'b010zz010: + if (~CF) begin + next_state = 3'b010; + next_cycle = 2'b00; + end + else begin + if ((instr[7:5] == 3'b010) && (instr[2:0] == 3'b010)) begin + ctrl_signals[7] = 1'b1; + ctrl_signals[9] = 1'b1; + end + next_state = 3'b111; + end + 8'b011zz000, 8'b011zz010: + if (CF) begin + next_state = 3'b010; + next_cycle = 2'b00; + end + else begin + if ((instr[7:5] == 3'b011) && (instr[2:0] == 3'b010)) begin + ctrl_signals[7] = 1'b1; + ctrl_signals[9] = 1'b1; + end + next_state = 3'b111; + end + default: next_state = 3'b111; + endcase + casez (instr) + 8'b00111110: begin + ctrl_signals[30] = 1'b1; + ctrl_signals[38] = 1'b1; + end + 8'b01zzz100, 8'b010zz000, 8'b011zz000, 8'b01zzz110, 8'b011zz010, 8'b010zz010: begin + ctrl_signals[32] = 1'b1; + ctrl_signals[39] = 1'b1; + end + default: + ; + endcase + end + 3'b111: begin + next_state = 3'b101; + casez (instr) + 8'b01zzz110, 8'b011zz010, 8'b010zz010: begin + ctrl_signals[33] = 1'b1; + ctrl_signals[6] = 1'b1; + ctrl_signals[4] = 1'b0; + end + 8'b01zzz100, 8'b010zz000, 8'b011zz000: begin + ctrl_signals[33] = 1'b1; + ctrl_signals[6] = 1'b1; + ctrl_signals[4] = 1'b0; + end + default: + ; + endcase + end + 3'b101: begin + next_state = 3'b010; + next_cycle = 2'b00; + casez (instr) + 8'b01zzz110, 8'b011zz010, 8'b010zz010, 8'b01zzz100, 8'b010zz000, 8'b011zz000: begin + ctrl_signals[30] = 1'b1; + ctrl_signals[6] = 1'b1; + ctrl_signals[4] = 1'b1; + end + default: + ; + endcase + end + default: begin + next_state = 3'b010; + next_cycle = 2'b00; + end + endcase + default: begin + next_state = 3'b010; + next_cycle = 2'b00; + ctrl_signals = 'd0; + end + endcase + end + always @(posedge clk) + if (rst) begin + cycle <= 2'b00; + state <= 3'b010; + end + else begin + cycle <= next_cycle; + state <= next_state; + end +endmodule +module reg_file ( + bus, + clk, + rst, + rf_ctrl, + rf_out, + ACC +); + parameter WIDTH = 8; + parameter HEIGHT = 7; + parameter SEL = $clog2(HEIGHT); + input wire [7:0] bus; + input wire clk; + input wire rst; + input wire [4:0] rf_ctrl; + output wire [7:0] rf_out; + output wire [7:0] ACC; + reg [7:0] rf [0:6]; + reg [7:0] rs; + wire [2:0] sel; + assign sel = (rf_ctrl[4-:3] == 3'b111 ? 3'd0 : rf_ctrl[4-:3]); + assign rf_out = rs; + assign ACC = rf[0]; + always @(posedge clk) + if (rst) begin + rf[3'd0] <= 8'd0; + rf[3'd1] <= 8'd0; + rf[3'd2] <= 8'd0; + rf[3'd3] <= 8'd0; + rf[3'd4] <= 8'd0; + rf[3'd5] <= 8'd0; + rf[3'd6] <= 8'd0; + end + else if (rf_ctrl[0] && (rf_ctrl[4-:3] != 3'b111)) + rf[rf_ctrl[4-:3]] <= bus; + always @(*) rs = rf[sel]; +endmodule +module stack ( + bus, + sel, + clk, + rst, + Stack_ctrl, + PC_out +); + parameter WIDTH = 14; + parameter BUS_WIDTH = 8; + parameter HEIGHT = 8; + parameter SEL = $clog2(HEIGHT); + input wire [7:0] bus; + input wire [2:0] sel; + input wire clk; + input wire rst; + input wire [6:0] Stack_ctrl; + output wire [7:0] PC_out; + reg [13:0] rf [0:7]; + reg [13:0] rs; + wire [7:0] upper; + wire [7:0] RST_AAA; + assign upper = {2'd0, rs[13:8]}; + assign PC_out = (Stack_ctrl[4] ? rs[7:0] : upper); + assign RST_AAA[5:3] = bus[5:3]; + assign RST_AAA[2:0] = 3'd0; + assign RST_AAA[7:6] = 2'd0; + always @(posedge clk) + if (rst) begin + rf[3'd0] <= 14'd0; + rf[3'd1] <= 14'd0; + rf[3'd2] <= 14'd0; + rf[3'd3] <= 14'd0; + rf[3'd4] <= 14'd0; + rf[3'd5] <= 14'd0; + rf[3'd6] <= 14'd0; + rf[3'd7] <= 14'd0; + end + else if (Stack_ctrl[6] && Stack_ctrl[4]) + rf[sel] <= (Stack_ctrl[2] ? {8'd0, RST_AAA} : {rf[sel][13:8], bus}); + else if (Stack_ctrl[6] && ~Stack_ctrl[4]) + rf[sel] <= {bus[5:0], rf[sel][7:0]}; + else if (Stack_ctrl[3]) + rf[sel] <= rf[sel] + 1; + always @(*) rs = rf[sel]; +endmodule +module Register ( + en, + clear, + clk, + d, + Q +); + parameter WIDTH = 8; + input wire en; + input wire clear; + input wire clk; + input wire [7:0] d; + output reg [7:0] Q; + always @(posedge clk) + if (clear) + Q <= 'd0; + else if (en) + Q <= d; +endmodule +module FlagRegister ( + en, + clear, + clk, + d, + Q +); + parameter WIDTH = 4; + input wire en; + input wire clear; + input wire clk; + input wire [3:0] d; + output reg [3:0] Q; + always @(posedge clk) + if (clear) + Q <= 'd0; + else if (en) + Q <= d; +endmodule +module Counter ( + en, + clear, + load, + up, + clk, + d, + Q +); + parameter WIDTH = 3; + input wire en; + input wire clear; + input wire load; + input wire up; + input wire clk; + input wire [2:0] d; + output reg [2:0] Q; + always @(posedge clk) + if (clear) + Q <= 'd0; + else if (load) + Q <= d; + else if (en && up) + Q <= Q + 1; + else if (en && ~up) + Q <= Q - 1; +endmodule +module Stabilizer ( + D, + clk, + Q +); + input wire D; + input wire clk; + output reg Q; + reg temp; + always @(posedge clk) begin + temp <= D; + Q <= temp; + end +endmodule +`default_nettype wire diff --git a/designs/d29_bwilhelm_i8008/src/pin_order.cfg b/designs/d29_bwilhelm_i8008/src/pin_order.cfg new file mode 100644 index 0000000..0b85c63 --- /dev/null +++ b/designs/d29_bwilhelm_i8008/src/pin_order.cfg @@ -0,0 +1,9 @@ +#N + +#S + +#E + +#W +io_in.* +io_out.* diff --git a/designs/d29_bwilhelm_i8008/src/toplevel_chip.v b/designs/d29_bwilhelm_i8008/src/toplevel_chip.v new file mode 100644 index 0000000..a82b427 --- /dev/null +++ b/designs/d29_bwilhelm_i8008/src/toplevel_chip.v @@ -0,0 +1,18 @@ +`default_nettype none + +// DO NOT EDIT THIS FILE +module toplevel_chip ( + input [13:0] io_in, + output [13:0] io_out +); + + my_chip mchip ( + .io_in(io_in[11:0]), + .io_out(io_out[11:0]), + .clock(io_in[12]), + .reset(io_in[13]) + ); + + assign io_out[13:12] = 2'b00; + +endmodule diff --git a/designs/d29_bwilhelm_i8008/tests/Makefile b/designs/d29_bwilhelm_i8008/tests/Makefile new file mode 100644 index 0000000..bca1ebe --- /dev/null +++ b/designs/d29_bwilhelm_i8008/tests/Makefile @@ -0,0 +1,11 @@ +TOPLEVEL_LANG ?= verilog + +PWD=$(shell pwd) + +#export PYTHONPATH := $(PWD)/../model:$(PYTHONPATH) + +VERILOG_SOURCES = $(PWD)/../src/i8008_core.v +TOPLEVEL := i8008_core +MODULE := i8008_tb + +include $(shell cocotb-config --makefiles)/Makefile.sim \ No newline at end of file diff --git a/designs/d29_bwilhelm_i8008/tests/debugChip.py b/designs/d29_bwilhelm_i8008/tests/debugChip.py new file mode 100644 index 0000000..51df754 --- /dev/null +++ b/designs/d29_bwilhelm_i8008/tests/debugChip.py @@ -0,0 +1,83 @@ +# Install dependencies PySerial +# - pip3 install pyserial + +# NOTE: Change the serial port here to match the one on your computer +# on macOS it looks something like "/dev/tty.usbserial-FT4MG9OV1" +# on Windows it looks something like "COM2" +# on Linux it looks like "/dev/ttyACM0" +SERIAL_PORT = "/dev/tty.usbserial-FT4MG9OV1" + +from interface import Chip +import serial.tools.list_ports +import time + +print("Listing all available serial ports:") +ports = serial.tools.list_ports.comports() +for port, desc, hwid in sorted(ports): + print("{}: {} [{}]".format(port, desc, hwid)) + +chip = Chip(SERIAL_PORT) + + +print("Resetting...") +chip.set_reset(1) +chip.step_clock() +chip.set_reset(0) + +for _ in range(10): + print("{:012b}".format(chip.get_all_outputs())) + chip.step_clock() + time.sleep(0.5) + + +print("Resetting...") +chip.set_reset(1) +chip.step_clock() +chip.set_reset(0) +print("{:012b}".format(chip.get_all_outputs())) +chip.step_clock() + +# assign D_in = chip_inputs[7:0]; +# assign INTR = chip_inputs[8]; +# assign READY = chip_inputs[9]; + +print("{:012b}".format(chip.get_all_outputs())) +chip.set_all_inputs(0b00_10_00001000) +chip.step_clock() +time.sleep(0.5) + +print("{:012b}".format(chip.get_all_outputs())) +chip.set_all_inputs(0b00_10_00001000) +chip.step_clock() +time.sleep(0.5) + +print("{:012b}".format(chip.get_all_outputs())) +chip.set_all_inputs(0b00_10_00001000) +chip.step_clock() +time.sleep(0.5) + +print("{:012b}".format(chip.get_all_outputs())) +chip.set_all_inputs(0b00_00_00001000) +chip.step_clock() +time.sleep(0.5) + +print("{:012b}".format(chip.get_all_outputs())) +chip.set_all_inputs(0b00_00_00001000) +chip.step_clock() +time.sleep(0.5) + +print("{:012b}".format(chip.get_all_outputs())) +chip.set_all_inputs(0b00_00_00001000) +chip.step_clock() +time.sleep(0.5) + +print("{:012b}".format(chip.get_all_outputs())) +chip.set_all_inputs(0b00_00_00001000) +chip.step_clock() +time.sleep(0.5) + +# TODO: Modify to accept input every cycle and print formatted outputs + +# Other useful commands: +# print(chip.get_output(0)) - gets the lowest bit of the chip's outputs +# chip.set_input(0, 1) - sets the lowest bit of the chip's inputs to be high diff --git a/designs/d29_bwilhelm_i8008/tests/i8008_tb.py b/designs/d29_bwilhelm_i8008/tests/i8008_tb.py new file mode 100644 index 0000000..bd740ce --- /dev/null +++ b/designs/d29_bwilhelm_i8008/tests/i8008_tb.py @@ -0,0 +1,1542 @@ +import os +import random +import sys +from pathlib import Path + +import cocotb +from cocotb.clock import Clock +from cocotb.runner import get_runner +from cocotb.triggers import Timer +from cocotb.triggers import RisingEdge + +from interface import Chip +import serial.tools.list_ports +import time + +SERIAL_PORT = "/dev/tty.usbserial-FT4MG9OV1" +CLK_TIME = .001 + +# print("Listing all available serial ports:") +# ports = serial.tools.list_ports.comports() +# for port, desc, hwid in sorted(ports): +# print("{}: {} [{}]".format(port, desc, hwid)) + + +PCI = 0b00 +PCR = 0b01 +PCC = 0b10 +PCW = 0b11 + +CYCLE1 = 0b00 +CYCLE2 = 0b01 +CYCLE3 = 0b10 + +Carry_bit = 0b1000 +Zero_bit = 0b0100 +Sign_bit = 0b0010 +Parity_bit = 0b0001 + +Ca = 0b00 +Ze = 0b01 +Si = 0b10 +Pa = 0b11 + +A = 0 +B = 1 +C = 2 +D = 3 +E = 4 +Hi = 5 +Lo = 6 +Mem = 0b111 + +# State defines +T1 = 2 #0b010 +T1I = 6 #0b110 +T2 = 4 #0b100 +WAIT = 0 # 0b000 +T3 = 1 # 0b001 +STOPPED = 3 # 0b011 +T4 = 7 # 0b111 +T5 = 5 # 0b101 + +op_mask = 0b11_000_111 +reg_mask = 0b00_111_000 + +Lr1r2 = 0b11_000_000 +LrI = 0b00_000_110 +LMI = 0b00_111_110 +LrM = 0b11_000_111 +LMr = 0b11_111_000 + +INr = 0b00_000_000 +DCr = 0b00_000_001 + +# ALU uops +ADx = 0b000 +ADr = 0b10_000_000 +ACx = 0b001 +SUx = 0b010 +SBx = 0b011 +NDx = 0b100 +XRx = 0b101 +ORx = 0b110 +CPx = 0b111 +CPI = 0b00_111_100 +CPM = 0b10_111_111 +alu_r_M_op = 0b10_000_000 +alu_I_op = 0b00_000_100 + +# ALU logic uops +RLC = 0b000 +RRC = 0b001 +RAL = 0b010 +RAR = 0b011 +alu_rot_op = 0b00_000_010 +alu_inr_op = 0b00_000_000 + + +JMP = 0b01_000_100 +JFc = 0b01_000_000 +JTc = 0b01_100_000 +CAL = 0b01_000_110 +CFc = 0b01_000_010 +CTc = 0b01_100_010 +RET = 0b00_000_111 +RFc = 0b00_000_011 +RTc = 0b00_100_011 +RST = 0b00_000_101 + +HLT0 = 0b00_000_000 +HLT0_1 = 0b00_000_001 +HLT1 = 0b11_111_111 + +verbose = False + +class i8008_model: + def __init__(self): + self.reg_file = [0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000] + self.pc = [0b00_0000_0000_0000, 0b00_0000_0000_0000, 0b00_0000_0000_0000, 0b00_0000_0000_0000, 0b00_0000_0000_0000, 0b00_0000_0000_0000, 0b00_0000_0000_0000, 0b00_0000_0000_0000] + self.stack_ind = 0 + self.flags = 0b0000 + self.prog = dict() + self.instr_addrs = [] + + def write_pc(self, pc): + self.pc[self.stack_ind] = pc + + def push_pc(self, new_pc): + if self.stack_ind != 7: + self.stack_ind = self.stack_ind + 1 + self.pc[self.stack_ind] = new_pc + + def pop_pc(self): + if self.stack_ind != 0: + self.stack_ind = self.stack_ind - 1 + + def incr_pc(self): + self.pc[self.stack_ind] = self.pc[self.stack_ind] + 1 + + def get_pc(self): + return self.pc[self.stack_ind] + + def update_flags(self, flags): + self.flags = flags #PSZC + + def gen_flags(self, res): + carry = (res & 0b100000000) >> 8 + res = res & 0b11111111 + zero = 0b0000 + if res == 0b00000000: + zero = 0b0010 + + sign = (res >> 7) << 2 + parity = (res >> 4) ^ (res & 0b1111) + parity = (parity >> 2) ^ (parity & 0b11) + if (parity == 0 or parity == 3): + parity = 0b1000 + else: + parity = 0b0000 + + self.flags = carry | zero | sign | parity + + def update_carry(self, carry): + self.flags = (self.flags & 0b1110) | (carry & 0b1) + + def get_carry(self): + return self.flags & 0b0001 + + def get_zero(self): + return (self.flags & 0b0010) >> 1 + + def get_sign(self): + return (self.flags & 0b0100) >> 2 + + def get_parity(self): + return self.flags >> 3 + + def cond_met(self, cond): + if cond == Ca: + return self.get_carry() + elif cond == Ze: + return self.get_zero() + elif cond == Si: + return self.get_sign() + elif cond == Pa: + return self.get_parity() + else: + return 0 + + def read_mem(self, addr): + if addr in self.prog: + return self.prog[addr] + else: + self.prog[addr] = 0b00000000 + return 0b00000000 + + def write_mem(self, addr, data): + if addr not in self.instr_addrs: # Don't allow writes to instruction memory + self.prog[addr] = data + + def get_rf_addr(self): + return self.reg_file[Hi] << 6 | self.reg_file[Lo] + + def read_rf(self, rf_ind): + if rf_ind == 0b111: + return self.read_mem(self.get_rf_addr()) + elif rf_ind >= 0b000 or rf_ind <= 0b110: + return self.reg_file[rf_ind] + else: assert 1 == 0, "BAD READ" + + def write_rf(self, rf_ind, data): + if rf_ind == 0b111: + self.write_mem(self.get_rf_addr(), data) + else: + self.reg_file[rf_ind] = data + + def state_check(self, dut, instr): + for i in range(8): + assert self.pc[i] == dut.Stack._id(f"rf[{i}]", extended=False).value, "Model failed with: %r, %r != %r" % (bin(instr), bin(self.pc[i]), dut.Stack._id(f"rf[{i}]", extended=False).value) + + for i in range(7): + assert self.reg_file[i] == dut.rf._id(f"rf[{i}]", extended=False).value, "Model failed with: %r %r, %r != %r" % (bin(instr), i, bin(self.reg_file[i]), dut.rf._id(f"rf[{i}]", extended=False).value) + assert self.flags == dut.Unit.flags.value, "Model failed with: %r, %r != %r" % (bin(instr), bin(self.flags), dut.Unit.flags.value) + + def dump_reg(self): + print("ModelDump:") + print("Stack_sel: ", self.stack_ind) + for sel in range(8): + print("\tSTACK_{sel}: {bpc} = {ipc}".format(sel=sel, bpc=bin(self.pc[sel]), ipc=self.pc[sel])) + for sel in range(7): + print("\tREG_{reg} = {val}".format(reg=sel, val=bin(self.reg_file[sel]))) + print("\tFlags: ", bin(self.flags)) + + def alu_op(self, D5_3, D2_0, imm, I): + Acc = self.read_rf(0) + Bcc = self.read_rf(D2_0) + + # Set to immediate/memory mode + if I != 0: + Bcc = imm + + if D5_3 == ADx: + res = (Acc + Bcc) + self.gen_flags(res) + self.write_rf(0, res & 0b11111111) + elif D5_3 == ACx: + res = (Acc + Bcc + self.get_carry()) + self.gen_flags(res) + self.write_rf(0, res & 0b11111111) + elif D5_3 == SUx: + res = (Acc + ((~Bcc + 1))) + self.gen_flags(res) + self.write_rf(0, res & 0b11111111) + elif D5_3 == SBx: + res = (Acc + ((~Bcc + 1)) + ((~self.get_carry() + 1))) + self.gen_flags(res) + self.write_rf(0, res & 0b11111111) + elif D5_3 == NDx: + res = (Acc & Bcc) + self.gen_flags(res) + self.write_rf(0, res & 0b11111111) + elif D5_3 == XRx: + res = (Acc ^ Bcc) + self.gen_flags(res) + self.write_rf(0, res & 0b11111111) + elif D5_3 == ORx: + res = (Acc | Bcc) + self.gen_flags(res) + self.write_rf(0, res & 0b11111111) + elif D5_3 == CPx: + res = (Acc + ((~Bcc + 1))) + self.gen_flags(res) + + + def gen_reg_state(self, prog, instr, mem_read, second_mem_read): + imm = mem_read + PC_L = mem_read + PC_H = second_mem_read + + if instr == HLT1 or instr == HLT0 or instr == HLT0_1: + return + + + op_class = (instr & 0b11_000_000) >> 6 + D5_3 = (instr & 0b00_111_000) >> 3 + D2_0 = (instr & 0b00_000_111) + + + if op_class == 0b00: + if D2_0 == 0b110 and D5_3 != 0b111: + #LrI + self.write_rf(D5_3, imm) + elif D2_0 == 0b110 and D5_3 == 0b111: + #LMI + addr = self.get_rf_addr() + self.write_mem(addr, imm) + elif D2_0 == 0b000: + #INr + if (D5_3 != 0b111): + res = (self.read_rf(D5_3)+1) & 0b11111111 + cbit = self.get_carry() + self.gen_flags(res) + self.update_carry(cbit) + self.write_rf(D5_3, res) + else: + assert False, "Invalid instruction" + elif D2_0 == 0b001: + #DCr + assert D5_3 != 0b000 + if (D5_3 != 0b111): + res = (self.read_rf(D5_3)+0b11111111) & 0b11111111 + cbit = self.get_carry() + self.gen_flags(res) + self.update_carry(cbit) + self.write_rf(D5_3, res) + else: + assert False, "Invalid instruction" + elif D2_0 == 0b100: + #ALU OP I + assert self.read_mem(self.get_pc() - 1) == imm + self.alu_op(D5_3, D2_0, imm, 1) + elif D2_0 == 0b010: #rot ops + if D5_3 == RLC: + rf_val = self.read_rf(0) + write_val = ((rf_val << 1) & (0b11111110)) | (rf_val >> 7) + self.write_rf(0, write_val) + self.update_carry(rf_val >> 7) + elif D5_3 == RRC: + rf_val = self.read_rf(0) + write_val = (rf_val >> 1) | ((rf_val << 7) & 0b10000000) + self.write_rf(0, write_val) + self.update_carry(rf_val & 0b00000001) + elif D5_3 == RAL: + rf_val = self.read_rf(0) + write_val = ((rf_val << 1) & (0b11111110)) | (self.get_carry()) + self.write_rf(0, write_val) + self.update_carry(rf_val >> 7) + elif D5_3 == RAR: + rf_val = self.read_rf(0) + write_val = (rf_val >> 1) | ((self.get_carry() << 7) & 0b10000000) + self.write_rf(0, write_val) + self.update_carry(rf_val & 0b00000001) + elif D2_0 == 0b111: + #RET + self.pop_pc() + print("Popped pc") + elif D2_0 == 0b011 and D5_3 >> 2 == 1: + #RTc + if self.cond_met(D5_3 & 0b011): + self.pop_pc() + elif D2_0 == 0b011 and D5_3 >> 2 == 0: + #RFc + if not(self.cond_met(D5_3 & 0b011)): + self.pop_pc() + elif D2_0 == 0b101: + #RST + self.push_pc(D5_3 << 3) + elif op_class == 0b01: + new_pc = PC_L | (PC_H << 8) + if D2_0 == 0b100: + #JMP + self.write_pc(new_pc) + elif D2_0 == 0b000 and (D5_3 >> 2 == 1): + #JTc + cond = (0b011 & D5_3) + if (self.cond_met(cond)): + self.write_pc(new_pc) + elif D2_0 == 0b000 and (D5_3 >> 2 == 0): + #JFc + cond = (0b011 & D5_3) + if (not(self.cond_met(cond))): + self.write_pc(new_pc) + elif D2_0 == 0b110: + #CAL + self.push_pc(new_pc) + elif D2_0 == 0b010 and (D5_3 >> 2 == 1): + #CTc + cond = (0b011 & D5_3) + if (self.cond_met(cond)): + self.push_pc(new_pc) + elif D2_0 == 0b010 and (D5_3 >> 2 == 0): + #CFc + cond = (0b011 & D5_3) + if (not(self.cond_met(cond))): + self.push_pc(new_pc) + elif D2_0 & 0b001 == 1: + if D5_3 >> 1 == 0: + #INP + self.write_rf(0, ) + else: + #OUT + return + elif op_class == 0b10: + # alu ops + self.alu_op(D5_3, D2_0, imm, D2_0 == 0b111) + else: + # Load case + if D5_3 == 0b111: + #LMr + self.write_mem(self.get_rf_addr(), self.read_rf(D2_0)) + elif D2_0 == 0b111: + #LrM + self.write_rf(D5_3, self.read_rf(D2_0)) + #self.reg_file[D5_3] = self.read_mem(self.get_rf_addr()) + else: + #Lr1r2 + self.write_rf(D5_3, self.read_rf(D2_0)) + # self.reg_file[D5_3] = self.reg_file[D2_0] + + return + + def gen_rand_alu_prog(self, length): + self.prog = dict() + addr = 0b00_0000_0000_0000 + + # randomly initialize reg file + for i in range(7): + self.prog[addr] = (LrI | (i << 3)) + self.instr_addrs.append(addr) + addr += 1 + self.prog[addr] = rand_imm() + self.instr_addrs.append(addr) + addr += 1 + + # populate rest of addresses with alu instruction + for _ in range(length): + new_op = rand_alu_op() + self.prog[addr] = new_op + self.instr_addrs.append(addr) + addr += 1 + if (new_op & 0b11_000_111) == alu_I_op: + # Add a value to be read in I case + self.instr_addrs.append(addr) + self.prog[addr] = rand_imm() + addr += 1 + + self.prog[addr] = rand_halt() + self.instr_addrs.append(addr) + + # for i in range(len(self.prog)): + # print(bin(self.prog[i])) + # assert self.prog[i] != 0b00_001_101, "Model failed with: {i}".format(i=i) + + return self.prog + + def gen_ctrl_flow(self): + self.prog = dict() + addr = 0b00_0000_0000_0000 + + # Load 1 into Acc + self.prog[addr] = (LrI | (0 << 3)) + self.instr_addrs.append(addr) + addr += 1 + self.prog[addr] = 0b0000_0001 + self.instr_addrs.append(addr) + addr += 1 + + # Load -1 into B + self.prog[addr] = (LrI | (1 << 3)) + self.instr_addrs.append(addr) + addr += 1 + self.prog[addr] = 0b1111_1111 + self.instr_addrs.append(addr) + addr += 1 + + # Load 2 into C + self.prog[addr] = (LrI | (2 << 3)) + self.instr_addrs.append(addr) + addr += 1 + self.prog[addr] = 0b0000_0010 + self.instr_addrs.append(addr) + addr += 1 + + # Compare A to B + self.prog[addr] = alu_r_M_op | (B) | (CPx << 3) + self.instr_addrs.append(addr) + addr += 1 + + PC = 0b00_1100_0000_0000 + # JMP instruction + self.prog[addr] = CAL | (Ca << 3) + self.instr_addrs.append(addr) + addr += 1 + self.prog[addr] = PC & 0b1111_1111 + self.instr_addrs.append(addr) + addr += 1 + self.prog[addr] = PC >> 8 + self.instr_addrs.append(addr) + addr += 1 + + # Add halt in case of fall through + self.prog[addr] = rand_halt() + self.instr_addrs.append(addr) + addr = PC + + # Add return to test call + self.prog[addr] = RET + self.instr_addrs.append(addr) + addr += 1 + + # Add halt if jump succeeds + self.prog[addr] = rand_halt() + self.instr_addrs.append(addr) + addr += 1 + + return self.prog + + def format_prog(self, asm, start_addr): + prog = dict() + instr_addrs = [] + addr = start_addr + + for i in asm: + prog[addr] = i + addr += 1 + instr_addrs.append(addr) + + self.prog.update(prog) + self.instr_addrs.extend(instr_addrs) + + def fill_mem(self, asm, start_addr): + prog = dict() + addr = start_addr + + for i in asm: + prog[addr] = i + addr += 1 + + self.prog.update(prog) + + def gen_period_search(self, mem): + self.prog = dict() + self.instr_addrs = [] + + period_search = [ + (LrI | (Lo << 3)), # Load 200 into Lo + 200, + (LrI | (Hi << 3)), # Load 0 into Hi + 0, + LrM, # Load character for memory + CPI, + 0b00101110, + (JTc | (Ze << 3)), # If equal go to return + 0b01110111, + 0, + CAL, # Call increment function + 0b00111100, + 0, + (Lr1r2 | (A << 3) | (Lo)), # Load Lo into A + CPI, # Compare with 220 + 220, + (JFc | (Ze << 3)), # If unequal go to loop + 0b01101000, + 0, + RET # Found, return + ] + + increment = [ + (INr | (Lo << 3)), # Increment L + (RFc | (Ze << 3)), # Return if not zero + (INr | (Hi << 3)), # Increment H + RET + ] + + main = [ + CAL, + 100, + 0, + rand_halt() + ] + + # Add instructions to instruction memory + self.format_prog(main, 0) + self.format_prog(period_search, 100) + self.format_prog(increment, 60) + + # Fill memory to search + self.fill_mem(mem, 200) + + def gen_fibonacci(self, num): + # WARNING: can only do 7 levels of recursion + # must call with num >= 0 + self.prog = dict() + self.instr_addrs = [] + # Start at address stored in {hi, lo}, increment twice for every recursion + # store answers in hi lo + # compute fib of number in Acc + + fib = [ + # If check + LMI, + 1, + CPI, # Compare num with 1 + 1, + (RTc | (Ca << 3)), # Return if less than + (RTc | (Ze << 3)), # Return if equal + LMr | (A), + + # b = 1, c = 1 + LrI | (B << 3), + 1, + LrI | (C << 3), + 1, + + #i = 2 + LrI | (E << 3), # Store 2 into E + 1, + + # A = b + c, JUMP HERE + Lr1r2 | (A << 3) | (B), + ADr | (C), + Lr1r2 | (D << 3) | (A), + + # c = b, b = A + Lr1r2 | (C << 3) | B, + Lr1r2 | (B << 3) | D, + + # i++ + INr | (E << 3), + + # while ( i <= num ) + Lr1r2 | (A << 3) | (E), + CPM, + JFc | (Ze << 3), # Jump if less than or equal + 113, + 0, + + LMr | (D), # Store answer to mem + Lr1r2 | (A << 3) | D,# And to A + RET + ] + + main = [ + (LrI | (Lo << 3)), # Load 200 into Lo + 200, + (LrI | (Hi << 3)), # Load 0 into Hi + 0, + (LrI | (0 << 3)), # Load the fib number into Acc + num, + CAL, # Call fib + 100, + 0, + LrM | (A << 3), # Load result from memory + rand_halt() + ] + + mem = [0] + + # Add instructions to instruction memory + self.format_prog(main, 0) + self.format_prog(fib, 100) + + # Fill memory to search + self.fill_mem(mem, 200) + + + +def rand_imm(): + return random.randint(0, 0b11111111) + +def rand_halt(): + choice = random.randint(0, 2) + if choice == 0: + return HLT0 + elif choice == 1: + return HLT0_1 + else: + return HLT1 + +def rand_alu_op(): + a_uops = [ADx, ACx, SUx, SBx, NDx, XRx, ORx, CPx] + r_uops = [RLC, RRC, RAL, RAR] + + # choose random op type and uop type + op_type = random.randint(1,4) + a_uop = random.choice(a_uops) + r_uop = random.choice(r_uops) + + # Choose random register or mem + rrr = random.randint(0, 7) + if (op_type <= 2): + op = alu_r_M_op | (a_uop << 3) | rrr + elif (op_type == 3): + op = alu_I_op | (a_uop << 3) + if op >> 1 == 0b0000000: + op |= alu_r_M_op + else: + if random.randint(0, 1) == 0: + if rrr == 0b111: + rrr -= 1 + if rrr == 0b000: + rrr += 1 + op = alu_inr_op | (rrr << 3) | random.randint(0, 1) + else: + op = alu_rot_op | (r_uop << 3) + + assert op != HLT0 and op != HLT1 and op != HLT0_1 and op & 0b11_000_111 != LrI and op & 0b11_000_111 != RST and op != 0b00_110_101, "{op_type}".format(op_type=op_type) + return op + + +def rand_ctrl(): + choice = random.randint(0, 9) + + if choice == 0: + instr = JMP + elif choice == 1: + instr = JFc + elif choice == 2: + instr = JTc + elif choice == 3: + instr = CAL + elif choice == 4: + instr = CFc + elif choice == 5: + instr = CTc + elif choice == 6: + instr = RET + elif choice == 7: + instr = RFc + elif choice == 8: + instr = RTc + elif choice == 9: + instr = RST + + + return instr + +def init_reg_file(): + prog = [] + for i in range(7): + prog.append((LrI | (i << 3))) + prog.append(rand_imm()) + + return prog + +def print_reg_state(dut): + reg_state = [0, 0, 0, 0, 0, 0, 0] + print("\nRegDump:") + print("\tCycle: {cyc}, State: {state}".format(cyc=dut.Brain.cycle.value, state=dut.Brain.state.value)) + print("\tStack: sel =", dut.sel_Stack.value) + for sel in range(8): + print("\tSTACK_{sel} = {val}".format(sel=sel, val=dut.Stack._id(f"rf[{sel}]", extended=False).value)) + for sel in range(7): + print("\tREG_{reg} = {val}".format(reg=sel, val=dut.rf._id(f"rf[{sel}]", extended=False).value)) + reg_state[sel] = dut.rf._id(f"rf[{sel}]", extended=False).value + print("\tFlags: ", dut.Unit.flags.value) + print("\tREG_a = ", dut.A_out.value) + print("\tREG_b = ", dut.B_out.value) + print("PC_L = {D_out}".format(D_out=dut.D_out.value)) + + return reg_state + +def get_chip_rf(chip): + prog = [ + LMr | 0, + LMr | 1, + LMr | 2, + LMr | 3, + LMr | 4, + LMr | 5, + LMr | 6, + ] + res = [0, 0, 0, 0, 0, 0, 0] + + while (chip.get_all_outputs() & 0b111_00000000) >> 8 != T1I: + chip.set_all_inputs(0b11_00000000) + chip.step_clock() + time.sleep(CLK_TIME) + + chip.set_all_inputs(0b00_00000000) + ind = 0 + while ind <= 2 * len(prog): + chip_state = (chip.get_all_outputs() & 0b111_00000000) >> 8 + if chip_state == T1 or chip_state == T1I: + ind += 1 + chip.step_clock() + time.sleep(CLK_TIME) + elif chip_state == T2: + chip.set_all_inputs(prog[int((ind-1)/2)] | (0b10_00000000)) + + chip.step_clock() + time.sleep(CLK_TIME) + elif chip_state == WAIT: + chip.set_all_inputs(prog[int((ind-1)/2)] | (0b00_00000000)) + chip.step_clock() + time.sleep(CLK_TIME) + elif chip_state == T3: + if ind % 2 == 0: + res[int((ind-1)/2)] = chip.get_all_outputs() & (0b11111111) + chip.step_clock() + time.sleep(CLK_TIME) + elif chip_state == STOPPED: + chip.step_clock() + time.sleep(CLK_TIME) + elif chip_state == T4: + chip.step_clock() + time.sleep(CLK_TIME) + elif chip_state == T5: + chip.step_clock() + time.sleep(CLK_TIME) + else: + assert 1==0, "Invalid state!" + + + return res + + +@cocotb.test() +async def i8008_basic_test(dut): + """Test for incr""" +# (input logic [7:0] D_in, +# input logic INTR, READY, clk, rst, +# output logic [7:0] D_out, +# output logic Sync, +# output state_t state) + + chip = Chip(SERIAL_PORT) + + clk = Clock(dut.clk, 10, units="us") + cocotb.start_soon(clk.start()) + + await RisingEdge(dut.clk) + chip.step_clock() + time.sleep(CLK_TIME) + + dut.D_in.value = 0 + dut.INTR.value = 0 + dut.READY.value = 0 + dut.rst.value = 1 + + chip.set_all_inputs(0b00_00_00000000) + chip.set_reset(1) + + await RisingEdge(dut.clk) + chip.step_clock() + time.sleep(CLK_TIME) + + await RisingEdge(dut.clk) + chip.step_clock() + time.sleep(CLK_TIME) + + assert dut.state.value == T1, "Basic test failed with: {state} != {actual}".format(state=T1, actual=dut.state.value) + assert dut.D_out.value == 0b00000000, "Basic test failed with: {D_out} != {actual}".format(D_out=0b00000000, actual=dut.D_out.value) + assert chip.get_all_outputs() == 0b1_010_00000000, "Basic test failed with: {D_out} != {actual}".format(D_out=bin(0b0_010_00000000), actual=bin(chip.get_all_outputs())) + + + await RisingEdge(dut.clk) + chip.step_clock() + time.sleep(CLK_TIME) + assert dut.state.value == T1, "Basic test failed with: {state} != {actual}".format(state=T1, actual=dut.state.value) + assert chip.get_all_outputs() == 0b1_010_00000000, "Basic test failed with: {D_out} != {actual}".format(D_out=bin(0b0_010_00000000), actual=bin(chip.get_all_outputs())) + + dut.D_in.value = 0b00_001_000 + dut.INTR.value = 0 + dut.READY.value = 0 + dut.rst.value = 0 + + chip.set_all_inputs(0b00_00_00001000) + chip.set_reset(0) + + await RisingEdge(dut.clk) + assert dut.state.value == T1, "Basic test failed with: {state} != {actual}".format(state=T1, actual=dut.state.value) + assert chip.get_all_outputs() == 0b1_010_00000000, "Basic test failed with: {D_out} != {actual}".format(D_out=bin(0b0_010_00000000), actual=bin(chip.get_all_outputs())) + + await RisingEdge(dut.clk) + chip.step_clock() + time.sleep(CLK_TIME) + assert dut.state.value == T2, "Basic test failed with: {state} != {actual}".format(state=T2, actual=dut.state.value) + assert chip.get_all_outputs() == 0b1_100_00000000, "Basic test failed with: {D_out} != {actual}".format(D_out=bin(0b1_100_00000000), actual=bin(chip.get_all_outputs())) + + dut.READY.value = 1 + chip.set_all_inputs(0b00_10_00001000) + + await RisingEdge(dut.clk) + chip.step_clock() + time.sleep(CLK_TIME) + assert dut.state.value == WAIT, "Basic test failed with: {state} != {actual}".format(state=WAIT, actual=dut.state.value) + assert chip.get_all_outputs() == 0b0_000_00000000, "Basic test failed with: {D_out} != {actual}".format(D_out=bin(0b0_000_00000000), actual=bin(chip.get_all_outputs())) + + await RisingEdge(dut.clk) + chip.step_clock() + time.sleep(CLK_TIME) + assert dut.state.value == WAIT, "Basic test failed with: {state} != {actual}".format(state=WAIT, actual=dut.state.value) + assert chip.get_all_outputs() == 0b0_000_00000000, "Basic test failed with: {D_out} != {actual}".format(D_out=bin(0b0_000_00000000), actual=bin(chip.get_all_outputs())) + + await RisingEdge(dut.clk) + assert dut.state.value == WAIT, "Basic test failed with: {state} != {actual}".format(state=WAIT, actual=dut.state.value) + assert chip.get_all_outputs() == 0b0_000_00000000, "Basic test failed with: {D_out} != {actual}".format(D_out=bin(0b0_000_00000000), actual=bin(chip.get_all_outputs())) + + await RisingEdge(dut.clk) + chip.step_clock() + time.sleep(CLK_TIME) + + dut.READY.value = 0 + chip.set_all_inputs(0b00_00_00001000) + assert dut.state.value == T3, "Basic test failed with: {state} != {actual}".format(state=T3, actual=dut.state.value) + assert chip.get_all_outputs() == 0b0_001_00001000, "Basic test failed with: {D_out} != {actual}".format(D_out=bin(0b0_001_00000000), actual=bin(chip.get_all_outputs())) + + await RisingEdge(dut.clk) + chip.step_clock() + time.sleep(CLK_TIME) + assert dut.state.value == T4, "Basic test failed with: {state} != {actual}".format(state=T4, actual=dut.state.value) + assert chip.get_all_outputs() == 0b0_111_00000000, "Basic test failed with: {D_out} != {actual}".format(D_out=bin(0b0_010_00000000), actual=bin(chip.get_all_outputs())) + + await RisingEdge(dut.clk) + chip.step_clock() + time.sleep(CLK_TIME) + assert dut.state.value == T5, "Basic test failed with: {state} != {actual}".format(state=T5, actual=dut.state.value) + assert chip.get_all_outputs() == 0b0_101_00000001, "Basic test failed with: {D_out} != {actual}".format(D_out=bin(0b0_101_00000000), actual=bin(chip.get_all_outputs())) + assert dut.rf.ACC.value == 0, "Basic test failed with: 1 != {actual}".format(actual=dut.rf.ACC.value) + assert dut.bus.value == 1, "Basic test failed with: 1 != {actual}".format(actual=dut.bus.value) + + + await RisingEdge(dut.clk) + chip.step_clock() + time.sleep(CLK_TIME) + + assert dut.rf.ACC.value == 0, "Basic test failed with: 1 != {actual}".format(actual=dut.rf.ACC.value) + + await RisingEdge(dut.clk) + chip.step_clock() + time.sleep(CLK_TIME) + + assert dut.state.value == T2, "Basic test failed with: {state} != {actual}".format(state=T2, actual=dut.state.value) + assert chip.get_all_outputs() == 0b1_100_00000000, "Basic test failed with: {D_out} != {actual}".format(D_out=bin(0b0_010_00000000), actual=bin(chip.get_all_outputs())) + dut.READY.value = 1 + dut.D_in.value = 0b11_111_001 + chip.set_all_inputs(0b00_10_11111001) + + await RisingEdge(dut.clk) + chip.step_clock() + time.sleep(CLK_TIME) + + assert dut.state.value == WAIT, "Basic test failed with: {state} != {actual}".format(state=WAIT, actual=dut.state.value) + assert chip.get_all_outputs() == 0b0_000_00000000, "Basic test failed with: {D_out} != {actual}".format(D_out=bin(0b0_000_00000000), actual=bin(chip.get_all_outputs())) + + await RisingEdge(dut.clk) + chip.step_clock() + time.sleep(CLK_TIME) + assert chip.get_all_outputs() == 0b0_000_00000000, "Basic test failed with: {D_out} != {actual}".format(D_out=bin(0b0_000_00000000), actual=bin(chip.get_all_outputs())) + + await RisingEdge(dut.clk) + # chip.step_clock() + # time.sleep(CLK_TIME) + assert chip.get_all_outputs() == 0b0_000_00000000, "Basic test failed with: {D_out} != {actual}".format(D_out=bin(0b0_000_00000000), actual=bin(chip.get_all_outputs())) + + await RisingEdge(dut.clk) + chip.step_clock() + time.sleep(CLK_TIME) + + dut.READY.value = 0 + chip.set_all_inputs(0b00_00_11111001) + assert dut.state.value == T3, "Basic test failed with: {state} != {actual}".format(state=T3, actual=dut.state.value) + assert chip.get_all_outputs() == 0b0_001_11111001, "Basic test failed with: {D_out} != {actual}".format(D_out=bin(0b0_001_00000000), actual=bin(chip.get_all_outputs())) + + + cycle_count = 0 + while dut.D_out.value != 0b00000001 and (cycle_count < 20): + cycle_count += 1 + await RisingEdge(dut.clk) + chip.step_clock() + time.sleep(CLK_TIME) + + assert dut.D_out.value == 0b00000001, "Basic test failed with: {D_out} != {actual}".format(D_out=0b00000001, actual=dut.D_out.value) + assert chip.get_all_outputs() == 0b0_111_00000001, "Basic test failed with: {D_out} != {actual}".format(D_out=bin(0b0_111_00000001), actual=bin(chip.get_all_outputs())) + + + +@cocotb.test() +async def ALU_add_test(dut): + """Test for alu add""" + prog = [0b00_001_110, # B <- Imm. (LrI) + 0b00_011_011, # Arbitrary Imm. + 0b00_001_000, # B++ (INr) + 0b10_001_001, # A <- A + B + (Carry) (ACr) + 0b10_011_001, # A <- A - B - (Carry) (SBr) + 0b10_000_111, # A <- A + Mem + 0b00_000_111] # "Mem" + + chip = Chip(SERIAL_PORT) + + clk = Clock(dut.clk, 10, units="us") + cocotb.start_soon(clk.start()) + + # Setup the processor for testing + await RisingEdge(dut.clk) + chip.step_clock() + time.sleep(CLK_TIME) + + dut.D_in.value = 0 + dut.INTR.value = 0 + dut.READY.value = 0 + dut.rst.value = 1 + + chip.set_all_inputs(0b00_00_00000000) + chip.set_reset(1) + + await RisingEdge(dut.clk) + chip.step_clock() + time.sleep(CLK_TIME) + + dut.rst.value = 0 + chip.set_reset(0) + + await RisingEdge(dut.clk) + # chip.step_clock() + # time.sleep(CLK_TIME) + + assert dut.state.value == T1, "ALU test failed with: {state} != {actual}".format(state=T1, actual=dut.state.value) + assert dut.D_out.value == 0b00000000, "ALU test failed with: {D_out} != {actual}".format(D_out=0b00000000, actual=dut.D_out.value) + assert chip.get_all_outputs() == 0b1_010_00000000, "ALU test failed with: {D_out} != {actual}".format(D_out=bin(0b1_010_00000000), actual=bin(chip.get_all_outputs())) + + + ind = 0 + chip_state = (chip.get_all_outputs() & 0b111_00000000) >> 8 + assert chip_state == dut.state.value + + while ind <= len(prog): + chip_state = (chip.get_all_outputs() & 0b111_00000000) >> 8 + # print("chip_state = {chip}, dut = {dut}".format(chip=bin(chip_state), dut=dut.state.value)) + assert chip_state == dut.state.value or (chip_state == T3 and dut.state.value == WAIT), "Ind is {ind}, pc is {PC}".format(ind=ind, PC=dut.PC_out.value) + + if dut.state.value == T1: + ind += 1 + if verbose: + print_reg_state(dut) + await RisingEdge(dut.clk) + chip.step_clock() + time.sleep(CLK_TIME) + elif dut.state.value == T2: + if verbose: print("PC_H = {PC_H}, TYPE = {AddrType}".format(PC_H=dut.D_out.value, AddrType=(dut.D_out.value>>6))) + dut.READY.value = 1 + dut.D_in.value = prog[ind-1] + chip.set_all_inputs(prog[ind-1] | (0b10_00000000)) + + await RisingEdge(dut.clk) + chip.step_clock() + time.sleep(CLK_TIME) + elif dut.state.value == WAIT: + dut.READY.value = 0 + chip.set_all_inputs(prog[ind-1] | (0b00_00000000)) + await RisingEdge(dut.clk) + if chip_state == WAIT: + chip.step_clock() + time.sleep(CLK_TIME) + elif dut.state.value == T3: + if verbose: print("Instr: %b", dut.instr.value) + + await RisingEdge(dut.clk) + chip.step_clock() + time.sleep(CLK_TIME) + elif dut.state.value == STOPPED: + await RisingEdge(dut.clk) + chip.step_clock() + time.sleep(CLK_TIME) + elif dut.state.value == T4: + await RisingEdge(dut.clk) + chip.step_clock() + time.sleep(CLK_TIME) + elif dut.state.value == T5: + await RisingEdge(dut.clk) + chip.step_clock() + time.sleep(CLK_TIME) + else: + assert 1==0, "Invalid state!" + + + if verbose: + print_reg_state(dut) + + res = get_chip_rf(chip) + + for sel in range(7): + if sel == 0: + assert dut.rf._id(f"rf[{sel}]", extended=False).value == 0b00000111 + assert res[sel] == 0b00000111 + elif sel == 1: + assert dut.rf._id(f"rf[{sel}]", extended=False).value == 0b00011100 + assert res[sel] == 0b00011100 + else: + assert dut.rf._id(f"rf[{sel}]", extended=False).value == 0 + assert res[sel] == 0b00000000 + + + +@cocotb.test() +async def ALU_rand_test(dut): + """Test for random alu ops""" + seed = random.randint(0, 0xFFFFFFFF) + random.seed(seed) + print("ALU_rand_test seed: ", seed) + + model = i8008_model() + + model.gen_rand_alu_prog(100) + + clk = Clock(dut.clk, 10, units="us") + cocotb.start_soon(clk.start()) + + # Setup the processor for testing + await RisingEdge(dut.clk) + dut.D_in.value = 0 + dut.INTR.value = 0 + dut.READY.value = 0 + dut.rst.value = 1 + await RisingEdge(dut.clk) + dut.rst.value = 0 + await RisingEdge(dut.clk) + + assert dut.state.value == T1, "Rand ALU test failed with: {state} != {actual}".format(state=T1, actual=dut.state.value) + assert dut.D_out.value == 0b00000000, "Rand ALU test failed with: {D_out} != {actual}".format(D_out=0b00000000, actual=dut.D_out.value) + + # used to print 8008 state + reg_state = [0, 0, 0, 0, 0, 0, 0] + last_instr = 0 + last_mem_read = 0 + + PC_L = 0 + PC_H = 0 + + # begin program simulation + while model.get_pc() in model.prog: # and (model.prog[model.get_pc()] != HLT0 or model.prog[model.get_pc()] != HLT0_1 or model.prog[model.get_pc()] != HLT1): + if dut.state.value == T1: + if verbose: + print_reg_state(dut) + PC_L = dut.D_out.value + await RisingEdge(dut.clk) + elif dut.state.value == T2: + AddrType = dut.D_out.value>>6 + if verbose: + print("PC_H = {PC_H}, TYPE = {AddrType}".format(PC_H=dut.D_out.value, AddrType=AddrType)) + PC_H = (dut.D_out.value & 0b11_1111) + PC = PC_L | (PC_H << 8) + + if AddrType == PCI: + model.gen_reg_state(model.prog, last_instr, last_mem_read, 0) + if verbose: model.dump_reg() + model.state_check(dut, last_instr) + + # update for new instruction + last_instr = model.prog[model.get_pc()] + + # input new program value into simulation + dut.READY.value = 1 + last_mem_read = model.read_mem(PC) + dut.D_in.value = last_mem_read + + if AddrType == PCI or (AddrType == PCR and last_instr & 0b11_000_111 != LrM and last_instr & 0b11_000_111 != 0b10_000_111 and last_instr & 0b11_111_000 != LMr): + model.incr_pc() + await RisingEdge(dut.clk) + elif dut.state.value == WAIT: + dut.READY.value = 0 + await RisingEdge(dut.clk) + elif dut.state.value == T3: + if verbose: + print("Instr: %b", dut.instr.value) + print("D_in: %b", dut.D_in.value) + + await RisingEdge(dut.clk) + elif dut.state.value == STOPPED: + assert False, "Program shouldn't be here" + elif dut.state.value == T4: + await RisingEdge(dut.clk) + elif dut.state.value == T5: + await RisingEdge(dut.clk) + else: + assert False, "Invalid state!" + + if verbose: + print_reg_state(dut) + + count = 0 + while dut.state.value != STOPPED: + if count > 10: + assert False, "Program did not halt" + await RisingEdge(dut.clk) + count += 1 + +@cocotb.test() +async def basic_ctrl_test(dut): + """Basic control flow testing""" + model = i8008_model() + # verbose = True + + model.gen_ctrl_flow() + + clk = Clock(dut.clk, 10, units="us") + cocotb.start_soon(clk.start()) + + # Setup the processor for testing + await RisingEdge(dut.clk) + dut.D_in.value = 0 + dut.INTR.value = 0 + dut.READY.value = 0 + dut.rst.value = 1 + await RisingEdge(dut.clk) + dut.rst.value = 0 + await RisingEdge(dut.clk) + + assert dut.state.value == T1, "Rand ALU test failed with: {state} != {actual}".format(state=T1, actual=dut.state.value) + assert dut.D_out.value == 0b00000000, "Rand ALU test failed with: {D_out} != {actual}".format(D_out=0b00000000, actual=dut.D_out.value) + + # used to print 8008 state + reg_state = [0, 0, 0, 0, 0, 0, 0] + last_instr = 0 + mem_reads = [] + + PC_L = 0 + PC_H = 0 + + # begin program simulation + while model.get_pc() in model.prog: # and (model.prog[model.get_pc()] != HLT0 or model.prog[model.get_pc()] != HLT0_1 or model.prog[model.get_pc()] != HLT1): + if dut.state.value == T1: + if verbose: + print_reg_state(dut) + PC_L = dut.D_out.value + await RisingEdge(dut.clk) + elif dut.state.value == T2: + AddrType = dut.D_out.value>>6 + if verbose: + print("PC_H = {PC_H}, TYPE = {AddrType}".format(PC_H=dut.D_out.value, AddrType=AddrType)) + PC_H = (dut.D_out.value & 0b11_1111) + PC = PC_L | (PC_H << 8) + + if AddrType == PCI: + mem_reads.extend([0, 0, 0]) + model.gen_reg_state(model.prog, mem_reads[0], mem_reads[1], mem_reads[2]) + if verbose: model.dump_reg() + model.state_check(dut, last_instr) + + # update for new instruction + last_instr = model.prog[model.get_pc()] + + # reset mem_reads + mem_reads = [] + + # input new program value into simulation + dut.READY.value = 1 + mem_reads.append(model.read_mem(PC)) + dut.D_in.value = model.read_mem(PC) + + if AddrType == PCI or (AddrType == PCR and last_instr & 0b11_000_111 != LrM and last_instr & 0b11_000_111 != 0b10_000_111 and last_instr & 0b11_111_000 != LMr): + model.incr_pc() + await RisingEdge(dut.clk) + elif dut.state.value == WAIT: + dut.READY.value = 0 + await RisingEdge(dut.clk) + elif dut.state.value == T3: + if verbose: + print("Instr: %b", dut.instr.value) + print("D_in: %b", dut.D_in.value) + #print("enable_SP", dut.enable_SP.value) + + await RisingEdge(dut.clk) + elif dut.state.value == STOPPED: + assert False, "Program shouldn't be here" + elif dut.state.value == T4: + await RisingEdge(dut.clk) + elif dut.state.value == T5: + await RisingEdge(dut.clk) + else: + assert False, "Invalid state!" + + if verbose: + print_reg_state(dut) + + count = 0 + while dut.state.value != STOPPED: + if count > 10: + assert False, "Program did not halt" + await RisingEdge(dut.clk) + count += 1 + + +@cocotb.test() +async def period_search_test(dut): + """Test for finding period in memory""" + seed = random.randint(0, 0xFFFFFFFF) + random.seed(seed) + print("period_search_test seed: ", seed) + + model = i8008_model() + + mem = [] + for i in range(20): + num = rand_imm() + while num == 0b00101110: + num = rand_imm() + mem.append(num) + choice = random.randint(0, 19) + + # insert period into memory + mem[choice] = 0b00101110 + model.gen_period_search(mem) + + clk = Clock(dut.clk, 10, units="us") + cocotb.start_soon(clk.start()) + + # Setup the processor for testing + await RisingEdge(dut.clk) + dut.D_in.value = 0 + dut.INTR.value = 0 + dut.READY.value = 0 + dut.rst.value = 1 + await RisingEdge(dut.clk) + dut.rst.value = 0 + await RisingEdge(dut.clk) + + assert dut.state.value == T1, "Rand ALU test failed with: {state} != {actual}".format(state=T1, actual=dut.state.value) + assert dut.D_out.value == 0b00000000, "Rand ALU test failed with: {D_out} != {actual}".format(D_out=0b00000000, actual=dut.D_out.value) + + # used to print 8008 state + reg_state = [0, 0, 0, 0, 0, 0, 0] + last_instr = 0 + mem_reads = [] + + PC_L = 0 + PC_H = 0 + + # begin program simulation + while (model.get_pc() in model.prog or model.get_pc() - 1 in model.prog): # and (model.prog[model.get_pc()] != HLT0 or model.prog[model.get_pc()] != HLT0_1 or model.prog[model.get_pc()] != HLT1): + if dut.state.value == T1: + if verbose: + print_reg_state(dut) + PC_L = dut.D_out.value + await RisingEdge(dut.clk) + elif dut.state.value == T2: + AddrType = dut.D_out.value>>6 + if verbose: + print("PC_H = {PC_H}, TYPE = {AddrType}".format(PC_H=dut.D_out.value, AddrType=AddrType)) + PC_H = (dut.D_out.value & 0b11_1111) + PC = PC_L | (PC_H << 8) + + if AddrType == PCI: + mem_reads.extend([0, 0, 0]) + model.gen_reg_state(model.prog, mem_reads[0], mem_reads[1], mem_reads[2]) + if verbose: model.dump_reg() + model.state_check(dut, last_instr) + + if model.get_pc() in model.prog: + # update for new instruction + last_instr = model.prog[model.get_pc()] + + # reset mem_reads + mem_reads = [] + + # input new program value into simulation + dut.READY.value = 1 + mem_reads.append(model.read_mem(PC)) + dut.D_in.value = model.read_mem(PC) + + if AddrType == PCI or (AddrType == PCR and last_instr & 0b11_000_111 != LrM and last_instr & 0b11_000_111 != 0b10_000_111 and last_instr & 0b11_111_000 != LMr): + model.incr_pc() + await RisingEdge(dut.clk) + elif dut.state.value == WAIT: + dut.READY.value = 0 + await RisingEdge(dut.clk) + elif dut.state.value == T3: + if verbose: + print("Instr: %b", dut.instr.value) + print("D_in: %b", dut.D_in.value) + print("enable_SP ", dut.enable_SP.value) + + await RisingEdge(dut.clk) + elif dut.state.value == STOPPED: + assert dut.rf._id(f"rf[{Lo}]", extended=False).value == 200 + choice, "Period not in set location" + return + assert False, "Program shouldn't be here" + elif dut.state.value == T4: + await RisingEdge(dut.clk) + elif dut.state.value == T5: + await RisingEdge(dut.clk) + else: + assert False, "Invalid state!" + + if verbose: + print_reg_state(dut) + print("Period should be found at: ", 200 + choice) + model.dump_reg() + + count = 0 + while dut.state.value != STOPPED: + if count > 10: + assert False, "Program did not halt" + await RisingEdge(dut.clk) + count += 1 + + assert dut.rf._id(f"rf[{Lo}]", extended=False).value == 200 + choice, "Period not in set location" + +def fib(num): + if num <= 1: + return 1 + else: + return fib(num - 1) + fib(num - 2) + +@cocotb.test() +async def fibonacci_test(dut): + """Test for finding nth fib num""" + seed = random.randint(0, 0xFFFFFFFF) + random.seed(seed) + print("fibonacci seed: ", seed) + + # verbose = True + model = i8008_model() + + choice = random.randint(0, 12) + expected = fib(choice) + + # generate fibonacci prog + model.gen_fibonacci(choice) + + clk = Clock(dut.clk, 10, units="us") + cocotb.start_soon(clk.start()) + + # Setup the processor for testing + await RisingEdge(dut.clk) + dut.D_in.value = 0 + dut.INTR.value = 0 + dut.READY.value = 0 + dut.rst.value = 1 + await RisingEdge(dut.clk) + dut.rst.value = 0 + await RisingEdge(dut.clk) + + assert dut.state.value == T1, "Rand ALU test failed with: {state} != {actual}".format(state=T1, actual=dut.state.value) + assert dut.D_out.value == 0b00000000, "Rand ALU test failed with: {D_out} != {actual}".format(D_out=0b00000000, actual=dut.D_out.value) + + # used to print 8008 state + reg_state = [0, 0, 0, 0, 0, 0, 0] + last_instr = 0 + mem_reads = [] + + PC_L = 0 + PC_H = 0 + + # begin program simulation + while (model.get_pc() in model.prog or model.get_pc() - 1 in model.prog): # and (model.prog[model.get_pc()] != HLT0 or model.prog[model.get_pc()] != HLT0_1 or model.prog[model.get_pc()] != HLT1): + if dut.state.value == T1: + if verbose: + print_reg_state(dut) + PC_L = dut.D_out.value + await RisingEdge(dut.clk) + elif dut.state.value == T2: + AddrType = dut.D_out.value>>6 + if verbose: + print("PC_H = {PC_H}, TYPE = {AddrType}".format(PC_H=dut.D_out.value, AddrType=AddrType)) + PC_H = (dut.D_out.value & 0b11_1111) + PC = PC_L | (PC_H << 8) + + if AddrType == PCI: + mem_reads.extend([0, 0, 0]) + model.gen_reg_state(model.prog, mem_reads[0], mem_reads[1], mem_reads[2]) + if verbose: model.dump_reg() + model.state_check(dut, last_instr) + + if model.get_pc() in model.prog: + # update for new instruction + last_instr = model.prog[model.get_pc()] + + # reset mem_reads + mem_reads = [] + + # input new program value into simulation + dut.READY.value = 1 + mem_reads.append(model.read_mem(PC)) + dut.D_in.value = model.read_mem(PC) + + if AddrType == PCI or (AddrType == PCR and last_instr & 0b11_000_111 != LrM and last_instr & 0b11_000_111 != 0b10_000_111 and last_instr & 0b11_111_000 != LMr): + model.incr_pc() + await RisingEdge(dut.clk) + elif dut.state.value == WAIT: + dut.READY.value = 0 + await RisingEdge(dut.clk) + elif dut.state.value == T3: + if verbose: + print("Instr: %b", dut.instr.value) + print("D_in: %b", dut.D_in.value) + + await RisingEdge(dut.clk) + elif dut.state.value == STOPPED: + assert dut.rf._id(f"rf[0]", extended=False).value == expected, "fib value wrong, {sim} != {expected}".format(sim=dut.rf._id(f"rf[0]", extended=False).value, expected=expected) + if verbose: + print_reg_state(dut) + print("result should be: ", fib(choice)) + return + assert False, "Program shouldn't be here" + elif dut.state.value == T4: + await RisingEdge(dut.clk) + elif dut.state.value == T5: + await RisingEdge(dut.clk) + else: + assert False, "Invalid state!" + + if verbose: + print_reg_state(dut) + print("result should be: ", expected) + model.dump_reg() + + count = 0 + while dut.state.value != STOPPED: + if count > 10: + assert False, "Program did not halt" + await RisingEdge(dut.clk) + count += 1 + + assert dut.rf._id(f"rf[0]", extended=False).value == fib(choice), "fib value wrong" + + + + +def test_i8008_runner(): + """Simulate the i8008 using the Python runner. + This file can be run directly or via pytest discovery. + """ + hdl_toplevel_lang = os.getenv("HDL_TOPLEVEL_LANG", "verilog") + sim = os.getenv("SIM", "icarus") + + proj_path = Path(__file__).resolve().parent.parent + # equivalent to setting the PYTHONPATH environment variable + # sys.path.append(str(proj_path / "model")) + + verilog_sources = [] + vhdl_sources = [] + + if hdl_toplevel_lang == "verilog": + verilog_sources = [proj_path / "i8008_core.v"] + + # equivalent to setting the PYTHONPATH environment variable + sys.path.append(str(proj_path / "tests")) + + runner = get_runner(sim) + runner.build( + verilog_sources=verilog_sources, + vhdl_sources=vhdl_sources, + hdl_toplevel="i8008_core", + always=True, + ) + runner.test(hdl_toplevel="i8008_core", test_module="i8008_tb") + + +if __name__ == "__main__": + test_i8008_runner() \ No newline at end of file diff --git a/designs/d29_bwilhelm_i8008/tests/interface.py b/designs/d29_bwilhelm_i8008/tests/interface.py new file mode 100644 index 0000000..a2e9902 --- /dev/null +++ b/designs/d29_bwilhelm_i8008/tests/interface.py @@ -0,0 +1,358 @@ +import time +from serial import Serial + +CMD_READ_REQ = 0b0001 +CMD_WRITE_REQ = 0b0010 +CMD_SET_ADDR = 0b0011 +CMD_SET_ADDR_INC = 0b0111 +CMD_BUS_RESET = 0b1111 + +RESP_READ_RESP = 0b0001 +RESP_WRITE_ACK = 0b0010 +RESP_ADDR_ACK = 0b0011 +RESP_BUS_ERROR = 0b0100 +RESP_BUS_RESET = 0b0101 +RESP_INTERRUPT_1 = 0b1000 +RESP_INTERRUPT_2 = 0b1001 +RESP_INTERRUPT_3 = 0b1010 +RESP_INTERRUPT_4 = 0b1011 + +RESP_INTERRUPT_ALL = [RESP_INTERRUPT_1, RESP_INTERRUPT_2, + RESP_INTERRUPT_3, RESP_INTERRUPT_4] + +def create_instruction(inst, data): + return [ + inst, + (data & 0xff000000) >> 24, + (data & 0x00ff0000) >> 16, + (data & 0x0000ff00) >> 8, + (data & 0x000000ff) >> 0 + ] + +def parse_instruction(byte_list): + data = int("".join(["{0:08b}".format(x) for x in byte_list[1:]]), 2) + return byte_list[0] & 0x0f, data + +class Chip: + def __init__(self, serial_port, baud=115200): + self.bus = _DebugBus(serial_port, baud, fifo_size=1, timeout=2) + self.out_state = 0b00000000000000 + + def get_all_outputs(self): + o = self.bus.read_peripheral(0)[0] & 0xFFF + return o + + def get_output(self, index): + assert index >= 0 and index < 12 + + o = self.bus.read_peripheral(0)[0] & 0xFFF + o = o & (1 << index) + return (o != 0) + + def _push_outputs(self): + self.bus.write_peripheral(0, self.out_state) + + def set_input(self, index, value, _bp=False): + if not _bp: + assert index >= 0 and index < 12 + + value_n = int(not (int(value) & 0x1)) + self.out_state |= (1 << index) + self.out_state ^= (value_n << index) + + self._push_outputs() + + def set_all_inputs(self, value): + value = value & 0xFFF + + self.out_state &= 0xF000 + self.out_state |= value + + self._push_outputs() + + def set_reset(self, value): + self.set_input(12, value, _bp=True) + + def step_clock(self): + self.set_input(13, 1, _bp=True) + self.set_input(13, 0, _bp=True) + +class _DebugBus: + + def __init__(self, serial_port, baud, fifo_size, timeout=0): + # Maximum number of ops that can be in-pipeline at once + self.max_buf = (fifo_size - 2) if fifo_size > 2 else fifo_size + assert self.max_buf > 0 + + # No timeout for serial port + # Instead, use unblocking serial port and block internally + self.port = Serial(serial_port, baud, timeout=0) + self.timeout = timeout + + self.interrupts = [False, False, False, False] + + self.recv_buffer = [] + self.recv_responses = [] + + # Read as much data from the port as is available and store it + def _read_port(self): + data = self.port.read(10000) # Read as much data is available + self.recv_buffer.extend(list(data)) + + while len(self.recv_buffer) >= 5: + instr = parse_instruction(self.recv_buffer[0:5]) + self.recv_buffer = self.recv_buffer[5:] + + # Parse interrupts + if instr[0] in RESP_INTERRUPT_ALL: + if instr[0] == RESP_INTERRUPT_1: + self.interrupts[0] = True + if instr[0] == RESP_INTERRUPT_2: + self.interrupts[1] = True + if instr[0] == RESP_INTERRUPT_3: + self.interrupts[2] = True + if instr[0] == RESP_INTERRUPT_4: + self.interrupts[3] = True + + elif instr[0] == RESP_BUS_ERROR: + raise RuntimeError("Bus error received") + + else: + self.recv_responses.append(instr) + + # Blocking-read `n` instructions from serial port + # If n = 0, will read 1 instruction in a non-blocking manner + def _read_data(self, n=0): + first = True + + start_time = time.time() + while True: + self._read_port() + + if n == 0: + if len(self.recv_responses) >= 1: + resp = self.recv_responses[0:1] + self.recv_responses = self.recv_responses[1:] + return resp + else: + return None + + else: + if len(self.recv_responses) >= n: + resp = self.recv_responses[0:n] + self.recv_responses = self.recv_responses[n:] + return resp + + first = False + if (self.timeout != 0) and (time.time() - start_time > self.timeout): + raise TimeoutError("Remote device not responding") + + time.sleep(0.01) + + def read(self, address, n=1, _increment=True): + """ + Read `n` contiguous 32-bit words starting at `address`. Blocks execution until finished or timed out. For reading multiple values from the same address (for peripherals which use a single register as a pipe), use read_peripheral(). If `n` = 1, returns a single integer value read from the bus, otherwise returns an array of integer values with length `n`. + + Arguments: + address (int): The base address to read from. + n (int): The number of values to read starting at the given address. + """ + + ret = [] + + # Set address + self.port.write(bytearray(create_instruction( + CMD_SET_ADDR_INC if _increment else CMD_SET_ADDR, address + ))) + + # Include address-set in first-round buffer-count + first_round = 1 + + # One extra readback (for address) + n = n + 1 + + # Send only enough ops at once to avoid overflowing buffer + while n > 0: + num_words = min(self.max_buf, n) + + for i in range(num_words - first_round): + self.port.write(bytearray(create_instruction( + CMD_READ_REQ, 0 + ))) + + first_round = 0 + + ret.extend(self._read_data(num_words)) + n = n - num_words + + # Remove address-acknowledge + assert ret[0][0] == RESP_ADDR_ACK + ret = ret[1:] + for inst, data in ret: + assert inst == RESP_READ_RESP + ret = [int(x[1]) for x in ret] + + if n == 1: + return ret[0] + else: + return ret + + def read_peripheral(self, address, n=1): + """ + Read `n` 32-bit words, all from `address`. Blocks execution until finished or timed out. This should be used for peripherals which use a single register as a pipe. If `n` = 1, returns a single integer value read from the bus, otherwise returns an array of integer values with length `n`. + + Arguments: + address (int): The singular address to read from. + n (int): The number of values to read from the given address. + """ + + return self.read(address, n=n, _increment=False) + + def write(self, address, data, verify=False, _increment=True): + """ + Write `data` into contiguous 32-bit words starting at `address`. Blocks execution until finished or timed out. `None` values in the data array will not be written. For writing multiple values to the same address (for peripherals which use a single register as a pipe), use write_peripheral(). + + Arguments: + address (int): The base address to write to. + data (list[int] OR int): The data to write. + verify (bool): Whether to read-back and verify the data after writing it. + """ + + ret = [] + + # Set address + self.port.write(bytearray(create_instruction( + CMD_SET_ADDR_INC if _increment else CMD_SET_ADDR, address + ))) + + # Include address-set in first-round buffer-count + first_round = 1 + + # Check data format + if isinstance(data, int): + data = [data] + data_buf = data[:] + + n = len(data) + + # One extra readback (for address) + n = n + 1 + + # Send only enough ops at once to avoid overflowing buffer + while n > 0: + num_words = min(self.max_buf, n) + + for i in range(num_words - first_round): + if data_buf[0] is None: + assert _increment + # Use read req to increment address w/o writing + self.port.write(bytearray(create_instruction( + CMD_READ_REQ, 0 + ))) + else: + self.port.write(bytearray(create_instruction( + CMD_WRITE_REQ, data_buf[0] + ))) + + data_buf = data_buf[1:] + + first_round = 0 + + ret.extend(self._read_data(num_words)) + n = n - num_words + + assert len(data_buf) == 0 + + # Remove address-acknowledge + assert ret[0][0] == RESP_ADDR_ACK + ret = ret[1:] + for i, resp in enumerate(ret): + if data[i] is None: + assert resp[0] == RESP_READ_RESP + else: + assert resp[0] == RESP_WRITE_ACK + + # Verify that correct data was written + if verify and _increment: + data_read = self.read(address, n=len(data), _increment=True) + + if len(data) == 1: + assert (data_read == data[0]) or (data[0] is None) + else: + for i in range(len(data)): + assert (data_read[i] == data[i]) or (data[i] is None) + + def write_peripheral(self, address, data): + """ + Write all values in `data` to `address`. Blocks execution until finished or timed out. This should be used for peripherals which use a single register as a pipe. + + Arguments: + address (int): The singular address to write to. + data (list[int]): The data to write to the address. + """ + + self.write(address, data, verify=False, _increment=False) + + def reset(self): + """ + Forcibly reset the bus. Blocks until the bus-reset is acknowledged. + """ + self.port.write(bytearray(create_instruction( + CMD_BUS_RESET, 0 + ))) + + while True: + inst, data = self._read_data(1)[0] + + if inst == RESP_BUS_RESET: + return + + def poll_interrupts(self, reset=False): + """ + Poll the received interrupts. Returns an array of the 4 interrupts. + + Arguments: + reset (bool): Whether to reset the interrupts after reading. + """ + + self._read_port() + + ret = self.interrupts[:] + if reset: + self.reset_interrupts() + + return ret + + def poll_interrupts(self, reset=False): + """ + Poll the received interrupts. Returns an array of the 4 interrupts. + + Arguments: + reset (bool): Whether to reset the interrupts after reading. + """ + + self._read_port() + + ret = self.interrupts[:] + if reset: + self.reset_interrupts() + + return ret + + def reset_interrupts(self): + """ + Reset interrupts regardless of whether they have been polled. + """ + self.interrupts = [False, False, False, False] + + def close(self): + self.port.close() + + # Context manager compliance + def __enter__(self): + return self + + def __exit__(self, exception_type, exception_value, traceback): + self.close() + + diff --git a/designs/d30_yuchingw_fpga/.lastupdated b/designs/d30_yuchingw_fpga/.lastupdated new file mode 100644 index 0000000..4d7b8c3 --- /dev/null +++ b/designs/d30_yuchingw_fpga/.lastupdated @@ -0,0 +1 @@ +2023-05-14 diff --git a/designs/d30_yuchingw_fpga/Images/2bitCounter.jpg b/designs/d30_yuchingw_fpga/Images/2bitCounter.jpg new file mode 100644 index 0000000..990abc2 Binary files /dev/null and b/designs/d30_yuchingw_fpga/Images/2bitCounter.jpg differ diff --git a/designs/d30_yuchingw_fpga/Images/OutputTestcase.png b/designs/d30_yuchingw_fpga/Images/OutputTestcase.png new file mode 100644 index 0000000..2f9b16a Binary files /dev/null and b/designs/d30_yuchingw_fpga/Images/OutputTestcase.png differ diff --git a/designs/d30_yuchingw_fpga/Images/file b/designs/d30_yuchingw_fpga/Images/file new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/designs/d30_yuchingw_fpga/Images/file @@ -0,0 +1 @@ + diff --git a/designs/d30_yuchingw_fpga/Images/passThrough.jpg b/designs/d30_yuchingw_fpga/Images/passThrough.jpg new file mode 100644 index 0000000..48aa4c3 Binary files /dev/null and b/designs/d30_yuchingw_fpga/Images/passThrough.jpg differ diff --git a/designs/d30_yuchingw_fpga/LICENSE b/designs/d30_yuchingw_fpga/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/designs/d30_yuchingw_fpga/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/designs/d30_yuchingw_fpga/README.md b/designs/d30_yuchingw_fpga/README.md new file mode 100644 index 0000000..24de1be --- /dev/null +++ b/designs/d30_yuchingw_fpga/README.md @@ -0,0 +1,47 @@ +# TinyTapeout_FPGA + +Yu-Ching Wu +18-224/624 Spring 2023 Final Tapeout Project + +## Overview + +A 4 by 4 basic FPGA. Can simulate up to 12 gates. + +## How it Works + +Each CLB block contains two switch box, one connecting to sel 0 in the LUT and the other connecting to sel 1 in the LUT. There is also the option of using the CLB block as register. It is possible for the CLB to be connected to any other CLB in the column before, current column, and the column after. + +![](datapath.png) + +## Inputs/Outputs +| Input Number | Config | User Input| +| --- | --- | --- | +| 0 | 1'b0 | 1'b1 | +| 1 | SelDFF | input[0] | +| 2 | LUT[0] | input[1] | +| 3 | LUT[1] | input[2] | +| 4 | LUT[2] | input[3]| +| 5 | LUW[3] | | +| 6 | Addr[0] | | +| 7 | Addr[1] | | +| 8 | Addr[2] | | +| 9 | Addr[3] | | +| 10 | Addr[4] | | +| 11 | Addr[5] | | + +Output[3:0] will be connected to the last four clb of the FPGA. + +## Hardware Peripherals +None + +## Design Testing / Bringup +Write system verilog testbench. Two testcases, one to be able to pass values through all the modules, and the other to simulate a simply 2 bit counter. + +![](Images/2bitCounter.jpg) + +![](Images/passThrough.jpg) + +Setting up and output of counter. + +![](Images/OutputTestcase.png) + diff --git a/designs/d30_yuchingw_fpga/Tests/FPGA_tests.sv b/designs/d30_yuchingw_fpga/Tests/FPGA_tests.sv new file mode 100644 index 0000000..9146287 --- /dev/null +++ b/designs/d30_yuchingw_fpga/Tests/FPGA_tests.sv @@ -0,0 +1,318 @@ +`default_nettype none + +// module Register_test (); +// logic en, clock, reset; +// logic [3:0] D, Q; + +// Register #(4) DUT(.*); +// initial begin +// reset = 1'b1; +// clock = 1'b1; +// forever #1 clock = ~clock; +// end + +// initial begin +// $monitor($time, , "clock: %b, reset: %b, D: %b, Q: %b", clock, reset, D, Q); +// @(posedge clock); +// en = 1'b1; +// reset <= 1'b0; +// D <= 4'b1111; +// @(posedge clock); +// D <= 4'b1111; +// @(posedge clock); +// D <= 4'b1010; +// @(posedge clock); +// D <= 4'b0000; +// @(posedge clock); +// D <= 4'b1111; +// @(posedge clock); +// #5 $finish; +// end +// endmodule: Register_test + +// module CLB_test (); +// logic set, clock, reset, memSel_in, out; +// logic [3:0] LUTConfig; +// logic [1:0] sel; + +// CLB #(4) DUT(.*); +// initial begin +// reset = 1'b1; +// clock = 1'b1; +// forever #1 clock = ~clock; +// end + +// initial begin +// $monitor($time, , "clock: %b, reset: %b, LUTConfig: %b, sel: %b, out: %b", clock, reset, LUTConfig, sel, out); +// @(posedge clock); +// // set an and gate configuration +// set = 1'b1; +// reset <= 1'b0; +// LUTConfig <= 4'b1000; +// memSel_in <= 0; +// @(posedge clock); +// set = 1'b0; +// sel <= 2'b00; +// @(posedge clock); +// sel <= 2'b01; +// @(posedge clock); +// sel <= 2'b10; +// @(posedge clock); +// sel <= 2'b11; + +// // set a xor gate configuration +// set <= 1'b1; +// LUTConfig <= 4'b0110; +// memSel_in <= 0; +// @(posedge clock); +// set <= 1'b0; +// sel <= 2'b00; +// @(posedge clock); +// sel <= 2'b01; +// @(posedge clock); +// sel <= 2'b10; +// @(posedge clock); +// sel <= 2'b11; +// @(posedge clock); + +// // set to memory configuration +// // set a xor gate configuration +// set <= 1'b1; +// LUTConfig <= 4'b0110; +// memSel_in <= 1'b1; +// sel <= 2'b01; +// @(posedge clock); +// set <= 1'b0; +// @(posedge clock); +// sel <= 2'b01; +// @(posedge clock); +// sel <= 2'b10; +// @(posedge clock); +// sel <= 2'b11; + +// #5 $finish; +// end +// endmodule: CLB_test + +// module SweitchBox_test (); +// logic [11:0] inputs; +// logic set, clock, reset; +// logic [3:0] selectConfig; +// logic out; + +// SwitchBox #(4) DUT(.*); +// initial begin +// reset = 1'b1; +// clock = 1'b1; +// forever #1 clock = ~clock; +// end + +// initial begin +// $monitor($time, , "set: %b, inputs: %b, selectLine %b, selectConfig: %b, out: %b", set, inputs, DUT.selectLine, selectConfig, out); +// @(posedge clock); +// set <= 1'b1; +// reset <= 1'b0; +// selectConfig <= 4'b0000; +// @(posedge clock); +// inputs <= 12'b000000001111; +// set <= 1'b0; +// @(posedge clock); +// inputs <= 12'b000000001110; +// @(posedge clock); +// set <= 1'b1; +// selectConfig <= 4'b0100; +// @(posedge clock); +// inputs <= 12'b000000001111; +// set <= 1'b0; + +// #5 $finish; +// end +// endmodule: SweitchBox_test + + +module FPGA_test (); + + logic enAddress, reset, clock; + logic [3:0] userInput; + logic [4:0] setData; + logic [3:0] out; + logic [5:0] address; + + FPGA #(4) DUT(.*); + initial begin + reset = 1'b1; + clock = 1'b1; + forever #1 clock = ~clock; + end + + initial begin + $monitor($time, , "userInput: %b, address: %d, setData: %b, clbOut %b, out %b", userInput, address, setData, DUT.CLBOut, out); + @(posedge clock); + reset <= 1'b0; + address <= 6'd40; + setData <= 5'b00000; // muxselect input[0] + @(posedge clock); + + address <= 6'd41; + setData <= 5'b00001; // muxselect input[1] + @(posedge clock); + + userInput <= 4'b0011; + + address <= 6'd0; + setData <= 5'b01000; // and gate + @(posedge clock); + + address <= 6'd16; + setData <= 5'b00000; // switchOut4[0] = CLBOut[0] + @(posedge clock); + + address <= 6'd17; + setData <= 5'b00001; // switchOut4[0] = CLBOut[0] + @(posedge clock); + + address <= 6'd4; + setData <= 5'b01010; // output is the same as select[0] + @(posedge clock); + + address <= 6'd8; + setData <= 5'b01010; // output is the same as select[0] + @(posedge clock); + address <= 6'd12; + setData <= 5'b01010; // output is the same as select[0] + @(posedge clock); + + address <= 6'd24; + setData <= 5'b00000; // switchOut8[0] = CLBOut[4] + @(posedge clock); + address <= 6'd32; + setData <= 5'b00000; // switchOut12[0] = CLBOut[8] + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + + if (DUT.CLBOut != 16'b0001_0001_0001_0001) begin + $display("failed and and pass case: %b\n", DUT.CLBOut); + end else begin + $display("passed full though testcase\n"); + end + + reset <= 1'b1; + @(posedge clock); + reset <= 1'b0; + userInput <= 4'b0001; + address <= 6'd40; + setData <= 5'b00000; // muxselect input[0] + @(posedge clock); + + address <= 6'd41; + setData <= 5'b00001; // muxselect input[1] + @(posedge clock); + + address <= 6'd0; + setData <= 5'b01010; // pass enable + @(posedge clock); + + address <= 6'd4; + setData <= 5'b00110; // xor + @(posedge clock); + + address <= 6'd8; + setData <= 5'b11010; // FF + @(posedge clock); + + address <= 6'd12; + setData <= 5'b01010; // wire + @(posedge clock); + + address <= 6'd5; + setData <= 5'b01000; // and + @(posedge clock); + + address <= 6'd9; + setData <= 5'b00110; // xor + @(posedge clock); + + address <= 6'd13; + setData <= 5'b11010; // FF + @(posedge clock); + + address <= 6'd16; + setData <= 5'b00000; // CLB4 0 + @(posedge clock); + + address <= 6'd17; + setData <= 5'b01000; // CLB4 1 + @(posedge clock); + + address <= 6'd18; + setData <= 5'b00000; // CLB4 0 + @(posedge clock); + + address <= 6'd19; + setData <= 5'b01000; // CLB4 1 + @(posedge clock); + + address <= 6'd26; + setData <= 5'b00001; // CLB9 0 + @(posedge clock); + + address <= 6'd27; + setData <= 5'b01001; // CLB9 1 + @(posedge clock); + + address <= 6'd34; + setData <= 5'b00001; // CLB9 1 + @(posedge clock); + + + address <= 6'd24; + setData <= 5'b00000; // switchOut8[0] = CLBOut[4] + @(posedge clock); + + address <= 6'd32; + setData <= 5'b00000; // switchOut12[0] = CLBOut[8] + @(posedge clock); + + $display("finish setting up, out is counting"); + + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + + + + + #5 $finish; + end + +endmodule: FPGA_test + +// module muxSel_test (); + +// logic [1:0] selConfig; +// logic [3:0] userInput; +// logic clock, reset, set; +// logic out; + +// muxSel DUT(.*); + +// initial begin +// reset = 1'b1; +// clock = 1'b1; +// forever #1 clock = ~clock; +// end + +// initial begin +// $monitor($time, , "userInput: %b, selConfig: %b, out %b", userInput, setData, out); +// @(posedge clock); + + + +// #5 $finish; +// end + +// endmodule: muxSel_test diff --git a/designs/d30_yuchingw_fpga/info.yaml b/designs/d30_yuchingw_fpga/info.yaml new file mode 100644 index 0000000..ca5aeac --- /dev/null +++ b/designs/d30_yuchingw_fpga/info.yaml @@ -0,0 +1,8 @@ +--- +project: + source_files: + - toplevel_chip.v + - chip.sv + - decoder.v + top_module: "toplevel_chip" + diff --git a/designs/d30_yuchingw_fpga/src/chip.sv b/designs/d30_yuchingw_fpga/src/chip.sv new file mode 100644 index 0000000..fc6a636 --- /dev/null +++ b/designs/d30_yuchingw_fpga/src/chip.sv @@ -0,0 +1,500 @@ +module Register +# (parameter + W = 4) +( + input logic reset, clock, en, + input logic [W-1:0] D, + output logic [W-1:0] Q +); + always_ff @(posedge clock, posedge reset) begin + if (reset) begin + Q <= 'd0; + end else if (en) begin + Q <= D; + end else begin + Q <= Q; + end + end + +endmodule: Register + +module Counter +# (parameter + W = 4) +( + input logic reset, clock, en, + output logic [W-1:0] Q +); + always_ff @(posedge clock, posedge reset) begin + if (reset) begin + Q <= 'd0; + end else if (en) begin + Q <= Q + 1'b1; + end else begin + Q <= Q; + end + end + +endmodule: Counter + +module CLB ( + input logic [1:0] sel, + input logic [3:0] LUTConfig, + input logic memSel_in, clock, reset, set, + output logic out +); + logic [3:0] LUTData; + logic regData, memSel_mem; + + // store configuration of LUT + Register #(4) data (.clock, .reset, .en(set), .D(LUTConfig), .Q(LUTData)); + + // register to store value from LUT + Register #(1) letVal (.clock, .reset, .en(1'b1), .D(LUTData[sel]), .Q(regData)); + + // store whether to use register + Register #(1) dataSel (.clock, .reset, .en(set), .D(memSel_in), .Q(memSel_mem)); + + assign out = memSel_mem ? regData : LUTData[sel]; + +endmodule: CLB + + +module SwitchBox( + input logic [11:0] inputs, + input logic set, clock, reset, + input logic [3:0] selectConfig, + output logic out +); + logic [3:0] selectLine; + // store configuration of select + Register #(4) data (.clock, .reset, .en(set), .D(selectConfig), .Q(selectLine)); + + + assign out = inputs[11:8]; +endmodule: SwitchBox + +// configures mux to select inputs for the initial column of CLB +module muxSel +( + input logic [1:0] selConfig, + input logic [3:0] userInput, + input logic clock, reset, set, + output logic out +); + + logic [1:0] selConfig_mem; + Register #(2) regInput(.clock, .reset, .en(set), .D(selConfig), .Q(selConfig_mem)); + + assign out = userInput[selConfig_mem]; + +endmodule: muxSel + +module my_chip ( + input logic [11:0] io_in, // Inputs to your chip + output logic [11:0] io_out, // Outputs from your chip + input logic clock, + input logic reset // Important: Reset is ACTIVE-HIGH +); + + logic [3:0] userInput; + logic [5:0] address; + logic [4:0] setData; + + always_comb begin + + if (io_in[0] == 1'b1) begin + userInput = 4'b0; + address = io_in[11:6]; + setData = io_in[5:1]; + end else begin + userInput = io_in[4:1]; + address = 6'b111111; + setData = 5'b00000; + end + end + + FPGA top(.reset, .clock, .address, .userInput, .setData, .out(io_out[3:0])); + +endmodule: my_chip + +module FPGA ( + input logic reset, clock, + input logic [5:0] address, + input logic [3:0] userInput, + input logic [4:0] setData, + output logic [3:0] out +); + + // logic [5:0] address; + logic [7:0] inputSel; + logic [15:0] CLBOut; + logic [1:0] switchOut4, switchOut5, switchOut6; + logic [1:0] switchOut7, switchOut8, switchOut9, switchOut10, switchOut11, switchOut12, switchOut13; + logic [1:0] switchOut14, switchOut15; + + assign out = CLBOut[15:12]; + + // Counter #(6) addressCount(.reset, .clock, .en(enAddress), .Q(address)); + + muxSel inputSel0(.clock, + .reset, + .userInput, + .set(address == 6'd40), + .selConfig(setData[1:0]), + .out(inputSel[0])); + + muxSel inputSel1(.clock, + .reset, + .userInput, + .set(address == 6'd41), + .selConfig(setData[1:0]), + .out(inputSel[1])); + + muxSel inputSel2(.clock, + .reset, + .userInput, + .set(address == 6'd42), + .selConfig(setData[1:0]), + .out(inputSel[2])); + + muxSel inputSel3(.clock, + .reset, + .userInput, + .set(address == 6'd43), + .selConfig(setData[1:0]), + .out(inputSel[3])); + + muxSel inputSel4(.clock, + .reset, + .userInput, + .set(address == 6'd44), + .selConfig(setData[1:0]), + .out(inputSel[4])); + + muxSel inputSel5(.clock, + .reset, + .userInput, + .set(address == 6'd45), + .selConfig(setData[1:0]), + .out(inputSel[5])); + + muxSel inputSel6(.clock, + .reset, + .userInput, + .set(address == 6'd46), + .selConfig(setData[1:0]), + .out(inputSel[6])); + + muxSel inputSel7(.clock, + .reset, + .userInput, + .set(address == 6'd47), + .selConfig(setData[1:0]), + .out(inputSel[7])); + + // first column of CLB + CLB addr0 (.clock, + .reset, + .sel(inputSel[1:0]), // from inputMuxes + .LUTConfig(setData[3:0]), + .memSel_in(setData[4]), + .set(address == 6'd0), + .out(CLBOut[0])); + + CLB addr1 (.clock, + .reset, + .sel(inputSel[3:2]), // from inputMuxes + .LUTConfig(setData[3:0]), + .memSel_in(setData[4]), + .set(address == 6'd1), + .out(CLBOut[1])); + + CLB addr2 (.clock, + .reset, + .sel(inputSel[5:4]), // from inputMuxes + .LUTConfig(setData[3:0]), + .memSel_in(setData[4]), + .set(address == 6'd2), + .out(CLBOut[2])); + + CLB addr3 (.clock, + .reset, + .sel(inputSel[7:6]), // from inputMuxes + .LUTConfig(setData[3:0]), + .memSel_in(setData[4]), + .set(address == 6'd3), + .out(CLBOut[3])); + + // second column of CLB + CLB addr4 (.clock, + .reset, + .sel(switchOut4), // from switchboxes + .LUTConfig(setData[3:0]), + .memSel_in(setData[4]), + .set(address == 6'd4), + .out(CLBOut[4])); + + CLB addr5 (.clock, + .reset, + .sel(switchOut5), // from switchboxes + .LUTConfig(setData[3:0]), + .memSel_in(setData[4]), + .set(address == 6'd5), + .out(CLBOut[5])); + + CLB addr6 (.clock, + .reset, + .sel(switchOut6), // from switchboxes + .LUTConfig(setData[3:0]), + .memSel_in(setData[4]), + .set(address == 6'd6), + .out(CLBOut[6])); + + CLB addr7 (.clock, + .reset, + .sel(switchOut7), // from switchboxes + .LUTConfig(setData[3:0]), + .memSel_in(setData[4]), + .set(address == 6'd7), + .out(CLBOut[7])); + + // third column of CLB + CLB addr8 (.clock, + .reset, + .sel(switchOut8), // from switchboxes + .LUTConfig(setData[3:0]), + .memSel_in(setData[4]), + .set(address == 6'd8), + .out(CLBOut[8])); + + CLB addr9 (.clock, + .reset, + .sel(switchOut9), // from switchboxes + .LUTConfig(setData[3:0]), + .memSel_in(setData[4]), + .set(address == 6'd9), + .out(CLBOut[9])); + + CLB addr10 (.clock, + .reset, + .sel(switchOut10), // from switchboxes + .LUTConfig(setData[3:0]), + .memSel_in(setData[4]), + .set(address == 6'd10), + .out(CLBOut[10])); + + CLB addr11 (.clock, + .reset, + .sel(switchOut11), // from switchboxes + .LUTConfig(setData[3:0]), + .memSel_in(setData[4]), + .set(address == 6'd11), + .out(CLBOut[11])); + + // fourth column of CLB + CLB addr12 (.clock, + .reset, + .sel(switchOut12), // from switchboxes + .LUTConfig(setData[3:0]), + .memSel_in(setData[4]), + .set(address == 6'd12), + .out(CLBOut[12])); + + CLB addr13 (.clock, + .reset, + .sel(switchOut13), // from switchboxes + .LUTConfig(setData[3:0]), + .memSel_in(setData[4]), + .set(address == 6'd13), + .out(CLBOut[13])); + + CLB addr14 (.clock, + .reset, + .sel(switchOut14), // from switchboxes + .LUTConfig(setData[3:0]), + .memSel_in(setData[4]), + .set(address == 6'd14), + .out(CLBOut[14])); + + CLB addr15 (.clock, + .reset, + .sel(switchOut15), // from switchboxes + .LUTConfig(setData[3:0]), + .memSel_in(setData[4]), + .set(address == 6'd15), + .out(CLBOut[15])); + + + // each layer have 8 switchboxes, 4 CLB + // 3 layer of switchboxes, 4 layers of CLB + SwitchBox switch16 (.clock, + .reset, + .set(address == 6'd16), + .inputs(CLBOut[11:0]), + .selectConfig(setData[3:0]), + .out(switchOut4[0])); + + SwitchBox switch17 (.clock, + .reset, + .set(address == 6'd17), + .inputs(CLBOut[11:0]), + .selectConfig(setData[3:0]), + .out(switchOut4[1])); + + SwitchBox switch18 (.clock, + .reset, + .set(address == 6'd18), + .inputs(CLBOut[11:0]), + .selectConfig(setData[3:0]), + .out(switchOut5[0])); + + SwitchBox switch19 (.clock, + .reset, + .set(address == 6'd19), + .inputs(CLBOut[11:0]), + .selectConfig(setData[3:0]), + .out(switchOut5[1])); + + SwitchBox switch20 (.clock, + .reset, + .set(address == 6'd20), + .inputs(CLBOut[11:0]), + .selectConfig(setData[3:0]), + .out(switchOut6[0])); + + SwitchBox switch21 (.clock, + .reset, + .set(address == 6'd21), + .inputs(CLBOut[11:0]), + .selectConfig(setData[3:0]), + .out(switchOut6[1])); + + SwitchBox switch22 (.clock, + .reset, + .set(address == 6'd22), + .inputs(CLBOut[11:0]), + .selectConfig(setData[3:0]), + .out(switchOut7[0])); + + SwitchBox switch23 (.clock, + .reset, + .set(address == 6'd23), + .inputs(CLBOut[11:0]), + .selectConfig(setData[3:0]), + .out(switchOut7[1])); + + SwitchBox switch24 (.clock, + .reset, + .set(address == 6'd24), + .inputs(CLBOut[15:4]), + .selectConfig(setData[3:0]), + .out(switchOut8[0])); + + SwitchBox switch25 (.clock, + .reset, + .set(address == 6'd25), + .inputs(CLBOut[15:4]), + .selectConfig(setData[3:0]), + .out(switchOut8[1])); + + SwitchBox switch26 (.clock, + .reset, + .set(address == 6'd26), + .inputs(CLBOut[15:4]), + .selectConfig(setData[3:0]), + .out(switchOut9[0])); + + SwitchBox switch27 (.clock, + .reset, + .set(address == 6'd27), + .inputs(CLBOut[15:4]), + .selectConfig(setData[3:0]), + .out(switchOut9[1])); + + SwitchBox switch28 (.clock, + .reset, + .set(address == 6'd28), + .inputs(CLBOut[15:4]), + .selectConfig(setData[3:0]), + .out(switchOut10[0])); + + SwitchBox switch29 (.clock, + .reset, + .set(address == 6'd29), + .inputs(CLBOut[15:4]), + .selectConfig(setData[3:0]), + .out(switchOut10[1])); + + SwitchBox switch30 (.clock, + .reset, + .set(address == 6'd30), + .inputs(CLBOut[15:4]), + .selectConfig(setData[3:0]), + .out(switchOut11[0])); + + SwitchBox switch31 (.clock, + .reset, + .set(address == 6'd31), + .inputs(CLBOut[15:4]), + .selectConfig(setData[3:0]), + .out(switchOut11[1])); + + SwitchBox switch32 (.clock, + .reset, + .set(address == 6'd32), + .inputs({4'b0, CLBOut[15:8]}), + .selectConfig(setData[3:0]), + .out(switchOut12[0])); + + SwitchBox switch33 (.clock, + .reset, + .set(address == 6'd33), + .inputs({4'b0, CLBOut[15:8]}), + .selectConfig(setData[3:0]), + .out(switchOut12[1])); + + SwitchBox switch34 (.clock, + .reset, + .set(address == 6'd34), + .inputs({4'b0, CLBOut[15:8]}), + .selectConfig(setData[3:0]), + .out(switchOut13[0])); + + SwitchBox switch35 (.clock, + .reset, + .set(address == 6'd35), + .inputs({4'b0, CLBOut[15:8]}), + .selectConfig(setData[3:0]), + .out(switchOut13[1])); + + SwitchBox switch36 (.clock, + .reset, + .set(address == 6'd36), + .inputs({4'b0, CLBOut[15:8]}), + .selectConfig(setData[3:0]), + .out(switchOut14[0])); + + SwitchBox switch37 (.clock, + .reset, + .set(address == 6'd37), + .inputs({4'b0, CLBOut[15:8]}), + .selectConfig(setData[3:0]), + .out(switchOut14[1])); + + SwitchBox switch38 (.clock, + .reset, + .set(address == 6'd38), + .inputs({4'b0, CLBOut[15:8]}), + .selectConfig(setData[3:0]), + .out(switchOut15[0])); + + SwitchBox switch39 (.clock, + .reset, + .set(address == 6'd39), + .inputs({4'b0, CLBOut[15:8]}), + .selectConfig(setData[3:0]), + .out(switchOut15[1])); + + +endmodule: FPGA diff --git a/designs/d30_yuchingw_fpga/src/config.tcl b/designs/d30_yuchingw_fpga/src/config.tcl new file mode 100644 index 0000000..aa589e4 --- /dev/null +++ b/designs/d30_yuchingw_fpga/src/config.tcl @@ -0,0 +1,68 @@ +# PLEASE DO NOT EDIT THIS FILE! +# IT WILL MAKE YOUR CHIP UNMANUFACTURABLE +# The only line you may edit is FP_CORE_UTIL +# (may benefit from reducing it slightly) + +# User config +set script_dir [file dirname [file normalize [info script]]] + +# read some user config that is written by the setup.py program. +# - the name of the module is defined +# - the list of source files +source $::env(DESIGN_DIR)/user_config.tcl + +# save some time +set ::env(RUN_KLAYOUT_XOR) 0 +set ::env(RUN_KLAYOUT_DRC) 0 + +# don't put clock buffers on the outputs +set ::env(PL_RESIZER_BUFFER_OUTPUT_PORTS) 0 + +# allow use of specific sky130 cells +set ::env(SYNTH_READ_BLACKBOX_LIB) 1 + +# put all the pins on the left +set ::env(FP_PIN_ORDER_CFG) $::env(DESIGN_DIR)/pin_order.cfg + +# reduce wasted space +set ::env(TOP_MARGIN_MULT) 2 +set ::env(BOTTOM_MARGIN_MULT) 2 + +# absolute die size +set ::env(FP_SIZING) absolute +set ::env(DIE_AREA) "0 0 280 280" + +## THIS IS THE ONLY LINE YOU CAN EDIT +set ::env(FP_CORE_UTIL) 45 + +## set ::env(PL_BASIC_PLACEMENT) {1} + +set ::env(FP_IO_HLENGTH) 2 +set ::env(FP_IO_VLENGTH) 2 + +# use alternative efabless decap cells to solve LI density issue +set ::env(DECAP_CELL) "\ + sky130_fd_sc_hd__decap_3 \ + sky130_fd_sc_hd__decap_4 \ + sky130_fd_sc_hd__decap_6 \ + sky130_fd_sc_hd__decap_8 \ + sky130_ef_sc_hd__decap_12" + +# clock +set ::env(CLOCK_TREE_SYNTH) 1 + +# period is in ns, so 500ns == 2 MHz +set ::env(CLOCK_PERIOD) "500" +set ::env(CLOCK_PORT) {io_in[12]} + +# hold/slack margin +# set ::env(PL_RESIZER_HOLD_SLACK_MARGIN) 0.8 +# set ::env(GLB_RESIZER_HOLD_SLACK_MARGIN) 0.8 + +# don't use power rings or met5 +set ::env(DESIGN_IS_CORE) 0 +set ::env(RT_MAX_LAYER) {met4} + +# connect to first digital rails +set ::env(VDD_NETS) [list {vccd1}] +set ::env(GND_NETS) [list {vssd1}] diff --git a/designs/d30_yuchingw_fpga/src/decoder.v b/designs/d30_yuchingw_fpga/src/decoder.v new file mode 100644 index 0000000..8d6310e --- /dev/null +++ b/designs/d30_yuchingw_fpga/src/decoder.v @@ -0,0 +1,38 @@ + +/* + -- 1 -- + | | + 6 2 + | | + -- 7 -- + | | + 5 3 + | | + -- 4 -- +*/ + +module seg7 ( + input wire [3:0] counter, + output reg [6:0] segments +); + + always @(*) begin + case(counter) + // 7654321 + 0: segments = 7'b0111111; + 1: segments = 7'b0000110; + 2: segments = 7'b1011011; + 3: segments = 7'b1001111; + 4: segments = 7'b1100110; + 5: segments = 7'b1101101; + 6: segments = 7'b1111100; + 7: segments = 7'b0000111; + 8: segments = 7'b1111111; + 9: segments = 7'b1100111; + default: + segments = 7'b0000000; + endcase + end + +endmodule + diff --git a/designs/d30_yuchingw_fpga/src/pin_order.cfg b/designs/d30_yuchingw_fpga/src/pin_order.cfg new file mode 100644 index 0000000..0b85c63 --- /dev/null +++ b/designs/d30_yuchingw_fpga/src/pin_order.cfg @@ -0,0 +1,9 @@ +#N + +#S + +#E + +#W +io_in.* +io_out.* diff --git a/designs/d30_yuchingw_fpga/src/toplevel_chip.v b/designs/d30_yuchingw_fpga/src/toplevel_chip.v new file mode 100644 index 0000000..a82b427 --- /dev/null +++ b/designs/d30_yuchingw_fpga/src/toplevel_chip.v @@ -0,0 +1,18 @@ +`default_nettype none + +// DO NOT EDIT THIS FILE +module toplevel_chip ( + input [13:0] io_in, + output [13:0] io_out +); + + my_chip mchip ( + .io_in(io_in[11:0]), + .io_out(io_out[11:0]), + .clock(io_in[12]), + .reset(io_in[13]) + ); + + assign io_out[13:12] = 2'b00; + +endmodule diff --git a/designs/d31_mdhamank_lfsr/LICENSE b/designs/d31_mdhamank_lfsr/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/designs/d31_mdhamank_lfsr/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/designs/d31_mdhamank_lfsr/README.md b/designs/d31_mdhamank_lfsr/README.md new file mode 100644 index 0000000..498a5fe --- /dev/null +++ b/designs/d31_mdhamank_lfsr/README.md @@ -0,0 +1,37 @@ +# LFSR PRNG + +Mihir Dhamankar +98-154 Intro to Open-Source Chip Design, Fall 2022 + +## Description + +8 bit linear feedback shift register pseudorandom number generator + +8 D flip flops make a shift register. The 4th, 5th, and 8th bits are XOR'd into the 1st bit on each cycle, giving a cycle of 255 bit permutations. Another layer of flip flops delays the output by 1 cycle to facilitate holding. + +## Testing + +Set clock to any frequency, power enable input, outputs should be randomized. Outputs should be in the range [1, 255], with a period of 255. + +#### Inputs + +- clock # clock +- enable # on to cycle the shift register +- hold # on to hold the output while cycling the internal shift register, connect to external clock to make PRNG less predictable. +- none +- none +- none +- none +- none + +#### Outputs + +- segment a # bit 0 +- segment b # bit 1 +- segment c # bit 2 +- segment d # bit 3 +- segment e # bit 4 +- segment f # bit 5 +- segment g # bit 6 +- segment h # bit 7 + diff --git a/designs/d31_mdhamank_lfsr/info.yaml b/designs/d31_mdhamank_lfsr/info.yaml new file mode 100644 index 0000000..0b36ccd --- /dev/null +++ b/designs/d31_mdhamank_lfsr/info.yaml @@ -0,0 +1,8 @@ +--- +project: + source_files: + - cells.v + - wokwi.v + top_module: "user_module_350041131706221138" + + tt02_fmt: true diff --git a/designs/d31_mdhamank_lfsr/src/cells.v b/designs/d31_mdhamank_lfsr/src/cells.v new file mode 100644 index 0000000..772fb21 --- /dev/null +++ b/designs/d31_mdhamank_lfsr/src/cells.v @@ -0,0 +1,102 @@ +/* +This file provides the mapping from the Wokwi modules to Verilog HDL + +It's only needed for Wokwi designs + +*/ +`define default_netname none + +module buffer_cell ( + input wire in, + output wire out + ); + assign out = in; +endmodule + +module and_cell ( + input wire a, + input wire b, + output wire out + ); + + assign out = a & b; +endmodule + +module or_cell ( + input wire a, + input wire b, + output wire out + ); + + assign out = a | b; +endmodule + +module xor_cell ( + input wire a, + input wire b, + output wire out + ); + + assign out = a ^ b; +endmodule + +module nand_cell ( + input wire a, + input wire b, + output wire out + ); + + assign out = !(a&b); +endmodule + +module not_cell ( + input wire in, + output wire out + ); + + assign out = !in; +endmodule + +module mux_cell ( + input wire a, + input wire b, + input wire sel, + output wire out + ); + + assign out = sel ? b : a; +endmodule + +module dff_cell ( + input wire clk, + input wire d, + output reg q, + output wire notq + ); + + assign notq = !q; + always @(posedge clk) + q <= d; + +endmodule + +module dffsr_cell ( + input wire clk, + input wire d, + input wire s, + input wire r, + output reg q, + output wire notq + ); + + assign notq = !q; + + always @(posedge clk or posedge s or posedge r) begin + if (r) + q <= 0; + else if (s) + q <= 1; + else + q <= d; + end +endmodule diff --git a/designs/d31_mdhamank_lfsr/src/config.tcl b/designs/d31_mdhamank_lfsr/src/config.tcl new file mode 100644 index 0000000..36321ab --- /dev/null +++ b/designs/d31_mdhamank_lfsr/src/config.tcl @@ -0,0 +1,65 @@ +# PLEASE DO NOT EDIT THIS FILE! +# The only thing you can change is the PL_BASIC_PLACEMENT line +# If you get stuck with this config, please open an issue or get in touch via the discord. + +# User config +set script_dir [file dirname [file normalize [info script]]] + +# read some user config that is written by the setup.py program. +# - the name of the module is defined +# - the list of source files +source $::env(DESIGN_DIR)/user_config.tcl + +# save some time +set ::env(RUN_KLAYOUT_XOR) 0 +set ::env(RUN_KLAYOUT_DRC) 0 + +# don't put clock buffers on the outputs +set ::env(PL_RESIZER_BUFFER_OUTPUT_PORTS) 0 + +# allow use of specific sky130 cells +set ::env(SYNTH_READ_BLACKBOX_LIB) 1 + +# put all the pins on the left +set ::env(FP_PIN_ORDER_CFG) $::env(DESIGN_DIR)/pin_order.cfg + +# reduce wasted space +set ::env(TOP_MARGIN_MULT) 2 +set ::env(BOTTOM_MARGIN_MULT) 2 + +# absolute die size +set ::env(FP_SIZING) absolute +set ::env(DIE_AREA) "0 0 150 170" +set ::env(FP_CORE_UTIL) 55 + +# comment this if your design has more than a few hundred cells +set ::env(PL_BASIC_PLACEMENT) {1} + +set ::env(FP_IO_HLENGTH) 2 +set ::env(FP_IO_VLENGTH) 2 + +# use alternative efabless decap cells to solve LI density issue +set ::env(DECAP_CELL) "\ + sky130_fd_sc_hd__decap_3 \ + sky130_fd_sc_hd__decap_4 \ + sky130_fd_sc_hd__decap_6 \ + sky130_fd_sc_hd__decap_8 \ + sky130_ef_sc_hd__decap_12" + +# clock +set ::env(CLOCK_TREE_SYNTH) 1 +# period is in ns, so 20000ns == 50kHz +set ::env(CLOCK_PERIOD) "20000" +set ::env(CLOCK_PORT) {io_in[0]} + +# hold/slack margin +# set ::env(PL_RESIZER_HOLD_SLACK_MARGIN) 0.8 +# set ::env(GLB_RESIZER_HOLD_SLACK_MARGIN) 0.8 + +# don't use power rings or met5 +set ::env(DESIGN_IS_CORE) 0 +set ::env(RT_MAX_LAYER) {met4} + +# connect to first digital rails +set ::env(VDD_NETS) [list {vccd1}] +set ::env(GND_NETS) [list {vssd1}] diff --git a/designs/d31_mdhamank_lfsr/src/pin_order.cfg b/designs/d31_mdhamank_lfsr/src/pin_order.cfg new file mode 100644 index 0000000..0b85c63 --- /dev/null +++ b/designs/d31_mdhamank_lfsr/src/pin_order.cfg @@ -0,0 +1,9 @@ +#N + +#S + +#E + +#W +io_in.* +io_out.* diff --git a/designs/d31_mdhamank_lfsr/src/wokwi.v b/designs/d31_mdhamank_lfsr/src/wokwi.v new file mode 100644 index 0000000..c249a45 --- /dev/null +++ b/designs/d31_mdhamank_lfsr/src/wokwi.v @@ -0,0 +1,211 @@ +/* Automatically generated from https://wokwi.com/projects/350041131706221138 */ + +`default_nettype none + +module user_module_350041131706221138( + input [7:0] io_in, + output [7:0] io_out +); + wire net1 = io_in[0]; + wire net2 = io_in[1]; + wire net3 = io_in[2]; + wire net4; + wire net5; + wire net6; + wire net7; + wire net8; + wire net9; + wire net10; + wire net11; + wire net12 = 1'b0; + wire net13 = 1'b1; + wire net14; + wire net15 = 1'b1; + wire net16; + wire net17; + wire net18; + wire net19; + wire net20; + wire net21; + wire net22; + wire net23; + wire net24; + wire net25; + wire net26; + wire net27; + wire net28; + wire net29; + wire net30; + wire net31; + wire net32; + wire net33; + wire net34; + wire net35; + wire net36; + wire net37; + + assign io_out[0] = net4; + assign io_out[1] = net5; + assign io_out[2] = net6; + assign io_out[3] = net7; + assign io_out[4] = net8; + assign io_out[5] = net9; + assign io_out[6] = net10; + assign io_out[7] = net11; + + not_cell gate5 ( + .in (net2), + .out (net14) + ); + dff_cell flipflop2 ( + .d (net16), + .clk (net1), + .q (net17) + ); + dff_cell flipflop1 ( + .d (net18), + .clk (net1), + .q (net19) + ); + dff_cell flipflop3 ( + .d (net17), + .clk (net1), + .q (net18) + ); + dff_cell flipflop4 ( + .d (net19), + .clk (net1), + .q (net20), + .notq (net21) + ); + dff_cell flipflop5 ( + .d (net21), + .clk (net1), + .q (net22) + ); + dff_cell flipflop6 ( + .d (net23), + .clk (net1), + .q (net24), + .notq (net25) + ); + dff_cell flipflop7 ( + .d (net22), + .clk (net1), + .q (net23) + ); + dff_cell flipflop8 ( + .d (net25), + .clk (net1), + .q (net26) + ); + xor_cell xor1 ( + .a (net27), + .b (net28), + .out (net29) + ); + xor_cell xor2 ( + .a (net23), + .b (net26), + .out (net28) + ); + xor_cell xor3 ( + .a (net20), + .b (net22), + .out (net27) + ); + dff_cell flipflop9 ( + .d (net30), + .clk (net1), + .q (net4) + ); + dff_cell flipflop10 ( + .d (net31), + .clk (net1), + .q (net6) + ); + dff_cell flipflop11 ( + .d (net32), + .clk (net1), + .q (net5) + ); + dff_cell flipflop12 ( + .d (net33), + .clk (net1), + .q (net7) + ); + dff_cell flipflop13 ( + .d (net34), + .clk (net1), + .q (net8) + ); + dff_cell flipflop14 ( + .d (net35), + .clk (net1), + .q (net10) + ); + dff_cell flipflop15 ( + .d (net36), + .clk (net1), + .q (net9) + ); + dff_cell flipflop16 ( + .d (net37), + .clk (net1), + .q (net11) + ); + mux_cell mux1 ( + .a (net14), + .b (net29), + .sel (net2), + .out (net16) + ); + mux_cell mux2 ( + .a (net17), + .b (net4), + .sel (net3), + .out (net30) + ); + mux_cell mux3 ( + .a (net18), + .b (net5), + .sel (net3), + .out (net32) + ); + mux_cell mux4 ( + .a (net19), + .b (net6), + .sel (net3), + .out (net31) + ); + mux_cell mux5 ( + .a (net20), + .b (net7), + .sel (net3), + .out (net33) + ); + mux_cell mux6 ( + .a (net22), + .b (net8), + .sel (net3), + .out (net34) + ); + mux_cell mux7 ( + .a (net23), + .b (net9), + .sel (net3), + .out (net36) + ); + mux_cell mux8 ( + .a (net24), + .b (net10), + .sel (net3), + .out (net35) + ); + mux_cell mux9 ( + .a (net26), + .b (net11), + .sel (net3), + .out (net37) + ); +endmodule diff --git a/designs/d32_ngaertne_cpu/LICENSE b/designs/d32_ngaertne_cpu/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/designs/d32_ngaertne_cpu/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/designs/d32_ngaertne_cpu/README.md b/designs/d32_ngaertne_cpu/README.md new file mode 100644 index 0000000..bebf92d --- /dev/null +++ b/designs/d32_ngaertne_cpu/README.md @@ -0,0 +1,71 @@ +# 4-bit CPU + +Noah Gaertner +98-154 Intro to Open-Source Chip Design, Fall 2022 + +## Description + +4-bit CPU that does add, subtract, multiply, left and right shifts, conditional jump based on external signal, logical and bitwise AND and OR, equality and inequality checking, bitwise inversion, and logical NOT. + +Implements a highly reduced ISA that fits on the limited allowed space, and uses a 4-bit bus to get the program and data values in and out of the chip, in addition to a two bit bus to tell it what to do at any given time, as well as a clock and reset signal. + +## How to Use + +Write a program for the ISA and try to run it! Remember you need to synchronously RESET and then SETRUNPT to the proper value before you try to do anything! + +### ***NOTE: MUST SEND SYNCHRONOUS RESET IMMEDIATELY BEFORE OPERATION*** + ## PINS: + - IN: + - IN[0]: clock + - IN[1]: reset + - IN[2]: instruction[0] + - IN[3]: instruction[1] + - IN[4]: DATA[0] + - IN[5]: DATA[1] + - IN[6]: DATA[2] + - IN[7]: DATA[3] + - OUT: + - OUT[0]: program counter[0] + - OUT[1]: program counter[1] + - OUT[2]: program counter[2] + - OUT[3]: program counter[3] + - OUT[4]: register value[0] + - OUT[5]: register value[1] + - OUT[6]: register value[2] + - OUT[7]: register value[3] + ## INSTRUCTIONS: + ```sv + LOADPROG = 2'd0, //loads a program into the program "file" using IN[7:4] + LOADDATA = 2'd1, //loads data into the data "file" using IN[7:4] + SETRUNPT = 2'd2, //designed to be used right before run, but can also be used to input additional data i guess + RUNPROG = 2'd3 //run the program + ``` + ## ISA: + ```sv + LOAD = 4'd0, //loads a value from data file into register + STORE = 4'd1, //stores value from register to data file + ADD = 4'd2, //adds datac to register value + MUL = 4'd3, //multiples register value by datac + SUB = 4'd4, //subtracts datac from register value + SHIFTL = 4'd5, //shifts register value left by datac + SHIFTR = 4'd6, //shifts register value right by datac + JUMPTOIF = 4'd7, //jumps pc to data[value] if io_in[7] is a 1, else + //does nothing + LOGICAND = 4'd8, + //logical and between register value and datac + LOGICOR = 4'd9, + //logical or between register value and datac + EQUALS = 4'd10, + //equality check between register value and datac + NEQ = 4'd11, + //inequality check between register value and datac + BITAND = 4'd12, + //bitwise and between register value and datac + BITOR = 4'd13, + //bitwise or between register value and datac + LOGICNOT = 4'd14, + //logical not on register value + BITNOT = 4'd15 + //bitwise not on register value + ``` + diff --git a/designs/d32_ngaertne_cpu/docs/pic.png b/designs/d32_ngaertne_cpu/docs/pic.png new file mode 100644 index 0000000..6e48917 Binary files /dev/null and b/designs/d32_ngaertne_cpu/docs/pic.png differ diff --git a/designs/d32_ngaertne_cpu/info.yaml b/designs/d32_ngaertne_cpu/info.yaml new file mode 100644 index 0000000..aff515a --- /dev/null +++ b/designs/d32_ngaertne_cpu/info.yaml @@ -0,0 +1,7 @@ +--- +project: + source_files: + - cpu.sv + top_module: "noahgaertner_cpu" + + tt02_fmt: true diff --git a/designs/d32_ngaertne_cpu/src/Makefile b/designs/d32_ngaertne_cpu/src/Makefile new file mode 100644 index 0000000..19d90c7 --- /dev/null +++ b/designs/d32_ngaertne_cpu/src/Makefile @@ -0,0 +1,18 @@ +# Makefile +# See https://docs.cocotb.org/en/stable/quickstart.html for more info + +# defaults +SIM ?= icarus +TOPLEVEL_LANG ?= verilog + +VERILOG_SOURCES += $(PWD)/tb.sv $(PWD)/cpu.sv + +# TOPLEVEL is the name of the toplevel module in your Verilog or VHDL file +TOPLEVEL = tb + +# MODULE is the basename of the Python test file +MODULE = test + +# include cocotb's make rules to take care of the simulator setup +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/designs/d32_ngaertne_cpu/src/config.tcl b/designs/d32_ngaertne_cpu/src/config.tcl new file mode 100644 index 0000000..86ffade --- /dev/null +++ b/designs/d32_ngaertne_cpu/src/config.tcl @@ -0,0 +1,65 @@ +# PLEASE DO NOT EDIT THIS FILE! +# The only thing you can change is the PL_BASIC_PLACEMENT line +# If you get stuck with this config, please open an issue or get in touch via the discord. + +# User config +set script_dir [file dirname [file normalize [info script]]] + +# read some user config that is written by the setup.py program. +# - the name of the module is defined +# - the list of source files +source $::env(DESIGN_DIR)/user_config.tcl + +# save some time +set ::env(RUN_KLAYOUT_XOR) 0 +set ::env(RUN_KLAYOUT_DRC) 0 + +# don't put clock buffers on the outputs +set ::env(PL_RESIZER_BUFFER_OUTPUT_PORTS) 0 + +# allow use of specific sky130 cells +set ::env(SYNTH_READ_BLACKBOX_LIB) 1 + +# put all the pins on the left +set ::env(FP_PIN_ORDER_CFG) $::env(DESIGN_DIR)/pin_order.cfg + +# reduce wasted space +set ::env(TOP_MARGIN_MULT) 2 +set ::env(BOTTOM_MARGIN_MULT) 2 + +# absolute die size +set ::env(FP_SIZING) absolute +set ::env(DIE_AREA) "0 0 150 170" +set ::env(FP_CORE_UTIL) 55 + +# comment this if your design has more than a few hundred cells +#set ::env(PL_BASIC_PLACEMENT) {1} + +set ::env(FP_IO_HLENGTH) 2 +set ::env(FP_IO_VLENGTH) 2 + +# use alternative efabless decap cells to solve LI density issue +set ::env(DECAP_CELL) "\ + sky130_fd_sc_hd__decap_3 \ + sky130_fd_sc_hd__decap_4 \ + sky130_fd_sc_hd__decap_6 \ + sky130_fd_sc_hd__decap_8 \ + sky130_ef_sc_hd__decap_12" + +# clock +set ::env(CLOCK_TREE_SYNTH) 1 +# period is in ns, so 20000ns == 50kHz +set ::env(CLOCK_PERIOD) "20000" +set ::env(CLOCK_PORT) {io_in[0]} + +# hold/slack margin +# set ::env(PL_RESIZER_HOLD_SLACK_MARGIN) 0.8 +# set ::env(GLB_RESIZER_HOLD_SLACK_MARGIN) 0.8 + +# don't use power rings or met5 +set ::env(DESIGN_IS_CORE) 0 +set ::env(RT_MAX_LAYER) {met4} + +# connect to first digital rails +set ::env(VDD_NETS) [list {vccd1}] +set ::env(GND_NETS) [list {vssd1}] diff --git a/designs/d32_ngaertne_cpu/src/cpu.sv b/designs/d32_ngaertne_cpu/src/cpu.sv new file mode 100644 index 0000000..acb03e7 --- /dev/null +++ b/designs/d32_ngaertne_cpu/src/cpu.sv @@ -0,0 +1,209 @@ +`default_nettype none +module noahgaertner_cpu ( + input logic [7:0] io_in, + output logic [7:0] io_out +); + logic clock, reset; + assign clock = io_in[0]; //clock + assign reset = io_in[1]; //reset to clear everything + typedef enum logic [3:0] { + LOAD = 4'd0, //loads a value from data file into register + STORE = 4'd1, //stores value from register to data file + ADD = 4'd2, //adds datac to register value + MUL = 4'd3, //multiples register value by datac + SUB = 4'd4, //subtracts datac from register value + SHIFTL = 4'd5, //shifts register value left by datac or 3, + //whichever is less + SHIFTR = 4'd6, //shifts register value right by datac or 3, + //whichever is less + JUMPTOIF = 4'd7, //jumps pc to data[value] if io_in[7] is a 1, else + //does nothing + LOGICAND = 4'd8, + //logical and between register value and datac + LOGICOR = 4'd9, + //logical or between register value and datac + EQUALS = 4'd10, + //equality check between register value and datac + NEQ = 4'd11, + //inequality check between register value and datac + BITAND = 4'd12, + //bitwise and between register value and datac + BITOR = 4'd13, + //bitwise or between register value and datac + LOGICNOT = 4'd14, + //logical not on register value + BITNOT = 4'd15 + //bitwise not on register value + } prog_t; + //yosys doesn't like it if i enum directly instead of typedef w/ memories for + //some reason + prog_t prog[15:0]; //program storage "file" + logic [3:0] data[15:0]; //data storage :file + enum logic [1:0] { + LOADPROG = 2'd0, //loads a program into the program "file" + LOADDATA = 2'd1, //loads data into the data "file" + SETRUNPT = 2'd2, //designed to be used right before run, but can also be used to input additional data i guess + RUNPROG = 2'd3 //run the program + } instruction; + assign instruction = io_in[3:2]; //current instruction + logic [3:0] pc; //program counter + logic [3:0] datac; + prog_t progc; + assign progc = prog[pc]; //prog at pc + assign datac = data[pc]; //data at pc + logic [3:0] regval; //current value being operated on (accumulator) + assign io_out = {regval, pc}; + logic [3:0] inputdata; + logic lastdata3; //input data + assign inputdata = io_in[7:4]; + logic [3:0] npc; + assign npc = pc+1; + + always_ff @(posedge clock) begin + if (!reset) begin + lastdata3 <= inputdata[3]; + case (instruction) + + LOADPROG: begin //loads a program into the program "file" + prog[pc] <= inputdata; + pc <= npc; + end + LOADDATA: begin //loads data into the data "file" + data[pc] <= inputdata; + pc <= npc; + end + SETRUNPT: begin //designed to be used right before run, but can also be used to input additional data i guess + pc <= inputdata; + end + RUNPROG: begin //run the program + case (progc) + LOAD: begin + //loads a value from the data file + regval <= datac; + pc <= npc; + end + STORE: begin + //stores a value into the data file + data[datac] <= regval; + pc <= npc; + end + ADD: begin + //adds the value at the appropriate data address to the register + regval <= regval + datac; + pc <= npc; + end + SUB: begin + //subtracts the value at the appropriate addr from the register + regval <= regval - datac; + pc <= npc; + end + MUL: begin + //multiplies the register by the value at the appropriate addr + pc <= npc; + regval <= regval * datac; + end + SHIFTL: begin + //shifts the register left by the value at the appropriate addr, + //or 3, whichever is less. + pc <= npc; + regval <= ((datac<4) ? regval<>datac : regval >> 3); + end + JUMPTOIF: //jumps to value if input pin 7 is a one + //not unconditional to avoid looping forever + //weird external condition because of single-register/stack + //design due to space limits & effective max of 16 + //microinstructions, which is theoretically circumventable + //by serializing IO and reassembling, but that takes too much + //space + begin + pc <= (lastdata3) ? datac : npc; + regval <= regval; + end + LOGICAND: begin + //logical and between regval and datac + pc <= npc; + regval <= regval && datac; + end + LOGICOR: begin + //logical or between regval and datac + pc <= npc; + regval <= regval || datac; + end + EQUALS: begin + //equality check between regval and datac + pc <= npc; + regval <= (regval == datac); + end + NEQ: begin + //inequality check between regval and datac + pc <= npc; + regval <= (regval != datac); + end + BITAND: begin + //bitwise and between regval and datac + pc <= npc; + regval <= (regval & datac); + end + BITNOT: begin + //bitwise inversion on regval + pc<= npc; + regval <= ~(regval); + end + BITOR: begin + //bitwise or between regval and datac + pc<= npc; + regval <= (regval | datac); + end + LOGICNOT: begin + //logical NOT on regval + pc <= npc; + regval <= !regval; + end + endcase + end + endcase + end else begin + pc <= 0; + regval <= 0; + data[0] <= 4'd0; + data[1] <= 4'd0; + data[2] <= 4'd0; + data[3] <= 4'd0; + data[4] <= 4'd0; + data[5] <= 4'd0; + data[6] <= 4'd0; + data[7] <= 4'd0; + data[8] <= 4'd0; + data[9] <= 4'd0; + data[10] <= 4'd0; + data[11] <= 4'd0; + data[12] <= 4'd0; + data[13] <= 4'd0; + data[14] <= 4'd0; + data[15] <= 4'd0; + prog[0] <= 4'd0; + prog[1] <= 4'd0; + prog[2] <= 4'd0; + prog[3] <= 4'd0; + prog[4] <= 4'd0; + prog[5] <= 4'd0; + prog[6] <= 4'd0; + prog[7] <= 4'd0; + prog[8] <= 4'd0; + prog[9] <= 4'd0; + prog[10] <= 4'd0; + prog[11] <= 4'd0; + prog[12] <= 4'd0; + prog[13] <= 4'd0; + prog[14] <= 4'd0; + prog[15] <= 4'd0; + lastdata3 <= 1'd0; + end + end +endmodule diff --git a/designs/d32_ngaertne_cpu/src/pin_order.cfg b/designs/d32_ngaertne_cpu/src/pin_order.cfg new file mode 100644 index 0000000..0b85c63 --- /dev/null +++ b/designs/d32_ngaertne_cpu/src/pin_order.cfg @@ -0,0 +1,9 @@ +#N + +#S + +#E + +#W +io_in.* +io_out.* diff --git a/designs/d32_ngaertne_cpu/src/tb.gtkw b/designs/d32_ngaertne_cpu/src/tb.gtkw new file mode 100644 index 0000000..52bcbba --- /dev/null +++ b/designs/d32_ngaertne_cpu/src/tb.gtkw @@ -0,0 +1,25 @@ +[*] +[*] GTKWave Analyzer v3.4.0 (w)1999-2022 BSI +[*] Thu Oct 27 10:17:53 2022 +[*] +[dumpfile] "/home/matt/work/asic-workshop/shuttle7/tt02-submission-template/src/tb.vcd" +[dumpfile_mtime] "Thu Oct 27 10:17:11 2022" +[dumpfile_size] 14468 +[savefile] "/home/matt/work/asic-workshop/shuttle7/tt02-submission-template/src/tb.gtkw" +[timestart] 0 +[size] 2286 698 +[pos] -1 -1 +*-30.600000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +[treeopen] tb. +[sst_width] 343 +[signals_width] 264 +[sst_expanded] 1 +[sst_vpaned_height] 190 +@28 +tb.clk +@29 +tb.rst +@22 +tb.segments[6:0] +[pattern_trace] 1 +[pattern_trace] 0 diff --git a/designs/d32_ngaertne_cpu/src/tb.sv b/designs/d32_ngaertne_cpu/src/tb.sv new file mode 100644 index 0000000..a23bbc6 --- /dev/null +++ b/designs/d32_ngaertne_cpu/src/tb.sv @@ -0,0 +1,67 @@ +`default_nettype none `timescale 1ns / 1ps + +/* +this testbench just instantiates the module and makes some convenient wires +that can be driven / tested by the cocotb test.py +*/ + +module tb(); +logic clock, reset; +initial begin + clock = 0; + forever #5 clock = ~clock; +end + // this part dumps the trace to a vcd file that can be viewed with GTKWave + initial begin + $dumpfile("tb.vcd"); + $dumpvars(0, tb); + #1; + end + enum logic [1:0] { + LOADPROG = 2'd0, + LOADDATA = 2'd1, + SETRUNPT = 2'd2, + RUNPROG = 2'd3 + } instruction; + logic [3:0] datain; + // wire up the inputs and output + logic [7:0] inputs; + logic [3:0] data; + logic [7:0] outputs; + assign inputs = {data, instruction, reset, clock}; + + // instantiate the DUT + noahgaertner_cpu cpu_dut ( + .io_in (inputs), + .io_out(outputs) + ); + logic [3:0] dataList[64:0]; + logic [1:0] instructionList[64:0]; + logic [7:0] icount; + initial begin + dataList = {4'd0,4'd0,4'd0,4'd0,4'd0,4'd0,4'd0,4'd0,4'd0,4'd0,4'd0,4'd0,4'd0,4'd0,4'd0,4'd0,4'd0,4'd0,4'd0,4'd0,4'd0,4'd0,4'd0,4'd0,4'd0,4'd0,4'd0,4'd0,4'd0,4'd0,4'd0,4'd15,4'd11,4'd10,4'd15,4'd15,4'd0,4'd11,4'd11,4'd3,4'd0,4'd1,4'd1,4'd11,4'd2,4'd5,4'd6,4'd2,4'd15,4'd14,4'd13,4'd12,4'd11,4'd10,4'd9,4'd8,4'd7,4'd6,4'd5,4'd4,4'd3,4'd2,4'd1,4'd0,4'd0}; + instructionList = {2'd3,2'd3,2'd3,2'd3,2'd3,2'd3,2'd3,2'd3,2'd3,2'd3,2'd3,2'd3,2'd3,2'd3,2'd3,2'd3,2'd3,2'd3,2'd3,2'd3,2'd3,2'd3,2'd3,2'd3,2'd3,2'd3,2'd3,2'd3,2'd3,2'd3,2'd3,2'd2,2'd2,2'd1,2'd1, 2'd1, 2'd1,2'd1,2'd1,2'd1,2'd1,2'd1,2'd1,2'd1,2'd1,2'd1,2'd1,2'd1,2'd0,2'd0,2'd0,2'd0,2'd0,2'd0,2'd0,2'd0,2'd0,2'd0,2'd0,2'd0,2'd0,2'd0,2'd0,2'd0,2'd2}; + $display("start"); + data = 0; + instruction = LOADPROG; + reset = 0; + @(posedge clock); + $display("reset"); + reset = 1; + @(posedge clock); + reset = 0; + $display("iterate through clocks"); + for(int i = 0; i<65; i++) begin + instruction = instructionList[i]; + icount = i; + data = dataList[i]; + if(i==57) data[3] = 1; else data[3] = dataList[i][3]; + $display("check clock %d", i); + @(posedge clock); + end + @(posedge clock); + reset = 1; + @(posedge clock); + $finish; + end +endmodule \ No newline at end of file diff --git a/designs/d32_ngaertne_cpu/src/test.py b/designs/d32_ngaertne_cpu/src/test.py new file mode 100644 index 0000000..99c8070 --- /dev/null +++ b/designs/d32_ngaertne_cpu/src/test.py @@ -0,0 +1,28 @@ +import cocotb +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge, FallingEdge, Timer, ClockCycles + + +instructionslist = [2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3] +datalist = [0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,2,0,5,2,11,5,1,0,3,11,11,0,15,15,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] + +@cocotb.test() +async def test_7seg(dut): + dut._log.info("start") + clock = Clock(dut.clk, 10, units="us") + cocotb.start_soon(clock.start()) + + dut._log.info("reset") + dut.rst.value = 1 + await ClockCycles(dut.clk, 1) + dut.rst.value = 0 + + dut._log.info("iterate through clocks") + for i in range(67): + dut.instruction.value = instructionslist[i] + dut.data.value = datalist[i] + dut._log.info("check clock {}".format(i)) + await ClockCycles(dut.clk, 1) + dut.rst.value = 1 + await ClockCycles(dut.clk,2) + dut.rst.value = 0 diff --git a/designs/d33_mgee3_adder/LICENSE b/designs/d33_mgee3_adder/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/designs/d33_mgee3_adder/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/designs/d33_mgee3_adder/README.md b/designs/d33_mgee3_adder/README.md new file mode 100644 index 0000000..5ddb04a --- /dev/null +++ b/designs/d33_mgee3_adder/README.md @@ -0,0 +1,34 @@ +# 3-bit adder in Wokwi + +Michael Gee +98-154 Intro to Open-Source Chip Design, Fall 2022 + +## Description + +Adds A0 A1 A2 and B0 B1 B2 implemented using one half-adder and two full-adders. LEDs light up correspondingly. + +## Testing + +Result: binary added score at output LED + +### Inputs + +- A0, lowest order bit of first number +- A1, second order bit of first number +- A2, highest order bit of first number +- B0, lowest order bit of second number +- B1, second order bit of second number +- B2, highest order bit of second number +- none +- none + +### Outputs + +- segment a +- segment b +- segment c +- segment d +- segment e +- segment f +- segment g +- none diff --git a/designs/d33_mgee3_adder/info.yaml b/designs/d33_mgee3_adder/info.yaml new file mode 100644 index 0000000..4334cfd --- /dev/null +++ b/designs/d33_mgee3_adder/info.yaml @@ -0,0 +1,8 @@ +--- +project: + source_files: + - cells.v + - wokwi.v + top_module: "user_module_364739787222127617" + + tt02_fmt: true diff --git a/designs/d33_mgee3_adder/src/cells.v b/designs/d33_mgee3_adder/src/cells.v new file mode 100644 index 0000000..772fb21 --- /dev/null +++ b/designs/d33_mgee3_adder/src/cells.v @@ -0,0 +1,102 @@ +/* +This file provides the mapping from the Wokwi modules to Verilog HDL + +It's only needed for Wokwi designs + +*/ +`define default_netname none + +module buffer_cell ( + input wire in, + output wire out + ); + assign out = in; +endmodule + +module and_cell ( + input wire a, + input wire b, + output wire out + ); + + assign out = a & b; +endmodule + +module or_cell ( + input wire a, + input wire b, + output wire out + ); + + assign out = a | b; +endmodule + +module xor_cell ( + input wire a, + input wire b, + output wire out + ); + + assign out = a ^ b; +endmodule + +module nand_cell ( + input wire a, + input wire b, + output wire out + ); + + assign out = !(a&b); +endmodule + +module not_cell ( + input wire in, + output wire out + ); + + assign out = !in; +endmodule + +module mux_cell ( + input wire a, + input wire b, + input wire sel, + output wire out + ); + + assign out = sel ? b : a; +endmodule + +module dff_cell ( + input wire clk, + input wire d, + output reg q, + output wire notq + ); + + assign notq = !q; + always @(posedge clk) + q <= d; + +endmodule + +module dffsr_cell ( + input wire clk, + input wire d, + input wire s, + input wire r, + output reg q, + output wire notq + ); + + assign notq = !q; + + always @(posedge clk or posedge s or posedge r) begin + if (r) + q <= 0; + else if (s) + q <= 1; + else + q <= d; + end +endmodule diff --git a/designs/d33_mgee3_adder/src/config.tcl b/designs/d33_mgee3_adder/src/config.tcl new file mode 100644 index 0000000..36321ab --- /dev/null +++ b/designs/d33_mgee3_adder/src/config.tcl @@ -0,0 +1,65 @@ +# PLEASE DO NOT EDIT THIS FILE! +# The only thing you can change is the PL_BASIC_PLACEMENT line +# If you get stuck with this config, please open an issue or get in touch via the discord. + +# User config +set script_dir [file dirname [file normalize [info script]]] + +# read some user config that is written by the setup.py program. +# - the name of the module is defined +# - the list of source files +source $::env(DESIGN_DIR)/user_config.tcl + +# save some time +set ::env(RUN_KLAYOUT_XOR) 0 +set ::env(RUN_KLAYOUT_DRC) 0 + +# don't put clock buffers on the outputs +set ::env(PL_RESIZER_BUFFER_OUTPUT_PORTS) 0 + +# allow use of specific sky130 cells +set ::env(SYNTH_READ_BLACKBOX_LIB) 1 + +# put all the pins on the left +set ::env(FP_PIN_ORDER_CFG) $::env(DESIGN_DIR)/pin_order.cfg + +# reduce wasted space +set ::env(TOP_MARGIN_MULT) 2 +set ::env(BOTTOM_MARGIN_MULT) 2 + +# absolute die size +set ::env(FP_SIZING) absolute +set ::env(DIE_AREA) "0 0 150 170" +set ::env(FP_CORE_UTIL) 55 + +# comment this if your design has more than a few hundred cells +set ::env(PL_BASIC_PLACEMENT) {1} + +set ::env(FP_IO_HLENGTH) 2 +set ::env(FP_IO_VLENGTH) 2 + +# use alternative efabless decap cells to solve LI density issue +set ::env(DECAP_CELL) "\ + sky130_fd_sc_hd__decap_3 \ + sky130_fd_sc_hd__decap_4 \ + sky130_fd_sc_hd__decap_6 \ + sky130_fd_sc_hd__decap_8 \ + sky130_ef_sc_hd__decap_12" + +# clock +set ::env(CLOCK_TREE_SYNTH) 1 +# period is in ns, so 20000ns == 50kHz +set ::env(CLOCK_PERIOD) "20000" +set ::env(CLOCK_PORT) {io_in[0]} + +# hold/slack margin +# set ::env(PL_RESIZER_HOLD_SLACK_MARGIN) 0.8 +# set ::env(GLB_RESIZER_HOLD_SLACK_MARGIN) 0.8 + +# don't use power rings or met5 +set ::env(DESIGN_IS_CORE) 0 +set ::env(RT_MAX_LAYER) {met4} + +# connect to first digital rails +set ::env(VDD_NETS) [list {vccd1}] +set ::env(GND_NETS) [list {vssd1}] diff --git a/designs/d33_mgee3_adder/src/pin_order.cfg b/designs/d33_mgee3_adder/src/pin_order.cfg new file mode 100644 index 0000000..0b85c63 --- /dev/null +++ b/designs/d33_mgee3_adder/src/pin_order.cfg @@ -0,0 +1,9 @@ +#N + +#S + +#E + +#W +io_in.* +io_out.* diff --git a/designs/d33_mgee3_adder/src/wokwi.v b/designs/d33_mgee3_adder/src/wokwi.v new file mode 100644 index 0000000..99692b7 --- /dev/null +++ b/designs/d33_mgee3_adder/src/wokwi.v @@ -0,0 +1,97 @@ +/* Automatically generated from https://wokwi.com/projects/364739787222127617 */ + +`default_nettype none + +module user_module_364739787222127617( + input [7:0] io_in, + output [7:0] io_out +); + wire net1; + wire net2; + wire net3; + wire net4; + wire net5 = io_in[0]; + wire net6 = io_in[1]; + wire net7 = io_in[2]; + wire net8 = io_in[3]; + wire net9 = io_in[4]; + wire net10 = io_in[5]; + wire net11 = 1'b0; + wire net12 = 1'b1; + wire net13; + wire net14 = 1'b0; + wire net15; + wire net16; + wire net17; + wire net18; + wire net19; + wire net20; + wire net21; + wire net22 = 1'b0; + + assign io_out[0] = net1; + assign io_out[1] = net2; + assign io_out[2] = net3; + assign io_out[3] = net4; + + xor_cell gate7 ( + .a (net6), + .b (net9), + .out (net13) + ); + xor_cell gate8 ( + .a (net13), + .b (net15), + .out (net2) + ); + and_cell gate9 ( + .a (net13), + .b (net15), + .out (net16) + ); + and_cell gate10 ( + .a (net6), + .b (net9), + .out (net17) + ); + or_cell gate11 ( + .a (net16), + .b (net17), + .out (net18) + ); + xor_cell gate12 ( + .a (net7), + .b (net10), + .out (net19) + ); + xor_cell gate13 ( + .a (net19), + .b (net18), + .out (net3) + ); + and_cell gate14 ( + .a (net19), + .b (net18), + .out (net20) + ); + and_cell gate15 ( + .a (net7), + .b (net10), + .out (net21) + ); + or_cell gate16 ( + .a (net20), + .b (net21), + .out (net4) + ); + and_cell gate17 ( + .a (net5), + .b (net8), + .out (net15) + ); + xor_cell gate18 ( + .a (net5), + .b (net8), + .out (net1) + ); +endmodule diff --git a/designs/d34_hgrodin_collatz/LICENSE b/designs/d34_hgrodin_collatz/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/designs/d34_hgrodin_collatz/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/designs/d34_hgrodin_collatz/README.md b/designs/d34_hgrodin_collatz/README.md new file mode 100644 index 0000000..d473835 --- /dev/null +++ b/designs/d34_hgrodin_collatz/README.md @@ -0,0 +1,30 @@ +# 4-bit Collatz Sequence Computer + +Harrison Grodin +98-154 Intro to Open-Source Chip Design, Fall 2022 + +## Description + +Computes the next number in the Collatz sequence using bit-level manipulations + +### Inputs + +- n[0] +- n[1] +- n[2] +- n[3] +- none +- none +- none +- none + +### Outputs + +- collatz[0] +- collatz[1] +- collatz[2] +- collatz[3] +- none +- none +- none +- none diff --git a/designs/d34_hgrodin_collatz/info.yaml b/designs/d34_hgrodin_collatz/info.yaml new file mode 100644 index 0000000..0703456 --- /dev/null +++ b/designs/d34_hgrodin_collatz/info.yaml @@ -0,0 +1,7 @@ +--- +project: + source_files: + - collatz.v + top_module: "collatz" + + tt02_fmt: true diff --git a/designs/d34_hgrodin_collatz/src/collatz.v b/designs/d34_hgrodin_collatz/src/collatz.v new file mode 100644 index 0000000..8c1d842 --- /dev/null +++ b/designs/d34_hgrodin_collatz/src/collatz.v @@ -0,0 +1,39 @@ +`default_nettype none + +module collatz ( + input wire [3:0] n, + output wire [3:0] out +); + wire [3:0] b = {n[0], n[0], n[0], n[0]}; + + wire [3:0] out_even; + assign out_even[3] = 0; + assign out_even[2:0] = n[3:1]; + + wire [3:0] out_odd; + wire [3:0] tmp; + assign tmp[3:1] = n[2:0]; + assign tmp[0] = 0; + wire [3:0] tmp2; + add4 inst2 ( tmp, n, tmp2 ); + add4 inst3 ( tmp2, 4'b0001 , out_odd ); + + assign out = (b & out_odd) | (~b & out_even); +endmodule + +// 4-bit adder +module add4(input wire [3:0] in1, input wire [3:0] in2, output wire [3:0] out); + wire [3:0] rem; + + assign out[0] = in1[0] ^ in2[0]; + assign rem[0] = in1[0] & in2[0]; + + assign out[1] = in1[1] ^ in2[1] ^ rem[0]; + assign rem[1] = (in1[1] & in2[1]) | (in1[1] & rem[0]) | (in2[1] & rem[0]); + + assign out[2] = in1[2] ^ in2[2] ^ rem[1]; + assign rem[2] = (in1[2] & in2[2]) | (in1[2] & rem[1]) | (in2[2] & rem[1]); + + assign out[3] = in1[3] ^ in2[3] ^ rem[2]; + assign rem[3] = (in1[3] & in2[3]) | (in1[3] & rem[2]) | (in2[3] & rem[2]); +endmodule diff --git a/designs/d34_hgrodin_collatz/src/config.tcl b/designs/d34_hgrodin_collatz/src/config.tcl new file mode 100644 index 0000000..36321ab --- /dev/null +++ b/designs/d34_hgrodin_collatz/src/config.tcl @@ -0,0 +1,65 @@ +# PLEASE DO NOT EDIT THIS FILE! +# The only thing you can change is the PL_BASIC_PLACEMENT line +# If you get stuck with this config, please open an issue or get in touch via the discord. + +# User config +set script_dir [file dirname [file normalize [info script]]] + +# read some user config that is written by the setup.py program. +# - the name of the module is defined +# - the list of source files +source $::env(DESIGN_DIR)/user_config.tcl + +# save some time +set ::env(RUN_KLAYOUT_XOR) 0 +set ::env(RUN_KLAYOUT_DRC) 0 + +# don't put clock buffers on the outputs +set ::env(PL_RESIZER_BUFFER_OUTPUT_PORTS) 0 + +# allow use of specific sky130 cells +set ::env(SYNTH_READ_BLACKBOX_LIB) 1 + +# put all the pins on the left +set ::env(FP_PIN_ORDER_CFG) $::env(DESIGN_DIR)/pin_order.cfg + +# reduce wasted space +set ::env(TOP_MARGIN_MULT) 2 +set ::env(BOTTOM_MARGIN_MULT) 2 + +# absolute die size +set ::env(FP_SIZING) absolute +set ::env(DIE_AREA) "0 0 150 170" +set ::env(FP_CORE_UTIL) 55 + +# comment this if your design has more than a few hundred cells +set ::env(PL_BASIC_PLACEMENT) {1} + +set ::env(FP_IO_HLENGTH) 2 +set ::env(FP_IO_VLENGTH) 2 + +# use alternative efabless decap cells to solve LI density issue +set ::env(DECAP_CELL) "\ + sky130_fd_sc_hd__decap_3 \ + sky130_fd_sc_hd__decap_4 \ + sky130_fd_sc_hd__decap_6 \ + sky130_fd_sc_hd__decap_8 \ + sky130_ef_sc_hd__decap_12" + +# clock +set ::env(CLOCK_TREE_SYNTH) 1 +# period is in ns, so 20000ns == 50kHz +set ::env(CLOCK_PERIOD) "20000" +set ::env(CLOCK_PORT) {io_in[0]} + +# hold/slack margin +# set ::env(PL_RESIZER_HOLD_SLACK_MARGIN) 0.8 +# set ::env(GLB_RESIZER_HOLD_SLACK_MARGIN) 0.8 + +# don't use power rings or met5 +set ::env(DESIGN_IS_CORE) 0 +set ::env(RT_MAX_LAYER) {met4} + +# connect to first digital rails +set ::env(VDD_NETS) [list {vccd1}] +set ::env(GND_NETS) [list {vssd1}] diff --git a/designs/d34_hgrodin_collatz/src/pin_order.cfg b/designs/d34_hgrodin_collatz/src/pin_order.cfg new file mode 100644 index 0000000..e2baa11 --- /dev/null +++ b/designs/d34_hgrodin_collatz/src/pin_order.cfg @@ -0,0 +1,9 @@ +#N + +#S + +#E + +#W +n.* +out.* diff --git a/designs/d35_ckasuba_comparator/LICENSE b/designs/d35_ckasuba_comparator/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/designs/d35_ckasuba_comparator/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/designs/d35_ckasuba_comparator/README.md b/designs/d35_ckasuba_comparator/README.md new file mode 100644 index 0000000..9028ab8 --- /dev/null +++ b/designs/d35_ckasuba_comparator/README.md @@ -0,0 +1,34 @@ +# Display Comparator + +Caroline Kasuba +98-154 Intro to Open-Source Chip Design, Fall 2022 + +## Description + +Chip is designed to display result of mag comparator. Logic for magnitude comparator is filtered into seven segment display data. + +## Testing + +Input ones and zeros and get resulting magnitude comparison on seven segment display. 'A' when A > B. 'b' when A < B. '=' when A = B + +### Inputs + +- input A[3] +- input A[2] +- input A[1] +- input A[0] +- input B[3] +- input B[2] +- input B[1] +- input B[0] + +### Outputs + +- segment a +- segment b +- segment c +- segment d +- segment e +- segment f +- segment g +- none diff --git a/designs/d35_ckasuba_comparator/info.yaml b/designs/d35_ckasuba_comparator/info.yaml new file mode 100644 index 0000000..7c0c88f --- /dev/null +++ b/designs/d35_ckasuba_comparator/info.yaml @@ -0,0 +1,8 @@ +--- +project: + source_files: + - cells.v + - wokwi.v + top_module: "user_module_350155397606146642" + + tt02_fmt: true diff --git a/designs/d35_ckasuba_comparator/src/cells.v b/designs/d35_ckasuba_comparator/src/cells.v new file mode 100644 index 0000000..772fb21 --- /dev/null +++ b/designs/d35_ckasuba_comparator/src/cells.v @@ -0,0 +1,102 @@ +/* +This file provides the mapping from the Wokwi modules to Verilog HDL + +It's only needed for Wokwi designs + +*/ +`define default_netname none + +module buffer_cell ( + input wire in, + output wire out + ); + assign out = in; +endmodule + +module and_cell ( + input wire a, + input wire b, + output wire out + ); + + assign out = a & b; +endmodule + +module or_cell ( + input wire a, + input wire b, + output wire out + ); + + assign out = a | b; +endmodule + +module xor_cell ( + input wire a, + input wire b, + output wire out + ); + + assign out = a ^ b; +endmodule + +module nand_cell ( + input wire a, + input wire b, + output wire out + ); + + assign out = !(a&b); +endmodule + +module not_cell ( + input wire in, + output wire out + ); + + assign out = !in; +endmodule + +module mux_cell ( + input wire a, + input wire b, + input wire sel, + output wire out + ); + + assign out = sel ? b : a; +endmodule + +module dff_cell ( + input wire clk, + input wire d, + output reg q, + output wire notq + ); + + assign notq = !q; + always @(posedge clk) + q <= d; + +endmodule + +module dffsr_cell ( + input wire clk, + input wire d, + input wire s, + input wire r, + output reg q, + output wire notq + ); + + assign notq = !q; + + always @(posedge clk or posedge s or posedge r) begin + if (r) + q <= 0; + else if (s) + q <= 1; + else + q <= d; + end +endmodule diff --git a/designs/d35_ckasuba_comparator/src/config.tcl b/designs/d35_ckasuba_comparator/src/config.tcl new file mode 100644 index 0000000..36321ab --- /dev/null +++ b/designs/d35_ckasuba_comparator/src/config.tcl @@ -0,0 +1,65 @@ +# PLEASE DO NOT EDIT THIS FILE! +# The only thing you can change is the PL_BASIC_PLACEMENT line +# If you get stuck with this config, please open an issue or get in touch via the discord. + +# User config +set script_dir [file dirname [file normalize [info script]]] + +# read some user config that is written by the setup.py program. +# - the name of the module is defined +# - the list of source files +source $::env(DESIGN_DIR)/user_config.tcl + +# save some time +set ::env(RUN_KLAYOUT_XOR) 0 +set ::env(RUN_KLAYOUT_DRC) 0 + +# don't put clock buffers on the outputs +set ::env(PL_RESIZER_BUFFER_OUTPUT_PORTS) 0 + +# allow use of specific sky130 cells +set ::env(SYNTH_READ_BLACKBOX_LIB) 1 + +# put all the pins on the left +set ::env(FP_PIN_ORDER_CFG) $::env(DESIGN_DIR)/pin_order.cfg + +# reduce wasted space +set ::env(TOP_MARGIN_MULT) 2 +set ::env(BOTTOM_MARGIN_MULT) 2 + +# absolute die size +set ::env(FP_SIZING) absolute +set ::env(DIE_AREA) "0 0 150 170" +set ::env(FP_CORE_UTIL) 55 + +# comment this if your design has more than a few hundred cells +set ::env(PL_BASIC_PLACEMENT) {1} + +set ::env(FP_IO_HLENGTH) 2 +set ::env(FP_IO_VLENGTH) 2 + +# use alternative efabless decap cells to solve LI density issue +set ::env(DECAP_CELL) "\ + sky130_fd_sc_hd__decap_3 \ + sky130_fd_sc_hd__decap_4 \ + sky130_fd_sc_hd__decap_6 \ + sky130_fd_sc_hd__decap_8 \ + sky130_ef_sc_hd__decap_12" + +# clock +set ::env(CLOCK_TREE_SYNTH) 1 +# period is in ns, so 20000ns == 50kHz +set ::env(CLOCK_PERIOD) "20000" +set ::env(CLOCK_PORT) {io_in[0]} + +# hold/slack margin +# set ::env(PL_RESIZER_HOLD_SLACK_MARGIN) 0.8 +# set ::env(GLB_RESIZER_HOLD_SLACK_MARGIN) 0.8 + +# don't use power rings or met5 +set ::env(DESIGN_IS_CORE) 0 +set ::env(RT_MAX_LAYER) {met4} + +# connect to first digital rails +set ::env(VDD_NETS) [list {vccd1}] +set ::env(GND_NETS) [list {vssd1}] diff --git a/designs/d35_ckasuba_comparator/src/pin_order.cfg b/designs/d35_ckasuba_comparator/src/pin_order.cfg new file mode 100644 index 0000000..0b85c63 --- /dev/null +++ b/designs/d35_ckasuba_comparator/src/pin_order.cfg @@ -0,0 +1,9 @@ +#N + +#S + +#E + +#W +io_in.* +io_out.* diff --git a/designs/d35_ckasuba_comparator/src/wokwi.v b/designs/d35_ckasuba_comparator/src/wokwi.v new file mode 100644 index 0000000..5b848c1 --- /dev/null +++ b/designs/d35_ckasuba_comparator/src/wokwi.v @@ -0,0 +1,263 @@ +/* Automatically generated from https://wokwi.com/projects/350155397606146642 */ + +`default_nettype none + +module user_module_350155397606146642( + input [7:0] io_in, + output [7:0] io_out +); + wire net1 = io_in[0]; + wire net2 = io_in[1]; + wire net3 = io_in[2]; + wire net4 = io_in[3]; + wire net5 = io_in[4]; + wire net6 = io_in[5]; + wire net7 = io_in[6]; + wire net8 = io_in[7]; + wire net9; + wire net10; + wire net11; + wire net12; + wire net13 = 1'b1; + wire net14 = 1'b0; + wire net15 = 1'b1; + wire net16; + wire net17; + wire net18; + wire net19; + wire net20; + wire net21; + wire net22; + wire net23; + wire net24; + wire net25; + wire net26; + wire net27; + wire net28; + wire net29; + wire net30; + wire net31; + wire net32; + wire net33; + wire net34; + wire net35; + wire net36; + wire net37; + wire net38; + wire net39; + wire net40; + wire net41; + wire net42; + wire net43; + wire net44; + wire net45; + wire net46; + wire net47; + wire net48; + wire net49; + wire net50; + wire net51; + wire net52; + + assign io_out[0] = net9; + assign io_out[1] = net10; + assign io_out[2] = net11; + assign io_out[3] = net12; + assign io_out[4] = net11; + assign io_out[5] = net11; + assign io_out[6] = net13; + + not_cell not1 ( + .in (net1), + .out (net16) + ); + not_cell not2 ( + .in (net5), + .out (net17) + ); + and_cell and1 ( + .a (net16), + .b (net5), + .out (net18) + ); + and_cell and2 ( + .a (net1), + .b (net17), + .out (net19) + ); + or_cell or1 ( + .a (net18), + .b (net19), + .out (net20) + ); + not_cell not3 ( + .in (net20), + .out (net21) + ); + not_cell not4 ( + .in (net2), + .out (net22) + ); + not_cell not5 ( + .in (net6), + .out (net23) + ); + and_cell and3 ( + .a (net22), + .b (net6), + .out (net24) + ); + and_cell and4 ( + .a (net2), + .b (net23), + .out (net25) + ); + or_cell or2 ( + .a (net24), + .b (net25), + .out (net26) + ); + not_cell not6 ( + .in (net26), + .out (net27) + ); + not_cell not7 ( + .in (net3), + .out (net28) + ); + not_cell not8 ( + .in (net7), + .out (net29) + ); + and_cell and5 ( + .a (net28), + .b (net7), + .out (net30) + ); + and_cell and6 ( + .a (net3), + .b (net29), + .out (net31) + ); + or_cell or3 ( + .a (net30), + .b (net31), + .out (net32) + ); + not_cell not9 ( + .in (net32), + .out (net33) + ); + not_cell not10 ( + .in (net4), + .out (net34) + ); + not_cell not11 ( + .in (net8), + .out (net35) + ); + and_cell and7 ( + .a (net34), + .b (net8), + .out (net36) + ); + and_cell and8 ( + .a (net4), + .b (net35), + .out (net37) + ); + or_cell or4 ( + .a (net36), + .b (net37), + .out (net38) + ); + not_cell not12 ( + .in (net38), + .out (net39) + ); + and_cell and9 ( + .a (net21), + .b (net27), + .out (net40) + ); + and_cell and10 ( + .a (net21), + .b (net24), + .out (net41) + ); + and_cell and11 ( + .a (net21), + .b (net25), + .out (net42) + ); + and_cell and12 ( + .a (net40), + .b (net33), + .out (net43) + ); + and_cell and13 ( + .a (net43), + .b (net39), + .out (net44) + ); + and_cell and14 ( + .a (net43), + .b (net36), + .out (net45) + ); + and_cell and15 ( + .a (net40), + .b (net31), + .out (net46) + ); + and_cell and16 ( + .a (net40), + .b (net30), + .out (net47) + ); + and_cell and17 ( + .a (net43), + .b (net37), + .out (net48) + ); + or_cell or5 ( + .a (net18), + .b (net41), + .out (net49) + ); + or_cell or6 ( + .a (net47), + .b (net45), + .out (net50) + ); + or_cell or7 ( + .a (net49), + .b (net50), + .out (net12) + ); + or_cell or8 ( + .a (net19), + .b (net42), + .out (net51) + ); + or_cell or9 ( + .a (net46), + .b (net48), + .out (net52) + ); + or_cell or10 ( + .a (net51), + .b (net52), + .out (net10) + ); + or_cell or11 ( + .a (net10), + .b (net44), + .out (net9) + ); + or_cell or12 ( + .a (net12), + .b (net10), + .out (net11) + ); +endmodule diff --git a/designs/d36_jxli_fpmul/LICENSE b/designs/d36_jxli_fpmul/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/designs/d36_jxli_fpmul/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/designs/d36_jxli_fpmul/README.md b/designs/d36_jxli_fpmul/README.md new file mode 100644 index 0000000..9e3be21 --- /dev/null +++ b/designs/d36_jxli_fpmul/README.md @@ -0,0 +1,33 @@ +# FP8(E4M3) Multiplier + +Joseph Li +98-154 Intro to Open-Source Chip Design, Fall 2022 + +## Description + +Multiply two 8-bit floating point numbers together (4-bit exponent, 3-bit mantissa). + +Provide two 8-bit floating point numbers 4 bits at a time, use enable pin to provide these bits one set at a time. Wait a while and the product will appear on the output. + +### Inputs + +- clock +- reset +- enable +- input1 (Sign Bit / Exponent 4) +- input1 (Exponent 1 / Mantissa 1) +- input1 (Exponent 2 / Mantissa 2) +- input1 (Exponent 3 / Mantissa 3) +- none + + +### Outputs + +- Mantissa 3 +- Mantissa 2 +- Mantissa 1 +- Exponent 4 +- Exponent 3 +- Exponent 2 +- Exponent 1 +- Sign Bit diff --git a/designs/d36_jxli_fpmul/info.yaml b/designs/d36_jxli_fpmul/info.yaml new file mode 100644 index 0000000..b7ecb54 --- /dev/null +++ b/designs/d36_jxli_fpmul/info.yaml @@ -0,0 +1,7 @@ +--- +project: + source_files: + - mul.sv + top_module: "jxli_fp8mul" + + tt02_fmt: true diff --git a/designs/d36_jxli_fpmul/src/cells.v b/designs/d36_jxli_fpmul/src/cells.v new file mode 100644 index 0000000..772fb21 --- /dev/null +++ b/designs/d36_jxli_fpmul/src/cells.v @@ -0,0 +1,102 @@ +/* +This file provides the mapping from the Wokwi modules to Verilog HDL + +It's only needed for Wokwi designs + +*/ +`define default_netname none + +module buffer_cell ( + input wire in, + output wire out + ); + assign out = in; +endmodule + +module and_cell ( + input wire a, + input wire b, + output wire out + ); + + assign out = a & b; +endmodule + +module or_cell ( + input wire a, + input wire b, + output wire out + ); + + assign out = a | b; +endmodule + +module xor_cell ( + input wire a, + input wire b, + output wire out + ); + + assign out = a ^ b; +endmodule + +module nand_cell ( + input wire a, + input wire b, + output wire out + ); + + assign out = !(a&b); +endmodule + +module not_cell ( + input wire in, + output wire out + ); + + assign out = !in; +endmodule + +module mux_cell ( + input wire a, + input wire b, + input wire sel, + output wire out + ); + + assign out = sel ? b : a; +endmodule + +module dff_cell ( + input wire clk, + input wire d, + output reg q, + output wire notq + ); + + assign notq = !q; + always @(posedge clk) + q <= d; + +endmodule + +module dffsr_cell ( + input wire clk, + input wire d, + input wire s, + input wire r, + output reg q, + output wire notq + ); + + assign notq = !q; + + always @(posedge clk or posedge s or posedge r) begin + if (r) + q <= 0; + else if (s) + q <= 1; + else + q <= d; + end +endmodule diff --git a/designs/d36_jxli_fpmul/src/config.tcl b/designs/d36_jxli_fpmul/src/config.tcl new file mode 100644 index 0000000..36321ab --- /dev/null +++ b/designs/d36_jxli_fpmul/src/config.tcl @@ -0,0 +1,65 @@ +# PLEASE DO NOT EDIT THIS FILE! +# The only thing you can change is the PL_BASIC_PLACEMENT line +# If you get stuck with this config, please open an issue or get in touch via the discord. + +# User config +set script_dir [file dirname [file normalize [info script]]] + +# read some user config that is written by the setup.py program. +# - the name of the module is defined +# - the list of source files +source $::env(DESIGN_DIR)/user_config.tcl + +# save some time +set ::env(RUN_KLAYOUT_XOR) 0 +set ::env(RUN_KLAYOUT_DRC) 0 + +# don't put clock buffers on the outputs +set ::env(PL_RESIZER_BUFFER_OUTPUT_PORTS) 0 + +# allow use of specific sky130 cells +set ::env(SYNTH_READ_BLACKBOX_LIB) 1 + +# put all the pins on the left +set ::env(FP_PIN_ORDER_CFG) $::env(DESIGN_DIR)/pin_order.cfg + +# reduce wasted space +set ::env(TOP_MARGIN_MULT) 2 +set ::env(BOTTOM_MARGIN_MULT) 2 + +# absolute die size +set ::env(FP_SIZING) absolute +set ::env(DIE_AREA) "0 0 150 170" +set ::env(FP_CORE_UTIL) 55 + +# comment this if your design has more than a few hundred cells +set ::env(PL_BASIC_PLACEMENT) {1} + +set ::env(FP_IO_HLENGTH) 2 +set ::env(FP_IO_VLENGTH) 2 + +# use alternative efabless decap cells to solve LI density issue +set ::env(DECAP_CELL) "\ + sky130_fd_sc_hd__decap_3 \ + sky130_fd_sc_hd__decap_4 \ + sky130_fd_sc_hd__decap_6 \ + sky130_fd_sc_hd__decap_8 \ + sky130_ef_sc_hd__decap_12" + +# clock +set ::env(CLOCK_TREE_SYNTH) 1 +# period is in ns, so 20000ns == 50kHz +set ::env(CLOCK_PERIOD) "20000" +set ::env(CLOCK_PORT) {io_in[0]} + +# hold/slack margin +# set ::env(PL_RESIZER_HOLD_SLACK_MARGIN) 0.8 +# set ::env(GLB_RESIZER_HOLD_SLACK_MARGIN) 0.8 + +# don't use power rings or met5 +set ::env(DESIGN_IS_CORE) 0 +set ::env(RT_MAX_LAYER) {met4} + +# connect to first digital rails +set ::env(VDD_NETS) [list {vccd1}] +set ::env(GND_NETS) [list {vssd1}] diff --git a/designs/d36_jxli_fpmul/src/mul.sv b/designs/d36_jxli_fpmul/src/mul.sv new file mode 100644 index 0000000..460120a --- /dev/null +++ b/designs/d36_jxli_fpmul/src/mul.sv @@ -0,0 +1,199 @@ +module jxli_fp8mul (input [7:0] io_in, output [7:0] io_out); + // 7 6 5 4 3 2 1 0 + //### DATA........... EN RST CLK + + enum logic [3:0] { + AHIGH, ALOW, + BHIGH, BLOW, + CALC1, // load + CALC2, // special cases + denorm + CALC3, + CALC4, + CALC5, + CALC6, + CALC7, + CALC8, + FINISH + } state; + + wire clock = io_in[0]; + wire reset = io_in[1]; + wire enable = io_in[2]; + wire [3:0] data = io_in[6:3]; + + // E4M3 + // 5 bits exponent registers + reg [4:0] ae, be, ce; + // 4 bits mantissa registers + reg [3:0] am, bm, cm; + + reg [7:0] a, b, c; + + assign io_out = c; + + logic aNaN, bNaN, aInfty, bInfty, aZero, bZero; + assign aNaN = ($signed(ae) == 8) && (am != 0); + assign bNaN = ($signed(be) == 8) && (bm != 0); + assign aInfty = ($signed(ae) == 8) && (am == 0); + assign bInfty = ($signed(be) == 8) && (bm == 0); + assign aZero = ($signed(ae) == -7) && (am == 0); + assign bZero = ($signed(be) == -7) && (bm == 0); + logic [6:0] NaN, infty; + assign NaN = 7'b1111_111; + assign infty = 7'b1111_000; + + logic [7:0] product; + assign product = am * bm; + + always_ff @(posedge clock) begin + case(state) + AHIGH: begin + if (enable) begin + a[7:4] <= data; + state <= ALOW; + end + end + + ALOW: begin + if (enable) begin + a[3:0] <= data; + state <= BHIGH; + end + end + + BHIGH: begin + if (enable) begin + b[7:4] <= data; + state <= BLOW; + end + end + + BLOW: begin + if (enable) begin + b[3:0] <= data; + state <= CALC1; + end + end + + CALC1: begin + ae <= {1'b0, a[6:3]} - 5'd7; + am <= {1'b0, a[2:0]}; + be <= {1'b0, b[6:3]} - 5'd7; + bm <= {1'b0, b[2:0]}; + c[7] <= a[7] ^ b[7]; + state <= CALC2; + end + + CALC2: begin + // Process all cases where NaN, Inf, or ±0 appear in input + state <= FINISH; + if (aNaN || bNaN) begin + c[6:0] <= NaN; + end else if (aInfty) begin + // a or b is infty, c is infty + if (bZero) + c[6:0] <= NaN; + else + c[6:0] <= infty; + end else if (bInfty) begin + if (aZero) + c[6:0] <= NaN; + else + c[6:0] <= infty; + end else if (aZero || bZero) begin + // a == 0 or b == 0, c = 0 + c[6:0] <= 7'd0; + end else begin + // denormalize numbers + state <= CALC3; + if ($signed(ae) == -7) begin + ae <= -7; + end else begin + am[3] <= 1; + end + if ($signed(be) == -7) begin + be <= -7; + end else begin + bm[3] <= 1; + end + end + end + + // Align mantissa of a + CALC3: begin + if (am[3]) begin + state <= CALC4; + end else begin + am <= am << 1; + ae <= ae - 1; + end + end + + // Align mantissa of b + CALC4: begin + if (bm[3]) begin + state <= CALC5; + end else begin + bm <= bm << 1; + be <= be - 1; + end + end + + // Perform computation, no rounding behavior + CALC5: begin + ce <= ae + be + 1; + cm <= product[7:3]; + state <= CALC6; + end + + // Create normalized format + CALC6: begin + if (cm[3]) begin + state <= CALC7; + end else begin + cm <= cm << 1; + ce <= ce - 1; + end + end + + // Part 2 + CALC7: begin + if ($signed(ce) < -6) begin + ce <= ce + 1; + cm <= cm >> 1; + end else begin + state <= CALC8; + end + end + + // Pack into output register, + // Detect denormalized number + // Detect overflow + CALC8: begin + c[6:3] <= ce[3:0] + 7; + c[2:0] <= cm[2:0]; + if ($signed(ce) == -6 && cm[3] == 0) begin + c[6:3] <= 0; + end + + if ($signed(ce) > 7) begin + c[6:0] <= infty; + end + + state <= FINISH; + end + + FINISH: begin + end + + endcase + + if(reset) begin + state <= AHIGH; + c <= 8'b1111_1111; + end + + end + + +endmodule diff --git a/designs/d36_jxli_fpmul/src/mul_tb.sv b/designs/d36_jxli_fpmul/src/mul_tb.sv new file mode 100644 index 0000000..59b3a6e --- /dev/null +++ b/designs/d36_jxli_fpmul/src/mul_tb.sv @@ -0,0 +1,82 @@ +module jxli_fp8mul_tb; + + logic clock, reset, enable; + logic [3:0] data; + logic [7:0] io_in, io_out; + + assign io_in = {1'b0, data, enable, reset, clock}; + + jxli_fp8mul dut(.*); + + initial begin + + clock = 1; + forever #5 clock = ~clock; + end + + initial begin + $monitor("in=%b, out=%b, state=%s, a=%b, b=%b, ce=%b, cm=%b", io_in, io_out, dut.state, dut.a, dut.b, dut.ce, dut.cm); + + #10; + reset = 1; + #10; + #10; + reset = 0; + enable = 1; + data = 4'b0111; + // 0 1110 111 * 0 1110 111 + // 1.111 x 2^(14 - 7) * 1.111 x 2^(14 - 7) + // = infty + #10; + #10; + #10; + #10; + #130; + + #10; + reset = 1; + #10; + #10; + reset = 0; + // -20 x 3 + // 1 1010 010 * 0 1000 100 + // 1.010 x 2^(10 - 7) * 1.1 x 2^(8 - 7) + // = -60 + data = 4'b1101; + #10; + data = 4'b0010; + #10; + data = 4'b0100; + #10; + data = 4'b0100; + #10; + #130; + // out = -60 = 1.11100 x 2^(12 - 7) + // = 1 1011 111 + + #10; + reset = 1; + #10; + #10; + reset = 0; + // NaN x Infty + // 1 1111 010 * 0 1111 000 + // = NaN + data = 4'b1111; + #10; + data = 4'b1010; + #10; + data = 4'b0111; + #10; + data = 4'b1000; + #10; + #130; + // out = qNaN + // = 1 1111 111 + + + + $finish; + + end +endmodule \ No newline at end of file diff --git a/designs/d36_jxli_fpmul/src/pin_order.cfg b/designs/d36_jxli_fpmul/src/pin_order.cfg new file mode 100644 index 0000000..0b85c63 --- /dev/null +++ b/designs/d36_jxli_fpmul/src/pin_order.cfg @@ -0,0 +1,9 @@ +#N + +#S + +#E + +#W +io_in.* +io_out.* diff --git a/designs/d37_sophiali_calculator/LICENSE b/designs/d37_sophiali_calculator/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/designs/d37_sophiali_calculator/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/designs/d37_sophiali_calculator/README.md b/designs/d37_sophiali_calculator/README.md new file mode 100644 index 0000000..89f8c88 --- /dev/null +++ b/designs/d37_sophiali_calculator/README.md @@ -0,0 +1,39 @@ +# Continuous Math + +Sophia Li +98-154 Intro to Open-Source Chip Design, Fall 2022 + +## Description + +Output is a total you can ADD, SUBTRACT, XOR, or LEFT_SHIFT with the input. + +Uses a register and some combinational logic. There is a simple state machine so you must release the button for enable_arithmetic before enabling it again. Basically, the same operation won't happen every clock cycle 100k times a second. + +## Testing + +Switch 6. after reset, the output should be zero. Hitting enable (Switch 5) will compute the current arithOp (+ = 2'b00, - = 2'b01, ^ = 2'b10, << = 2'b11 + +### Inputs + +- clock +- reset +- enable +- in_val[2] +- in_val[1] +- in_val[0] +- arithOp[1] +- arithOp[0] + + +### Outputs + +- LED[7] +- LED[6] +- LED[5] +- LED[4] +- LED[3] +- LED[2] +- LED[1] +- LED[0] + + diff --git a/designs/d37_sophiali_calculator/info.yaml b/designs/d37_sophiali_calculator/info.yaml new file mode 100644 index 0000000..6a7fb15 --- /dev/null +++ b/designs/d37_sophiali_calculator/info.yaml @@ -0,0 +1,8 @@ +--- +project: + source_files: + - math.sv + top_module: "sophialiCMU_math" + + tt02_fmt: true + diff --git a/designs/d37_sophiali_calculator/src/TB.sv b/designs/d37_sophiali_calculator/src/TB.sv new file mode 100644 index 0000000..efb2a9b --- /dev/null +++ b/designs/d37_sophiali_calculator/src/TB.sv @@ -0,0 +1,143 @@ + +module sophialiCMU_math_test(); + logic clock, reset, en; + logic [2:0] in; // can input #s 0-7 + logic [1:0] arithOp; + logic [7:0] out; // can output #s 0-15 + + // instansiate + sophialiCMU_math dut(.*); + + // Begin clock + initial begin + clock = 1'b0; + forever #10 clock = ~clock; + end + + initial begin + #100000 + + $display("@%0t: Error timeout!", $time); + $finish; + end + + // Testing values + logic [4:0] i; + logic [3:0] in_val; + logic [7:0] total, want_out; + enum logic [1:0] {ADD = 2'b00, SUB = 2'b01, XOR = 2'b10, LSH = 2'b11} op; + + initial begin + arithOp = 2'b0; + in = 3'b0; + en = 1'b0; + + resetFF(); + + // Test add + $display("====== Start ADD Test ======"); + arithOp = ADD; + total = 0; + for (i = 0; i < 4'b1000; i++) begin + in_val = i[3:0]; + total += in_val; + sendVal(in_val); + assert (out == total); + end + $display("====== End ADD Test ======"); + + // Test sub + $display("====== Start SUB Test ======"); + arithOp = SUB; + for (i = 0; i < 4'b1000; i++) begin + in_val = i[3:0]; + total -= in_val; + sendVal(in_val); + assert (out == total); + end + + // Test sub overflow + resetFF(); + arithOp = SUB; + total = 0; + + for (i = 0; i < 4'b1000; i++) begin + in_val = i[3:0]; + total -= in_val; + sendVal(in_val); + assert (out == total); + end + $display("====== End SUB Test ======"); + + // Test button is stuck at en + // Using a physical button input for enable is slower than + // assigning this enable line. Test for if the FSM works to stop + // the math operation happening multiple times if the enable line + // is active for multiple clocks. + $display("====== Start Stuck En Test ======"); + reset = 1'b0; + reset <= 1'b1; + reset <= #1 1'b0; + repeat (3) @(posedge clock); + arithOp = ADD; + total = 0; + for (i = 0; i < 4'b1000; i++) begin + in_val = i[3:0]; + total += in_val; + in = in_val; + en <= 1'b1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + en <= 1'b0; + @(posedge clock); + assert (out == total); + end + $display("====== End Stuck En Test ======"); + + // Test some ^ + $display("====== Start XOR and LSH Test ======"); + resetFF(); + + // Test 1101_1100 ^ 100 = 1101_1000 + want_out = 8'b1101_1100; + getGivenOut(want_out); + assert(out == want_out) + @(posedge clock); + + $display("====== End XOR and LSH Test ======"); + + + $display("@%0t: Finished!", $time); + $finish; + end + + task sendVal(input logic [2:0] in_val); + in = in_val; + en <= 1'b1; + @(posedge clock); + en <= 1'b0; + @(posedge clock); + endtask: sendVal + + task resetFF(); + reset = 1'b0; + reset <= 1'b1; + reset <= #1 1'b0; + repeat (2) @(posedge clock); + endtask: resetFF + + task getGivenOut(input logic [7:0] wantOut); + arithOp <= ADD; + sendVal(wantOut[7:5]); // out = 0000_0xxx + arithOp <= LSH; + sendVal(3'd3); // out = 00xx_x000 + arithOp <= XOR; + sendVal(wantOut[4:2]); // out = 00xx_xyyy + arithOp <= LSH; + sendVal(3'd2); // out = xxxy_yy00 + arithOp <= XOR; + sendVal({1'b0, wantOut[1:0]}); // out = xxxy_yyzz + endtask: getGivenOut + +endmodule: Math_test \ No newline at end of file diff --git a/designs/d37_sophiali_calculator/src/cells.v b/designs/d37_sophiali_calculator/src/cells.v new file mode 100644 index 0000000..772fb21 --- /dev/null +++ b/designs/d37_sophiali_calculator/src/cells.v @@ -0,0 +1,102 @@ +/* +This file provides the mapping from the Wokwi modules to Verilog HDL + +It's only needed for Wokwi designs + +*/ +`define default_netname none + +module buffer_cell ( + input wire in, + output wire out + ); + assign out = in; +endmodule + +module and_cell ( + input wire a, + input wire b, + output wire out + ); + + assign out = a & b; +endmodule + +module or_cell ( + input wire a, + input wire b, + output wire out + ); + + assign out = a | b; +endmodule + +module xor_cell ( + input wire a, + input wire b, + output wire out + ); + + assign out = a ^ b; +endmodule + +module nand_cell ( + input wire a, + input wire b, + output wire out + ); + + assign out = !(a&b); +endmodule + +module not_cell ( + input wire in, + output wire out + ); + + assign out = !in; +endmodule + +module mux_cell ( + input wire a, + input wire b, + input wire sel, + output wire out + ); + + assign out = sel ? b : a; +endmodule + +module dff_cell ( + input wire clk, + input wire d, + output reg q, + output wire notq + ); + + assign notq = !q; + always @(posedge clk) + q <= d; + +endmodule + +module dffsr_cell ( + input wire clk, + input wire d, + input wire s, + input wire r, + output reg q, + output wire notq + ); + + assign notq = !q; + + always @(posedge clk or posedge s or posedge r) begin + if (r) + q <= 0; + else if (s) + q <= 1; + else + q <= d; + end +endmodule diff --git a/designs/d37_sophiali_calculator/src/config.tcl b/designs/d37_sophiali_calculator/src/config.tcl new file mode 100644 index 0000000..36321ab --- /dev/null +++ b/designs/d37_sophiali_calculator/src/config.tcl @@ -0,0 +1,65 @@ +# PLEASE DO NOT EDIT THIS FILE! +# The only thing you can change is the PL_BASIC_PLACEMENT line +# If you get stuck with this config, please open an issue or get in touch via the discord. + +# User config +set script_dir [file dirname [file normalize [info script]]] + +# read some user config that is written by the setup.py program. +# - the name of the module is defined +# - the list of source files +source $::env(DESIGN_DIR)/user_config.tcl + +# save some time +set ::env(RUN_KLAYOUT_XOR) 0 +set ::env(RUN_KLAYOUT_DRC) 0 + +# don't put clock buffers on the outputs +set ::env(PL_RESIZER_BUFFER_OUTPUT_PORTS) 0 + +# allow use of specific sky130 cells +set ::env(SYNTH_READ_BLACKBOX_LIB) 1 + +# put all the pins on the left +set ::env(FP_PIN_ORDER_CFG) $::env(DESIGN_DIR)/pin_order.cfg + +# reduce wasted space +set ::env(TOP_MARGIN_MULT) 2 +set ::env(BOTTOM_MARGIN_MULT) 2 + +# absolute die size +set ::env(FP_SIZING) absolute +set ::env(DIE_AREA) "0 0 150 170" +set ::env(FP_CORE_UTIL) 55 + +# comment this if your design has more than a few hundred cells +set ::env(PL_BASIC_PLACEMENT) {1} + +set ::env(FP_IO_HLENGTH) 2 +set ::env(FP_IO_VLENGTH) 2 + +# use alternative efabless decap cells to solve LI density issue +set ::env(DECAP_CELL) "\ + sky130_fd_sc_hd__decap_3 \ + sky130_fd_sc_hd__decap_4 \ + sky130_fd_sc_hd__decap_6 \ + sky130_fd_sc_hd__decap_8 \ + sky130_ef_sc_hd__decap_12" + +# clock +set ::env(CLOCK_TREE_SYNTH) 1 +# period is in ns, so 20000ns == 50kHz +set ::env(CLOCK_PERIOD) "20000" +set ::env(CLOCK_PORT) {io_in[0]} + +# hold/slack margin +# set ::env(PL_RESIZER_HOLD_SLACK_MARGIN) 0.8 +# set ::env(GLB_RESIZER_HOLD_SLACK_MARGIN) 0.8 + +# don't use power rings or met5 +set ::env(DESIGN_IS_CORE) 0 +set ::env(RT_MAX_LAYER) {met4} + +# connect to first digital rails +set ::env(VDD_NETS) [list {vccd1}] +set ::env(GND_NETS) [list {vssd1}] diff --git a/designs/d37_sophiali_calculator/src/math.sv b/designs/d37_sophiali_calculator/src/math.sv new file mode 100644 index 0000000..9499aa8 --- /dev/null +++ b/designs/d37_sophiali_calculator/src/math.sv @@ -0,0 +1,66 @@ +// 8 inputs +// 8 outputs + +// 4 bit input value (switches) +// reset +// do arithmetic +// 2 bits for +, -, ^, << +// I would have done & and | but doing those operations with +// an 8-bit number and 3-bit number wasn't that useful + +// 2 7-segment displays + +module sophialiCMU_math ( + input logic [7:0] io_in, + output logic [7:0] io_out +); + + logic clock, reset, en; + logic [2:0] in; + logic [1:0] arithOp; + + always_comb begin + clock = io_in[0]; + reset = io_in[1]; + en = io_in[2]; + in = io_in[3:5]; + arithOp = io_in[6:7]; + end + + logic enable; + enum logic {IDLE, GO} state, nextState; + + // ALU + always_ff @(posedge clock, posedge reset) begin + if (reset) + io_out <= 0; + else begin + if (enable) + unique case (arithOp) + 2'b00: io_out <= io_out + in; // add + 2'b01: io_out <= io_out - in; // subtract + 2'b10: io_out <= io_out ^ {5'b0, in}; // XOR per bit + 2'b11: io_out <= io_out << in; // Left-shift per bit + endcase + end + end + + // FF to ensure button for enable isn't continuously set + always_ff @(posedge clock, posedge reset) begin + if (reset) + state <= IDLE; + else begin + state <= nextState; + end + end + + assign enable = (state == IDLE && nextState == GO); + always_comb begin + if (state == IDLE) begin + nextState = (en) ? GO : IDLE; + end + else + nextState = (en) ? GO : IDLE; + end + +endmodule: sophialiCMU_math diff --git a/designs/d37_sophiali_calculator/src/pin_order.cfg b/designs/d37_sophiali_calculator/src/pin_order.cfg new file mode 100644 index 0000000..0b85c63 --- /dev/null +++ b/designs/d37_sophiali_calculator/src/pin_order.cfg @@ -0,0 +1,9 @@ +#N + +#S + +#E + +#W +io_in.* +io_out.* diff --git a/designs/d38_jxlu_pwm/LICENSE b/designs/d38_jxlu_pwm/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/designs/d38_jxlu_pwm/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/designs/d38_jxlu_pwm/README.md b/designs/d38_jxlu_pwm/README.md new file mode 100644 index 0000000..f126d8b --- /dev/null +++ b/designs/d38_jxlu_pwm/README.md @@ -0,0 +1,33 @@ +# PWM Generator + +Jason Lu +98-154 Intro to Open-Source Chip Design, Fall 2022 + +## Description + +Generates 100 Hz PWM signal. The duty cycle inputs run from 0 - 50 and specify a duty cycle of input * 2. + +Link up switches to the duty cycle inputs and toggle them to set the duty cycle. Wire an LED to the PWM output to see the output. + +### Inputs + +- clock +- reset +- duty cycle 0 +- duty cycle 1 +- duty cycle 2 +- duty cycle 3 +- duty cycle 4 +- duty cycle 5 + + +### Outputs + +- pwm output +- none +- none +- none +- none +- none +- none +- none diff --git a/designs/d38_jxlu_pwm/configure.py b/designs/d38_jxlu_pwm/configure.py new file mode 100755 index 0000000..6d892e2 --- /dev/null +++ b/designs/d38_jxlu_pwm/configure.py @@ -0,0 +1,163 @@ +#!/usr/bin/env python3 +import requests +import argparse +import os +import glob +import yaml +import logging +import sys +import csv +import re + + +def load_yaml(yaml_file): + with open(yaml_file, "r") as stream: + return (yaml.safe_load(stream)) + + +def write_user_config(module_name, sources): + filename = 'user_config.tcl' + with open(os.path.join('src', filename), 'w') as fh: + fh.write("set ::env(DESIGN_NAME) {}\n".format(module_name)) + fh.write('set ::env(VERILOG_FILES) "\\\n') + for line, source in enumerate(sources): + fh.write(" $::env(DESIGN_DIR)/" + source) + if line != len(sources) - 1: + fh.write(' \\\n') + fh.write('"\n') + + +def get_project_source(yaml): + # wokwi_id must be an int or 0 + try: + wokwi_id = int(yaml['project']['wokwi_id']) + except ValueError: + logging.error("wokwi id must be an integer") + exit(1) + + # it's a wokwi project + if wokwi_id != 0: + url = "https://wokwi.com/api/projects/{}/verilog".format(wokwi_id) + logging.info("trying to download {}".format(url)) + r = requests.get(url) + if r.status_code != 200: + logging.warning("couldn't download {}".format(url)) + exit(1) + + filename = "user_module_{}.v".format(wokwi_id) + with open(os.path.join('src', filename), 'wb') as fh: + fh.write(r.content) + + # also fetch the wokwi diagram + url = "https://wokwi.com/api/projects/{}/diagram.json".format(wokwi_id) + logging.info("trying to download {}".format(url)) + r = requests.get(url) + if r.status_code != 200: + logging.warning("couldn't download {}".format(url)) + exit(1) + + with open(os.path.join('src', "wokwi_diagram.json"), 'wb') as fh: + fh.write(r.content) + + return [filename, 'cells.v'] + + # else it's HDL, so check source files + else: + if 'source_files' not in yaml['project']: + logging.error("source files must be provided if wokwi_id is set to 0") + exit(1) + + source_files = yaml['project']['source_files'] + if source_files is None: + logging.error("must be more than 1 source file") + exit(1) + + if len(source_files) == 0: + logging.error("must be more than 1 source file") + exit(1) + + if 'top_module' not in yaml['project']: + logging.error("must provide a top module name") + exit(1) + + for filename in source_files: + assert os.path.exists(os.path.join('src', filename)) + + return source_files + + +# documentation +def check_docs(yaml): + for key in ['author', 'title', 'description', 'how_it_works', 'how_to_test', 'language']: + if key not in yaml['documentation']: + logging.error("missing key {} in documentation".format(key)) + exit(1) + if yaml['documentation'][key] == "": + logging.error("missing value for {} in documentation".format(key)) + exit(1) + + # if provided, check discord handle is valid + if len(yaml['documentation']['discord']): + parts = yaml['documentation']['discord'].split('#') + if len(parts) != 2 or len(parts[0]) == 0 or not re.match('^[0-9]{4}$', parts[1]): + logging.error(f'Invalid format for discord username') + exit(1) + + +def get_top_module(yaml): + wokwi_id = int(yaml['project']['wokwi_id']) + if wokwi_id != 0: + return "user_module_{}".format(wokwi_id) + else: + return yaml['project']['top_module'] + + +def get_stats(): + with open('runs/wokwi/reports/metrics.csv') as f: + report = list(csv.DictReader(f))[0] + + print('# Routing stats') + print() + print('| Utilisation | Wire length (um) |') + print('|-------------|------------------|') + print('| {} | {} |'.format(report['OpenDP_Util'], report['wire_length'])) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description="TT setup") + + parser.add_argument('--check-docs', help="check the documentation part of the yaml", action="store_const", const=True) + parser.add_argument('--get-stats', help="print some stats from the run", action="store_const", const=True) + parser.add_argument('--create-user-config', help="create the user_config.tcl file with top module and source files", action="store_const", const=True) + parser.add_argument('--debug', help="debug logging", action="store_const", dest="loglevel", const=logging.DEBUG, default=logging.INFO) + parser.add_argument('--yaml', help="yaml file to load", default='info.yaml') + + args = parser.parse_args() + # setup log + log_format = logging.Formatter('%(asctime)s - %(module)-10s - %(levelname)-8s - %(message)s') + # configure the client logging + log = logging.getLogger('') + # has to be set to debug as is the root logger + log.setLevel(args.loglevel) + + # create console handler and set level to info + ch = logging.StreamHandler(sys.stdout) + # create formatter for console + ch.setFormatter(log_format) + log.addHandler(ch) + + if args.get_stats: + get_stats() + + elif args.check_docs: + logging.info("checking docs") + config = load_yaml(args.yaml) + check_docs(config) + + elif args.create_user_config: + logging.info("creating include file") + config = load_yaml(args.yaml) + source_files = get_project_source(config) + top_module = get_top_module(config) + assert top_module != 'top' + write_user_config(top_module, source_files) diff --git a/designs/d38_jxlu_pwm/info.yaml b/designs/d38_jxlu_pwm/info.yaml new file mode 100644 index 0000000..4067f2c --- /dev/null +++ b/designs/d38_jxlu_pwm/info.yaml @@ -0,0 +1,9 @@ +--- +project: + source_files: + - poisonninja_top.v + - pwm_generator.v + top_module: "poisonninja_top" + + tt02_fmt: true + diff --git a/designs/d38_jxlu_pwm/src/cells.v b/designs/d38_jxlu_pwm/src/cells.v new file mode 100644 index 0000000..772fb21 --- /dev/null +++ b/designs/d38_jxlu_pwm/src/cells.v @@ -0,0 +1,102 @@ +/* +This file provides the mapping from the Wokwi modules to Verilog HDL + +It's only needed for Wokwi designs + +*/ +`define default_netname none + +module buffer_cell ( + input wire in, + output wire out + ); + assign out = in; +endmodule + +module and_cell ( + input wire a, + input wire b, + output wire out + ); + + assign out = a & b; +endmodule + +module or_cell ( + input wire a, + input wire b, + output wire out + ); + + assign out = a | b; +endmodule + +module xor_cell ( + input wire a, + input wire b, + output wire out + ); + + assign out = a ^ b; +endmodule + +module nand_cell ( + input wire a, + input wire b, + output wire out + ); + + assign out = !(a&b); +endmodule + +module not_cell ( + input wire in, + output wire out + ); + + assign out = !in; +endmodule + +module mux_cell ( + input wire a, + input wire b, + input wire sel, + output wire out + ); + + assign out = sel ? b : a; +endmodule + +module dff_cell ( + input wire clk, + input wire d, + output reg q, + output wire notq + ); + + assign notq = !q; + always @(posedge clk) + q <= d; + +endmodule + +module dffsr_cell ( + input wire clk, + input wire d, + input wire s, + input wire r, + output reg q, + output wire notq + ); + + assign notq = !q; + + always @(posedge clk or posedge s or posedge r) begin + if (r) + q <= 0; + else if (s) + q <= 1; + else + q <= d; + end +endmodule diff --git a/designs/d38_jxlu_pwm/src/config.tcl b/designs/d38_jxlu_pwm/src/config.tcl new file mode 100644 index 0000000..5d6d339 --- /dev/null +++ b/designs/d38_jxlu_pwm/src/config.tcl @@ -0,0 +1,62 @@ +# DO NOT EDIT THIS FILE! +# We will rebuild your GDS for the final submission using the information given in the yaml file only +# If you get stuck with this config, please open an issue or get in touch via the discord. + +# User config +set script_dir [file dirname [file normalize [info script]]] + +# read some user config that is written by the setup.py program. +# - the name of the module is defined +# - the list of source files +source $::env(DESIGN_DIR)/user_config.tcl + +# save some time +set ::env(RUN_KLAYOUT_XOR) 0 +set ::env(RUN_KLAYOUT_DRC) 0 + +# don't put clock buffers on the outputs +set ::env(PL_RESIZER_BUFFER_OUTPUT_PORTS) 0 + +# allow use of specific sky130 cells +set ::env(SYNTH_READ_BLACKBOX_LIB) 1 + +# put all the pins on the left +set ::env(FP_PIN_ORDER_CFG) $::env(DESIGN_DIR)/pin_order.cfg + +# reduce wasted space +set ::env(TOP_MARGIN_MULT) 2 +set ::env(BOTTOM_MARGIN_MULT) 2 + +# absolute die size +set ::env(FP_SIZING) absolute +set ::env(DIE_AREA) "0 0 150 170" +set ::env(FP_CORE_UTIL) 55 +set ::env(PL_BASIC_PLACEMENT) {1} + +set ::env(FP_IO_HLENGTH) 2 +set ::env(FP_IO_VLENGTH) 2 + +# use alternative efabless decap cells to solve LI density issue +set ::env(DECAP_CELL) "\ + sky130_fd_sc_hd__decap_3 \ + sky130_fd_sc_hd__decap_4 \ + sky130_fd_sc_hd__decap_6 \ + sky130_fd_sc_hd__decap_8 \ + sky130_ef_sc_hd__decap_12" + +# clock +set ::env(CLOCK_TREE_SYNTH) 1 +set ::env(CLOCK_PERIOD) "100000" +set ::env(CLOCK_PORT) {io_in[0]} + +# hold/slack margin +# set ::env(PL_RESIZER_HOLD_SLACK_MARGIN) 0.8 +# set ::env(GLB_RESIZER_HOLD_SLACK_MARGIN) 0.8 + +# don't use power rings or met5 +set ::env(DESIGN_IS_CORE) 0 +set ::env(RT_MAX_LAYER) {met4} + +# connect to first digital rails +set ::env(VDD_NETS) [list {vccd1}] +set ::env(GND_NETS) [list {vssd1}] diff --git a/designs/d38_jxlu_pwm/src/pin_order.cfg b/designs/d38_jxlu_pwm/src/pin_order.cfg new file mode 100644 index 0000000..0b85c63 --- /dev/null +++ b/designs/d38_jxlu_pwm/src/pin_order.cfg @@ -0,0 +1,9 @@ +#N + +#S + +#E + +#W +io_in.* +io_out.* diff --git a/designs/d38_jxlu_pwm/src/poisonninja_top.v b/designs/d38_jxlu_pwm/src/poisonninja_top.v new file mode 100644 index 0000000..6551d0c --- /dev/null +++ b/designs/d38_jxlu_pwm/src/poisonninja_top.v @@ -0,0 +1,11 @@ +`default_nettype none + +module poisonninja_top ( + input logic [7:0] io_in, + output logic [7:0] io_out +); + + assign io_out[7:1] = 0; + pwm_generator pwm(.clk(io_in[0]), .reset(io_in[1]), .duty(io_in[7:2]), .pwm_signal(io_out[0])); + +endmodule \ No newline at end of file diff --git a/designs/d38_jxlu_pwm/src/pwm_generator.v b/designs/d38_jxlu_pwm/src/pwm_generator.v new file mode 100644 index 0000000..1e44c50 --- /dev/null +++ b/designs/d38_jxlu_pwm/src/pwm_generator.v @@ -0,0 +1,39 @@ +`default_nettype none + +module pwm_generator ( + input logic clk, + input logic reset, + input logic [5:0] duty, + output logic pwm_signal +); + logic [5:0] counter; + logic [5:0] active_duty; + + always_ff @(posedge clk) begin + if (reset == 1) begin + if (duty > 6'd50) begin + active_duty <= 6'd50; + end + else begin + active_duty <= duty; + end + + counter <= 0; + end + else begin + counter <= counter + 1'b1; + + if (counter == 49) begin + counter <= 0; + end + + if (counter >= active_duty) begin + pwm_signal <= 1'b0; + end + else begin + pwm_signal <= 1'b1; + end + end + end + +endmodule \ No newline at end of file diff --git a/designs/d38_jxlu_pwm/src/tb.v b/designs/d38_jxlu_pwm/src/tb.v new file mode 100644 index 0000000..786fbcc --- /dev/null +++ b/designs/d38_jxlu_pwm/src/tb.v @@ -0,0 +1,62 @@ +module tb; + + logic [5:0] io_in; + logic [7:0] io_out; + logic clock; + logic reset; + poisonninja_top dut(.io_in({io_in, reset, clock}), .io_out(io_out)); + + always #1 clock = ~clock; + + initial begin + clock = 0; + $monitor("%t: Duty: %d, Output: %d", $time, io_in, io_out[0]); + + io_in = 25; + reset = 1; + @(negedge clock); + reset = 0; + for (int i = 0; i < 25; i++) begin + @(negedge clock); + assert(io_out[0] == 1); + end + for (int i = 0; i < 25; i++) begin + @(negedge clock); + assert(io_out[0] == 0); + end + + io_in = 10; + reset = 1; + @(negedge clock); + reset = 0; + for (int i = 0; i < 10; i++) begin + @(negedge clock); + assert(io_out[0] == 1); + end + for (int i = 0; i < 40; i++) begin + @(negedge clock); + assert(io_out[0] == 0); + end + + io_in = 50; + reset = 1; + @(negedge clock); + reset = 0; + for (int i = 0; i < 50; i++) begin + @(negedge clock); + assert(io_out[0] == 1); + end + + io_in = 60; + reset = 1; + @(negedge clock); + reset = 0; + for (int i = 0; i < 50; i++) begin + @(negedge clock); + assert(io_out[0] == 1); + end + + $finish; + end + +endmodule \ No newline at end of file diff --git a/designs/d38_jxlu_pwm/src/test.sh b/designs/d38_jxlu_pwm/src/test.sh new file mode 100755 index 0000000..f90d453 --- /dev/null +++ b/designs/d38_jxlu_pwm/src/test.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +set -xe + +iverilog -g2012 -o test.vvp poisonninja_top.v tb.v pwm_generator.v +vvp test.vvp +rm test.vvp \ No newline at end of file diff --git a/designs/d39_oonyeado_sevenseg/LICENSE b/designs/d39_oonyeado_sevenseg/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/designs/d39_oonyeado_sevenseg/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/designs/d39_oonyeado_sevenseg/README.md b/designs/d39_oonyeado_sevenseg/README.md new file mode 100644 index 0000000..03f0012 --- /dev/null +++ b/designs/d39_oonyeado_sevenseg/README.md @@ -0,0 +1,34 @@ +# Hex to Seven-Segment Converter + +Kachi Onyeador +98-154 Intro to Open-Source Chip Design, Fall 2022 + +## Description + +Takes a Hex Input using a 4 way DIP switch and outputs the corresponding representation on a Seven-Segment Display + +## Testing + +Enter the binary for a the hex digit on the DIP switch + +### Inputs + +- DIP Switch Position 1 +- DIP Switch Position 2 +- DIP Switch Position 3 +- DIP Switch Position 4 +- none +- none +- none +- none + +### Outputs + +- segment a +- segment b +- segment c +- segment d +- segment e +- segment f +- segment g +- none diff --git a/designs/d39_oonyeado_sevenseg/info.yaml b/designs/d39_oonyeado_sevenseg/info.yaml new file mode 100644 index 0000000..3cddf4d --- /dev/null +++ b/designs/d39_oonyeado_sevenseg/info.yaml @@ -0,0 +1,8 @@ +--- +project: + source_files: + - cells.v + - wokwi.v + top_module: "user_module_350866594173289042" + + tt02_fmt: true diff --git a/designs/d39_oonyeado_sevenseg/src/cells.v b/designs/d39_oonyeado_sevenseg/src/cells.v new file mode 100644 index 0000000..772fb21 --- /dev/null +++ b/designs/d39_oonyeado_sevenseg/src/cells.v @@ -0,0 +1,102 @@ +/* +This file provides the mapping from the Wokwi modules to Verilog HDL + +It's only needed for Wokwi designs + +*/ +`define default_netname none + +module buffer_cell ( + input wire in, + output wire out + ); + assign out = in; +endmodule + +module and_cell ( + input wire a, + input wire b, + output wire out + ); + + assign out = a & b; +endmodule + +module or_cell ( + input wire a, + input wire b, + output wire out + ); + + assign out = a | b; +endmodule + +module xor_cell ( + input wire a, + input wire b, + output wire out + ); + + assign out = a ^ b; +endmodule + +module nand_cell ( + input wire a, + input wire b, + output wire out + ); + + assign out = !(a&b); +endmodule + +module not_cell ( + input wire in, + output wire out + ); + + assign out = !in; +endmodule + +module mux_cell ( + input wire a, + input wire b, + input wire sel, + output wire out + ); + + assign out = sel ? b : a; +endmodule + +module dff_cell ( + input wire clk, + input wire d, + output reg q, + output wire notq + ); + + assign notq = !q; + always @(posedge clk) + q <= d; + +endmodule + +module dffsr_cell ( + input wire clk, + input wire d, + input wire s, + input wire r, + output reg q, + output wire notq + ); + + assign notq = !q; + + always @(posedge clk or posedge s or posedge r) begin + if (r) + q <= 0; + else if (s) + q <= 1; + else + q <= d; + end +endmodule diff --git a/designs/d39_oonyeado_sevenseg/src/config.tcl b/designs/d39_oonyeado_sevenseg/src/config.tcl new file mode 100644 index 0000000..36321ab --- /dev/null +++ b/designs/d39_oonyeado_sevenseg/src/config.tcl @@ -0,0 +1,65 @@ +# PLEASE DO NOT EDIT THIS FILE! +# The only thing you can change is the PL_BASIC_PLACEMENT line +# If you get stuck with this config, please open an issue or get in touch via the discord. + +# User config +set script_dir [file dirname [file normalize [info script]]] + +# read some user config that is written by the setup.py program. +# - the name of the module is defined +# - the list of source files +source $::env(DESIGN_DIR)/user_config.tcl + +# save some time +set ::env(RUN_KLAYOUT_XOR) 0 +set ::env(RUN_KLAYOUT_DRC) 0 + +# don't put clock buffers on the outputs +set ::env(PL_RESIZER_BUFFER_OUTPUT_PORTS) 0 + +# allow use of specific sky130 cells +set ::env(SYNTH_READ_BLACKBOX_LIB) 1 + +# put all the pins on the left +set ::env(FP_PIN_ORDER_CFG) $::env(DESIGN_DIR)/pin_order.cfg + +# reduce wasted space +set ::env(TOP_MARGIN_MULT) 2 +set ::env(BOTTOM_MARGIN_MULT) 2 + +# absolute die size +set ::env(FP_SIZING) absolute +set ::env(DIE_AREA) "0 0 150 170" +set ::env(FP_CORE_UTIL) 55 + +# comment this if your design has more than a few hundred cells +set ::env(PL_BASIC_PLACEMENT) {1} + +set ::env(FP_IO_HLENGTH) 2 +set ::env(FP_IO_VLENGTH) 2 + +# use alternative efabless decap cells to solve LI density issue +set ::env(DECAP_CELL) "\ + sky130_fd_sc_hd__decap_3 \ + sky130_fd_sc_hd__decap_4 \ + sky130_fd_sc_hd__decap_6 \ + sky130_fd_sc_hd__decap_8 \ + sky130_ef_sc_hd__decap_12" + +# clock +set ::env(CLOCK_TREE_SYNTH) 1 +# period is in ns, so 20000ns == 50kHz +set ::env(CLOCK_PERIOD) "20000" +set ::env(CLOCK_PORT) {io_in[0]} + +# hold/slack margin +# set ::env(PL_RESIZER_HOLD_SLACK_MARGIN) 0.8 +# set ::env(GLB_RESIZER_HOLD_SLACK_MARGIN) 0.8 + +# don't use power rings or met5 +set ::env(DESIGN_IS_CORE) 0 +set ::env(RT_MAX_LAYER) {met4} + +# connect to first digital rails +set ::env(VDD_NETS) [list {vccd1}] +set ::env(GND_NETS) [list {vssd1}] diff --git a/designs/d39_oonyeado_sevenseg/src/pin_order.cfg b/designs/d39_oonyeado_sevenseg/src/pin_order.cfg new file mode 100644 index 0000000..0b85c63 --- /dev/null +++ b/designs/d39_oonyeado_sevenseg/src/pin_order.cfg @@ -0,0 +1,9 @@ +#N + +#S + +#E + +#W +io_in.* +io_out.* diff --git a/designs/d39_oonyeado_sevenseg/src/wokwi.v b/designs/d39_oonyeado_sevenseg/src/wokwi.v new file mode 100644 index 0000000..5df65ca --- /dev/null +++ b/designs/d39_oonyeado_sevenseg/src/wokwi.v @@ -0,0 +1,488 @@ +/* Automatically generated from https://wokwi.com/projects/350866594173289042 */ + +`default_nettype none + +module user_module_350866594173289042( + input [7:0] io_in, + output [7:0] io_out +); + wire net1 = io_in[4]; + wire net2 = io_in[5]; + wire net3 = io_in[6]; + wire net4 = io_in[7]; + wire net5; + wire net6; + wire net7; + wire net8; + wire net9; + wire net10; + wire net11; + wire net12 = 1'b1; + wire net13; + wire net14; + wire net15; + wire net16; + wire net17; + wire net18; + wire net19; + wire net20; + wire net21; + wire net22; + wire net23; + wire net24; + wire net25; + wire net26; + wire net27; + wire net28; + wire net29; + wire net30; + wire net31; + wire net32; + wire net33; + wire net34; + wire net35; + wire net36; + wire net37; + wire net38; + wire net39; + wire net40; + wire net41; + wire net42; + wire net43; + wire net44; + wire net45; + wire net46; + wire net47; + wire net48; + wire net49; + wire net50; + wire net51; + wire net52; + wire net53; + wire net54; + wire net55; + wire net56; + wire net57; + wire net58; + wire net59; + wire net60; + wire net61; + wire net62; + wire net63; + wire net64; + wire net65; + wire net66; + wire net67; + wire net68; + wire net69; + wire net70; + wire net71; + wire net72; + wire net73; + wire net74; + wire net75; + wire net76; + wire net77; + wire net78; + wire net79; + wire net80; + wire net81; + wire net82; + wire net83; + wire net84 = 1'b0; + + assign io_out[1] = net5; + assign io_out[2] = net6; + assign io_out[3] = net7; + assign io_out[4] = net8; + assign io_out[5] = net9; + assign io_out[6] = net10; + assign io_out[7] = net11; + + and_cell gate1 ( + .a (net13), + .b (net3), + .out (net14) + ); + or_cell gate2 ( + .a (net15), + .b (net16), + .out (net17) + ); + not_cell gate5 ( + .in (net4), + .out (net13) + ); + not_cell gate7 ( + .in (net3), + .out (net18) + ); + not_cell gate8 ( + .in (net2), + .out (net19) + ); + not_cell gate9 ( + .in (net1), + .out (net20) + ); + or_cell gate10 ( + .a (net21), + .b (net22), + .out (net23) + ); + or_cell gate11 ( + .a (net17), + .b (net23), + .out (net8) + ); + or_cell gate12 ( + .a (net24), + .b (net25), + .out (net22) + ); + or_cell gate13 ( + .a (net26), + .b (net27), + .out (net28) + ); + or_cell gate14 ( + .a (net29), + .b (net30), + .out (net31) + ); + or_cell gate15 ( + .a (net28), + .b (net31), + .out (net10) + ); + or_cell gate16 ( + .a (net32), + .b (net33), + .out (net30) + ); + or_cell gate17 ( + .a (net34), + .b (net35), + .out (net36) + ); + or_cell gate18 ( + .a (net37), + .b (net38), + .out (net39) + ); + or_cell gate19 ( + .a (net36), + .b (net39), + .out (net9) + ); + or_cell gate20 ( + .a (net40), + .b (net41), + .out (net42) + ); + or_cell gate21 ( + .a (net43), + .b (net44), + .out (net45) + ); + or_cell gate22 ( + .a (net42), + .b (net45), + .out (net11) + ); + or_cell gate23 ( + .a (net46), + .b (net47), + .out (net44) + ); + or_cell gate24 ( + .a (net48), + .b (net49), + .out (net50) + ); + or_cell gate25 ( + .a (net51), + .b (net52), + .out (net53) + ); + or_cell gate26 ( + .a (net50), + .b (net53), + .out (net6) + ); + or_cell gate27 ( + .a (net54), + .b (net55), + .out (net52) + ); + or_cell gate28 ( + .a (net56), + .b (net57), + .out (net58) + ); + or_cell gate29 ( + .a (net59), + .b (net60), + .out (net61) + ); + or_cell gate30 ( + .a (net58), + .b (net61), + .out (net7) + ); + or_cell gate31 ( + .a (net62), + .b (net63), + .out (net60) + ); + or_cell gate3 ( + .a (net64), + .b (net65), + .out (net66) + ); + or_cell gate6 ( + .a (net67), + .b (net68), + .out (net69) + ); + or_cell gate32 ( + .a (net66), + .b (net69), + .out (net5) + ); + or_cell gate33 ( + .a (net70), + .b (net71), + .out (net68) + ); + or_cell gate34 ( + .a (net72), + .b (net73), + .out (net64) + ); + and_cell gate4 ( + .a (net14), + .b (net19), + .out (net40) + ); + and_cell gate35 ( + .a (net20), + .b (net18), + .out (net74) + ); + and_cell gate36 ( + .a (net74), + .b (net13), + .out (net15) + ); + and_cell gate37 ( + .a (net1), + .b (net2), + .out (net75) + ); + and_cell gate38 ( + .a (net75), + .b (net18), + .out (net16) + ); + and_cell gate39 ( + .a (net3), + .b (net19), + .out (net76) + ); + and_cell gate40 ( + .a (net76), + .b (net1), + .out (net21) + ); + and_cell gate41 ( + .a (net3), + .b (net2), + .out (net77) + ); + and_cell gate42 ( + .a (net77), + .b (net20), + .out (net24) + ); + and_cell gate43 ( + .a (net13), + .b (net3), + .out (net78) + ); + and_cell gate44 ( + .a (net78), + .b (net19), + .out (net26) + ); + and_cell gate45 ( + .a (net4), + .b (net19), + .out (net79) + ); + and_cell gate46 ( + .a (net79), + .b (net1), + .out (net51) + ); + and_cell gate47 ( + .a (net13), + .b (net2), + .out (net80) + ); + and_cell gate48 ( + .a (net80), + .b (net1), + .out (net49) + ); + and_cell gate49 ( + .a (net13), + .b (net3), + .out (net81) + ); + and_cell gate50 ( + .a (net81), + .b (net1), + .out (net73) + ); + and_cell gate51 ( + .a (net13), + .b (net19), + .out (net82) + ); + and_cell gate52 ( + .a (net82), + .b (net20), + .out (net48) + ); + and_cell gate53 ( + .a (net4), + .b (net18), + .out (net83) + ); + and_cell gate54 ( + .a (net83), + .b (net19), + .out (net72) + ); + and_cell gate57 ( + .a (net18), + .b (net20), + .out (net65) + ); + and_cell gate58 ( + .a (net13), + .b (net2), + .out (net67) + ); + and_cell gate59 ( + .a (net4), + .b (net20), + .out (net70) + ); + and_cell gate60 ( + .a (net3), + .b (net2), + .out (net71) + ); + and_cell gate61 ( + .a (net18), + .b (net19), + .out (net54) + ); + and_cell gate62 ( + .a (net18), + .b (net20), + .out (net55) + ); + and_cell gate63 ( + .a (net13), + .b (net19), + .out (net56) + ); + and_cell gate64 ( + .a (net13), + .b (net1), + .out (net57) + ); + and_cell gate65 ( + .a (net19), + .b (net1), + .out (net59) + ); + and_cell gate66 ( + .a (net13), + .b (net3), + .out (net62) + ); + and_cell gate67 ( + .a (net4), + .b (net18), + .out (net63) + ); + and_cell gate69 ( + .a (net4), + .b (net19), + .out (net25) + ); + and_cell gate55 ( + .a (net4), + .b (net2), + .out (net34) + ); + and_cell gate56 ( + .a (net4), + .b (net3), + .out (net35) + ); + and_cell gate68 ( + .a (net2), + .b (net20), + .out (net37) + ); + and_cell gate70 ( + .a (net18), + .b (net20), + .out (net38) + ); + and_cell gate71 ( + .a (net19), + .b (net20), + .out (net27) + ); + and_cell gate72 ( + .a (net3), + .b (net20), + .out (net29) + ); + and_cell gate73 ( + .a (net4), + .b (net18), + .out (net32) + ); + and_cell gate74 ( + .a (net4), + .b (net2), + .out (net33) + ); + and_cell gate75 ( + .a (net4), + .b (net18), + .out (net41) + ); + and_cell gate76 ( + .a (net4), + .b (net1), + .out (net43) + ); + and_cell gate77 ( + .a (net18), + .b (net2), + .out (net46) + ); + and_cell gate78 ( + .a (net2), + .b (net20), + .out (net47) + ); +endmodule diff --git a/designs/d40_jrecta_asyncfifo/LICENSE b/designs/d40_jrecta_asyncfifo/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/designs/d40_jrecta_asyncfifo/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/designs/d40_jrecta_asyncfifo/README.md b/designs/d40_jrecta_asyncfifo/README.md new file mode 100644 index 0000000..66dceb5 --- /dev/null +++ b/designs/d40_jrecta_asyncfifo/README.md @@ -0,0 +1,32 @@ +# Async FIFO + +Jon Recta +98-154 Intro to Open-Source Chip Design, Fall 2022 + +## Description + +A very small asynchonous FIFO. + +After reset, run write_clock and assert write_enable with some data on wdata, then while run_clock is running, assert read_enable. If write_enable is asserted while full is high, the data will be rejected. If read_enable is asserted while empty is high, read_data is invalid. + +### Inputs + +- write_clock +- read_clock +- reset +- write_enable +- read_enable +- wdata[0] +- wdata[1] +- wdata[2] + +### Outputs + +- none +- none +- none +- fifo_full +- fifo_empty +- rdata[0] +- rdata[1] +- rdata[2] diff --git a/designs/d40_jrecta_asyncfifo/info.yaml b/designs/d40_jrecta_asyncfifo/info.yaml new file mode 100644 index 0000000..304d745 --- /dev/null +++ b/designs/d40_jrecta_asyncfifo/info.yaml @@ -0,0 +1,8 @@ +--- +project: + source_files: + - top.sv + - async-fifo.sv + top_module: "jonpaolo02_async_fifo" + + tt02_fmt: true diff --git a/designs/d40_jrecta_asyncfifo/src/async-fifo.sv b/designs/d40_jrecta_asyncfifo/src/async-fifo.sv new file mode 100644 index 0000000..4e01bb8 --- /dev/null +++ b/designs/d40_jrecta_asyncfifo/src/async-fifo.sv @@ -0,0 +1,128 @@ +`default_nettype none + +module async_fifo + #(parameter WIDTH=4, + parameter DEPTH=4) + (input logic rst, + input logic wclk, we, + output logic full, + input logic[WIDTH-1:0] wdata, + input logic rclk, re, + output logic empty, + output logic[WIDTH-1:0] rdata); + + // extra bit for full detection + parameter PTR_WIDTH = $clog2(DEPTH)+1; + + logic [PTR_WIDTH-1:0] wptr, wptr_gray, rptr, rptr_gray; + logic [WIDTH-1:0] data[DEPTH-1:0]; + + // store data + always_ff @(posedge wclk) + if(we & ~full) + data[wptr[PTR_WIDTH-2:0]] <= wdata; + assign rdata = data[rptr[PTR_WIDTH-2:0]]; + + // all logic in write domain + write_half #(PTR_WIDTH) frontend + (.rst, .wclk, .we, + .rptr_gray, + .wptr, .wptr_gray, + .full); + + // all logic in read domain + read_half #(PTR_WIDTH) backend + (.rst, .rclk, .re, + .wptr_gray, + .rptr, .rptr_gray, + .empty); +endmodule: async_fifo + +module read_half + #(parameter PTR_WIDTH) + (input logic rst, rclk, re, + input logic [PTR_WIDTH-1:0] wptr_gray, + output logic [PTR_WIDTH-1:0] rptr, rptr_gray, + output logic empty); + + logic [PTR_WIDTH-1:0] wptr_gray1, wptr_gray2; + + // rptr counter + reg_ar #(PTR_WIDTH) rptr_reg + (.rst, .clk(rclk), .en(re & ~empty), + .d(rptr + (PTR_WIDTH)'(1)), .q(rptr)); + + // sync wptr_gray + reg_ar #(2*PTR_WIDTH) wptr_gray_sync + (.rst, .clk(rclk), .en('1), + .d({wptr_gray, wptr_gray1}), .q({wptr_gray1, wptr_gray2})); + + // generate gray code + bin2gray #(PTR_WIDTH) rptr_b2g + (.binary(rptr), .gray(rptr_gray)); + + // empty is easy to check + assign empty = wptr_gray2 == rptr_gray; +endmodule + +module write_half + #(parameter PTR_WIDTH) + (input logic rst, wclk, we, + input logic [PTR_WIDTH-1:0] rptr_gray, + output logic [PTR_WIDTH-1:0] wptr, wptr_gray, + output logic full); + + logic [PTR_WIDTH-1:0] rptr_gray1, rptr_gray2; + + // wptr counter + reg_ar #(PTR_WIDTH) wptr_reg + (.rst, .clk(wclk), .en(we & ~full), + .d(wptr + (PTR_WIDTH)'(1)), .q(wptr)); + + // sync rptr_gray + reg_ar #(2*PTR_WIDTH) rptr_gray_sync + (.rst, .clk(wclk), .en('1), + .d({rptr_gray, rptr_gray1}), .q({rptr_gray1, rptr_gray2})); + + // generate gray code + bin2gray #(PTR_WIDTH) wptr_b2g + (.binary(wptr), .gray(wptr_gray)); + + // grey code math... + if(PTR_WIDTH > 2) + assign full = rptr_gray2[PTR_WIDTH-1 -: 2] == ~wptr_gray[PTR_WIDTH-1 -: 2] + && rptr_gray2[0 +: (PTR_WIDTH-2)] == wptr_gray[0 +: (PTR_WIDTH-2)]; + else + assign full = rptr_gray2 == ~wptr_gray; +endmodule + +module reg_ar + #(parameter WIDTH) + (input logic clk, rst, en, + input logic[WIDTH-1:0] d, + output logic[WIDTH-1:0] q); + always_ff @(posedge clk, posedge rst) + if(rst) + q <= '0; + else if(en) + q <= d; +endmodule // reg_ar + +module gray2bin + #(parameter WIDTH) + (input logic[WIDTH-1:0] gray, + output logic[WIDTH-1:0] binary); + + generate for(genvar i = 0; i < WIDTH-1; i++) + assign binary[i] = gray[i] ^ binary[i+1]; + endgenerate + assign binary[WIDTH-1] = gray[WIDTH-1]; +endmodule // gray2bin + +module bin2gray + #(parameter WIDTH) + (input logic[WIDTH-1:0] binary, + output logic [WIDTH-1:0] gray); + + assign gray = binary ^ (binary >> 1); +endmodule // bin2gray diff --git a/designs/d40_jrecta_asyncfifo/src/cells.v b/designs/d40_jrecta_asyncfifo/src/cells.v new file mode 100644 index 0000000..772fb21 --- /dev/null +++ b/designs/d40_jrecta_asyncfifo/src/cells.v @@ -0,0 +1,102 @@ +/* +This file provides the mapping from the Wokwi modules to Verilog HDL + +It's only needed for Wokwi designs + +*/ +`define default_netname none + +module buffer_cell ( + input wire in, + output wire out + ); + assign out = in; +endmodule + +module and_cell ( + input wire a, + input wire b, + output wire out + ); + + assign out = a & b; +endmodule + +module or_cell ( + input wire a, + input wire b, + output wire out + ); + + assign out = a | b; +endmodule + +module xor_cell ( + input wire a, + input wire b, + output wire out + ); + + assign out = a ^ b; +endmodule + +module nand_cell ( + input wire a, + input wire b, + output wire out + ); + + assign out = !(a&b); +endmodule + +module not_cell ( + input wire in, + output wire out + ); + + assign out = !in; +endmodule + +module mux_cell ( + input wire a, + input wire b, + input wire sel, + output wire out + ); + + assign out = sel ? b : a; +endmodule + +module dff_cell ( + input wire clk, + input wire d, + output reg q, + output wire notq + ); + + assign notq = !q; + always @(posedge clk) + q <= d; + +endmodule + +module dffsr_cell ( + input wire clk, + input wire d, + input wire s, + input wire r, + output reg q, + output wire notq + ); + + assign notq = !q; + + always @(posedge clk or posedge s or posedge r) begin + if (r) + q <= 0; + else if (s) + q <= 1; + else + q <= d; + end +endmodule diff --git a/designs/d40_jrecta_asyncfifo/src/config.tcl b/designs/d40_jrecta_asyncfifo/src/config.tcl new file mode 100644 index 0000000..5d6d339 --- /dev/null +++ b/designs/d40_jrecta_asyncfifo/src/config.tcl @@ -0,0 +1,62 @@ +# DO NOT EDIT THIS FILE! +# We will rebuild your GDS for the final submission using the information given in the yaml file only +# If you get stuck with this config, please open an issue or get in touch via the discord. + +# User config +set script_dir [file dirname [file normalize [info script]]] + +# read some user config that is written by the setup.py program. +# - the name of the module is defined +# - the list of source files +source $::env(DESIGN_DIR)/user_config.tcl + +# save some time +set ::env(RUN_KLAYOUT_XOR) 0 +set ::env(RUN_KLAYOUT_DRC) 0 + +# don't put clock buffers on the outputs +set ::env(PL_RESIZER_BUFFER_OUTPUT_PORTS) 0 + +# allow use of specific sky130 cells +set ::env(SYNTH_READ_BLACKBOX_LIB) 1 + +# put all the pins on the left +set ::env(FP_PIN_ORDER_CFG) $::env(DESIGN_DIR)/pin_order.cfg + +# reduce wasted space +set ::env(TOP_MARGIN_MULT) 2 +set ::env(BOTTOM_MARGIN_MULT) 2 + +# absolute die size +set ::env(FP_SIZING) absolute +set ::env(DIE_AREA) "0 0 150 170" +set ::env(FP_CORE_UTIL) 55 +set ::env(PL_BASIC_PLACEMENT) {1} + +set ::env(FP_IO_HLENGTH) 2 +set ::env(FP_IO_VLENGTH) 2 + +# use alternative efabless decap cells to solve LI density issue +set ::env(DECAP_CELL) "\ + sky130_fd_sc_hd__decap_3 \ + sky130_fd_sc_hd__decap_4 \ + sky130_fd_sc_hd__decap_6 \ + sky130_fd_sc_hd__decap_8 \ + sky130_ef_sc_hd__decap_12" + +# clock +set ::env(CLOCK_TREE_SYNTH) 1 +set ::env(CLOCK_PERIOD) "100000" +set ::env(CLOCK_PORT) {io_in[0]} + +# hold/slack margin +# set ::env(PL_RESIZER_HOLD_SLACK_MARGIN) 0.8 +# set ::env(GLB_RESIZER_HOLD_SLACK_MARGIN) 0.8 + +# don't use power rings or met5 +set ::env(DESIGN_IS_CORE) 0 +set ::env(RT_MAX_LAYER) {met4} + +# connect to first digital rails +set ::env(VDD_NETS) [list {vccd1}] +set ::env(GND_NETS) [list {vssd1}] diff --git a/designs/d40_jrecta_asyncfifo/src/pin_order.cfg b/designs/d40_jrecta_asyncfifo/src/pin_order.cfg new file mode 100644 index 0000000..0b85c63 --- /dev/null +++ b/designs/d40_jrecta_asyncfifo/src/pin_order.cfg @@ -0,0 +1,9 @@ +#N + +#S + +#E + +#W +io_in.* +io_out.* diff --git a/designs/d40_jrecta_asyncfifo/src/tests.sv b/designs/d40_jrecta_asyncfifo/src/tests.sv new file mode 100644 index 0000000..dca153a --- /dev/null +++ b/designs/d40_jrecta_asyncfifo/src/tests.sv @@ -0,0 +1,102 @@ +`default_nettype none + +module gray2bin_test; + + logic [3:0] gray, binary_out; + gray2bin #(4) DUT (.gray, .binary(binary_out)); + + initial begin + for(int i = 0; i < 16; i++) begin + gray = 4'(i) ^ (4'(i) >> 1); + #1 test_decode: assert(binary_out == 4'(i)) else + $display("bin=%b gray=%b, got=%b", i, gray, binary_out); + end + #10 $finish; + end // initial begin +endmodule // gray2bin_test + +module async_fifo_test; + parameter WIDTH=3; + parameter DEPTH=8; + + logic [WIDTH-1:0] q[$]; + + logic rst; + logic wclk, we; + logic full; + logic[WIDTH-1:0] wdata; + logic rclk, re; + logic empty; + logic[WIDTH-1:0] rdata; + int wval,rval, vals_written, vals_read; + logic rdone, wdone; + + async_fifo #(.WIDTH(WIDTH), .DEPTH(DEPTH)) DUT(.*); + + initial begin + rclk = '0; + forever #7 rclk = ~rclk; + end + + initial begin + wclk = '0; + rst = '0; + #1 rst = '1; + #9 rst = '0; + forever #5 wclk = ~wclk; + end + + parameter VALS=32; + initial begin + wdone = '0; + vals_written = 0; + wval = $urandom(240); + we = '0; + @(posedge wclk); + while(vals_written < VALS) begin + #1; + if(~full) begin + we <= '1; + wval = vals_written % (2**WIDTH);// $urandom() % (2**WIDTH); + wdata <= wval; + q.push_front(wval); + // vals_written++; + end else begin + we <= '0; + end + @(posedge wclk); + if(we) vals_written++; + + end + @(posedge wclk); + we <= '0; + repeat(10) @(posedge wclk); + wdone <= '1; + end + + initial begin + rdone = '0; + vals_read = 0; + rval = -1; + re = '0; + @(posedge full); + repeat(5) @(posedge rclk); + while(vals_read < VALS)begin + @(posedge rclk) #1; + if(~empty) begin + re <= '1; + rval = q.pop_back(); + #1 assert(rdata == rval); + vals_read++; + end + else begin + re <= '0; + end + end + rdone <= '1; + end + + initial begin + wait(rdone && wdone) $finish; + end +endmodule diff --git a/designs/d40_jrecta_asyncfifo/src/top.sv b/designs/d40_jrecta_asyncfifo/src/top.sv new file mode 100644 index 0000000..93de1fc --- /dev/null +++ b/designs/d40_jrecta_asyncfifo/src/top.sv @@ -0,0 +1,17 @@ +module jonpaolo02_async_fifo ( + input [7:0] io_in, + output [7:0] io_out + ); + + + async_fifo #(.WIDTH(3), .DEPTH(8)) top + (.rst(io_in[2]), + + .wclk(io_in[0]), .we(io_in[3]), + .full(io_out[3]), + .wdata(io_in[7:5]), + + .rclk(io_in[1]), .re(io_in[4]), + .empty(io_out[4]), + .rdata(io_out[7:5])); +endmodule diff --git a/designs/d42_qilins_sevenseg/LICENSE b/designs/d42_qilins_sevenseg/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/designs/d42_qilins_sevenseg/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/designs/d42_qilins_sevenseg/README.md b/designs/d42_qilins_sevenseg/README.md new file mode 100644 index 0000000..3df20bd --- /dev/null +++ b/designs/d42_qilins_sevenseg/README.md @@ -0,0 +1,8 @@ +# Hex to Seven-Segment + +Samuel Sun +98-154 Intro to Open-Source Chip Design, Fall 2022 + +## Description + +Convert a binary input and display it on a seven-segment display diff --git a/designs/d42_qilins_sevenseg/info.yaml b/designs/d42_qilins_sevenseg/info.yaml new file mode 100644 index 0000000..8112e7c --- /dev/null +++ b/designs/d42_qilins_sevenseg/info.yaml @@ -0,0 +1,8 @@ +--- +project: + source_files: + - cells.v + - wokwi.v + top_module: "user_module_349519263900369490" + + tt02_fmt: true diff --git a/designs/d42_qilins_sevenseg/src/cells.v b/designs/d42_qilins_sevenseg/src/cells.v new file mode 100644 index 0000000..772fb21 --- /dev/null +++ b/designs/d42_qilins_sevenseg/src/cells.v @@ -0,0 +1,102 @@ +/* +This file provides the mapping from the Wokwi modules to Verilog HDL + +It's only needed for Wokwi designs + +*/ +`define default_netname none + +module buffer_cell ( + input wire in, + output wire out + ); + assign out = in; +endmodule + +module and_cell ( + input wire a, + input wire b, + output wire out + ); + + assign out = a & b; +endmodule + +module or_cell ( + input wire a, + input wire b, + output wire out + ); + + assign out = a | b; +endmodule + +module xor_cell ( + input wire a, + input wire b, + output wire out + ); + + assign out = a ^ b; +endmodule + +module nand_cell ( + input wire a, + input wire b, + output wire out + ); + + assign out = !(a&b); +endmodule + +module not_cell ( + input wire in, + output wire out + ); + + assign out = !in; +endmodule + +module mux_cell ( + input wire a, + input wire b, + input wire sel, + output wire out + ); + + assign out = sel ? b : a; +endmodule + +module dff_cell ( + input wire clk, + input wire d, + output reg q, + output wire notq + ); + + assign notq = !q; + always @(posedge clk) + q <= d; + +endmodule + +module dffsr_cell ( + input wire clk, + input wire d, + input wire s, + input wire r, + output reg q, + output wire notq + ); + + assign notq = !q; + + always @(posedge clk or posedge s or posedge r) begin + if (r) + q <= 0; + else if (s) + q <= 1; + else + q <= d; + end +endmodule diff --git a/designs/d42_qilins_sevenseg/src/config.tcl b/designs/d42_qilins_sevenseg/src/config.tcl new file mode 100644 index 0000000..36321ab --- /dev/null +++ b/designs/d42_qilins_sevenseg/src/config.tcl @@ -0,0 +1,65 @@ +# PLEASE DO NOT EDIT THIS FILE! +# The only thing you can change is the PL_BASIC_PLACEMENT line +# If you get stuck with this config, please open an issue or get in touch via the discord. + +# User config +set script_dir [file dirname [file normalize [info script]]] + +# read some user config that is written by the setup.py program. +# - the name of the module is defined +# - the list of source files +source $::env(DESIGN_DIR)/user_config.tcl + +# save some time +set ::env(RUN_KLAYOUT_XOR) 0 +set ::env(RUN_KLAYOUT_DRC) 0 + +# don't put clock buffers on the outputs +set ::env(PL_RESIZER_BUFFER_OUTPUT_PORTS) 0 + +# allow use of specific sky130 cells +set ::env(SYNTH_READ_BLACKBOX_LIB) 1 + +# put all the pins on the left +set ::env(FP_PIN_ORDER_CFG) $::env(DESIGN_DIR)/pin_order.cfg + +# reduce wasted space +set ::env(TOP_MARGIN_MULT) 2 +set ::env(BOTTOM_MARGIN_MULT) 2 + +# absolute die size +set ::env(FP_SIZING) absolute +set ::env(DIE_AREA) "0 0 150 170" +set ::env(FP_CORE_UTIL) 55 + +# comment this if your design has more than a few hundred cells +set ::env(PL_BASIC_PLACEMENT) {1} + +set ::env(FP_IO_HLENGTH) 2 +set ::env(FP_IO_VLENGTH) 2 + +# use alternative efabless decap cells to solve LI density issue +set ::env(DECAP_CELL) "\ + sky130_fd_sc_hd__decap_3 \ + sky130_fd_sc_hd__decap_4 \ + sky130_fd_sc_hd__decap_6 \ + sky130_fd_sc_hd__decap_8 \ + sky130_ef_sc_hd__decap_12" + +# clock +set ::env(CLOCK_TREE_SYNTH) 1 +# period is in ns, so 20000ns == 50kHz +set ::env(CLOCK_PERIOD) "20000" +set ::env(CLOCK_PORT) {io_in[0]} + +# hold/slack margin +# set ::env(PL_RESIZER_HOLD_SLACK_MARGIN) 0.8 +# set ::env(GLB_RESIZER_HOLD_SLACK_MARGIN) 0.8 + +# don't use power rings or met5 +set ::env(DESIGN_IS_CORE) 0 +set ::env(RT_MAX_LAYER) {met4} + +# connect to first digital rails +set ::env(VDD_NETS) [list {vccd1}] +set ::env(GND_NETS) [list {vssd1}] diff --git a/designs/d42_qilins_sevenseg/src/pin_order.cfg b/designs/d42_qilins_sevenseg/src/pin_order.cfg new file mode 100644 index 0000000..0b85c63 --- /dev/null +++ b/designs/d42_qilins_sevenseg/src/pin_order.cfg @@ -0,0 +1,9 @@ +#N + +#S + +#E + +#W +io_in.* +io_out.* diff --git a/designs/d42_qilins_sevenseg/src/wokwi.v b/designs/d42_qilins_sevenseg/src/wokwi.v new file mode 100644 index 0000000..08bee31 --- /dev/null +++ b/designs/d42_qilins_sevenseg/src/wokwi.v @@ -0,0 +1,501 @@ +/* Automatically generated from https://wokwi.com/projects/349519263900369490 */ + +`default_nettype none + +module user_module_349519263900369490( + input [7:0] io_in, + output [7:0] io_out +); + wire net1 = io_in[0]; + wire net2 = io_in[1]; + wire net3 = io_in[2]; + wire net4 = io_in[3]; + wire net5; + wire net6; + wire net7; + wire net8; + wire net9; + wire net10; + wire net11; + wire net12; + wire net13 = 1'b0; + wire net14 = 1'b1; + wire net15; + wire net16; + wire net17; + wire net18; + wire net19; + wire net20; + wire net21; + wire net22; + wire net23; + wire net24; + wire net25; + wire net26; + wire net27; + wire net28; + wire net29; + wire net30; + wire net31; + wire net32; + wire net33; + wire net34; + wire net35; + wire net36; + wire net37; + wire net38; + wire net39; + wire net40; + wire net41; + wire net42; + wire net43; + wire net44; + wire net45; + wire net46; + wire net47; + wire net48; + wire net49; + wire net50; + wire net51; + wire net52; + wire net53; + wire net54; + wire net55; + wire net56; + wire net57; + wire net58; + wire net59; + wire net60; + wire net61; + wire net62; + wire net63; + wire net64; + wire net65; + wire net66; + wire net67; + wire net68; + wire net69; + wire net70; + wire net71; + wire net72; + wire net73; + wire net74; + wire net75; + wire net76; + wire net77; + wire net78; + wire net79; + wire net80; + wire net81; + wire net82; + wire net83; + wire net84; + wire net85; + wire net86; + + assign io_out[0] = net5; + assign io_out[1] = net6; + assign io_out[2] = net7; + assign io_out[3] = net8; + assign io_out[4] = net9; + assign io_out[5] = net10; + assign io_out[6] = net11; + assign io_out[7] = net12; + + not_cell gate7 ( + .in (net1), + .out (net15) + ); + not_cell gate8 ( + .in (net2), + .out (net16) + ); + not_cell gate9 ( + .in (net3), + .out (net17) + ); + not_cell gate10 ( + .in (net4), + .out (net18) + ); + and_cell gate11 ( + .a (net15), + .b (net2), + .out (net19) + ); + and_cell gate14 ( + .a (net17), + .b (net19), + .out (net20) + ); + and_cell gate12 ( + .a (net17), + .b (net18), + .out (net21) + ); + and_cell gate15 ( + .a (net2), + .b (net18), + .out (net22) + ); + and_cell gate16 ( + .a (net1), + .b (net16), + .out (net23) + ); + and_cell gate17 ( + .a (net1), + .b (net3), + .out (net24) + ); + or_cell gate18 ( + .a (net20), + .b (net21), + .out (net25) + ); + or_cell gate19 ( + .a (net22), + .b (net23), + .out (net26) + ); + or_cell gate20 ( + .a (net25), + .b (net27), + .out (net10) + ); + or_cell gate21 ( + .a (net26), + .b (net24), + .out (net27) + ); + and_cell gate22 ( + .a (net1), + .b (net16), + .out (net28) + ); + and_cell gate23 ( + .a (net17), + .b (net28), + .out (net29) + ); + and_cell gate24 ( + .a (net15), + .b (net2), + .out (net30) + ); + and_cell gate25 ( + .a (net30), + .b (net4), + .out (net31) + ); + and_cell gate26 ( + .a (net1), + .b (net18), + .out (net32) + ); + and_cell gate27 ( + .a (net15), + .b (net3), + .out (net33) + ); + and_cell gate28 ( + .a (net2), + .b (net3), + .out (net34) + ); + and_cell gate29 ( + .a (net16), + .b (net18), + .out (net35) + ); + or_cell gate30 ( + .a (net29), + .b (net31), + .out (net36) + ); + or_cell gate31 ( + .a (net32), + .b (net33), + .out (net37) + ); + or_cell gate32 ( + .a (net34), + .b (net35), + .out (net38) + ); + or_cell gate33 ( + .a (net36), + .b (net37), + .out (net39) + ); + or_cell gate34 ( + .a (net39), + .b (net38), + .out (net5) + ); + and_cell gate13 ( + .a (net15), + .b (net17), + .out (net40) + ); + and_cell gate35 ( + .a (net18), + .b (net40), + .out (net41) + ); + and_cell gate36 ( + .a (net15), + .b (net3), + .out (net42) + ); + and_cell gate37 ( + .a (net4), + .b (net42), + .out (net43) + ); + and_cell gate38 ( + .a (net1), + .b (net17), + .out (net44) + ); + and_cell gate39 ( + .a (net4), + .b (net44), + .out (net45) + ); + and_cell gate40 ( + .a (net16), + .b (net17), + .out (net46) + ); + and_cell gate41 ( + .a (net16), + .b (net18), + .out (net47) + ); + or_cell gate42 ( + .a (net41), + .b (net43), + .out (net48) + ); + or_cell gate43 ( + .a (net45), + .b (net46), + .out (net49) + ); + or_cell gate44 ( + .a (net48), + .b (net49), + .out (net50) + ); + or_cell gate45 ( + .a (net50), + .b (net47), + .out (net6) + ); + and_cell gate46 ( + .a (net15), + .b (net17), + .out (net51) + ); + and_cell gate47 ( + .a (net15), + .b (net4), + .out (net52) + ); + and_cell gate48 ( + .a (net17), + .b (net4), + .out (net53) + ); + and_cell gate49 ( + .a (net15), + .b (net2), + .out (net54) + ); + and_cell gate50 ( + .a (net1), + .b (net16), + .out (net55) + ); + or_cell gate51 ( + .a (net51), + .b (net52), + .out (net56) + ); + or_cell gate52 ( + .a (net53), + .b (net54), + .out (net57) + ); + or_cell gate53 ( + .a (net58), + .b (net55), + .out (net7) + ); + or_cell gate54 ( + .a (net56), + .b (net57), + .out (net58) + ); + and_cell gate55 ( + .a (net15), + .b (net16), + .out (net59) + ); + and_cell gate56 ( + .a (net59), + .b (net18), + .out (net60) + ); + and_cell gate57 ( + .a (net16), + .b (net3), + .out (net61) + ); + and_cell gate58 ( + .a (net61), + .b (net4), + .out (net62) + ); + and_cell gate59 ( + .a (net2), + .b (net17), + .out (net63) + ); + and_cell gate60 ( + .a (net63), + .b (net4), + .out (net64) + ); + and_cell gate61 ( + .a (net2), + .b (net3), + .out (net65) + ); + and_cell gate62 ( + .a (net65), + .b (net18), + .out (net66) + ); + and_cell gate63 ( + .a (net1), + .b (net17), + .out (net67) + ); + or_cell gate64 ( + .a (net60), + .b (net62), + .out (net68) + ); + or_cell gate65 ( + .a (net68), + .b (net69), + .out (net70) + ); + or_cell gate66 ( + .a (net64), + .b (net66), + .out (net69) + ); + or_cell gate68 ( + .a (net70), + .b (net67), + .out (net8) + ); + and_cell gate67 ( + .a (net16), + .b (net18), + .out (net71) + ); + and_cell gate69 ( + .a (net3), + .b (net18), + .out (net72) + ); + and_cell gate70 ( + .a (net1), + .b (net3), + .out (net73) + ); + and_cell gate71 ( + .a (net1), + .b (net2), + .out (net74) + ); + or_cell gate72 ( + .a (net71), + .b (net72), + .out (net75) + ); + or_cell gate73 ( + .a (net73), + .b (net74), + .out (net76) + ); + or_cell gate74 ( + .a (net75), + .b (net76), + .out (net9) + ); + and_cell gate75 ( + .a (net15), + .b (net2), + .out (net77) + ); + and_cell gate76 ( + .a (net77), + .b (net17), + .out (net78) + ); + and_cell gate77 ( + .a (net16), + .b (net3), + .out (net79) + ); + and_cell gate78 ( + .a (net3), + .b (net18), + .out (net80) + ); + and_cell gate79 ( + .a (net1), + .b (net16), + .out (net81) + ); + and_cell gate80 ( + .a (net1), + .b (net4), + .out (net82) + ); + or_cell gate81 ( + .a (net78), + .b (net79), + .out (net83) + ); + or_cell gate82 ( + .a (net80), + .b (net81), + .out (net84) + ); + or_cell gate83 ( + .a (net85), + .b (net82), + .out (net11) + ); + or_cell gate84 ( + .a (net83), + .b (net84), + .out (net85) + ); + and_cell gate85 ( + .a (net1), + .b (net86), + .out (net12) + ); + nand_cell gate87 ( + .a (net17), + .b (net16), + .out (net86) + ); +endmodule diff --git a/designs/import-wokwi.sh b/designs/import-wokwi.sh new file mode 100755 index 0000000..4444ad3 --- /dev/null +++ b/designs/import-wokwi.sh @@ -0,0 +1,10 @@ +# script for importing a TinyTapeout Wokwi repo from TT02 +mkdir $1 && \ + cd $1 && + cp ../../templates/tt02-wokwi-template/LICENSE . && \ + cp ../../templates/tt02-wokwi-template/README.md . && \ + cat ../../templates/tt02-wokwi-template/info.yaml | sed 's/WID/'$2'/g' > info.yaml && \ + cp -r ../../templates/tt02-wokwi-template/src src && \ + curl https://wokwi.com/api/projects/$2/verilog > src/wokwi.v && \ + vim README.md + diff --git a/designs/import.sh b/designs/import.sh new file mode 100755 index 0000000..3575bc9 --- /dev/null +++ b/designs/import.sh @@ -0,0 +1,3 @@ +# script for importing a TinyTapeout-format repo into our standard format +cp -r $2 $1 && cd $1 && cp ../.lastupdated . ; rm -r .github .gitignore ; rm configure.py ; vim README.md && vim info.yaml && ls -la && ls -la src; +grep "Apache License" LICENSE > /dev/null && printf "$(tty -s && tput setaf 76)++ Valid License$(tty -s && tput sgr0)" || printf "$(tty -s && tput setaf 1)Invalid License$(tty -s && tput sgr0)" diff --git a/templates/tt02-wokwi-template/LICENSE b/templates/tt02-wokwi-template/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/templates/tt02-wokwi-template/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/templates/tt02-wokwi-template/README.md b/templates/tt02-wokwi-template/README.md new file mode 100644 index 0000000..d12221d --- /dev/null +++ b/templates/tt02-wokwi-template/README.md @@ -0,0 +1,17 @@ +# title + +Student +98-154 Intro to Open-Source Chip Design, Fall 2022 + +## Description + + +## Testing + + +### Inputs + + + +### Outputs + diff --git a/templates/tt02-wokwi-template/info.yaml b/templates/tt02-wokwi-template/info.yaml new file mode 100644 index 0000000..88c74b0 --- /dev/null +++ b/templates/tt02-wokwi-template/info.yaml @@ -0,0 +1,8 @@ +--- +project: + source_files: + - cells.v + - wokwi.v + top_module: "user_module_WID" + + tt02_fmt: true diff --git a/templates/tt02-wokwi-template/src/cells.v b/templates/tt02-wokwi-template/src/cells.v new file mode 100644 index 0000000..772fb21 --- /dev/null +++ b/templates/tt02-wokwi-template/src/cells.v @@ -0,0 +1,102 @@ +/* +This file provides the mapping from the Wokwi modules to Verilog HDL + +It's only needed for Wokwi designs + +*/ +`define default_netname none + +module buffer_cell ( + input wire in, + output wire out + ); + assign out = in; +endmodule + +module and_cell ( + input wire a, + input wire b, + output wire out + ); + + assign out = a & b; +endmodule + +module or_cell ( + input wire a, + input wire b, + output wire out + ); + + assign out = a | b; +endmodule + +module xor_cell ( + input wire a, + input wire b, + output wire out + ); + + assign out = a ^ b; +endmodule + +module nand_cell ( + input wire a, + input wire b, + output wire out + ); + + assign out = !(a&b); +endmodule + +module not_cell ( + input wire in, + output wire out + ); + + assign out = !in; +endmodule + +module mux_cell ( + input wire a, + input wire b, + input wire sel, + output wire out + ); + + assign out = sel ? b : a; +endmodule + +module dff_cell ( + input wire clk, + input wire d, + output reg q, + output wire notq + ); + + assign notq = !q; + always @(posedge clk) + q <= d; + +endmodule + +module dffsr_cell ( + input wire clk, + input wire d, + input wire s, + input wire r, + output reg q, + output wire notq + ); + + assign notq = !q; + + always @(posedge clk or posedge s or posedge r) begin + if (r) + q <= 0; + else if (s) + q <= 1; + else + q <= d; + end +endmodule diff --git a/templates/tt02-wokwi-template/src/config.tcl b/templates/tt02-wokwi-template/src/config.tcl new file mode 100644 index 0000000..36321ab --- /dev/null +++ b/templates/tt02-wokwi-template/src/config.tcl @@ -0,0 +1,65 @@ +# PLEASE DO NOT EDIT THIS FILE! +# The only thing you can change is the PL_BASIC_PLACEMENT line +# If you get stuck with this config, please open an issue or get in touch via the discord. + +# User config +set script_dir [file dirname [file normalize [info script]]] + +# read some user config that is written by the setup.py program. +# - the name of the module is defined +# - the list of source files +source $::env(DESIGN_DIR)/user_config.tcl + +# save some time +set ::env(RUN_KLAYOUT_XOR) 0 +set ::env(RUN_KLAYOUT_DRC) 0 + +# don't put clock buffers on the outputs +set ::env(PL_RESIZER_BUFFER_OUTPUT_PORTS) 0 + +# allow use of specific sky130 cells +set ::env(SYNTH_READ_BLACKBOX_LIB) 1 + +# put all the pins on the left +set ::env(FP_PIN_ORDER_CFG) $::env(DESIGN_DIR)/pin_order.cfg + +# reduce wasted space +set ::env(TOP_MARGIN_MULT) 2 +set ::env(BOTTOM_MARGIN_MULT) 2 + +# absolute die size +set ::env(FP_SIZING) absolute +set ::env(DIE_AREA) "0 0 150 170" +set ::env(FP_CORE_UTIL) 55 + +# comment this if your design has more than a few hundred cells +set ::env(PL_BASIC_PLACEMENT) {1} + +set ::env(FP_IO_HLENGTH) 2 +set ::env(FP_IO_VLENGTH) 2 + +# use alternative efabless decap cells to solve LI density issue +set ::env(DECAP_CELL) "\ + sky130_fd_sc_hd__decap_3 \ + sky130_fd_sc_hd__decap_4 \ + sky130_fd_sc_hd__decap_6 \ + sky130_fd_sc_hd__decap_8 \ + sky130_ef_sc_hd__decap_12" + +# clock +set ::env(CLOCK_TREE_SYNTH) 1 +# period is in ns, so 20000ns == 50kHz +set ::env(CLOCK_PERIOD) "20000" +set ::env(CLOCK_PORT) {io_in[0]} + +# hold/slack margin +# set ::env(PL_RESIZER_HOLD_SLACK_MARGIN) 0.8 +# set ::env(GLB_RESIZER_HOLD_SLACK_MARGIN) 0.8 + +# don't use power rings or met5 +set ::env(DESIGN_IS_CORE) 0 +set ::env(RT_MAX_LAYER) {met4} + +# connect to first digital rails +set ::env(VDD_NETS) [list {vccd1}] +set ::env(GND_NETS) [list {vssd1}] diff --git a/templates/tt02-wokwi-template/src/pin_order.cfg b/templates/tt02-wokwi-template/src/pin_order.cfg new file mode 100644 index 0000000..0b85c63 --- /dev/null +++ b/templates/tt02-wokwi-template/src/pin_order.cfg @@ -0,0 +1,9 @@ +#N + +#S + +#E + +#W +io_in.* +io_out.*