├── LICENSE ├── README.md ├── ddr3.gprj ├── doc ├── design.md ├── screenshot.png ├── simulation.png └── waveform.png ├── simulation ├── Makefile ├── README.md └── tb_controller.v └── src ├── ddr3.sdc ├── ddr3_controller.v ├── ddr3_top.v ├── gowin_rpll ├── gowin_rpll.ipc ├── gowin_rpll.mod ├── gowin_rpll.v └── gowin_rpll_tmp.v ├── print.v ├── tang20k.cst └── uart_tx_V2.v /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Simple low-latency DDR3 PHY controller for Tang Primer 20K 3 | 4 | This is a DDR3 controller for GW2A / Tang Primer 20K. It was designed for [NESTang](https://github.com/nand2mario/nestang) and should hopefully be useful for other projects. 5 | 6 | Unlike more portable designs, we use Gowin OSER8_MEM/DQS primitives for running at higher speeds (DDR3-800). We are aiming mostly at low-latency use cases like FPGA gaming. The achieved read latency is about 90ns. The interface is single 16-bit word based and uses no bursting. For more predictable behavior, the controller also exposes a *refresh* input for executing auto-refreshes, avoiding the longer latencies introduced by controller-initiated refreshes. Resource usage is 1377 logic elements (6% on GW2A-18C). 7 | 8 | DDR3 requires a fair amount of setting-ups to function properly. In particular, it needs dynamic adjustments to clock timings to make reads/writes more stable. Here are the implemented mechanisms: ZQ calibration, writing leveling, read calibration and dynamic ODT. 9 | 10 | The official documentation from Gowin is quite lacking for DDR-related primitives like DQS, IDES8_MEM and OSER8_MEM. The dev process thus involved quite some trial-and-errors and cross-checking with other vendors' docs. So the code also serves as examples/documentation for these constructs. 11 | 12 | Test screenshot: 13 | 14 | 15 | 16 | There's also an iverilog and gtkwave-based simulation, if you are interested in all the signaling/timing details about DDR3. See [simulation instructions](simulation/README.md). 17 | 18 | Build instructions, 19 | * Gowin IDE 1.8.0.7 20 | * Project->Configuration->Synthesis: set Verilog language to SystemVerilog 21 | * Project->Configuration->Dual Purpose Pin: Use SSPI as regular IO 22 | 23 | nand2mario, 2022.9 24 | -------------------------------------------------------------------------------- /ddr3.gprj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 5 6 | gw2a18c-011 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /doc/design.md: -------------------------------------------------------------------------------- 1 | 2 | ## Design notes for the DDR3 controller 3 | 4 | For now, here're some essential references, 5 | 6 | * DDR3 specification: [JEDEC JESD79-3F](https://github.com/LongJohnCoder/ddr-doc/find/gh-pages) 7 | * SKHynix [H5TQ1G63EFR-PBC datasheet](https://www.datasheets360.com/part/detail/h5tq1g63efr-pbc/5056929029748192395/). 8 | * Micron [TN-41-13](https://www.micron.com/-/media/client/global/documents/products/technical-note/dram/tn4113_ddr3_point_to_point_design.pdf): DDR3 Point-to-Point Design Support -------------------------------------------------------------------------------- /doc/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nand2mario/ddr3-tang-primer-20k/a6d866d2369eb27e99cedee6c0cb8a09f311fa57/doc/screenshot.png -------------------------------------------------------------------------------- /doc/simulation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nand2mario/ddr3-tang-primer-20k/a6d866d2369eb27e99cedee6c0cb8a09f311fa57/doc/simulation.png -------------------------------------------------------------------------------- /doc/waveform.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nand2mario/ddr3-tang-primer-20k/a6d866d2369eb27e99cedee6c0cb8a09f311fa57/doc/waveform.png -------------------------------------------------------------------------------- /simulation/Makefile: -------------------------------------------------------------------------------- 1 | 2 | DIR := ../src 3 | 4 | controller.vvp: ddr3.v $(DIR)/ddr3_controller.v tb_controller.v prim_sim.v 5 | iverilog -o controller.vvp -D SIM -D den1024Mb -D sg25 -D x16 -g 2012 tb_controller.v ddr3.v $(DIR)/ddr3_controller.v prim_sim.v 6 | 7 | controller: controller.vvp 8 | 9 | run.controller: controller.vvp 10 | if not exist tmp mkdir tmp 11 | vvp controller.vvp 12 | 13 | # Vanilla Micron DDR3 simulation 14 | ddr3.vvp: ddr3.v 1024*.vh tb.v subtest.vh 15 | iverilog -o ddr3.vvp -D den1024Mb -D sg25 -D x16 -g 2012 tb.v ddr3.v 16 | 17 | ddr3: ddr3.vvp 18 | 19 | run.ddr3: ddr3.vvp 20 | if not exist tmp mkdir tmp 21 | vvp ddr3.vvp 22 | 23 | # Misc 24 | tag: *.v *.vh 25 | ctags -R *.v 1024* 26 | 27 | clean: 28 | del *.vvp 29 | 30 | -------------------------------------------------------------------------------- /simulation/README.md: -------------------------------------------------------------------------------- 1 | 2 | ## Simulation setup using Icarus Verilog, prim_sim.v and Micro DDR3 model 3 | 4 | The Gowin IDE doesn't come with integrated model simulation as of late 2022. Luckily they do provide behavioral HDL for their primitives. So combining that with a DDR3 memory model, we can simulate our design with iverilog. 5 | 6 | What you need (on Windows). 7 | 8 | * [Icarus Verilog 11](https://bleyer.org/icarus/iverilog-v11-20201123-x64_setup.exe). This particular version works for me. The latest version has some issues (assertion errors) with the Micron DDR3 model. 9 | * Micron DDR3 memory model. Get it from [Micron's website](https://www.micron.com/products/dram/ddr3-sdram) ("DDR3 SDRAM Verilog Model, version 1.74"). Extract the source files to this dir. 10 | * Gowin's `prim_sim.v`. It comes with Gowin IDE: for example `Gowin_V1.9.8.07/IDE/simlib/gw2a/prim_sim.v`. 11 | * GNU make: `choco install make` 12 | 13 | Then you can run 14 | ```bash 15 | make run.controller 16 | ``` 17 | 18 | It gives a detailed view of what's happening, including timing errors. This is essential for debugging the controller. 19 | 20 | 21 | 22 | With gtkwave, you can view the wavefrom: 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /simulation/tb_controller.v: -------------------------------------------------------------------------------- 1 | // 2 | // Test bench of ddr3_controller.v with Micro DDR3 model 3 | // nand2mario, 2022.9 4 | // 5 | 6 | `timescale 1ps / 1ps 7 | 8 | module tb; 9 | 10 | // sg125=DDR3-1600 11 | `define sg125 12 | `include "1024Mb_ddr3_parameters.vh" 13 | 14 | // DDR3 ports 15 | reg rst_n; 16 | reg ck; 17 | wire ck_n = ~ck; 18 | wire cke; 19 | wire cs_n; 20 | wire ras_n; 21 | wire cas_n; 22 | wire we_n; 23 | wire [BA_BITS-1:0] ba; 24 | wire [ADDR_BITS-1:0] a; 25 | wire [DM_BITS-1:0] dm; 26 | wire [DQ_BITS-1:0] dq; 27 | wire [DQS_BITS-1:0] dqs; 28 | wire [DQS_BITS-1:0] dqs_n = ~dqs; 29 | wire [DQS_BITS-1:0] tdqs_n = 2'bzz; 30 | wire odt; 31 | 32 | // Controller ports 33 | reg pclk; // 100Mhz primary clock 34 | reg fclk; // 400Mhz fast clock 35 | reg [25:0] addr; 36 | reg rd, wr, refresh; // command pins 37 | reg [15:0] din; 38 | wire [15:0] dout; 39 | wire data_ready, busy; 40 | 41 | real tck; 42 | reg [(AL_MAX+CL_MAX):0] odt_fifo; 43 | 44 | wire [7:0] wstep; 45 | wire [1:0] rclkpos; 46 | wire [2:0] rclksel; 47 | wire wlevel_done; 48 | wire rcalib_done; 49 | 50 | wire ddr_nrst; 51 | wire ddr_ck; 52 | 53 | // Micron DDR3 memory module 54 | ddr3 sdramddr3_0 ( 55 | ddr_nrst, ddr_ck, ~ddr_ck, cke, 56 | cs_n, ras_n, cas_n, we_n, 57 | dm, ba, a, dq, dqs, dqs_n, 58 | tdqs_n, odt 59 | ); 60 | 61 | // Our DDR3 controller, main clock=200Mhz, memory clock(x2)=400Mhz, DDR3-800 62 | ddr3_controller #(/*.FREQ(200_000_000),*/ .ROW_WIDTH(13), .COL_WIDTH(10)) u_sdram ( 63 | .pclk(pclk), .fclk(fclk), .ck(ck), .resetn(rst_n), 64 | .addr(addr), .rd(rd), .wr(wr), .refresh(refresh), 65 | .din(din), .dout(dout), .data_ready(data_ready), .busy(busy), 66 | .write_level_done(wlevel_done), .wstep(wstep), 67 | .read_calib_done(rcalib_done), .rclkpos(rclkpos), .rclksel(rclksel), 68 | 69 | .DDR3_nRESET(ddr_nrst), 70 | .DDR3_CK(ddr_ck), 71 | .DDR3_CKE(cke), 72 | 73 | .DDR3_nCS(cs_n), // a single chip select 74 | .DDR3_nRAS(ras_n), // row address select 75 | .DDR3_nCAS(cas_n), // columns address select 76 | .DDR3_nWE(we_n), // write enable 77 | 78 | .DDR3_DM(dm), 79 | .DDR3_BA(ba), // two banks 80 | .DDR3_A(a), // 13 bit multiplexed address bus 81 | .DDR3_DQ(dq), // 16 bit bidirectional data bus 82 | .DDR3_DQS(dqs), // DQ strobes 83 | 84 | .DDR3_ODT(odt) 85 | ); 86 | 87 | // 88 | // clock initialization and generation 89 | // 90 | initial begin 91 | $timeformat (-9, 1, " ns", 1); 92 | tck <= 2500; // DDR-800, tck = 2.5ns 93 | // tck <= 1875; // DDR-1066, tck = 1.875ns 94 | fclk <= 1'b1; // fclk is 400Mhz 95 | ck <= 1'b1; // ck is 90-degree shifted fclk 96 | pclk <= 1'b1; // pclk is 100Mhz 97 | odt_fifo <= 0; 98 | 99 | forever begin 100 | #(tck/4) ck = ~ck; 101 | #(tck/4) fclk = ~fclk; 102 | #(tck/4) ck = ~ck; 103 | #(tck/4) fclk = ~fclk; 104 | #(tck/4) ck = ~ck; 105 | #(tck/4) fclk = ~fclk; 106 | #(tck/4) ck = ~ck; 107 | #(tck/4) fclk = ~fclk; 108 | pclk = ~pclk; 109 | end 110 | end 111 | 112 | initial begin 113 | end 114 | // 115 | // functions and tasks 116 | // 117 | function integer ceil; 118 | input number; 119 | real number; 120 | if (number > $rtoi(number)) 121 | ceil = $rtoi(number) + 1; 122 | else 123 | ceil = number; 124 | endfunction 125 | 126 | function integer max; 127 | input arg1; 128 | input arg2; 129 | integer arg1; 130 | integer arg2; 131 | if (arg1 > arg2) 132 | max = arg1; 133 | else 134 | max = arg2; 135 | endfunction 136 | 137 | task test_done; 138 | begin 139 | $display ("%m at time %t: INFO: Simulation is Complete", $time); 140 | $finish(0); 141 | end 142 | endtask 143 | 144 | task write(input [26:0] a, input [15:0] v); 145 | begin 146 | wait(busy == 1'b0); 147 | @ (posedge pclk); 148 | wr <= 1'b1; 149 | addr <= a; 150 | din <= v; 151 | 152 | @ (posedge pclk); 153 | wr <= 1'b0; 154 | @ (posedge pclk); 155 | end 156 | endtask 157 | 158 | time start_time; 159 | task verify(input [26:0] a, input [15:0] expected); 160 | begin 161 | wait(busy == 1'b0); 162 | @ (posedge pclk); 163 | rd <= 1'b1; 164 | addr <= a; 165 | 166 | @ (posedge pclk); 167 | rd <= 1'b0; 168 | 169 | start_time <= $time; 170 | #0.01 wait(data_ready == 1'b1 || $time > start_time + 200_000); // timeout is 200ns 171 | // if (rburst) begin 172 | // $display("RBURST=1"); 173 | // if (~data_ready) 174 | // wait(data_ready == 1'b1 || $time > start_time + 200_000); 175 | // end 176 | @ (posedge pclk); 177 | $display("READ: dout=%h, data_ready=%d, time=%d", dout, data_ready, $time); 178 | if (dout != expected) 179 | $display("ERROR: mismatch, expecting %h", expected); 180 | end 181 | endtask 182 | 183 | integer i, j; 184 | 185 | initial begin : test 186 | $dumpfile("controller.vcd"); 187 | $dumpvars(0, tb); 188 | 189 | $display("Powering up and reset the controller"); 190 | rst_n <= 1'b0; 191 | rd <= 1'b0; wr <= 1'b0; refresh <= 1'b0; 192 | # (10000); // 10ns reset pulse 193 | @ (negedge ck) rst_n = 1'b1; 194 | 195 | // write 16'h1234 to address 25'h000_1000 196 | write(26'h1000, 16'h1234); 197 | write(26'h1001, 16'h5678); 198 | write(26'hf0000, 16'h8765); 199 | write(26'hf0008, 16'habcd); 200 | 201 | verify(26'h1000, 16'h1234); 202 | verify(26'h1001, 16'h5678); 203 | verify(26'hf0008, 16'habcd); 204 | verify(26'hf0000, 16'h8765); 205 | 206 | // Do reading calibration 207 | // for (i = 1; i < 3; i++) begin // 1, 2 208 | // for (j = 0; j < 8; j++) begin 209 | // $display("Reading with rclkpos=%d, rclksel=%d", i, j); 210 | // set_read_timing(i,j); 211 | // verify(26'h1000, 16'h1234); 212 | // # (50_000); // wait 5 pclk cycles 213 | // end 214 | // end 215 | 216 | # (50_000); // keep running for 50ns 217 | 218 | // we are all done 219 | test_done; 220 | 221 | end 222 | 223 | endmodule 224 | -------------------------------------------------------------------------------- /src/ddr3.sdc: -------------------------------------------------------------------------------- 1 | //Copyright (C)2014-2022 GOWIN Semiconductor Corporation. 2 | //All rights reserved. 3 | //File Title: Timing Constraints file 4 | //GOWIN Version: 1.9.8.05 5 | //Created Time: 2022-05-06 23:08:41 6 | create_clock -name clk -period 10 -waveform {0 5} [get_nets {clk}] 7 | create_clock -name clk_x4 -period 2.5 -waveform {0 1.25} [get_nets {clk_x4}] 8 | set_clock_groups -asynchronous -group [get_clocks {clk_x4}] -group [get_clocks {clk}] 9 | report_timing -hold -from_clock [get_clocks {clk*}] -to_clock [get_clocks {clk*}] -max_paths 25 -max_common_paths 1 10 | report_timing -setup -from_clock [get_clocks {clk*}] -to_clock [get_clocks {clk*}] -max_paths 25 -max_common_paths 1 11 | -------------------------------------------------------------------------------- /src/ddr3_controller.v: -------------------------------------------------------------------------------- 1 | 2 | // Simple low-latency DDR3 PHY controller for Tang Primer 20K 3 | // nand2mario, 2022.9 4 | // 5 | // Tested on SKHynix H5TQ1G63EFR-PBC (1Gb) 6 | // - PB speed grade: JEDEC DDR3-1600 11-11-11 (aka DDR3-1600K) 7 | // - RCD=RP=13.75ns, RC=48.75ns 8 | // - Equivalent to "sg25" in Micron DDR3 model 9 | // 10 | 11 | // Undefine this to use DDR3-1066 12 | `define DDR3_800 13 | 14 | module ddr3_controller 15 | #( 16 | // Main clock frequency, 75Mhz~100Mhz (DDR3 nominal clock 300Mhz~400Mhz) 17 | parameter ROW_WIDTH = 13, 18 | parameter COL_WIDTH = 10, 19 | parameter BANK_WIDTH = 3, 20 | 21 | // Time delays in nCK (tCK=2.5ns for DDR-800, 1.875ns for DDR-1066). 22 | `ifdef DDR3_800 23 | parameter CAS = 6, // 6 cycles, set in MR0[6,5,4,2] = 0100 24 | parameter BL = 2, // BC4 bursting means 2 cycles, MR0[1:0] = 10 25 | parameter CWL = 5, // 5 cycles, set in MR2[5:3] = 000 26 | parameter WR = 6, // 15ns, write recovery 27 | parameter MRD = 8, // 4 cycles, mode register set delay 28 | parameter RP = 6, // 13.75ns, precharge to active 29 | parameter RCD = 6, // 13.75ns, active to r/w 30 | parameter RC = 20, // 48.25ns, ref/active to ref/active 31 | parameter MOD = 12 // 12nCK/15ns, cycles after MRS before any other command 32 | `else 33 | // DDR3-1066 34 | parameter CAS = 7, // MR0[6,5,4,2] = 0110 35 | parameter CWL = 6, // MR2[5:3] = 001 36 | parameter RCD = 8, // 13.75ns, active to r/w 37 | parameter WR = 8, // MR0[11:9] = 100 38 | parameter MRD = 8, // >=4 cycles, mode register set delay 39 | parameter RP = 8, // 13.75ns, precharge to active 40 | parameter RC = 26, // 48.25ns, ref/active to ref/active 41 | parameter MOD = 12 // 12nCK/15ns, cycles after MRS before any other command 42 | `endif 43 | ) 44 | ( 45 | // DDR3 side interface 46 | inout [15:0] DDR3_DQ, 47 | inout [1:0] DDR3_DQS, 48 | output[ROW_WIDTH-1:0] DDR3_A, 49 | output[BANK_WIDTH-1:0] DDR3_BA, 50 | 51 | output DDR3_nRAS, 52 | output DDR3_nCAS, 53 | output DDR3_nWE, 54 | 55 | output DDR3_nCS, // always 0 56 | output DDR3_CK, // ck, 180-degree shifted fclk 57 | output reg DDR3_CKE, 58 | output DDR3_nRESET, // reset pin 59 | output [1:0] DDR3_DM, // always 0 60 | output DDR3_ODT, // always 1 61 | 62 | // System side interface 63 | input pclk, // primary clock (rd, wr, etc), e.g. 100Mhz 64 | input fclk, // fast clock (4*pclk), e.g. 400Mhz 65 | input ck, // 90-degree shifted fclk for memory clock 66 | input resetn, 67 | input rd, // command: read 68 | input wr, // command: write 69 | input refresh, // command: auto refresh. 4096 refresh cycles in 64ms. Once per 15us. 70 | input [BANK_WIDTH+ROW_WIDTH+COL_WIDTH-1:0] 71 | addr, // word address 72 | input [15:0] din, // 16-bit data input 73 | output [15:0] dout, // word output 74 | output [127:0] dout128, // 128-bit data output 75 | output reg data_ready = 1'b0, // available 6 cycles after wr is set 76 | output reg busy = 1'b1, // 0: ready for next command 77 | 78 | // Write leveling. This is done after mode registers are set. 79 | output write_level_done, // 1 means write leveling is successful for this DQS 80 | output reg [7:0] wstep, // write delay steps, 8 bits for each DQS. this is result of write leveling. 81 | 82 | // Read calibration 83 | // Increment rclkpos/rclksel, send a BL8 read command, and once a rburst 84 | // pulse is detected, then we have read calibration. 85 | output read_calib_done, // 1: read calibration successful 86 | output reg [1:0] rclkpos, // cycle value for read clock (0-3), 2 bits for each DQS 87 | output reg [2:0] rclksel, // phase value for read clock (0-7), 3 bits for each DQS 88 | 89 | output [63:0] debug 90 | ); 91 | 92 | // More timing parameters 93 | localparam WLMRD= 44; // Write leveling wait time before DQS pulse 94 | localparam SERDES = 16; // SERDES round-trip latency in (OSER8 is 3 clk, IDER8 is 1 clk) 95 | 96 | `ifdef DDR3_800 97 | localparam USEC = 100; // a micro second in pclk cycles (pclk <= 100Mhz) 98 | `else 99 | localparam USEC = 134; // pclk <= 133Mhz 100 | `endif 101 | 102 | // Wait until DLL locked to do anything 103 | wire dlllock; 104 | wire rst_lock_n = resetn & dlllock; 105 | reg resetn_delay; 106 | assign DDR3_nRESET = rst_lock_n & resetn_delay; 107 | assign DDR3_ODT = 1'b1; // Use dynamic ODT 108 | 109 | // Tri-state DQ inout signals (double DDR3_CK speed) 110 | reg [15:0] dq_out [7:0]; // DQ output data 111 | reg [0:3] dq_oen; // out_enable_n for dq_out[1:0], [3:2], [5:4], [7:6] 112 | wire [15:0] dq_in [7:0]; // DQ input data 113 | reg [0:7] dqs_out; // DQS output 114 | reg [0:3] dqs_oen; // out_enable_n for dqs_out[1:0], [3:2], [5:4], [7:6] 115 | reg [0:7] dm_out; 116 | 117 | // Bit lengths 118 | typedef logic [7:0] BYTE; 119 | typedef logic [3:0] NIB; 120 | typedef logic [4:0] FIVEB; 121 | 122 | // Debug stuff 123 | reg [7:0] cnt_read = 0; 124 | reg [7:0] cnt_write = 0; 125 | assign debug = {cnt_write, cnt_read, BYTE'(state)}; 126 | 127 | // Output signals 128 | reg nRAS[3:0], nCAS[3:0], nWE[3:0]; 129 | reg [ROW_WIDTH-1:0] A[3:0]; 130 | reg [2:0] BA[3:0]; 131 | assign DDR3_CK = ck; 132 | assign DDR3_nCS = 1'b0; 133 | 134 | assign dout128 = {dq_in[0], dq_in[1], dq_in[2], dq_in[3], dq_in[4], dq_in[5], dq_in[6], dq_in[7]}; 135 | `ifdef SIM 136 | assign dout = dq_in[4]; // somehow in simulation data is here 137 | `else 138 | `ifdef DDR3_800 139 | assign dout = dq_in[0]; 140 | `else 141 | assign dout = dq_in[4]; 142 | `endif 143 | `endif 144 | 145 | // Our main FSM state 146 | reg [3:0] state; 147 | localparam RST_WAIT = 4'd0; 148 | localparam CKE_WAIT = 4'b1; 149 | localparam CONFIG = 4'd2; 150 | localparam ZQCL = 4'd3; 151 | localparam IDLE = 4'd4; 152 | localparam READ = 4'd5; 153 | localparam WRITE = 4'd6; 154 | localparam REFRESH = 4'd7; 155 | localparam WRITE_LEVELING = 4'd8; 156 | localparam READ_CALIB = 4'd9; 157 | reg [4:0] cycle; // step within operation (config/read/write) 158 | reg tick; // pulse after tick_counter cycles 159 | reg [16:0] tick_counter = 17'd50_000; 160 | 161 | // RAS# CAS# WE# 162 | localparam CMD_SetModeReg=3'b000; 163 | localparam CMD_AutoRefresh=3'b001; 164 | localparam CMD_PreCharge=3'b010; 165 | localparam CMD_BankActivate=3'b011; 166 | localparam CMD_Write=3'b100; 167 | localparam CMD_Read=3'b101; 168 | localparam CMD_ZQCL=3'b110; 169 | localparam CMD_NOP=3'b111; 170 | 171 | // Mode registers are {BA[2:0], A[12:0]}, total 16 bits 172 | localparam [1:0] M_BL = 2'b01; // burst length BC4 or 8 on the fly 173 | `ifdef DDR3_800 174 | localparam [3:0] M_CAS = 4'b0100; // 6 cycles 175 | localparam [2:0] M_CWL = 3'b000; // 5 cycles 176 | localparam [2:0] M_WR = 3'b010; // 6 cycles 177 | `else 178 | localparam [3:0] M_CAS = 4'b0110; // 7 cycles 179 | localparam [2:0] M_CWL = 3'b001; // 6 cycles 180 | localparam [2:0] M_WR = 3'b100; // 8 cycles 181 | `endif 182 | localparam M_DLLReset = 1'b1; 183 | localparam M_RTT_NOM = 3'b000; // Disabled, RTT_NOM is only needed for multi-rank systems 184 | localparam M_RTT_WR = 2'b01; // RTT_WR = 60ohm (2: 120ohm) 185 | localparam M_RTT_WR_off = 2'b00; // 186 | localparam M_DRIVE = 2'b00; // 00: low drive strength, 01: high 187 | localparam M_AL = 2'b0; // AL=0 188 | wire [15:0] MR0 = 189 | //15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 190 | {3'b000, 1'b0, M_WR, M_DLLReset, 1'b0, M_CAS[3:1], 1'b0, M_CAS[0], M_BL}; 191 | wire [15:0] MR1 = 192 | //15 14 13 12:10 9 8 7 6 5 4 3 2 1 0 193 | {3'b001, 3'b0, M_RTT_NOM[2], 2'b0, M_RTT_NOM[1], M_DRIVE[1], M_AL, M_RTT_NOM[0], M_DRIVE[0], 1'b0}; 194 | wire [15:0] MR2 = 195 | //15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 196 | {3'b010, 2'b0, M_RTT_WR_off, 3'b0, M_CWL, 3'b0}; 197 | wire [15:0] MR2_RTT_WR = // Dynamic ODT is applied after write leveling 198 | {3'b010, 2'b0, M_RTT_WR, 3'b0, M_CWL, 3'b0}; 199 | // We use dynamic ODT because it allows ODT pin to be tied to 1. 200 | // RTT_WR will be automatically applied when there is a write. 201 | // See: Micron TN-41-13: DDR3 Point-to-Point Design Support 202 | wire [15:0] MR3 = {3'b011, 13'b0}; 203 | 204 | // Write leveling 205 | reg wlevel_done = 1'b0; 206 | reg [3:0] wlevel_cnt = 3'b0; 207 | assign write_level_done = wlevel_done; 208 | 209 | // Read calibration. 210 | // Note there's no read eye diagram testing yet. 211 | reg [3:0] dqs_read = 4'b0; 212 | reg dqs_hold = 1'b0; 213 | wire [1:0] rburst; 214 | reg [1:0] rburst_seen; 215 | reg rcalib_done = 1'b0; 216 | reg [3:0] rcalib_cnt = 4'b0; 217 | assign read_calib_done = rcalib_done; 218 | 219 | `ifdef SIM 220 | localparam WLEVEL_COUNT=2; 221 | localparam RCALIB_COUNT=2; 222 | `else 223 | localparam WLEVEL_COUNT=1; // test this many times before a wstep passes write leveling 224 | localparam RCALIB_COUNT=8; // test this many times before rclkpos/rclksel passes read calib 225 | `endif 226 | 227 | // 228 | // DDR3 state machine 229 | // 230 | always @(posedge pclk) begin 231 | if (rst_lock_n) begin 232 | cycle <= cycle == 5'd31 ? 5'd31 : cycle + 4'd1; 233 | tick <= tick_counter == 16'd1; 234 | tick_counter <= tick_counter == 0 ? 0 : tick_counter - 16'd1; 235 | 236 | // defaults 237 | {nRAS[0], nCAS[0], nWE[0]} <= CMD_NOP; {nRAS[1], nCAS[1], nWE[1]} <= CMD_NOP; 238 | {nRAS[2], nCAS[2], nWE[2]} <= CMD_NOP; {nRAS[3], nCAS[3], nWE[3]} <= CMD_NOP; 239 | A[0] <= 1'b0; A[1] <= 1'b0; A[2] <= 1'b0; A[3] <= 1'b0; 240 | BA[0] <= 3'b0; BA[1] <= 3'b0; BA[2] <= 3'b0; BA[3] <= 3'b0; 241 | dm_out = 8'b1111_1111; 242 | dqs_oen[0:3] <= 4'b1111; 243 | dq_oen[0:3] <= 4'b1111; 244 | dqs_hold <= 1'b0; 245 | 246 | casex ({state, cycle}) 247 | // RESET off after 200 us 248 | {RST_WAIT, 5'bxxxxx} : if (tick) begin 249 | resetn_delay <= 1'b1; 250 | `ifdef SIM 251 | tick_counter <= 17'd19; 252 | `else 253 | tick_counter <= 500 * USEC + 20; 254 | `endif 255 | state <= CKE_WAIT; 256 | end 257 | 258 | // CKE on after 500 us before 259 | {CKE_WAIT, 5'bxxxxx} : begin 260 | if (tick_counter == 16'd15) 261 | DDR3_CKE <= 1'b1; // tXPR (120ns) between CKE and MRS 262 | if (tick) begin 263 | state <= CONFIG; 264 | cycle <= 0; 265 | end 266 | end 267 | 268 | // Mode Register Config sequence 269 | // cycle //0 \___/ ...___//4 \___/ ... __//8 \___/ ...___//12\___/ ...___//16\___/ ...___//28\___/ ...___/1024+28\___ 270 | // cmd | MR0 | | MR1 | | MR2 | | MR3 | | ZQCL | | _Next_| 271 | // '---- MRD=4 ----'---- MRD=4 ---'---- MRD=4 ---'-----MOD=12----'--tZQCL+tDLLK--' 272 | {CONFIG, FIVEB'(0)} : begin 273 | {nRAS[0], nCAS[0], nWE[0]} <= CMD_SetModeReg; 274 | {BA[0], A[0][12:0]} <= MR2; 275 | end 276 | {CONFIG, FIVEB'(MRD/4)} : begin 277 | {nRAS[0], nCAS[0], nWE[0]} <= CMD_SetModeReg; 278 | {BA[0], A[0][12:0]} <= MR3; 279 | end 280 | {CONFIG, FIVEB'(MRD/2)} : begin 281 | {nRAS[0], nCAS[0], nWE[0]} <= CMD_SetModeReg; 282 | {BA[0], A[0][12:0]} <= MR1; 283 | end 284 | {CONFIG, FIVEB'(MRD*3/4)} : begin 285 | {nRAS[0], nCAS[0], nWE[0]} <= CMD_SetModeReg; 286 | {BA[0], A[0][12:0]} <= MR0; 287 | end 288 | {CONFIG, FIVEB'(MRD*3/4+MOD/4+1)} : begin 289 | {nRAS[0], nCAS[0], nWE[0]} <= CMD_ZQCL; 290 | A[0][10] <= 1'b1; // long ZQ calibration 291 | `ifdef SIM 292 | tick_counter <= 16'd2; // 1024 nCK (256 clk), set to 2 for simulation 293 | `else 294 | tick_counter <= 16'd512 + 2; 295 | `endif 296 | state <= ZQCL; 297 | end 298 | 299 | // ZQ calibration 300 | {ZQCL, 5'bxxxxx} : if (tick) begin 301 | state <= WRITE_LEVELING; 302 | cycle <= 0; 303 | end 304 | 305 | // read/write/refresh 306 | {IDLE, 5'bxxxxx}: if (rd | wr) begin 307 | // bank activate 308 | {nRAS[0], nCAS[0], nWE[0]} <= CMD_BankActivate; 309 | BA[0] <= addr[ROW_WIDTH+COL_WIDTH+BANK_WIDTH-1 : ROW_WIDTH+COL_WIDTH]; // bank id 310 | A[0] <= addr[ROW_WIDTH+COL_WIDTH-1:COL_WIDTH]; // 12-bit row address 311 | state <= rd ? READ : WRITE; 312 | if (rd) cnt_read <= cnt_read == 8'hff ? 8'hff : cnt_read + 1; 313 | if (wr) cnt_write <= cnt_write == 8'hff ? 8'hff : cnt_write + 1; 314 | cycle <= 4'd1; 315 | busy <= 1'b1; 316 | if (rd) dqs_hold <= 1'b1; // reset WPOINT/RPOINT 317 | end else if (refresh) begin 318 | // auto-refresh 319 | // no need for precharge-all b/c all our r/w are done with auto-precharge. 320 | {nRAS[0], nCAS[0], nWE[0]} <= CMD_AutoRefresh; 321 | state <= REFRESH; 322 | cycle <= 4'd1; 323 | busy <= 1'b1; 324 | end 325 | 326 | // Read sequence (9 cycles at 100Mhz) 327 | // Quirk: you can issue next command once you see data_ready at cycle 8 (busy will be 0 next cycle), that saves a cycle 328 | // CK \___//0 \___/ 1 \___/ 2 \___/ 3 \___//4 \___/ 5 \___/ 6 \___/ 7 \___//8 \___/ 9 \___/ 10\___/ 11 ...//32\___/ 33\___/ 34\___/ 35\___//36\___/ 37\___/ 38\___/ 39\___ 329 | // RD _|| 1 || || _NEXT_ | 330 | // CMD ||ACTIVE| | | || | | READ | || 331 | // ADDR ||Row | | | || | | Col n | || 332 | // DQS ---------------------------------------------------------------------------------------------____/ \___/ \___-------------- 333 | // DQ ||DO|DO |DO |DO || 334 | // ||n |n+1|n+2|n+3|| 335 | // `-------------------- RCD=6 --------------------' CL6+SERDES=22 ' 336 | // data_ready ___________________________________________________________________________________________/ \______ 337 | // busy ________________________________/ \______ 338 | {READ, FIVEB'(RCD/4)}: begin // 1 339 | {nRAS[RCD%4], nCAS[RCD%4], nWE[RCD%4]} <= CMD_Read; // 101 340 | BA[RCD%4] <= addr[ROW_WIDTH+COL_WIDTH+BANK_WIDTH-1 : ROW_WIDTH+COL_WIDTH]; // bank id 341 | A[RCD%4][12] <= 1'b1; // BL8 burst length 342 | A[RCD%4][10] <= 1'b1; // set auto precharge 343 | A[RCD%4][9:0] <= addr[COL_WIDTH-1:0]; // column address 344 | 345 | dqs_hold <= 1'b1; // make hold pulse one cycle longer as we are having setup violation here... 346 | end 347 | {READ, FIVEB'((RCD+CAS+SERDES)/4+1)}: begin // 7 (6+6+16 = 28) 348 | data_ready <= 1'b1; 349 | end 350 | {READ, FIVEB'((RCD+CAS+SERDES)/4+2)}: begin // 8 351 | data_ready <= 1'b0; 352 | busy <= 0; 353 | state <= IDLE; 354 | end 355 | 356 | // write sequence (7 cycles at 100Mhz) 357 | // CK \___//0 \___/ 1 \___/ 2 \___/ 3 \___//4 \___/ 5 \___/ 6 \___/ 7 \___//8 \___/ 9 \___/ 10\___/ 11\___//12\___/ 13\___/ 14\___/ 15\___//16\___/ 17\___/ 18\___/ 19 ...//28\___/ 29\___/ 30\___/ 31\___ 358 | // WR | 1 || | || | | || _NEXT_ 359 | // CMD ||ACTIVE| | | || | | WRITE | || | || | | 360 | // ADDR || Row | | | || | | COL n | || | || | | 361 | // DQS ----------------------------------------------------------------------------------------------------------------------/ \___/ \___/ \___---------- 362 | // DQ |Din|Din|Din|Din|Din|Din|Din|Din| 363 | // |n |n+1|n+2|n+3|n+4|n+5|n+6|n+7| 364 | // `-------------------- RCD=6 --------------------'--------------- CWL = 5 ---------------'------------ 4 --------------'--------- WR+RP = 12 ----------' 365 | // busy __________________________________/ \_______ (negedge at 24) 366 | 367 | {WRITE, FIVEB'(RCD/4)}: begin 368 | {nRAS[RCD%4], nCAS[RCD%4], nWE[RCD%4]} <= CMD_Write; // 100 369 | BA[RCD%4] <= addr[ROW_WIDTH+COL_WIDTH+BANK_WIDTH-1 : ROW_WIDTH+COL_WIDTH]; // bank id 370 | A[RCD%4][10] <= 1'b1; // set auto precharge 371 | A[RCD%4][9:0] <= addr[COL_WIDTH-1:0]; // column address 372 | A[RCD%4][12] <= 1'b0; // BC4 burst length 373 | end 374 | `ifdef DDR3_800 375 | {WRITE, FIVEB'((RCD+CWL)/4)}: begin 376 | // DQS output 377 | dqs_out <= 8'b1111_1110; 378 | dqs_oen <= 4'b1110; 379 | 380 | // DQ output 381 | dq_out[6] <= 0; dq_out[7] <= din; 382 | dq_oen <= 4'b1110; 383 | 384 | // DM, umask the word we are writing to 385 | // Note that BC4 write always start from whole 4 words (not the exact address we want to write to) 386 | dm_out[7] <= !(addr[1:0] == 2'b00); 387 | end 388 | {WRITE, FIVEB'((RCD+CWL)/4+1)}: begin 389 | // DQS output 390 | dqs_out <= 8'b1010_0000; 391 | dqs_oen <= 4'b0011; 392 | 393 | // DQ output 394 | dq_out[0] <= din; dq_out[1] <= din; 395 | dq_out[2] <= din; dq_out[3] <= 0; 396 | dq_oen <= 4'b0011; 397 | 398 | dm_out[0] <= !(addr[1:0] == 2'b01); 399 | dm_out[1] <= !(addr[1:0] == 2'b10); 400 | dm_out[2] <= !(addr[1:0] == 2'b11); 401 | end 402 | {WRITE, FIVEB'(20/4)}: begin // busy=0 at 24 403 | busy <= 0; 404 | state <= IDLE; 405 | end 406 | `else 407 | // DDR3-1066: phase is 2 steps ahead of DDR3-800 408 | {WRITE, FIVEB'((RCD+CWL)/4)}: begin // 3 (8+6=14) for DDR3-1066 409 | // DQS output 410 | dqs_out <= 8'b1111_1010; 411 | dqs_oen <= 4'b1100; 412 | 413 | // DQ output 414 | dq_out[4] <= 0; dq_out[5] <= din; 415 | dq_out[6] <= din; dq_out[7] <= din; 416 | dq_oen <= 4'b1100; 417 | 418 | dm_out[5] <= !(addr[1:0] == 2'b00); 419 | dm_out[6] <= !(addr[1:0] == 2'b01); 420 | dm_out[7] <= !(addr[1:0] == 2'b10); 421 | end 422 | {WRITE, FIVEB'((RCD+CWL)/4+1)}: begin 423 | // DQS output 424 | dqs_out <= 8'b1000_0000; 425 | dqs_oen <= 4'b0111; 426 | 427 | // DQ output 428 | dq_out[0] <= din; dq_out[1] <= 0; 429 | dq_oen <= 4'b0111; 430 | 431 | dm_out[0] <= !(addr[1:0] == 2'b11); 432 | end 433 | {WRITE, FIVEB'(24/4)}: begin // busy=0 at 28 434 | busy <= 0; 435 | state <= IDLE; 436 | end 437 | `endif 438 | 439 | 440 | // refresh sequence (6 cycles in 100Mhz) 441 | // ck \___//0 \___/ 1 \___/ 2 \___/ 3 \___//4 \___/ 5 \___/ 6 \___/ 7 ...//20\___/ 21\___/ 22\___/ 23\___//24\___/ 25\___/ 26\___/ 27\___ 442 | // refresh | 1 | || _NEXT_ | 443 | // cmd |Refresh| | | || | | | || 444 | // busy _______________________________/ \________________________________ 445 | // `----------------------- T_RC ----------------------------------' 446 | {REFRESH, FIVEB'(RC/4)}: begin 447 | state <= IDLE; 448 | busy <= 0; 449 | end 450 | 451 | // Write Leveling 452 | // After tWLDQSEN(25nck), drive DQS low. After tWLMRD (40nCK), pulse DQS, then after tWLO (7.2ns) feedback is provide on prime DQ 453 | {WRITE_LEVELING, FIVEB'(0)}: begin 454 | $display("Entering WRITE LEVELING"); 455 | // enter write leveling mode 456 | {nRAS[0], nCAS[0], nWE[0]} <= CMD_SetModeReg; 457 | // MR1[9,6,2]=001, RTT_NOM=60ohm, as dynamic ODT is not available in write leveling 458 | {BA[0], A[0][12:0]} <= MR1 | 8'b1000_0100; // MR1[7] is write-leveling 459 | wlevel_cnt <= 0; 460 | `ifdef SIM 461 | `ifdef DDR3_800 462 | wstep <= 8'h18; // quick start write leveling for simulation 463 | `else 464 | wstep <= 8'h12; 465 | `endif 466 | `endif 467 | end 468 | {WRITE_LEVELING, FIVEB'(WLMRD/4-1)}, {WRITE_LEVELING, FIVEB'(WLMRD/4+1)}, 469 | {WRITE_LEVELING, FIVEB'(WLMRD/4+2)}, {WRITE_LEVELING, FIVEB'(WLMRD/4+3)}, 470 | {WRITE_LEVELING, FIVEB'(WLMRD/4+4)}, {WRITE_LEVELING, FIVEB'(WLMRD/4+5)}: begin 471 | dqs_out[0:7] <= 8'b0; // bring down DQS 472 | dqs_oen[0:3] <= 4'b0; 473 | end 474 | {WRITE_LEVELING, FIVEB'(WLMRD/4)}: begin 475 | $display("wstep=%d", wstep); 476 | dqs_out[0:7] <= 8'b1010_1010; // provide a test pulse 477 | dqs_oen[0:3] <= 4'b0; 478 | end 479 | {WRITE_LEVELING, FIVEB'(WLMRD/4+6)}: begin // SERDES round trip + feedback time tWLO=7.5ns 480 | dqs_out[0:7] <= 8'b0; 481 | dqs_oen[0:3] <= 4'b0; 482 | 483 | if (~DDR3_DQ[0] || ~DDR3_DQ[8]) begin 484 | wstep <= wstep + 1'd1; 485 | wlevel_cnt <= 0; 486 | cycle <= FIVEB'(WLMRD/4-1); // loop 487 | end else begin 488 | wlevel_cnt <= wlevel_cnt + 1'b1; 489 | // test WLEVEL_COUNT times before we commit 490 | if (wlevel_cnt == NIB'(WLEVEL_COUNT-1'b1)) begin 491 | $display("Write leveling process finished."); 492 | wlevel_done <= 1'b1; 493 | // Exit write leveling mode 494 | {nRAS[0], nCAS[0], nWE[0]} <= CMD_SetModeReg; 495 | {BA[0], A[0][12:0]} <= MR1; // A[7] is write-leveling 496 | end else 497 | cycle <= FIVEB'(WLMRD/4-1); 498 | end 499 | end 500 | {WRITE_LEVELING, FIVEB'((WLMRD+MRD)/4+6)}: begin 501 | // Turn on dynamic ODT 502 | {nRAS[0], nCAS[0], nWE[0]} <= CMD_SetModeReg; 503 | {BA[0], A[0][12:0]} <= MR2_RTT_WR; 504 | end 505 | {WRITE_LEVELING, FIVEB'((WLMRD+MRD+MOD)/4+6)}: begin 506 | state <= READ_CALIB; // now continue to read calibration 507 | cycle <= 0; 508 | end 509 | 510 | // Read calibration 511 | // Issues BL8 read commands while adjusting rclkpos (0-3), rclksel (0-7) 512 | // until we see rburst pulse after the read. Then read calibration is achieved. 513 | {READ_CALIB, FIVEB'(0)}: begin 514 | $display("Entering READ CALIBRATION"); 515 | // activate bank 0 516 | {nRAS[0], nCAS[0], nWE[0]} <= CMD_BankActivate; 517 | BA[0] <= 0; A[0] <= 0; 518 | rcalib_cnt <= 0; 519 | `ifdef SIM 520 | // in simulation the final rclkpos=2, rclksel=0 for DDR3-800 521 | // rclkpos=1, rclksel=1 for DDR3-1066 522 | `ifdef DDR3_800 523 | rclkpos <= 2'd1; rclksel <= 3'd6; 524 | `else 525 | rclkpos <= 2'd1; rclksel <= 3'd0; 526 | `endif 527 | `endif 528 | end 529 | {READ_CALIB, FIVEB'(RCD/4)}: begin 530 | // issue read 531 | $display("rclkpos=%d, rclksel=%d", rclkpos, rclksel); 532 | {nRAS[2], nCAS[2], nWE[2]} <= CMD_Read; 533 | A[2][12] <= 1'b1; // BL8 burst length 534 | A[2][10] <= 1'b0; // NO auto precharge 535 | A[2][9:0] <= 0; // row address=0 536 | end 537 | {READ_CALIB, FIVEB'(RCD/4+10)}: begin // Allow 10 cycles for rburst signal 538 | if (rburst_seen != 2'b11) begin 539 | rclksel <= rclksel + 3'b1; 540 | rclkpos <= rclksel == 3'd7 ? rclkpos + 2'b1 : rclkpos; 541 | rcalib_cnt <= 0; 542 | cycle <= FIVEB'(RCD/4); // loop 543 | end else begin 544 | rcalib_cnt <= rcalib_cnt + 1'b1; 545 | // test RCALIB_COUNT times before we commit 546 | if (rcalib_cnt == NIB'(RCALIB_COUNT - 1)) begin 547 | // read calibration is achieved 548 | rcalib_done <= 1'b1; 549 | {nRAS[0], nCAS[0], nWE[0]} <= CMD_PreCharge; // precharge 550 | BA[0] <= 0; A[0] <= 0; // bank 0, row 0 551 | // exit read calib 552 | end else 553 | cycle <= FIVEB'(RCD/4); // loop 554 | end 555 | end 556 | {READ_CALIB, FIVEB'(RCD/4+10+RP/4)}: begin 557 | // Precharge is finished. Exit read calibration. Initialization is all done. 558 | $display("All initialization DONE..."); 559 | busy <= 1'b0; 560 | state <= IDLE; 561 | end 562 | endcase 563 | end else if (~rst_lock_n) begin 564 | busy <= 1'b1; 565 | data_ready <= 1'b0; 566 | DDR3_CKE <= 1'b0; 567 | {nRAS[0], nCAS[0], nWE[0]} <= CMD_NOP; 568 | {nRAS[1], nCAS[1], nWE[1]} <= CMD_NOP; 569 | {nRAS[2], nCAS[2], nWE[2]} <= CMD_NOP; 570 | {nRAS[3], nCAS[3], nWE[3]} <= CMD_NOP; 571 | `ifdef SIM 572 | tick_counter <= 16'd1; // initial 500us delay, 140ns in simulation 573 | `else 574 | tick_counter <= 16'd60_000; // initial 500us delay 575 | `endif 576 | tick <= 0; 577 | cycle <= 0; 578 | wlevel_cnt <= 0; wlevel_done <= 2'b0; wstep <= 0; 579 | rcalib_cnt <= 0; rcalib_done <= 0; rclkpos <= 0; rclksel <= 0; 580 | resetn_delay <= 1'b0; // cause extra 200us reset for DDR3 581 | state <= RST_WAIT; 582 | end 583 | end 584 | 585 | // Monitor rburst pulses and set rburst_seen when one is seen 586 | always @(posedge pclk) begin 587 | if (rburst[0]) rburst_seen[0] <= 1'b1; 588 | if (rburst[1]) rburst_seen[1] <= 1'b1; 589 | if ({state,cycle} == {READ_CALIB, FIVEB'(RCD/4)}) // when we send read calibration req. 590 | rburst_seen <= 2'b0; 591 | if (~rst_lock_n) begin 592 | rburst_seen <= 2'b0; 593 | end 594 | end 595 | 596 | // Output READ pulse is for detecting DQS signal 597 | // RCLKSEL shifts READ pulse by 1/4 CK per step 598 | // Read calibration is done by first trying all RCLKSEL values (total 8) 599 | // Then move READ pulse to next cycle (total 4). So there're 32 positions to try. 600 | // When signals align, there will be a RBURST pulse. 601 | always @(posedge pclk) begin 602 | dqs_read <= 0; 603 | if ((state == READ || state == READ_CALIB) 604 | && cycle == FIVEB'(rclkpos+RCD/4+1)) begin 605 | dqs_read <= 4'b1111; 606 | end 607 | end 608 | 609 | // 610 | // SERDES IOLOGIC for DDR3 611 | // 612 | wire [7:0] dllstep; 613 | 614 | `ifdef SIM 615 | // DLL simulation takes too long to lock (33600 cycles). So let's cheat. 616 | assign dllstep = 8'd25; 617 | assign dlllock = 1'b1; 618 | `else 619 | // SCAL_EN=="false" means constant output of 620 | // Every DLL step is about 0.025 ns. For 100Mhz, dllstep should be roughly 0.625/0.025=25 621 | DLL #( 622 | .SCAL_EN("true"), .CODESCAL("101") // 68-degree phase shift 623 | // .SCAL_EN("false") // 90° phase shift 624 | ) dll( 625 | .CLKIN(fclk), .RESET(~resetn), .STOP(0), 626 | .UPDNCNTL(1'b0), .STEP(dllstep), .LOCK(dlllock) 627 | ); 628 | `endif 629 | 630 | wire [2:0] dqs_waddr[1:0], dqs_raddr[1:0]; 631 | wire clk_dqsr[1:0]; 632 | wire clk_dqsw[1:0]; 633 | wire clk_dqsw270[1:0]; 634 | generate 635 | // ck is fclk delayed 90 degrees with PLL 636 | // DQSR90 is DQSIN delayed DLLSTEP. 637 | // DQSW0 is fclk delayed WSTEP 638 | // DQSW270 is fclk delayed WSTEP+DLLSTEP+180-degrees. 639 | for (genvar i0 = 0; i0 < 2; i0++) begin : gen_dqs_controller 640 | DQS #( 641 | .DQS_MODE("X4"), .HWL("false") // HWL is related to WL&RL 642 | // .DQS_MODE("X4"), .HWL("true") 643 | ) u_dqs ( 644 | .FCLK(fclk), .PCLK(pclk), .DQSIN(DDR3_DQS[i0]), .RESET(~rst_lock_n), .HOLD(dqs_hold), 645 | .RLOADN(1'b0), .WLOADN(1'b0), .RMOVE(1'b0), .WMOVE(1'b0), 646 | .DLLSTEP(dllstep), .WSTEP(wstep), // 0.625/0.025 647 | .RCLKSEL(rclksel), .READ(dqs_read), 648 | .DQSR90(clk_dqsr[i0]), .WPOINT(dqs_waddr[i0]), .RPOINT(dqs_raddr[i0]), 649 | .DQSW0(clk_dqsw[i0]), .DQSW270(clk_dqsw270[i0]), .RBURST(rburst[i0]) 650 | ); 651 | end 652 | endgenerate 653 | 654 | // 2*CK speed in/out for data(DQ), data strobe(DQS) and data mask(DM) 655 | wire [15:0] dq_buf, dq_buf_oen; // I/O buffer internal use 656 | generate 657 | for (genvar i1 = 0; i1 < 16; i1++) begin : gen_dq 658 | OSER8_MEM #(.TCLK_SOURCE("DQSW270")) oser_dq( 659 | .D0(dq_out[0][i1]), .D1(dq_out[1][i1]), .D2(dq_out[2][i1]), .D3(dq_out[3][i1]), 660 | .D4(dq_out[4][i1]), .D5(dq_out[5][i1]), .D6(dq_out[6][i1]), .D7(dq_out[7][i1]), 661 | .TX0(dq_oen[0]), .TX1(dq_oen[1]), .TX2(dq_oen[2]), .TX3(dq_oen[3]), 662 | .FCLK(fclk), .PCLK(pclk), .TCLK(clk_dqsw270[i1/8]), .RESET(~rst_lock_n|| ~dlllock), 663 | .Q0(dq_buf[i1]), .Q1(dq_buf_oen[i1]) 664 | ); 665 | assign DDR3_DQ[i1] = dq_buf_oen[i1] ? 1'bz : dq_buf[i1]; 666 | 667 | // The fifo is for clock domain crossing from DQS to fclk 668 | IDES8_MEM iser_dq( 669 | .D(DDR3_DQ[i1]), .ICLK(clk_dqsr[i1/8]), .FCLK(fclk), .PCLK(pclk), .CALIB(1'b0), .RESET(~rst_lock_n), 670 | .Q0(dq_in[0][i1]), .Q1(dq_in[1][i1]), .Q2(dq_in[2][i1]), .Q3(dq_in[3][i1]), 671 | .Q4(dq_in[4][i1]), .Q5(dq_in[5][i1]), .Q6(dq_in[6][i1]), .Q7(dq_in[7][i1]), 672 | .WADDR(dqs_waddr[i1/8]), .RADDR(dqs_raddr[i1/8]) 673 | ); 674 | end 675 | endgenerate 676 | 677 | // DQS[1:0], DM[1:0] 678 | wire [1:0] dqs_buf, dqs_buf_oen; 679 | wire [1:0] dqs_buf_delayed; 680 | generate 681 | for (genvar i2 = 0; i2 < 2; i2++) begin : gen_dqs 682 | // DQS is output using the DQSW0 683 | OSER8_MEM oser_dqs( 684 | .D0(dqs_out[0]), .D1(dqs_out[1]), .D2(dqs_out[2]), .D3(dqs_out[3]), 685 | .D4(dqs_out[4]), .D5(dqs_out[5]), .D6(dqs_out[6]), .D7(dqs_out[7]), 686 | .TX0(dqs_oen[0]), .TX1(dqs_oen[1]), .TX2(dqs_oen[2]), .TX3(dqs_oen[3]), 687 | .FCLK(fclk), .PCLK(pclk), .TCLK(clk_dqsw[i2]), .RESET(~rst_lock_n), 688 | .Q0(dqs_buf[i2]), .Q1(dqs_buf_oen[i2]) 689 | ); 690 | assign DDR3_DQS[i2] = dqs_buf_oen[i2] ? 1'bz : dqs_buf[i2]; 691 | 692 | // DM is aligned with DQ 693 | OSER8_MEM #(.TCLK_SOURCE("DQSW270")) oser_dm( 694 | .D0(dm_out[0]), .D1(dm_out[1]), .D2(dm_out[2]), .D3(dm_out[3]), 695 | .D4(dm_out[4]), .D5(dm_out[5]), .D6(dm_out[6]), .D7(dm_out[7]), 696 | .FCLK(fclk), .PCLK(pclk), .TCLK(clk_dqsw270[i2]), .RESET(~rst_lock_n), .Q0(DDR3_DM[i2]) 697 | ); 698 | end 699 | endgenerate 700 | 701 | // CK speed output for nRAS, nCAS, nWE 702 | OSER8 oser_nras( 703 | .D0(nRAS[0]), .D1(nRAS[0]), .D2(nRAS[1]), .D3(nRAS[1]), 704 | .D4(nRAS[2]), .D5(nRAS[2]), .D6(nRAS[3]), .D7(nRAS[3]), 705 | .FCLK(fclk), .PCLK(pclk), .RESET(~rst_lock_n), .Q0(DDR3_nRAS) 706 | ); 707 | OSER8 oser_ncas( 708 | .D0(nCAS[0]), .D1(nCAS[0]), .D2(nCAS[1]), .D3(nCAS[1]), 709 | .D4(nCAS[2]), .D5(nCAS[2]), .D6(nCAS[3]), .D7(nCAS[3]), 710 | .FCLK(fclk), .PCLK(pclk), .RESET(~rst_lock_n), .Q0(DDR3_nCAS) 711 | ); 712 | OSER8 oser_nwe( 713 | .D0(nWE[0]), .D1(nWE[0]), .D2(nWE[1]), .D3(nWE[1]), 714 | .D4(nWE[2]), .D5(nWE[2]), .D6(nWE[3]), .D7(nWE[3]), 715 | .FCLK(fclk), .PCLK(pclk), .RESET(~rst_lock_n), .Q0(DDR3_nWE) 716 | ); 717 | 718 | // Address lines (CK speed) 719 | generate 720 | for (genvar i3 = 0; i3 < ROW_WIDTH; i3++) begin: gen_a 721 | OSER8 oser_a( 722 | .D0(A[0][i3]), .D1(A[0][i3]), .D2(A[1][i3]), .D3(A[1][i3]), 723 | .D4(A[2][i3]), .D5(A[2][i3]), .D6(A[3][i3]), .D7(A[3][i3]), 724 | .FCLK(fclk), .PCLK(pclk), .RESET(~rst_lock_n), .Q0(DDR3_A[i3]) 725 | ); 726 | end 727 | endgenerate 728 | 729 | // BA lines (CK speed) 730 | generate 731 | for (genvar i4 = 0; i4 < 3; i4++) begin: gen_ba 732 | OSER8 oser_ba( 733 | .D0(BA[0][i4]), .D1(BA[0][i4]), .D2(BA[1][i4]), .D3(BA[1][i4]), 734 | .D4(BA[2][i4]), .D5(BA[2][i4]), .D6(BA[3][i4]), .D7(BA[3][i4]), 735 | .FCLK(fclk), .PCLK(pclk), .RESET(~rst_lock_n), .Q0(DDR3_BA[i4]) 736 | ); 737 | end 738 | endgenerate 739 | 740 | endmodule -------------------------------------------------------------------------------- /src/ddr3_top.v: -------------------------------------------------------------------------------- 1 | // 2 | // DDR3 test top level @ 100Mhz 3 | // 4 | 5 | `timescale 1ps /1ps 6 | 7 | module ddr3_top 8 | ( 9 | input sys_clk, 10 | input sys_resetn, 11 | 12 | input d7, 13 | 14 | inout [15:0] DDR3_DQ, // 16 bit bidirectional data bus 15 | inout [1:0] DDR3_DQS, // DQ strobe for high and low bytes 16 | output [13:0] DDR3_A, // 14 bit multiplexed address bus 17 | output [2:0] DDR3_BA, // 3 banks 18 | output DDR3_nCS, // a single chip select 19 | output DDR3_nWE, // write enable 20 | output DDR3_nRAS, // row address select 21 | output DDR3_nCAS, // columns address select 22 | output DDR3_CK, 23 | output DDR3_nRESET, 24 | output DDR3_CKE, 25 | output DDR3_ODT, 26 | output [1:0] DDR3_DM, 27 | 28 | output [7:0] led, 29 | output [7:0] led2, 30 | 31 | output uart_txp 32 | ); 33 | 34 | reg start = 1'b1; 35 | `ifdef D7_TO_START 36 | // switch d7 on to start running 37 | always @(posedge clk) begin 38 | if (d7) start <= 1; 39 | if (~sys_resetn) start <= 0; 40 | end 41 | `endif 42 | 43 | reg rd, wr, refresh; 44 | reg [25:0] addr; 45 | reg [15:0] din; 46 | wire [127:0] dout128; 47 | wire [15:0] dout; 48 | 49 | localparam FREQ=99_800_000; 50 | 51 | localparam [25:0] START_ADDR = 26'h0; 52 | localparam [25:0] TOTAL_SIZE = 8*1024*1024; // Test 8MB 53 | //localparam [25:0] TOTAL_SIZE = 32*1024*1024; // Test 64MB 54 | 55 | Gowin_rPLL pll( 56 | .clkout(clk_x4), // 398.25 Mhz 57 | .clkoutp(clk_ck), // 90-degree shifted 58 | .lock(lock), 59 | .clkoutd(clk), // 99.56 Mhz 60 | .clkin(sys_clk) // 27 Mhz 61 | ); 62 | 63 | wire [7:0] wstep; 64 | reg [1:0] rclkpos; 65 | reg [2:0] rclksel; 66 | wire [63:0] debug; 67 | 68 | ddr3_controller #(.ROW_WIDTH(13), .COL_WIDTH(10)) u_ddr3 ( 69 | .pclk(clk), .fclk(clk_x4), .ck(clk_ck), .resetn(sys_resetn & lock), 70 | .addr(addr), .rd(rd), .wr(wr), .refresh(refresh), 71 | .din(din), .dout128(dout128), .dout(dout), .data_ready(data_ready), .busy(busy), 72 | .write_level_done(write_level_done), .wstep(wstep), // write leveling status 73 | .read_calib_done(read_calib_done), .rclkpos(rclkpos), .rclksel(rclksel), // read calibration status 74 | .debug(debug), 75 | 76 | .DDR3_nRESET(DDR3_nRESET), 77 | .DDR3_DQ(DDR3_DQ), // 16 bit bidirectional data bus 78 | .DDR3_DQS(DDR3_DQS), // DQ strobes 79 | .DDR3_A(DDR3_A), // 13 bit multiplexed address bus 80 | .DDR3_BA(DDR3_BA), // two banks 81 | .DDR3_nCS(DDR3_nCS), // a single chip select 82 | .DDR3_nWE(DDR3_nWE), // write enable 83 | .DDR3_nRAS(DDR3_nRAS), // row address select 84 | .DDR3_nCAS(DDR3_nCAS), // columns address select 85 | .DDR3_CK(DDR3_CK), 86 | .DDR3_CKE(DDR3_CKE), 87 | .DDR3_ODT(DDR3_ODT), 88 | .DDR3_DM(DDR3_DM) 89 | ); 90 | 91 | localparam INIT = 0; 92 | localparam PRINT_STATUS = 1; 93 | localparam WRITE1 = 2; 94 | localparam WRITE2 = 3; 95 | localparam WRITE3 = 4; 96 | localparam READ_START = 5; 97 | localparam READ = 6; 98 | localparam READ_DONE = 7; 99 | localparam WRITE_BLOCK = 8; 100 | localparam VERIFY_BLOCK = 9; 101 | localparam WIPE = 10; 102 | localparam FINISH = 11; 103 | 104 | reg [7:0] state, end_state; 105 | reg [7:0] work_counter; // 10ms per state to give UART time to print one line of message 106 | reg [7:0] latency_write1, latency_write2, latency_read; 107 | 108 | reg error_bit; 109 | 110 | reg refresh_needed; 111 | reg refresh_executed; // pulse from main FSM 112 | 113 | // 7.8us refresh 114 | reg [11:0] refresh_time; 115 | localparam REFRESH_COUNT=FREQ/1000/1000*7813/1000; // one refresh every 781 cycles for 100Mhz 116 | 117 | always @(posedge clk) begin 118 | if (state) begin 119 | refresh_time <= refresh_time == (REFRESH_COUNT*2-2) ? (REFRESH_COUNT*2-2) : refresh_time + 1; 120 | if (refresh_time == REFRESH_COUNT) 121 | refresh_needed <= 1; 122 | if (refresh_executed) begin 123 | refresh_time <= refresh_time - REFRESH_COUNT; 124 | refresh_needed <= 0; 125 | end 126 | if (~sys_resetn) begin 127 | refresh_time <= 0; 128 | refresh_needed <= 0; 129 | end 130 | end 131 | end 132 | 133 | reg refresh_cycle; 134 | reg [23:0] refresh_count; 135 | reg [24:0] refresh_addr; 136 | 137 | reg [63:0] debug_dq_in_buf [15:0]; 138 | reg [3:0] debug_cycle; 139 | reg [19:0] tick_counter; // 0.01s max 140 | reg tick; 141 | reg result_to_print; // pulse for print control to print a line of result 142 | reg [15:0] expected, actual; 143 | reg [127:0] actual128; 144 | reg [25:0] addr_read; 145 | reg wlevel_feedback; 146 | reg wlevel_done = 0; 147 | reg rlevel_done = 0; 148 | reg [7:0] read_level_cnt; 149 | 150 | // LED module in right-bottom PMOD 151 | assign led = ~{state[3:0], busy, error_bit, read_calib_done, write_level_done}; 152 | assign led2 = ~wstep; // for write leveling 153 | //assign led2 = ~{read_calib_done, 2'b0, rclkpos[1:0], rclksel[2:0]}; // for read calib 154 | 155 | typedef logic [7:0] BYTE; 156 | typedef logic [25:0] ADDR; 157 | 158 | always @(posedge clk) begin 159 | wr <= 0; rd <= 0; refresh <= 0; refresh_executed <= 0; 160 | work_counter <= work_counter + 1; 161 | tick_counter <= tick_counter == 0 ? 0 : tick_counter - 20'd1; 162 | tick <= tick_counter == 20'd1; 163 | 164 | case (state) 165 | // wait for busy==0 (controller initialization done) 166 | INIT: if (lock && sys_resetn && !busy && start) begin 167 | state <= PRINT_STATUS; 168 | tick_counter <= 20'd100_000; 169 | end 170 | PRINT_STATUS: if (tick) begin 171 | tick_counter <= 20'd100_000; 172 | work_counter <= 0; 173 | addr = START_ADDR; 174 | state <= WRITE1; 175 | end 176 | 177 | // Part 1 - single write/read test 178 | WRITE1: if (tick) begin 179 | wr <= 1'b1; 180 | addr <= 26'h0000; 181 | din <= 16'h1122; 182 | work_counter <= 0; 183 | state <= WRITE2; /* WRITE2 */ 184 | tick_counter <= 20'd100_000; // 1ms 185 | end 186 | WRITE2: if (tick) begin 187 | wr <= 1'b1; 188 | addr <= 26'h0001; 189 | din <= 16'h3344; 190 | work_counter <= 0; 191 | state <= WRITE3; /* WRITE2 */ 192 | tick_counter <= 20'd100_000; // 1ms 193 | end 194 | WRITE3: if (tick) begin 195 | if (busy) error_bit <= 1; 196 | // record write latency and issue another write command 197 | latency_write1 <= work_counter[7:0]; 198 | wr <= 1'b1; 199 | addr <= 26'h0002; 200 | din <= 16'h5566; 201 | state <= READ_START; 202 | work_counter <= 0; 203 | debug_cycle <= 0; 204 | tick_counter <= 20'd100_000; // wait 1ms 205 | end 206 | 207 | READ_START: if (tick) begin 208 | addr[15:0] <= 16'h0000; 209 | tick_counter <= 20'd100_000; // wait 1ms 210 | state <= READ; 211 | end 212 | READ: begin 213 | result_to_print <= 0; 214 | if (tick) begin 215 | // issue one read command every tick 216 | if (addr[15:0] == 16'h0003) begin 217 | tick_counter <= 20'd200_000; // wait 2ms 218 | state <= READ_DONE; 219 | end else begin 220 | rd <= 1'b1; 221 | tick_counter <= 20'd200_000; // wait 2ms 222 | end 223 | end else if (data_ready) begin 224 | actual <= dout; 225 | actual128 <= dout128; 226 | addr_read <= addr; 227 | result_to_print <= 1'b1; 228 | addr[15:0] <= addr[15:0] + 16'd1; 229 | end 230 | end 231 | READ_DONE: begin 232 | state <= WIPE; 233 | work_counter <= 0; 234 | addr <= START_ADDR; 235 | end 236 | 237 | // Part 2 - bulk write/read test 238 | WIPE: begin 239 | if (addr == ADDR'(START_ADDR + TOTAL_SIZE)) begin 240 | work_counter <= 0; 241 | addr <= START_ADDR; 242 | state <= WRITE_BLOCK; 243 | end else begin 244 | if (work_counter == 0) begin 245 | if (!refresh_needed) begin 246 | wr <= 1'b1; 247 | din <= 0; 248 | refresh_cycle <= 0; 249 | end else begin 250 | refresh <= 1'b1; 251 | refresh_executed <= 1'b1; 252 | refresh_cycle <= 1'b1; 253 | refresh_count <= refresh_count + 1; 254 | refresh_addr <= addr; 255 | end 256 | end else if (!wr && !refresh && !busy) begin 257 | work_counter <= 0; 258 | if (!refresh_cycle) 259 | addr <= addr + 1; 260 | end 261 | end 262 | end 263 | 264 | WRITE_BLOCK: begin 265 | // write some data 266 | if (addr == ADDR'(START_ADDR + TOTAL_SIZE)) begin 267 | state <= VERIFY_BLOCK; 268 | work_counter <= 0; 269 | addr <= START_ADDR; 270 | end else begin 271 | if (work_counter == 0) begin 272 | if (!refresh_needed) begin 273 | wr <= 1'b1; 274 | din <= addr[15:0] ^ {6'b0, addr[25:16]} ^ 16'd59; 275 | refresh_cycle <= 0; 276 | end else begin 277 | refresh <= 1'b1; 278 | refresh_executed <= 1'b1; 279 | refresh_cycle <= 1'b1; 280 | refresh_count <= refresh_count + 1; 281 | refresh_addr <= addr; 282 | end 283 | end else if (!wr && !refresh && !busy) begin 284 | work_counter <= 0; 285 | if (!refresh_cycle) 286 | addr <= addr + 1; 287 | end 288 | end 289 | end 290 | 291 | VERIFY_BLOCK: begin 292 | if (addr == ADDR'(START_ADDR + TOTAL_SIZE)) begin 293 | end_state <= state; 294 | state <= FINISH; 295 | end else begin 296 | if (work_counter == 0) begin 297 | // send next read request or refresh 298 | if (!refresh_needed) begin 299 | rd <= 1'b1; 300 | refresh_cycle <= 1'b0; 301 | end else begin 302 | refresh <= 1'b1; 303 | refresh_executed <= 1'b1; 304 | refresh_cycle <= 1'b1; 305 | refresh_count <= refresh_count + 1; 306 | refresh_addr <= addr; 307 | end 308 | end else if (data_ready) begin 309 | // verify result 310 | expected <= addr[15:0] ^ {6'b0, addr[25:16]} ^ 16'd59; 311 | actual <= dout; 312 | actual128 <= dout128; 313 | if (dout[7:0] != BYTE'(addr ^ {6'b0, addr[25:16]} ^ 16'd59)) begin // only test lower byte 314 | error_bit <= 1'b1; 315 | end_state <= state; 316 | state <= FINISH; 317 | end 318 | end else if (!rd && !refresh && !busy) begin 319 | work_counter <= 0; // start next read 320 | if (!refresh_cycle) begin 321 | addr <= addr + 1; 322 | end 323 | end 324 | end 325 | end 326 | 327 | 328 | 329 | 330 | endcase 331 | 332 | if (~sys_resetn) begin 333 | error_bit <= 1'b0; 334 | tick <= 1'b0; 335 | tick_counter <= 20'd100_000; // wait 1ms for everything to initialize 336 | latency_write1 <= 0; latency_write2 <= 0; latency_read <= 0; 337 | refresh_count <= 0; 338 | state <= INIT; 339 | end 340 | end 341 | 342 | 343 | `include "print.v" 344 | defparam tx.uart_freq=115200; 345 | defparam tx.clk_freq=FREQ; 346 | assign print_clk = clk; 347 | assign txp = uart_txp; 348 | 349 | reg[3:0] state_0; 350 | reg[3:0] state_1; 351 | reg[3:0] state_old; 352 | wire[3:0] state_new = state_1; 353 | 354 | reg [7:0] print_counters = 0, print_counters_p; 355 | reg [7:0] print_stat = 0, print_stat_p; 356 | 357 | typedef logic [3:0] NIB; 358 | 359 | always@(posedge clk)begin 360 | state_1<=state_0; 361 | state_0<=state; 362 | 363 | if(state_0==state_1) begin //stable value 364 | state_old<=state_new; 365 | 366 | if(state_old!=state_new)begin//state changes 367 | if(state_new==INIT)`print("Initializing SDRAM\n",STR); 368 | 369 | if (state_new==PRINT_STATUS) begin 370 | if (write_level_done && read_calib_done) 371 | `print("Write leveling and read calib successful. \n\n{WSTEP[7:0], rclkpos[3:0], rclksel[3:0]}=", STR); 372 | else 373 | `print("Write leveling or read calibration failed. \n\n{WSTEP[7:0], rclkpos[3:0], rclksel[3:0]}=", STR); 374 | end 375 | 376 | if(state_new==WRITE1) 377 | `print({wstep, NIB'(rclkpos), NIB'(rclksel)}, 2); 378 | 379 | if (state_new==WRITE2) `print("\n\n1 - Single write/read tests:\n", STR); 380 | 381 | if(state_new==FINISH) begin 382 | if(error_bit) 383 | `print("\n\n2 - Bulk write/read tests: ERROR. See below for actual dout.\n",STR); 384 | else 385 | `print("\n\n2 - Bulk write/read tests: SUCCESS.\n",STR); 386 | print_stat <= 1; 387 | end 388 | end 389 | end 390 | 391 | if (result_to_print) print_counters <= 1'b1; // trigger result printing 392 | 393 | print_counters_p <= print_counters; 394 | if (print_counters != 0 && print_counters == print_counters_p && print_state == PRINT_IDLE_STATE) begin 395 | case (print_counters) 396 | 8'd1: `print("\n", STR); 397 | 8'd2: `print(addr_read[15:0], 2); 398 | 8'd3: `print("=", STR); 399 | 8'd4: `print(actual, 2); 400 | // 8'd4: `print(actual128[127:0], 16); // print everything for debug 401 | endcase 402 | print_counters <= print_counters == 8'd255 ? 0 : print_counters + 1; 403 | end 404 | 405 | print_stat_p <= print_stat; 406 | if (print_stat != 0 && print_stat == print_stat_p && print_state == PRINT_IDLE_STATE) begin 407 | case (print_stat) 408 | 8'd1: `print("\nFinal address=", STR); 409 | 8'd2: `print({6'b0, addr[25:0]}, 4); 410 | 8'd3: `print("\nError=", STR); 411 | 8'd4: `print({7'b0, error_bit}, 1); 412 | 8'd5: `print("\nExpected=", STR); 413 | 8'd6: `print(expected[15:0], 2); 414 | 8'd7: `print("\nActual=", STR); 415 | 8'd8: `print(actual[15:0], 2); 416 | // 8'd10: `print(actual128, 16); 417 | // 8'd17: `print("\nRefresh counts=", STR); 418 | // 8'd18: `print(refresh_count, 3); 419 | // 8'd19: `print("\nLast refresh address=", STR); 420 | // 8'd20: `print(refresh_addr[23:0], 3); 421 | 8'd255: `print("\n\n", STR); 422 | endcase 423 | print_stat <= print_stat == 8'd255 ? 0 : print_stat + 1; 424 | end 425 | end 426 | 427 | 428 | endmodule 429 | 430 | -------------------------------------------------------------------------------- /src/gowin_rpll/gowin_rpll.ipc: -------------------------------------------------------------------------------- 1 | [General] 2 | ipc_version=4 3 | file=gowin_rpll 4 | module=Gowin_rPLL 5 | target_device=gw2a18c-011 6 | type=clock_rpll 7 | version=1.0 8 | 9 | [Config] 10 | CKLOUTD3=false 11 | CLKFB_SOURCE=0 12 | CLKIN_FREQ=27 13 | CLKOUTD=true 14 | CLKOUTP=false 15 | CLKOUT_BYPASS=false 16 | CLKOUT_DIVIDE_DYN=true 17 | CLKOUT_FREQ=200 18 | CLKOUT_TOLERANCE=3 19 | DYNAMIC=false 20 | LANG=0 21 | LOCK_EN=true 22 | MODE_GENERAL=true 23 | PLL_PWD=false 24 | RESET_PLL=false 25 | CLKOUTD_BYPASS=false 26 | CLKOUTD_FREQ=100 27 | CLKOUTD_SOURCE_CLKOUT=true 28 | CLKOUTD_TOLERANCE=3 29 | -------------------------------------------------------------------------------- /src/gowin_rpll/gowin_rpll.mod: -------------------------------------------------------------------------------- 1 | -series GW2A 2 | -device GW2A-18C 3 | -package PBGA256 4 | -part_number GW2A-LV18PG256C8/I7 5 | 6 | 7 | -mod_name Gowin_rPLL 8 | -file_name gowin_rpll 9 | -path D:/Gowin/dev/tang-primer-20k/09.ddr3/src/gowin_rpll/ 10 | -type PLL 11 | -rPll true 12 | -file_type vlg 13 | -dev_type GW2A-18C 14 | -dyn_idiv_sel false 15 | -idiv_sel 5 16 | -dyn_fbdiv_sel false 17 | -fbdiv_sel 37 18 | -dyn_odiv_sel false 19 | -odiv_sel 4 20 | -dyn_sdiv_sel 2 21 | -dyn_da_en false 22 | -rst_sig false 23 | -rst_sig_p false 24 | -fclkin 27 25 | -clkfb_sel 0 26 | -en_lock true 27 | -clkout_bypass false 28 | -en_clkoutp false 29 | -clkoutp_bypass false 30 | -en_clkoutd true 31 | -clkoutd_bypass false 32 | -clkoutd_src CLKOUT 33 | -en_clkoutd3 false -------------------------------------------------------------------------------- /src/gowin_rpll/gowin_rpll.v: -------------------------------------------------------------------------------- 1 | //Copyright (C)2014-2022 Gowin Semiconductor Corporation. 2 | //All rights reserved. 3 | //File Title: IP file 4 | //GOWIN Version: V1.9.8.07 5 | //Part Number: GW2A-LV18PG256C8/I7 6 | //Device: GW2A-18C 7 | //Created Time: Sat Sep 17 22:58:08 2022 8 | 9 | module Gowin_rPLL (clkout, clkoutp, lock, clkoutd, clkin); 10 | 11 | output clkout; 12 | output clkoutp; 13 | output lock; 14 | output clkoutd; 15 | input clkin; 16 | 17 | wire clkoutd3_o; 18 | wire gw_gnd; 19 | 20 | assign gw_gnd = 1'b0; 21 | 22 | rPLL rpll_inst ( 23 | .CLKOUT(clkout), 24 | .LOCK(lock), 25 | .CLKOUTP(clkoutp), 26 | .CLKOUTD(clkoutd), 27 | .CLKOUTD3(clkoutd3_o), 28 | .RESET(gw_gnd), 29 | .RESET_P(gw_gnd), 30 | .CLKIN(clkin), 31 | .CLKFB(gw_gnd), 32 | .FBDSEL({gw_gnd,gw_gnd,gw_gnd,gw_gnd,gw_gnd,gw_gnd}), 33 | .IDSEL({gw_gnd,gw_gnd,gw_gnd,gw_gnd,gw_gnd,gw_gnd}), 34 | .ODSEL({gw_gnd,gw_gnd,gw_gnd,gw_gnd,gw_gnd,gw_gnd}), 35 | .PSDA({gw_gnd,gw_gnd,gw_gnd,gw_gnd}), 36 | .DUTYDA({gw_gnd,gw_gnd,gw_gnd,gw_gnd}), 37 | .FDLY({gw_gnd,gw_gnd,gw_gnd,gw_gnd}) 38 | ); 39 | 40 | // clkout @ 499.5 Mhz 41 | //defparam rpll_inst.FBDIV_SEL = 36; 42 | //defparam rpll_inst.IDIV_SEL = 1; 43 | //defparam rpll_inst.ODIV_SEL = 2; 44 | 45 | // clkout @ 398.25 Mhz 46 | defparam rpll_inst.FBDIV_SEL = 58; 47 | defparam rpll_inst.IDIV_SEL = 3; 48 | defparam rpll_inst.ODIV_SEL = 2; 49 | 50 | // clkoutd @ 1/4 * clkout 51 | defparam rpll_inst.DYN_SDIV_SEL = 4; 52 | 53 | defparam rpll_inst.FCLKIN = "27"; 54 | defparam rpll_inst.DYN_IDIV_SEL = "false"; 55 | defparam rpll_inst.DYN_FBDIV_SEL = "false"; 56 | defparam rpll_inst.DYN_ODIV_SEL = "false"; 57 | defparam rpll_inst.PSDA_SEL = "0100"; 58 | defparam rpll_inst.DYN_DA_EN = "false"; 59 | defparam rpll_inst.DUTYDA_SEL = "1000"; 60 | defparam rpll_inst.CLKOUT_FT_DIR = 1'b1; 61 | defparam rpll_inst.CLKOUTP_FT_DIR = 1'b1; 62 | defparam rpll_inst.CLKOUT_DLY_STEP = 0; 63 | defparam rpll_inst.CLKOUTP_DLY_STEP = 0; 64 | defparam rpll_inst.CLKFB_SEL = "internal"; 65 | defparam rpll_inst.CLKOUT_BYPASS = "false"; 66 | defparam rpll_inst.CLKOUTP_BYPASS = "false"; 67 | defparam rpll_inst.CLKOUTD_BYPASS = "false"; 68 | defparam rpll_inst.CLKOUTD_SRC = "CLKOUT"; 69 | defparam rpll_inst.CLKOUTD3_SRC = "CLKOUT"; 70 | defparam rpll_inst.DEVICE = "GW2A-18C"; 71 | 72 | endmodule //Gowin_rPLL 73 | -------------------------------------------------------------------------------- /src/gowin_rpll/gowin_rpll_tmp.v: -------------------------------------------------------------------------------- 1 | //Copyright (C)2014-2022 Gowin Semiconductor Corporation. 2 | //All rights reserved. 3 | //File Title: Template file for instantiation 4 | //GOWIN Version: V1.9.8.07 5 | //Part Number: GW2A-LV18PG256C8/I7 6 | //Device: GW2A-18C 7 | //Created Time: Sat Sep 17 22:58:08 2022 8 | 9 | //Change the instance name and port connections to the signal names 10 | //--------Copy here to design-------- 11 | 12 | Gowin_rPLL your_instance_name( 13 | .clkout(clkout_o), //output clkout 14 | .lock(lock_o), //output lock 15 | .clkoutd(clkoutd_o), //output clkoutd 16 | .clkin(clkin_i) //input clkin 17 | ); 18 | 19 | //--------Copy end------------------- 20 | -------------------------------------------------------------------------------- /src/print.v: -------------------------------------------------------------------------------- 1 | parameter STR = 0; 2 | parameter HEX = 1; 3 | 4 | wire print_clk; 5 | 6 | reg[7:0] print_seq[255:0]; 7 | reg[7:0] seq_head=8'd0; 8 | reg[7:0] seq_tail=8'd0; 9 | 10 | reg[1023:0] print_buffer=1024'h0; 11 | reg[6:0] print_buffer_pointer = 7'd0; 12 | 13 | reg last_spin_state=0; 14 | reg spin_state=0; 15 | reg[6:0] print_length; 16 | reg print_type; 17 | 18 | parameter PRINT_IDLE_STATE = 0; 19 | parameter PRINT_WAIT_STATE = 1; 20 | parameter PRINT_WORK_STATE = 2; 21 | parameter PRINT_CONV_STATE = 3; 22 | reg[1:0] print_state=PRINT_IDLE_STATE; 23 | 24 | wire[7:0] hex_lib[15:0]; 25 | assign hex_lib[4'h0] = 8'h30; 26 | assign hex_lib[4'h1] = 8'h31; 27 | assign hex_lib[4'h2] = 8'h32; 28 | assign hex_lib[4'h3] = 8'h33; 29 | assign hex_lib[4'h4] = 8'h34; 30 | assign hex_lib[4'h5] = 8'h35; 31 | assign hex_lib[4'h6] = 8'h36; 32 | assign hex_lib[4'h7] = 8'h37; 33 | assign hex_lib[4'h8] = 8'h38; 34 | assign hex_lib[4'h9] = 8'h39; 35 | assign hex_lib[4'hA] = 8'h61; 36 | assign hex_lib[4'hB] = 8'h62; 37 | assign hex_lib[4'hC] = 8'h63; 38 | assign hex_lib[4'hD] = 8'h64; 39 | assign hex_lib[4'hE] = 8'h65; 40 | assign hex_lib[4'hF] = 8'h66; 41 | 42 | //always block to handle the print task 43 | always@(posedge print_clk)begin 44 | last_spin_state<=spin_state; 45 | 46 | case(print_state) 47 | PRINT_IDLE_STATE:begin//IDLE, check if spin_state is changed 48 | if(spin_state!=last_spin_state)begin 49 | print_state<=PRINT_WAIT_STATE; 50 | end 51 | end 52 | PRINT_WAIT_STATE:begin//WAIT, wait 1 clk then start to fill print_seq 53 | print_state<=PRINT_WORK_STATE; 54 | if(print_type==STR) 55 | print_buffer_pointer<=7'd127; 56 | else 57 | print_buffer_pointer<=7'd127; 58 | end 59 | PRINT_WORK_STATE:begin//WORK, fill print_seq 60 | if(print_type==STR)begin//type is string, fill as it is 61 | if(print_buffer[ 62 | print_buffer_pointer*8+7 -: 8 63 | ]!=8'd0)begin 64 | print_seq[seq_tail]<=print_buffer[ 65 | print_buffer_pointer*8+7 -: 8 66 | ]; 67 | seq_tail<=seq_tail+8'd1; 68 | end else begin 69 | print_state<=PRINT_IDLE_STATE; 70 | end 71 | 72 | print_buffer_pointer<=print_buffer_pointer-7'd1; 73 | 74 | if(print_buffer_pointer==7'd0)begin 75 | print_state<=PRINT_IDLE_STATE; 76 | end 77 | end else begin //type is data, fill as hex 78 | print_seq[seq_tail]<=hex_lib[print_buffer[ 79 | print_buffer_pointer*8+7 -: 4 80 | ]]; 81 | seq_tail<=seq_tail+8'd1; 82 | 83 | //another convert clock cycle is needed 84 | print_state<=PRINT_CONV_STATE; 85 | end 86 | end 87 | PRINT_CONV_STATE:begin//CONV, convert data to hex 88 | print_seq[seq_tail]<=hex_lib[print_buffer[ 89 | print_buffer_pointer*8+3 -: 4 90 | ]]; 91 | seq_tail<=seq_tail+8'd1; 92 | print_state<=PRINT_WORK_STATE; 93 | 94 | print_buffer_pointer<=print_buffer_pointer-7'd1; 95 | 96 | if(print_buffer_pointer==print_length) 97 | print_state<=PRINT_IDLE_STATE; 98 | end 99 | endcase 100 | end 101 | 102 | reg uart_en; 103 | wire uart_bz; 104 | wire uart_txp; 105 | uart_tx_V2 tx(print_clk, print_seq[seq_head], uart_en, uart_bz, uart_txp); 106 | 107 | //always block to send the data via UART 108 | always@(posedge print_clk)begin 109 | uart_en<=1'b0; 110 | if(uart_en && uart_bz) 111 | seq_head<=seq_head+8'd1; 112 | if(seq_head!=seq_tail && !uart_bz) 113 | uart_en<=1'b1; 114 | end 115 | 116 | task int_print( 117 | input[1023:0] strin,//max 128 characters 118 | input[7:0] type_length //8bit width to show 128 characters 119 | ); 120 | begin 121 | if(print_state==PRINT_IDLE_STATE)begin//print when busy will be ignored 122 | spin_state<=~spin_state; 123 | 124 | if(type_length==STR)begin 125 | print_type<=STR; 126 | end else begin 127 | print_type<=HEX; 128 | print_length<=8'd128-type_length; 129 | end 130 | 131 | print_buffer<=strin; 132 | end 133 | end 134 | 135 | `define print(a,b) int_print({>>{a}},b) 136 | endtask 137 | -------------------------------------------------------------------------------- /src/tang20k.cst: -------------------------------------------------------------------------------- 1 | IO_LOC "sys_clk" H11; 2 | IO_PORT "sys_clk" IO_TYPE=LVCMOS33 PULL_MODE=UP; 3 | 4 | IO_LOC "sys_resetn" T2; 5 | IO_PORT "sys_resetn" PULL_MODE=NONE; 6 | 7 | IO_LOC "d7" D7; 8 | IO_PORT "d7" PULL_MODE=NONE IO_TYPE=LVCMOS15; 9 | 10 | // DDR pins 11 | IO_LOC "DDR3_BA[2]" H5; 12 | IO_PORT "DDR3_BA[2]" IO_TYPE=SSTL15 PULL_MODE=NONE DRIVE=8 BANK_VCCIO=1.5; 13 | IO_LOC "DDR3_BA[1]" D3; 14 | IO_PORT "DDR3_BA[1]" IO_TYPE=SSTL15 PULL_MODE=NONE DRIVE=8 BANK_VCCIO=1.5; 15 | IO_LOC "DDR3_BA[0]" H4; 16 | IO_PORT "DDR3_BA[0]" IO_TYPE=SSTL15 PULL_MODE=NONE DRIVE=8 BANK_VCCIO=1.5; 17 | IO_LOC "DDR3_A[13]" C8; 18 | IO_PORT "DDR3_A[13]" IO_TYPE=SSTL15 PULL_MODE=NONE DRIVE=8 BANK_VCCIO=1.5; 19 | IO_LOC "DDR3_A[12]" A3; 20 | IO_PORT "DDR3_A[12]" IO_TYPE=SSTL15 PULL_MODE=NONE DRIVE=8 BANK_VCCIO=1.5; 21 | IO_LOC "DDR3_A[11]" B7; 22 | IO_PORT "DDR3_A[11]" IO_TYPE=SSTL15 PULL_MODE=NONE DRIVE=8 BANK_VCCIO=1.5; 23 | IO_LOC "DDR3_A[10]" K3; 24 | IO_PORT "DDR3_A[10]" IO_TYPE=SSTL15 PULL_MODE=NONE DRIVE=8 BANK_VCCIO=1.5; 25 | IO_LOC "DDR3_A[9]" F9; 26 | IO_PORT "DDR3_A[9]" IO_TYPE=SSTL15 PULL_MODE=NONE DRIVE=8 BANK_VCCIO=1.5; 27 | IO_LOC "DDR3_A[8]" A5; 28 | IO_PORT "DDR3_A[8]" IO_TYPE=SSTL15 PULL_MODE=NONE DRIVE=8 BANK_VCCIO=1.5; 29 | IO_LOC "DDR3_A[7]" D8; 30 | IO_PORT "DDR3_A[7]" IO_TYPE=SSTL15 PULL_MODE=NONE DRIVE=8 BANK_VCCIO=1.5; 31 | IO_LOC "DDR3_A[6]" B1; 32 | IO_PORT "DDR3_A[6]" IO_TYPE=SSTL15 PULL_MODE=NONE DRIVE=8 BANK_VCCIO=1.5; 33 | IO_LOC "DDR3_A[5]" E6; 34 | IO_PORT "DDR3_A[5]" IO_TYPE=SSTL15 PULL_MODE=NONE DRIVE=8 BANK_VCCIO=1.5; 35 | IO_LOC "DDR3_A[4]" C4; 36 | IO_PORT "DDR3_A[4]" IO_TYPE=SSTL15 PULL_MODE=NONE DRIVE=8 BANK_VCCIO=1.5; 37 | IO_LOC "DDR3_A[3]" F8; 38 | IO_PORT "DDR3_A[3]" IO_TYPE=SSTL15 PULL_MODE=NONE DRIVE=8 BANK_VCCIO=1.5; 39 | IO_LOC "DDR3_A[2]" D6; 40 | IO_PORT "DDR3_A[2]" IO_TYPE=SSTL15 PULL_MODE=NONE DRIVE=8 BANK_VCCIO=1.5; 41 | IO_LOC "DDR3_A[1]" A4; 42 | IO_PORT "DDR3_A[1]" IO_TYPE=SSTL15 PULL_MODE=NONE DRIVE=8 BANK_VCCIO=1.5; 43 | IO_LOC "DDR3_A[0]" F7; 44 | IO_PORT "DDR3_A[0]" IO_TYPE=SSTL15 PULL_MODE=NONE DRIVE=8 BANK_VCCIO=1.5; 45 | IO_LOC "DDR3_ODT" R3; 46 | IO_PORT "DDR3_ODT" IO_TYPE=SSTL15 PULL_MODE=NONE DRIVE=8 BANK_VCCIO=1.5; 47 | IO_LOC "DDR3_CKE" J2; 48 | IO_PORT "DDR3_CKE" IO_TYPE=SSTL15 PULL_MODE=NONE DRIVE=8 BANK_VCCIO=1.5; 49 | IO_LOC "DDR3_nWE" L2; 50 | IO_PORT "DDR3_nWE" IO_TYPE=SSTL15 PULL_MODE=NONE DRIVE=8 BANK_VCCIO=1.5; 51 | IO_LOC "DDR3_nCAS" R6; 52 | IO_PORT "DDR3_nCAS" IO_TYPE=SSTL15 PULL_MODE=NONE DRIVE=8 BANK_VCCIO=1.5; 53 | IO_LOC "DDR3_nRAS" R4; 54 | IO_PORT "DDR3_nRAS" IO_TYPE=SSTL15 PULL_MODE=NONE DRIVE=8 BANK_VCCIO=1.5; 55 | IO_LOC "DDR3_nRESET" B9; 56 | IO_PORT "DDR3_nRESET" IO_TYPE=SSTL15 PULL_MODE=NONE DRIVE=8 BANK_VCCIO=1.5; 57 | IO_LOC "DDR3_CK" J1,J3; 58 | IO_PORT "DDR3_CK" IO_TYPE=SSTL15D PULL_MODE=NONE DRIVE=8 BANK_VCCIO=1.5; 59 | IO_LOC "DDR3_DQ[15]" M2; 60 | IO_PORT "DDR3_DQ[15]" IO_TYPE=SSTL15 PULL_MODE=NONE DRIVE=8 VREF=INTERNAL BANK_VCCIO=1.5; 61 | IO_LOC "DDR3_DQ[14]" R1; 62 | IO_PORT "DDR3_DQ[14]" IO_TYPE=SSTL15 PULL_MODE=NONE DRIVE=8 VREF=INTERNAL BANK_VCCIO=1.5; 63 | IO_LOC "DDR3_DQ[13]" H3; 64 | IO_PORT "DDR3_DQ[13]" IO_TYPE=SSTL15 PULL_MODE=NONE DRIVE=8 VREF=INTERNAL BANK_VCCIO=1.5; 65 | IO_LOC "DDR3_DQ[12]" P4; 66 | IO_PORT "DDR3_DQ[12]" IO_TYPE=SSTL15 PULL_MODE=NONE DRIVE=8 VREF=INTERNAL BANK_VCCIO=1.5; 67 | IO_LOC "DDR3_DQ[11]" L1; 68 | IO_PORT "DDR3_DQ[11]" IO_TYPE=SSTL15 PULL_MODE=NONE DRIVE=8 VREF=INTERNAL BANK_VCCIO=1.5; 69 | IO_LOC "DDR3_DQ[10]" N2; 70 | IO_PORT "DDR3_DQ[10]" IO_TYPE=SSTL15 PULL_MODE=NONE DRIVE=8 VREF=INTERNAL BANK_VCCIO=1.5; 71 | IO_LOC "DDR3_DQ[9]" K4; 72 | IO_PORT "DDR3_DQ[9]" IO_TYPE=SSTL15 PULL_MODE=NONE DRIVE=8 VREF=INTERNAL BANK_VCCIO=1.5; 73 | IO_LOC "DDR3_DQ[8]" M3; 74 | IO_PORT "DDR3_DQ[8]" IO_TYPE=SSTL15 PULL_MODE=NONE DRIVE=8 VREF=INTERNAL BANK_VCCIO=1.5; 75 | IO_LOC "DDR3_DQ[7]" B3; 76 | IO_PORT "DDR3_DQ[7]" IO_TYPE=SSTL15 PULL_MODE=NONE DRIVE=8 VREF=INTERNAL BANK_VCCIO=1.5; 77 | IO_LOC "DDR3_DQ[6]" E1; 78 | IO_PORT "DDR3_DQ[6]" IO_TYPE=SSTL15 PULL_MODE=NONE DRIVE=8 VREF=INTERNAL BANK_VCCIO=1.5; 79 | IO_LOC "DDR3_DQ[5]" C1; 80 | IO_PORT "DDR3_DQ[5]" IO_TYPE=SSTL15 PULL_MODE=NONE DRIVE=8 VREF=INTERNAL BANK_VCCIO=1.5; 81 | IO_LOC "DDR3_DQ[4]" E2; 82 | IO_PORT "DDR3_DQ[4]" IO_TYPE=SSTL15 PULL_MODE=NONE DRIVE=8 VREF=INTERNAL BANK_VCCIO=1.5; 83 | IO_LOC "DDR3_DQ[3]" F3; 84 | IO_PORT "DDR3_DQ[3]" IO_TYPE=SSTL15 PULL_MODE=NONE DRIVE=8 VREF=INTERNAL BANK_VCCIO=1.5; 85 | IO_LOC "DDR3_DQ[2]" F4; 86 | IO_PORT "DDR3_DQ[2]" IO_TYPE=SSTL15 PULL_MODE=NONE DRIVE=8 VREF=INTERNAL BANK_VCCIO=1.5; 87 | IO_LOC "DDR3_DQ[1]" F5; 88 | IO_PORT "DDR3_DQ[1]" IO_TYPE=SSTL15 PULL_MODE=NONE DRIVE=8 VREF=INTERNAL BANK_VCCIO=1.5; 89 | IO_LOC "DDR3_DQ[0]" G5; 90 | IO_PORT "DDR3_DQ[0]" IO_TYPE=SSTL15 PULL_MODE=NONE DRIVE=8 VREF=INTERNAL BANK_VCCIO=1.5; 91 | IO_LOC "DDR3_DQS[1]" J5,K6; 92 | IO_PORT "DDR3_DQS[1]" IO_TYPE=SSTL15D PULL_MODE=NONE DRIVE=8 BANK_VCCIO=1.5; 93 | IO_LOC "DDR3_DQS[0]" G2,G3; 94 | IO_PORT "DDR3_DQS[0]" IO_TYPE=SSTL15D PULL_MODE=NONE DRIVE=8 BANK_VCCIO=1.5; 95 | IO_LOC "DDR3_DM[1]" K5; 96 | IO_PORT "DDR3_DM[1]" IO_TYPE=SSTL15 PULL_MODE=NONE DRIVE=8 BANK_VCCIO=1.5; 97 | IO_LOC "DDR3_DM[0]" G1; 98 | IO_PORT "DDR3_DM[0]" IO_TYPE=SSTL15 PULL_MODE=NONE DRIVE=8 BANK_VCCIO=1.5; 99 | 100 | // LED 101 | IO_LOC "led[7]" L16; 102 | IO_PORT "led[7]" IO_TYPE=LVCMOS33 PULL_MODE=UP DRIVE=8; 103 | IO_LOC "led[6]" N16; 104 | IO_PORT "led[6]" IO_TYPE=LVCMOS33 PULL_MODE=UP DRIVE=8; 105 | IO_LOC "led[5]" P16; 106 | IO_PORT "led[5]" IO_TYPE=LVCMOS33 PULL_MODE=UP DRIVE=8; 107 | IO_LOC "led[4]" R16; 108 | IO_PORT "led[4]" IO_TYPE=LVCMOS33 PULL_MODE=UP DRIVE=8; 109 | IO_LOC "led[3]" L14; 110 | IO_PORT "led[3]" IO_TYPE=LVCMOS33 PULL_MODE=UP DRIVE=8; 111 | IO_LOC "led[2]" N14; 112 | IO_PORT "led[2]" IO_TYPE=LVCMOS33 PULL_MODE=UP DRIVE=8; 113 | IO_LOC "led[1]" N15; 114 | IO_PORT "led[1]" IO_TYPE=LVCMOS33 PULL_MODE=UP DRIVE=8; 115 | IO_LOC "led[0]" P15; 116 | IO_PORT "led[0]" IO_TYPE=LVCMOS33 PULL_MODE=UP DRIVE=8; 117 | 118 | // Set 2, up 119 | IO_LOC "led2[7]" T9; 120 | IO_PORT "led2[7]" IO_TYPE=LVCMOS33 PULL_MODE=UP DRIVE=8; 121 | IO_LOC "led2[6]" T8; 122 | IO_PORT "led2[6]" IO_TYPE=LVCMOS33 PULL_MODE=UP DRIVE=8; 123 | IO_LOC "led2[5]" T7; 124 | IO_PORT "led2[5]" IO_TYPE=LVCMOS33 PULL_MODE=UP DRIVE=8; 125 | IO_LOC "led2[4]" T6; 126 | IO_PORT "led2[4]" IO_TYPE=LVCMOS33 PULL_MODE=UP DRIVE=8; 127 | IO_LOC "led2[3]" P9; 128 | IO_PORT "led2[3]" IO_TYPE=LVCMOS33 PULL_MODE=UP DRIVE=8; 129 | IO_LOC "led2[2]" P8; // Schematics says M6. It should be P8. 130 | IO_PORT "led2[2]" IO_TYPE=LVCMOS33 PULL_MODE=UP DRIVE=8; 131 | IO_LOC "led2[1]" R8; 132 | IO_PORT "led2[1]" IO_TYPE=LVCMOS33 PULL_MODE=UP DRIVE=8; 133 | IO_LOC "led2[0]" P6; 134 | IO_PORT "led2[0]" IO_TYPE=LVCMOS33 PULL_MODE=UP DRIVE=8; 135 | 136 | // UART 137 | IO_LOC "uart_txp" M11; 138 | IO_PORT "uart_txp" IO_TYPE=LVCMOS33 PULL_MODE=UP DRIVE=8; 139 | 140 | // Fix location of PLL as it impacts write/read leveling timing 141 | INS_LOC "pll/rpll_inst" PLL_L[0]; 142 | -------------------------------------------------------------------------------- /src/uart_tx_V2.v: -------------------------------------------------------------------------------- 1 | module uart_tx_V2( 2 | input wire clk, 3 | input wire [7:0] din, 4 | input wire wr_en, 5 | output wire tx_busy, 6 | 7 | output reg tx_p 8 | ); 9 | 10 | initial begin 11 | tx_p = 1'b1; 12 | end 13 | 14 | parameter clk_freq = 27000000; 15 | parameter uart_freq = 115200; 16 | 17 | localparam STATE_IDLE = 2'b00; 18 | localparam STATE_START = 2'b01; 19 | localparam STATE_DATA = 2'b10; 20 | localparam STATE_STOP = 2'b11; 21 | 22 | reg[7:0] localdin; 23 | reg localwr_en; 24 | 25 | //always@(posedge clk)begin 26 | always@(*)begin 27 | localdin<=din; 28 | localwr_en<=wr_en; 29 | end 30 | 31 | reg [7:0] data= 8'h00; 32 | reg [2:0] bitpos= 3'h0; 33 | reg [1:0] state= STATE_IDLE; 34 | 35 | wire tx_clk; 36 | 37 | localparam TX_CLK_MAX = (clk_freq / uart_freq)-1; 38 | 39 | reg[$clog2(TX_CLK_MAX+1)+1:0] tx_clkcnt; 40 | 41 | assign tx_clk = (tx_clkcnt == 0); 42 | 43 | initial tx_clkcnt=0; 44 | 45 | always @(posedge clk) begin 46 | if (tx_clkcnt >= TX_CLK_MAX) 47 | tx_clkcnt <= 0; 48 | else 49 | tx_clkcnt <= tx_clkcnt + 1; 50 | end 51 | 52 | 53 | always @(posedge clk) begin 54 | case (state) 55 | STATE_IDLE: begin 56 | if (localwr_en) begin 57 | state <= STATE_START; 58 | data <= localdin; 59 | bitpos <= 3'h0; 60 | end 61 | end 62 | STATE_START: begin 63 | if (tx_clk) begin 64 | tx_p <= 1'b0; 65 | state <= STATE_DATA; 66 | end 67 | end 68 | STATE_DATA: begin 69 | if (tx_clk) begin 70 | if (bitpos == 3'h7) 71 | state <= STATE_STOP; 72 | else 73 | bitpos <= bitpos + 3'h1; 74 | tx_p <= data[bitpos]; 75 | end 76 | end 77 | STATE_STOP: begin 78 | if (tx_clk) begin 79 | tx_p <= 1'b1; 80 | state <= STATE_IDLE; 81 | end 82 | end 83 | default: begin 84 | tx_p <= 1'b1; 85 | state <= STATE_IDLE; 86 | end 87 | endcase 88 | end 89 | 90 | assign tx_busy = (state != STATE_IDLE); 91 | 92 | endmodule 93 | --------------------------------------------------------------------------------