├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── include └── verilog_math.vh ├── sim ├── .gitignore ├── sqrt_generic.do ├── t_button_debounce.v ├── t_pipeline_registers_set.v ├── t_sqrt_generic.v └── t_sqrt_pipelined.v └── src ├── button_debounce.v ├── cordic_cir.v ├── cordic_hyp.v ├── div_pipelined.v ├── pipeline_registers.v ├── pipeline_registers_set.v ├── ram_infer.v ├── reset.v ├── sign_extender.v ├── sqrt_generic.v ├── sqrt_pipelined.v ├── uart_rx.v └── uart_tx.v /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *# -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "util/hdl-tools"] 2 | path = util/hdl-tools 3 | url = https://github.com/ibm/hdl-tools 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | Repository for Verilog building blocks with a high chance of reuse 4 | across different hardware projects (e.g. debouncers, display drivers). 5 | 6 | Most of these modules are well tested and shouldn't have issues. 7 | However, I'm generally allowing myself to upload things which *may* 8 | have issues. 9 | 10 | ## Modules 11 | 12 | * `button_debounce.v` -- Timing-based button debouncing circuit. 13 | 14 | * `pipeline_registers.v` -- A parameterized number of pipeline 15 | registers of some depth and width. This is primarily useful as a 16 | building block for _other_ modules. 17 | 18 | * `pipeline_registers_set.v` -- Pipeline registers (as above), but 19 | with the ability to _set_ the value of the registers. 20 | 21 | * `ram_infer.v` -- Xilinx standard module that will infer RAM during 22 | FPGA synthesis. 23 | 24 | * `reset.v` -- Implements a "good" reset with asynchronous assertion 25 | and synchronous de-assertion. 26 | 27 | * `sign_extender.v` -- Explicit sign extender (this should be 28 | unnecessary in Verilog...) 29 | 30 | * `sqrt_pipelined.v` -- A pipelined implementation of a fixed point 31 | square root. **Deprecated due to complexity and incorrect rounding**. 32 | 33 | * `sqrt_generic.v` -- A refactor of `sqrt_pipelined.v` into a cleaner 34 | syntax. This uses implicit truncation rounding and will show a 35 | resulting bias towards negative infinity. 36 | 37 | * `uart_rx.v` -- UART receiver. 38 | 39 | * `uart_tx.v` -- UART transmitter. 40 | 41 | * `div_pipelined.v` -- Pipelined division module (**largely untested**) 42 | 43 | ## Submodules 44 | 45 | In an attempt at modularity, I'm now including a submodules directory 46 | which is intended to contain other repositories (of mine most likely, 47 | but not restricted as such) that are useful. These can be pulled in 48 | with: 49 | 50 | ``` 51 | git submodule init 52 | git submodule update 53 | ``` 54 | 55 | And recursively updated with: 56 | 57 | ``` 58 | git submodule foreach git pull origin master 59 | ``` 60 | 61 | * [hdl-tools](https://github.com/ibm/hdl-tools) -- 62 | Basically, a dumping ground of scripts I've written that make 63 | working with HDLs easier. For example, `addWavesRecursive.tcl` will 64 | populate a GTKWave configuration with the module hierarchy found in 65 | a VCD file. 66 | -------------------------------------------------------------------------------- /include/verilog_math.vh: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Schuyler Eldridge 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Helper math functions to make my Verilog coding life easier. This 16 | // must be included INSIDE in the module/endmodule region, not 17 | // before. This has something to do with global function defintions in 18 | // the standard. 19 | 20 | // A Xilinx implementation of the base 2 logarithm. This is very 21 | // useful when assigning port widths based on parameters. 22 | function integer lg; 23 | input integer value; 24 | reg [31:0] shifted; 25 | integer res; 26 | begin 27 | if (value < 2) 28 | lg = value; 29 | else 30 | begin 31 | shifted = value-1; 32 | for (res=0; shifted>0; res=res+1) 33 | shifted = shifted>>1; 34 | lg = res; 35 | end 36 | end 37 | endfunction 38 | 39 | // Function to convert a fixed point number to a real 40 | function real fixed_to_real; 41 | input x, binary_point; 42 | real fixed_to_real; 43 | fixed_to_real = $itor(f)/2**binary_point; 44 | endfunction 45 | 46 | // Macro to pack a 2D array into a 1D vector based on some number of 47 | // items each with a specified width. 48 | // u_src: unpacked source 49 | // p_dst: packed destination (obviously must be a wire) 50 | // width: the width of one unpacked item 51 | // num_items: the number of items to be packed 52 | `define PACK(u_src, p_dest, width, num_items) \ 53 | generate\ 54 | for (genvar __pack_i = 0; __pack_i < (num_items); __pack_i = __pack_i + 1) begin\ 55 | assign p_dest[(width)*(__pack_i+1)-1:(width)*__pack_i] = u_src[__pack_i]; end\ 56 | endgenerate 57 | 58 | // Macro to unpack a 1D vector into a 2D array based on some number of 59 | // items wach with a specified width. 60 | // p_src: packed source 61 | // u_dst: unpacked destination (a wire) 62 | // width: the width of one unpacked item 63 | // num_items: the number of items to be unpacked 64 | `define UNPACK(p_src, u_dest, width, num_items) \ 65 | generate\ 66 | for (genvar __unpack_i = 0; __unpack_i < (num_items); __unpack_i = __unpack_i + 1) begin\ 67 | assign u_dest[__unpack_i] = p_src[(width)*(__unpack_i+1)-1:(width)*__unpack_i]; end\ 68 | endgenerate 69 | 70 | // Macro to generate a random variable of some width using the $random 71 | // function. This is obviously only suitable for testbenches... 72 | // f: register you want to assign a random value to every clock cycle 73 | // width: width of f 74 | // period: how often to change the random variable 75 | genvar __random_width_i; 76 | `define RANDOM_WIDTH(f, width, period) \ 77 | generate\ 78 | for (__random_width_i = 0; __random_width_i < width>>5; __random_width_i = __random_width_i + 1)\ 79 | always #period f[32*(__random_width_i+1)-1:32*__random_width_i] = $random;\ 80 | always #period f[width-1:32*(width>>5)] = $random;\ 81 | endgenerate 82 | 83 | // Macro to generate a random varible of some width that changes with 84 | // some delay after a clock using the $random function. This is 85 | // intended to be used to create variable input data that does not 86 | // violate setup/hold times (i.e. you want data that changes HOLD_TIME 87 | // after clock rising edge). 88 | // f: output 89 | // width: width of f 90 | // clk: clock 91 | // delay: time after clk posedge when f changes 92 | genvar __random_width_clk_i; 93 | `define RANDOM_WIDTH_OFFSET(f, width, clk, delay) \ 94 | generate\ 95 | for (__random_width_clk_i = 0; __random_width_clk_i < width >> 5; __random_width_clk_i = __random_width_clk_i + 1)\ 96 | always @ (posedge clk)\ 97 | #delay f[32*(__random_width_clk_i+1)-1:32*__random_width_clk_i] = $random;\ 98 | always @ (posedge clk)\ 99 | #delay f[width-1:32*(width>>5)] = $random;\ 100 | endgenerate 101 | -------------------------------------------------------------------------------- /sim/.gitignore: -------------------------------------------------------------------------------- 1 | transcript 2 | vsim.wlf 3 | work -------------------------------------------------------------------------------- /sim/sqrt_generic.do: -------------------------------------------------------------------------------- 1 | vlib work 2 | vlog -vlog01compat +incdir+../src+../include t_sqrt_generic.v 3 | vsim -voptargs=+acc work.t_sqrt_generic 4 | run -all 5 | -------------------------------------------------------------------------------- /sim/t_button_debounce.v: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Schuyler Eldridge 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | `timescale 1ns / 1ps 16 | module t_button_debounce(); 17 | 18 | parameter 19 | CLK_FREQUENCY = 10_000_000, 20 | DEBOUNCE_HZ = 2; 21 | 22 | reg clk, reset_n, button; 23 | wire debounce; 24 | 25 | button_debounce 26 | #( 27 | .CLK_FREQUENCY(CLK_FREQUENCY), 28 | .DEBOUNCE_HZ(DEBOUNCE_HZ) 29 | ) 30 | button_debounce 31 | ( 32 | .clk(clk), 33 | .reset_n(reset_n), 34 | .button(button), 35 | .debounce(debounce) 36 | ); 37 | 38 | initial begin 39 | clk = 1'bx; reset_n = 1'bx; button = 1'bx; 40 | #10 reset_n = 1; 41 | #10 reset_n = 0; clk = 0; 42 | #10 reset_n = 1; 43 | #10 button = 0; 44 | end 45 | 46 | always 47 | #5 clk = ~clk; 48 | 49 | always begin 50 | #100 button = ~button; 51 | #0.1 button = ~button; 52 | #0.1 button = ~button; 53 | #0.1 button = ~button; 54 | #0.1 button = ~button; 55 | #0.1 button = ~button; 56 | #0.1 button = ~button; 57 | #0.1 button = ~button; 58 | #0.1 button = ~button; 59 | end 60 | 61 | endmodule 62 | -------------------------------------------------------------------------------- /sim/t_pipeline_registers_set.v: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Schuyler Eldridge 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | `timescale 1ns/1ps 16 | `include "pipeline_registers_set.v" 17 | module t_pipeline_registers_set(); 18 | `define PERIOD_TARGET 3 19 | `define SLACK 0 20 | `define PERIOD (`PERIOD_TARGET-(`SLACK)) 21 | `define HALF_PERIOD (`PERIOD/2) 22 | `define CQ_DELAY 0.100 23 | `include "verilog_math.vh" 24 | 25 | localparam 26 | BIT_WIDTH = 8, 27 | NUMBER_OF_STAGES = 4; 28 | 29 | reg clk, reset_n, set; 30 | reg [BIT_WIDTH-1:0] pipe_in; 31 | reg [BIT_WIDTH-1:0] set_data_unpacked [NUMBER_OF_STAGES-1:0]; 32 | wire [BIT_WIDTH*NUMBER_OF_STAGES-1:0] set_data; 33 | wire [BIT_WIDTH-1:0] pipe_out; 34 | 35 | `PACK(set_data_unpacked, set_data, BIT_WIDTH, NUMBER_OF_STAGES) 36 | 37 | pipeline_registers_set 38 | #( 39 | .BIT_WIDTH(BIT_WIDTH), 40 | .NUMBER_OF_STAGES(NUMBER_OF_STAGES) 41 | ) 42 | u_pipeline_registers_set 43 | ( 44 | .clk(clk), 45 | .reset_n(reset_n), 46 | .set(set), 47 | .set_data(set_data), 48 | .pipe_in(pipe_out), 49 | .pipe_out(pipe_out) 50 | ); 51 | 52 | always 53 | #`HALF_PERIOD clk = ~clk; 54 | 55 | initial begin 56 | $display("---------------------------------------- starting simulation"); 57 | $display("Period is %0.3fns (%0.0fMHz)", `PERIOD, 1/(`PERIOD)*10**3); 58 | set_data_unpacked[0] = 8'h01; 59 | set_data_unpacked[1] = 8'h23; 60 | set_data_unpacked[2] = 8'h45; 61 | set_data_unpacked[3] = 8'h67; 62 | #5 clk = 0; reset_n = 0; 63 | #10 reset_n = 1; 64 | #10 set = 1; 65 | #10 set = 0; 66 | end 67 | 68 | 69 | 70 | endmodule 71 | -------------------------------------------------------------------------------- /sim/t_sqrt_generic.v: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Schuyler Eldridge 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | `timescale 1ns/1ps 16 | `include "sqrt_generic.v" 17 | module t_sqrt_generic(); 18 | localparam 19 | WIDTH_INPUT = 16, 20 | WIDTH_OUTPUT = WIDTH_INPUT / 2 + WIDTH_INPUT % 2; 21 | 22 | reg clk, rst_n, valid_in; 23 | wire valid_out; 24 | reg [WIDTH_INPUT-1:0] radicand; 25 | wire [WIDTH_INPUT-1:0] radicand_d; 26 | wire [WIDTH_OUTPUT-1:0] root; 27 | 28 | sqrt_generic 29 | #(.WIDTH_INPUT(WIDTH_INPUT), 30 | .WIDTH_OUTPUT(WIDTH_OUTPUT)) 31 | u_sqrt_generic 32 | (.clk(clk), 33 | .rst_n(rst_n), 34 | .valid_in(valid_in), 35 | .radicand(radicand), 36 | .valid_out(valid_out), 37 | .root(root)); 38 | 39 | pipeline_registers 40 | #(.BIT_WIDTH(WIDTH_INPUT), 41 | .NUMBER_OF_STAGES(WIDTH_OUTPUT)) 42 | u_pipe_radicand 43 | (.clk(clk), 44 | .reset_n(rst_n), 45 | .pipe_in(radicand), 46 | .pipe_out(radicand_d)); 47 | 48 | 49 | always 50 | #1 clk = ~clk; 51 | 52 | initial begin 53 | clk = 0; rst_n = 0; 54 | #5 rst_n = 1; 55 | end 56 | 57 | always @(posedge clk) begin 58 | radicand <= radicand + 1; 59 | valid_in <= 1; 60 | if (valid_out) begin 61 | if ($itor(root) - $floor($itor(radicand_d)) > 0) 62 | $error("Bad square root value:\n sqrt(%0d) = %0d (correct: %0.0f)", 63 | radicand_d, root, $floor($itor(radicand_d))); 64 | // $display("%8d %8d", root, radicand_d); 65 | end 66 | 67 | if (radicand_d >= (1 << WIDTH_INPUT) - 1) begin 68 | $stop; 69 | end 70 | 71 | // Reset case 72 | if (!rst_n) begin 73 | radicand <= '0; 74 | valid_in <= 0; 75 | end 76 | end 77 | 78 | endmodule 79 | -------------------------------------------------------------------------------- /sim/t_sqrt_pipelined.v: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Schuyler Eldridge 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | `timescale 1ns / 1ps 16 | module t_sqrt_pipelined(); 17 | 18 | parameter 19 | INPUT_BITS = 4; 20 | localparam 21 | OUTPUT_BITS = INPUT_BITS / 2 + INPUT_BITS % 2; 22 | 23 | reg [INPUT_BITS-1:0] radicand; 24 | reg clk, start, reset_n; 25 | 26 | wire [OUTPUT_BITS-1:0] root; 27 | wire data_valid; 28 | // wire [7:0] root_good; 29 | 30 | sqrt_pipelined 31 | #( 32 | .INPUT_BITS(INPUT_BITS) 33 | ) 34 | sqrt_pipelined 35 | ( 36 | .clk(clk), 37 | .reset_n(reset_n), 38 | .start(start), 39 | .radicand(radicand), 40 | .data_valid(data_valid), 41 | .root(root) 42 | ); 43 | 44 | initial begin 45 | radicand = 16'bx; clk = 1'bx; start = 1'bx; reset_n = 1'bx;; 46 | #10 reset_n = 0; clk = 0; 47 | #50 reset_n = 1; radicand = 0; 48 | // #40 radicand = 81; start = 1; 49 | // #10 radicand = 16'bx; start = 0; 50 | #10000 $finish; 51 | end 52 | 53 | always 54 | #5 clk = ~clk; 55 | 56 | always begin 57 | #10 radicand = radicand + 1; start = 1; 58 | #10 start = 0; 59 | end 60 | 61 | 62 | // always begin 63 | // #80 start = 1; 64 | // #10 start = 0; 65 | // end 66 | 67 | endmodule 68 | -------------------------------------------------------------------------------- /src/button_debounce.v: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Schuyler Eldridge 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | `timescale 1ns / 1ps 16 | module button_debounce 17 | #( 18 | parameter 19 | CLK_FREQUENCY = 10_000_000, 20 | DEBOUNCE_HZ = 2 21 | // These parameters are specified such that you can choose any power 22 | // of 2 frequency for a debouncer between 1 Hz and 23 | // CLK_FREQUENCY. Note, that this will throw errors if you choose a 24 | // non power of 2 frequency (i.e. count_value evaluates to some 25 | // number / 3 which isn't interpreted as a logical right shift). I'm 26 | // assuming this will not work for DEBOUNCE_HZ values less than 1, 27 | // however, I'm uncertain of the value of a debouncer for fractional 28 | // hertz button presses. 29 | ) 30 | ( 31 | input clk, // clock 32 | input reset_n, // asynchronous reset 33 | input button, // bouncy button 34 | output reg debounce // debounced 1-cycle signal 35 | ); 36 | 37 | localparam 38 | COUNT_VALUE = CLK_FREQUENCY / DEBOUNCE_HZ, 39 | WAIT = 0, 40 | FIRE = 1, 41 | COUNT = 2; 42 | 43 | reg [1:0] state, next_state; 44 | reg [25:0] count; 45 | 46 | always @ (posedge clk or negedge reset_n) 47 | state <= (!reset_n) ? WAIT : next_state; 48 | 49 | always @ (posedge clk or negedge reset_n) begin 50 | if (!reset_n) begin 51 | debounce <= 0; 52 | count <= 0; 53 | end 54 | else begin 55 | debounce <= 0; 56 | count <= 0; 57 | case (state) 58 | WAIT: begin 59 | end 60 | FIRE: begin 61 | debounce <= 1; 62 | end 63 | COUNT: begin 64 | count <= count + 1; 65 | end 66 | endcase 67 | end 68 | end 69 | 70 | always @ * begin 71 | case (state) 72 | WAIT: next_state = (button) ? FIRE : state; 73 | FIRE: next_state = COUNT; 74 | COUNT: next_state = (count > COUNT_VALUE - 1) ? WAIT : state; 75 | default: next_state = WAIT; 76 | endcase 77 | end 78 | 79 | endmodule 80 | -------------------------------------------------------------------------------- /src/cordic_cir.v: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Schuyler Eldridge 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Description: 16 | // Pipelined implementation of the CORDIC vector rotation algorithm in circular 17 | // mode. The input is selected through an input "func" select line. Currently 18 | // implemented functions are: 19 | // func select | function 20 | // 0 | sine 21 | // 1 | cosine 22 | // Format is two's complement fixed point with 11 bits before the 23 | // binary point and 12 bits after e.g.: 24 | // [ sign ][ 11 bits ].[ 12 bits ] 25 | 26 | `timescale 1ns/1ps 27 | `include "pipeline_registers.v" 28 | module cordic_cir 29 | #( 30 | parameter 31 | W = 12 // input/output width 32 | ) 33 | ( 34 | input clk, rst_n, start, 35 | input func, // function to perform (see above) 36 | input signed [W*2-1:0] a, b, // function inputs 37 | output valid, // output data valid 38 | output reg [W-1:0] f // function output 39 | ); 40 | 41 | localparam 42 | COS = 1'd0, 43 | SIN = 1'd1; 44 | localparam 45 | ROT = 1'd0, 46 | VEC = 1'd1; 47 | localparam 48 | INV_GAIN_32 = 32'h4DBA76D4, // 0.60725293500888133000 49 | PI_DIV_TWO = 32'sh6487ED51, // 1.57079632679489660000 50 | TWO_DIV_PI = 32'sh28BE60DC; // 0.63661977236758138000 51 | 52 | reg func_pp, inv_pp; 53 | reg [31:0] atan_table [31:0]; 54 | reg [W-1:0] sigma, mode; 55 | reg [W-1:0] x_neg [W:0]; 56 | reg [W-1:0] y_neg [W:0]; 57 | reg signed [W-1:0] x [W:0]; 58 | reg signed [W-1:0] y [W:0]; 59 | reg signed [W-1:0] z [W:0]; 60 | reg signed [W-1:0] x_round [W:0]; 61 | reg signed [W-1:0] y_round [W:0]; 62 | 63 | wire func_out, inv_out; 64 | wire signed [W*2-1:0] inv_gain, pi_div_two, two_div_pi; 65 | wire signed [W*4-1:0] q; 66 | wire [W*4-1:0] d; 67 | 68 | initial begin // this is overkill, how to improve? 69 | atan_table[0] = 32'hC90FDAA2; // 0.78539816339744828000 70 | atan_table[1] = 32'h76B19C16; // 0.46364760900080609000 71 | atan_table[2] = 32'h3EB6EBF2; // 0.24497866312686414000 72 | atan_table[3] = 32'h1FD5BA9B; // 0.12435499454676144000 73 | atan_table[4] = 32'h0FFAADDC; // 0.06241880999595735000 74 | atan_table[5] = 32'h07FF556F; // 0.03123983343026827700 75 | atan_table[6] = 32'h03FFEAAB; // 0.01562372862047683100 76 | atan_table[7] = 32'h01FFFD55; // 0.00781234106010111110 77 | atan_table[8] = 32'h00FFFFAB; // 0.00390623013196697180 78 | atan_table[9] = 32'h007FFFF5; // 0.00195312251647881880 79 | atan_table[10] = 32'h003FFFFF; // 0.00097656218955931946 80 | atan_table[11] = 32'h00200000; // 0.00048828121119489829 81 | atan_table[12] = 32'h00100000; // 0.00024414062014936177 82 | atan_table[13] = 32'h00080000; // 0.00012207031189367021 83 | atan_table[14] = 32'h00040000; // 0.00006103515617420877 84 | atan_table[15] = 32'h00020000; // 0.00003051757811552610 85 | atan_table[16] = 32'h00010000; // 0.00001525878906131576 86 | atan_table[17] = 32'h00008000; // 0.00000762939453110197 87 | atan_table[18] = 32'h00004000; // 0.00000381469726560650 88 | atan_table[19] = 32'h00002000; // 0.00000190734863281019 89 | atan_table[20] = 32'h00001000; // 0.00000095367431640596 90 | atan_table[21] = 32'h00000800; // 0.00000047683715820309 91 | atan_table[22] = 32'h00000400; // 0.00000023841857910156 92 | atan_table[23] = 32'h00000200; // 0.00000011920928955078 93 | atan_table[24] = 32'h00000100; // 0.00000005960464477539 94 | atan_table[25] = 32'h00000080; // 0.00000002980232238770 95 | atan_table[26] = 32'h00000040; // 0.00000001490116119385 96 | atan_table[27] = 32'h00000020; // 0.00000000745058059692 97 | atan_table[28] = 32'h00000010; // 0.00000000372529029846 98 | atan_table[29] = 32'h00000008; // 0.00000000186264514923 99 | atan_table[30] = 32'h00000004; // 0.00000000093132257462 100 | atan_table[31] = 32'h00000002; // 0.00000000046566128731 101 | end 102 | 103 | assign inv_gain = (INV_GAIN_32 >>> (32-W+1)) + INV_GAIN_32[32-W]; 104 | assign pi_div_two = (PI_DIV_TWO >>> (32-W*2)) + PI_DIV_TWO[32-W*2+1]; 105 | assign two_div_pi = (TWO_DIV_PI >>> (32-W*2)) + TWO_DIV_PI[32-W*2+1]; 106 | assign q = a * two_div_pi; 107 | assign d = (q[33:10]+q[9]) * pi_div_two; 108 | 109 | always @ * begin 110 | case (func) 111 | COS: begin 112 | case (q[35:34]) 113 | 2'd0: begin func_pp = COS; inv_pp = 0; end 114 | 2'd1: begin func_pp = SIN; inv_pp = 1; end 115 | 2'd2: begin func_pp = COS; inv_pp = 1; end 116 | 2'd3: begin func_pp = SIN; inv_pp = 0; end 117 | endcase 118 | end 119 | SIN: begin 120 | case (q[35:34]) 121 | 2'd0: begin func_pp = SIN; inv_pp = 0; end 122 | 2'd1: begin func_pp = COS; inv_pp = 0; end 123 | 2'd2: begin func_pp = SIN; inv_pp = 1; end 124 | 2'd3: begin func_pp = COS; inv_pp = 1; end 125 | endcase 126 | end 127 | endcase 128 | end 129 | 130 | always @ (posedge clk or negedge rst_n) begin//function pre-processing 131 | if (!rst_n) begin 132 | x[0] <= 0; 133 | y[0] <= 0; 134 | z[0] <= 0; 135 | mode[0] <= 0; 136 | end 137 | else begin 138 | case (func_pp) 139 | COS: begin 140 | x[0] <= inv_gain; 141 | y[0] <= 0; 142 | z[0] <= {1'b0,d[W*4-2:W*4-2-10]}; 143 | mode[0] <= ROT; 144 | end 145 | SIN: begin 146 | x[0] <= inv_gain; 147 | y[0] <= 0; 148 | z[0] <= {1'b0,d[W*4-2:W*4-2-10]}; 149 | mode[0] <= ROT; 150 | end 151 | default: begin 152 | x[0] <= 32'bx; 153 | y[0] <= 32'bx; 154 | z[0] <= 32'bx; 155 | mode[0] <= 1'bx; 156 | end 157 | endcase 158 | end 159 | end 160 | 161 | generate 162 | genvar i; 163 | for (i = 0; i < W; i = i + 1) begin : gen_stages 164 | always @ * begin 165 | x_neg[i] = ~x[i] + 1; 166 | y_neg[i] = ~y[i] + 1; 167 | if (i==0) begin 168 | x_round[i] = x[i]; 169 | y_round[i] = y[i]; 170 | end 171 | else begin 172 | x_round[i] = (x[i][W-1]) ? ~(x_neg[i] + (x_neg[i][i-1] << i)+1) + 1 : x[i] + (x[i][i-1] << i); 173 | y_round[i] = (y[i][W-1]) ? ~(y_neg[i] + (y_neg[i][i-1] << i)+1) + 1 : y[i] + (y[i][i-1] << i); 174 | end 175 | end 176 | always @ * begin 177 | case (mode[0]) 178 | ROT: sigma[i] = ~z[i][W-1];//z>=0 179 | VEC: sigma[i] = y[i][W-1];//y<0 180 | default: sigma[i] = 1'd0; 181 | endcase 182 | end 183 | always @ (posedge clk or negedge rst_n) begin 184 | if (!rst_n) begin 185 | x[i+1] <= 0; 186 | y[i+1] <= 0; 187 | z[i+1] <= 0; 188 | end 189 | else begin 190 | x[i+1] <= (sigma[i]) ? x[i] - (y_round[i] >>> i) : x[i] + (y_round[i] >>> i); 191 | y[i+1] <= (sigma[i]) ? y[i] + (x_round[i] >>> i) : y[i] - (x_round[i] >>> i); 192 | z[i+1] <= (sigma[i]) ? z[i] - {2'b0, (atan_table[i][31:31-W+3]+atan_table[i][31-W+3-1])} : 193 | z[i] + {2'b0, atan_table[i][31:31-W+3]+atan_table[i][31-W+3-1]}; 194 | end 195 | end 196 | end 197 | endgenerate 198 | 199 | always @ (posedge clk or negedge rst_n) begin//function post-processing 200 | if (!rst_n) 201 | f <= 0; 202 | else begin 203 | case (func_out) 204 | COS: f <= (inv_out) ? ~x[W] + 1 : x[W]; 205 | SIN: f <= (inv_out) ? ~y[W] + 1 : y[W]; 206 | endcase 207 | end 208 | end 209 | 210 | pipeline_registers 211 | #( 212 | .BIT_WIDTH(3), 213 | .NUMBER_OF_STAGES(W+1) 214 | ) 215 | pipe_valid 216 | ( 217 | .clk(clk), 218 | .rst_n(rst_n), 219 | .pipe_in({func_pp,start,inv_pp}), 220 | .pipe_out({func_out,valid,inv_out}) 221 | ); 222 | 223 | endmodule 224 | -------------------------------------------------------------------------------- /src/cordic_hyp.v: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Schuyler Eldridge 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Pipelined implementation of the CORDIC vector rotation algorithm in 16 | // hyperbolic mode. 17 | // 18 | // functions (governed by input func): 19 | // 1'd0: exp 20 | // 1'd1: ln 21 | // 22 | // The formats for inputs and outputs are as follows: 23 | // -------------------------------------------- 24 | // | function | input | output | 25 | // -------------------------------------------- 26 | // | exp | s0.9876543210 | s10.876543210 | 27 | // | ln | s3210.6543210 | [s][.876543210 | 28 | // -------------------------------------------- 29 | // >>>>> actually: [sign][11 bits].[12 bits] 30 | 31 | `include "pipeline_registers.v" 32 | `include "sign_extender.v" 33 | module cordic_hyp 34 | #( 35 | parameter 36 | W = 12 // input/output width/# stages 37 | ) 38 | ( 39 | input clk, rst_n, start, 40 | input func, // function to perform (see above) 41 | input signed [W*2-1:0] a, b, // function inputs 42 | output valid, // output data valid 43 | output reg [W*2-1:0] f // function output 44 | ); 45 | 46 | localparam 47 | EXP = 1'd0, 48 | LN = 1'd1; 49 | localparam 50 | ROT = 1'd0, 51 | VEC = 1'd1; 52 | localparam 53 | INV_GAIN_32 = 32'sh9A8F4390, // 1.20749706776307210000 54 | LN_2 = 32'sh2C5C85FE, // 0.69314718055994529000 55 | LN_2_INV = 32'sh5C551D95; // 1.44269504088896340000 56 | localparam // account for repeated stages 57 | STAGES = W+(W>=4)+(W>=13)+(W>=40)+(W>=121)+(W>=364)+(W>=1093); 58 | 59 | reg [4:0] first_bit; 60 | reg [STAGES:0] mode; 61 | reg [31:0] atanh_table [31:0]; 62 | reg [STAGES-1:0] sigma; 63 | reg [W-1:0] x_neg [STAGES:0]; 64 | reg [W-1:0] y_neg [STAGES:0]; 65 | reg signed [W-1:0] x [STAGES:0]; 66 | reg signed [W-1:0] y [STAGES:0]; 67 | reg signed [W-1:0] z [STAGES:0]; 68 | reg signed [W-1:0] x_round [STAGES:0]; 69 | reg signed [W-1:0] y_round [STAGES:0]; 70 | 71 | wire func_out; 72 | wire [W-1:0] inv_gain, e_exp, e_exp_out; 73 | wire [W*2-1:0] m, d; 74 | wire [W*3-1:0] q; 75 | wire signed [4:0] e, e_out; 76 | wire signed [W-1:0] ln_2, ln_2_inv; 77 | wire signed [W+5-1:0] e_out_mul_ln_2; 78 | wire signed [W*2-1:0] z_se, e_out_mul_ln_2_se; 79 | 80 | initial begin // this is overkill, how to improve? 81 | atanh_table[0] = 32'h8C9F53D5; // 0.54930614433405478000 82 | atanh_table[1] = 32'h4162BBEA; // 0.25541281188299536000 83 | atanh_table[2] = 32'h202B1239; // 0.12565721414045303000 84 | atanh_table[3] = 32'h1005588B; // 0.06258157147700300900 85 | atanh_table[4] = 32'h0800AAC4; // 0.03126017849066699300 86 | atanh_table[5] = 32'h04001556; // 0.01562627175205220900 87 | atanh_table[6] = 32'h020002AB; // 0.00781265895154042120 88 | atanh_table[7] = 32'h01000055; // 0.00390626986839682620 89 | atanh_table[8] = 32'h0080000B; // 0.00195312748353254980 90 | atanh_table[9] = 32'h00400001; // 0.00097656281044103594 91 | atanh_table[10] = 32'h00200000; // 0.00048828128880511277 92 | atanh_table[11] = 32'h00100000; // 0.00024414062985063861 93 | atanh_table[12] = 32'h00080000; // 0.00012207031310632982 94 | atanh_table[13] = 32'h00040000; // 0.00006103515632579122 95 | atanh_table[14] = 32'h00020000; // 0.00003051757813447390 96 | atanh_table[15] = 32'h00010000; // 0.00001525878906368424 97 | atanh_table[16] = 32'h00008000; // 0.00000762939453139803 98 | atanh_table[17] = 32'h00004000; // 0.00000381469726564350 99 | atanh_table[18] = 32'h00002000; // 0.00000190734863281481 100 | atanh_table[19] = 32'h00001000; // 0.00000095367431640654 101 | atanh_table[20] = 32'h00000800; // 0.00000047683715820316 102 | atanh_table[21] = 32'h00000400; // 0.00000023841857910157 103 | atanh_table[22] = 32'h00000200; // 0.00000011920928955078 104 | atanh_table[23] = 32'h00000100; // 0.00000005960464477539 105 | atanh_table[24] = 32'h00000080; // 0.00000002980232238770 106 | atanh_table[25] = 32'h00000040; // 0.00000001490116119385 107 | atanh_table[26] = 32'h00000020; // 0.00000000745058059692 108 | atanh_table[27] = 32'h00000010; // 0.00000000372529029846 109 | atanh_table[28] = 32'h00000008; // 0.00000000186264514923 110 | atanh_table[29] = 32'h00000004; // 0.00000000093132257462 111 | atanh_table[30] = 32'h00000002; // 0.00000000046566128731 112 | atanh_table[31] = 32'h00000001; // 0.00000000023283064365 113 | end 114 | 115 | assign ln_2 = (LN_2[31:31-W+1] + LN_2[31-W]); 116 | assign ln_2_inv = (LN_2_INV[31:31-W+1] + LN_2_INV[31-W]); 117 | assign inv_gain = (INV_GAIN_32 >> (32-W+1)) + INV_GAIN_32[32-W]; 118 | assign m = (first_bit > 11) ? a >> (first_bit-11) : a << (11-first_bit); 119 | assign e = first_bit - 11; 120 | assign e_out_mul_ln_2 = e_out * ln_2; 121 | assign q = a * ln_2_inv; 122 | assign d = (q[21:21-W+1]+q[21-W]) * ln_2; 123 | assign e_exp = q[W*3-3:W*2-2]; 124 | 125 | always @ * begin 126 | casex(a) 127 | 24'b1_xxxxxxxxxxx_xxxxxxxxxxxx: first_bit = 23; 128 | 24'b0_1xxxxxxxxxx_xxxxxxxxxxxx: first_bit = 22; 129 | 24'b0_01xxxxxxxxx_xxxxxxxxxxxx: first_bit = 21; 130 | 24'b0_001xxxxxxxx_xxxxxxxxxxxx: first_bit = 20; 131 | 24'b0_0001xxxxxxx_xxxxxxxxxxxx: first_bit = 19; 132 | 24'b0_00001xxxxxx_xxxxxxxxxxxx: first_bit = 18; 133 | 24'b0_000001xxxxx_xxxxxxxxxxxx: first_bit = 17; 134 | 24'b0_0000001xxxx_xxxxxxxxxxxx: first_bit = 16; 135 | 24'b0_00000001xxx_xxxxxxxxxxxx: first_bit = 15; 136 | 24'b0_000000001xx_xxxxxxxxxxxx: first_bit = 14; 137 | 24'b0_0000000001x_xxxxxxxxxxxx: first_bit = 13; 138 | 24'b0_00000000001_xxxxxxxxxxxx: first_bit = 12; 139 | 24'b0_00000000000_1xxxxxxxxxxx: first_bit = 11; 140 | 24'b0_00000000000_01xxxxxxxxxx: first_bit = 10; 141 | 24'b0_00000000000_001xxxxxxxxx: first_bit = 9; 142 | 24'b0_00000000000_0001xxxxxxxx: first_bit = 8; 143 | 24'b0_00000000000_00001xxxxxxx: first_bit = 7; 144 | 24'b0_00000000000_000001xxxxxx: first_bit = 6; 145 | 24'b0_00000000000_0000001xxxxx: first_bit = 5; 146 | 24'b0_00000000000_00000001xxxx: first_bit = 4; 147 | 24'b0_00000000000_000000001xxx: first_bit = 3; 148 | 24'b0_00000000000_0000000001xx: first_bit = 2; 149 | 24'b0_00000000000_00000000001x: first_bit = 1; 150 | 24'b0_00000000000_000000000001: first_bit = 0; 151 | default: first_bit = 0; 152 | endcase 153 | end 154 | 155 | always @ (posedge clk or negedge rst_n) begin//function pre-processing 156 | if (!rst_n) begin 157 | x[0] <= 0; 158 | y[0] <= 0; 159 | z[0] <= 0; 160 | mode[0] <= ROT; 161 | end 162 | else begin 163 | case (func) 164 | EXP: begin 165 | x[0] <= inv_gain; 166 | y[0] <= 0; 167 | z[0] <= d[W*2-1:W]; 168 | mode[0] <= ROT; 169 | end 170 | LN: begin 171 | x[0] <= {2'b0,m[11:2]} + 12'b0100_0000_0000;//not rounded 172 | y[0] <= {2'b0,m[11:2]} - 12'b0100_0000_0000;//not rounded 173 | z[0] <= 0; 174 | mode[0] <= VEC; 175 | end 176 | default: begin 177 | x[0] <= 32'bx; 178 | y[0] <= 32'bx; 179 | z[0] <= 32'bx; 180 | mode[0] <= ROT; 181 | end 182 | endcase 183 | end 184 | end 185 | 186 | generate 187 | genvar i; 188 | for (i = 0; i < STAGES; i = i + 1) begin : gen_stages 189 | always @ * begin 190 | x_neg[i] = ~x[i] + 1; 191 | y_neg[i] = ~y[i] + 1; 192 | if (i==0) begin 193 | x_round[i] = x[i]; 194 | y_round[i] = y[i]; 195 | end 196 | else begin 197 | x_round[i] = (x[i][W-1]) ? ~(x_neg[i] + (x_neg[i][i-1] << i)+1) + 1 : x[i] + (x[i][i-1] << i); 198 | y_round[i] = (y[i][W-1]) ? ~(y_neg[i] + (y_neg[i][i-1] << i)+1) + 1 : y[i] + (y[i][i-1] << i); 199 | end 200 | end 201 | always @ * begin 202 | case (mode[i]) 203 | ROT: sigma[i] = ~z[i][W-1];//z>=0 204 | VEC: sigma[i] = y[i][W-1];//y<0 205 | default: sigma[i] = 1'd0; 206 | endcase 207 | end 208 | always @ (posedge clk or negedge rst_n) begin 209 | if (!rst_n) begin 210 | x[i+1] <= 0; 211 | y[i+1] <= 0; 212 | z[i+1] <= 0; 213 | mode[i+1] <= 0; 214 | end 215 | else begin 216 | x[i+1] <= (sigma[i]) ? 217 | x[i] + (y_round[i] >>> i+1-(i>4)-(i>13)-(i>40)-(i>121)-(i>364)-(i>1093)) : 218 | x[i] - (y_round[i] >>> i+1-(i>4)-(i>13)-(i>40)-(i>121)-(i>364)-(i>1093)); 219 | y[i+1] <= (sigma[i]) ? 220 | y[i] + (x_round[i] >>> i+1-(i>4)-(i>13)-(i>40)-(i>121)-(i>364)-(i>1093)) : 221 | y[i] - (x_round[i] >>> i+1-(i>4)-(i>13)-(i>40)-(i>121)-(i>364)-(i>1093)); 222 | z[i+1] <= (sigma[i]) ? 223 | z[i] - {2'b0,(atanh_table[i-(i>4)-(i>13)-(i>40)-(i>121)- 224 | (i>364)-(i>1093)][31:31-W+3] + 225 | atanh_table[i-(i>4)-(i>13)-(i>40)-(i>121)- 226 | (i>364)-(i>1093)][31-W+3-1])} : 227 | z[i] + {2'b0,(atanh_table[i-(i>4)-(i>13)-(i>40)-(i>121)- 228 | (i>364)-(i>1093)][31:31-W+3] + 229 | atanh_table[i-(i>4)-(i>13)-(i>40)-(i>121)-(i>364)- 230 | (i>1093)][31-W+3-1])}; 231 | mode[i+1] <= mode[i]; 232 | end 233 | end 234 | end 235 | endgenerate 236 | 237 | always @ (posedge clk or negedge rst_n) begin//function post-processing 238 | if (!rst_n) 239 | f <= 0; 240 | else begin 241 | case (func_out) 242 | EXP: f <= (e_exp_out[W-1]) ? 243 | (x[STAGES] + y[STAGES]) >> (~e_exp_out+12'b1) : 244 | (x[STAGES] + y[STAGES]) << e_exp_out; 245 | LN: f <= (z_se * 2 + e_out_mul_ln_2_se) * 4; 246 | endcase 247 | end 248 | end 249 | 250 | sign_extender 251 | #( 252 | .INPUT_WIDTH(W), 253 | .OUTPUT_WIDTH(W*2) 254 | ) 255 | sign_extender_z 256 | ( 257 | .original(z[STAGES]), 258 | .sign_extended_original(z_se) 259 | ); 260 | 261 | sign_extender 262 | #( 263 | .INPUT_WIDTH(W+5), 264 | .OUTPUT_WIDTH(W*2) 265 | ) 266 | sign_extender_e_out_mul_LN_2 267 | ( 268 | .original(e_out_mul_ln_2), 269 | .sign_extended_original(e_out_mul_ln_2_se) 270 | ); 271 | 272 | pipeline_registers 273 | #( 274 | .BIT_WIDTH(1), 275 | .NUMBER_OF_STAGES(W+3) 276 | ) 277 | pipe_valid 278 | ( 279 | .clk(clk), 280 | .rst_n(rst_n), 281 | .pipe_in(start), 282 | .pipe_out(valid) 283 | ); 284 | 285 | pipeline_registers 286 | #( 287 | .BIT_WIDTH(1+5+12), 288 | .NUMBER_OF_STAGES(W+2) 289 | ) 290 | pipe_func_e_exp 291 | ( 292 | .clk(clk), 293 | .rst_n(rst_n), 294 | .pipe_in({func,e,e_exp}), 295 | .pipe_out({func_out,e_out,e_exp_out}) 296 | ); 297 | 298 | endmodule 299 | -------------------------------------------------------------------------------- /src/div_pipelined.v: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Schuyler Eldridge 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Implements a fixed-point parameterized pipelined division 16 | // operation. Outputs are expected to be on range [-1,1), techincally 17 | // [-1,2^(BITS-1)-1/2^(BITS-1)]. There is no convergent rounding. 18 | // 19 | // [TODO] Implement optional convergent rounding and some form of 20 | // variable output binary point placement. There are arguments in 21 | // these changes that make sense (specifically, adding an additional 22 | // bit results in a gain of one value when all the other 2^6 values 23 | // greater than 1 aren't used). Other improvements that are needed: 1) 24 | // quotient_gen is getting smaller by one bit in every stage, it would 25 | // make more sense to generate this as such, 2) there's some weird 26 | // initial behavior after rst_n is deasserted, you get weird output on 27 | // the quotient line for a number of cycles. 28 | // 29 | // [TODO] This doesn't exactly behave as expected if you specify 30 | // different BITS and STAGES parameters (which for a functional 31 | // module, should be implemented). Note, that this technically works, 32 | // but needs more investigation to fully understand its properties. 33 | 34 | `timescale 1ns / 1ps 35 | module div_pipelined 36 | ( 37 | input clk, 38 | input rst_n, 39 | input start, 40 | input [BITS-1:0] dividend, 41 | input [BITS-1:0] divisor, 42 | output reg data_valid, 43 | output reg div_by_zero, 44 | output reg [STAGES-1:0] quotient 45 | // output reg [7:0] quotient_correct 46 | ); 47 | 48 | // WARNING!!! THESE PARAMETERS ARE INTENDED TO BE MODIFIED IN A TOP 49 | // LEVEL MODULE. LOCAL CHANGES HERE WILL, MOST LIKELY, BE 50 | // OVERWRITTEN! 51 | parameter 52 | BITS = 8, 53 | STAGES = BITS; 54 | 55 | // y = a/bQ 56 | 57 | reg [STAGES-1:0] start_gen, negative_quotient_gen, div_by_zero_gen; 58 | reg [BITS*2*(STAGES-1)-1:0] dividend_gen, divisor_gen, quotient_gen; 59 | wire [BITS-1:0] pad_dividend; 60 | wire [BITS-2:0] pad_divisor; 61 | 62 | assign pad_dividend = 0; 63 | assign pad_divisor = 0; 64 | 65 | // sign conversion stage 66 | always @ (posedge clk or negedge rst_n) 67 | begin 68 | if (!rst_n) begin 69 | div_by_zero_gen[0] <= 0; 70 | start_gen[0] <=0; 71 | negative_quotient_gen[0] <= 0; 72 | dividend_gen[BITS*2-1:0] <= 0; 73 | divisor_gen[BITS*2-1:0] <= 0; end 74 | else begin 75 | div_by_zero_gen[0] <= (divisor == 0); 76 | start_gen[0] <= start; 77 | negative_quotient_gen[0] <= dividend[BITS-1] ^ divisor[BITS-1]; 78 | dividend_gen[BITS*2-1:0] <= (dividend[BITS-1]) ? ~{dividend,pad_dividend} + 1 : {dividend,pad_dividend}; 79 | divisor_gen[BITS*2-1:0] <= (divisor [BITS-1]) ? ~{1'b1,divisor, pad_divisor} + 1 : {1'b0,divisor, pad_divisor}; 80 | end 81 | end 82 | 83 | // first computation stage 84 | always @ (posedge clk or negedge rst_n) begin 85 | if (!rst_n) begin 86 | div_by_zero_gen[1] <= 0; 87 | start_gen[1] <= 0; 88 | negative_quotient_gen[1] <= 0; 89 | divisor_gen[BITS*2*2-1:BITS*2] <= 0; 90 | quotient_gen[BITS*2-1:0] <= 0; 91 | dividend_gen[BITS*2*2-1:BITS*2] <= 0; 92 | end 93 | else begin 94 | div_by_zero_gen[1] <= div_by_zero_gen[0]; 95 | start_gen[1] <= start_gen[0]; 96 | negative_quotient_gen[1] <= negative_quotient_gen[0]; 97 | divisor_gen[BITS*2*2-1:BITS*2] <= divisor_gen[BITS*2-1:0] >> 1; 98 | if ( dividend_gen[BITS*2-1:0] >= divisor_gen[BITS*2-1:0]) begin 99 | quotient_gen[BITS*2-1:0] <= 1 << STAGES - 2; 100 | dividend_gen[BITS*2*2-1:BITS*2] <= dividend_gen[BITS*2-1:0] - divisor_gen[BITS*2-1:0]; 101 | end 102 | else begin 103 | quotient_gen[BITS*2-1:0] <= 0; 104 | dividend_gen[BITS*2*2-1:BITS*2] <= dividend_gen[BITS*2-1:0]; 105 | end 106 | end // else: !if(!rst_n) 107 | end // always @ (posedge clk) 108 | 109 | generate 110 | genvar i; 111 | for (i = 1; i < STAGES - 2; i = i + 1) begin : pipeline 112 | always @ (posedge clk or negedge rst_n) begin 113 | if (!rst_n) begin 114 | div_by_zero_gen[i+1] <= 0; 115 | start_gen[i+1] <= 0; 116 | negative_quotient_gen[i+1] <= 0; 117 | divisor_gen[BITS*2*(i+2)-1:BITS*2*(i+1)] <= 0; 118 | quotient_gen[BITS*2*(i+1)-1:BITS*2*i] <= 0; 119 | dividend_gen[BITS*2*(i+2)-1:BITS*2*(i+1)] <= 0; 120 | end 121 | else begin 122 | div_by_zero_gen[i+1] <= div_by_zero_gen[i]; 123 | start_gen[i+1] <= start_gen[i]; 124 | negative_quotient_gen[i+1] <= negative_quotient_gen[i]; 125 | divisor_gen[BITS*2*(i+2)-1:BITS*2*(i+1)] <= divisor_gen[BITS*2*(i+1)-1:BITS*2*i] >> 1; 126 | if (dividend_gen[BITS*2*(i+1)-1:BITS*2*i] >= divisor_gen[BITS*2*(i+1)-1:BITS*2*i]) begin 127 | quotient_gen[BITS*2*(i+1)-1:BITS*2*i] <= quotient_gen[BITS*2*i-1:BITS*2*(i-1)] | (1 << (STAGES-2-i)); 128 | dividend_gen[BITS*2*(i+2)-1:BITS*2*(i+1)] <= dividend_gen[BITS*2*(i+1)-1:BITS*2*i] - divisor_gen[BITS*2*(i+1)-1:BITS*2*i]; 129 | end 130 | else begin 131 | quotient_gen[BITS*2*(i+1)-1:BITS*2*i] <= quotient_gen[BITS*2*i-1:BITS*2*(i-1)]; 132 | dividend_gen[BITS*2*(i+2)-1:BITS*2*(i+1)] <= dividend_gen[BITS*2*(i+1)-1:BITS*2*i]; 133 | end 134 | end // else: !if(!rst_n) 135 | end // always @ (posedge clk or negedge rst_n) 136 | end // block: pipeline 137 | endgenerate 138 | 139 | // last computation stage 140 | always @ (posedge clk or negedge rst_n) begin 141 | if (!rst_n) begin 142 | div_by_zero_gen[STAGES-1] <= 0; 143 | start_gen[STAGES-1] <= 0; 144 | negative_quotient_gen[STAGES-1] <= 0; 145 | quotient_gen[BITS*2*(STAGES-1)-1:BITS*2*(STAGES-2)] <= 0; 146 | end 147 | else begin 148 | div_by_zero_gen[STAGES-1] <= div_by_zero_gen[STAGES-2]; 149 | start_gen[STAGES-1] <= start_gen[STAGES-2]; 150 | negative_quotient_gen[STAGES-1] <= negative_quotient_gen[STAGES-2]; 151 | if ( dividend_gen[BITS*2*(STAGES-1)-1:BITS*2*(STAGES-2)] >= divisor_gen[BITS*2*(STAGES-1)-1:BITS*2*(STAGES-2)] ) 152 | quotient_gen[BITS*2*(STAGES-1)-1:BITS*2*(STAGES-2)] <= quotient_gen[BITS*2*(STAGES-2)-1:BITS*2*(STAGES-3)] | 1; 153 | else 154 | quotient_gen[BITS*2*(STAGES-1)-1:BITS*2*(STAGES-2)] <= quotient_gen[BITS*2*(STAGES-2)-1:BITS*2*(STAGES-3)]; 155 | end // else: !if(!rst_n) 156 | end // always @ (posedge clk) 157 | 158 | // sign conversion stage 159 | always @ (posedge clk or negedge rst_n) begin 160 | if (!rst_n) begin 161 | div_by_zero <= 0; 162 | data_valid <= 0; 163 | quotient <= 0; 164 | end 165 | else begin 166 | div_by_zero <= div_by_zero_gen[STAGES-1]; 167 | data_valid <= start_gen[STAGES-1]; 168 | quotient <= (negative_quotient_gen[STAGES-1]) ? ~quotient_gen[BITS*2*(STAGES-1)-1:BITS*2*(STAGES-2)] + 1 : quotient_gen[BITS*2*(STAGES-1)-1:BITS*2*(STAGES-2)]; 169 | end 170 | end 171 | 172 | endmodule 173 | -------------------------------------------------------------------------------- /src/pipeline_registers.v: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Schuyler Eldridge 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Implements a series of pipeline registers specified by the input 16 | // parameters BIT_WIDTH and NUMBER_OF_STAGES. BIT_WIDTH determines the 17 | // size of the signal passed through each of the pipeline 18 | // registers. NUMBER_OF_STAGES is the number of pipeline registers 19 | // generated. This accepts values of 0 (yes, it just passes data from 20 | // input to output...) up to however many stages specified. 21 | 22 | `timescale 1ns / 1ps 23 | module pipeline_registers 24 | #( 25 | parameter 26 | BIT_WIDTH = 10, 27 | NUMBER_OF_STAGES = 5 28 | ) 29 | ( 30 | input clk, 31 | input reset_n, 32 | input [BIT_WIDTH-1:0] pipe_in, 33 | output reg [BIT_WIDTH-1:0] pipe_out 34 | ); 35 | 36 | // Main generate function for conditional hardware instantiation 37 | generate 38 | genvar i; 39 | // Pass-through case for the odd event that no pipeline stages are 40 | // specified. 41 | if (NUMBER_OF_STAGES == 0) begin 42 | always @ * 43 | pipe_out = pipe_in; 44 | end 45 | // Single flop case for a single stage pipeline 46 | else if (NUMBER_OF_STAGES == 1) begin 47 | always @ (posedge clk or negedge reset_n) 48 | pipe_out <= (!reset_n) ? 0 : pipe_in; 49 | end 50 | // Case for 2 or more pipeline stages 51 | else begin 52 | // Create the necessary regs 53 | reg [BIT_WIDTH*(NUMBER_OF_STAGES-1)-1:0] pipe_gen; 54 | // Create logic for the initial and final pipeline registers 55 | always @ (posedge clk or negedge reset_n) begin 56 | if (!reset_n) begin 57 | pipe_gen[BIT_WIDTH-1:0] <= 0; 58 | pipe_out <= 0; 59 | end 60 | else begin 61 | pipe_gen[BIT_WIDTH-1:0] <= pipe_in; 62 | pipe_out <= pipe_gen[BIT_WIDTH*(NUMBER_OF_STAGES-1)-1:BIT_WIDTH*(NUMBER_OF_STAGES-2)]; 63 | end 64 | end 65 | // Create the intermediate pipeline registers if there are 3 or 66 | // more pipeline stages 67 | for (i = 1; i < NUMBER_OF_STAGES-1; i = i + 1) begin : pipeline 68 | always @ (posedge clk or negedge reset_n) 69 | pipe_gen[BIT_WIDTH*(i+1)-1:BIT_WIDTH*i] <= (!reset_n) ? 0 : pipe_gen[BIT_WIDTH*i-1:BIT_WIDTH*(i-1)]; 70 | end 71 | end 72 | endgenerate 73 | 74 | endmodule 75 | -------------------------------------------------------------------------------- /src/pipeline_registers_set.v: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Schuyler Eldridge 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Extension of original pipeline_registers.v that allows for a 16 | // synchronous set of all the internal registers. 17 | 18 | `timescale 1ns / 1ps 19 | module pipeline_registers_set 20 | #( 21 | parameter 22 | BIT_WIDTH = 10, 23 | NUMBER_OF_STAGES = 5 24 | ) 25 | ( 26 | input clk, 27 | input reset_n, 28 | input set, 29 | input [BIT_WIDTH*NUMBER_OF_STAGES-1:0] set_data, 30 | input [BIT_WIDTH-1:0] pipe_in, 31 | output reg [BIT_WIDTH-1:0] pipe_out 32 | ); 33 | 34 | // Main generate function for conditional hardware instantiation 35 | generate 36 | genvar i; 37 | // Pass-through case for the odd event that no pipeline stages are 38 | // specified. 39 | if (NUMBER_OF_STAGES == 0) begin 40 | always @ * 41 | pipe_out = pipe_in; 42 | end 43 | // Single flop case for a single stage pipeline 44 | else if (NUMBER_OF_STAGES == 1) begin 45 | always @ (posedge clk or negedge reset_n) 46 | pipe_out <= (!reset_n) ? 0 : (set) ? set_data : pipe_in; 47 | end 48 | // Case for 2 or more pipeline stages 49 | else begin 50 | // Create the necessary regs 51 | reg [BIT_WIDTH*(NUMBER_OF_STAGES-1)-1:0] pipe_gen; 52 | // Create logic for the initial and final pipeline registers 53 | always @ (posedge clk or negedge reset_n) begin 54 | if (!reset_n) begin 55 | pipe_gen[BIT_WIDTH-1:0] <= 0; 56 | pipe_out <= 0; 57 | end 58 | else if (set) begin 59 | pipe_gen[BIT_WIDTH-1:0] <= set_data[BIT_WIDTH-1:0]; 60 | pipe_out <= set_data[BIT_WIDTH*NUMBER_OF_STAGES-1:BIT_WIDTH*(NUMBER_OF_STAGES-1)]; 61 | end 62 | else begin 63 | pipe_gen[BIT_WIDTH-1:0] <= pipe_in; 64 | pipe_out <= pipe_gen[BIT_WIDTH*(NUMBER_OF_STAGES-1)-1:BIT_WIDTH*(NUMBER_OF_STAGES-2)]; 65 | end 66 | end 67 | // Create the intermediate pipeline registers if there are 3 or 68 | // more pipeline stages 69 | for (i = 1; i < NUMBER_OF_STAGES-1; i = i + 1) begin : pipeline 70 | always @ (posedge clk or negedge reset_n) 71 | pipe_gen[BIT_WIDTH*(i+1)-1:BIT_WIDTH*i] <= (!reset_n) ? 0 : (set) ? set_data[BIT_WIDTH*(i+1)-1:BIT_WIDTH*i] : pipe_gen[BIT_WIDTH*i-1:BIT_WIDTH*(i-1)]; 72 | end 73 | end 74 | endgenerate 75 | 76 | endmodule 77 | -------------------------------------------------------------------------------- /src/ram_infer.v: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Schuyler Eldridge 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Infers parameterized block RAM from behavioral syntax. Based off an 16 | // example by Eric Johnson and Prof. Derek Chiou at UT Austin (see 17 | // http://users.ece.utexas.edu/~derek/code/BRAM.v). Tested by 18 | // inspection of simulated RTL schematic as this successfully infers 19 | // block RAM. 20 | 21 | `timescale 1ns/1ps 22 | module ram_infer 23 | #( 24 | parameter 25 | WIDTH = 8, 26 | DEPTH = 64, 27 | LG_DEPTH = 6, 28 | INIT_VAL = 8'd0 29 | ) 30 | ( 31 | input clka, clkb, wea, web, ena, enb, 32 | input [LG_DEPTH-1:0] addra, addrb, 33 | input [WIDTH-1:0] dina, dinb, 34 | output reg [WIDTH-1:0] douta, doutb 35 | ); 36 | 37 | reg [WIDTH-1:0] ram [DEPTH-1:0]; 38 | reg [WIDTH-1:0] doa, dob; 39 | 40 | genvar i; 41 | 42 | generate 43 | for (i=0; i 0) begin 69 | if (root_gen[i-1] + mask_gen[i] <= radicand_gen[i-1]) begin 70 | radicand_gen[i] <= radicand_gen[i-1] - mask_gen[i] - root_gen[i-1]; 71 | root_gen[i] <= (root_gen[i-1] >> 1) + mask_gen[i]; 72 | end 73 | else begin 74 | radicand_gen[i] <= radicand_gen[i-1]; 75 | root_gen[i] <= root_gen[i-1] >> 1; 76 | end 77 | end 78 | 79 | // Logic specific to the first stage 80 | if (i == 0) begin 81 | if (mask_gen[i] <= radicand) begin 82 | radicand_gen[i] <= radicand - mask_gen[i]; 83 | root_gen[i] <= mask_gen[i]; 84 | end 85 | else begin 86 | radicand_gen[i] <= radicand; 87 | root_gen[i] <= 0; 88 | end 89 | end 90 | end 91 | end 92 | end 93 | endgenerate 94 | 95 | assign root = root_gen[WIDTH_OUTPUT-1]; 96 | 97 | endmodule 98 | -------------------------------------------------------------------------------- /src/sqrt_pipelined.v: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Schuyler Eldridge 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Implements a fixed-point parameterized pipelined square root 16 | // operation on an unsigned input of any bit length. The number of 17 | // stages in the pipeline is equal to the number of output bits in the 18 | // computation. This pipelien sustains a throughput of one computation 19 | // per clock cycle. 20 | 21 | `timescale 1ns / 1ps 22 | module sqrt_pipelined 23 | #( 24 | parameter 25 | INPUT_BITS = 16, // number of input bits (any integer) 26 | OUTPUT_BITS = INPUT_BITS / 2 + INPUT_BITS % 2 // number of output bits 27 | ) 28 | ( 29 | input clk, // clock 30 | input reset_n, // asynchronous reset 31 | input start, // optional start signal 32 | input [INPUT_BITS-1:0] radicand, // unsigned radicand 33 | output reg data_valid, // optional data valid signal 34 | output reg [OUTPUT_BITS-1:0] root // unsigned root 35 | ); 36 | 37 | reg [OUTPUT_BITS-1:0] start_gen; // valid data propagation 38 | reg [OUTPUT_BITS*INPUT_BITS-1:0] root_gen; // root values 39 | reg [OUTPUT_BITS*INPUT_BITS-1:0] radicand_gen; // radicand values 40 | wire [OUTPUT_BITS*INPUT_BITS-1:0] mask_gen; // mask values 41 | 42 | // This is the first stage of the pipeline. 43 | always @ (posedge clk or negedge reset_n) begin 44 | if (!reset_n) begin 45 | start_gen[0] <= 0; 46 | radicand_gen[INPUT_BITS-1:0] <= 0; 47 | root_gen[INPUT_BITS-1:0] <= 0; 48 | end 49 | else begin 50 | start_gen[0] <= start; 51 | if ( mask_gen[INPUT_BITS-1:0] <= radicand ) begin 52 | radicand_gen[INPUT_BITS-1:0] <= radicand - mask_gen[INPUT_BITS-1:0]; 53 | root_gen[INPUT_BITS-1:0] <= mask_gen[INPUT_BITS-1:0]; 54 | end 55 | else begin 56 | radicand_gen[INPUT_BITS-1:0] <= radicand; 57 | root_gen[INPUT_BITS-1:0] <= 0; 58 | end 59 | end 60 | end 61 | 62 | // Main generate loop to create the masks and pipeline stages. 63 | generate 64 | genvar i; 65 | // Generate all the mask values. These are built up in the 66 | // following fashion: 67 | // LAST MASK: 0x00...001 68 | // 0x00...004 Increasing # OUTPUT_BITS 69 | // 0x00...010 | 70 | // 0x00...040 v 71 | // ... 72 | // FIRST MASK: 0x10...000 # masks == # OUTPUT_BITS 73 | // 74 | // Note that the first mask used can either be of the 0x1... or 75 | // 0x4... variety. This is purely determined by the number of 76 | // computation stages. However, the last mask used will always be 77 | // 0x1 and the second to last mask used will always be 0x4. 78 | for (i = 0; i < OUTPUT_BITS; i = i + 1) begin: mask_4 79 | if (i % 2) // i is odd, this is a 4 mask 80 | assign mask_gen[INPUT_BITS*(OUTPUT_BITS-i)-1:INPUT_BITS*(OUTPUT_BITS-i-1)] = 4 << 4 * (i/2); 81 | else // i is even, this is a 1 mask 82 | assign mask_gen[INPUT_BITS*(OUTPUT_BITS-i)-1:INPUT_BITS*(OUTPUT_BITS-i-1)] = 1 << 4 * (i/2); 83 | end 84 | // Generate all the pipeline stages to compute the square root of 85 | // the input radicand stream. The general approach is to compare 86 | // the current values of the root plus the mask to the 87 | // radicand. If root/mask sum is greater than the radicand, 88 | // subtract the mask and the root from the radicand and store the 89 | // radicand for the next stage. Additionally, the root is 90 | // increased by the value of the mask and stored for the next 91 | // stage. If this test fails, then the radicand and the root 92 | // retain their value through to the next stage. The one weird 93 | // thing is that the mask indices appear to be incremented by one 94 | // additional position. This is not the case, however, because the 95 | // first mask is used in the first stage (always block after the 96 | // generate statement). 97 | for (i = 0; i < OUTPUT_BITS - 1; i = i + 1) begin: pipeline 98 | always @ (posedge clk or negedge reset_n) begin : pipeline_stage 99 | if (!reset_n) begin 100 | start_gen[i+1] <= 0; 101 | radicand_gen[INPUT_BITS*(i+2)-1:INPUT_BITS*(i+1)] <= 0; 102 | root_gen[INPUT_BITS*(i+2)-1:INPUT_BITS*(i+1)] <= 0; 103 | end 104 | else begin 105 | start_gen[i+1] <= start_gen[i]; 106 | if ((root_gen[INPUT_BITS*(i+1)-1:INPUT_BITS*i] + 107 | mask_gen[INPUT_BITS*(i+2)-1:INPUT_BITS*(i+1)]) <= radicand_gen[INPUT_BITS*(i+1)-1:INPUT_BITS*i]) begin 108 | radicand_gen[INPUT_BITS*(i+2)-1:INPUT_BITS*(i+1)] <= radicand_gen[INPUT_BITS*(i+1)-1:INPUT_BITS*i] - 109 | mask_gen[INPUT_BITS*(i+2)-1:INPUT_BITS*(i+1)] - 110 | root_gen[INPUT_BITS*(i+1)-1:INPUT_BITS*i]; 111 | root_gen[INPUT_BITS*(i+2)-1:INPUT_BITS*(i+1)] <= (root_gen[INPUT_BITS*(i+1)-1:INPUT_BITS*i] >> 1) + 112 | mask_gen[INPUT_BITS*(i+2)-1:INPUT_BITS*(i+1)]; 113 | end 114 | else begin 115 | radicand_gen[INPUT_BITS*(i+2)-1:INPUT_BITS*(i+1)] <= radicand_gen[INPUT_BITS*(i+1)-1:INPUT_BITS*i]; 116 | root_gen[INPUT_BITS*(i+2)-1:INPUT_BITS*(i+1)] <= root_gen[INPUT_BITS*(i+1)-1:INPUT_BITS*i] >> 1; 117 | end 118 | end 119 | end 120 | end 121 | endgenerate 122 | 123 | // This is the final stage which just implements a rounding 124 | // operation. This stage could be tacked on as a combinational logic 125 | // stage, but who cares about latency, anyway? This is NOT a true 126 | // rounding stage. In order to add convergent rounding, you need to 127 | // increase the input bit width by 2 (increase the number of 128 | // pipeline stages by 1) and implement rounding in the module that 129 | // instantiates this one. 130 | always @ (posedge clk or negedge reset_n) begin 131 | if (!reset_n) begin 132 | data_valid <= 0; 133 | root <= 0; 134 | end 135 | else begin 136 | data_valid <= start_gen[OUTPUT_BITS-1]; 137 | if (root_gen[OUTPUT_BITS*INPUT_BITS-1:OUTPUT_BITS*INPUT_BITS-INPUT_BITS] > root_gen[OUTPUT_BITS*INPUT_BITS-1:OUTPUT_BITS*INPUT_BITS-INPUT_BITS]) 138 | root <= root_gen[OUTPUT_BITS*INPUT_BITS-1:OUTPUT_BITS*INPUT_BITS-INPUT_BITS] + 1; 139 | else 140 | root <= root_gen[OUTPUT_BITS*INPUT_BITS-1:OUTPUT_BITS*INPUT_BITS-INPUT_BITS]; 141 | end 142 | end 143 | 144 | endmodule 145 | -------------------------------------------------------------------------------- /src/uart_rx.v: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Schuyler Eldridge 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Uart receiver module. Reads data from a serial UART line (rx) and 16 | // outputs it over a parallel bus (data) based on the clock frequency 17 | // of the FPGA and the anticipated UART frequency. 18 | 19 | //`define PARITY // enable parity bit (not implemented) 20 | module uart_rx 21 | #( 22 | parameter 23 | CLK_FREQUENCY = 66_000_000, // fpga clock frequency 24 | UART_FREQUENCY = 921_600 // UART clock frequency 25 | ) 26 | ( 27 | input clk, rst_n, rx, // 1-bit inputs 28 | output reg valid, // signals that data is valid 29 | output reg [7:0] data // output parallel data 30 | ); 31 | 32 | reg [2:0] state, next_state; // state/next state variables 33 | reg [3:0] bit_count; // remembers the bit that we're on 34 | reg [7:0] data_tmp; // stores intermediate values for data 35 | reg [14:0] tick_count; // used to know when to read rx line 36 | 37 | localparam 38 | TICKS_PER_BIT = CLK_FREQUENCY / UART_FREQUENCY, 39 | HALF_TICKS_PER_BIT = TICKS_PER_BIT / 2, 40 | NUM_BITS = 4'd8; 41 | 42 | localparam 43 | IDLE = 3'd0, // wait for a transmission to come in 44 | START = 3'd1, // start bit 45 | DATA = 3'd2, // data bits 46 | // PARITY = 3'd3, // parity bit (not implemented) 47 | VALID = 3'd4, // output valid data 48 | STOP = 3'd5; // stop bit 49 | 50 | always @ (posedge clk or negedge rst_n) begin 51 | if (!rst_n) begin 52 | tick_count <= 15'b0; 53 | bit_count <= 4'b0; 54 | end 55 | else begin 56 | case (state) 57 | START: begin 58 | tick_count <= (tick_count==HALF_TICKS_PER_BIT) ? 15'b0 : tick_count + 15'b1; 59 | bit_count <= 4'b0; 60 | end 61 | DATA: begin 62 | tick_count <= (tick_count==TICKS_PER_BIT-1) ? 15'b0 : 63 | tick_count + 15'b1; 64 | bit_count <= (tick_count==TICKS_PER_BIT-1) ? bit_count + 1 : 65 | bit_count; 66 | end 67 | VALID: begin 68 | tick_count <= tick_count + 15'b1; 69 | end 70 | STOP: begin 71 | tick_count <= (tick_count==TICKS_PER_BIT-1) ? 15'b0 : 72 | tick_count + 15'b1; 73 | end 74 | default: begin 75 | tick_count <= 15'b0; 76 | bit_count <= 4'b0; 77 | end 78 | endcase 79 | end 80 | end 81 | 82 | always @ (posedge clk or negedge rst_n) 83 | state <= (!rst_n) ? IDLE : next_state; 84 | 85 | always @ (posedge clk or negedge rst_n) begin 86 | if (!rst_n) begin 87 | data <= 8'b0; 88 | data_tmp <= 8'b0; 89 | valid <= 1'b0; 90 | end 91 | else begin 92 | data <= 8'bx; 93 | data_tmp <= data_tmp; 94 | valid <= 0; 95 | case (state) 96 | IDLE: data_tmp <= 8'bx; 97 | START: data_tmp <= 8'bx; 98 | DATA: if (tick_count == TICKS_PER_BIT-1) data_tmp[bit_count] <= rx; 99 | VALID: begin 100 | data <= data_tmp; 101 | valid <= 1'b1; 102 | end 103 | STOP: data_tmp <= 8'bx; 104 | endcase 105 | end 106 | end 107 | 108 | always @ * begin 109 | case (state) 110 | IDLE: next_state = (!rx) ? START : state; 111 | START: next_state = (tick_count==HALF_TICKS_PER_BIT) ? DATA : state; 112 | DATA: next_state = ((tick_count==TICKS_PER_BIT - 1) & 113 | (bit_count==NUM_BITS - 1))?VALID:state; 114 | // PARITY: next_state = () ? : state; 115 | VALID: next_state = STOP; 116 | STOP: next_state = (tick_count==TICKS_PER_BIT-1) ? IDLE : state; 117 | default: next_state = IDLE; 118 | endcase 119 | end 120 | 121 | endmodule 122 | -------------------------------------------------------------------------------- /src/uart_tx.v: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Schuyler Eldridge 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | module uart_tx 16 | #( 17 | parameter 18 | CLK_FREQUENCY = 66_000_000, // fpga clock frequency 19 | UART_FREQUENCY = 921_600 // UART clock frequency 20 | ) 21 | ( 22 | input user_clk, // 66 MHz 23 | input rst_n, 24 | input start_tx, 25 | input [7:0] data, 26 | output reg tx_bit, 27 | output reg ready, 28 | output reg chipscope_clk 29 | ); 30 | 31 | localparam 32 | TICKS_PER_BIT = CLK_FREQUENCY / UART_FREQUENCY; 33 | localparam IDLE = 2'd0, 34 | INIT = 2'd1, 35 | TX = 2'd2, 36 | DONE = 2'd3; 37 | 38 | reg [ 1:0] state, next_state; 39 | reg [ 2:0] bit_count; 40 | reg [ 7:0] data_buf; 41 | reg [11:0] clk_count; 42 | 43 | always @ (posedge user_clk or negedge rst_n) begin 44 | if (!rst_n) 45 | chipscope_clk <= 0; 46 | else if ((clk_count == TICKS_PER_BIT-1) | 47 | (clk_count == TICKS_PER_BIT>>1)) 48 | chipscope_clk <= ~chipscope_clk; 49 | else 50 | chipscope_clk <= chipscope_clk; 51 | end 52 | 53 | always @ (posedge user_clk or negedge rst_n) begin 54 | state <= (!rst_n) ? IDLE : next_state; 55 | end 56 | 57 | always @ (posedge user_clk or negedge rst_n) begin 58 | if (!rst_n) begin 59 | tx_bit <= 1; // should be pulled up on reset 60 | ready <= 1; 61 | data_buf <= 0; 62 | bit_count <= 0; 63 | clk_count <= 0; 64 | end 65 | else begin 66 | case (state) 67 | IDLE: begin 68 | tx_bit <= 1; 69 | ready <= 1; 70 | data_buf <= data; 71 | bit_count <= 0; 72 | clk_count <= 0; 73 | end 74 | INIT: begin 75 | tx_bit <= 0; 76 | ready <= 0; 77 | data_buf <= data_buf; 78 | bit_count <= 0; 79 | clk_count <= (clk_count == TICKS_PER_BIT-1) ? 12'b0 : clk_count + 12'b1; 80 | end 81 | TX: begin 82 | tx_bit <= data_buf[bit_count]; 83 | ready <= 0; 84 | data_buf <= data_buf; 85 | bit_count <= (clk_count == TICKS_PER_BIT-1) ? bit_count+3'b1 : bit_count; 86 | clk_count <= (clk_count == TICKS_PER_BIT-1) ? 12'b0 : clk_count + 12'b1; 87 | end 88 | DONE: begin 89 | tx_bit <= 1; 90 | ready <= 0; 91 | data_buf <= data_buf; 92 | bit_count <= 0; 93 | clk_count <= (clk_count == TICKS_PER_BIT-1) ? 12'b0 : clk_count + 12'b1; 94 | end 95 | default: begin 96 | tx_bit <= 1'bx; 97 | ready <= 1'bx; 98 | data_buf <= 8'bx; 99 | bit_count <= 3'bx; 100 | clk_count <= 12'bx; 101 | end 102 | endcase 103 | end 104 | end 105 | 106 | always @ * begin 107 | case (state) 108 | IDLE: next_state <= (start_tx) ? INIT : state; 109 | INIT: next_state <= (clk_count == TICKS_PER_BIT-1) ? TX : state; 110 | TX: next_state <= ((bit_count == 7) & (clk_count 111 | == TICKS_PER_BIT-1)) ? DONE : state; 112 | DONE: next_state <= (clk_count == TICKS_PER_BIT-1) ? IDLE : state; 113 | default: next_state <= IDLE; 114 | endcase 115 | end 116 | 117 | endmodule 118 | --------------------------------------------------------------------------------