├── 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 | FPGA
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 |
--------------------------------------------------------------------------------