├── .gitmodules ├── LICENSE.md ├── README.md ├── blink ├── rtl │ └── blink.vhd ├── sim │ ├── Makefile │ └── tb_blink.vhd └── syn │ ├── Makefile │ ├── blink.ccf │ └── tb_blink.v ├── lib ├── rtl_components.vhd ├── sim_components.vhd └── user_components.vhd ├── neorv32_aes ├── rtl │ └── neorv32_aes.vhd ├── sim │ ├── Makefile │ └── tb_neorv32_aes.vhd └── syn │ ├── Makefile │ ├── neorv32_aes.ccf │ └── tb_neorv32_aes.v ├── uart_aes ├── rtl │ ├── uart_aes.vhd │ ├── uart_aes_types.vhd │ ├── uart_ctrl.vhd │ ├── uart_rx.vhd │ └── uart_tx.vhd ├── sim │ ├── Makefile │ ├── tb_uart_aes.tcl │ ├── tb_uart_aes.vhd │ ├── uart_aes_ref.c │ ├── uart_aes_ref.vhd │ └── uart_aes_sim.vhd └── syn │ ├── Makefile │ ├── read_data.txt │ ├── tb_uart_aes.v │ ├── uart_aes.ccf │ └── write_cmds.txt ├── uart_loop ├── rtl │ ├── uart_loop.vhd │ ├── uart_rx.vhd │ └── uart_tx.vhd ├── sim │ ├── Makefile │ └── tb_uart_loop.vhd └── syn │ ├── Makefile │ ├── tb_uart_loop.v │ └── uart_loop.ccf ├── uart_reg ├── rtl │ ├── uart_ctrl.vhd │ ├── uart_reg.vhd │ ├── uart_rx.vhd │ └── uart_tx.vhd ├── sim │ ├── Makefile │ └── tb_uart_reg.vhd └── syn │ ├── Makefile │ ├── tb_uart_reg.v │ └── uart_reg.ccf └── uart_trng ├── rtl ├── firo.vhd ├── firo_ctrl.vhd ├── uart_trng.vhd └── uart_tx.vhd ├── sim ├── Makefile └── tb_uart_trng.vhd ├── sw ├── Makefile └── uart_trng.c └── syn ├── Makefile ├── tb_uart_trng.v └── uart_trng.ccf /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "neorv32"] 2 | path = neorv32 3 | url = https://github.com/tmeissner/neorv32.git 4 | branch = aes_cfs 5 | [submodule "cryptocores"] 6 | path = cryptocores 7 | url = https://git.goodcleanfun.de/tmeissner/cryptocores.git 8 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # Apache License 2 | 3 | Version 2.0, January 2004 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, and distribution as defined by Sections 1 through 9 of this document. 10 | 11 | *"Licensor"* shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. 12 | 13 | *"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. 14 | 15 | *"You"* (or *"Your"*) shall mean an individual or Legal Entity exercising permissions granted by this License. 16 | 17 | *"Source"* form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. 18 | 19 | *"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. 20 | 21 | *"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). 22 | 23 | *"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. 24 | 25 | *"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."* 26 | 27 | *"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. 28 | 29 | ### 2. Grant of Copyright License. 30 | 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. 31 | 32 | ### 3. Grant of Patent License. 33 | 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. 34 | 35 | ### 4. Redistribution. 36 | 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: 37 | 38 | - You must give any other recipients of the Work or Derivative Works a copy of this License; and 39 | - You must cause any modified files to carry prominent notices stating that You changed the files; and 40 | - 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 41 | - 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. 42 | 43 | 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. 44 | 45 | ### 5. Submission of Contributions. 46 | 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. 47 | 48 | ### 6. Trademarks. 49 | 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. 50 | 51 | ### 7. Disclaimer of Warranty. 52 | 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. 53 | 54 | ### 8. Limitation of Liability. 55 | 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. 56 | 57 | ### 9. Accepting Warranty or Additional Liability. 58 | 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. 59 | 60 | 61 | ## Appendix: How to apply the Apache License to your work 62 | 63 | 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. 64 | 65 | Copyright [yyyy] [name of copyright owner] 66 | 67 | Licensed under the Apache License, Version 2.0 (the "License"); 68 | you may not use this file except in compliance with the License. 69 | You may obtain a copy of the License at 70 | 71 | http://www.apache.org/licenses/LICENSE-2.0 72 | 73 | Unless required by applicable law or agreed to in writing, software 74 | distributed under the License is distributed on an "AS IS" BASIS, 75 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 76 | See the License for the specific language governing permissions and 77 | limitations under the License. 78 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gatemate_experiments 2 | 3 | Ongoing experiments with the Cologne Chip's GateMate FPGA architecture. All experiments are done with teh GateMate FPGA Starter (Eval) Kit. 4 | 5 | *HINT:* 6 | 7 | This project uses external projects (a *neorv32* fork & *cryptocores*), which are redistributed as submodules. To get & nitialize the submodule, please use the `--recursive` option when cloning this repository. Use `git submodule update --recursive` to update the submodule if you already chaked out the main repository. 8 | 9 | ## Designs 10 | 11 | ### blink 12 | 13 | Simple design which should display a blinking LED waving from LED1-LED8 of the GateMate FPGA Starter Kit. It uses *CC_PLL* & *CC_CFG_END* primitives of the GateMate FPGA. 14 | 15 | ### neorv32_aes 16 | 17 | Try to implement a neorv32 processor with a AES-CTR custom function on the GateMate FPGA. However, it only works in simulation at the moment. 18 | 19 | ### uart_aes 20 | 21 | AES-CTR unit which can be accessed through UART. It uses *CC_PLL* & *CC_CFG_END* primitives of the GateMate FPGA. It contains 5 registers storing values of one byte each. The first received byte on the UART contains command & address: 22 | 23 | * `7 ` reserved 24 | * `6:4` register address 25 | * `3:0` command (`0x0` read, `0x1` write) 26 | 27 | In case of a write command, the payload has to follow with the next byte. In case of a read command, the value of the addressed register is returned on the axis out port. 28 | 29 | Register map: 30 | 31 | 0. `ctrl ` 1 byte (bit meaning: `0` reset, `1` CTR start, `2` AES start `3` AES finished) 32 | 1. `key ` 16 byte 33 | 2. `nonce` 12 byte 34 | 3. `din ` 16 byte 35 | 4. `dout ` 16 byte 36 | 37 | Content of registers bigger than one byte can be accessed by sending read/write commands for each of the bytes. 38 | 39 | Here is a simple example: 40 | 41 | First fill the key register with ascending bytes. 42 | 43 | ``` 44 | 11 01 11 23 11 45 11 67 11 89 11 AB 11 CD 11 EF 11 01 11 23 11 45 11 67 11 89 11 AB 11 CD 11 EF 45 | ``` 46 | 47 | Next fill the nonce register with ascending bytes. 48 | 49 | ``` 50 | 21 01 21 23 21 45 21 67 21 89 21 AB 21 CD 21 EF 21 01 21 23 21 45 21 67 51 | ``` 52 | 53 | Now fill the din register with ascending bytes. 54 | 55 | ``` 56 | 31 01 31 23 31 45 31 67 31 89 31 AB 31 CD 31 EF 31 01 31 23 31 45 31 67 31 89 31 AB 31 CD 31 EF 57 | ``` 58 | 59 | Finally, set bit 1 & 2 in control register to start a new AES-CTR operation. 60 | 61 | ``` 62 | 01 06 63 | ``` 64 | 65 | Check bit 3 of control register to know when AES-CTR calculation is finished. All other bits of control register are reset when AES-CTR calculation is finished. 66 | 67 | `00` returns `80` 68 | 69 | Now you can read the encrypted data from the dout register. 70 | 71 | ``` 72 | 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 73 | ``` 74 | 75 | returns (hopefully) 76 | 77 | ``` 78 | A0 55 A0 62 BC DD C3 4C 33 FE 9F A6 0C FB 6F 2D 79 | ``` 80 | 81 | You can start another AES-CTR round without restarting the counter (nonce register isn't used) ommiting bit 1 of the control register. 82 | 83 | ``` 84 | 01 04 85 | ``` 86 | 87 | Control registers bit 0 is used to reset registers 0 - 3. 88 | 89 | ``` 90 | 01 01 91 | ``` 92 | 93 | ### uart_loop 94 | 95 | Simple UART loop with UART RX & TX units and FIFO buffer between. It uses *CC_PLL* & *CC_CFG_END* primitives of the GateMate FPGA. With fifo depth >= 18 Yosys is infering *CC_BRAM_20K* instead of registers. 96 | 97 | Beware: The simulation model of *CC_BRAM_20K* seems to be incorrect, so better set fifo depth < 18 or use yosys option `-nobram` when synthesizing the model for post-synthesis & post-implementation simulation. 98 | 99 | ### uart_reg 100 | 101 | Register file which can be accessed through UART. It uses *CC_PLL* & *CC_CFG_END* primitives of the GateMate FPGA. It contains 8 registers storing values of one byte each. The first received byte on the axis in port contains command & address: 102 | 103 | * `7 ` reserved 104 | * `6:4` register address 105 | * `3:0` command (`0x0` read, `0x1` write) 106 | 107 | In case of a write command, the payload has to follow with the next byte. In case of a read command, the value of the addressed register is returned on the axis out port. Register at address 0 is special. It contains the version and is read-only. Writes to that register are ignored. 108 | 109 | ### uart_trng 110 | 111 | An implementation of a TRNG which allows to read random data from the FPGA via UART. Inclusive a software tool for easy access. Random generation is based on a fibonacci ring oscillator (FiRo) with toggle flip-flop and von Neumann post-processing. 112 | 113 | ## Further Ressources 114 | 115 | * [GateMate FPGA](https://www.colognechip.com/programmable-logic/gatemate) 116 | * [GateMate FPGA Eval Board](https://www.colognechip.com/programmable-logic/gatemate-evaluation-board) 117 | * [GHDL VHDL Simulation & Synthesis](https://github.com/ghdl/ghdl) 118 | * [Yosys Synthesis Suite](https://github.com/YosysHQ/yosys) 119 | -------------------------------------------------------------------------------- /blink/rtl/blink.vhd: -------------------------------------------------------------------------------- 1 | -- This design should display incrementing binary numbers 2 | -- at LED1-LED8 of the GateMate FPGA Starter Kit. 3 | 4 | 5 | library ieee ; 6 | use ieee.std_logic_1164.all; 7 | use ieee.numeric_std.all; 8 | 9 | library gatemate; 10 | use gatemate.components.all; 11 | 12 | 13 | entity blink is 14 | generic ( 15 | SIM : natural := 0 16 | ); 17 | port ( 18 | clk_i : in std_logic; -- 10 MHz clock 19 | rst_n_i : in std_logic; -- SW3 button 20 | led_n_o : out std_logic_vector(7 downto 0) -- LED1..LED8 21 | ); 22 | end entity blink; 23 | 24 | 25 | architecture rtl of blink is 26 | 27 | subtype t_clk_cnt is unsigned(19 downto 0); 28 | signal s_clk_cnt : t_clk_cnt; 29 | signal s_clk_cnt_end : t_clk_cnt; 30 | 31 | signal s_pll_clk : std_logic; 32 | signal s_pll_lock : std_logic; 33 | signal s_clk_en : boolean; 34 | 35 | signal s_rst_n : std_logic; 36 | signal s_usr_rstn : std_logic; 37 | 38 | signal s_sys_rst_n : std_logic; 39 | 40 | begin 41 | 42 | pll : CC_PLL 43 | generic map ( 44 | REF_CLK => "10", 45 | OUT_CLK => "2", 46 | PERF_MD => "SPEED" 47 | ) 48 | port map ( 49 | CLK_REF => clk_i, 50 | CLK_FEEDBACK => '0', 51 | USR_CLK_REF => '0', 52 | USR_LOCKED_STDY_RST => '0', 53 | USR_PLL_LOCKED_STDY => open, 54 | USR_PLL_LOCKED => s_pll_lock, 55 | CLK270 => open, 56 | CLK180 => open, 57 | CLK0 => s_pll_clk, 58 | CLK90 => open, 59 | CLK_REF_OUT => open 60 | ); 61 | 62 | cc_usr_rstn_inst : CC_USR_RSTN 63 | port map ( 64 | USR_RSTN => s_usr_rstn 65 | ); 66 | 67 | -- This works 68 | s_rst_n <= rst_n_i and s_pll_lock and s_usr_rstn; 69 | 70 | -- This doesn't work. 71 | -- The reset module seems to be removed during Yosys flatten pass, even 72 | -- when the output is connected with an output port, WHY does this happen? 73 | -- 2.5. Executing FLATTEN pass (flatten design). 74 | -- Deleting now unused module reset_sync_c4ea21bb365bbeeaf5f2c654883e56d11e43c44e. 75 | -- 76 | reset : entity work.reset_sync 77 | generic map ( 78 | POLARITY => '0' 79 | ) 80 | port map ( 81 | clk_i => s_pll_clk, 82 | rst_i => rst_n_i and s_pll_lock and s_usr_rstn, 83 | rst_o => s_sys_rst_n 84 | ); 85 | 86 | s_clk_cnt_end <= 20x"FFFFF" when SIM = 0 else -- synthesis 87 | 20x"000FF"; -- simulation 88 | 89 | process (s_pll_clk, s_rst_n) is 90 | begin 91 | if (not s_rst_n) then 92 | s_clk_cnt <= (others => '0'); 93 | elsif (rising_edge(s_pll_clk)) then 94 | if (s_clk_cnt = s_clk_cnt_end) then 95 | s_clk_cnt <= (others => '0'); 96 | else 97 | s_clk_cnt <= s_clk_cnt + 1; 98 | end if; 99 | end if; 100 | end process; 101 | 102 | s_clk_en <= s_clk_cnt = s_clk_cnt_end; 103 | 104 | process (s_pll_clk, s_rst_n) is 105 | begin 106 | if (not s_rst_n) then 107 | led_n_o <= x"FE"; 108 | elsif (rising_edge(s_pll_clk)) then 109 | if (s_clk_en) then 110 | led_n_o <= led_n_o(6 downto 0) & led_n_o(7); 111 | end if; 112 | end if; 113 | end process; 114 | 115 | 116 | end architecture; 117 | -------------------------------------------------------------------------------- /blink/sim/Makefile: -------------------------------------------------------------------------------- 1 | DESIGN_NAME := blink 2 | LIB_SRC := ../../lib/rtl_components.vhd ../../lib/sim_components.vhd 3 | RTL_SRC := ../../lib/user_components.vhd ../rtl/${DESIGN_NAME}.vhd 4 | SIM_SRC := tb_${DESIGN_NAME}.vhd 5 | SIM_FLAGS := --std=08 -fpsl --workdir=work 6 | 7 | .PHONY: all compile sim clean 8 | 9 | all: sim 10 | compile: tb_${DESIGN_NAME} 11 | 12 | tb_${DESIGN_NAME}: ${LIB_SRC} ${RTL_SRC} ${SIM_SRC} | work 13 | @echo "Analyze gatemate library ..." 14 | ghdl -a ${SIM_FLAGS} --work=gatemate ${LIB_SRC} 15 | @echo "Analyze testbench & design ..." 16 | ghdl -a ${SIM_FLAGS} -Pwork ${RTL_SRC} ${SIM_SRC} 17 | @echo "Elaborate testbench & design ..." 18 | ghdl -e ${SIM_FLAGS} -Pwork $@ 19 | 20 | sim: tb_${DESIGN_NAME} 21 | @echo "Run testbench ..." 22 | ghdl -r ${SIM_FLAGS} -Pwork tb_${DESIGN_NAME} --assert-level=error --wave=tb_${DESIGN_NAME}.ghw 23 | 24 | work: 25 | mkdir $@ 26 | 27 | clean: 28 | @echo "Cleaning simulation files ..." 29 | rm -rf tb_${DESIGN_NAME} *.o work/ 30 | -------------------------------------------------------------------------------- /blink/sim/tb_blink.vhd: -------------------------------------------------------------------------------- 1 | library ieee ; 2 | use ieee.std_logic_1164.all; 3 | use ieee.numeric_std.all; 4 | 5 | use std.env.all; 6 | 7 | 8 | entity tb_blink is 9 | end entity tb_blink; 10 | 11 | 12 | architecture sim of tb_blink is 13 | 14 | signal s_clk : std_logic := '1'; 15 | signal s_rst_n : std_logic := '0'; 16 | 17 | signal s_led_n : std_logic_vector(7 downto 0); 18 | 19 | begin 20 | 21 | dut : entity work.blink 22 | generic map ( 23 | SIM => 1 24 | ) 25 | port map ( 26 | clk_i => s_clk, 27 | rst_n_i => s_rst_n, 28 | led_n_o => s_led_n 29 | ); 30 | 31 | s_rst_n <= '1' after 120 ns; 32 | s_clk <= not s_clk after 50 ns; 33 | 34 | -- Let's test one complete rotate of LED output 35 | TestP : process is 36 | variable v_led_n : std_logic_vector(s_led_n'range) := x"FE"; 37 | begin 38 | wait until s_rst_n; 39 | wait until rising_edge(s_clk); 40 | for i in 0 to 7 loop 41 | report "LED: " & to_hstring(s_led_n); 42 | assert s_led_n = v_led_n 43 | report "LED error, got 0x" & to_hstring(s_led_n) & ", expected 0x" & to_hstring(v_led_n) 44 | severity failure; 45 | wait until s_led_n'event; 46 | v_led_n := v_led_n(6 downto 0) & v_led_n(7); 47 | end loop; 48 | report "Simulation finished :-)"; 49 | stop(0); 50 | end process; 51 | 52 | end architecture; 53 | -------------------------------------------------------------------------------- /blink/syn/Makefile: -------------------------------------------------------------------------------- 1 | DESIGN_NAME := blink 2 | WORK_FILES := ../../lib/user_components.vhd ../rtl/blink.vhd 3 | GM_FILES := ../../lib/rtl_components.vhd 4 | GHDL_FLAGS := --std=08 --workdir=build -Pbuild 5 | YOSYSPIPE := -nomx8 -retime 6 | # ATTENTION: -luttree option seems to mis-synthesize the design, broken with synth_gatemate? 7 | PNRFLAGS := -om 3 8 | PNRTOOL := $(shell which p_r) 9 | 10 | .PHONY: all syn imp prog syn_sim imp_sim 11 | 12 | all: imp 13 | syn: ${DESIGN_NAME}.v 14 | imp: ${DESIGN_NAME}.bit 15 | 16 | build/work-obj08.cf: ${WORK_FILES} build/gatemate-obj08.cf 17 | ghdl -a ${GHDL_FLAGS} --work=work ${WORK_FILES} 18 | 19 | build/gatemate-obj08.cf: ${GM_FILES} 20 | mkdir -p build 21 | ghdl -a ${GHDL_FLAGS} --work=gatemate ${GM_FILES} 22 | 23 | # Synthesis target for implementation 24 | ${DESIGN_NAME}.v: build/work-obj08.cf 25 | ghdl --synth ${GHDL_FLAGS} ${DESIGN_NAME} > ${DESIGN_NAME}.vhd 26 | yosys -m ghdl -p 'ghdl ${GHDL_FLAGS} --warn-no-binding --no-formal ${DESIGN_NAME}; synth_gatemate -top $(DESIGN_NAME) ${YOSYSPIPE} -vlog $@' \ 27 | 2>&1 | tee build/yosys-report.txt 28 | 29 | # Synthesis target for post-syn/post-imp simulation 30 | ${DESIGN_NAME}_sim.v: build/work-obj08.cf 31 | ghdl --synth ${GHDL_FLAGS} ${DESIGN_NAME} > ${DESIGN_NAME}.vhd 32 | yosys -m ghdl -p 'ghdl ${GHDL_FLAGS} -gSIM=1 --warn-no-binding --no-formal ${DESIGN_NAME}; synth_gatemate -top $(DESIGN_NAME) ${YOSYSPIPE} -vlog $@' \ 33 | 2>&1 | tee build/yosys-report.txt 34 | 35 | # Implementation target for FPGA 36 | ${DESIGN_NAME}.bit: ${DESIGN_NAME}.v ${DESIGN_NAME}.ccf 37 | cd build && \ 38 | ${PNRTOOL} -i ../${DESIGN_NAME}.v -o $@ --ccf ../${DESIGN_NAME}.ccf $(PNRFLAGS) \ 39 | 2>&1 | tee p_r-report.txt && \ 40 | mv ${DESIGN_NAME}*.bit ../$@ 41 | 42 | # Implementation target for post-implementation simulation 43 | build/${DESIGN_NAME}_00.v: ${DESIGN_NAME}_sim.v ${DESIGN_NAME}.ccf 44 | cd build && \ 45 | ${PNRTOOL} -i ../${DESIGN_NAME}_sim.v -o ${DESIGN_NAME}.v --ccf ../${DESIGN_NAME}.ccf $(PNRFLAGS) \ 46 | 2>&1 | tee p_r-report.txt 47 | 48 | # Post-synthesis simulation target 49 | syn_sim: ${DESIGN_NAME}_sim.v 50 | iverilog -g2012 -o tb_${DESIGN_NAME}_syn.vvp ${DESIGN_NAME}_sim.v tb_${DESIGN_NAME}.v /usr/local/share/yosys/gatemate/cells_sim.v 51 | vvp -N tb_${DESIGN_NAME}_syn.vvp -fst 52 | 53 | # Post-implementation simulation target 54 | imp_sim: build/${DESIGN_NAME}_00.v 55 | iverilog -g2012 -o tb_${DESIGN_NAME}_imp.vvp build/${DESIGN_NAME}_00.v tb_${DESIGN_NAME}.v /opt/cc-toolchain-linux/bin/p_r/cpelib.v 56 | vvp -N tb_${DESIGN_NAME}_imp.vvp -fst 57 | 58 | # FPGA FW load per JTAG 59 | prog: ${DESIGN_NAME}.bit 60 | openFPGALoader -b gatemate_evb_jtag $< 61 | 62 | clean : 63 | echo "# Cleaning files" 64 | rm -rf build ${DESIGN_NAME}.v ${DESIGN_NAME}_sim.v ${DESIGN_NAME}.vhd ${DESIGN_NAME}.bit *.vvp *.fst 65 | -------------------------------------------------------------------------------- /blink/syn/blink.ccf: -------------------------------------------------------------------------------- 1 | # Configuration for the Gatemate eval board 2 | 3 | Pin_in "clk_i" Loc = "IO_SB_A8" | SCHMITT_TRIGGER=true; 4 | Pin_in "rst_n_i" Loc = "IO_EB_B0"; # SW3 5 | 6 | Pin_out "led_n_o[0]" Loc = "IO_EB_B1"; # LED D1 7 | Pin_out "led_n_o[1]" Loc = "IO_EB_B2"; # LED D2 8 | Pin_out "led_n_o[2]" Loc = "IO_EB_B3"; # LED D3 9 | Pin_out "led_n_o[3]" Loc = "IO_EB_B4"; # LED D4 10 | Pin_out "led_n_o[4]" Loc = "IO_EB_B5"; # LED D5 11 | Pin_out "led_n_o[5]" Loc = "IO_EB_B6"; # LED D6 12 | Pin_out "led_n_o[6]" Loc = "IO_EB_B7"; # LED D7 13 | Pin_out "led_n_o[7]" Loc = "IO_EB_B8"; # LED D8 14 | 15 | Pin_out "debug_o[0]" Loc = "IO_NB_A4"; 16 | Pin_out "debug_o[1]" Loc = "IO_NB_A5"; 17 | Pin_out "debug_o[2]" Loc = "IO_NB_A6"; 18 | Pin_out "debug_o[3]" Loc = "IO_NB_A7"; 19 | Pin_out "debug_o[4]" Loc = "IO_NB_B4"; 20 | Pin_out "debug_o[5]" Loc = "IO_NB_B5"; 21 | Pin_out "debug_o[6]" Loc = "IO_NB_B6"; 22 | Pin_out "debug_o[7]" Loc = "IO_NB_B7"; 23 | -------------------------------------------------------------------------------- /blink/syn/tb_blink.v: -------------------------------------------------------------------------------- 1 | `timescale 1 ns/1 ns // time-unit = 1 ns, precision = 10 ps 2 | 3 | // simplified CC_PLL model 4 | module CC_PLL #( 5 | parameter REF_CLK = "", // e.g. "10.0" 6 | parameter OUT_CLK = "", // e.g. "50.0" 7 | parameter PERF_MD = "", // LOWPOWER, ECONOMY, SPEED 8 | parameter LOW_JITTER = 1, 9 | parameter CI_FILTER_CONST = 2, 10 | parameter CP_FILTER_CONST = 4 11 | )( 12 | input CLK_REF, CLK_FEEDBACK, USR_CLK_REF, 13 | input USR_LOCKED_STDY_RST, USR_SET_SEL, 14 | output USR_PLL_LOCKED_STDY, USR_PLL_LOCKED, 15 | output CLK270, CLK180, CLK90, CLK0, CLK_REF_OUT 16 | ); 17 | 18 | reg r_pll_clk; 19 | reg r_user_pll_locked; 20 | 21 | // OUT_FREQ = 2 MHz 22 | integer clk_half_period = 250; 23 | 24 | initial begin 25 | r_pll_clk = 1'b0; 26 | r_user_pll_locked = 1'b1; 27 | end 28 | 29 | always #clk_half_period r_pll_clk = ~r_pll_clk; 30 | 31 | assign CLK0 = r_pll_clk; 32 | assign USR_PLL_LOCKED = r_user_pll_locked; 33 | 34 | endmodule 35 | 36 | 37 | // simplified CC_CFG_END model 38 | module CC_CFG_END ( 39 | output CFG_END 40 | ); 41 | 42 | assign CFG_END = 1'b1; 43 | 44 | endmodule 45 | 46 | 47 | module tb_blink; 48 | 49 | // DUT in/out 50 | reg clk = 1'b0; 51 | reg rst_n = 1'b1; 52 | wire [7:0] led_n; 53 | 54 | // Testbench variables 55 | reg [7:0] led_exp = 8'hfe; 56 | 57 | // Testbench 1/2 clock period 58 | localparam clk_half_period = 50; 59 | 60 | blink DUT (.clk_i(clk), .rst_n_i(rst_n), .led_n_o(led_n)); 61 | 62 | // Set dumpfile 63 | initial begin 64 | $dumpfile ("tb_blink.fst"); 65 | $dumpvars (0, tb_blink); 66 | end 67 | 68 | // Setup simulation 69 | initial begin 70 | #1 rst_n = 1'b0; 71 | #120 rst_n = 1'b1; 72 | end 73 | 74 | // Generate 10 mhz clock 75 | always #clk_half_period clk = !clk; 76 | 77 | // Checker 78 | initial begin 79 | @(posedge rst_n) 80 | for (integer i = 0; i < 7; i = i + 1) begin 81 | assert (led_n == led_exp) 82 | $display("LED : 0x%h", led_n); 83 | else 84 | $warning("LED error, got 0x%h, expected 0x%h", led_n, led_exp); 85 | #128_000; 86 | led_exp = {led_exp[6:0], led_exp[7]}; 87 | end 88 | $display ("LED tests finished"); 89 | $finish; 90 | end 91 | 92 | 93 | endmodule 94 | -------------------------------------------------------------------------------- /lib/rtl_components.vhd: -------------------------------------------------------------------------------- 1 | library ieee ; 2 | use ieee.std_logic_1164.all; 3 | 4 | package components is 5 | 6 | component CC_PLL 7 | generic ( 8 | REF_CLK : string := "0"; -- reference clk in MHz 9 | OUT_CLK : string := "0"; -- output clk in MHz 10 | PERF_MD : string := "UNDEFINED"; -- LOWPOWER, ECONOMY, SPEED (optional, global, setting of Place&Route can be used instead) 11 | LOW_JITTER : natural := 1; -- 0: disable, 1: enable low jitter mode 12 | CI_FILTER_CONST : natural := 2; -- optional CI filter constant 13 | CP_FILTER_CONST : natural := 4 -- optional CP filter constant 14 | ); 15 | port ( 16 | CLK_REF : in std_logic; 17 | CLK_FEEDBACK : in std_logic; 18 | USR_CLK_REF : in std_logic; 19 | USR_LOCKED_STDY_RST : in std_logic; 20 | USR_PLL_LOCKED_STDY : out std_logic; 21 | USR_PLL_LOCKED : out std_logic; 22 | CLK270 : out std_logic; 23 | CLK180 : out std_logic; 24 | CLK0 : out std_logic; 25 | CLK90 : out std_logic; 26 | CLK_REF_OUT : out std_logic 27 | ); 28 | end component; 29 | 30 | component CC_PLL_ADV 31 | generic ( 32 | PLL_CFG_A : std_logic_vector(95 downto 0) := (others => 'X'); 33 | PLL_CFG_B : std_logic_vector(95 downto 0) := (others => 'X') 34 | ); 35 | port ( 36 | CLK_REF : in std_logic; 37 | CLK_FEEDBACK : in std_logic; 38 | USR_CLK_REF : in std_logic; 39 | USR_LOCKED_STDY_RST : in std_logic; 40 | USR_SEL_A_B : in std_logic; 41 | USR_PLL_LOCKED_STDY : out std_logic; 42 | USR_PLL_LOCKED : out std_logic; 43 | CLK270 : out std_logic; 44 | CLK180 : out std_logic; 45 | CLK0 : out std_logic; 46 | CLK90 : out std_logic; 47 | CLK_REF_OUT : out std_logic 48 | ); 49 | end component; 50 | 51 | component CC_SERDES 52 | generic ( 53 | SERDES_CFG : string := "" 54 | ); 55 | port ( 56 | TX_DATA_I : in std_logic_vector(63 downto 0); 57 | TX_RESET_I : in std_logic; 58 | TX_PCS_RESET_I : in std_logic; 59 | TX_PMA_RESET_I : in std_logic; 60 | PLL_RESET_I : in std_logic; 61 | TX_POWERDOWN_N_I : in std_logic; 62 | TX_POLARITY_I : in std_logic; 63 | TX_PRBS_SEL_I : in std_logic_vector(2 downto 0); 64 | TX_PRBS_FORCE_ERR_I : in std_logic; 65 | TX_8B10B_EN_I : in std_logic; 66 | TX_8B10B_BYPASS_I : in std_logic_vector(7 downto 0); 67 | TX_CHAR_IS_K_I : in std_logic_vector(7 downto 0); 68 | TX_CHAR_DISPMODE_I : in std_logic_vector(7 downto 0); 69 | TX_CHAR_DISPVAL_I : in std_logic_vector(7 downto 0); 70 | TX_ELEC_IDLE_I : in std_logic; 71 | TX_DETECT_RX_I : in std_logic; 72 | LOOPBACK_I : in std_logic_vector(2 downto 0); 73 | CLK_CORE_TX_I : in std_logic; 74 | CLK_CORE_RX_I : in std_logic; 75 | RX_RESET_I : in std_logic; 76 | RX_PMA_RESET_I : in std_logic; 77 | RX_EQA_RESET_I : in std_logic; 78 | RX_CDR_RESET_I : in std_logic; 79 | RX_PCS_RESET_I : in std_logic; 80 | RX_BUF_RESET_I : in std_logic; 81 | RX_POWERDOWN_N_I : in std_logic; 82 | RX_POLARITY_I : in std_logic; 83 | RX_PRBS_SEL_I : in std_logic_vector(2 downto 0); 84 | RX_PRBS_CNT_RESET_I : in std_logic; 85 | RX_8B10B_EN_I : in std_logic; 86 | RX_8B10B_BYPASS_I : in std_logic_vector(7 downto 0); 87 | RX_EN_EI_DETECTOR_I : in std_logic; 88 | RX_COMMA_DETECT_EN_I : in std_logic; 89 | RX_SLIDE_I : in std_logic; 90 | RX_MCOMMA_ALIGN_I : in std_logic; 91 | RX_PCOMMA_ALIGN_I : in std_logic; 92 | CLK_REG_I : in std_logic; 93 | REGFILE_WE_I : in std_logic; 94 | REGFILE_EN_I : in std_logic; 95 | REGFILE_ADDR_I : in std_logic_vector(7 downto 0); 96 | REGFILE_DI_I : in std_logic_vector(15 downto 0); 97 | REGFILE_MASK_I : in std_logic_vector(15 downto 0); 98 | RX_DATA_O : out std_logic_vector(63 downto 0); 99 | RX_NOT_IN_TABLE_O : out std_logic_vector(7 downto 0); 100 | RX_CHAR_IS_COMMA_O : out std_logic_vector(7 downto 0); 101 | RX_CHAR_IS_K_O : out std_logic_vector(7 downto 0); 102 | RX_DISP_ERR_O : out std_logic_vector(7 downto 0); 103 | RX_DETECT_DONE_O : out std_logic; 104 | RX_PRESENT_O : out std_logic; 105 | TX_BUF_ERR_O : out std_logic; 106 | TX_RESETDONE_O : out std_logic; 107 | RX_PRBS_ERR_O : out std_logic; 108 | RX_BUF_ERR_O : out std_logic; 109 | RX_BYTE_IS_ALIGNED_O : out std_logic; 110 | RX_BYTE_REALIGN_O : out std_logic; 111 | RX_RESETDONE_O : out std_logic; 112 | RX_EI_EN_O : out std_logic; 113 | CLK_CORE_RX_O : out std_logic; 114 | CLK_CORE_PLL_O : out std_logic; 115 | REGFILE_DO_O : out std_logic_vector(15 downto 0); 116 | REGFILE_RDY_O : out std_logic 117 | ); 118 | end component; 119 | 120 | component CC_CFG_CTRL 121 | port ( 122 | DATA : in std_logic_vector(7 downto 0); 123 | CLK : in std_logic; 124 | EN : in std_logic; 125 | RECFG : in std_logic; 126 | VALID : in std_logic 127 | ); 128 | end component; 129 | 130 | component CC_BRAM_20K is 131 | generic ( 132 | -- Location format: D(0..N-1)X(0..3)Y(0..7) or UNPLACED 133 | LOC : string := "UNPLACED"; 134 | -- Port Widths 135 | A_RD_WIDTH : natural := 0; 136 | B_RD_WIDTH : natural := 0; 137 | A_WR_WIDTH : natural := 0; 138 | B_WR_WIDTH : natural := 0; 139 | -- RAM and Write Modes 140 | RAM_MODE : string := "SDP"; 141 | A_WR_MODE : string := "NO_CHANGE"; 142 | B_WR_MODE : string := "NO_CHANGE"; 143 | -- Inverting Control Pins 144 | A_CLK_INV : std_logic := '0'; 145 | B_CLK_INV : std_logic := '0'; 146 | A_EN_INV : std_logic := '0'; 147 | B_EN_INV : std_logic := '0'; 148 | A_WE_INV : std_logic := '0'; 149 | B_WE_INV : std_logic := '0'; 150 | -- Output Register 151 | A_DO_REG : std_logic := '0'; 152 | B_DO_REG : std_logic := '0'; 153 | -- Error Checking and Correction 154 | ECC_EN : std_logic := '0'; 155 | -- RAM init content 156 | INIT_00 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 157 | INIT_01 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 158 | INIT_02 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 159 | INIT_03 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 160 | INIT_04 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 161 | INIT_05 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 162 | INIT_06 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 163 | INIT_07 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 164 | INIT_08 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 165 | INIT_09 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 166 | INIT_0A : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 167 | INIT_0B : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 168 | INIT_0C : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 169 | INIT_0D : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 170 | INIT_0E : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 171 | INIT_0F : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 172 | INIT_10 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 173 | INIT_11 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 174 | INIT_12 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 175 | INIT_13 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 176 | INIT_14 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 177 | INIT_15 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 178 | INIT_16 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 179 | INIT_17 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 180 | INIT_18 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 181 | INIT_19 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 182 | INIT_1A : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 183 | INIT_1B : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 184 | INIT_1C : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 185 | INIT_1D : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 186 | INIT_1E : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 187 | INIT_1F : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 188 | INIT_20 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 189 | INIT_21 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 190 | INIT_22 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 191 | INIT_23 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 192 | INIT_24 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 193 | INIT_25 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 194 | INIT_26 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 195 | INIT_27 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 196 | INIT_28 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 197 | INIT_29 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 198 | INIT_2A : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 199 | INIT_2B : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 200 | INIT_2C : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 201 | INIT_2D : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 202 | INIT_2E : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 203 | INIT_2F : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 204 | INIT_30 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 205 | INIT_31 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 206 | INIT_32 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 207 | INIT_33 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 208 | INIT_34 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 209 | INIT_35 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 210 | INIT_36 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 211 | INIT_37 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 212 | INIT_38 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 213 | INIT_39 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 214 | INIT_3A : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 215 | INIT_3B : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 216 | INIT_3C : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 217 | INIT_3D : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 218 | INIT_3E : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 219 | INIT_3F : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000" 220 | ); 221 | port ( 222 | -- clocks 223 | A_CLK : in std_logic; 224 | B_CLK : in std_logic; 225 | -- inputs 226 | A_EN : in std_logic; 227 | B_EN : in std_logic; 228 | A_WE : in std_logic; 229 | B_WE : in std_logic; 230 | A_ADDR : in std_logic_vector(15 downto 0); 231 | B_ADDR : in std_logic_vector(15 downto 0); 232 | A_DI : in std_logic_vector(19 downto 0); 233 | B_DI : in std_logic_vector(19 downto 0); 234 | A_BM : in std_logic_vector(19 downto 0); 235 | B_BM : in std_logic_vector(19 downto 0); 236 | -- outputs 237 | A_DO : out std_logic_vector(19 downto 0); 238 | B_DO : out std_logic_vector(19 downto 0); 239 | ECC_1B_ERR : out std_logic; 240 | ECC_2B_ERR : out std_logic 241 | ); 242 | end component; 243 | 244 | component CC_BRAM_40K is 245 | generic ( 246 | -- Location format: D(0..N-1)X(0..3)Y(0..7) or UNPLACED 247 | LOC : string := "UNPLACED"; 248 | CAS : string := "NONE"; -- NONE, UPPER, LOWER 249 | -- Port Widths 250 | A_RD_WIDTH : natural := 0; 251 | B_RD_WIDTH : natural := 0; 252 | A_WR_WIDTH : natural := 0; 253 | B_WR_WIDTH : natural := 0; 254 | -- RAM and Write Modes 255 | RAM_MODE : string := "SDP"; 256 | A_WR_MODE : string := "NO_CHANGE"; 257 | B_WR_MODE : string := "NO_CHANGE"; 258 | -- Inverting Control Pins 259 | A_CLK_INV : std_logic := '0'; 260 | B_CLK_INV : std_logic := '0'; 261 | A_EN_INV : std_logic := '0'; 262 | B_EN_INV : std_logic := '0'; 263 | A_WE_INV : std_logic := '0'; 264 | B_WE_INV : std_logic := '0'; 265 | -- Output Register 266 | A_DO_REG : std_logic := '0'; 267 | B_DO_REG : std_logic := '0'; 268 | -- Error Checking and Correction 269 | A_ECC_EN : std_logic := '0'; 270 | B_ECC_EN : std_logic := '0'; 271 | -- RAM init content 272 | INIT_00 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 273 | INIT_01 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 274 | INIT_02 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 275 | INIT_03 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 276 | INIT_04 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 277 | INIT_05 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 278 | INIT_06 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 279 | INIT_07 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 280 | INIT_08 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 281 | INIT_09 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 282 | INIT_0A : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 283 | INIT_0B : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 284 | INIT_0C : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 285 | INIT_0D : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 286 | INIT_0E : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 287 | INIT_0F : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 288 | INIT_10 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 289 | INIT_11 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 290 | INIT_12 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 291 | INIT_13 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 292 | INIT_14 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 293 | INIT_15 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 294 | INIT_16 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 295 | INIT_17 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 296 | INIT_18 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 297 | INIT_19 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 298 | INIT_1A : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 299 | INIT_1B : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 300 | INIT_1C : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 301 | INIT_1D : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 302 | INIT_1E : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 303 | INIT_1F : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 304 | INIT_20 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 305 | INIT_21 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 306 | INIT_22 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 307 | INIT_23 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 308 | INIT_24 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 309 | INIT_25 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 310 | INIT_26 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 311 | INIT_27 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 312 | INIT_28 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 313 | INIT_29 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 314 | INIT_2A : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 315 | INIT_2B : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 316 | INIT_2C : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 317 | INIT_2D : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 318 | INIT_2E : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 319 | INIT_2F : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 320 | INIT_30 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 321 | INIT_31 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 322 | INIT_32 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 323 | INIT_33 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 324 | INIT_34 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 325 | INIT_35 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 326 | INIT_36 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 327 | INIT_37 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 328 | INIT_38 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 329 | INIT_39 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 330 | INIT_3A : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 331 | INIT_3B : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 332 | INIT_3C : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 333 | INIT_3D : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 334 | INIT_3E : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 335 | INIT_3F : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 336 | INIT_40 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 337 | INIT_41 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 338 | INIT_42 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 339 | INIT_43 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 340 | INIT_44 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 341 | INIT_45 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 342 | INIT_46 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 343 | INIT_47 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 344 | INIT_48 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 345 | INIT_49 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 346 | INIT_4A : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 347 | INIT_4B : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 348 | INIT_4C : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 349 | INIT_4D : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 350 | INIT_4E : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 351 | INIT_4F : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 352 | INIT_50 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 353 | INIT_51 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 354 | INIT_52 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 355 | INIT_53 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 356 | INIT_54 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 357 | INIT_55 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 358 | INIT_56 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 359 | INIT_57 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 360 | INIT_58 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 361 | INIT_59 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 362 | INIT_5A : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 363 | INIT_5B : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 364 | INIT_5C : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 365 | INIT_5D : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 366 | INIT_5E : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 367 | INIT_5F : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 368 | INIT_60 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 369 | INIT_61 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 370 | INIT_62 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 371 | INIT_63 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 372 | INIT_64 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 373 | INIT_65 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 374 | INIT_66 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 375 | INIT_67 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 376 | INIT_68 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 377 | INIT_69 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 378 | INIT_6A : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 379 | INIT_6B : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 380 | INIT_6C : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 381 | INIT_6D : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 382 | INIT_6E : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 383 | INIT_6F : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 384 | INIT_70 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 385 | INIT_71 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 386 | INIT_72 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 387 | INIT_73 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 388 | INIT_74 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 389 | INIT_75 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 390 | INIT_76 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 391 | INIT_77 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 392 | INIT_78 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 393 | INIT_79 : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 394 | INIT_7A : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 395 | INIT_7B : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 396 | INIT_7C : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 397 | INIT_7D : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 398 | INIT_7E : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000"; 399 | INIT_7F : std_logic_vector(319 downto 0) := x"00000000000000000000000000000000000000000000000000000000000000000000000000000000" 400 | ); 401 | port ( 402 | -- clocks 403 | A_CLK : in std_logic; 404 | B_CLK : in std_logic; 405 | -- inputs 406 | A_EN : in std_logic; 407 | B_EN : in std_logic; 408 | A_WE : in std_logic; 409 | B_WE : in std_logic; 410 | A_ADDR : in std_logic_vector(15 downto 0); 411 | B_ADDR : in std_logic_vector(15 downto 0); 412 | A_DI : in std_logic_vector(39 downto 0); 413 | B_DI : in std_logic_vector(39 downto 0); 414 | A_BM : in std_logic_vector(39 downto 0); 415 | B_BM : in std_logic_vector(39 downto 0); 416 | A_CI : in std_logic; 417 | B_CI : in std_logic; 418 | -- outputs 419 | A_DO : out std_logic_vector(39 downto 0); 420 | B_DO : out std_logic_vector(39 downto 0); 421 | A_ECC_1B_ERR : out std_logic; 422 | B_ECC_1B_ERR : out std_logic; 423 | A_ECC_2B_ERR : out std_logic; 424 | B_ECC_2B_ERR : out std_logic 425 | -- These ports are listed in the Primitives Doc, but p_r tool doesn't knows them: 426 | -- FATAL ERROR: (51513): Component CC_BRAM_40K has no port name: A_CO 427 | -- FATAL ERROR: (51513): Component CC_BRAM_40K has no port name: B_CO 428 | -- A_CO : out std_logic; 429 | -- B_CO : out std_logic 430 | ); 431 | end component; 432 | 433 | component CC_FIFO_40K 434 | generic ( 435 | LOC : string := "UNPLACED"; -- Location format: D(0..N-1)X(0..3)Y(0..7) or UNPLACED 436 | ALMOST_FULL_OFFSET : std_logic_vector (12 downto 0) := (others => '0'); -- Almost full offset 437 | ALMOST_EMPTY_OFFSET : std_logic_vector (12 downto 0) := (others => '0'); -- Almost empty offset 438 | A_WIDTH : natural := 0; -- Port A Width 439 | B_WIDTH : natural := 0; -- Port B Width 440 | RAM_MODE : string := "SDP"; -- RAM mode: "TPD" or "SDP" 441 | FIFO_MODE : string := "SYNC"; -- Write mode: "ASYNC" or "SYNC" 442 | A_CLK_INV : std_logic := '0'; -- Inverting Control Pins 443 | B_CLK_INV : std_logic := '0'; -- Inverting Control Pins 444 | A_EN_INV : std_logic := '0'; -- Inverting Control Pins 445 | B_EN_INV : std_logic := '0'; -- Inverting Control Pins 446 | A_WE_INV : std_logic := '0'; -- Inverting Control Pins 447 | B_WE_INV : std_logic := '0'; -- Inverting Control Pins 448 | A_DO_REG : std_logic := '0'; -- Port A Output Register 449 | B_DO_REG : std_logic := '0'; -- Port B Output Register 450 | A_ECC_EN : std_logic := '0'; -- Port A Error Checking and Correction 451 | B_ECC_EN : std_logic := '0' -- Port B Error Checking and Correction 452 | ); 453 | port ( 454 | A_ECC_1B_ERR : out std_logic; 455 | B_ECC_1B_ERR : out std_logic; 456 | A_ECC_2B_ERR : out std_logic; 457 | B_ECC_2B_ERR : out std_logic; 458 | -- FIFO pop port 459 | A_DO : out std_logic_vector(39 downto 0); 460 | B_DO : out std_logic_vector(39 downto 0); 461 | 462 | A_CLK : in std_logic; 463 | A_EN : in std_logic; 464 | -- FIFO push port 465 | A_DI : in std_logic_vector(39 downto 0); 466 | B_DI : in std_logic_vector(39 downto 0); 467 | A_BM : in std_logic_vector(39 downto 0); 468 | B_BM : in std_logic_vector(39 downto 0); 469 | 470 | B_CLK : in std_logic; 471 | B_EN : in std_logic; 472 | B_WE : in std_logic; 473 | -- FIFO control 474 | F_RST_N : in std_logic; 475 | F_ALMOST_FULL_OFFSET : in std_logic_vector(12 downto 0); 476 | F_ALMOST_EMPTY_OFFSET : in std_logic_vector(12 downto 0); 477 | -- FIFO status signals 478 | F_FULL : out std_logic; 479 | F_EMPTY : out std_logic; 480 | F_ALMOST_FULL : out std_logic; 481 | F_ALMOST_EMPTY : out std_logic; 482 | F_RD_ERROR : out std_logic; 483 | F_WR_ERROR : out std_logic; 484 | F_RD_PTR : out std_logic_vector(15 downto 0); 485 | F_WR_PTR : out std_logic_vector(15 downto 0) 486 | ); 487 | end component; 488 | 489 | component CC_CFG_END 490 | port ( 491 | CFG_END : out std_logic 492 | ); 493 | end component; 494 | 495 | component CC_USR_RSTN 496 | port ( 497 | USR_RSTN : out std_logic 498 | ); 499 | end component; 500 | 501 | component CC_BUFG 502 | port ( 503 | I : in std_logic; 504 | O : out std_logic 505 | ); 506 | end component; 507 | 508 | 509 | end package components; -------------------------------------------------------------------------------- /lib/sim_components.vhd: -------------------------------------------------------------------------------- 1 | library ieee ; 2 | use ieee.std_logic_1164.all; 3 | use ieee.math_real.all; 4 | 5 | 6 | entity CC_PLL is 7 | generic ( 8 | REF_CLK : string := "0"; -- reference clk in MHz 9 | OUT_CLK : string := "0"; -- output clk in MHz 10 | PERF_MD : string := "UNDEFINED"; -- LOWPOWER, ECONOMY, SPEED (optional, global, setting of Place&Route can be used instead) 11 | LOW_JITTER : natural := 1; -- 0: disable, 1: enable low jitter mode 12 | CI_FILTER_CONST : natural := 2; -- optional CI filter constant 13 | CP_FILTER_CONST : natural := 4 -- optional CP filter constant 14 | ); 15 | port ( 16 | CLK_REF : in std_logic; 17 | CLK_FEEDBACK : in std_logic; 18 | USR_CLK_REF : in std_logic; 19 | USR_LOCKED_STDY_RST : in std_logic; 20 | USR_PLL_LOCKED_STDY : out std_logic; 21 | USR_PLL_LOCKED : out std_logic; 22 | CLK270 : out std_logic := '0'; 23 | CLK180 : out std_logic := '0'; 24 | CLK0 : out std_logic := '0'; 25 | CLK90 : out std_logic := '0'; 26 | CLK_REF_OUT : out std_logic 27 | ); 28 | end entity; 29 | 30 | 31 | architecture sim of CC_PLL is 32 | 33 | signal s_pll_clk_2 : std_logic := '1'; 34 | signal s_pll_clk_pos : std_logic := '0'; 35 | signal s_pll_clk_neg : std_logic := '0'; 36 | 37 | begin 38 | 39 | -- First create a clock with freq = 2 * OUT_CLK; 40 | s_pll_clk_2 <= not s_pll_clk_2 after (250.0 / real'value(OUT_CLK)) * ns; 41 | 42 | -- Then create clocks with freq = OUT_CLK and shifted by 180 degree 43 | s_pll_clk_pos <= not s_pll_clk_pos when rising_edge(s_pll_clk_2); 44 | s_pll_clk_neg <= not s_pll_clk_pos when falling_edge(s_pll_clk_2); 45 | 46 | -- Finally assign the clock outputs to avoid delta cycle delay problems 47 | -- All these clocks should by phase aligned 48 | CLK0 <= s_pll_clk_pos; 49 | CLK90 <= s_pll_clk_neg; 50 | CLK180 <= not s_pll_clk_pos; 51 | CLK270 <= not s_pll_clk_neg; 52 | 53 | CLK_REF_OUT <= CLK_REF or USR_CLK_REF; 54 | 55 | USR_PLL_LOCKED <= '1'; 56 | 57 | end architecture; 58 | 59 | 60 | library ieee ; 61 | use ieee.std_logic_1164.all; 62 | 63 | 64 | entity CC_USR_RSTN 65 | port ( 66 | USR_RSTN : out std_logic 67 | ); 68 | end entity; 69 | 70 | 71 | architecture sim of CC_USR_RSTN is 72 | begin 73 | 74 | USR_RSTN <= '1'; 75 | 76 | end architecture; 77 | -------------------------------------------------------------------------------- /lib/user_components.vhd: -------------------------------------------------------------------------------- 1 | -- Async reset synchronizer circuit inspired from 2 | -- Chris Cummings SNUG 2002 paper 3 | -- Synchronous Resets? Asynchronous Resets? 4 | -- I am so confused! 5 | -- How will I ever know which to use? 6 | 7 | 8 | library ieee ; 9 | use ieee.std_logic_1164.all; 10 | 11 | 12 | entity reset_sync is 13 | generic ( 14 | POLARITY : std_logic := '0' 15 | ); 16 | port ( 17 | clk_i : in std_logic; 18 | rst_i : in std_logic; 19 | rst_o : out std_logic 20 | ); 21 | end entity; 22 | 23 | 24 | architecture sim of reset_sync is 25 | 26 | signal s_rst_d : std_logic_vector(1 downto 0); 27 | 28 | begin 29 | 30 | process (clk_i, rst_i) is 31 | begin 32 | if (rst_i = POLARITY) then 33 | s_rst_d <= (others => POLARITY); 34 | elsif (rising_edge(clk_i)) then 35 | s_rst_d <= s_rst_d(0) & not POLARITY; 36 | end if; 37 | end process; 38 | 39 | rst_o <= s_rst_d(1); 40 | 41 | end architecture; 42 | 43 | 44 | -- Async reset synchronizer circuit inspired from 45 | -- Chris Cummings SNUG 2002 paper 46 | -- Synchronous Resets? Asynchronous Resets? 47 | -- I am so confused! 48 | -- How will I ever know which to use? 49 | 50 | 51 | library ieee ; 52 | use ieee.std_logic_1164.all; 53 | 54 | 55 | entity reset_sync_slv is 56 | generic ( 57 | POLARITY : std_logic := '0' 58 | ); 59 | port ( 60 | clk_i : in std_logic; 61 | rst_i : in std_logic_vector; 62 | rst_o : out std_logic_vector 63 | ); 64 | end entity; 65 | 66 | 67 | architecture sim of reset_sync_slv is 68 | 69 | begin 70 | 71 | GEN : for i in rst_i'range generate 72 | signal s_rst_d : std_logic_vector(1 downto 0); 73 | begin 74 | 75 | process (clk_i, rst_i(i)) is 76 | begin 77 | if (rst_i(i) = POLARITY) then 78 | s_rst_d <= (others => POLARITY); 79 | elsif (rising_edge(clk_i)) then 80 | s_rst_d <= s_rst_d(0) & not POLARITY; 81 | end if; 82 | end process; 83 | 84 | rst_o(i) <= s_rst_d(1); 85 | 86 | end generate; 87 | 88 | end architecture; 89 | 90 | 91 | library ieee; 92 | use ieee.std_logic_1164.all; 93 | use ieee.numeric_std.all; 94 | 95 | 96 | entity fifo is 97 | generic ( 98 | DEPTH : positive := 16; 99 | WIDTH : positive := 16 100 | ); 101 | port ( 102 | rst_n_i : in std_logic; 103 | clk_i : in std_logic; 104 | -- write 105 | wen_i : in std_logic; 106 | din_i : in std_logic_vector(WIDTH-1 downto 0); 107 | full_o : out std_logic; 108 | werror_o : out std_logic; 109 | -- read 110 | ren_i : in std_logic; 111 | dout_o : out std_logic_vector(WIDTH-1 downto 0); 112 | empty_o : out std_logic; 113 | rerror_o : out std_logic 114 | ); 115 | end entity fifo; 116 | 117 | 118 | architecture rtl of fifo is 119 | 120 | subtype t_fifo_pnt is natural range 0 to DEPTH-1; 121 | signal s_write_pnt : t_fifo_pnt; 122 | signal s_read_pnt : t_fifo_pnt; 123 | 124 | type t_fifo_mem is array (t_fifo_pnt'low to t_fifo_pnt'high) of std_logic_vector(din_i'range); 125 | signal s_fifo_mem : t_fifo_mem; 126 | 127 | signal s_almost_full : boolean; 128 | signal s_almost_empty : boolean; 129 | 130 | function incr_pnt (data : t_fifo_pnt) return t_fifo_pnt is 131 | begin 132 | if (data = t_fifo_mem'high) then 133 | return 0; 134 | end if; 135 | return data + 1; 136 | end function incr_pnt; 137 | 138 | begin 139 | 140 | s_almost_full <= (s_write_pnt = s_read_pnt - 1) or 141 | (s_write_pnt = t_fifo_mem'high and s_read_pnt = t_fifo_mem'low); 142 | 143 | s_almost_empty <= (s_read_pnt = s_write_pnt - 1) or 144 | (s_read_pnt = t_fifo_mem'high and s_write_pnt = t_fifo_mem'low); 145 | 146 | WriteP : process (rst_n_i, clk_i) is 147 | begin 148 | if (not rst_n_i) then 149 | s_write_pnt <= 0; 150 | werror_o <= '0'; 151 | elsif (rising_edge(clk_i)) then 152 | werror_o <= Wen_i and Full_o; 153 | if (Wen_i = '1' and Full_o = '0') then 154 | s_fifo_mem(s_write_pnt) <= Din_i; 155 | s_write_pnt <= incr_pnt(s_write_pnt); 156 | end if; 157 | end if; 158 | end process WriteP; 159 | 160 | ReadP : process (rst_n_i, clk_i) is 161 | begin 162 | if (not rst_n_i) then 163 | s_read_pnt <= 0; 164 | rerror_o <= '0'; 165 | elsif (rising_edge(clk_i)) then 166 | rerror_o <= Ren_i and Empty_o; 167 | if (Ren_i = '1' and Empty_o = '0') then 168 | Dout_o <= s_fifo_mem(s_read_pnt); 169 | s_read_pnt <= incr_pnt(s_read_pnt); 170 | end if; 171 | end if; 172 | end process ReadP; 173 | 174 | FlagsP : process (rst_n_i, clk_i) is 175 | begin 176 | if (rst_n_i = '0') then 177 | Full_o <= '0'; 178 | Empty_o <= '1'; 179 | elsif (rising_edge(clk_i)) then 180 | if (Wen_i = '1') then 181 | if (Ren_i = '0' and s_almost_full) then 182 | Full_o <= '1'; 183 | end if; 184 | Empty_o <= '0'; 185 | end if; 186 | if (Ren_i = '1') then 187 | if (Wen_i = '0' and s_almost_empty) then 188 | Empty_o <= '1'; 189 | end if; 190 | Full_o <= '0'; 191 | end if; 192 | end if; 193 | end process FlagsP; 194 | 195 | end architecture; 196 | 197 | 198 | -- Synchronous AXI stream FIFO based on generic fifo 199 | -- component. Configurable depth and width. 200 | 201 | 202 | library ieee ; 203 | use ieee.std_logic_1164.all; 204 | 205 | library gatemate; 206 | use gatemate.components.all; 207 | 208 | 209 | entity axis_fifo is 210 | generic ( 211 | DEPTH : positive := 8; 212 | WIDTH : positive := 8 213 | ); 214 | port ( 215 | -- global 216 | rst_n_i : in std_logic; 217 | clk_i : in std_logic; 218 | -- axis in 219 | tdata_i : in std_logic_vector(WIDTH-1 downto 0); 220 | tvalid_i : in std_logic; 221 | tready_o : out std_logic; 222 | -- axis aout 223 | tdata_o : out std_logic_vector(WIDTH-1 downto 0); 224 | tvalid_o : out std_logic; 225 | tready_i : in std_logic 226 | ); 227 | end entity; 228 | 229 | 230 | architecture rtl of axis_fifo is 231 | 232 | signal s_fifo_wen : std_logic; 233 | signal s_fifo_ren : std_logic; 234 | signal s_fifo_empty : std_logic; 235 | signal s_fifo_full : std_logic; 236 | signal s_fwft_empty : std_logic; 237 | signal s_ren : std_logic; 238 | 239 | begin 240 | 241 | fifo : entity work.fifo 242 | generic map ( 243 | DEPTH => DEPTH, 244 | WIDTH => WIDTH 245 | ) 246 | port map ( 247 | rst_n_i => rst_n_i, 248 | clk_i => clk_i, 249 | -- write 250 | wen_i => s_fifo_wen, 251 | din_i => tdata_i, 252 | full_o => s_fifo_full, 253 | werror_o => open, 254 | -- read 255 | ren_i => s_fifo_ren, 256 | dout_o => tdata_o, 257 | empty_o => s_fifo_empty, 258 | rerror_o => open 259 | ); 260 | 261 | -- FWFT logic 262 | process (clk_i, rst_n_i) is 263 | begin 264 | if (not rst_n_i) then 265 | s_fwft_empty <= '1'; 266 | elsif (rising_edge(clk_i)) then 267 | if (s_fifo_ren) then 268 | s_fwft_empty <= '0'; 269 | elsif (s_ren) then 270 | s_fwft_empty <= '1'; 271 | end if; 272 | end if; 273 | end process; 274 | 275 | s_fifo_ren <= not s_fifo_empty and (s_fwft_empty or s_ren); 276 | 277 | -- AXIS logic 278 | s_fifo_wen <= tvalid_i and not s_fifo_full; 279 | s_ren <= tready_i and not s_fwft_empty; 280 | 281 | tready_o <= not s_fifo_full; 282 | 283 | tvalid_o <= not s_fwft_empty; 284 | end architecture; 285 | 286 | 287 | -- Synchronous AXI stream FIFO based on GateMate CC_FIFO_40K 288 | -- primitive 289 | 290 | 291 | library ieee ; 292 | use ieee.std_logic_1164.all; 293 | 294 | library gatemate; 295 | use gatemate.components.all; 296 | 297 | 298 | entity axis_fifo_gm is 299 | generic ( 300 | WIDTH : positive := 8 301 | ); 302 | port ( 303 | -- global 304 | rst_n_i : in std_logic; 305 | clk_i : in std_logic; 306 | -- axis in 307 | tdata_i : in std_logic_vector(WIDTH-1 downto 0); 308 | tvalid_i : in std_logic; 309 | tready_o : out std_logic; 310 | -- axis aout 311 | tdata_o : out std_logic_vector(WIDTH-1 downto 0); 312 | tvalid_o : out std_logic; 313 | tready_i : in std_logic 314 | ); 315 | end entity; 316 | 317 | 318 | architecture rtl of axis_fifo_gm is 319 | 320 | signal s_fifo_wen : std_logic; 321 | signal s_fifo_ren : std_logic; 322 | signal s_fifo_empty : std_logic; 323 | signal s_fifo_full : std_logic; 324 | signal s_fwft_empty : std_logic; 325 | signal s_ren : std_logic; 326 | 327 | signal s_fifo_a_en : std_logic; 328 | signal s_fifo_b_en : std_logic; 329 | signal s_fifo_b_we : std_logic; 330 | 331 | signal s_fifo_din : std_logic_vector(79 downto 0); 332 | signal s_fifo_dout : std_logic_vector(79 downto 0); 333 | 334 | begin 335 | 336 | -- CC_FIFO_40K instance (512x80) 337 | fifo : CC_FIFO_40K 338 | generic map ( 339 | LOC => "UNPLACED", 340 | ALMOST_FULL_OFFSET => (others => '0'), 341 | ALMOST_EMPTY_OFFSET => (others => '0'), 342 | A_WIDTH => WIDTH, -- 1..80 343 | B_WIDTH => WIDTH, -- 1..80 344 | RAM_MODE => "SDP", 345 | FIFO_MODE => "SYNC", 346 | A_CLK_INV => '0', 347 | B_CLK_INV => '0', 348 | A_EN_INV => '0', 349 | B_EN_INV => '0', 350 | A_WE_INV => '0', 351 | B_WE_INV => '0', 352 | A_DO_REG => '0', 353 | B_DO_REG => '0', 354 | A_ECC_EN => '0', 355 | B_ECC_EN => '0' 356 | ) 357 | port map( 358 | A_ECC_1B_ERR => open, 359 | B_ECC_1B_ERR => open, 360 | A_ECC_2B_ERR => open, 361 | B_ECC_2B_ERR => open, 362 | -- FIFO pop port 363 | A_DO => s_fifo_dout(39 downto 0), 364 | B_DO => s_fifo_dout(79 downto 40), 365 | 366 | A_CLK => clk_i, 367 | A_EN => s_fifo_a_en, 368 | -- FIFO push port 369 | A_DI => s_fifo_din(39 downto 0), 370 | B_DI => s_fifo_din(79 downto 40), 371 | A_BM => (others => '1'), 372 | B_BM => (others => '1'), 373 | 374 | B_CLK => clk_i, 375 | B_EN => s_fifo_b_en, 376 | B_WE => s_fifo_b_we, 377 | -- FIFO control 378 | F_RST_N => rst_n_i, 379 | F_ALMOST_FULL_OFFSET => (others => '0'), 380 | F_ALMOST_EMPTY_OFFSET => (others => '0'), 381 | -- FIFO status signals 382 | F_FULL => s_fifo_full, 383 | F_EMPTY => s_fifo_empty, 384 | F_ALMOST_FULL => open, 385 | F_ALMOST_EMPTY => open, 386 | F_RD_ERROR => open, 387 | F_WR_ERROR => open, 388 | F_RD_PTR => open, 389 | F_WR_PTR => open 390 | ); 391 | 392 | s_fifo_b_en <= s_fifo_wen; 393 | s_fifo_b_we <= s_fifo_wen; 394 | s_fifo_a_en <= s_fifo_ren; 395 | 396 | -- FWFT logic 397 | process (clk_i, rst_n_i) is 398 | begin 399 | if (not rst_n_i) then 400 | s_fwft_empty <= '1'; 401 | elsif (rising_edge(clk_i)) then 402 | if (s_fifo_ren) then 403 | s_fwft_empty <= '0'; 404 | elsif (s_ren) then 405 | s_fwft_empty <= '1'; 406 | end if; 407 | end if; 408 | end process; 409 | 410 | s_fifo_ren <= not s_fifo_empty and (s_fwft_empty or s_ren); 411 | 412 | -- AXIS logic 413 | s_fifo_wen <= tvalid_i and not s_fifo_full; 414 | s_ren <= tready_i and not s_fwft_empty; 415 | 416 | tready_o <= not s_fifo_full; 417 | s_fifo_din(tdata_i'range) <= tdata_i; 418 | 419 | tvalid_o <= not s_fwft_empty; 420 | tdata_o <= s_fifo_dout(tdata_o'range); 421 | 422 | end architecture; 423 | -------------------------------------------------------------------------------- /neorv32_aes/rtl/neorv32_aes.vhd: -------------------------------------------------------------------------------- 1 | -- ################################################################################################# 2 | -- # << NEORV32 - Example setup including the bootloader, for the Gatemate (c) Eval Board >> # 3 | -- # ********************************************************************************************* # 4 | -- # BSD 3-Clause License # 5 | -- # # 6 | -- # Copyright (c) 2022, Torsten Meissner. All rights reserved. # 7 | -- # # 8 | -- # Redistribution and use in source and binary forms, with or without modification, are # 9 | -- # permitted provided that the following conditions are met: # 10 | -- # # 11 | -- # 1. Redistributions of source code must retain the above copyright notice, this list of # 12 | -- # conditions and the following disclaimer. # 13 | -- # # 14 | -- # 2. Redistributions in binary form must reproduce the above copyright notice, this list of # 15 | -- # conditions and the following disclaimer in the documentation and/or other materials # 16 | -- # provided with the distribution. # 17 | -- # # 18 | -- # 3. Neither the name of the copyright holder nor the names of its contributors may be used to # 19 | -- # endorse or promote products derived from this software without specific prior written # 20 | -- # permission. # 21 | -- # # 22 | -- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS # 23 | -- # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF # 24 | -- # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # 25 | -- # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, # 26 | -- # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE # 27 | -- # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED # 28 | -- # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING # 29 | -- # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED # 30 | -- # OF THE POSSIBILITY OF SUCH DAMAGE. # 31 | -- # ********************************************************************************************* # 32 | -- # The NEORV32 Processor - https://github.com/stnolting/neorv32 (c) Stephan Nolting # 33 | -- ################################################################################################# 34 | 35 | library ieee; 36 | use ieee.std_logic_1164.all; 37 | use ieee.numeric_std.all; 38 | 39 | library neorv32; 40 | use neorv32.neorv32_package.all; 41 | 42 | library gatemate; 43 | use gatemate.components.all; 44 | 45 | 46 | entity neorv32_aes is 47 | port ( 48 | -- Clock and Reset inputs 49 | clk_i : in std_logic; -- 10 MHz clock 50 | rst_n_i : in std_logic; -- SW3 button 51 | -- LED outputs 52 | led_n_o : out std_logic_vector(7 downto 0); 53 | -- UART0 54 | uart_rx_i : in std_logic; -- PMODA IO 55 | uart_tx_o : out std_logic; -- PMODA IO 56 | debug_o : out std_logic_vector(15 downto 0) 57 | ); 58 | end entity; 59 | 60 | architecture rtl of neorv32_aes is 61 | 62 | -- configuration -- 63 | constant f_clock_c : natural := 10_000_000; -- clock frequency in Hz 64 | 65 | -- Globals 66 | signal s_pll_lock : std_logic; 67 | signal s_pll_clk : std_logic; 68 | signal s_cfg_end : std_logic; 69 | 70 | signal s_rst_n : std_logic; 71 | signal s_rst_debounced : std_logic; 72 | 73 | signal s_con_gpio : std_ulogic_vector(63 downto 0); 74 | 75 | signal s_debug : std_logic_vector(63 downto 0); 76 | 77 | begin 78 | 79 | PLL : CC_PLL 80 | generic map ( 81 | REF_CLK => "10", 82 | OUT_CLK => "10", 83 | PERF_MD => "SPEED" 84 | ) 85 | port map ( 86 | CLK_REF => clk_i, 87 | USR_CLK_REF => '0', 88 | CLK_FEEDBACK => '0', 89 | USR_LOCKED_STDY_RST => '0', 90 | USR_PLL_LOCKED_STDY => open, 91 | USR_PLL_LOCKED => s_pll_lock, 92 | CLK0 => s_pll_clk, 93 | CLK90 => open, 94 | CLK180 => open, 95 | CLK270 => open, 96 | CLK_REF_OUT => open 97 | ); 98 | 99 | cfg_end : CC_CFG_END 100 | port map ( 101 | CFG_END => s_cfg_end 102 | ); 103 | 104 | rst_debounce : block is 105 | signal s_rst_d : std_logic_vector(29 downto 0); 106 | begin 107 | process (s_pll_clk, rst_n_i) is 108 | begin 109 | if (not rst_n_i) then 110 | s_rst_d <= (others => '0'); 111 | elsif (rising_edge(s_pll_clk)) then 112 | s_rst_d <= s_rst_d(s_rst_d'left-1 downto 0) & rst_n_i; 113 | end if; 114 | end process; 115 | s_rst_debounced <= and s_rst_d; 116 | end block rst_debounce; 117 | 118 | s_rst_n <= s_pll_lock and s_cfg_end and s_rst_debounced; 119 | 120 | -- The core of the problem ---------------------------------------------------------------- 121 | -- ------------------------------------------------------------------------------------------- 122 | neorv32_inst: entity neorv32.neorv32_top 123 | generic map ( 124 | CLOCK_FREQUENCY => f_clock_c, -- clock frequency of s_pll_clk in Hz 125 | INT_BOOTLOADER_EN => false, -- boot configuration: true = boot explicit bootloader; false = boot from int/ext (I)MEM 126 | -- RISC-V CPU Extensions -- 127 | CPU_EXTENSION_RISCV_C => false, -- implement compressed extension? 128 | CPU_EXTENSION_RISCV_M => true, -- implement mul/div extension? 129 | CPU_EXTENSION_RISCV_Zicsr => true, -- implement CSR system? 130 | CPU_EXTENSION_RISCV_Zicntr => true, -- implement base counters? 131 | -- Tuning Options -- 132 | FAST_MUL_EN => false, 133 | FAST_SHIFT_EN => false, 134 | -- Internal Instruction memory -- 135 | MEM_INT_IMEM_EN => true, -- implement processor-internal instruction memory 136 | MEM_INT_IMEM_SIZE => 4*1024, --16*1024, -- size of processor-internal instruction memory in bytes 137 | -- Internal Data memory -- 138 | MEM_INT_DMEM_EN => true, -- implement processor-internal data memory 139 | MEM_INT_DMEM_SIZE => 8*1024, -- size of processor-internal data memory in bytes 140 | -- Processor peripherals -- 141 | IO_GPIO_EN => true, -- implement general purpose input/output port unit (GPIO)? 142 | IO_MTIME_EN => true, -- implement machine system timer (MTIME)? 143 | IO_UART0_EN => true, -- implement primary universal asynchronous receiver/transmitter (UART0)? 144 | IO_CFS_EN => true -- implement custom functions subsystem (CFS, AES-CTR)? 145 | ) 146 | port map ( 147 | -- Global control -- 148 | clk_i => std_ulogic(s_pll_clk), 149 | rstn_i => std_ulogic(s_rst_n), 150 | -- GPIO 151 | gpio_o => s_con_gpio, 152 | -- primary UART0 153 | uart0_txd_o => uart_tx_o, 154 | uart0_rxd_i => uart_rx_i 155 | ); 156 | 157 | debug_o <= s_debug(15 downto 0); 158 | 159 | -- p_r ERROR when connecting uart_rx_i & yosys option -retime (with both Yosys inferred & instantiated CC_BRAM_40K or CC_BRAM_40K memory) 160 | -- FATAL ERROR: RAM 4070 Output DOA[6] not used but Input DIA[6] used! 161 | -- program finished with exit code: 2 162 | 163 | -- IO Connection -------------------------------------------------------------------------- 164 | led_n_o <= not std_logic_vector(s_con_gpio(7 downto 0)); 165 | 166 | end architecture; 167 | -------------------------------------------------------------------------------- /neorv32_aes/sim/Makefile: -------------------------------------------------------------------------------- 1 | DESIGN_NAME := neorv32_aes 2 | 3 | NEORV32_CORE_DIR := ../../neorv32/rtl/core 4 | NEORV32_PKG := $(NEORV32_CORE_DIR)/neorv32_package.vhd 5 | NEORV32_APP_SRC := $(NEORV32_CORE_DIR)/neorv32_application_image.vhd 6 | NEORV32_TEMPLATES := ../../neorv32/rtl/processor_templates 7 | 8 | NEORV32_MEM_ENTITIES := \ 9 | $(NEORV32_CORE_DIR)/neorv32_dmem.entity.vhd \ 10 | $(NEORV32_CORE_DIR)/neorv32_imem.entity.vhd 11 | 12 | NEORV32_MEM_SRC := \ 13 | $(NEORV32_CORE_DIR)/mem/neorv32_imem.default.vhd \ 14 | $(NEORV32_CORE_DIR)/mem/neorv32_dmem.default.vhd 15 | 16 | NEORV32_CORE_SRC := \ 17 | $(NEORV32_CORE_DIR)/neorv32_bootloader_image.vhd \ 18 | $(NEORV32_CORE_DIR)/neorv32_boot_rom.vhd \ 19 | $(NEORV32_CORE_DIR)/neorv32_bus_keeper.vhd \ 20 | $(NEORV32_CORE_DIR)/neorv32_busswitch.vhd \ 21 | $(NEORV32_CORE_DIR)/neorv32_cpu.vhd \ 22 | $(NEORV32_CORE_DIR)/neorv32_cpu_alu.vhd \ 23 | $(NEORV32_CORE_DIR)/neorv32_cpu_bus.vhd \ 24 | $(NEORV32_CORE_DIR)/neorv32_cpu_control.vhd \ 25 | $(NEORV32_CORE_DIR)/neorv32_cpu_cp_bitmanip.vhd \ 26 | $(NEORV32_CORE_DIR)/neorv32_cpu_cp_cfu.vhd \ 27 | $(NEORV32_CORE_DIR)/neorv32_cpu_cp_fpu.vhd \ 28 | $(NEORV32_CORE_DIR)/neorv32_cpu_cp_muldiv.vhd \ 29 | $(NEORV32_CORE_DIR)/neorv32_cpu_cp_shifter.vhd \ 30 | $(NEORV32_CORE_DIR)/neorv32_cpu_decompressor.vhd \ 31 | $(NEORV32_CORE_DIR)/neorv32_cpu_regfile.vhd \ 32 | $(NEORV32_CORE_DIR)/neorv32_debug_dm.vhd \ 33 | $(NEORV32_CORE_DIR)/neorv32_debug_dtm.vhd \ 34 | $(NEORV32_CORE_DIR)/neorv32_fifo.vhd \ 35 | $(NEORV32_CORE_DIR)/neorv32_gpio.vhd \ 36 | $(NEORV32_CORE_DIR)/neorv32_gptmr.vhd \ 37 | $(NEORV32_CORE_DIR)/neorv32_icache.vhd \ 38 | $(NEORV32_CORE_DIR)/neorv32_mtime.vhd \ 39 | $(NEORV32_CORE_DIR)/neorv32_neoled.vhd \ 40 | $(NEORV32_CORE_DIR)/neorv32_onewire.vhd \ 41 | $(NEORV32_CORE_DIR)/neorv32_pwm.vhd \ 42 | $(NEORV32_CORE_DIR)/neorv32_slink.vhd \ 43 | $(NEORV32_CORE_DIR)/neorv32_spi.vhd \ 44 | $(NEORV32_CORE_DIR)/neorv32_sysinfo.vhd \ 45 | $(NEORV32_CORE_DIR)/neorv32_trng.vhd \ 46 | $(NEORV32_CORE_DIR)/neorv32_twi.vhd \ 47 | $(NEORV32_CORE_DIR)/neorv32_uart.vhd \ 48 | $(NEORV32_CORE_DIR)/neorv32_wdt.vhd \ 49 | $(NEORV32_CORE_DIR)/neorv32_wishbone.vhd \ 50 | $(NEORV32_CORE_DIR)/neorv32_xip.vhd \ 51 | $(NEORV32_CORE_DIR)/neorv32_xirq.vhd \ 52 | $(NEORV32_CORE_DIR)/neorv32_cfs.vhd \ 53 | $(NEORV32_CORE_DIR)/neorv32_cfs_aes.vhd \ 54 | $(NEORV32_CORE_DIR)/neorv32_top.vhd 55 | 56 | NEORV32_SRC := ${NEORV32_PKG} ${NEORV32_APP_SRC} ${NEORV32_MEM_ENTITIES} \ 57 | ${NEORV32_MEM_SRC} ${NEORV32_CORE_SRC} 58 | 59 | AES_DIR := ../../cryptocores/aes/rtl/vhdl 60 | CRYPTO_SRC := \ 61 | $(AES_DIR)/aes_pkg.vhd \ 62 | $(AES_DIR)/aes_enc.vhd \ 63 | $(AES_DIR)/aes_dec.vhd \ 64 | $(AES_DIR)/aes.vhd \ 65 | $(AES_DIR)/../../../ctraes/rtl/vhdl/ctraes.vhd 66 | 67 | 68 | WORK_FILES := ../rtl/${DESIGN_NAME}.vhd tb_${DESIGN_NAME}.vhd 69 | GM_FILES := ../../lib/rtl_components.vhd ../../lib/sim_components.vhd 70 | 71 | SIM_FLAGS := --std=08 -fpsl --workdir=work -Pwork 72 | 73 | .PHONY: all compile sim clean 74 | 75 | all: sim 76 | compile: tb_${DESIGN_NAME} 77 | 78 | 79 | work/work-obj08.cf: ${WORK_FILES} work/gatemate-obj08.cf work/neorv32-obj08.cf 80 | mkdir -p work 81 | ghdl -a ${SIM_FLAGS} --work=work ${WORK_FILES} 82 | 83 | work/neorv32-obj08.cf: work/gatemate-obj08.cf work/cryptocores-obj08.cf ${NEORV32_SRC} 84 | mkdir -p work 85 | ghdl -a $(SIM_FLAGS) --work=neorv32 ${NEORV32_SRC} 86 | 87 | work/cryptocores-obj08.cf: ${CRYPTO_SRC} 88 | mkdir -p work 89 | ghdl -a $(SIM_FLAGS) --work=cryptocores ${CRYPTO_SRC} 90 | 91 | work/gatemate-obj08.cf: ${GM_FILES} 92 | mkdir -p work 93 | ghdl -a ${SIM_FLAGS} --work=gatemate ${GM_FILES} 94 | 95 | tb_${DESIGN_NAME}: work/gatemate-obj08.cf work/cryptocores-obj08.cf work/neorv32-obj08.cf work/work-obj08.cf 96 | @echo "Elaborate testbench & design ..." 97 | ghdl -e ${SIM_FLAGS} -Pwork $@ 98 | 99 | sim: tb_${DESIGN_NAME} 100 | @echo "Run testbench ..." 101 | ghdl -r ${SIM_FLAGS} -Pwork tb_${DESIGN_NAME} --assert-level=error --ieee-asserts=disable --wave=tb_${DESIGN_NAME}.ghw 102 | 103 | work: 104 | mkdir $@ 105 | 106 | clean: 107 | @echo "Cleaning simulation files ..." 108 | rm -rf tb_${DESIGN_NAME} tb_${DESIGN_NAME}.ghw *.o work/ 109 | -------------------------------------------------------------------------------- /neorv32_aes/sim/tb_neorv32_aes.vhd: -------------------------------------------------------------------------------- 1 | library ieee ; 2 | use ieee.std_logic_1164.all; 3 | use ieee.numeric_std.all; 4 | 5 | use std.env.all; 6 | 7 | 8 | entity tb_neorv32_aes is 9 | end entity tb_neorv32_aes; 10 | 11 | 12 | architecture sim of tb_neorv32_aes is 13 | 14 | constant c_baudrate : natural := 9600; 15 | constant c_period_ns : time := 1000000000 / c_baudrate * ns; 16 | 17 | procedure uart_send ( data : in std_logic_vector(7 downto 0); 18 | signal tx : out std_logic) is 19 | begin 20 | report "UART send: 0x" & to_hstring(data); 21 | tx <= '0'; 22 | wait for c_period_ns; 23 | for i in 0 to 7 loop 24 | tx <= data(i); 25 | wait for c_period_ns; 26 | end loop; 27 | tx <= '1'; 28 | wait for c_period_ns; 29 | end procedure; 30 | 31 | procedure uart_recv ( data : out std_logic_vector(7 downto 0); 32 | signal rx : in std_logic) is 33 | begin 34 | wait until not rx; 35 | wait for c_period_ns; -- Skip start bit 36 | wait for c_period_ns/2; 37 | for i in 0 to 7 loop 38 | data(i) := rx; 39 | wait for c_period_ns; 40 | end loop; 41 | report "UART recv: 0x" & to_hstring(data); 42 | end procedure; 43 | 44 | signal s_clk : std_logic := '1'; 45 | signal s_rst_n : std_logic := '0'; 46 | 47 | signal s_len_n : std_logic_vector(7 downto 0); 48 | signal s_debug : std_logic_vector(15 downto 0); 49 | 50 | begin 51 | 52 | dut : entity work.neorv32_aes 53 | port map ( 54 | clk_i => s_clk, 55 | rst_n_i => s_rst_n, 56 | -- 57 | led_n_o => s_len_n, 58 | --uart_tx_o => s_uart_tx 59 | --uart_rx_i => s_uart_rx 60 | debug_o => s_debug 61 | ); 62 | 63 | s_rst_n <= '1' after 120 ns; 64 | s_clk <= not s_clk after 50 ns; 65 | 66 | process is 67 | begin 68 | wait for 2 ms; 69 | stop(0); 70 | end process; 71 | 72 | 73 | end architecture; 74 | -------------------------------------------------------------------------------- /neorv32_aes/syn/Makefile: -------------------------------------------------------------------------------- 1 | DESIGN_NAME := neorv32_aes 2 | 3 | NEORV32_CORE_DIR := ../../neorv32/rtl/core 4 | NEORV32_PKG := $(NEORV32_CORE_DIR)/neorv32_package.vhd 5 | NEORV32_APP_SRC := $(NEORV32_CORE_DIR)/neorv32_application_image.vhd 6 | NEORV32_TEMPLATES := ../../neorv32/rtl/processor_templates 7 | 8 | NEORV32_MEM_ENTITIES := \ 9 | $(NEORV32_CORE_DIR)/neorv32_dmem.entity.vhd \ 10 | $(NEORV32_CORE_DIR)/neorv32_imem.entity.vhd 11 | 12 | NEORV32_MEM_SRC := \ 13 | $(NEORV32_CORE_DIR)/mem/neorv32_imem.default.vhd \ 14 | $(NEORV32_CORE_DIR)/mem/neorv32_dmem.gatemate.vhd 15 | 16 | NEORV32_CORE_SRC := \ 17 | $(NEORV32_CORE_DIR)/neorv32_bootloader_image.vhd \ 18 | $(NEORV32_CORE_DIR)/neorv32_boot_rom.vhd \ 19 | $(NEORV32_CORE_DIR)/neorv32_bus_keeper.vhd \ 20 | $(NEORV32_CORE_DIR)/neorv32_busswitch.vhd \ 21 | $(NEORV32_CORE_DIR)/neorv32_cpu.vhd \ 22 | $(NEORV32_CORE_DIR)/neorv32_cpu_alu.vhd \ 23 | $(NEORV32_CORE_DIR)/neorv32_cpu_bus.vhd \ 24 | $(NEORV32_CORE_DIR)/neorv32_cpu_control.vhd \ 25 | $(NEORV32_CORE_DIR)/neorv32_cpu_cp_bitmanip.vhd \ 26 | $(NEORV32_CORE_DIR)/neorv32_cpu_cp_cfu.vhd \ 27 | $(NEORV32_CORE_DIR)/neorv32_cpu_cp_fpu.vhd \ 28 | $(NEORV32_CORE_DIR)/neorv32_cpu_cp_muldiv.vhd \ 29 | $(NEORV32_CORE_DIR)/neorv32_cpu_cp_shifter.vhd \ 30 | $(NEORV32_CORE_DIR)/neorv32_cpu_decompressor.vhd \ 31 | $(NEORV32_CORE_DIR)/neorv32_cpu_regfile.vhd \ 32 | $(NEORV32_CORE_DIR)/neorv32_debug_dm.vhd \ 33 | $(NEORV32_CORE_DIR)/neorv32_debug_dtm.vhd \ 34 | $(NEORV32_CORE_DIR)/neorv32_fifo.vhd \ 35 | $(NEORV32_CORE_DIR)/neorv32_gpio.vhd \ 36 | $(NEORV32_CORE_DIR)/neorv32_gptmr.vhd \ 37 | $(NEORV32_CORE_DIR)/neorv32_icache.vhd \ 38 | $(NEORV32_CORE_DIR)/neorv32_mtime.vhd \ 39 | $(NEORV32_CORE_DIR)/neorv32_neoled.vhd \ 40 | $(NEORV32_CORE_DIR)/neorv32_onewire.vhd \ 41 | $(NEORV32_CORE_DIR)/neorv32_pwm.vhd \ 42 | $(NEORV32_CORE_DIR)/neorv32_slink.vhd \ 43 | $(NEORV32_CORE_DIR)/neorv32_spi.vhd \ 44 | $(NEORV32_CORE_DIR)/neorv32_sysinfo.vhd \ 45 | $(NEORV32_CORE_DIR)/neorv32_trng.vhd \ 46 | $(NEORV32_CORE_DIR)/neorv32_twi.vhd \ 47 | $(NEORV32_CORE_DIR)/neorv32_uart.vhd \ 48 | $(NEORV32_CORE_DIR)/neorv32_wdt.vhd \ 49 | $(NEORV32_CORE_DIR)/neorv32_wishbone.vhd \ 50 | $(NEORV32_CORE_DIR)/neorv32_xip.vhd \ 51 | $(NEORV32_CORE_DIR)/neorv32_xirq.vhd \ 52 | $(NEORV32_CORE_DIR)/neorv32_cfs.vhd \ 53 | $(NEORV32_CORE_DIR)/neorv32_cfs_aes.vhd \ 54 | $(NEORV32_CORE_DIR)/neorv32_top.vhd 55 | 56 | NEORV32_SRC := ${NEORV32_PKG} ${NEORV32_APP_SRC} ${NEORV32_MEM_ENTITIES} \ 57 | ${NEORV32_MEM_SRC} ${NEORV32_CORE_SRC} 58 | 59 | AES_DIR := ../../cryptocores/aes/rtl/vhdl 60 | CRYPTO_SRC := \ 61 | $(AES_DIR)/aes_pkg.vhd \ 62 | $(AES_DIR)/aes_enc.vhd \ 63 | $(AES_DIR)/aes_dec.vhd \ 64 | $(AES_DIR)/aes.vhd \ 65 | $(AES_DIR)/../../../ctraes/rtl/vhdl/ctraes.vhd 66 | 67 | 68 | WORK_FILES := ../rtl/${DESIGN_NAME}.vhd 69 | GM_FILES := ../../lib/rtl_components.vhd 70 | 71 | GHDL_FLAGS := --std=08 --workdir=build -Pbuild 72 | ICARUSFLAGS := -Wall -Winfloop -g2012 -gspecify -Ttyp 73 | 74 | YOSYSPIPE := -nomx8 -nobram 75 | PNRFLAGS := -om 3 -cCP on 76 | PNRTOOL := $(shell which p_r) 77 | 78 | .PHONY: all syn imp prog syn_sim imp_sim 79 | 80 | all: imp 81 | syn: ${DESIGN_NAME}.v 82 | imp: ${DESIGN_NAME}.bit 83 | 84 | build/work-obj08.cf: ${WORK_FILES} build/gatemate-obj08.cf build/neorv32-obj08.cf 85 | ghdl -a ${GHDL_FLAGS} --work=work ${WORK_FILES} 86 | 87 | build/neorv32-obj08.cf: build/gatemate-obj08.cf build/cryptocores-obj08.cf ${NEORV32_SRC} 88 | ghdl -a $(GHDL_FLAGS) --work=neorv32 ${NEORV32_SRC} 89 | 90 | build/cryptocores-obj08.cf: ${CRYPTO_SRC} 91 | ghdl -a $(GHDL_FLAGS) --work=cryptocores ${CRYPTO_SRC} 92 | 93 | build/gatemate-obj08.cf: ${GM_FILES} 94 | mkdir -p build 95 | ghdl -a ${GHDL_FLAGS} --work=gatemate ${GM_FILES} 96 | 97 | # Synthesis target for implementation 98 | ${DESIGN_NAME}.v: build/work-obj08.cf 99 | yosys -m ghdl -p 'ghdl ${GHDL_FLAGS} --warn-no-binding --no-formal ${DESIGN_NAME}; synth_gatemate -top $(DESIGN_NAME) ${YOSYSPIPE} -vlog $@' \ 100 | 2>&1 | tee build/yosys-report.txt 101 | 102 | # Implementation target for FPGA 103 | ${DESIGN_NAME}.bit: ${DESIGN_NAME}.v ${DESIGN_NAME}.ccf 104 | cd build && \ 105 | ${PNRTOOL} -i ../${DESIGN_NAME}.v -o $@ --ccf ../${DESIGN_NAME}.ccf $(PNRFLAGS) \ 106 | 2>&1 | tee p_r-report.txt && \ 107 | mv ${DESIGN_NAME}*.bit ../$@ 108 | 109 | # Post-synthesis simulation target 110 | syn_sim: ${DESIGN_NAME}.v 111 | iverilog ${ICARUSFLAGS} -o tb_${DESIGN_NAME}_syn.vvp ${DESIGN_NAME}.v tb_${DESIGN_NAME}.v /usr/local/share/yosys/gatemate/cells_sim.v 112 | vvp -N tb_${DESIGN_NAME}_syn.vvp -fst 113 | 114 | # Post-implementation simulation target 115 | imp_sim: ${DESIGN_NAME}.bit 116 | iverilog ${ICARUSFLAGS} -o tb_${DESIGN_NAME}_imp.vvp build/${DESIGN_NAME}_00.v tb_${DESIGN_NAME}.v /opt/cc-toolchain-linux/bin/p_r/cpelib.v 117 | vvp -N tb_${DESIGN_NAME}_imp.vvp -fst 118 | 119 | # FPGA FW load per JTAG 120 | prog: ${DESIGN_NAME}.bit 121 | openFPGALoader -b gatemate_evb_jtag $< 122 | 123 | clean : 124 | echo "# Cleaning files" 125 | rm -rf build ${DESIGN_NAME}.v ${DESIGN_NAME}_sim.v ${DESIGN_NAME}.vhd ${DESIGN_NAME}.bit *.vvp *.fst 126 | -------------------------------------------------------------------------------- /neorv32_aes/syn/neorv32_aes.ccf: -------------------------------------------------------------------------------- 1 | # Configuration for the Gatemate eval board 2 | 3 | Pin_in "clk_i" Loc = "IO_SB_A8" | SCHMITT_TRIGGER=true; 4 | Pin_in "rst_n_i" Loc = "IO_EB_B0"; # SW3 5 | 6 | Pin_out "led_n_o[0]" Loc = "IO_EB_B1"; # LED D1 7 | Pin_out "led_n_o[1]" Loc = "IO_EB_B2"; # LED D2 8 | Pin_out "led_n_o[2]" Loc = "IO_EB_B3"; # LED D3 9 | Pin_out "led_n_o[3]" Loc = "IO_EB_B4"; # LED D4 10 | Pin_out "led_n_o[4]" Loc = "IO_EB_B5"; # LED D5 11 | Pin_out "led_n_o[5]" Loc = "IO_EB_B6"; # LED D6 12 | Pin_out "led_n_o[6]" Loc = "IO_EB_B7"; # LED D7 13 | Pin_out "led_n_o[7]" Loc = "IO_EB_B8"; # LED D8 14 | 15 | #Pin_in "uart_rx_i" Loc = "IO_NB_A1"; # PMODA IO3 16 | #Pin_out "uart_tx_o" Loc = "IO_NB_A0"; # PMODA IO1 17 | # 18 | Pin_out "debug_o[0]" Loc = "IO_NB_A4"; 19 | Pin_out "debug_o[1]" Loc = "IO_NB_A5"; 20 | Pin_out "debug_o[2]" Loc = "IO_NB_A6"; 21 | Pin_out "debug_o[3]" Loc = "IO_NB_A7"; 22 | Pin_out "debug_o[4]" Loc = "IO_NB_B4"; 23 | Pin_out "debug_o[5]" Loc = "IO_NB_B5"; 24 | Pin_out "debug_o[6]" Loc = "IO_NB_B6"; 25 | Pin_out "debug_o[7]" Loc = "IO_NB_B7"; 26 | 27 | Pin_out "debug_o[8]" Loc = "IO_NB_A0"; 28 | Pin_out "debug_o[9]" Loc = "IO_NB_A1"; 29 | Pin_out "debug_o[10]" Loc = "IO_NB_A2"; 30 | Pin_out "debug_o[11]" Loc = "IO_NB_A3"; 31 | Pin_out "debug_o[12]" Loc = "IO_NB_B0"; 32 | Pin_out "debug_o[13]" Loc = "IO_NB_B1"; 33 | Pin_out "debug_o[14]" Loc = "IO_NB_B2"; 34 | Pin_out "debug_o[15]" Loc = "IO_NB_B3"; 35 | -------------------------------------------------------------------------------- /neorv32_aes/syn/tb_neorv32_aes.v: -------------------------------------------------------------------------------- 1 | `timescale 1 ns/10 ps // time-unit = 1 ns, precision = 10 ps 2 | 3 | `define USE_RAM 4 | 5 | // simplified CC_PLL model 6 | module CC_PLL #( 7 | parameter REF_CLK = "", // e.g. "10.0" 8 | parameter OUT_CLK = "", // e.g. "50.0" 9 | parameter PERF_MD = "", // LOWPOWER, ECONOMY, SPEED 10 | parameter LOW_JITTER = 1, 11 | parameter CI_FILTER_CONST = 2, 12 | parameter CP_FILTER_CONST = 4 13 | )( 14 | input CLK_REF, CLK_FEEDBACK, USR_CLK_REF, 15 | input USR_LOCKED_STDY_RST, USR_SET_SEL, 16 | output USR_PLL_LOCKED_STDY, USR_PLL_LOCKED, 17 | output CLK270, CLK180, CLK90, CLK0, CLK_REF_OUT 18 | ); 19 | 20 | reg r_pll_clk; 21 | reg r_user_pll_locked; 22 | 23 | // OUT_FREQ = 10 MHz 24 | localparam clk_half_period = 50; 25 | 26 | initial begin 27 | r_pll_clk = 1'b0; 28 | r_user_pll_locked = 1'b1; 29 | end 30 | 31 | always #clk_half_period r_pll_clk = ~r_pll_clk; 32 | 33 | assign CLK0 = r_pll_clk; 34 | assign USR_PLL_LOCKED = r_user_pll_locked; 35 | 36 | endmodule 37 | 38 | 39 | // simplified CC_CFG_END model 40 | module CC_CFG_END ( 41 | output CFG_END 42 | ); 43 | 44 | assign CFG_END = 1'b1; 45 | 46 | endmodule 47 | 48 | module tb_neorv32_aes; 49 | 50 | // DUT in/out 51 | reg clk = 1'b0; 52 | reg rst_n = 1'b1; 53 | wire [7:0] led; 54 | wire [63:0] debug; 55 | reg uart_rx; 56 | wire uart_tx; 57 | 58 | // Testbench variables 59 | 60 | // Testbench 1/2 clock period 61 | localparam clk_half_period = 50; 62 | 63 | // UART period calculation (9600 baud) 64 | localparam uart_bit_period = 1000000000 / 9600; 65 | localparam uart_bit_half_period = uart_bit_period/2; 66 | 67 | neorv32_aes UUT (.clk_i(clk), .rst_n_i(rst_n), .led_n_o(led), .debug_o(debug)); 68 | // neorv32_aes UUT (.clk_i(clk), .rst_n_i(rst_n), .led_n_o(led), .uart_tx_o(uart_tx), .uart_rx_i(uart_rx)); 69 | 70 | // set dumpfile 71 | initial begin 72 | $dumpfile ("tb_neorv32_aes.fst"); 73 | $dumpvars (0, tb_neorv32_aes); 74 | end 75 | 76 | // Setup simulation 77 | initial begin 78 | uart_rx = 1'b1; 79 | #1 rst_n = 1'b0; 80 | #120 rst_n = 1'b1; 81 | end 82 | 83 | // Generate 10 mhz clock 84 | always #clk_half_period clk = !clk; 85 | 86 | // Stimuli generator 87 | initial 88 | forever @(posedge rst_n) begin 89 | // Simulate for 100 us 90 | #500_000 91 | // @(negedge led[0]); 92 | // #100 93 | $display ("NEORV32 test finished"); 94 | $finish; 95 | end 96 | 97 | // Monitor 98 | initial begin 99 | $monitor("monitor time=%t ns, rst_n=%b, led=%b, imem.addr=%d, dmem.addr=%h", $time, rst_n, led, debug[31:2], debug[63:32]); 100 | end 101 | 102 | endmodule 103 | -------------------------------------------------------------------------------- /uart_aes/rtl/uart_aes.vhd: -------------------------------------------------------------------------------- 1 | -- This design implements a AES-CTR unit which which can 2 | -- be accessed by an UART with 9600 baud 3 | -- 4 | -- See into uart_ctrl.vhd for documentation of the protocol 5 | -- used to read / write the AES-CTR registers. 6 | 7 | 8 | library ieee ; 9 | use ieee.std_logic_1164.all; 10 | use ieee.numeric_std.all; 11 | 12 | library gatemate; 13 | use gatemate.components.all; 14 | 15 | library cryptocores; 16 | 17 | use work.uart_aes_types.all; 18 | 19 | 20 | entity uart_aes is 21 | port ( 22 | clk_i : in std_logic; -- 10 MHz clock 23 | rst_n_i : in std_logic; -- SW3 button 24 | uart_rx_i : in std_logic; -- PMODA IO3 25 | uart_tx_o : out std_logic; -- PMODA IO5 26 | led_n_o : out std_logic_vector(3 downto 0) 27 | ); 28 | end entity uart_aes; 29 | 30 | 31 | architecture rtl of uart_aes is 32 | 33 | signal s_pll_clk : std_logic; 34 | signal s_pll_lock : std_logic; 35 | 36 | signal s_rst_n : std_logic; 37 | signal s_usr_rstn : std_logic; 38 | 39 | signal s_uart_rx_tdata : std_logic_vector(7 downto 0); 40 | signal s_uart_rx_tvalid : std_logic; 41 | signal s_uart_rx_tready : std_logic; 42 | 43 | signal s_uart_tx_tdata : std_logic_vector(7 downto 0); 44 | signal s_uart_tx_tvalid : std_logic; 45 | signal s_uart_tx_tready : std_logic; 46 | 47 | signal s_ctrl_aes_m2s : t_axis_ctrl_aes_m2s; 48 | signal s_ctrl_aes_s2m : t_axis_s2m; 49 | signal s_aes_ctrl_m2s : t_axis_aes_ctrl_m2s; 50 | signal s_aes_ctrl_s2m : t_axis_s2m; 51 | 52 | begin 53 | 54 | pll : CC_PLL 55 | generic map ( 56 | REF_CLK => "10", 57 | OUT_CLK => "10", 58 | PERF_MD => "SPEED" 59 | ) 60 | port map ( 61 | CLK_REF => clk_i, 62 | CLK_FEEDBACK => '0', 63 | USR_CLK_REF => '0', 64 | USR_LOCKED_STDY_RST => '0', 65 | USR_PLL_LOCKED_STDY => open, 66 | USR_PLL_LOCKED => s_pll_lock, 67 | CLK270 => open, 68 | CLK180 => open, 69 | CLK0 => s_pll_clk, 70 | CLK90 => open, 71 | CLK_REF_OUT => open 72 | ); 73 | 74 | cc_usr_rstn_inst : CC_USR_RSTN 75 | port map ( 76 | USR_RSTN => s_usr_rstn 77 | ); 78 | 79 | uart_rx : entity work.uart_rx 80 | generic map ( 81 | CLK_DIV => 1040 82 | ) 83 | port map ( 84 | -- globals 85 | rst_n_i => s_rst_n, 86 | clk_i => s_pll_clk, 87 | -- axis user interface 88 | tdata_o => s_uart_rx_tdata, 89 | tvalid_o => s_uart_rx_tvalid, 90 | tready_i => s_uart_rx_tready, 91 | -- uart interface 92 | rx_i => uart_rx_i 93 | ); 94 | 95 | uart_ctrl : entity work.uart_ctrl 96 | port map ( 97 | -- globals 98 | rst_n_i => s_rst_n, 99 | clk_i => s_pll_clk, 100 | -- uart rx interface 101 | tdata_i => s_uart_rx_tdata, 102 | tvalid_i => s_uart_rx_tvalid, 103 | tready_o => s_uart_rx_tready, 104 | -- uart tx interface 105 | tdata_o => s_uart_tx_tdata, 106 | tvalid_o => s_uart_tx_tvalid, 107 | tready_i => s_uart_tx_tready, 108 | -- aes out 109 | ctrl_aes_o => s_ctrl_aes_m2s, 110 | ctrl_aes_i => s_ctrl_aes_s2m, 111 | -- aes in 112 | aes_ctrl_i => s_aes_ctrl_m2s, 113 | aes_ctrl_o => s_aes_ctrl_s2m 114 | ); 115 | 116 | aes_inst : entity cryptocores.ctraes 117 | port map ( 118 | reset_i => s_rst_n, 119 | clk_i => s_pll_clk, 120 | start_i => s_ctrl_aes_m2s.tuser.start, 121 | nonce_i => s_ctrl_aes_m2s.tuser.nonce, 122 | key_i => s_ctrl_aes_m2s.tuser.key, 123 | data_i => s_ctrl_aes_m2s.tdata, 124 | valid_i => s_ctrl_aes_m2s.tvalid, 125 | accept_o => s_ctrl_aes_s2m.tready, 126 | data_o => s_aes_ctrl_m2s.tdata, 127 | valid_o => s_aes_ctrl_m2s.tvalid, 128 | accept_i => s_aes_ctrl_s2m.tready 129 | ); 130 | 131 | uart_tx : entity work.uart_tx 132 | generic map ( 133 | CLK_DIV => 1040 134 | ) 135 | port map ( 136 | -- globals 137 | rst_n_i => s_rst_n, 138 | clk_i => s_pll_clk, 139 | -- axis user interface 140 | tdata_i => s_uart_tx_tdata, 141 | tvalid_i => s_uart_tx_tvalid, 142 | tready_o => s_uart_tx_tready, 143 | -- uart interface 144 | tx_o => uart_tx_o 145 | ); 146 | 147 | s_rst_n <= rst_n_i and s_pll_lock and s_usr_rstn; 148 | 149 | -- Lets some LEDs blink 150 | led_n_o(0) <= rst_n_i; -- reset button 151 | led_n_o(1) <= s_uart_rx_tready and s_uart_tx_tvalid; -- uart ctrl ready 152 | led_n_o(2) <= not s_uart_rx_tready; -- uart received 153 | led_n_o(3) <= not s_uart_tx_tvalid; -- uart send 154 | 155 | end architecture; 156 | -------------------------------------------------------------------------------- /uart_aes/rtl/uart_aes_types.vhd: -------------------------------------------------------------------------------- 1 | library ieee; 2 | use ieee.std_logic_1164.all; 3 | 4 | 5 | package uart_aes_types is 6 | 7 | type t_axis_ctrl_aes_tuser is record 8 | start : std_logic; 9 | key : std_logic_vector(0 to 127); 10 | nonce : std_logic_vector(0 to 95); 11 | end record; 12 | 13 | type t_axis_ctrl_aes_m2s is record 14 | tuser : t_axis_ctrl_aes_tuser; 15 | tdata : std_logic_vector(0 to 127); 16 | tvalid : std_logic; 17 | end record; 18 | 19 | type t_axis_m2s is record 20 | tdata : std_logic_vector(0 to 127); 21 | tvalid : std_logic; 22 | end record; 23 | 24 | alias t_axis_aes_ctrl_m2s is t_axis_m2s; 25 | 26 | type t_axis_s2m is record 27 | tready : std_logic; 28 | end record; 29 | 30 | -- No dout reg necessary, as we simply use AES tdata output 31 | type t_reg_file is record 32 | ctrl : std_logic_vector(7 downto 0); 33 | key : std_logic_vector(0 to 127); 34 | nonce : std_logic_vector(0 to 95); 35 | din : std_logic_vector(0 to 127); 36 | end record; 37 | 38 | constant c_reg_file_init : t_reg_file := (8x"0", 128x"0", 96x"0", 128x"0"); 39 | 40 | end package; 41 | -------------------------------------------------------------------------------- /uart_aes/rtl/uart_ctrl.vhd: -------------------------------------------------------------------------------- 1 | -- UART register 2 | 3 | -- Register file with 8 registers storing values of one byte each. 4 | -- 5 | -- The first received byte on the axis in port contains command & address: 6 | -- 7 | -- 7 reserved 8 | -- 6:4 register address 9 | -- 3:0 command 10 | -- 0x0 read 11 | -- 0x1 write 12 | -- 13 | -- In case of a write command, the payload has to follow 14 | -- with the next byte. 15 | -- 16 | -- In case of a read command, the value of the addressed 17 | -- register is returned on the axis out port. 18 | -- 19 | -- Register at address 0 is special. It contains the version 20 | -- and is read-only. Writes to that register are ignored. 21 | 22 | 23 | library ieee; 24 | use ieee.std_logic_1164.all; 25 | use ieee.numeric_std.all; 26 | 27 | use work.uart_aes_types.all; 28 | 29 | 30 | entity uart_ctrl is 31 | port ( 32 | -- globals 33 | rst_n_i : in std_logic; 34 | clk_i : in std_logic; 35 | -- axis in 36 | tdata_i : in std_logic_vector(7 downto 0); 37 | tvalid_i : in std_logic; 38 | tready_o : out std_logic; 39 | -- axis out 40 | tdata_o : out std_logic_vector(7 downto 0); 41 | tvalid_o : out std_logic; 42 | tready_i : in std_logic; 43 | -- aes out 44 | ctrl_aes_o : out t_axis_ctrl_aes_m2s; 45 | ctrl_aes_i : in t_axis_s2m; 46 | -- aes in 47 | aes_ctrl_i : in t_axis_aes_ctrl_m2s; 48 | aes_ctrl_o : out t_axis_s2m 49 | ); 50 | end entity uart_ctrl; 51 | 52 | 53 | architecture rtl of uart_ctrl is 54 | 55 | type t_state is (IDLE, GET_CMD, RECV_DATA, SEND_DATA); 56 | signal s_state : t_state; 57 | 58 | signal s_reg_file : t_reg_file; 59 | 60 | signal s_reg_addr : natural range 0 to 7; 61 | signal s_reg_data : std_logic_vector(7 downto 0); 62 | 63 | subtype t_cmd is std_ulogic_vector(3 downto 0); 64 | constant c_read : t_cmd := x"0"; 65 | constant c_write : t_cmd := x"1"; 66 | 67 | alias a_tdata_cmd is tdata_i(3 downto 0); 68 | alias a_tdata_addr is tdata_i(6 downto 4); 69 | 70 | constant c_ctrl_addr : natural := 0; 71 | constant c_key_addr : natural := 1; 72 | constant c_nonce_addr : natural := 2; 73 | constant c_din_addr : natural := 3; 74 | constant c_out_addr : natural := 4; 75 | 76 | constant AES_RESET : natural := 0; -- Reset key & din registers 77 | constant CTR_START : natural := 1; -- 1st round of counter mode 78 | constant AES_START : natural := 2; -- start AES engine (cleared with AES_END) 79 | constant AES_END : natural := 3; -- AES engine finished 80 | 81 | type reg_acc_cnt_t is array (natural range <>) of unsigned(3 downto 0); 82 | signal read_acc_cnt : reg_acc_cnt_t(0 to 3); 83 | signal write_acc_cnt : reg_acc_cnt_t(0 to 2); 84 | 85 | begin 86 | 87 | -- Register memory 88 | process (clk_i, rst_n_i) is 89 | begin 90 | if (not rst_n_i) then 91 | s_reg_data <= (others => '0'); 92 | s_reg_file <= c_reg_file_init; 93 | read_acc_cnt <= (others => x"0"); 94 | write_acc_cnt <= (others => x"0"); 95 | elsif (rising_edge(clk_i)) then 96 | -- Register write 97 | if (s_state = RECV_DATA and tvalid_i = '1') then 98 | case s_reg_addr is 99 | when 0 => s_reg_file.ctrl <= tdata_i; 100 | -- Clear all regs when AES_RESET bit set 101 | if (tdata_i(AES_RESET)) then 102 | s_reg_file.ctrl <= (others => '0'); 103 | s_reg_file.key <= (others => '0'); 104 | s_reg_file.nonce <= (others => '0'); 105 | s_reg_file.din <= (others => '0'); 106 | write_acc_cnt <= (others => x"0"); 107 | read_acc_cnt <= (others => x"0"); 108 | end if; 109 | when 1 => write_acc_cnt(0) <= write_acc_cnt(0) + 1; 110 | s_reg_file.key(to_integer(write_acc_cnt(0))*8 to to_integer(write_acc_cnt(0))*8+7) <= tdata_i; 111 | when 2 => if (write_acc_cnt(1) = 11) then 112 | write_acc_cnt(1) <= x"0"; 113 | else 114 | write_acc_cnt(1) <= write_acc_cnt(1) + 1; 115 | end if; 116 | s_reg_file.nonce(to_integer(write_acc_cnt(1))*8 to to_integer(write_acc_cnt(1))*8+7) <= tdata_i; 117 | when 3 => write_acc_cnt(2) <= write_acc_cnt(2) + 1; 118 | s_reg_file.din(to_integer(write_acc_cnt(2))*8 to to_integer(write_acc_cnt(2))*8+7) <= tdata_i; 119 | when others => null; 120 | end case; 121 | end if; 122 | -- Register read 123 | aes_ctrl_o.tready <= '0'; 124 | if (s_state = GET_CMD and a_tdata_cmd = c_read) then 125 | case s_reg_addr is 126 | when 0 => s_reg_data <= s_reg_file.ctrl; 127 | when 1 => read_acc_cnt(0) <= read_acc_cnt(0) + 1; 128 | s_reg_data <= s_reg_file.key(to_integer(read_acc_cnt(0))*8 to to_integer(read_acc_cnt(0))*8+7); 129 | when 2 => if (read_acc_cnt(1) = 11) then 130 | read_acc_cnt(1) <= x"0"; 131 | else 132 | read_acc_cnt(1) <= read_acc_cnt(1) + 1; 133 | end if; 134 | s_reg_data <= s_reg_file.nonce(to_integer(read_acc_cnt(1))*8 to to_integer(read_acc_cnt(1))*8+7); 135 | when 3 => read_acc_cnt(2) <= read_acc_cnt(2) + 1; 136 | s_reg_data <= s_reg_file.din(to_integer(read_acc_cnt(2))*8 to to_integer(read_acc_cnt(2))*8+7); 137 | when 4 => read_acc_cnt(3) <= read_acc_cnt(3) + 1; 138 | s_reg_data <= aes_ctrl_i.tdata(to_integer(read_acc_cnt(3))*8 to to_integer(read_acc_cnt(3))*8+7); 139 | if (read_acc_cnt(3) = 15) then 140 | aes_ctrl_o.tready <= aes_ctrl_i.tvalid; 141 | end if; 142 | when others => s_reg_data <= (others => '0'); 143 | end case; 144 | end if; 145 | 146 | -- Set AES_END when AES out data is valid 147 | -- Reset when AES out data was accepted (all 16 bytes of AES output data were read) 148 | if (aes_ctrl_o.tready) then 149 | s_reg_file.ctrl(AES_END) <= '0'; 150 | elsif (aes_ctrl_i.tvalid) then 151 | s_reg_file.ctrl(AES_END) <= '1'; 152 | end if; 153 | 154 | -- Reset AES_START & CTR_START when AES engine accepts in data 155 | if (ctrl_aes_i.tready and s_reg_file.ctrl(AES_START)) then 156 | s_reg_file.ctrl(AES_START) <= '0'; 157 | s_reg_file.ctrl(CTR_START) <= '0'; 158 | end if; 159 | end if; 160 | end process; 161 | 162 | -- Control state machine 163 | process (clk_i, rst_n_i) is 164 | begin 165 | if (not rst_n_i) then 166 | s_state <= IDLE; 167 | s_reg_addr <= 0; 168 | elsif (rising_edge(clk_i)) then 169 | case s_state is 170 | when IDLE => 171 | if (tvalid_i) then 172 | s_state <= GET_CMD; 173 | s_reg_addr <= to_integer(unsigned(a_tdata_addr)); 174 | end if; 175 | when GET_CMD => 176 | if (a_tdata_cmd = c_read) then 177 | s_state <= SEND_DATA; 178 | elsif (a_tdata_cmd = c_write) then 179 | s_state <= RECV_DATA; 180 | else 181 | s_state <= IDLE; 182 | end if; 183 | when RECV_DATA => 184 | if (tvalid_i) then 185 | s_state <= IDLE; 186 | end if; 187 | when SEND_DATA => 188 | if (tready_i) then 189 | s_state <= IDLE; 190 | end if; 191 | when others => 192 | null; 193 | end case; 194 | end if; 195 | end process; 196 | 197 | tready_o <= '1' when s_state = GET_CMD or s_state = RECV_DATA else '0'; 198 | 199 | tdata_o <= s_reg_data; 200 | tvalid_o <= '1' when s_state = SEND_DATA else '0'; 201 | 202 | ctrl_aes_o.tuser.start <= s_reg_file.ctrl(CTR_START); 203 | ctrl_aes_o.tuser.key <= s_reg_file.key; 204 | ctrl_aes_o.tuser.nonce <= s_reg_file.nonce; 205 | ctrl_aes_o.tdata <= s_reg_file.din; 206 | ctrl_aes_o.tvalid <= s_reg_file.ctrl(AES_START); 207 | 208 | 209 | end architecture; 210 | -------------------------------------------------------------------------------- /uart_aes/rtl/uart_rx.vhd: -------------------------------------------------------------------------------- 1 | -- Copyright (c) 2022 by Torsten Meissner 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 | -- https://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 | 16 | 17 | library ieee; 18 | use ieee.std_logic_1164.all; 19 | use ieee.numeric_std.all; 20 | 21 | 22 | entity uart_rx is 23 | generic ( 24 | CLK_DIV : natural := 10 25 | ); 26 | port ( 27 | -- globals 28 | rst_n_i : in std_logic; 29 | clk_i : in std_logic; 30 | -- axis user interface 31 | tdata_o : out std_logic_vector(7 downto 0); 32 | tvalid_o : out std_logic; 33 | tready_i : in std_logic; 34 | -- uart interface 35 | rx_i : in std_logic 36 | ); 37 | end entity uart_rx; 38 | 39 | 40 | architecture rtl of uart_rx is 41 | 42 | type t_uart_state is (IDLE, RECEIVE, VALID); 43 | signal s_uart_state : t_uart_state; 44 | 45 | signal s_clk_en : std_logic; 46 | signal s_clk_cnt : natural range 0 to CLK_DIV-1; 47 | signal s_bit_cnt : natural range 0 to tdata_o'length+1; 48 | signal s_rx_d : std_logic_vector(3 downto 0); 49 | 50 | begin 51 | 52 | ClkDivP : process (clk_i, rst_n_i) is 53 | begin 54 | if (not rst_n_i) then 55 | s_clk_cnt <= CLK_DIV-1; 56 | elsif (rising_edge(clk_i)) then 57 | if (s_uart_state = IDLE) then 58 | s_clk_cnt <= CLK_DIV-2; 59 | elsif (s_uart_state = RECEIVE) then 60 | if (s_clk_cnt = 0) then 61 | s_clk_cnt <= CLK_DIV-1; 62 | else 63 | s_clk_cnt <= s_clk_cnt - 1; 64 | end if; 65 | end if; 66 | end if; 67 | end process ClkDivP; 68 | 69 | s_clk_en <= '1' when s_uart_state = RECEIVE and s_clk_cnt = CLK_DIV/2-1 else '0'; 70 | 71 | RxP : process (clk_i, rst_n_i) is 72 | begin 73 | if (not rst_n_i) then 74 | s_uart_state <= IDLE; 75 | tdata_o <= (others => '0'); 76 | s_rx_d <= x"1"; 77 | s_bit_cnt <= 0; 78 | elsif (rising_edge(clk_i)) then 79 | s_rx_d <= s_rx_d(2 downto 0) & rx_i; 80 | FsmL : case s_uart_state is 81 | when IDLE => 82 | s_bit_cnt <= tdata_o'length+1; 83 | if (s_rx_d = "1000") then 84 | s_uart_state <= RECEIVE; 85 | end if; 86 | when RECEIVE => 87 | if (s_clk_en) then 88 | if (s_bit_cnt = 0) then 89 | s_uart_state <= VALID; 90 | else 91 | tdata_o <= s_rx_d(3) & tdata_o(tdata_o'length-1 downto 1); 92 | s_bit_cnt <= s_bit_cnt - 1; 93 | end if; 94 | end if; 95 | when VALID => 96 | if (tready_i) then 97 | s_uart_state <= IDLE; 98 | end if; 99 | end case; 100 | end if; 101 | end process RxP; 102 | 103 | tvalid_o <= '1' when s_uart_state = VALID else '0'; 104 | 105 | end architecture rtl; 106 | -------------------------------------------------------------------------------- /uart_aes/rtl/uart_tx.vhd: -------------------------------------------------------------------------------- 1 | -- Copyright (c) 2022 by Torsten Meissner 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 | -- https://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 | 16 | 17 | library ieee; 18 | use ieee.std_logic_1164.all; 19 | use ieee.numeric_std.all; 20 | 21 | 22 | entity uart_tx is 23 | generic ( 24 | CLK_DIV : natural := 10 25 | ); 26 | port ( 27 | -- globals 28 | rst_n_i : in std_logic; 29 | clk_i : in std_logic; 30 | -- axis user interface 31 | tdata_i : in std_logic_vector(7 downto 0); 32 | tvalid_i : in std_logic; 33 | tready_o : out std_logic; 34 | -- uart interface 35 | tx_o : out std_logic 36 | ); 37 | end entity uart_tx; 38 | 39 | 40 | architecture rtl of uart_tx is 41 | 42 | type t_uart_state is (IDLE, SEND); 43 | signal s_uart_state : t_uart_state; 44 | 45 | signal s_data : std_logic_vector(tdata_i'length+1 downto 0); 46 | signal s_clk_cnt : natural range 0 to CLK_DIV-1; 47 | signal s_clk_en : std_logic; 48 | signal s_bit_cnt : natural range 0 to s_data'length-1; 49 | 50 | begin 51 | 52 | ClkDivP : process (clk_i, rst_n_i) is 53 | begin 54 | if (not rst_n_i) then 55 | s_clk_cnt <= CLK_DIV-1; 56 | elsif (rising_edge(clk_i)) then 57 | if (s_uart_state = IDLE) then 58 | s_clk_cnt <= CLK_DIV-2; 59 | elsif (s_uart_state = SEND) then 60 | if (s_clk_cnt = 0) then 61 | s_clk_cnt <= CLK_DIV-1; 62 | else 63 | s_clk_cnt <= s_clk_cnt - 1; 64 | end if; 65 | end if; 66 | end if; 67 | end process ClkDivP; 68 | 69 | s_clk_en <= '1' when s_uart_state = SEND and s_clk_cnt = 0 else '0'; 70 | 71 | TxP : process (clk_i, rst_n_i) is 72 | begin 73 | if (not rst_n_i) then 74 | s_uart_state <= IDLE; 75 | s_data <= (0 => '1', others => '0'); 76 | s_bit_cnt <= 0; 77 | elsif (rising_edge(clk_i)) then 78 | FsmL : case s_uart_state is 79 | when IDLE => 80 | s_bit_cnt <= s_data'length-1; 81 | if (tvalid_i) then 82 | s_data <= '1' & tdata_i & '0'; 83 | s_uart_state <= SEND; 84 | end if; 85 | when SEND => 86 | if (s_clk_en) then 87 | s_data <= '1' & s_data(s_data'length-1 downto 1); 88 | if (s_bit_cnt = 0) then 89 | s_uart_state <= IDLE; 90 | else 91 | s_bit_cnt <= s_bit_cnt - 1; 92 | end if; 93 | end if; 94 | end case; 95 | end if; 96 | end process TxP; 97 | 98 | tready_o <= '1' when s_uart_state = IDLE else '0'; 99 | 100 | tx_o <= s_data(0); 101 | 102 | end architecture rtl; 103 | -------------------------------------------------------------------------------- /uart_aes/sim/Makefile: -------------------------------------------------------------------------------- 1 | DESIGN_NAME := uart_aes 2 | 3 | AES_DIR := ../../cryptocores/aes/rtl/vhdl 4 | CRYPTO_SRC := \ 5 | $(AES_DIR)/aes_pkg.vhd \ 6 | $(AES_DIR)/aes_enc.vhd \ 7 | $(AES_DIR)/aes_dec.vhd \ 8 | $(AES_DIR)/aes.vhd \ 9 | $(AES_DIR)/../../../ctraes/rtl/vhdl/ctraes.vhd 10 | 11 | WORK_FILES := \ 12 | ../rtl/uart_aes_types.vhd \ 13 | ../rtl/uart_tx.vhd \ 14 | ../rtl/uart_rx.vhd \ 15 | ../rtl/uart_ctrl.vhd \ 16 | ../rtl/${DESIGN_NAME}.vhd \ 17 | uart_aes_sim.vhd \ 18 | uart_aes_ref.vhd \ 19 | tb_${DESIGN_NAME}.vhd 20 | 21 | GM_FILES := ../../lib/rtl_components.vhd ../../lib/sim_components.vhd 22 | 23 | SIM_SRC := tb_${DESIGN_NAME}.vhd 24 | SIM_FLAGS := --std=08 -fpsl --workdir=work -Pwork 25 | 26 | 27 | .PHONY: all compile sim clean 28 | 29 | all: sim 30 | compile: tb_${DESIGN_NAME} 31 | 32 | work/work-obj08.cf: ${WORK_FILES} work/gatemate-obj08.cf work/cryptocores-obj08.cf 33 | mkdir -p work 34 | ghdl -a ${SIM_FLAGS} --work=work ${WORK_FILES} 35 | 36 | work/cryptocores-obj08.cf: ${CRYPTO_SRC} 37 | mkdir -p work 38 | ghdl -a $(SIM_FLAGS) --work=cryptocores ${CRYPTO_SRC} 39 | 40 | work/gatemate-obj08.cf: ${GM_FILES} 41 | mkdir -p work 42 | ghdl -a ${SIM_FLAGS} --work=gatemate ${GM_FILES} 43 | 44 | tb_${DESIGN_NAME}: work/work-obj08.cf uart_aes_ref.c 45 | @echo "Elaborate testbench & design ..." 46 | ghdl -e ${SIM_FLAGS} -Wl,uart_aes_ref.c -Wl,-lcrypto -Wl,-lssl $@ 47 | 48 | sim: tb_${DESIGN_NAME} 49 | @echo "Run testbench ..." 50 | ghdl -r ${SIM_FLAGS} tb_${DESIGN_NAME} --assert-level=error --ieee-asserts=disable --wave=tb_${DESIGN_NAME}.ghw 51 | 52 | work: 53 | mkdir $@ 54 | 55 | clean: 56 | @echo "Cleaning simulation files ..." 57 | rm -rf tb_${DESIGN_NAME} tb_${DESIGN_NAME}.ghw *.o work/ 58 | -------------------------------------------------------------------------------- /uart_aes/sim/tb_uart_aes.tcl: -------------------------------------------------------------------------------- 1 | set signals [list] 2 | lappend signals "top.tb_uart_aes.dut.aes_inst.reset_i" 3 | lappend signals "top.tb_uart_aes.dut.aes_inst.clk_i" 4 | lappend signals "top.tb_uart_aes.dut.aes_inst.valid_i" 5 | lappend signals "top.tb_uart_aes.dut.aes_inst.accept_o" 6 | lappend signals "top.tb_uart_aes.dut.aes_inst.start_i" 7 | lappend signals "top.tb_uart_aes.dut.aes_inst.key_i" 8 | lappend signals "top.tb_uart_aes.dut.aes_inst.nonce_i" 9 | lappend signals "top.tb_uart_aes.dut.aes_inst.data_i" 10 | lappend signals "top.tb_uart_aes.dut.aes_inst.valid_o" 11 | lappend signals "top.tb_uart_aes.dut.aes_inst.accept_i" 12 | lappend signals "top.tb_uart_aes.dut.aes_inst.data_o" 13 | set num_added [ gtkwave::addSignalsFromList $signals ] 14 | -------------------------------------------------------------------------------- /uart_aes/sim/tb_uart_aes.vhd: -------------------------------------------------------------------------------- 1 | library ieee ; 2 | use ieee.std_logic_1164.all; 3 | use ieee.numeric_std.all; 4 | 5 | use std.env.all; 6 | 7 | use work.uart_aes_ref.all; 8 | 9 | entity tb_uart_aes is 10 | end entity tb_uart_aes; 11 | 12 | 13 | architecture sim of tb_uart_aes is 14 | 15 | signal s_clk : std_logic := '1'; 16 | signal s_rst_n : std_logic := '0'; 17 | 18 | signal s_uart_rx : std_logic := '1'; 19 | signal s_uart_tx : std_logic; 20 | 21 | constant c_baudrate : natural := 9600; 22 | constant c_period_ns : time := 1_000_000_000 / c_baudrate * ns; 23 | 24 | package uart_aes_sim_inst is new work.uart_aes_sim 25 | generic map (period_ns => c_period_ns); 26 | 27 | use uart_aes_sim_inst.all; 28 | 29 | begin 30 | 31 | dut : entity work.uart_aes 32 | port map ( 33 | clk_i => s_clk, 34 | rst_n_i => s_rst_n, 35 | uart_rx_i => s_uart_rx, 36 | uart_tx_o => s_uart_tx 37 | ); 38 | 39 | s_rst_n <= '1' after 120 ns; 40 | s_clk <= not s_clk after 50 ns; 41 | 42 | TestP : process is 43 | variable v_data : std_logic_vector(7 downto 0); 44 | variable v_uart_data : std_logic_vector(0 to 127); 45 | variable v_key : std_logic_vector(0 to 127); 46 | variable v_nonce : std_logic_vector(0 to 95); 47 | variable v_in_data : std_logic_vector(0 to 127); 48 | variable v_ref_data : std_logic_vector(0 to 127); 49 | begin 50 | wait until s_rst_n; 51 | wait until rising_edge(s_clk); 52 | wait for 200 us; 53 | v_key := x"0123456789ABCDEF0123456789ABCDEF"; 54 | v_nonce := x"0123456789ABCDEF01234567"; 55 | aes_setup(v_key, v_nonce, s_uart_rx); 56 | for i in 0 to 7 loop 57 | report "Test round " & to_string(i); 58 | v_in_data := x"0123456789ABCDEF0123456789ABCDEF"; 59 | aes_write(v_in_data, s_uart_rx); 60 | aes_crypt(s_uart_rx, s_uart_tx); 61 | aes_read(v_uart_data, s_uart_rx, s_uart_tx); 62 | -- Calc reference data 63 | cryptData(swap(v_in_data), swap(v_key), swap(v_nonce & 32x"0"), i=0, i=7, v_ref_data, v_in_data'length/8); 64 | assert v_uart_data = swap(v_ref_data) 65 | report "Encryption error: Expected 0x" & to_hstring(swap(v_ref_data)) & ", got 0x" & to_hstring(v_uart_data) 66 | severity failure; 67 | end loop; 68 | wait for 100 us; 69 | report "Simulation finished without errors"; 70 | stop(0); 71 | end process; 72 | 73 | end architecture; 74 | -------------------------------------------------------------------------------- /uart_aes/sim/uart_aes_ref.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | static const char HDL_LOGIC_CHAR[] = { 'U', 'X', '0', '1', 'Z', 'W', 'L', 'H', '-'}; 8 | 9 | enum HDL_LOGIC_STATES { 10 | HDL_U = 0, 11 | HDL_X = 1, 12 | HDL_0 = 2, 13 | HDL_1 = 3, 14 | HDL_Z = 4, 15 | HDL_W = 5, 16 | HDL_L = 6, 17 | HDL_H = 7, 18 | HDL_D = 8, 19 | }; 20 | 21 | EVP_CIPHER_CTX *ctx; 22 | 23 | void slv_to_uchar(char* datain, unsigned char* dataout, int bytelen) { 24 | 25 | for (int i = 0; i < bytelen; i++) { 26 | for (int y = 0; y < 8; y++) { 27 | if (*datain == HDL_1) { 28 | *dataout |= 1 << y; 29 | } else if (*datain == HDL_0) { 30 | *dataout &= ~(1 << y); 31 | } 32 | datain++; 33 | } 34 | dataout++; 35 | } 36 | 37 | return; 38 | 39 | } 40 | 41 | 42 | void slv_to_string(char* datain, char* dataout, int bytelen) { 43 | 44 | for (int i = 0; i < bytelen; i++) { 45 | *dataout = HDL_LOGIC_CHAR[*datain]; 46 | datain++; 47 | dataout++; 48 | } 49 | 50 | return; 51 | 52 | } 53 | 54 | 55 | void uchar_to_slv(unsigned char* datain, char* dataout, int bytelen) { 56 | 57 | for (int i = 0; i < bytelen; i++) { 58 | for (int y = 0; y < 8; y++) { 59 | if ((*datain >> y) & 1 == 1) { 60 | *dataout = HDL_1 ; 61 | } else { 62 | *dataout = HDL_0; 63 | } 64 | dataout++; 65 | } 66 | datain++; 67 | } 68 | 69 | return; 70 | 71 | } 72 | 73 | 74 | void handleErrors(void) { 75 | 76 | ERR_print_errors_fp(stderr); 77 | abort(); 78 | 79 | } 80 | 81 | 82 | void init(unsigned char *key, unsigned char *iv) { 83 | 84 | // Create and initialise the context 85 | if(!(ctx = EVP_CIPHER_CTX_new())) 86 | handleErrors(); 87 | 88 | // Initialise the encryption operation, no IV needed in CTR mode 89 | if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_128_ctr(), NULL, key, iv)) 90 | handleErrors(); 91 | 92 | // We don't want padding 93 | if(1 != EVP_CIPHER_CTX_set_padding(ctx, 0)) 94 | handleErrors(); 95 | 96 | } 97 | 98 | 99 | int encrypt(unsigned char *plaintext, 100 | int plaintext_len, 101 | unsigned char *ciphertext) { 102 | 103 | int len = 0; 104 | 105 | // Provide the message to be encrypted, and obtain the encrypted output 106 | if (1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len)) 107 | handleErrors(); 108 | 109 | return len; 110 | 111 | } 112 | 113 | 114 | int finalize(void) { 115 | 116 | int len = 0; 117 | unsigned char data[16]; 118 | 119 | // Finalise the encryption. No further bytes are written as padding is switched off 120 | if (1 != EVP_EncryptFinal_ex(ctx, data, &len)) 121 | handleErrors(); 122 | 123 | // Clean up 124 | EVP_CIPHER_CTX_free(ctx); 125 | 126 | return len; 127 | 128 | } 129 | 130 | 131 | void cryptData(char* datain, char* key, char* iv, char start, char final, char* dataout, int bytelen) { 132 | 133 | int crypt_len; 134 | unsigned char c_din[bytelen]; 135 | unsigned char c_key[bytelen]; 136 | unsigned char c_iv[bytelen]; 137 | unsigned char c_dout[bytelen]; 138 | 139 | slv_to_uchar(datain, c_din, bytelen); 140 | slv_to_uchar(key, c_key, bytelen); 141 | slv_to_uchar(iv, c_iv, bytelen); 142 | 143 | if (start) { 144 | init(c_key, c_iv); 145 | } 146 | 147 | crypt_len = encrypt(c_din, bytelen, c_dout); 148 | 149 | if (crypt_len != bytelen) { 150 | printf("Warning: encrypt() returned with unexpected length %d\n", crypt_len); 151 | } 152 | 153 | if (final) { 154 | crypt_len = finalize(); 155 | if (crypt_len != 0) { 156 | printf("Warning: finalize() returned with unexpected length %d\n", crypt_len); 157 | } 158 | } 159 | 160 | uchar_to_slv(c_dout, dataout, bytelen); 161 | 162 | return; 163 | 164 | } 165 | -------------------------------------------------------------------------------- /uart_aes/sim/uart_aes_ref.vhd: -------------------------------------------------------------------------------- 1 | library ieee ; 2 | use ieee.std_logic_1164.all; 3 | 4 | 5 | package uart_aes_ref is 6 | 7 | procedure cryptData(datain : in std_logic_vector(0 to 127); 8 | key : in std_logic_vector(0 to 127); 9 | iv : in std_logic_vector(0 to 127); 10 | start : in boolean; 11 | final : in boolean; 12 | dataout : out std_logic_vector(0 to 127); 13 | bytelen : in integer); 14 | 15 | attribute foreign of cryptData: procedure is "VHPIDIRECT cryptData"; 16 | 17 | function swap (datain : std_logic_vector(0 to 127)) return std_logic_vector; 18 | 19 | end package; 20 | 21 | 22 | package body uart_aes_ref is 23 | 24 | procedure cryptData(datain : in std_logic_vector(0 to 127); 25 | key : in std_logic_vector(0 to 127); 26 | iv : in std_logic_vector(0 to 127); 27 | start : in boolean; 28 | final : in boolean; 29 | dataout : out std_logic_vector(0 to 127); 30 | bytelen : in integer) is 31 | begin 32 | report "VHPIDIRECT cryptData" severity failure; 33 | end procedure; 34 | 35 | function swap (datain : std_logic_vector(0 to 127)) return std_logic_vector is 36 | variable v_data : std_logic_vector(0 to 127); 37 | begin 38 | for i in 0 to 15 loop 39 | for y in 0 to 7 loop 40 | v_data((i*8)+y) := datain((i*8)+7-y); 41 | end loop; 42 | end loop; 43 | return v_data; 44 | end function; 45 | 46 | end package body; 47 | -------------------------------------------------------------------------------- /uart_aes/sim/uart_aes_sim.vhd: -------------------------------------------------------------------------------- 1 | library ieee ; 2 | use ieee.std_logic_1164.all; 3 | 4 | 5 | package uart_aes_sim is 6 | 7 | generic ( 8 | period_ns : time 9 | ); 10 | 11 | procedure uart_send ( data : in std_logic_vector(7 downto 0); 12 | signal tx : out std_logic); 13 | 14 | procedure uart_recv ( data : out std_logic_vector(7 downto 0); 15 | signal rx : in std_logic); 16 | 17 | procedure aes_setup ( key : in std_logic_vector(0 to 127); 18 | nonce : in std_logic_vector(0 to 95); 19 | signal tx : out std_logic); 20 | 21 | procedure aes_write ( data : in std_logic_vector(0 to 127); 22 | signal tx : out std_logic); 23 | 24 | procedure aes_read ( data : out std_logic_vector(0 to 127); 25 | signal tx : out std_logic; 26 | signal rx : in std_logic); 27 | 28 | procedure aes_crypt (signal tx : out std_logic; 29 | signal rx : in std_logic); 30 | 31 | end package; 32 | 33 | package body uart_aes_sim is 34 | 35 | procedure uart_send ( data : in std_logic_vector(7 downto 0); 36 | signal tx : out std_logic) is 37 | begin 38 | report "UART send: 0x" & to_hstring(data); 39 | wait for period_ns; 40 | tx <= '0'; 41 | wait for period_ns; 42 | for i in 0 to 7 loop 43 | tx <= data(i); 44 | wait for period_ns; 45 | end loop; 46 | tx <= '1'; 47 | wait for 0 ns; 48 | end procedure; 49 | 50 | procedure uart_recv ( data : out std_logic_vector(7 downto 0); 51 | signal rx : in std_logic) is 52 | begin 53 | wait until not rx; 54 | wait for period_ns; -- Skip start bit 55 | wait for period_ns/2; 56 | for i in 0 to 7 loop 57 | data(i) := rx; 58 | wait for period_ns; 59 | end loop; 60 | report "UART recv: 0x" & to_hstring(data); 61 | end procedure; 62 | 63 | procedure aes_setup ( key : in std_logic_vector(0 to 127); 64 | nonce : in std_logic_vector(0 to 95); 65 | signal tx : out std_logic) is 66 | begin 67 | -- Reset control register 68 | uart_send(x"01", tx); 69 | uart_send(x"01", tx); 70 | -- Write key register 71 | for i in 0 to 15 loop 72 | uart_send(x"11", tx); 73 | uart_send(key(i*8 to i*8+7), tx); 74 | end loop; 75 | -- Write nonce register 76 | for i in 0 to 11 loop 77 | uart_send(x"21", tx); 78 | uart_send(nonce(i*8 to i*8+7), tx); 79 | end loop; 80 | -- Set control registers CTR_START bit 81 | uart_send(x"01", tx); 82 | uart_send(x"02", tx); 83 | end procedure; 84 | 85 | procedure aes_write ( data : in std_logic_vector(0 to 127); 86 | signal tx : out std_logic) is 87 | begin 88 | -- Write din register 89 | for i in 0 to 15 loop 90 | uart_send(x"31", tx); 91 | uart_send(data(i*8 to i*8+7), tx); 92 | end loop; 93 | end procedure; 94 | 95 | procedure aes_read ( data : out std_logic_vector(0 to 127); 96 | signal tx : out std_logic; 97 | signal rx : in std_logic) is 98 | variable v_data : std_logic_vector(7 downto 0); 99 | begin 100 | -- Check for valid AES output data 101 | loop 102 | uart_send(x"00", tx); 103 | uart_recv(v_data, rx); 104 | exit when v_data(3); 105 | end loop; 106 | -- Read dout register 107 | for i in 0 to 15 loop 108 | uart_send(x"40", tx); 109 | uart_recv(data(i*8 to i*8+7), rx); 110 | end loop; 111 | end procedure; 112 | 113 | procedure aes_crypt (signal tx : out std_logic; 114 | signal rx : in std_logic) is 115 | variable v_data : std_logic_vector(7 downto 0); 116 | begin 117 | uart_send(x"00", tx); 118 | uart_recv(v_data, rx); 119 | v_data(2) := '1'; 120 | -- Set control registers CTR_START bit 121 | uart_send(x"01", tx); 122 | uart_send(v_data, tx); 123 | end procedure; 124 | 125 | end package body; 126 | -------------------------------------------------------------------------------- /uart_aes/syn/Makefile: -------------------------------------------------------------------------------- 1 | DESIGN_NAME := uart_aes 2 | 3 | AES_DIR := ../../cryptocores/aes/rtl/vhdl 4 | CRYPTO_SRC := \ 5 | $(AES_DIR)/aes_pkg.vhd \ 6 | $(AES_DIR)/aes_enc.vhd \ 7 | $(AES_DIR)/../../../ctraes/rtl/vhdl/ctraes.vhd 8 | 9 | WORK_FILES := \ 10 | ../rtl/uart_aes_types.vhd \ 11 | ../rtl/uart_tx.vhd \ 12 | ../rtl/uart_rx.vhd \ 13 | ../rtl/uart_ctrl.vhd \ 14 | ../rtl/${DESIGN_NAME}.vhd 15 | 16 | GM_FILES := ../../lib/rtl_components.vhd 17 | 18 | GHDL_FLAGS := --std=08 --workdir=build -Pbuild 19 | ICARUSFLAGS := -Wall -Winfloop -g2012 -gspecify -Ttyp 20 | 21 | YOSYSPIPE := -nomx8 22 | # yosys -nomx8 option has to be used as GM FPGA hasn't any (working?) MUX8 cells (in contrast to documentation) 23 | # yosys -retime option causes design AES unit misbehavior (wrong results) 24 | # yosys -dff option can be used without risk (but leads to 2.5 mhz less fmax) 25 | 26 | PNRTOOL := $(shell which p_r) 27 | PNRFLAGS := -om 3 -cCP off 28 | # p_r +cCP option causes design AES unit misbehavior (wrong results != retime results) 29 | # p_r +sp option causes design AES unit misbehavior (wrong results != retime results != cCP results) 30 | # p_r +cCP with +gCP also breaks UART 31 | 32 | 33 | .PHONY: all syn imp prog syn_sim imp_sim 34 | 35 | all: imp 36 | syn: ${DESIGN_NAME}.v 37 | imp: ${DESIGN_NAME}.bit 38 | 39 | build/work-obj08.cf: ${WORK_FILES} build/gatemate-obj08.cf build/cryptocores-obj08.cf 40 | ghdl -a ${GHDL_FLAGS} --work=work ${WORK_FILES} 41 | 42 | build/cryptocores-obj08.cf: ${CRYPTO_SRC} 43 | ghdl -a $(GHDL_FLAGS) --work=cryptocores ${CRYPTO_SRC} 44 | 45 | build/gatemate-obj08.cf: ${GM_FILES} 46 | mkdir -p build 47 | ghdl -a ${GHDL_FLAGS} --work=gatemate ${GM_FILES} 48 | 49 | # Synthesis target for implementation 50 | ${DESIGN_NAME}.v: build/work-obj08.cf 51 | yosys -m ghdl -p 'ghdl ${GHDL_FLAGS} --warn-no-binding --no-formal ${DESIGN_NAME}; synth_gatemate -top $(DESIGN_NAME) ${YOSYSPIPE} -vlog $@' \ 52 | 2>&1 | tee build/yosys-report.txt 53 | 54 | # Implementation target for FPGA 55 | ${DESIGN_NAME}.bit: ${DESIGN_NAME}.v ${DESIGN_NAME}.ccf 56 | cd build && \ 57 | ${PNRTOOL} -i ../${DESIGN_NAME}.v -o $@ --ccf ../${DESIGN_NAME}.ccf $(PNRFLAGS) \ 58 | 2>&1 | tee p_r-report.txt && \ 59 | mv ${DESIGN_NAME}*.bit ../$@ 60 | 61 | # Post-synthesis simulation target 62 | syn_sim: ${DESIGN_NAME}.v 63 | iverilog ${ICARUSFLAGS} -o tb_${DESIGN_NAME}_syn.vvp ${DESIGN_NAME}.v tb_${DESIGN_NAME}.v /usr/local/share/yosys/gatemate/cells_sim.v 64 | vvp -N tb_${DESIGN_NAME}_syn.vvp -fst 65 | 66 | # Post-implementation simulation target 67 | imp_sim: ${DESIGN_NAME}.bit 68 | iverilog ${ICARUSFLAGS} -o tb_${DESIGN_NAME}_imp.vvp build/${DESIGN_NAME}_00.v tb_${DESIGN_NAME}.v /opt/cc-toolchain-linux/bin/p_r/cpelib.v 69 | vvp -N tb_${DESIGN_NAME}_imp.vvp -fst 70 | 71 | # FPGA FW load per JTAG 72 | prog: ${DESIGN_NAME}.bit 73 | openFPGALoader -b gatemate_evb_jtag $< 74 | 75 | clean : 76 | echo "# Cleaning files" 77 | rm -rf build ${DESIGN_NAME}.v ${DESIGN_NAME}_sim.v ${DESIGN_NAME}.vhd ${DESIGN_NAME}.bit *.vvp *.fst 78 | -------------------------------------------------------------------------------- /uart_aes/syn/read_data.txt: -------------------------------------------------------------------------------- 1 | A0 2 | 55 3 | A0 4 | 62 5 | BC 6 | DD 7 | C3 8 | 4C 9 | 33 10 | FE 11 | 9F 12 | A6 13 | 0C 14 | FB 15 | 6F 16 | 2D -------------------------------------------------------------------------------- /uart_aes/syn/tb_uart_aes.v: -------------------------------------------------------------------------------- 1 | `timescale 1 ns/100 ps // time-unit = 1 ns, precision = 10 ps 2 | 3 | // simplified CC_PLL model 4 | module CC_PLL #( 5 | parameter REF_CLK = "", // e.g. "10.0" 6 | parameter OUT_CLK = "", // e.g. "50.0" 7 | parameter PERF_MD = "", // LOWPOWER, ECONOMY, SPEED 8 | parameter LOW_JITTER = 1, 9 | parameter CI_FILTER_CONST = 2, 10 | parameter CP_FILTER_CONST = 4 11 | )( 12 | input CLK_REF, CLK_FEEDBACK, USR_CLK_REF, 13 | input USR_LOCKED_STDY_RST, USR_SET_SEL, 14 | output USR_PLL_LOCKED_STDY, USR_PLL_LOCKED, 15 | output CLK270, CLK180, CLK90, CLK0, CLK_REF_OUT 16 | ); 17 | 18 | reg r_pll_clk; 19 | reg r_user_pll_locked; 20 | 21 | // OUT_FREQ = 10 MHz 22 | integer clk_half_period = 50; 23 | 24 | initial begin 25 | r_pll_clk = 1'b0; 26 | r_user_pll_locked = 1'b1; 27 | end 28 | 29 | always #clk_half_period r_pll_clk = ~r_pll_clk; 30 | 31 | assign CLK0 = r_pll_clk; 32 | assign USR_PLL_LOCKED = r_user_pll_locked; 33 | 34 | endmodule 35 | 36 | 37 | // simplified CC_CFG_END model 38 | module CC_CFG_END ( 39 | output CFG_END 40 | ); 41 | 42 | assign CFG_END = 1'b1; 43 | 44 | endmodule 45 | 46 | module tb_uart_aes; 47 | 48 | // DUT in/out 49 | reg clk = 1'b0; 50 | reg rst_n = 1'b1; 51 | reg uart_rx; 52 | wire uart_tx; 53 | wire [3:0] led_n; 54 | 55 | // Testbench variables 56 | reg [7:0] tx_data = 8'h0; 57 | reg [7:0] rx_data = 8'h0; 58 | 59 | // Testbench 1/2 clock period 60 | localparam clk_half_period = 50; 61 | 62 | // UART period calculation (9600 baud) 63 | localparam uart_bit_period = 1000000000 / 9600; 64 | localparam uart_bit_half_period = uart_bit_period/2; 65 | 66 | uart_aes UUT (.clk_i(clk), .rst_n_i(rst_n), .uart_rx_i(uart_rx), .uart_tx_o(uart_tx), .led_n_o(led_n)); 67 | 68 | // set dumpfile 69 | initial begin 70 | $dumpfile ("tb_uart_aes.fst"); 71 | $dumpvars (0, tb_uart_aes); 72 | end 73 | 74 | // Setup simulation 75 | initial begin 76 | uart_rx = 1'b1; 77 | #1 rst_n = 1'b0; 78 | #120 rst_n = 1'b1; 79 | end 80 | 81 | // Generate 10 mhz clock 82 | always #clk_half_period clk = !clk; 83 | 84 | reg [7:0] write_cmds [0:89]; 85 | reg [7:0] read_data [0:15]; 86 | 87 | // read in test data files 88 | initial begin 89 | $readmemh("write_cmds.txt", write_cmds); 90 | $readmemh("read_data.txt", read_data); 91 | end 92 | 93 | // Stimuli generator 94 | initial 95 | forever @(posedge rst_n) begin 96 | uart_rx = 1'b1; 97 | #uart_bit_period; 98 | // start crypto 99 | for (integer i = 0; i < $size(write_cmds); i = i + 1) begin 100 | tx_data = write_cmds[i]; 101 | $display ("UART send: 0x%h", tx_data); 102 | uart_rx = 1'b0; 103 | #uart_bit_period; 104 | for (integer i = 0; i <= 7; i = i + 1) begin 105 | uart_rx = tx_data[i]; 106 | #uart_bit_period; 107 | end 108 | uart_rx = 1'b1; 109 | #uart_bit_period; 110 | #uart_bit_period; 111 | end 112 | // Request read of data out register 113 | for (integer i = 0; i <= 15; i = i + 1) begin 114 | tx_data = 8'h40; 115 | $display ("UART send: 0x%h", tx_data); 116 | uart_rx = 1'b0; 117 | #uart_bit_period; 118 | for (integer i = 0; i <= 7; i = i + 1) begin 119 | uart_rx = tx_data[i]; 120 | #uart_bit_period; 121 | end 122 | uart_rx = 1'b1; 123 | #uart_bit_period; 124 | #uart_bit_period; 125 | end 126 | end 127 | 128 | // Checker 129 | initial begin 130 | @(posedge rst_n) 131 | for (integer i = 0; i <= 15; i = i + 1) begin 132 | @(negedge uart_tx) 133 | #uart_bit_period; 134 | #uart_bit_half_period; 135 | for (integer i = 0; i <= 7; i = i + 1) begin 136 | rx_data[i] = uart_tx; 137 | #uart_bit_period; 138 | end 139 | assert (rx_data == read_data[i]) 140 | $display("UART recv: 0x%h", rx_data); 141 | else 142 | $error("UART receive error, got 0x%h, expected 0x%h", rx_data, read_data[i]); 143 | end 144 | $display ("UART tests finished"); 145 | $finish; 146 | end 147 | 148 | 149 | endmodule 150 | -------------------------------------------------------------------------------- /uart_aes/syn/uart_aes.ccf: -------------------------------------------------------------------------------- 1 | # Configuration for the Gatemate eval board 2 | 3 | Pin_in "clk_i" Loc = "IO_SB_A8" | SCHMITT_TRIGGER=true; 4 | Pin_in "rst_n_i" Loc = "IO_EB_B0"; # SW3 5 | 6 | Pin_in "uart_rx_i" Loc = "IO_NB_A1"; # PMODA IO3 7 | Pin_out "uart_tx_o" Loc = "IO_NB_A0"; # PMODA IO1 8 | 9 | Pin_out "led_n_o[0]" Loc = "IO_EB_B1"; # LED D1 10 | Pin_out "led_n_o[1]" Loc = "IO_EB_B2"; # LED D2 11 | Pin_out "led_n_o[2]" Loc = "IO_EB_B3"; # LED D3 12 | Pin_out "led_n_o[3]" Loc = "IO_EB_B4"; # LED D4 13 | 14 | #Pin_out "debug_o[0]" Loc = "IO_NB_A4"; 15 | #Pin_out "debug_o[1]" Loc = "IO_NB_A5"; 16 | #Pin_out "debug_o[2]" Loc = "IO_NB_A6"; 17 | #Pin_out "debug_o[3]" Loc = "IO_NB_A7"; 18 | #Pin_out "debug_o[4]" Loc = "IO_NB_B4"; 19 | #Pin_out "debug_o[5]" Loc = "IO_NB_B5"; 20 | #Pin_out "debug_o[6]" Loc = "IO_NB_B6"; 21 | #Pin_out "debug_o[7]" Loc = "IO_NB_B7"; 22 | -------------------------------------------------------------------------------- /uart_aes/syn/write_cmds.txt: -------------------------------------------------------------------------------- 1 | 11 2 | 01 3 | 11 4 | 23 5 | 11 6 | 45 7 | 11 8 | 67 9 | 11 10 | 89 11 | 11 12 | AB 13 | 11 14 | CD 15 | 11 16 | EF 17 | 11 18 | 01 19 | 11 20 | 23 21 | 11 22 | 45 23 | 11 24 | 67 25 | 11 26 | 89 27 | 11 28 | AB 29 | 11 30 | CD 31 | 11 32 | EF 33 | 21 34 | 01 35 | 21 36 | 23 37 | 21 38 | 45 39 | 21 40 | 67 41 | 21 42 | 89 43 | 21 44 | AB 45 | 21 46 | CD 47 | 21 48 | EF 49 | 21 50 | 01 51 | 21 52 | 23 53 | 21 54 | 45 55 | 21 56 | 67 57 | 31 58 | 01 59 | 31 60 | 23 61 | 31 62 | 45 63 | 31 64 | 67 65 | 31 66 | 89 67 | 31 68 | AB 69 | 31 70 | CD 71 | 31 72 | EF 73 | 31 74 | 01 75 | 31 76 | 23 77 | 31 78 | 45 79 | 31 80 | 67 81 | 31 82 | 89 83 | 31 84 | AB 85 | 31 86 | CD 87 | 31 88 | EF 89 | 01 90 | 06 -------------------------------------------------------------------------------- /uart_loop/rtl/uart_loop.vhd: -------------------------------------------------------------------------------- 1 | -- Simple UART loop with UART RX & TX units and FIFO buffer 2 | -- between. It's working at baudrate 9600. 3 | 4 | 5 | library ieee ; 6 | use ieee.std_logic_1164.all; 7 | use ieee.numeric_std.all; 8 | 9 | library gatemate; 10 | use gatemate.components.all; 11 | 12 | 13 | entity uart_loop is 14 | port ( 15 | clk_i : in std_logic; -- 10 MHz clock 16 | rst_n_i : in std_logic; -- SW3 button 17 | uart_rx_i : in std_logic; -- PMODA IO3 18 | uart_tx_o : out std_logic -- PMODA IO5 19 | ); 20 | end entity uart_loop; 21 | 22 | 23 | architecture rtl of uart_loop is 24 | 25 | signal s_pll_clk : std_logic; 26 | signal s_pll_lock : std_logic; 27 | 28 | signal s_rst_n : std_logic; 29 | signal s_usr_rstn : std_logic; 30 | 31 | signal s_uart_rx_tdata : std_logic_vector(7 downto 0); 32 | signal s_uart_rx_tvalid : std_logic; 33 | signal s_uart_rx_tready : std_logic; 34 | 35 | signal s_uart_tx_tdata : std_logic_vector(7 downto 0); 36 | signal s_uart_tx_tvalid : std_logic; 37 | signal s_uart_tx_tready : std_logic; 38 | 39 | begin 40 | 41 | pll : CC_PLL 42 | generic map ( 43 | REF_CLK => "10", 44 | OUT_CLK => "10", 45 | PERF_MD => "SPEED" 46 | ) 47 | port map ( 48 | CLK_REF => clk_i, 49 | CLK_FEEDBACK => '0', 50 | USR_CLK_REF => '0', 51 | USR_LOCKED_STDY_RST => '0', 52 | USR_PLL_LOCKED_STDY => open, 53 | USR_PLL_LOCKED => s_pll_lock, 54 | CLK270 => open, 55 | CLK180 => open, 56 | CLK0 => s_pll_clk, 57 | CLK90 => open, 58 | CLK_REF_OUT => open 59 | ); 60 | 61 | cc_usr_rstn_inst : CC_USR_RSTN 62 | port map ( 63 | USR_RSTN => s_usr_rstn 64 | ); 65 | 66 | uart_rx : entity work.uart_rx 67 | generic map ( 68 | CLK_DIV => 1040 69 | ) 70 | port map ( 71 | -- globals 72 | rst_n_i => s_rst_n, 73 | clk_i => s_pll_clk, 74 | -- axis user interface 75 | tdata_o => s_uart_rx_tdata, 76 | tvalid_o => s_uart_rx_tvalid, 77 | tready_i => s_uart_rx_tready, 78 | -- uart interface 79 | rx_i => uart_rx_i 80 | ); 81 | 82 | axis_fifo : entity work.axis_fifo 83 | generic map ( 84 | DEPTH => 32, 85 | WIDTH => 8 86 | ) 87 | port map ( 88 | -- globals 89 | rst_n_i => s_rst_n, 90 | clk_i => s_pll_clk, 91 | -- uart rx interface 92 | tdata_i => s_uart_rx_tdata, 93 | tvalid_i => s_uart_rx_tvalid, 94 | tready_o => s_uart_rx_tready, 95 | -- uart tx interface 96 | tdata_o => s_uart_tx_tdata, 97 | tvalid_o => s_uart_tx_tvalid, 98 | tready_i => s_uart_tx_tready 99 | ); 100 | 101 | -- s_uart_tx_tdata <= s_uart_rx_tdata; 102 | -- s_uart_tx_tvalid <= s_uart_rx_tvalid; 103 | -- s_uart_rx_tready <= s_uart_tx_tready; 104 | 105 | uart_tx : entity work.uart_tx 106 | generic map ( 107 | CLK_DIV => 1040 108 | ) 109 | port map ( 110 | -- globals 111 | rst_n_i => s_rst_n, 112 | clk_i => s_pll_clk, 113 | -- axis user interface 114 | tdata_i => s_uart_tx_tdata, 115 | tvalid_i => s_uart_tx_tvalid, 116 | tready_o => s_uart_tx_tready, 117 | -- uart interface 118 | tx_o => uart_tx_o 119 | ); 120 | 121 | s_rst_n <= rst_n_i and s_pll_lock and s_usr_rstn; 122 | 123 | end architecture; 124 | -------------------------------------------------------------------------------- /uart_loop/rtl/uart_rx.vhd: -------------------------------------------------------------------------------- 1 | -- Copyright (c) 2022 by Torsten Meissner 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 | -- https://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 | 16 | 17 | library ieee; 18 | use ieee.std_logic_1164.all; 19 | use ieee.numeric_std.all; 20 | 21 | 22 | entity uart_rx is 23 | generic ( 24 | CLK_DIV : natural := 10 25 | ); 26 | port ( 27 | -- globals 28 | rst_n_i : in std_logic; 29 | clk_i : in std_logic; 30 | -- axis user interface 31 | tdata_o : out std_logic_vector(7 downto 0); 32 | tvalid_o : out std_logic; 33 | tready_i : in std_logic; 34 | -- uart interface 35 | rx_i : in std_logic 36 | ); 37 | end entity uart_rx; 38 | 39 | 40 | architecture rtl of uart_rx is 41 | 42 | type t_uart_state is (IDLE, RECEIVE, VALID); 43 | signal s_uart_state : t_uart_state; 44 | 45 | signal s_clk_en : std_logic; 46 | signal s_clk_cnt : natural range 0 to CLK_DIV-1; 47 | signal s_bit_cnt : natural range 0 to tdata_o'length+1; 48 | signal s_rx_d : std_logic_vector(3 downto 0); 49 | 50 | begin 51 | 52 | ClkDivP : process (clk_i, rst_n_i) is 53 | begin 54 | if (not rst_n_i) then 55 | s_clk_cnt <= CLK_DIV-1; 56 | elsif (rising_edge(clk_i)) then 57 | if (s_uart_state = IDLE) then 58 | s_clk_cnt <= CLK_DIV-2; 59 | elsif (s_uart_state = RECEIVE) then 60 | if (s_clk_cnt = 0) then 61 | s_clk_cnt <= CLK_DIV-1; 62 | else 63 | s_clk_cnt <= s_clk_cnt - 1; 64 | end if; 65 | end if; 66 | end if; 67 | end process ClkDivP; 68 | 69 | s_clk_en <= '1' when s_uart_state = RECEIVE and s_clk_cnt = CLK_DIV/2-1 else '0'; 70 | 71 | RxP : process (clk_i, rst_n_i) is 72 | begin 73 | if (not rst_n_i) then 74 | s_uart_state <= IDLE; 75 | tdata_o <= (others => '0'); 76 | s_rx_d <= x"1"; 77 | s_bit_cnt <= 0; 78 | elsif (rising_edge(clk_i)) then 79 | s_rx_d <= s_rx_d(2 downto 0) & rx_i; 80 | FsmL : case s_uart_state is 81 | when IDLE => 82 | s_bit_cnt <= tdata_o'length+1; 83 | if (s_rx_d = "1000") then 84 | s_uart_state <= RECEIVE; 85 | end if; 86 | when RECEIVE => 87 | if (s_clk_en) then 88 | if (s_bit_cnt = 0) then 89 | s_uart_state <= VALID; 90 | else 91 | tdata_o <= s_rx_d(3) & tdata_o(tdata_o'length-1 downto 1); 92 | s_bit_cnt <= s_bit_cnt - 1; 93 | end if; 94 | end if; 95 | when VALID => 96 | if (tready_i) then 97 | s_uart_state <= IDLE; 98 | end if; 99 | end case; 100 | end if; 101 | end process RxP; 102 | 103 | tvalid_o <= '1' when s_uart_state = VALID else '0'; 104 | 105 | end architecture rtl; 106 | -------------------------------------------------------------------------------- /uart_loop/rtl/uart_tx.vhd: -------------------------------------------------------------------------------- 1 | -- Copyright (c) 2022 by Torsten Meissner 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 | -- https://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 | 16 | 17 | library ieee; 18 | use ieee.std_logic_1164.all; 19 | use ieee.numeric_std.all; 20 | 21 | 22 | entity uart_tx is 23 | generic ( 24 | CLK_DIV : natural := 10 25 | ); 26 | port ( 27 | -- globals 28 | rst_n_i : in std_logic; 29 | clk_i : in std_logic; 30 | -- axis user interface 31 | tdata_i : in std_logic_vector(7 downto 0); 32 | tvalid_i : in std_logic; 33 | tready_o : out std_logic; 34 | -- uart interface 35 | tx_o : out std_logic 36 | ); 37 | end entity uart_tx; 38 | 39 | 40 | architecture rtl of uart_tx is 41 | 42 | type t_uart_state is (IDLE, SEND); 43 | signal s_uart_state : t_uart_state; 44 | 45 | signal s_data : std_logic_vector(tdata_i'length+1 downto 0); 46 | signal s_clk_cnt : natural range 0 to CLK_DIV-1; 47 | signal s_clk_en : std_logic; 48 | signal s_bit_cnt : natural range 0 to s_data'length-1; 49 | 50 | begin 51 | 52 | ClkDivP : process (clk_i, rst_n_i) is 53 | begin 54 | if (not rst_n_i) then 55 | s_clk_cnt <= CLK_DIV-1; 56 | elsif (rising_edge(clk_i)) then 57 | if (s_uart_state = IDLE) then 58 | s_clk_cnt <= CLK_DIV-2; 59 | elsif (s_uart_state = SEND) then 60 | if (s_clk_cnt = 0) then 61 | s_clk_cnt <= CLK_DIV-1; 62 | else 63 | s_clk_cnt <= s_clk_cnt - 1; 64 | end if; 65 | end if; 66 | end if; 67 | end process ClkDivP; 68 | 69 | s_clk_en <= '1' when s_uart_state = SEND and s_clk_cnt = 0 else '0'; 70 | 71 | TxP : process (clk_i, rst_n_i) is 72 | begin 73 | if (not rst_n_i) then 74 | s_uart_state <= IDLE; 75 | s_data <= (0 => '1', others => '0'); 76 | s_bit_cnt <= 0; 77 | elsif (rising_edge(clk_i)) then 78 | FsmL : case s_uart_state is 79 | when IDLE => 80 | s_bit_cnt <= s_data'length-1; 81 | if (tvalid_i) then 82 | s_data <= '1' & tdata_i & '0'; 83 | s_uart_state <= SEND; 84 | end if; 85 | when SEND => 86 | if (s_clk_en) then 87 | s_data <= '1' & s_data(s_data'length-1 downto 1); 88 | if (s_bit_cnt = 0) then 89 | s_uart_state <= IDLE; 90 | else 91 | s_bit_cnt <= s_bit_cnt - 1; 92 | end if; 93 | end if; 94 | end case; 95 | end if; 96 | end process TxP; 97 | 98 | tready_o <= '1' when s_uart_state = IDLE else '0'; 99 | 100 | tx_o <= s_data(0); 101 | 102 | end architecture rtl; 103 | -------------------------------------------------------------------------------- /uart_loop/sim/Makefile: -------------------------------------------------------------------------------- 1 | DESIGN_NAME := uart_loop 2 | LIB_SRC := ../../lib/rtl_components.vhd ../../lib/sim_components.vhd 3 | RTL_SRC := ../../lib/user_components.vhd ../rtl/uart_tx.vhd ../rtl/uart_rx.vhd ../rtl/${DESIGN_NAME}.vhd 4 | SIM_SRC := tb_${DESIGN_NAME}.vhd 5 | SIM_FLAGS := --std=08 -fpsl --workdir=work 6 | 7 | .PHONY: all compile sim clean 8 | 9 | all: sim 10 | compile: tb_${DESIGN_NAME} 11 | 12 | tb_${DESIGN_NAME}: ${LIB_SRC} ${RTL_SRC} ${SIM_SRC} 13 | mkdir -p work 14 | @echo "Analyze gatemate library ..." 15 | ghdl -a ${SIM_FLAGS} --work=gatemate ${LIB_SRC} 16 | @echo "Analyze testbench & design ..." 17 | ghdl -a ${SIM_FLAGS} -Pwork ${RTL_SRC} ${SIM_SRC} 18 | @echo "Elaborate testbench & design ..." 19 | ghdl -e ${SIM_FLAGS} -Pwork $@ 20 | 21 | sim: tb_${DESIGN_NAME} 22 | @echo "Run testbench ..." 23 | ghdl -r ${SIM_FLAGS} -Pwork tb_${DESIGN_NAME} --assert-level=error --wave=tb_${DESIGN_NAME}.ghw 24 | 25 | work: 26 | mkdir $@ 27 | 28 | clean: 29 | @echo "Cleaning simulation files ..." 30 | rm -rf tb_${DESIGN_NAME} *.o work/ 31 | -------------------------------------------------------------------------------- /uart_loop/sim/tb_uart_loop.vhd: -------------------------------------------------------------------------------- 1 | library ieee ; 2 | use ieee.std_logic_1164.all; 3 | use ieee.numeric_std.all; 4 | 5 | use std.env.all; 6 | 7 | 8 | entity tb_uart_loop is 9 | end entity tb_uart_loop; 10 | 11 | 12 | architecture sim of tb_uart_loop is 13 | 14 | signal s_clk : std_logic := '1'; 15 | signal s_rst_n : std_logic := '0'; 16 | 17 | signal s_uart_rx : std_logic := '1'; 18 | signal s_uart_tx : std_logic; 19 | 20 | constant c_baudrate : natural := 9600; 21 | constant c_period_ns : time := 1000000000 / c_baudrate * ns; 22 | 23 | procedure uart_send ( data : in std_logic_vector(7 downto 0); 24 | signal tx : out std_logic) is 25 | begin 26 | report "UART send: 0x" & to_hstring(data); 27 | tx <= '0'; 28 | wait for c_period_ns; 29 | for i in 0 to 7 loop 30 | tx <= data(i); 31 | wait for c_period_ns; 32 | end loop; 33 | tx <= '1'; 34 | wait for c_period_ns; 35 | end procedure; 36 | 37 | procedure uart_recv ( data : out std_logic_vector(7 downto 0); 38 | signal rx : in std_logic) is 39 | begin 40 | wait until not rx; 41 | wait for c_period_ns; -- Skip start bit 42 | wait for c_period_ns/2; 43 | for i in 0 to 7 loop 44 | data(i) := rx; 45 | wait for c_period_ns; 46 | end loop; 47 | report "UART recv: 0x" & to_hstring(data); 48 | end procedure; 49 | 50 | begin 51 | 52 | dut : entity work.uart_loop 53 | port map ( 54 | clk_i => s_clk, 55 | rst_n_i => s_rst_n, 56 | uart_rx_i => s_uart_rx, 57 | uart_tx_o => s_uart_tx 58 | ); 59 | 60 | s_rst_n <= '1' after 120 ns; 61 | s_clk <= not s_clk after 50 ns; 62 | 63 | SendP : process is 64 | variable v_data : std_logic_vector(7 downto 0); 65 | begin 66 | wait until s_rst_n; 67 | wait until rising_edge(s_clk); 68 | wait for 200 us; 69 | -- First read all registers 70 | for i in 0 to 255 loop 71 | v_data := std_logic_vector(to_unsigned(i, 8)); 72 | uart_send(v_data, s_uart_rx); 73 | end loop; 74 | wait; 75 | end process; 76 | 77 | ReceiveP : process is 78 | variable v_exp : std_logic_vector(7 downto 0); 79 | variable v_data : std_logic_vector(7 downto 0); 80 | begin 81 | wait until s_rst_n; 82 | wait until rising_edge(s_clk); 83 | -- First read all registers 84 | for i in 0 to 255 loop 85 | v_exp := std_logic_vector(to_unsigned(i, 8)); 86 | uart_recv(v_data, s_uart_tx); 87 | assert v_data = v_exp 88 | report "UART receive error, got 0x" & to_hstring(v_data) & ", expected 0x" & to_hstring(v_exp) 89 | severity failure; 90 | end loop; 91 | wait for 200 us; 92 | report "Simulation finished :-)"; 93 | stop(0); 94 | end process; 95 | 96 | end architecture; 97 | -------------------------------------------------------------------------------- /uart_loop/syn/Makefile: -------------------------------------------------------------------------------- 1 | DESIGN_NAME := uart_loop 2 | WORK_FILES := ../../lib/user_components.vhd ../rtl/uart_tx.vhd ../rtl/uart_rx.vhd ../rtl/${DESIGN_NAME}.vhd 3 | GM_FILES := ../../lib/rtl_components.vhd 4 | GHDL_FLAGS := --std=08 --workdir=build -Pbuild 5 | YOSYSPIPE := -nomx8 -retime 6 | # ATTENTION: -luttree option seems to mis-synthesize the design, broken with synth_gatemate? 7 | PNRFLAGS := -om 3 8 | PNRTOOL := $(shell which p_r) 9 | 10 | .PHONY: all syn imp prog syn_sim imp_sim 11 | 12 | all: imp 13 | syn: ${DESIGN_NAME}.v 14 | imp: ${DESIGN_NAME}.bit 15 | 16 | build/work-obj08.cf: ${WORK_FILES} build/gatemate-obj08.cf 17 | ghdl -a ${GHDL_FLAGS} --work=work ${WORK_FILES} 18 | 19 | build/gatemate-obj08.cf: ${GM_FILES} 20 | mkdir -p build 21 | ghdl -a ${GHDL_FLAGS} --work=gatemate ${GM_FILES} 22 | 23 | # Synthesis target for implementation 24 | ${DESIGN_NAME}.v: build/work-obj08.cf 25 | yosys -m ghdl -p 'ghdl ${GHDL_FLAGS} --warn-no-binding --no-formal ${DESIGN_NAME}; synth_gatemate -top $(DESIGN_NAME) ${YOSYSPIPE} -vlog $@' \ 26 | 2>&1 | tee build/yosys-report.txt 27 | 28 | # Implementation target for FPGA 29 | ${DESIGN_NAME}.bit: ${DESIGN_NAME}.v ${DESIGN_NAME}.ccf 30 | cd build && \ 31 | ${PNRTOOL} -i ../${DESIGN_NAME}.v -o $@ --ccf ../${DESIGN_NAME}.ccf $(PNRFLAGS) \ 32 | 2>&1 | tee p_r-report.txt && \ 33 | mv ${DESIGN_NAME}*.bit ../$@ 34 | 35 | # Post-synthesis simulation target 36 | syn_sim: ${DESIGN_NAME}.v 37 | iverilog -g2012 -o tb_${DESIGN_NAME}_syn.vvp ${DESIGN_NAME}.v tb_${DESIGN_NAME}.v /usr/local/share/yosys/gatemate/cells_sim.v 38 | vvp -N tb_${DESIGN_NAME}_syn.vvp -fst 39 | 40 | # Post-implementation simulation target 41 | imp_sim: ${DESIGN_NAME}.bit 42 | iverilog -g2012 -o tb_${DESIGN_NAME}_imp.vvp build/${DESIGN_NAME}_00.v tb_${DESIGN_NAME}.v /opt/cc-toolchain-linux/bin/p_r/cpelib.v 43 | vvp -N tb_${DESIGN_NAME}_imp.vvp -fst 44 | 45 | # FPGA FW load per JTAG 46 | prog: ${DESIGN_NAME}.bit 47 | openFPGALoader -b gatemate_evb_jtag $< 48 | 49 | clean : 50 | echo "# Cleaning files" 51 | rm -rf build ${DESIGN_NAME}.v ${DESIGN_NAME}_sim.v ${DESIGN_NAME}.vhd ${DESIGN_NAME}.bit *.vvp *.fst 52 | -------------------------------------------------------------------------------- /uart_loop/syn/tb_uart_loop.v: -------------------------------------------------------------------------------- 1 | `timescale 1 ns/10 ps // time-unit = 1 ns, precision = 10 ps 2 | 3 | // simplified CC_PLL model 4 | module CC_PLL #( 5 | parameter REF_CLK = "", // e.g. "10.0" 6 | parameter OUT_CLK = "", // e.g. "50.0" 7 | parameter PERF_MD = "", // LOWPOWER, ECONOMY, SPEED 8 | parameter LOW_JITTER = 1, 9 | parameter CI_FILTER_CONST = 2, 10 | parameter CP_FILTER_CONST = 4 11 | )( 12 | input CLK_REF, CLK_FEEDBACK, USR_CLK_REF, 13 | input USR_LOCKED_STDY_RST, USR_SET_SEL, 14 | output USR_PLL_LOCKED_STDY, USR_PLL_LOCKED, 15 | output CLK270, CLK180, CLK90, CLK0, CLK_REF_OUT 16 | ); 17 | 18 | reg r_pll_clk; 19 | reg r_user_pll_locked; 20 | 21 | // OUT_FREQ = 10 MHz 22 | integer clk_half_period = 50; 23 | 24 | initial begin 25 | r_pll_clk = 1'b0; 26 | r_user_pll_locked = 1'b1; 27 | end 28 | 29 | always #clk_half_period r_pll_clk = ~r_pll_clk; 30 | 31 | assign CLK0 = r_pll_clk; 32 | assign USR_PLL_LOCKED = r_user_pll_locked; 33 | 34 | endmodule 35 | 36 | 37 | // simplified CC_CFG_END model 38 | module CC_CFG_END ( 39 | output CFG_END 40 | ); 41 | 42 | assign CFG_END = 1'b1; 43 | 44 | endmodule 45 | 46 | module tb_uart_loop; 47 | 48 | // DUT in/out 49 | reg clk = 1'b0; 50 | reg rst_n = 1'b1; 51 | reg uart_rx; 52 | wire uart_tx; 53 | 54 | // Testbench variables 55 | reg [7:0] tx_data = 8'h0; 56 | reg [7:0] rx_data = 8'h0; 57 | reg [7:0] ref_data [0:15]; 58 | 59 | // Testbench 1/2 clock period 60 | localparam clk_half_period = 50; 61 | 62 | // UART period calculation (9600 baud) 63 | localparam uart_bit_period = 1000000000 / 9600; 64 | localparam uart_bit_half_period = uart_bit_period/2; 65 | 66 | uart_loop UUT (.clk_i(clk), .rst_n_i(rst_n), .uart_rx_i(uart_rx), .uart_tx_o(uart_tx)); 67 | 68 | // set dumpfile 69 | initial begin 70 | $dumpfile ("tb_uart_loop.fst"); 71 | $dumpvars (0, tb_uart_loop); 72 | end 73 | 74 | // Setup simulation 75 | initial begin 76 | uart_rx = 1'b1; 77 | #1 rst_n = 1'b0; 78 | #120 rst_n = 1'b1; 79 | end 80 | 81 | // Generate 10 mhz clock 82 | always #clk_half_period clk = !clk; 83 | 84 | // Stimuli generator 85 | initial 86 | forever @(posedge rst_n) begin 87 | uart_rx = 1'b1; 88 | #uart_bit_period; 89 | for (integer i = 0; i < $size(ref_data); i = i + 1) begin 90 | tx_data = {$random} % 255; 91 | ref_data[i] = tx_data; 92 | $display ("UART send: 0x%h", tx_data); 93 | uart_rx = 1'b0; 94 | #uart_bit_period; 95 | for (integer i = 0; i <= 7; i = i + 1) begin 96 | uart_rx = tx_data[i]; 97 | #uart_bit_period; 98 | end 99 | uart_rx = 1'b1; 100 | #uart_bit_period; 101 | #uart_bit_period; 102 | #uart_bit_period; 103 | end 104 | end 105 | 106 | // Checker 107 | initial begin 108 | @(posedge rst_n) 109 | for (integer i = 0; i < $size(ref_data); i = i + 1) begin 110 | @(negedge uart_tx) 111 | #uart_bit_period; 112 | #uart_bit_half_period; 113 | for (integer i = 0; i <= 7; i = i + 1) begin 114 | rx_data[i] = uart_tx; 115 | #uart_bit_period; 116 | end 117 | assert (rx_data == ref_data[i]) 118 | $display("UART recv: 0x%h", rx_data); 119 | else 120 | $error("UART receive error, got 0x%h, expected 0x%h", rx_data, ref_data[i]); 121 | end 122 | $display ("UART tests finished"); 123 | $finish; 124 | end 125 | 126 | 127 | endmodule 128 | -------------------------------------------------------------------------------- /uart_loop/syn/uart_loop.ccf: -------------------------------------------------------------------------------- 1 | # Configuration for the Gatemate eval board 2 | 3 | Pin_in "clk_i" Loc = "IO_SB_A8" | SCHMITT_TRIGGER=true; 4 | Pin_in "rst_n_i" Loc = "IO_EB_B0"; # SW3 5 | 6 | Pin_in "uart_rx_i" Loc = "IO_NB_A1"; # PMODA IO3 7 | Pin_out "uart_tx_o" Loc = "IO_NB_A0"; # PMODA IO1 8 | 9 | Pin_out "debug_o[0]" Loc = "IO_NB_A4"; 10 | Pin_out "debug_o[1]" Loc = "IO_NB_A5"; 11 | Pin_out "debug_o[2]" Loc = "IO_NB_A6"; 12 | Pin_out "debug_o[3]" Loc = "IO_NB_A7"; 13 | Pin_out "debug_o[4]" Loc = "IO_NB_B4"; 14 | Pin_out "debug_o[5]" Loc = "IO_NB_B5"; 15 | Pin_out "debug_o[6]" Loc = "IO_NB_B6"; 16 | Pin_out "debug_o[7]" Loc = "IO_NB_B7"; 17 | -------------------------------------------------------------------------------- /uart_reg/rtl/uart_ctrl.vhd: -------------------------------------------------------------------------------- 1 | -- UART register 2 | 3 | -- Register file with 8 registers storing values of one byte each. 4 | -- 5 | -- The first received byte on the axis in port contains command & address: 6 | -- 7 | -- 7 reserved 8 | -- 6:4 register address 9 | -- 3:0 command 10 | -- 0x0 read 11 | -- 0x1 write 12 | -- 13 | -- In case of a write command, the payload has to follow 14 | -- with the next byte. 15 | -- 16 | -- In case of a read command, the value of the addressed 17 | -- register is returned on the axis out port. 18 | -- 19 | -- Register at address 0 is special. It contains the version 20 | -- and is read-only. Writes to that register are ignored. 21 | 22 | 23 | library ieee; 24 | use ieee.std_logic_1164.all; 25 | use ieee.numeric_std.all; 26 | 27 | 28 | entity uart_ctrl is 29 | port ( 30 | -- globals 31 | rst_n_i : in std_logic; 32 | clk_i : in std_logic; 33 | -- axis in 34 | tdata_i : in std_logic_vector(7 downto 0); 35 | tvalid_i : in std_logic; 36 | tready_o : out std_logic; 37 | -- axis out 38 | tdata_o : out std_logic_vector(7 downto 0); 39 | tvalid_o : out std_logic; 40 | tready_i : in std_logic 41 | ); 42 | end entity uart_ctrl; 43 | 44 | 45 | architecture rtl of uart_ctrl is 46 | 47 | type t_state is (IDLE, GET_CMD, RECV_DATA, SEND_DATA); 48 | signal s_state : t_state; 49 | 50 | subtype t_reg is std_logic_vector(7 downto 0); 51 | 52 | type t_reg_file is array (1 to 7) of t_reg; 53 | signal s_reg_file : t_reg_file; 54 | 55 | constant c_version : t_reg := x"01"; 56 | 57 | signal s_reg_addr : natural range 0 to 7; 58 | signal s_reg_data : t_reg; 59 | 60 | subtype t_cmd is std_ulogic_vector(3 downto 0); 61 | constant c_read : t_cmd := x"0"; 62 | constant c_write : t_cmd := x"1"; 63 | 64 | alias a_tdata_cmd is tdata_i(3 downto 0); 65 | alias a_tdata_addr is tdata_i(6 downto 4); 66 | 67 | begin 68 | 69 | -- Register memory, omitted reset of memory during synthesis 70 | -- for better RAM detection 71 | process (clk_i, rst_n_i) is 72 | begin 73 | if (not rst_n_i) then 74 | -- synthesis translate_off 75 | s_reg_file <= (others => (others => '0')); 76 | -- synthesis translate_on 77 | s_reg_data <= (others => '0'); 78 | elsif (rising_edge(clk_i)) then 79 | -- Write 80 | if (s_state = RECV_DATA and tvalid_i = '1') then 81 | -- Ignore writes to version register 82 | if (s_reg_addr /= 0) then 83 | s_reg_file(s_reg_addr) <= tdata_i; 84 | end if; 85 | end if; 86 | -- Always read, regardless of write or read command 87 | if (s_state = GET_CMD) then 88 | if (s_reg_addr /= 0) then 89 | s_reg_data <= s_reg_file(s_reg_addr); 90 | end if; 91 | end if; 92 | end if; 93 | end process; 94 | 95 | -- Control state machine 96 | process (clk_i, rst_n_i) is 97 | begin 98 | if (not rst_n_i) then 99 | s_state <= IDLE; 100 | s_reg_addr <= 0; 101 | elsif (rising_edge(clk_i)) then 102 | case s_state is 103 | when IDLE => 104 | if (tvalid_i) then 105 | s_state <= GET_CMD; 106 | s_reg_addr <= to_integer(unsigned(a_tdata_addr)); 107 | end if; 108 | when GET_CMD => 109 | if (a_tdata_cmd = c_read) then 110 | s_state <= SEND_DATA; 111 | elsif (a_tdata_cmd = c_write) then 112 | s_state <= RECV_DATA; 113 | else 114 | s_state <= IDLE; 115 | end if; 116 | when RECV_DATA => 117 | if (tvalid_i) then 118 | s_state <= IDLE; 119 | end if; 120 | when SEND_DATA => 121 | if (tready_i) then 122 | s_state <= IDLE; 123 | end if; 124 | when others => 125 | null; 126 | end case; 127 | end if; 128 | end process; 129 | 130 | tready_o <= '1' when s_state = GET_CMD or s_state = RECV_DATA else '0'; 131 | 132 | tdata_o <= c_version when s_reg_addr = 0 else s_reg_data; 133 | tvalid_o <= '1' when s_state = SEND_DATA else '0'; 134 | 135 | end architecture; 136 | -------------------------------------------------------------------------------- /uart_reg/rtl/uart_reg.vhd: -------------------------------------------------------------------------------- 1 | -- This design implements a register file which can 2 | -- be accessed by an UART with 9600 baud 3 | -- 4 | -- See into uart_ctrl.vhd for documentation of the protocol 5 | -- used to read / write the register file. 6 | 7 | 8 | library ieee ; 9 | use ieee.std_logic_1164.all; 10 | use ieee.numeric_std.all; 11 | 12 | library gatemate; 13 | use gatemate.components.all; 14 | 15 | 16 | entity uart_reg is 17 | port ( 18 | clk_i : in std_logic; -- 10 MHz clock 19 | rst_n_i : in std_logic; -- SW3 button 20 | uart_rx_i : in std_logic; -- PMODA IO3 21 | uart_tx_o : out std_logic -- PMODA IO5 22 | ); 23 | end entity uart_reg; 24 | 25 | 26 | architecture rtl of uart_reg is 27 | 28 | signal s_pll_clk : std_logic; 29 | signal s_pll_lock : std_logic; 30 | 31 | signal s_rst_n : std_logic; 32 | signal s_usr_rstn : std_logic; 33 | 34 | signal s_uart_rx_tdata : std_logic_vector(7 downto 0); 35 | signal s_uart_rx_tvalid : std_logic; 36 | signal s_uart_rx_tready : std_logic; 37 | 38 | signal s_uart_tx_tdata : std_logic_vector(7 downto 0); 39 | signal s_uart_tx_tvalid : std_logic; 40 | signal s_uart_tx_tready : std_logic; 41 | 42 | begin 43 | 44 | pll : CC_PLL 45 | generic map ( 46 | REF_CLK => "10", 47 | OUT_CLK => "10", 48 | PERF_MD => "SPEED" 49 | ) 50 | port map ( 51 | CLK_REF => clk_i, 52 | CLK_FEEDBACK => '0', 53 | USR_CLK_REF => '0', 54 | USR_LOCKED_STDY_RST => '0', 55 | USR_PLL_LOCKED_STDY => open, 56 | USR_PLL_LOCKED => s_pll_lock, 57 | CLK270 => open, 58 | CLK180 => open, 59 | CLK0 => s_pll_clk, 60 | CLK90 => open, 61 | CLK_REF_OUT => open 62 | ); 63 | 64 | cc_usr_rstn_inst : CC_USR_RSTN 65 | port map ( 66 | USR_RSTN => s_usr_rstn 67 | ); 68 | 69 | uart_rx : entity work.uart_rx 70 | generic map ( 71 | CLK_DIV => 1040 72 | ) 73 | port map ( 74 | -- globals 75 | rst_n_i => s_rst_n, 76 | clk_i => s_pll_clk, 77 | -- axis user interface 78 | tdata_o => s_uart_rx_tdata, 79 | tvalid_o => s_uart_rx_tvalid, 80 | tready_i => s_uart_rx_tready, 81 | -- uart interface 82 | rx_i => uart_rx_i 83 | ); 84 | 85 | uart_ctrl : entity work.uart_ctrl 86 | port map ( 87 | -- globals 88 | rst_n_i => s_rst_n, 89 | clk_i => s_pll_clk, 90 | -- uart rx interface 91 | tdata_i => s_uart_rx_tdata, 92 | tvalid_i => s_uart_rx_tvalid, 93 | tready_o => s_uart_rx_tready, 94 | -- uart tx interface 95 | tdata_o => s_uart_tx_tdata, 96 | tvalid_o => s_uart_tx_tvalid, 97 | tready_i => s_uart_tx_tready 98 | ); 99 | 100 | uart_tx : entity work.uart_tx 101 | generic map ( 102 | CLK_DIV => 1040 103 | ) 104 | port map ( 105 | -- globals 106 | rst_n_i => s_rst_n, 107 | clk_i => s_pll_clk, 108 | -- axis user interface 109 | tdata_i => s_uart_tx_tdata, 110 | tvalid_i => s_uart_tx_tvalid, 111 | tready_o => s_uart_tx_tready, 112 | -- uart interface 113 | tx_o => uart_tx_o 114 | ); 115 | 116 | s_rst_n <= rst_n_i and s_pll_lock and s_usr_rstn; 117 | 118 | end architecture; 119 | -------------------------------------------------------------------------------- /uart_reg/rtl/uart_rx.vhd: -------------------------------------------------------------------------------- 1 | -- Copyright (c) 2022 by Torsten Meissner 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 | -- https://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 | 16 | 17 | library ieee; 18 | use ieee.std_logic_1164.all; 19 | use ieee.numeric_std.all; 20 | 21 | 22 | entity uart_rx is 23 | generic ( 24 | CLK_DIV : natural := 10 25 | ); 26 | port ( 27 | -- globals 28 | rst_n_i : in std_logic; 29 | clk_i : in std_logic; 30 | -- axis user interface 31 | tdata_o : out std_logic_vector(7 downto 0); 32 | tvalid_o : out std_logic; 33 | tready_i : in std_logic; 34 | -- uart interface 35 | rx_i : in std_logic 36 | ); 37 | end entity uart_rx; 38 | 39 | 40 | architecture rtl of uart_rx is 41 | 42 | type t_uart_state is (IDLE, RECEIVE, VALID); 43 | signal s_uart_state : t_uart_state; 44 | 45 | signal s_clk_en : std_logic; 46 | signal s_clk_cnt : natural range 0 to CLK_DIV-1; 47 | signal s_bit_cnt : natural range 0 to tdata_o'length+1; 48 | signal s_rx_d : std_logic_vector(3 downto 0); 49 | 50 | begin 51 | 52 | ClkDivP : process (clk_i, rst_n_i) is 53 | begin 54 | if (not rst_n_i) then 55 | s_clk_cnt <= CLK_DIV-1; 56 | elsif (rising_edge(clk_i)) then 57 | if (s_uart_state = IDLE) then 58 | s_clk_cnt <= CLK_DIV-2; 59 | elsif (s_uart_state = RECEIVE) then 60 | if (s_clk_cnt = 0) then 61 | s_clk_cnt <= CLK_DIV-1; 62 | else 63 | s_clk_cnt <= s_clk_cnt - 1; 64 | end if; 65 | end if; 66 | end if; 67 | end process ClkDivP; 68 | 69 | s_clk_en <= '1' when s_uart_state = RECEIVE and s_clk_cnt = CLK_DIV/2-1 else '0'; 70 | 71 | RxP : process (clk_i, rst_n_i) is 72 | begin 73 | if (not rst_n_i) then 74 | s_uart_state <= IDLE; 75 | tdata_o <= (others => '0'); 76 | s_rx_d <= x"1"; 77 | s_bit_cnt <= 0; 78 | elsif (rising_edge(clk_i)) then 79 | s_rx_d <= s_rx_d(2 downto 0) & rx_i; 80 | FsmL : case s_uart_state is 81 | when IDLE => 82 | s_bit_cnt <= tdata_o'length+1; 83 | if (s_rx_d = "1000") then 84 | s_uart_state <= RECEIVE; 85 | end if; 86 | when RECEIVE => 87 | if (s_clk_en) then 88 | if (s_bit_cnt = 0) then 89 | s_uart_state <= VALID; 90 | else 91 | tdata_o <= s_rx_d(3) & tdata_o(tdata_o'length-1 downto 1); 92 | s_bit_cnt <= s_bit_cnt - 1; 93 | end if; 94 | end if; 95 | when VALID => 96 | if (tready_i) then 97 | s_uart_state <= IDLE; 98 | end if; 99 | end case; 100 | end if; 101 | end process RxP; 102 | 103 | tvalid_o <= '1' when s_uart_state = VALID else '0'; 104 | 105 | end architecture rtl; 106 | -------------------------------------------------------------------------------- /uart_reg/rtl/uart_tx.vhd: -------------------------------------------------------------------------------- 1 | -- Copyright (c) 2022 by Torsten Meissner 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 | -- https://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 | 16 | 17 | library ieee; 18 | use ieee.std_logic_1164.all; 19 | use ieee.numeric_std.all; 20 | 21 | 22 | entity uart_tx is 23 | generic ( 24 | CLK_DIV : natural := 10 25 | ); 26 | port ( 27 | -- globals 28 | rst_n_i : in std_logic; 29 | clk_i : in std_logic; 30 | -- axis user interface 31 | tdata_i : in std_logic_vector(7 downto 0); 32 | tvalid_i : in std_logic; 33 | tready_o : out std_logic; 34 | -- uart interface 35 | tx_o : out std_logic 36 | ); 37 | end entity uart_tx; 38 | 39 | 40 | architecture rtl of uart_tx is 41 | 42 | type t_uart_state is (IDLE, SEND); 43 | signal s_uart_state : t_uart_state; 44 | 45 | signal s_data : std_logic_vector(tdata_i'length+1 downto 0); 46 | signal s_clk_cnt : natural range 0 to CLK_DIV-1; 47 | signal s_clk_en : std_logic; 48 | signal s_bit_cnt : natural range 0 to s_data'length-1; 49 | 50 | begin 51 | 52 | ClkDivP : process (clk_i, rst_n_i) is 53 | begin 54 | if (not rst_n_i) then 55 | s_clk_cnt <= CLK_DIV-1; 56 | elsif (rising_edge(clk_i)) then 57 | if (s_uart_state = IDLE) then 58 | s_clk_cnt <= CLK_DIV-2; 59 | elsif (s_uart_state = SEND) then 60 | if (s_clk_cnt = 0) then 61 | s_clk_cnt <= CLK_DIV-1; 62 | else 63 | s_clk_cnt <= s_clk_cnt - 1; 64 | end if; 65 | end if; 66 | end if; 67 | end process ClkDivP; 68 | 69 | s_clk_en <= '1' when s_uart_state = SEND and s_clk_cnt = 0 else '0'; 70 | 71 | TxP : process (clk_i, rst_n_i) is 72 | begin 73 | if (not rst_n_i) then 74 | s_uart_state <= IDLE; 75 | s_data <= (0 => '1', others => '0'); 76 | s_bit_cnt <= 0; 77 | elsif (rising_edge(clk_i)) then 78 | FsmL : case s_uart_state is 79 | when IDLE => 80 | s_bit_cnt <= s_data'length-1; 81 | if (tvalid_i) then 82 | s_data <= '1' & tdata_i & '0'; 83 | s_uart_state <= SEND; 84 | end if; 85 | when SEND => 86 | if (s_clk_en) then 87 | s_data <= '1' & s_data(s_data'length-1 downto 1); 88 | if (s_bit_cnt = 0) then 89 | s_uart_state <= IDLE; 90 | else 91 | s_bit_cnt <= s_bit_cnt - 1; 92 | end if; 93 | end if; 94 | end case; 95 | end if; 96 | end process TxP; 97 | 98 | tready_o <= '1' when s_uart_state = IDLE else '0'; 99 | 100 | tx_o <= s_data(0); 101 | 102 | end architecture rtl; 103 | -------------------------------------------------------------------------------- /uart_reg/sim/Makefile: -------------------------------------------------------------------------------- 1 | DESIGN_NAME := uart_reg 2 | LIB_SRC := ../../lib/rtl_components.vhd ../../lib/sim_components.vhd 3 | RTL_SRC := ../rtl/uart_tx.vhd ../rtl/uart_rx.vhd ../rtl/uart_ctrl.vhd ../rtl/${DESIGN_NAME}.vhd 4 | SIM_SRC := tb_${DESIGN_NAME}.vhd 5 | SIM_FLAGS := --std=08 -fpsl --workdir=work 6 | 7 | .PHONY: all compile sim clean 8 | 9 | all: sim 10 | compile: tb_${DESIGN_NAME} 11 | 12 | tb_${DESIGN_NAME}: ${LIB_SRC} ${RTL_SRC} ${SIM_SRC} 13 | mkdir -p work 14 | @echo "Analyze gatemate library ..." 15 | ghdl -a ${SIM_FLAGS} --work=gatemate ${LIB_SRC} 16 | @echo "Analyze testbench & design ..." 17 | ghdl -a ${SIM_FLAGS} -Pwork ${RTL_SRC} ${SIM_SRC} 18 | @echo "Elaborate testbench & design ..." 19 | ghdl -e ${SIM_FLAGS} -Pwork $@ 20 | 21 | sim: tb_${DESIGN_NAME} 22 | @echo "Run testbench ..." 23 | ghdl -r ${SIM_FLAGS} -Pwork tb_${DESIGN_NAME} --assert-level=error 24 | 25 | work: 26 | mkdir $@ 27 | 28 | clean: 29 | @echo "Cleaning simulation files ..." 30 | rm -rf tb_${DESIGN_NAME} *.o work/ 31 | -------------------------------------------------------------------------------- /uart_reg/sim/tb_uart_reg.vhd: -------------------------------------------------------------------------------- 1 | library ieee ; 2 | use ieee.std_logic_1164.all; 3 | use ieee.numeric_std.all; 4 | 5 | use std.env.all; 6 | 7 | 8 | entity tb_uart_reg is 9 | end entity tb_uart_reg; 10 | 11 | 12 | architecture sim of tb_uart_reg is 13 | 14 | signal s_clk : std_logic := '1'; 15 | signal s_rst_n : std_logic := '0'; 16 | 17 | signal s_uart_rx : std_logic := '1'; 18 | signal s_uart_tx : std_logic; 19 | 20 | constant c_baudrate : natural := 9600; 21 | constant c_period_ns : time := 1000000000 / c_baudrate * ns; 22 | 23 | procedure uart_send ( data : in std_logic_vector(7 downto 0); 24 | signal tx : out std_logic) is 25 | begin 26 | report "UART send: 0x" & to_hstring(data); 27 | tx <= '0'; 28 | wait for c_period_ns; 29 | for i in 0 to 7 loop 30 | tx <= data(i); 31 | wait for c_period_ns; 32 | end loop; 33 | tx <= '1'; 34 | wait for c_period_ns; 35 | end procedure; 36 | 37 | procedure uart_recv ( data : out std_logic_vector(7 downto 0); 38 | signal rx : in std_logic) is 39 | begin 40 | wait until not rx; 41 | wait for c_period_ns; -- Skip start bit 42 | wait for c_period_ns/2; 43 | for i in 0 to 7 loop 44 | data(i) := rx; 45 | wait for c_period_ns; 46 | end loop; 47 | report "UART recv: 0x" & to_hstring(data); 48 | end procedure; 49 | 50 | begin 51 | 52 | dut : entity work.uart_reg 53 | port map ( 54 | clk_i => s_clk, 55 | rst_n_i => s_rst_n, 56 | uart_rx_i => s_uart_rx, 57 | uart_tx_o => s_uart_tx 58 | ); 59 | 60 | s_rst_n <= '1' after 120 ns; 61 | s_clk <= not s_clk after 50 ns; 62 | 63 | SendP : process is 64 | variable v_data : std_logic_vector(7 downto 0); 65 | begin 66 | wait until s_rst_n; 67 | wait until rising_edge(s_clk); 68 | wait for 200 us; 69 | -- First read all registers 70 | for i in 0 to 7 loop 71 | v_data := std_logic_vector(to_unsigned(i, 4)) & x"0"; 72 | uart_send(v_data, s_uart_rx); 73 | end loop; 74 | -- Then write all registers 75 | for i in 0 to 7 loop 76 | v_data := std_logic_vector(to_unsigned(i, 4)) & x"1"; 77 | uart_send(v_data, s_uart_rx); 78 | uart_send(x"FF", s_uart_rx); 79 | end loop; 80 | -- Finally read all registers again after write 81 | for i in 0 to 7 loop 82 | v_data := std_logic_vector(to_unsigned(i, 4)) & x"0"; 83 | uart_send(v_data, s_uart_rx); 84 | end loop; 85 | wait; 86 | end process; 87 | 88 | ReceiveP : process is 89 | type t_exp is array (0 to 7) of std_logic_vector(7 downto 0); 90 | variable v_exp : t_exp; 91 | variable v_data : std_logic_vector(7 downto 0); 92 | begin 93 | wait until s_rst_n; 94 | wait until rising_edge(s_clk); 95 | -- First read all registers 96 | v_exp := (0 => x"01", others => x"00"); 97 | for i in 0 to 7 loop 98 | uart_recv(v_data, s_uart_tx); 99 | assert v_data = v_exp(i) 100 | report "UART receive error, got 0x" & to_hstring(v_data) & ", expected 0x" & to_hstring(v_exp(i)) 101 | severity failure; 102 | end loop; 103 | -- Finally read all registers again after write 104 | v_exp := (0 => x"01", others => x"FF"); 105 | for i in 0 to 7 loop 106 | uart_recv(v_data, s_uart_tx); 107 | assert v_data = v_exp(i) 108 | report "UART receive error, got 0x" & to_hstring(v_data) & ", expected 0x" & to_hstring(v_exp(i)) 109 | severity failure; 110 | end loop; 111 | wait for 200 us; 112 | report "Simulation finished :-)"; 113 | stop(0); 114 | end process; 115 | 116 | end architecture; 117 | -------------------------------------------------------------------------------- /uart_reg/syn/Makefile: -------------------------------------------------------------------------------- 1 | DESIGN_NAME := uart_reg 2 | WORK_FILES := ../rtl/uart_ctrl.vhd ../rtl/uart_tx.vhd ../rtl/uart_rx.vhd ../rtl/uart_reg.vhd 3 | GM_FILES := ../../lib/rtl_components.vhd 4 | GHDL_FLAGS := --std=08 --workdir=build -Pbuild 5 | YOSYSPIPE := -nomx8 -retime 6 | # ATTENTION: -luttree option seems to mis-synthesize the design, broken with synth_gatemate? 7 | PNRFLAGS := -om 3 8 | PNRTOOL := $(shell which p_r) 9 | 10 | .PHONY: all syn imp prog syn_sim imp_sim 11 | 12 | all: imp 13 | syn: ${DESIGN_NAME}.v 14 | imp: ${DESIGN_NAME}.bit 15 | 16 | build/work-obj08.cf: ${WORK_FILES} build/gatemate-obj08.cf 17 | ghdl -a ${GHDL_FLAGS} --work=work ${WORK_FILES} 18 | 19 | build/gatemate-obj08.cf: ${GM_FILES} 20 | mkdir -p build 21 | ghdl -a ${GHDL_FLAGS} --work=gatemate ${GM_FILES} 22 | 23 | # Synthesis target for implementation 24 | ${DESIGN_NAME}.v: build/work-obj08.cf 25 | yosys -m ghdl -p 'ghdl ${GHDL_FLAGS} --warn-no-binding --no-formal ${DESIGN_NAME}; synth_gatemate -top $(DESIGN_NAME) ${YOSYSPIPE} -vlog $@' \ 26 | 2>&1 | tee build/yosys-report.txt 27 | 28 | # Implementation target for FPGA 29 | ${DESIGN_NAME}.bit: ${DESIGN_NAME}.v ${DESIGN_NAME}.ccf 30 | cd build && \ 31 | ${PNRTOOL} -i ../${DESIGN_NAME}.v -o $@ --ccf ../${DESIGN_NAME}.ccf $(PNRFLAGS) \ 32 | 2>&1 | tee p_r-report.txt && \ 33 | mv ${DESIGN_NAME}*.bit ../$@ 34 | 35 | # Post-synthesis simulation target 36 | syn_sim: ${DESIGN_NAME}.v 37 | iverilog -g2012 -o tb_${DESIGN_NAME}_syn.vvp ${DESIGN_NAME}.v tb_${DESIGN_NAME}.v /usr/local/share/yosys/gatemate/cells_sim.v 38 | vvp -N tb_${DESIGN_NAME}_syn.vvp -fst 39 | 40 | # Post-implementation simulation target 41 | imp_sim: ${DESIGN_NAME}.bit 42 | iverilog -g2012 -o tb_${DESIGN_NAME}_imp.vvp build/${DESIGN_NAME}_00.v tb_${DESIGN_NAME}.v /opt/cc-toolchain-linux/bin/p_r/cpelib.v 43 | vvp -N tb_${DESIGN_NAME}_imp.vvp -fst 44 | 45 | # FPGA FW load per JTAG 46 | prog: ${DESIGN_NAME}.bit 47 | openFPGALoader -b gatemate_evb_jtag $< 48 | 49 | clean : 50 | echo "# Cleaning files" 51 | rm -rf build ${DESIGN_NAME}.v ${DESIGN_NAME}_sim.v ${DESIGN_NAME}.vhd ${DESIGN_NAME}.bit *.vvp *.fst 52 | -------------------------------------------------------------------------------- /uart_reg/syn/tb_uart_reg.v: -------------------------------------------------------------------------------- 1 | `timescale 1 ns/10 ps // time-unit = 1 ns, precision = 10 ps 2 | 3 | // simplified CC_PLL model 4 | module CC_PLL #( 5 | parameter REF_CLK = "", // e.g. "10.0" 6 | parameter OUT_CLK = "", // e.g. "50.0" 7 | parameter PERF_MD = "", // LOWPOWER, ECONOMY, SPEED 8 | parameter LOW_JITTER = 1, 9 | parameter CI_FILTER_CONST = 2, 10 | parameter CP_FILTER_CONST = 4 11 | )( 12 | input CLK_REF, CLK_FEEDBACK, USR_CLK_REF, 13 | input USR_LOCKED_STDY_RST, USR_SET_SEL, 14 | output USR_PLL_LOCKED_STDY, USR_PLL_LOCKED, 15 | output CLK270, CLK180, CLK90, CLK0, CLK_REF_OUT 16 | ); 17 | 18 | reg r_pll_clk; 19 | reg r_user_pll_locked; 20 | 21 | // OUT_FREQ = 1 MHz 22 | integer clk_half_period = 50; 23 | 24 | initial begin 25 | r_pll_clk = 1'b0; 26 | r_user_pll_locked = 1'b1; 27 | end 28 | 29 | always #clk_half_period r_pll_clk = ~r_pll_clk; 30 | 31 | assign CLK0 = r_pll_clk; 32 | assign USR_PLL_LOCKED = r_user_pll_locked; 33 | 34 | endmodule 35 | 36 | 37 | // simplified CC_CFG_END model 38 | module CC_CFG_END ( 39 | output CFG_END 40 | ); 41 | 42 | assign CFG_END = 1'b1; 43 | 44 | endmodule 45 | 46 | module tb_uart_reg; 47 | 48 | // DUT in/out 49 | reg clk = 1'b0; 50 | reg rst_n = 1'b1; 51 | reg uart_rx; 52 | wire uart_tx; 53 | 54 | // Testbench variables 55 | reg [7:0] tx_data = 8'h0; 56 | reg [7:0] rx_data = 8'h0; 57 | 58 | // Testbench 1/2 clock period 59 | localparam clk_half_period = 50; 60 | 61 | // UART period calculation (9600 baud) 62 | localparam uart_bit_period = 1000000000 / 9600; 63 | localparam uart_bit_half_period = uart_bit_period/2; 64 | 65 | uart_reg UUT (.clk_i(clk), .rst_n_i(rst_n), .uart_rx_i(uart_rx), .uart_tx_o(uart_tx)); 66 | 67 | // set dumpfile 68 | initial begin 69 | $dumpfile ("tb_uart_reg.fst"); 70 | $dumpvars (0, tb_uart_reg); 71 | end 72 | 73 | // Setup simulation 74 | initial begin 75 | uart_rx = 1'b1; 76 | #1 rst_n = 1'b0; 77 | #120 rst_n = 1'b1; 78 | end 79 | 80 | // Generate 10 mhz clock 81 | always #clk_half_period clk = !clk; 82 | 83 | // Stimuli generator 84 | initial 85 | forever @(posedge rst_n) begin 86 | uart_rx = 1'b1; 87 | #uart_bit_period; 88 | for (integer tx = 0; tx < 32; tx = tx + 1) begin 89 | tx_data = tx; 90 | $display ("UART send: 0x%h", tx_data); 91 | uart_rx = 1'b0; 92 | #uart_bit_period; 93 | for (integer i = 0; i <= 7; i = i + 1) begin 94 | uart_rx = tx_data[i]; 95 | #uart_bit_period; 96 | end 97 | uart_rx = 1'b1; 98 | #uart_bit_period; 99 | #uart_bit_period 100 | #uart_bit_period; 101 | end 102 | end 103 | 104 | // Checker 105 | initial begin 106 | @(posedge rst_n) 107 | for (reg [7:0] rx = 0; rx < 32; rx = rx + 1) begin 108 | @(negedge uart_tx) 109 | #uart_bit_period; 110 | #uart_bit_half_period; 111 | for (integer i = 0; i <= 7; i = i + 1) begin 112 | rx_data[i] = uart_tx; 113 | #uart_bit_period; 114 | end 115 | assert (rx_data == rx) 116 | $display("UART recv: 0x%h", rx_data); 117 | else 118 | $warning("UART receive error, got 0x%h, expected 0x%h", rx_data, rx); 119 | end 120 | $display ("UART tests finished"); 121 | $finish; 122 | end 123 | 124 | 125 | endmodule 126 | -------------------------------------------------------------------------------- /uart_reg/syn/uart_reg.ccf: -------------------------------------------------------------------------------- 1 | # Configuration for the Gatemate eval board 2 | 3 | Pin_in "clk_i" Loc = "IO_SB_A8" | SCHMITT_TRIGGER=true; 4 | Pin_in "rst_n_i" Loc = "IO_EB_B0"; # SW3 5 | 6 | Pin_in "uart_rx_i" Loc = "IO_NB_A1"; # PMODA IO3 7 | Pin_out "uart_tx_o" Loc = "IO_NB_A0"; # PMODA IO1 8 | 9 | Pin_out "debug_o[0]" Loc = "IO_NB_A4"; 10 | Pin_out "debug_o[1]" Loc = "IO_NB_A5"; 11 | Pin_out "debug_o[2]" Loc = "IO_NB_A6"; 12 | Pin_out "debug_o[3]" Loc = "IO_NB_A7"; 13 | Pin_out "debug_o[4]" Loc = "IO_NB_B4"; 14 | Pin_out "debug_o[5]" Loc = "IO_NB_B5"; 15 | Pin_out "debug_o[6]" Loc = "IO_NB_B6"; 16 | Pin_out "debug_o[7]" Loc = "IO_NB_B7"; 17 | -------------------------------------------------------------------------------- /uart_trng/rtl/firo.vhd: -------------------------------------------------------------------------------- 1 | library ieee; 2 | use ieee.std_logic_1164.all; 3 | use ieee.numeric_std.all; 4 | 5 | 6 | entity firo is 7 | generic ( 8 | TOGGLE : boolean := true 9 | ); 10 | port ( 11 | frun_i : in std_logic; 12 | fdata_o : out std_logic 13 | ); 14 | end entity firo; 15 | 16 | 17 | architecture rtl of firo is 18 | 19 | signal s_ring : std_logic_vector(15 downto 0); 20 | signal s_tff : std_logic; 21 | 22 | begin 23 | 24 | firoring : for index in 1 to 15 generate 25 | s_ring(index) <= not s_ring(index - 1); 26 | end generate; 27 | 28 | s_ring(0) <= (s_ring(15) xor s_ring(14) xor s_ring(7) xor s_ring(6) xor s_ring(5) xor s_ring(4) xor s_ring(2)) and frun_i; 29 | 30 | with_toggle : if TOGGLE generate 31 | tffP : process(frun_i, s_ring(15)) is 32 | begin 33 | if (not frun_i) then 34 | s_tff <= '0'; 35 | elsif (rising_edge(s_ring(15))) then 36 | s_tff <= not s_tff; 37 | end if; 38 | end process tffP; 39 | fdata_o <= s_ring(15) xor s_tff; 40 | else generate 41 | fdata_o <= s_ring(15); 42 | end generate; 43 | 44 | 45 | end architecture rtl; 46 | -------------------------------------------------------------------------------- /uart_trng/rtl/firo_ctrl.vhd: -------------------------------------------------------------------------------- 1 | library ieee; 2 | use ieee.std_logic_1164.all; 3 | use ieee.numeric_std.all; 4 | 5 | 6 | entity firo_ctrl is 7 | generic ( 8 | EXTRACT : boolean := true 9 | ); 10 | port ( 11 | -- system 12 | clk_i : in std_logic; 13 | rst_n_i : in std_logic; 14 | -- axis in 15 | tvalid_i : in std_logic; 16 | tready_o : out std_logic; 17 | -- axis out 18 | tdata_o : out std_logic_vector(7 downto 0); 19 | tvalid_o : out std_logic; 20 | tready_i : in std_logic; 21 | -- firo 22 | frun_o : out std_logic; 23 | fdata_i : in std_logic 24 | ); 25 | end entity firo_ctrl; 26 | 27 | 28 | architecture rtl of firo_ctrl is 29 | 30 | signal s_clk_counter : unsigned(4 downto 0); 31 | signal s_run : std_logic; 32 | signal s_firo_valid : std_logic; 33 | 34 | type t_neumann_state is (BIT1, BIT2, BIT3, BIT4); 35 | signal s_neumann_state : t_neumann_state; 36 | signal s_neumann_buffer : std_logic_vector(2 downto 0); 37 | 38 | type t_register_state is (SLEEP, COLLECT, VALID); 39 | signal s_register_state : t_register_state; 40 | signal s_register_enable : std_logic; 41 | signal s_register_din : std_logic_vector(1 downto 0); 42 | signal s_register_data : std_logic_vector(8 downto 0); 43 | signal s_register_counter : unsigned(2 downto 0); 44 | signal s_register_length : positive range 1 to 2; 45 | 46 | signal s_data : std_logic_vector(3 downto 0); 47 | 48 | begin 49 | 50 | frun_o <= s_run when s_register_state = COLLECT else '0'; 51 | s_data <= s_neumann_buffer & fdata_i; 52 | 53 | ControllerP : process (clk_i) is 54 | begin 55 | if (rising_edge(clk_i)) then 56 | if (s_register_state = SLEEP) then 57 | s_clk_counter <= (others => '1'); 58 | s_run <= '0'; 59 | s_firo_valid <= '0'; 60 | else 61 | s_clk_counter <= s_clk_counter - 1; 62 | s_firo_valid <= '0'; 63 | if (s_clk_counter = 23 and s_run = '0') then 64 | s_run <= '1'; 65 | s_clk_counter <= (others => '1'); 66 | end if; 67 | if (s_clk_counter = 12 and s_run = '1') then 68 | s_run <= '0'; 69 | s_clk_counter <= (others => '1'); 70 | end if; 71 | if (s_clk_counter = 13 and s_run = '1') then 72 | s_firo_valid <= '1'; 73 | end if; 74 | end if; 75 | end if; 76 | end process ControllerP; 77 | 78 | VON_NEUMANN : if EXTRACT generate 79 | process (clk_i, rst_n_i) is 80 | begin 81 | if (not rst_n_i) then 82 | s_neumann_state <= BIT1; 83 | s_register_enable <= '0'; 84 | s_register_din <= "00"; 85 | elsif (rising_edge(clk_i)) then 86 | case s_neumann_state is 87 | when BIT1 => 88 | s_register_enable <= '0'; 89 | if (s_firo_valid) then 90 | s_neumann_buffer(2) <= fdata_i; 91 | s_neumann_state <= BIT2; 92 | end if; 93 | when BIT2 => 94 | if (s_firo_valid) then 95 | s_neumann_buffer(1) <= fdata_i; 96 | s_neumann_state <= BIT3; 97 | end if; 98 | when BIT3 => 99 | if (s_firo_valid) then 100 | s_neumann_buffer(0) <= fdata_i; 101 | s_neumann_state <= BIT4; 102 | end if; 103 | when BIT4 => 104 | if (s_firo_valid) then 105 | s_register_enable <= '1'; 106 | s_register_length <= 1; 107 | s_register_din <= "00"; 108 | s_neumann_state <= BIT1; 109 | case (s_data) is 110 | when x"5" => 111 | s_register_din <= "01"; 112 | when x"1" | x"6" | x"7" => 113 | s_register_length <= 2; 114 | when x"2" | x"9" | x"b" => 115 | s_register_din <= "01"; 116 | s_register_length <= 2; 117 | when x"4" | x"a" | x"d" => 118 | s_register_din <= "10"; 119 | s_register_length <= 2; 120 | when x"8" | x"c" | x"e" => 121 | s_register_din <= "11"; 122 | s_register_length <= 2; 123 | when x"0" | x"f" => 124 | s_register_enable <= '0'; 125 | when others => -- incl. x"3" 126 | null; 127 | end case; 128 | end if; 129 | when others => 130 | null; 131 | end case; 132 | end if; 133 | end process; 134 | else generate 135 | s_register_enable <= s_firo_valid; 136 | s_register_din(0) <= fdata_i; 137 | s_register_length <= 1; 138 | end generate; 139 | 140 | ShiftRegisterP : process (clk_i, rst_n_i) is 141 | begin 142 | if (not rst_n_i) then 143 | s_register_counter <= (others => '1'); 144 | s_register_state <= SLEEP; 145 | elsif (rising_edge(clk_i)) then 146 | case s_register_state is 147 | when SLEEP => 148 | if (tvalid_i) then 149 | s_register_state <= COLLECT; 150 | s_register_data(0) <= s_register_data(8); 151 | end if; 152 | when COLLECT => 153 | if (s_register_enable) then 154 | if (s_register_counter = 0) then 155 | s_register_data <= s_register_din(1) & s_register_data(6 downto 0) & s_register_din(0); 156 | s_register_state <= VALID; 157 | elsif (s_register_counter = 1) then 158 | if (s_register_length = 1) then 159 | s_register_data(7 downto 0) <= s_register_data(6 downto 0) & s_register_din(0); 160 | end if; 161 | if (s_register_length = 2) then 162 | s_register_data(7 downto 0) <= s_register_data(5 downto 0) & s_register_din; 163 | s_register_state <= VALID; 164 | end if; 165 | else 166 | if (s_register_length = 1) then 167 | s_register_data(7 downto 0) <= s_register_data(6 downto 0) & s_register_din(0); 168 | else 169 | s_register_data(7 downto 0) <= s_register_data(5 downto 0) & s_register_din; 170 | end if; 171 | end if; 172 | s_register_counter <= s_register_counter - s_register_length; 173 | end if; 174 | when VALID => 175 | if (tready_i) then 176 | s_register_state <= SLEEP; 177 | end if; 178 | when others => 179 | null; 180 | end case; 181 | end if; 182 | end process ShiftRegisterP; 183 | 184 | tready_o <= '1' when s_register_state = SLEEP else '0'; 185 | 186 | tvalid_o <= '1' when s_register_state = VALID else '0'; 187 | tdata_o <= s_register_data(7 downto 0); 188 | 189 | end architecture rtl; 190 | -------------------------------------------------------------------------------- /uart_trng/rtl/uart_trng.vhd: -------------------------------------------------------------------------------- 1 | -- This design implements a register file which can 2 | -- be accessed by an UART with 9600 baud 3 | -- 4 | -- See into uart_ctrl.vhd for documentation of the protocol 5 | -- used to read / write the register file. 6 | 7 | 8 | library ieee ; 9 | use ieee.std_logic_1164.all; 10 | use ieee.numeric_std.all; 11 | use ieee.math_real.all; 12 | 13 | library gatemate; 14 | use gatemate.components.all; 15 | 16 | 17 | entity uart_trng is 18 | generic ( 19 | SIM : natural := 0 20 | ); 21 | port ( 22 | clk_i : in std_logic; -- 10 MHz clock 23 | rst_n_i : in std_logic; -- SW3 button 24 | uart_tx_o : out std_logic -- PMODA IO5 25 | ); 26 | end entity uart_trng; 27 | 28 | 29 | architecture rtl of uart_trng is 30 | 31 | signal s_pll_clk : std_logic; 32 | signal s_pll_lock : std_logic; 33 | 34 | signal s_rst_n : std_logic; 35 | signal s_usr_rstn : std_logic; 36 | 37 | signal s_uart_tx_tdata : std_logic_vector(7 downto 0); 38 | signal s_uart_tx_tvalid : std_logic; 39 | signal s_uart_tx_tready : std_logic; 40 | 41 | signal s_firo_run : std_logic; 42 | signal s_firo_data : std_logic; 43 | 44 | begin 45 | 46 | pll : CC_PLL 47 | generic map ( 48 | REF_CLK => "10", 49 | OUT_CLK => "10", 50 | PERF_MD => "SPEED" 51 | ) 52 | port map ( 53 | CLK_REF => clk_i, 54 | CLK_FEEDBACK => '0', 55 | USR_CLK_REF => '0', 56 | USR_LOCKED_STDY_RST => '0', 57 | USR_PLL_LOCKED_STDY => open, 58 | USR_PLL_LOCKED => s_pll_lock, 59 | CLK270 => open, 60 | CLK180 => open, 61 | CLK0 => s_pll_clk, 62 | CLK90 => open, 63 | CLK_REF_OUT => open 64 | ); 65 | 66 | cc_usr_rstn_inst : CC_USR_RSTN 67 | port map ( 68 | USR_RSTN => s_usr_rstn 69 | ); 70 | 71 | firo_ctrl : entity work.firo_ctrl 72 | generic map ( 73 | EXTRACT => true 74 | ) 75 | port map ( 76 | -- system 77 | rst_n_i => s_rst_n, 78 | clk_i => s_pll_clk, 79 | -- axis in 80 | tvalid_i => '1', 81 | tready_o => open, 82 | -- axis out 83 | tdata_o => s_uart_tx_tdata, 84 | tvalid_o => s_uart_tx_tvalid, 85 | tready_i => s_uart_tx_tready, 86 | -- firo 87 | frun_o => s_firo_run, 88 | fdata_i => s_firo_data 89 | ); 90 | 91 | SIMULATION : if (SIM /= 0) generate 92 | -- simple random bit generator 93 | RandomGenP : process (s_pll_clk, s_firo_run) is 94 | variable v_seed1, v_seed2 : positive := 1; 95 | variable v_real_rand : real; 96 | begin 97 | if (not s_firo_run) then 98 | s_firo_data <= '0'; 99 | elsif (s_pll_clk'event) then 100 | uniform(v_seed1, v_seed2, v_real_rand); 101 | if (v_real_rand < 0.5) then 102 | s_firo_data <= '0'; 103 | else 104 | s_firo_data <= '1'; 105 | end if; 106 | end if; 107 | end process RandomGenP; 108 | else generate 109 | firo : entity work.firo 110 | generic map ( 111 | TOGGLE => true 112 | ) 113 | port map ( 114 | frun_i => s_firo_run, 115 | fdata_o => s_firo_data 116 | ); 117 | end generate; 118 | 119 | uart_tx : entity work.uart_tx 120 | generic map ( 121 | CLK_DIV => 1040 122 | ) 123 | port map ( 124 | -- globals 125 | rst_n_i => s_rst_n, 126 | clk_i => s_pll_clk, 127 | -- axis user interface 128 | tdata_i => s_uart_tx_tdata, 129 | tvalid_i => s_uart_tx_tvalid, 130 | tready_o => s_uart_tx_tready, 131 | -- uart interface 132 | tx_o => uart_tx_o 133 | ); 134 | 135 | s_rst_n <= rst_n_i and s_pll_lock and s_usr_rstn; 136 | 137 | end architecture; 138 | -------------------------------------------------------------------------------- /uart_trng/rtl/uart_tx.vhd: -------------------------------------------------------------------------------- 1 | -- Copyright (c) 2022 by Torsten Meissner 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 | -- https://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 | 16 | 17 | library ieee; 18 | use ieee.std_logic_1164.all; 19 | use ieee.numeric_std.all; 20 | 21 | 22 | entity uart_tx is 23 | generic ( 24 | CLK_DIV : natural := 10 25 | ); 26 | port ( 27 | -- globals 28 | rst_n_i : in std_logic; 29 | clk_i : in std_logic; 30 | -- axis user interface 31 | tdata_i : in std_logic_vector(7 downto 0); 32 | tvalid_i : in std_logic; 33 | tready_o : out std_logic; 34 | -- uart interface 35 | tx_o : out std_logic 36 | ); 37 | end entity uart_tx; 38 | 39 | 40 | architecture rtl of uart_tx is 41 | 42 | type t_uart_state is (IDLE, SEND); 43 | signal s_uart_state : t_uart_state; 44 | 45 | signal s_data : std_logic_vector(tdata_i'length+1 downto 0); 46 | signal s_clk_cnt : natural range 0 to CLK_DIV-1; 47 | signal s_clk_en : std_logic; 48 | signal s_bit_cnt : natural range 0 to s_data'length-1; 49 | 50 | begin 51 | 52 | ClkDivP : process (clk_i, rst_n_i) is 53 | begin 54 | if (not rst_n_i) then 55 | s_clk_cnt <= CLK_DIV-1; 56 | elsif (rising_edge(clk_i)) then 57 | if (s_uart_state = IDLE) then 58 | s_clk_cnt <= CLK_DIV-2; 59 | elsif (s_uart_state = SEND) then 60 | if (s_clk_cnt = 0) then 61 | s_clk_cnt <= CLK_DIV-1; 62 | else 63 | s_clk_cnt <= s_clk_cnt - 1; 64 | end if; 65 | end if; 66 | end if; 67 | end process ClkDivP; 68 | 69 | s_clk_en <= '1' when s_uart_state = SEND and s_clk_cnt = 0 else '0'; 70 | 71 | TxP : process (clk_i, rst_n_i) is 72 | begin 73 | if (not rst_n_i) then 74 | s_uart_state <= IDLE; 75 | s_data <= (0 => '1', others => '0'); 76 | s_bit_cnt <= 0; 77 | elsif (rising_edge(clk_i)) then 78 | FsmL : case s_uart_state is 79 | when IDLE => 80 | s_bit_cnt <= s_data'length-1; 81 | if (tvalid_i) then 82 | s_data <= '1' & tdata_i & '0'; 83 | s_uart_state <= SEND; 84 | end if; 85 | when SEND => 86 | if (s_clk_en) then 87 | s_data <= '1' & s_data(s_data'length-1 downto 1); 88 | if (s_bit_cnt = 0) then 89 | s_uart_state <= IDLE; 90 | else 91 | s_bit_cnt <= s_bit_cnt - 1; 92 | end if; 93 | end if; 94 | end case; 95 | end if; 96 | end process TxP; 97 | 98 | tready_o <= '1' when s_uart_state = IDLE else '0'; 99 | 100 | tx_o <= s_data(0); 101 | 102 | end architecture rtl; 103 | -------------------------------------------------------------------------------- /uart_trng/sim/Makefile: -------------------------------------------------------------------------------- 1 | DESIGN_NAME := uart_trng 2 | LIB_SRC := ../../lib/rtl_components.vhd ../../lib/sim_components.vhd 3 | RTL_SRC := ../rtl/uart_tx.vhd ../rtl/firo.vhd ../rtl/firo_ctrl.vhd ../rtl/${DESIGN_NAME}.vhd 4 | SIM_SRC := tb_${DESIGN_NAME}.vhd 5 | SIM_FLAGS := --std=08 -fpsl --workdir=work 6 | 7 | .PHONY: all compile sim clean 8 | 9 | all: sim 10 | compile: tb_${DESIGN_NAME} 11 | 12 | tb_${DESIGN_NAME}: ${LIB_SRC} ${RTL_SRC} ${SIM_SRC} 13 | mkdir -p work 14 | @echo "Analyze gatemate library ..." 15 | ghdl -a ${SIM_FLAGS} --work=gatemate ${LIB_SRC} 16 | @echo "Analyze testbench & design ..." 17 | ghdl -a ${SIM_FLAGS} -Pwork ${RTL_SRC} ${SIM_SRC} 18 | @echo "Elaborate testbench & design ..." 19 | ghdl -e ${SIM_FLAGS} -Pwork $@ 20 | 21 | sim: tb_${DESIGN_NAME} 22 | @echo "Run testbench ..." 23 | ghdl -r ${SIM_FLAGS} -Pwork tb_${DESIGN_NAME} --assert-level=error --wave=tb_${DESIGN_NAME}.ghw 24 | 25 | work: 26 | mkdir $@ 27 | 28 | clean: 29 | @echo "Cleaning simulation files ..." 30 | rm -rf tb_${DESIGN_NAME} tb_${DESIGN_NAME}.ghw *.o work/ 31 | -------------------------------------------------------------------------------- /uart_trng/sim/tb_uart_trng.vhd: -------------------------------------------------------------------------------- 1 | library ieee ; 2 | use ieee.std_logic_1164.all; 3 | use ieee.numeric_std.all; 4 | 5 | use std.env.all; 6 | 7 | 8 | entity tb_uart_trng is 9 | end entity tb_uart_trng; 10 | 11 | 12 | architecture sim of tb_uart_trng is 13 | 14 | signal s_clk : std_logic := '1'; 15 | signal s_rst_n : std_logic := '0'; 16 | 17 | signal s_uart_tx : std_logic; 18 | 19 | constant c_baudrate : natural := 9600; 20 | constant c_period_ns : time := 1000000000 / c_baudrate * ns; 21 | 22 | procedure uart_send ( data : in std_logic_vector(7 downto 0); 23 | signal tx : out std_logic) is 24 | begin 25 | report "UART send: 0x" & to_hstring(data); 26 | tx <= '0'; 27 | wait for c_period_ns; 28 | for i in 0 to 7 loop 29 | tx <= data(i); 30 | wait for c_period_ns; 31 | end loop; 32 | tx <= '1'; 33 | wait for c_period_ns; 34 | end procedure; 35 | 36 | procedure uart_recv ( data : out std_logic_vector(7 downto 0); 37 | signal rx : in std_logic) is 38 | begin 39 | wait until not rx; 40 | wait for c_period_ns; -- Skip start bit 41 | wait for c_period_ns/2; 42 | for i in 0 to 7 loop 43 | data(i) := rx; 44 | wait for c_period_ns; 45 | end loop; 46 | report "UART recv: 0x" & to_hstring(data); 47 | end procedure; 48 | 49 | begin 50 | 51 | dut : entity work.uart_trng 52 | generic map ( 53 | SIM => 1 54 | ) 55 | port map ( 56 | clk_i => s_clk, 57 | rst_n_i => s_rst_n, 58 | uart_tx_o => s_uart_tx 59 | ); 60 | 61 | s_rst_n <= '1' after 120 ns; 62 | s_clk <= not s_clk after 50 ns; 63 | 64 | ReceiveP : process is 65 | type t_exp is array (0 to 7) of std_logic_vector(7 downto 0); 66 | variable v_exp : t_exp; 67 | variable v_data : std_logic_vector(7 downto 0); 68 | begin 69 | wait until s_rst_n; 70 | wait until rising_edge(s_clk); 71 | -- First read all registers 72 | for i in 0 to 7 loop 73 | uart_recv(v_data, s_uart_tx); 74 | end loop; 75 | wait for 200 us; 76 | report "Simulation finished :-)"; 77 | stop(0); 78 | end process; 79 | 80 | end architecture; 81 | -------------------------------------------------------------------------------- /uart_trng/sw/Makefile: -------------------------------------------------------------------------------- 1 | all: uart_trng 2 | 3 | uart_trng: uart_trng.c 4 | gcc -Wall uart_trng.c -o uart_trng 5 | 6 | clean: 7 | rm -rf uart_trng 8 | -------------------------------------------------------------------------------- /uart_trng/sw/uart_trng.c: -------------------------------------------------------------------------------- 1 | #include /* Standard input/output definitions */ 2 | #include 3 | #include /* Standard types */ 4 | #include /* String function definitions */ 5 | #include /* UNIX standard function definitions */ 6 | #include /* File control definitions */ 7 | #include /* Error number definitions */ 8 | #include /* POSIX terminal control definitions */ 9 | #include 10 | 11 | 12 | #ifdef __APPLE__ 13 | // define 460k baud rate, seems not to be available in headers on osx 14 | #define B460800 460800 15 | #endif 16 | 17 | 18 | void help(void); 19 | int serialport_init(const char* serialport, unsigned int baud); 20 | int serialport_read_until(int fd, unsigned int until); 21 | 22 | 23 | // Checks for an argument (characters with a leading '-') 24 | // Returns 0 if argument does not exist or the index of argument 25 | // type in the argv[] array 26 | int parArgTypExists (int argc, char *argv[], char argType) 27 | { 28 | char tmp[3]; 29 | 30 | tmp[0] = '-'; 31 | tmp[1] = argType; 32 | tmp[2] = 0; 33 | 34 | if (argc > 1) { 35 | for (int i = 1; i < argc; i++) { 36 | if (!strcmp (argv[i], tmp)) 37 | return i; 38 | } 39 | } 40 | return 0; 41 | } 42 | 43 | 44 | // Get string argument value 45 | // Returns 0 in error case, returns 1 if OK 46 | // (string is limited to max. 4096 characters) 47 | int parGetString (int argc, char *argv[], char argType, char *value) 48 | { 49 | int a = parArgTypExists(argc, argv, argType); 50 | 51 | // Check for errors 52 | if (a == 0) return 0; 53 | if (a >= (argc -1)) return 0; 54 | if (strlen(argv[a+1]) > 256) return 0; 55 | 56 | strcpy(value, argv[a+1]); 57 | return 1; 58 | } 59 | 60 | 61 | // Get unsigned int argument value 62 | // Returns 0 in error case, 1 if OK 63 | int parGetUnsignedInt (int argc, char *argv[], char argType, 64 | unsigned int *value) 65 | { 66 | int a = parArgTypExists (argc, argv, argType); 67 | 68 | /* error checking */ 69 | if (a == 0) return 0; 70 | if (a >= (argc -1)) return 0; 71 | 72 | a = sscanf(argv[a+1], "%iu", value); 73 | 74 | return a; 75 | } 76 | 77 | 78 | void help(void) { 79 | printf("Usage: uart_trng -p [OPTIONS]\n" 80 | "\n" 81 | "Options:\n" 82 | " -h, --help Print this help message\n" 83 | " -p, --port=serialport Serial port where the uart_trng device is plugged on\n" 84 | " -b, --baud=baudrate Baudrate (bps) of uart_trng device, default = 9600\n" 85 | " -s, --size number of bytes to receive from uart_trng device,\n" 86 | " 0 for reading until break with Ctrl-c, default = 1024\n" 87 | "\n"); 88 | } 89 | 90 | 91 | int main(int argc, char *argv[]) 92 | { 93 | int fd = 0; 94 | int r = 0; 95 | char serialport[256]; 96 | unsigned int baudrate = 9600; 97 | unsigned int size = 1024; 98 | 99 | // check for command line arguments 100 | if (argc == 1) { 101 | help(); 102 | return 1; 103 | } 104 | else { 105 | if (parArgTypExists (argc, argv, 'h')) { 106 | help(); 107 | return 1; 108 | } 109 | // get serial port 110 | if (parArgTypExists (argc, argv, 'p')) { 111 | r = parGetString (argc, argv, 'p', serialport); 112 | if (r == 0) { 113 | return (1); 114 | } 115 | } else { 116 | help(); 117 | return (1); 118 | } 119 | // get baud rate 120 | if (parArgTypExists (argc, argv, 'b')) { 121 | r = parGetUnsignedInt (argc, argv, 'b', &baudrate); 122 | if (r == 0) { 123 | return (1); 124 | } 125 | } 126 | // get read size in bytes 127 | if (parArgTypExists (argc, argv, 's')) { 128 | r = parGetUnsignedInt (argc, argv, 's', &size); 129 | if (r == 0) { 130 | return (1); 131 | } 132 | } 133 | } 134 | 135 | fd = serialport_init(serialport, baudrate); 136 | if (fd == -1) 137 | return -1; 138 | serialport_read_until(fd, size); 139 | 140 | exit(EXIT_SUCCESS); 141 | } 142 | 143 | 144 | int serialport_read_until(int fd, unsigned int until) 145 | { 146 | char b[1]; 147 | int index = 0; 148 | int n; 149 | while (1) { 150 | while (1) { 151 | // read one char 152 | n = read(fd, b, 1); 153 | // we had a read error 154 | // check if there were no bytes to read or if it was a real error 155 | if (n == -1) { 156 | if (errno != EAGAIN) { 157 | fprintf(stderr,"serial read error at byte %d", index); 158 | return -1; 159 | } 160 | } else { 161 | break; 162 | } 163 | } 164 | // we got no byte, so wait 10 ms for the next try 165 | if (n == 0) { 166 | usleep (10 * 1000); 167 | continue; 168 | } 169 | printf("%c",b[0]); 170 | if (until == 0) { 171 | continue; 172 | } else { 173 | index++; 174 | if (index == until) { 175 | break; 176 | } 177 | } 178 | }; 179 | 180 | fprintf(stderr,"uart_trng: read %d random bytes from device\n", until); 181 | return 0; 182 | } 183 | 184 | 185 | // takes the string name of the serial port (e.g. "/dev/tty.usbserial","COM1") 186 | // and a baud rate (bps) and connects to that port at that speed and 8N1. 187 | // opens the port in fully raw mode so you can send binary data. 188 | // returns valid fd, or -1 on error 189 | int serialport_init(const char* serialport, unsigned int baud) 190 | { 191 | struct termios toptions; 192 | int fd; 193 | 194 | fprintf(stderr,"init_serialport: opening port %s @ %u bps\n", 195 | serialport, baud); 196 | 197 | fd = open(serialport, O_RDWR | O_NOCTTY | O_NDELAY); 198 | if (fd == -1) { 199 | perror("init_serialport: Unable to open port "); 200 | return -1; 201 | } 202 | 203 | if (tcgetattr(fd, &toptions) < 0) { 204 | perror("init_serialport: Couldn't get term attributes"); 205 | return -1; 206 | } 207 | speed_t brate = baud; // let you override switch below if needed 208 | switch(baud) { 209 | case 4800: brate=B4800; break; 210 | case 9600: brate=B9600; break; 211 | #ifdef B14400 212 | case 14400: brate=B14400; break; 213 | #endif 214 | case 19200: brate=B19200; break; 215 | #ifdef B28800 216 | case 28800: brate=B28800; break; 217 | #endif 218 | case 38400: brate=B38400; break; 219 | case 57600: brate=B57600; break; 220 | case 115200: brate=B115200; break; 221 | case 230400: brate=B230400; break; 222 | case 460800: brate=B460800; break; 223 | } 224 | cfsetispeed(&toptions, brate); 225 | cfsetospeed(&toptions, brate); 226 | 227 | // 8N1 228 | toptions.c_cflag &= ~PARENB; 229 | toptions.c_cflag &= ~CSTOPB; 230 | toptions.c_cflag &= ~CSIZE; 231 | toptions.c_cflag |= CS8; 232 | // no flow control 233 | toptions.c_cflag &= ~CRTSCTS; 234 | 235 | toptions.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines 236 | toptions.c_iflag &= ~(IXON | IXOFF | IXANY); // turn off s/w flow ctrl 237 | 238 | toptions.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // make raw 239 | toptions.c_oflag &= ~OPOST; // make raw 240 | 241 | // see: http://unixwiz.net/techtips/termios-vmin-vtime.html 242 | toptions.c_cc[VMIN] = 0; 243 | toptions.c_cc[VTIME] = 20; 244 | 245 | if( tcsetattr(fd, TCSANOW, &toptions) < 0) { 246 | perror("init_serialport: Couldn't set term attributes"); 247 | return -1; 248 | } 249 | 250 | return fd; 251 | } 252 | 253 | -------------------------------------------------------------------------------- /uart_trng/syn/Makefile: -------------------------------------------------------------------------------- 1 | DESIGN_NAME := uart_trng 2 | WORK_FILES := ../rtl/uart_tx.vhd ../rtl/firo.vhd ../rtl/firo_ctrl.vhd ../rtl/${DESIGN_NAME}.vhd 3 | GM_FILES := ../../lib/rtl_components.vhd 4 | GHDL_FLAGS := --std=08 --workdir=build -Pbuild 5 | YOSYSPIPE := -nomx8 -retime 6 | # ATTENTION: -luttree option seems to mis-synthesize the design, broken with synth_gatemate? 7 | PNRFLAGS := -om 3 8 | PNRTOOL := $(shell which p_r) 9 | 10 | .PHONY: all syn imp prog syn_sim imp_sim 11 | 12 | all: imp 13 | syn: ${DESIGN_NAME}.v 14 | imp: ${DESIGN_NAME}.bit 15 | 16 | build/work-obj08.cf: ${WORK_FILES} build/gatemate-obj08.cf 17 | ghdl -a ${GHDL_FLAGS} --work=work ${WORK_FILES} 18 | 19 | build/gatemate-obj08.cf: ${GM_FILES} 20 | mkdir -p build 21 | ghdl -a ${GHDL_FLAGS} --work=gatemate ${GM_FILES} 22 | 23 | # Synthesis target for implementation 24 | ${DESIGN_NAME}.v: build/work-obj08.cf 25 | yosys -m ghdl -p 'ghdl ${GHDL_FLAGS} --warn-no-binding --no-formal ${DESIGN_NAME}; synth_gatemate -top $(DESIGN_NAME) ${YOSYSPIPE} -vlog $@' \ 26 | 2>&1 | tee build/yosys-report.txt 27 | 28 | # Implementation target for FPGA 29 | ${DESIGN_NAME}.bit: ${DESIGN_NAME}.v ${DESIGN_NAME}.ccf 30 | cd build && \ 31 | ${PNRTOOL} -i ../${DESIGN_NAME}.v -o $@ --ccf ../${DESIGN_NAME}.ccf $(PNRFLAGS) \ 32 | 2>&1 | tee p_r-report.txt && \ 33 | mv ${DESIGN_NAME}*.bit ../$@ 34 | 35 | # Post-synthesis simulation target 36 | syn_sim: ${DESIGN_NAME}.v 37 | iverilog -g2012 -o tb_${DESIGN_NAME}_syn.vvp ${DESIGN_NAME}.v tb_${DESIGN_NAME}.v /usr/local/share/yosys/gatemate/cells_sim.v 38 | vvp -N tb_${DESIGN_NAME}_syn.vvp -fst 39 | 40 | # Post-implementation simulation target 41 | imp_sim: ${DESIGN_NAME}.bit 42 | iverilog -g2012 -o tb_${DESIGN_NAME}_imp.vvp build/${DESIGN_NAME}_00.v tb_${DESIGN_NAME}.v /opt/cc-toolchain-linux/bin/p_r/cpelib.v 43 | vvp -N tb_${DESIGN_NAME}_imp.vvp -fst 44 | 45 | # FPGA FW load per JTAG 46 | prog: ${DESIGN_NAME}.bit 47 | openFPGALoader -b gatemate_evb_jtag $< 48 | 49 | clean : 50 | echo "# Cleaning files" 51 | rm -rf build ${DESIGN_NAME}.v ${DESIGN_NAME}_sim.v ${DESIGN_NAME}.vhd ${DESIGN_NAME}.bit *.vvp *.fst 52 | -------------------------------------------------------------------------------- /uart_trng/syn/tb_uart_trng.v: -------------------------------------------------------------------------------- 1 | `timescale 1 ns/10 ps // time-unit = 1 ns, precision = 10 ps 2 | 3 | // simplified CC_PLL model 4 | module CC_PLL #( 5 | parameter REF_CLK = "", // e.g. "10.0" 6 | parameter OUT_CLK = "", // e.g. "50.0" 7 | parameter PERF_MD = "", // LOWPOWER, ECONOMY, SPEED 8 | parameter LOW_JITTER = 1, 9 | parameter CI_FILTER_CONST = 2, 10 | parameter CP_FILTER_CONST = 4 11 | )( 12 | input CLK_REF, CLK_FEEDBACK, USR_CLK_REF, 13 | input USR_LOCKED_STDY_RST, USR_SET_SEL, 14 | output USR_PLL_LOCKED_STDY, USR_PLL_LOCKED, 15 | output CLK270, CLK180, CLK90, CLK0, CLK_REF_OUT 16 | ); 17 | 18 | reg r_pll_clk; 19 | reg r_user_pll_locked; 20 | 21 | // OUT_FREQ = 1 MHz 22 | integer clk_half_period = 50; 23 | 24 | initial begin 25 | r_pll_clk = 1'b0; 26 | r_user_pll_locked = 1'b1; 27 | end 28 | 29 | always #clk_half_period r_pll_clk = ~r_pll_clk; 30 | 31 | assign CLK0 = r_pll_clk; 32 | assign USR_PLL_LOCKED = r_user_pll_locked; 33 | 34 | endmodule 35 | 36 | 37 | // simplified CC_CFG_END model 38 | module CC_CFG_END ( 39 | output CFG_END 40 | ); 41 | 42 | assign CFG_END = 1'b1; 43 | 44 | endmodule 45 | 46 | module tb_uart_trng; 47 | 48 | // DUT in/out 49 | reg clk = 1'b0; 50 | reg rst_n = 1'b1; 51 | reg uart_tx; 52 | 53 | // Testbench variables 54 | reg [7:0] tx_data = 8'h0; 55 | reg [7:0] rx_data = 8'h0; 56 | 57 | // Testbench 1/2 clock period 58 | localparam clk_half_period = 50; 59 | 60 | // UART period calculation (9600 baud) 61 | localparam uart_bit_period = 1000000000 / 9600; 62 | localparam uart_bit_half_period = uart_bit_period/2; 63 | 64 | uart_trng UUT (.clk_i(clk), .rst_n_i(rst_n), .uart_tx_o(uart_tx)); 65 | 66 | // set dumpfile 67 | initial begin 68 | $dumpfile ("tb_uart_trng.fst"); 69 | $dumpvars (0, tb_uart_trng); 70 | end 71 | 72 | // Setup simulation 73 | initial begin 74 | #1 rst_n = 1'b0; 75 | #120 rst_n = 1'b1; 76 | end 77 | 78 | // Generate 10 mhz clock 79 | always #clk_half_period clk = !clk; 80 | 81 | // Checker 82 | initial begin 83 | @(posedge rst_n) 84 | for (reg [7:0] rx = 0; rx < 32; rx = rx + 1) begin 85 | @(negedge uart_tx) 86 | #uart_bit_period; 87 | #uart_bit_half_period; 88 | for (integer i = 0; i < 7; i = i + 1) begin 89 | rx_data[i] = uart_tx; 90 | #uart_bit_period; 91 | end 92 | $display ("UART recv: 0x%h", rx_data); 93 | end 94 | $display ("UART tests finished"); 95 | $finish; 96 | end 97 | 98 | 99 | endmodule 100 | -------------------------------------------------------------------------------- /uart_trng/syn/uart_trng.ccf: -------------------------------------------------------------------------------- 1 | # Configuration for the Gatemate eval board 2 | 3 | Pin_in "clk_i" Loc = "IO_SB_A8" | SCHMITT_TRIGGER=true; 4 | Pin_in "rst_n_i" Loc = "IO_EB_B0"; # SW3 5 | 6 | Pin_out "uart_tx_o" Loc = "IO_NB_A0"; # PMODA IO1 7 | 8 | Pin_out "debug_o[0]" Loc = "IO_NB_A4"; 9 | Pin_out "debug_o[1]" Loc = "IO_NB_A5"; 10 | Pin_out "debug_o[2]" Loc = "IO_NB_A6"; 11 | Pin_out "debug_o[3]" Loc = "IO_NB_A7"; 12 | Pin_out "debug_o[4]" Loc = "IO_NB_B4"; 13 | Pin_out "debug_o[5]" Loc = "IO_NB_B5"; 14 | Pin_out "debug_o[6]" Loc = "IO_NB_B6"; 15 | Pin_out "debug_o[7]" Loc = "IO_NB_B7"; 16 | --------------------------------------------------------------------------------