Skip to content

Commit 94beacc

Browse files
committed
Rename sdram_ctrl to sdram_gw2ar and add example
Rename the module and all associated files to sdram_gw2ar to encode the target product (GW2AR embedded SDRAM in the Tang Nano 20K). Add sdram_gw2ar_example.v demonstrating a write-then-read-back pattern using a 6-state FSM, with LED outputs reporting pass/fail. Made-with: Cursor
1 parent 15634f7 commit 94beacc

File tree

7 files changed

+208
-39
lines changed

7 files changed

+208
-39
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ NyanSoC/
2727
│ │ ├── uart_tx.v # UART transmitter
2828
│ │ └── uart_rx.v # UART receiver
2929
│ └── gowin/
30-
│ └── sdram_ctrl.v # SDRAM controller
30+
│ └── sdram_gw2ar.v # SDRAM controller for GW2AR embedded SDRAM
3131
├── boards/
3232
│ └── tangnano20k/ # Tang Nano 20K top-level + P&R scripts (only supported board)
3333
├── firmware/

rtl/gowin/.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
*_prove
22
*_cover
3-
sdram_ctrl/*
3+
sdram_gw2ar/*

rtl/gowin/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
.PHONY: prove cover
22
prove:
3-
sby -f sdram_ctrl.sby prove
3+
sby -f sdram_gw2ar.sby prove
44

55
cover:
6-
sby -f sdram_ctrl.sby cover
6+
sby -f sdram_gw2ar.sby cover

rtl/gowin/sdram_ctrl.sby

Lines changed: 0 additions & 33 deletions
This file was deleted.

rtl/gowin/sdram_gw2ar.sby

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
[tasks]
2+
cover
3+
prove
4+
5+
[options]
6+
prove: mode prove
7+
cover: mode cover
8+
prove: depth 50
9+
cover: depth 80
10+
11+
[engines]
12+
smtbmc z3
13+
14+
[script]
15+
read -formal sdram_gw2ar.v
16+
# Scale down all timing so the full init+read+write sequence fits in <80 cycles:
17+
# INIT_CYCLES = (2000 * 1) / 1000 = 2
18+
# T_RP=T_RFC=T_MRD=T_RCD=T_CL=T_WR = 2
19+
# REFRESH_INTERVAL = (4096 / 1 * 1) / 1000 = 4 (so refresh fires every 4 cycles)
20+
chparam -set CLOCK_FREQ_MHZ 1 sdram_gw2ar
21+
chparam -set INITIALIZATION_WAIT_PERIOD_NS 2000 sdram_gw2ar
22+
chparam -set REFRESH_PERIOD_NS 4096 sdram_gw2ar
23+
chparam -set REFRESH_TIMES 1 sdram_gw2ar
24+
chparam -set T_RP_PERIOD 2 sdram_gw2ar
25+
chparam -set T_RFC_PERIOD 2 sdram_gw2ar
26+
chparam -set T_MRD_PERIOD 2 sdram_gw2ar
27+
chparam -set T_RCD_PERIOD 2 sdram_gw2ar
28+
chparam -set T_CL_PERIOD 2 sdram_gw2ar
29+
chparam -set T_WR_PERIOD 2 sdram_gw2ar
30+
prep -top sdram_gw2ar
31+
32+
[files]
33+
./sdram_gw2ar.v
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
// [ROW_WIDTH+COLUMN_WIDTH-1 : COLUMN_WIDTH] = row
1111
// [COLUMN_WIDTH-1 : 0] = column
1212

13-
module sdram_ctrl #(
13+
module sdram_gw2ar #(
1414
parameter integer DATA_WIDTH = 32, // {8,16,32,64}
1515
parameter integer BANK_WIDTH = 2, // {1,2}
1616
parameter integer ROW_WIDTH = 11, // {11,12,13,14}
@@ -473,4 +473,4 @@ module sdram_ctrl #(
473473

474474
`endif // FORMAL
475475

476-
endmodule // sdram_ctrl
476+
endmodule // sdram_gw2ar

rtl/gowin/sdram_gw2ar_example.v

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
`default_nettype none
2+
`timescale 1 ns / 1 ps
3+
4+
// Example usage of sdram_gw2ar.
5+
//
6+
// After initialization completes the module writes the 32-bit word 0xDEADBEEF
7+
// to SDRAM address 0, then reads it back. Two LEDs report the outcome:
8+
// o_led_ok – pulses high when the readback value matches the written word
9+
// o_led_err – pulses high when the readback value does not match
10+
//
11+
// Wiring for Tang Nano 20K (27 MHz oscillator, GW2AR-18 embedded SDRAM):
12+
// i_clk <- 27 MHz system clock (same clock fed to SDRAM)
13+
// i_rst_n <- active-low reset (e.g. button_n)
14+
// o_sdram_* <- connect directly to the GW2AR embedded SDRAM pins
15+
// io_sdram_dq<- bidirectional data bus
16+
17+
module sdram_gw2ar_example (
18+
input wire i_clk,
19+
input wire i_rst_n,
20+
21+
// Status LEDs (active-high)
22+
output reg o_led_ok,
23+
output reg o_led_err,
24+
25+
// SDRAM physical interface (pass through from sdram_gw2ar)
26+
output wire o_sdram_clk,
27+
output wire o_sdram_cke,
28+
output wire o_sdram_cs_n,
29+
output wire o_sdram_cas_n,
30+
output wire o_sdram_ras_n,
31+
output wire o_sdram_wen_n,
32+
output wire [ 3:0] o_sdram_dqm,
33+
output wire [10:0] o_sdram_addr,
34+
output wire [ 1:0] o_sdram_ba,
35+
inout wire [31:0] io_sdram_dq
36+
);
37+
38+
// ── Controller user-side wires ─────────────────────────────────────────────
39+
reg sdrc_wr_n;
40+
reg sdrc_rd_n;
41+
reg [20:0] sdrc_addr;
42+
reg [31:0] sdrc_data_in;
43+
wire [31:0] sdrc_data_out;
44+
wire sdrc_init_done;
45+
wire sdrc_busy_n;
46+
wire sdrc_rd_valid;
47+
wire sdrc_wrd_ack;
48+
49+
// ── sdram_gw2ar instance ───────────────────────────────────────────────────
50+
// Tang Nano 20K: 27 MHz, GW2AR-18 embedded SDRAM (64 Mbit, 32-bit wide).
51+
// Timing parameters follow the JEDEC SDR SDRAM spec for -6 speed grade.
52+
sdram_gw2ar #(
53+
.DATA_WIDTH (32),
54+
.BANK_WIDTH (2),
55+
.ROW_WIDTH (11),
56+
.COLUMN_WIDTH (8),
57+
.CLOCK_FREQ_MHZ (27),
58+
.REFRESH_PERIOD_NS (64_000_000),
59+
.REFRESH_TIMES (4096),
60+
.INITIALIZATION_WAIT_PERIOD_NS(200_000),
61+
.T_CL_PERIOD (3),
62+
.T_RP_PERIOD (3),
63+
.T_MRD_PERIOD (3),
64+
.T_WR_PERIOD (3),
65+
.T_RFC_PERIOD (9),
66+
.T_RCD_PERIOD (3)
67+
) u_sdram (
68+
.i_sdrc_rst_n (i_rst_n),
69+
.i_sdrc_clk (i_clk),
70+
.i_sdram_clk (i_clk),
71+
.i_sdrc_self_refresh(1'b0),
72+
.i_sdrc_power_down (1'b0),
73+
.i_sdrc_wr_n (sdrc_wr_n),
74+
.i_sdrc_rd_n (sdrc_rd_n),
75+
.i_sdrc_addr (sdrc_addr),
76+
.i_sdrc_dqm (4'b0000),
77+
.i_sdrc_data_len (8'd0),
78+
.i_sdrc_data (sdrc_data_in),
79+
.o_sdrc_data (sdrc_data_out),
80+
.o_sdrc_init_done (sdrc_init_done),
81+
.o_sdrc_busy_n (sdrc_busy_n),
82+
.o_sdrc_rd_valid (sdrc_rd_valid),
83+
.o_sdrc_wrd_ack (sdrc_wrd_ack),
84+
85+
.o_sdram_clk (o_sdram_clk),
86+
.o_sdram_cke (o_sdram_cke),
87+
.o_sdram_cs_n (o_sdram_cs_n),
88+
.o_sdram_cas_n(o_sdram_cas_n),
89+
.o_sdram_ras_n(o_sdram_ras_n),
90+
.o_sdram_wen_n(o_sdram_wen_n),
91+
.o_sdram_dqm (o_sdram_dqm),
92+
.o_sdram_addr (o_sdram_addr),
93+
.o_sdram_ba (o_sdram_ba),
94+
.io_sdram_dq (io_sdram_dq)
95+
);
96+
97+
// ── Simple write-then-read-back FSM ───────────────────────────────────────
98+
localparam [2:0]
99+
S_WAIT_INIT = 3'd0, // wait for controller initialisation to finish
100+
S_WRITE = 3'd1, // issue a single-word write
101+
S_WAIT_ACK = 3'd2, // wait for write acknowledgement
102+
S_READ = 3'd3, // issue a single-word read
103+
S_WAIT_DATA = 3'd4, // wait for read data to be valid
104+
S_DONE = 3'd5; // latch result, stay here
105+
106+
localparam [31:0] TEST_WORD = 32'hDEAD_BEEF;
107+
localparam [20:0] TEST_ADDRESS = 21'd0;
108+
109+
reg [2:0] state;
110+
111+
always @(posedge i_clk) begin
112+
if (!i_rst_n) begin
113+
state <= S_WAIT_INIT;
114+
sdrc_wr_n <= 1'b1;
115+
sdrc_rd_n <= 1'b1;
116+
sdrc_addr <= 21'd0;
117+
sdrc_data_in <= 32'd0;
118+
o_led_ok <= 1'b0;
119+
o_led_err <= 1'b0;
120+
end else begin
121+
// Default: deassert strobes every cycle so they are single-cycle pulses.
122+
sdrc_wr_n <= 1'b1;
123+
sdrc_rd_n <= 1'b1;
124+
125+
case (state)
126+
127+
S_WAIT_INIT: begin
128+
if (sdrc_init_done && sdrc_busy_n)
129+
state <= S_WRITE;
130+
end
131+
132+
S_WRITE: begin
133+
sdrc_wr_n <= 1'b0;
134+
sdrc_addr <= TEST_ADDRESS;
135+
sdrc_data_in <= TEST_WORD;
136+
state <= S_WAIT_ACK;
137+
end
138+
139+
S_WAIT_ACK: begin
140+
if (sdrc_wrd_ack)
141+
state <= S_READ;
142+
end
143+
144+
S_READ: begin
145+
if (sdrc_busy_n) begin
146+
sdrc_rd_n <= 1'b0;
147+
sdrc_addr <= TEST_ADDRESS;
148+
state <= S_WAIT_DATA;
149+
end
150+
end
151+
152+
S_WAIT_DATA: begin
153+
if (sdrc_rd_valid) begin
154+
o_led_ok <= (sdrc_data_out == TEST_WORD);
155+
o_led_err <= (sdrc_data_out != TEST_WORD);
156+
state <= S_DONE;
157+
end
158+
end
159+
160+
S_DONE: begin
161+
// Result latched in LEDs; stay idle.
162+
end
163+
164+
default: state <= S_WAIT_INIT;
165+
endcase
166+
end
167+
end
168+
169+
endmodule // sdram_gw2ar_example

0 commit comments

Comments
 (0)