]> git.ozlabs.org Git - minimigmac.git/blob - fpga/spi_backbus.v
Add GPL v2
[minimigmac.git] / fpga / spi_backbus.v
1 `timescale 1ns / 100ps
2
3 /* SPI to backbus interface for minimigmac
4  *
5  * This layers on top of the spi_slave module. It provides a protocol
6  * which allows to read and write from of 8-bit wide, 6 addr bit bus
7  * which is connected to various modules in the system.
8  *
9  * The basic SPI protocol starts with one byte received by the FPGA,
10  * which is has the format <RW:1> <AI:1> <ADDR:6>
11  * 
12  * RW   : Read (0) / Write (1)
13  * AI   : Auto-increment
14  * ADDR : Register address
15  * 
16  * For writes, all subsequent bytes are directly relevant. For reads,
17  * the next byte after the read command shall be ignored, then subsequent
18  * bytes are relevant.
19  * 
20  * The backbus side protocol is:
21  * 
22  *  - Writes: at clock with strobe high and wr high, data and address
23  *            are stable and shall be latched.
24  *  - Reads : at clock with strobe high and wr low, address stable,
25  *            we latch data immediately.
26  */
27
28 module spi_backbus
29 (
30         /* Clock & Reset */
31         input                   sysclk,
32         input                   reset,
33  
34         /* SPI signals (through to the SPI slave core) */
35         input                   sdi,
36         output                  sdo,
37         input                   sck,
38         input                   _scs,
39
40         /* Backbus interface */
41         output reg [5:0]        bb_addr,
42         output [7:0]            bb_wdata,
43         input [7:0]             bb_rdata,
44         output reg              bb_strobe,
45         output reg              bb_wr
46  );
47
48         /* SPI slave wires */
49         wire       spi_rx;
50         wire       spi_cmd;
51
52         /* Protocol internals */
53         reg        ainc;
54         reg        delayed_ainc;
55         reg        write;
56
57         /* Data read latch */
58         reg [7:0]  data;
59
60         /* Instanciate SPI slave interface */
61         spi_slave spi0(.sysclk(sysclk),
62                        .reset(reset),
63                        ._scs(_scs),
64                        .sdi(sdi),
65                        .sdo(sdo),
66                        .sck(sck),
67                        .wdata(data),
68                        .rdata(bb_wdata),
69                        .rx(spi_rx),
70                        .cmd(spi_cmd));
71
72         /* Data latch */
73         always@(posedge sysclk or posedge reset) begin
74                 if (reset) begin
75                         data <= 0;
76                 end else begin
77                         /* Latch read data at read strobe */
78                         if (bb_strobe && !bb_wr)
79                           data <= bb_rdata;
80                 end
81         end
82
83         /* One state machine to rule them all coz I'm lazy */
84         always@(posedge sysclk or posedge reset) begin
85                 if (reset) begin
86                         bb_addr <= 0;
87                 end else begin
88                         /* Command byte. Establish addr, wr and set strobe on read */
89                         if (spi_rx && spi_cmd) begin
90                                 bb_addr <= bb_wdata[5:0];
91                                 delayed_ainc <= bb_wdata[6];
92                                 ainc <= bb_wdata[7] ? 0 : bb_wdata[6];
93                                 bb_wr <= bb_wdata[7];
94                                 bb_strobe <= ~bb_wdata[7];
95                         end else if (spi_rx) begin
96                                 /* Subsequent bytes */
97                                 ainc <= delayed_ainc;
98                                 if (ainc) begin
99                                         bb_addr <= bb_addr + 1;
100                                 end
101                                 /* New strobe */
102                                 bb_strobe <= 1;                         
103                         end else begin
104                                 bb_strobe <= 0;
105                         end             
106                 end
107         end
108 endmodule
109
110