-
Notifications
You must be signed in to change notification settings - Fork 14
/
top.v
154 lines (136 loc) · 4.8 KB
/
top.v
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
`timescale 1ns / 1ps
`include "defs.vh"
// In a simulation reset comes from the testbench and clk_to_mem_out has to be connected
// to the SPI memory model in the testbench.
// In hardware, if the FPGA SPI boot memory is used, the memory clock has to be connected
// via STARTUPE2 and end_of_startup can be used as a reset.
module top (
input CLK_100M,
output reg [1:0] status_led,
`ifndef __SYNTHESIS__
output clk_to_mem_out,
input rst,
`endif
inout [3:0] DQio,
output S
);
wire clk_to_mem, clk;
wire end_of_startup;
`ifndef __SYNTHESIS__
assign clk_to_mem_out = clk_to_mem;
`else
wire rst = ~end_of_startup;
`endif
wire [7:0] readout;
wire busy;
wire error;
reg trigger;
reg quad_mode;
reg [7:0] cmd;
reg [(3+256)*8-1:0] data_send;
reg [4:0] state;
clk_for_spi clk_spi_inst (
.clk_in1(CLK_100M), // input clk_in1, 100 MHz
.clk_out1(clk), // output clk_out1, 40 MHz, 0 deg
.clk_out2(clk_to_mem), // output clk_out2, 40 MHz, 180 deg
.reset(rst)
);
STARTUPE2 #(
.PROG_USR("FALSE"),
.SIM_CCLK_FREQ(10.0)
) STARTUPE2_inst (
.CFGCLK(),
.CFGMCLK(),
.EOS(end_of_startup),
.PREQ(),
.CLK(1'b0),
.GSR(1'b0),
.GTS(1'b0),
.KEYCLEARB(1'b0),
.PACK(1'b0),
.USRCCLKO(clk_to_mem),
.USRCCLKTS(1'b0),
.USRDONEO(1'b1),
.USRDONETS(1'b1)
);
qspi_mem_controller mc(
.clk(clk),
.reset(rst),
.S(S),
.DQio(DQio),
.trigger(trigger),
.quad_mode(quad_mode),
.cmd(cmd),
.data_send(data_send),
.readout(readout),
.busy(busy),
.error(error)
);
always @(posedge clk) begin
if (rst) begin
trigger <= 0;
state <= 0;
status_led <= 0;
quad_mode <= 0;
end else begin
case(state)
0: begin
if (!busy)
state <= state+1;
end
1: begin // read memory ID to test the communication
cmd <= `CMD_RDID;
trigger <= 1;
state <= state+1;
end
2: begin
if (trigger)
trigger <= 0;
else if (!busy) begin
$display("mem id: %x", readout);
if (readout == `JEDEC_ID) begin // verify the memory ID read
status_led[1] <= 1;
// enable quad IO
cmd <= `CMD_WRVECR;
data_send[7:0] <= 8'b010_01_111; // quad protocol, hold/accelerator disabled, default drive strength
trigger <= 1;
state <= state+1;
end else begin
status_led[0] <= 1; // memory ID is wrong, error, finish
end
end
end
3: begin
if (trigger) begin
trigger <= 0;
end else if (!busy) begin
quad_mode <= 1;
cmd <= `CMD_WREN;
trigger <= 1;
state <= state+1;
end
end
4: begin
if (trigger)
trigger <= 0;
else if (!busy) begin
cmd <= `CMD_PP;
// 3 bytes of address, then random data
data_send <= {24'hA30000, 2048'h01020304057372f04a39e4d37746533f26c5e18660ac4f512a18faef74279aae5f886745368ff4bdc0505deeb822c1c2a0ac568c4c11b41a9f62f93492cdbdb2a2b57f16c173a319879b8e45baee122f7c5821445ae1ad29f7e2655ac509ca8b450d453638de42e853adb1fbbcc9bac5f7f35b16346431aa0ac6f4865abaa74859cdf4d94c46b40efabe211621515d5dc2d383debab44cdbd57c41b37c34d6466f15cf7e36b481e104bf0367d7f7393fe2e62f489e8c9f6c522ec842789e8b6d251d35cb938664fda91a44de72227f9d748dacc21bc0e5ad5df3458e8f3b023e4e53cb4b266d0fb495aaeae3a56f04f9a1117409992975c4b4a5a88048edee5d};
trigger <= 1;
state <= state+1;
end
end
5: begin
trigger <= 0;
if (!busy && !trigger) begin
status_led[0] <= 1;
status_led[1] <= ~error;
end
end
default:
state <= state+1;
endcase
end
end
endmodule