1 | |
---|
2 | module warp_spi_io ( |
---|
3 | input sys_clk, |
---|
4 | input reset, |
---|
5 | input go, |
---|
6 | input [0:2] clkDiv, |
---|
7 | |
---|
8 | input [0:31] txData, |
---|
9 | |
---|
10 | output reg [0:31] rxData1, |
---|
11 | output reg [0:31] rxData2, |
---|
12 | output reg [0:31] rxData3, |
---|
13 | output reg [0:31] rxData4, |
---|
14 | |
---|
15 | output done, |
---|
16 | |
---|
17 | //Current bit index, in case user code needs to switch output enable mid-xfer |
---|
18 | output [0:4] currBitNum, |
---|
19 | |
---|
20 | //SPI signals |
---|
21 | output spi_mosi, //Master-out-slave-in serial data |
---|
22 | output spi_cs, //Active-high chip select |
---|
23 | output spi_sclk, //Serial clock (masked by spi_cs) |
---|
24 | |
---|
25 | input spi_miso1, //Dev 1 master-in-slave-out |
---|
26 | input spi_miso2, //Dev 2 master-in-slave-out |
---|
27 | input spi_miso3, //Dev 3 master-in-slave-out |
---|
28 | input spi_miso4 //Dev 4 master-in-slave-out |
---|
29 | ); |
---|
30 | |
---|
31 | parameter SPI_XFER_LEN = 5'd24; |
---|
32 | |
---|
33 | //Counter to generate SPI clock |
---|
34 | // Big enough that clkDiv can index any bit |
---|
35 | reg [0:7] spi_clk_counter; |
---|
36 | |
---|
37 | wire spi_clk; |
---|
38 | reg spi_clk_d1; |
---|
39 | wire spi_clk_pos, spi_clk_neg; |
---|
40 | |
---|
41 | reg go_d1; |
---|
42 | wire go_pos; |
---|
43 | |
---|
44 | reg [0:4] spi_xfer_counter; |
---|
45 | reg spi_xfer_running, spi_xfer_done; |
---|
46 | |
---|
47 | assign go_pos = go & ~go_d1; |
---|
48 | |
---|
49 | assign spi_cs = spi_xfer_running; |
---|
50 | assign currBitNum = spi_xfer_counter; |
---|
51 | assign done = spi_xfer_done; |
---|
52 | |
---|
53 | always @(posedge sys_clk) |
---|
54 | begin |
---|
55 | if(reset == 1) |
---|
56 | go_d1 <= 1'b0; |
---|
57 | else if(spi_clk_neg) |
---|
58 | go_d1 <= go; |
---|
59 | end |
---|
60 | |
---|
61 | //Free-running counter to generate SPI clock |
---|
62 | // 1 bit of this counter will be selected as the clock source |
---|
63 | always @(posedge sys_clk) |
---|
64 | begin |
---|
65 | if(reset == 1) |
---|
66 | begin |
---|
67 | spi_clk_counter <= 6'b0; |
---|
68 | spi_clk_d1 <= 1'b0; |
---|
69 | end |
---|
70 | else |
---|
71 | begin |
---|
72 | spi_clk_counter <= spi_clk_counter + 6'b000001; |
---|
73 | spi_clk_d1 <= spi_clk; |
---|
74 | end |
---|
75 | end |
---|
76 | |
---|
77 | //Select a bit of the counter to create the free-running clock |
---|
78 | // masked by an active SPI transfer |
---|
79 | //User code will mask again by per-device CS |
---|
80 | assign spi_clk = spi_clk_counter[clkDiv]; |
---|
81 | assign spi_sclk = spi_clk & spi_xfer_running; |
---|
82 | |
---|
83 | //Rising/falling edges of spi clk for internal clk enables |
---|
84 | assign spi_clk_pos = (spi_clk & ~spi_clk_d1); |
---|
85 | assign spi_clk_neg = (~spi_clk & spi_clk_d1); |
---|
86 | |
---|
87 | |
---|
88 | //SPI transfer status signals |
---|
89 | // spi_xfer_running: |
---|
90 | // Asserts when the user signals go |
---|
91 | // De-asserts when the last SPI character bit is processed |
---|
92 | // spi_xfer_done |
---|
93 | // Asserts after the last SPI character bit is processed |
---|
94 | // De-asserts when a new SPI transaction starts |
---|
95 | always @(posedge sys_clk) |
---|
96 | begin |
---|
97 | if(reset == 1) |
---|
98 | begin |
---|
99 | spi_xfer_running <= 1'b0; |
---|
100 | spi_xfer_done <= 1'b0; |
---|
101 | end |
---|
102 | else if( go & (spi_xfer_counter < SPI_XFER_LEN) & spi_clk_neg) |
---|
103 | begin |
---|
104 | spi_xfer_running <= 1'b1; |
---|
105 | spi_xfer_done <= 1'b0; |
---|
106 | end |
---|
107 | else if(spi_xfer_counter >= SPI_XFER_LEN) |
---|
108 | begin |
---|
109 | spi_xfer_running <= 1'b0; |
---|
110 | spi_xfer_done <= 1'b1; |
---|
111 | end |
---|
112 | else |
---|
113 | begin |
---|
114 | spi_xfer_running <= spi_xfer_running; |
---|
115 | spi_xfer_done <= 1'b0; |
---|
116 | end |
---|
117 | end |
---|
118 | |
---|
119 | //Bit-counter for SPI transactions |
---|
120 | // Counts from 0 to SPI_XFER_LEN, used to select the current Tx/Rx bit for serial I/O |
---|
121 | // Increments on the neg edge of the output SPI clock, so that output data is valid |
---|
122 | // on the arriving rising edge of sclk at SPI slave devices |
---|
123 | always @(posedge sys_clk) |
---|
124 | begin |
---|
125 | if((reset == 1) || spi_xfer_done) |
---|
126 | spi_xfer_counter <= 5'b0; |
---|
127 | else if (spi_xfer_counter >= (SPI_XFER_LEN)) |
---|
128 | spi_xfer_counter <= SPI_XFER_LEN; |
---|
129 | else if (spi_xfer_running & spi_clk_neg) |
---|
130 | spi_xfer_counter <= spi_xfer_counter + 1; |
---|
131 | else |
---|
132 | spi_xfer_counter <= spi_xfer_counter; |
---|
133 | end |
---|
134 | |
---|
135 | //Add 1 extra bit to txData, so the bit select below can safely select bit[32] |
---|
136 | wire [0:32] txData_safe; |
---|
137 | wire [4:0] data_bitSel; |
---|
138 | assign data_bitSel = spi_xfer_counter + (32-SPI_XFER_LEN); |
---|
139 | assign txData_safe = {txData, 1'b0}; |
---|
140 | |
---|
141 | //SPI data out is one bit from txData |
---|
142 | // The least significant SPI_XFER_LEN bits of txData are used |
---|
143 | // Data is transmitted MSB first |
---|
144 | //Example: for SPI_XFER_LEN=24, txData[8:31] is used, with txData[8] sent first, txData[31] last |
---|
145 | assign spi_mosi = spi_xfer_running ? txData_safe[data_bitSel] : 1'b0; |
---|
146 | |
---|
147 | //Second condition used to be: |
---|
148 | // else if(spi_xfer_running & spi_rnw & (spi_xfer_counter >= SPI_FIRST_RXBIT) & spi_clk_freerun_neg) |
---|
149 | // Don't care about rnw at this level anymore (right?) |
---|
150 | //data capture used to be: |
---|
151 | // if(~ad1_spi_cs_n) |
---|
152 | // rxByte1[spi_xfer_counter - SPI_FIRST_RXBIT] <= ad1_spi_miso; |
---|
153 | |
---|
154 | always @(posedge sys_clk) |
---|
155 | begin |
---|
156 | if(reset == 1) |
---|
157 | begin |
---|
158 | rxData1 <= 32'b0; |
---|
159 | rxData2 <= 32'b0; |
---|
160 | rxData3 <= 32'b0; |
---|
161 | rxData4 <= 32'b0; |
---|
162 | end |
---|
163 | // else if(spi_xfer_running & spi_clk_neg) |
---|
164 | else if(spi_xfer_running & spi_clk_pos) |
---|
165 | begin |
---|
166 | rxData1[data_bitSel] <= spi_miso1; |
---|
167 | rxData2[data_bitSel] <= spi_miso2; |
---|
168 | rxData3[data_bitSel] <= spi_miso3; |
---|
169 | rxData4[data_bitSel] <= spi_miso4; |
---|
170 | end |
---|
171 | else |
---|
172 | begin |
---|
173 | rxData1 <= rxData1; |
---|
174 | rxData2 <= rxData2; |
---|
175 | rxData3 <= rxData3; |
---|
176 | rxData4 <= rxData4; |
---|
177 | end |
---|
178 | end |
---|
179 | |
---|
180 | endmodule |
---|