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
155
156
|
`timescale 1ns / 1ps
module m25p16_spi_core(
input clk_i,
input rst_i,
input [4:0] opcode_i,
input [31:0] info_i,
input [31:0] dat_i,
output [31:0] dat_o,
output dat_o_read,
output dat_o_valid,
input [31:0] adr_i,
output finish_o
);
wire spi_finish;
reg [31:0] data;
reg [31:0] info;
reg [7:0] cnt;
//***********************************
// SPI M25P16 Core state
//***********************************
// Memory for storing state
reg[7:0] state = IDLE_S;
reg[7:0] next_state;
localparam OPCODE_READING_DATA = 1,
OPCODE_WRITING_DATA = 2,
OPCODE_ERASING_SECTOR = 3,
OPCODE_BULK_ERASING = 4,
OPCODE_READING_STATUS = 5,
OPCODE_WRITING_STATUS = 6;
localparam IDLE_S = 0,
WRITING_DATA_WRITE_ENABLE_S = 1,
WRITING_DATA_WRITE_INSTR_S = 2,
WRITING_DATA_WRITE_DATA_S = 3,
WRITING_DATA_WRITE_DISABLE_S = 4,
FINISH_S = 64;
always @*
case( state )
IDLE_S:
info = info_i;
endcase
always @( posedge clk_i, posedge rst_i )
if( rst_i )
state <= IDLE_S;
else
state <= next_state;
always @*
begin
next_state = state;
case( state )
IDLE_S:
if( opcode_i == OPCODE_WRITING_DATA )
next_state = WRITING_DATA_WRITE_ENABLE_S;
WRITING_DATA_WRITE_ENABLE_S:
if( spi_finish )
next_state = WRITING_DATA_WRITE_INSTR_S;
WRITING_DATA_WRITE_INSTR_S:
if( next_w )
next_state = WRITING_DATA_WRITE_DATA_S;
WRITING_DATA_WRITE_DATA_S:
if( spi_finish )
next_state = WRITING_DATA_WRITE_DISABLE_S;
WRITING_DATA_WRITE_DISABLE_S:
if( spi_finish )
next_state = FINISH_S;
FINISH_S:
next_state = IDLE_S;
endcase
end
always @*
case( next_state )
WRITING_DATA_WRITE_INSTR_S:
cnt = 4;
WRITING_DATA_WRITE_ENABLE_S, WRITING_DATA_WRITE_DISABLE_S:
cnt = 1;
WRITING_DATA_WRITE_DATA_S:
cnt = info[7:0] << 2;
endcase
always @*
case( state )
WRITING_DATA_WRITE_DATA_S:
data = dat_i;
endcase
always @*
case( next_state )
WRITING_DATA_WRITE_ENABLE_S:
data = 32'hAA;
WRITING_DATA_WRITE_INSTR_S:
data = 32'hFF000000 | adr_i[23:0];
WRITING_DATA_WRITE_DATA_S:
data = dat_i;
WRITING_DATA_WRITE_DISABLE_S:
data = 32'hDD;
endcase
//***********************************
// SPI Routine
//***********************************
wire spi_miso_i, spi_sclk_o, spi_mosi_o, spi_ss_i;
assign spi_rd_i = 1'b0; // TODO: unused
assign spi_wr_i = (WRITING_DATA_WRITE_ENABLE_S ||
WRITING_DATA_WRITE_INSTR_S ||
WRITING_DATA_WRITE_DATA_S ||
WRITING_DATA_WRITE_DISABLE_S);
assign spi_sclk_i = clk_i;
wire [31:0] rx_o; // TODO: unused
wire next_o;
wire next_w;
assign next_o = ( state == WRITING_DATA_WRITE_DATA_S ? dat_o_read : next_w );
spi_routine spi_routine(
.clk_i(clk_i),
.rst_i(1'b0),
.sclk_o(spi_sclk_o),
.ss_i(spi_ss_i),
.mosi_o(spi_mosi_o),
.miso_i(spi_miso_i),
.rx_o(rx_o),
.tx_i(data),
.wr_i(spi_wr_i),
.rd_i(spi_rd_i),
.cnt_i(cnt),
.next_o(next_o),
.finish_o(spi_finish)
);
assign finish_o = ( state == FINISH_S ? 1 : 0 );
endmodule
|