aboutsummaryrefslogtreecommitdiffstats
path: root/spiflash/spiflash.v
blob: 933f3a28ed2341a786130887ea6f954c85064d01 (plain)
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
module spiflash (
	input      spi_cs,
	output reg spi_miso,
	input      spi_mosi,
	input      spi_sclk
);
	localparam verbose = 1;
	
	reg [7:0] buffer;
	integer bitcount = 0;
	integer bytecount = 0;

	reg [7:0] spi_cmd;
	reg [23:0] spi_addr;

	reg [7:0] spi_in;
	reg [7:0] spi_out;
	reg spi_io_vld;

	reg powered_up = 0;
	reg in_xfer = 0;

	// 16 MB (128Mb) Flash
	reg [7:0] memory [0:16*1024*1024-1];

	initial begin
		$readmemh("firmware.hex", memory);
	end

	task spi_action;
		begin
			if (verbose) begin
				if (bytecount == 1)
					$write("<SPI>");
				$write("<SPI:%02x", buffer);
				spi_in = buffer;
			end

			if (bytecount == 1) begin
				spi_cmd = buffer;
				if (spi_cmd == 8'hAB)
					powered_up = 1;
				if (spi_cmd == 8'hB9)
					powered_up = 0;
			end

			if (powered_up && spi_cmd == 'h03) begin
				if (bytecount == 2)
					spi_addr[23:16] = buffer;

				if (bytecount == 3)
					spi_addr[15:8] = buffer;

				if (bytecount == 4)
					spi_addr[7:0] = buffer;

				if (bytecount >= 4) begin
					buffer = memory[spi_addr];
					spi_addr = spi_addr + 1;
				end
			end

			if (verbose) begin
				$write(":%02x>", buffer);
				spi_out = buffer;
				spi_io_vld = 1;
				$fflush;
			end
		end
	endtask

	always @(spi_cs) begin
		if (spi_cs) begin
			if (verbose && in_xfer) begin
				$display("");
				$fflush;
			end
			buffer = 0;
			in_xfer = 0;
			bitcount = 0;
			bytecount = 0;
			spi_miso = 0;
		end
	end

	always @(spi_cs, spi_sclk) begin
		spi_io_vld = 0;
		if (!spi_cs && !spi_sclk) begin
			spi_miso = buffer[7];
		end
	end

	always @(posedge spi_sclk) begin
		if (!spi_cs) begin
			buffer = {buffer, spi_mosi};
			bitcount = bitcount + 1;
			if (bitcount == 8) begin
				in_xfer = 1;
				bitcount = 0;
				bytecount = bytecount + 1;
				spi_action;
			end
		end
	end
endmodule