source: PlatformSupport/Deprecated/pcores/SPI_Controller/hdl/verilog/spi_top.v

Last change on this file was 35, checked in by snovich, 19 years ago

Working new radio controller and working spi controller

File size: 12.5 KB
Line 
1//////////////////////////////////////////////////////////////////////
2////                                                              ////
3////  spi_top.v                                                   ////
4////                                                              ////
5////  This file is part of the SPI IP core project                ////
6////  http://www.opencores.org/projects/spi/                      ////
7////                                                              ////
8////  Author(s):                                                  ////
9////      - Simon Srot (simons@opencores.org)                     ////
10////                                                              ////
11////  All additional information is avaliable in the Readme.txt   ////
12////  file.                                                       ////
13////                                                              ////
14//////////////////////////////////////////////////////////////////////
15////                                                              ////
16//// Copyright (C) 2002 Authors                                   ////
17////                                                              ////
18//// This source file may be used and distributed without         ////
19//// restriction provided that this copyright statement is not    ////
20//// removed from the file and that any derivative work contains  ////
21//// the original copyright notice and the associated disclaimer. ////
22////                                                              ////
23//// This source file is free software; you can redistribute it   ////
24//// and/or modify it under the terms of the GNU Lesser General   ////
25//// Public License as published by the Free Software Foundation; ////
26//// either version 2.1 of the License, or (at your option) any   ////
27//// later version.                                               ////
28////                                                              ////
29//// This source is distributed in the hope that it will be       ////
30//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
31//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
32//// PURPOSE.  See the GNU Lesser General Public License for more ////
33//// details.                                                     ////
34////                                                              ////
35//// You should have received a copy of the GNU Lesser General    ////
36//// Public License along with this source; if not, download it   ////
37//// from http://www.opencores.org/lgpl.shtml                     ////
38////                                                              ////
39//////////////////////////////////////////////////////////////////////
40
41
42`include "spi_defines.v"
43
44module spi_top
45(
46  // Wishbone signals
47  wb_clk_i, wb_rst_i, wb_adr_i, wb_dat_i, wb_dat_o, wb_sel_i,
48  wb_we_i, wb_stb_i, wb_cyc_i, wb_ack_o, wb_err_o, wb_int_o,
49
50  // SPI signals
51  ss_pad_o, sclk_pad_o, mosi_pad_o, miso_pad_i
52);
53
54  parameter Tp = 1;
55
56
57
58  // Wishbone signals
59  input                            wb_clk_i;         // master clock input
60  input                            wb_rst_i;         // synchronous active high reset
61  input                      [31:0] wb_adr_i;         // lower address bits
62  input                   [32-1:0] wb_dat_i;         // databus input
63  output                  [32-1:0] wb_dat_o;         // databus output
64  input                      [3:0] wb_sel_i;         // byte select inputs
65  input                            wb_we_i;          // write enable input
66  input                            wb_stb_i;         // stobe/core select signal
67  input                            wb_cyc_i;         // valid bus cycle input
68  output                           wb_ack_o;         // bus cycle acknowledge output
69  output                           wb_err_o;         // termination w/ error
70  output                           wb_int_o;         // interrupt request signal output
71                                                     
72  // SPI signals                                     
73  output          [`SPI_SS_NB-1:0] ss_pad_o;         // slave select
74  output                           sclk_pad_o;       // serial clock
75  output                           mosi_pad_o;       // master out slave in
76  input                            miso_pad_i;       // master in slave out
77                                                     
78  reg                     [32-1:0] wb_dat_o;
79  reg                              wb_ack_o;
80  reg                              wb_int_o;
81                                               
82  // Internal signals
83  reg       [`SPI_DIVIDER_LEN-1:0] divider;          // Divider register
84  reg       [`SPI_CTRL_BIT_NB-1:0] ctrl;             // Control and status register
85  reg             [`SPI_SS_NB-1:0] ss;               // Slave select register
86  reg                     [32-1:0] wb_dat;           // wb data out
87  wire         [`SPI_MAX_CHAR-1:0] rx;               // Rx register
88  wire                             rx_negedge;       // miso is sampled on negative edge
89  wire                             tx_negedge;       // mosi is driven on negative edge
90  wire    [`SPI_CHAR_LEN_BITS-1:0] char_len;         // char len
91  wire                             go;               // go
92  wire                             lsb;              // lsb first on line
93  wire                             ie;               // interrupt enable
94  wire                             ass;              // automatic slave select
95  wire                             spi_divider_sel;  // divider register select
96  wire                             spi_ctrl_sel;     // ctrl register select
97  wire                       [3:0] spi_tx_sel;       // tx_l register select
98  wire                             spi_ss_sel;       // ss register select
99  wire                             tip;              // transfer in progress
100  wire                             pos_edge;         // recognize posedge of sclk
101  wire                             neg_edge;         // recognize negedge of sclk
102  wire                             last_bit;         // marks last character bit
103 
104  // Address decoder
105  assign spi_divider_sel = wb_cyc_i & wb_stb_i & (wb_adr_i[`SPI_OFS_BITS] == `SPI_DEVIDE);
106  assign spi_ctrl_sel    = wb_cyc_i & wb_stb_i & (wb_adr_i[`SPI_OFS_BITS] == `SPI_CTRL);
107  assign spi_tx_sel[0]   = wb_cyc_i & wb_stb_i & (wb_adr_i[`SPI_OFS_BITS] == `SPI_TX_0);
108  assign spi_tx_sel[1]   = wb_cyc_i & wb_stb_i & (wb_adr_i[`SPI_OFS_BITS] == `SPI_TX_1);
109  assign spi_tx_sel[2]   = wb_cyc_i & wb_stb_i & (wb_adr_i[`SPI_OFS_BITS] == `SPI_TX_2);
110  assign spi_tx_sel[3]   = wb_cyc_i & wb_stb_i & (wb_adr_i[`SPI_OFS_BITS] == `SPI_TX_3);
111  assign spi_ss_sel      = wb_cyc_i & wb_stb_i & (wb_adr_i[`SPI_OFS_BITS] == `SPI_SS);
112 
113  // Read from registers
114  always @(wb_adr_i[`SPI_OFS_BITS] or rx or ctrl or divider or ss)
115  begin
116    case (wb_adr_i[`SPI_OFS_BITS])
117`ifdef SPI_MAX_CHAR_128
118      `SPI_RX_0:    wb_dat = rx[31:0];
119      `SPI_RX_1:    wb_dat = rx[63:32];
120      `SPI_RX_2:    wb_dat = rx[95:64];
121      `SPI_RX_3:    wb_dat = {{128-`SPI_MAX_CHAR{1'b0}}, rx[`SPI_MAX_CHAR-1:96]};
122`else
123`ifdef SPI_MAX_CHAR_64
124      `SPI_RX_0:    wb_dat = rx[31:0];
125      `SPI_RX_1:    wb_dat = {{64-`SPI_MAX_CHAR{1'b0}}, rx[`SPI_MAX_CHAR-1:32]};
126      `SPI_RX_2:    wb_dat = 32'b0;
127      `SPI_RX_3:    wb_dat = 32'b0;
128`else
129      `SPI_RX_0:    wb_dat = {{32-`SPI_MAX_CHAR{1'b0}}, rx[`SPI_MAX_CHAR-1:0]};
130      `SPI_RX_1:    wb_dat = 32'b0;
131      `SPI_RX_2:    wb_dat = 32'b0;
132      `SPI_RX_3:    wb_dat = 32'b0;
133`endif
134`endif
135      `SPI_CTRL:    wb_dat = {{32-`SPI_CTRL_BIT_NB{1'b0}}, ctrl};
136      `SPI_DEVIDE:  wb_dat = {{32-`SPI_DIVIDER_LEN{1'b0}}, divider};
137      `SPI_SS:      wb_dat = {{32-`SPI_SS_NB{1'b0}}, ss};
138      default:      wb_dat = 32'bx;
139    endcase
140  end
141 
142  // Wb data out
143  always @(posedge wb_clk_i or posedge wb_rst_i)
144  begin
145    if (wb_rst_i)
146      wb_dat_o <= #Tp 32'b0;
147    else
148      wb_dat_o <= #Tp wb_dat;
149  end
150 
151  // Wb acknowledge
152  always @(posedge wb_clk_i or posedge wb_rst_i)
153  begin
154    if (wb_rst_i)
155      wb_ack_o <= #Tp 1'b0;
156    else
157      wb_ack_o <= #Tp wb_cyc_i & wb_stb_i & ~wb_ack_o;
158  end
159 
160  // Wb error
161  assign wb_err_o = 1'b0;
162 
163  // Interrupt
164  always @(posedge wb_clk_i or posedge wb_rst_i)
165  begin
166    if (wb_rst_i)
167      wb_int_o <= #Tp 1'b0;
168    else if (ie && tip && last_bit && pos_edge)
169      wb_int_o <= #Tp 1'b1;
170    else if (wb_ack_o)
171      wb_int_o <= #Tp 1'b0;
172  end
173 
174  // Divider register
175  always @(posedge wb_clk_i or posedge wb_rst_i)
176  begin
177    if (wb_rst_i)
178        divider <= #Tp {`SPI_DIVIDER_LEN{1'b0}};
179    else if (spi_divider_sel && wb_we_i && !tip)
180      begin
181      `ifdef SPI_DIVIDER_LEN_8
182        if (wb_sel_i[0])
183          divider <= #Tp wb_dat_i[`SPI_DIVIDER_LEN-1:0];
184      `endif
185      `ifdef SPI_DIVIDER_LEN_16
186        if (wb_sel_i[0])
187          divider[7:0] <= #Tp wb_dat_i[7:0];
188        if (wb_sel_i[1])
189          divider[`SPI_DIVIDER_LEN-1:8] <= #Tp wb_dat_i[`SPI_DIVIDER_LEN-1:8];
190      `endif
191      `ifdef SPI_DIVIDER_LEN_24
192        if (wb_sel_i[0])
193          divider[7:0] <= #Tp wb_dat_i[7:0];
194        if (wb_sel_i[1])
195          divider[15:8] <= #Tp wb_dat_i[15:8];
196        if (wb_sel_i[2])
197          divider[`SPI_DIVIDER_LEN-1:16] <= #Tp wb_dat_i[`SPI_DIVIDER_LEN-1:16];
198      `endif
199      `ifdef SPI_DIVIDER_LEN_32
200        if (wb_sel_i[0])
201          divider[7:0] <= #Tp wb_dat_i[7:0];
202        if (wb_sel_i[1])
203          divider[15:8] <= #Tp wb_dat_i[15:8];
204        if (wb_sel_i[2])
205          divider[23:16] <= #Tp wb_dat_i[23:16];
206        if (wb_sel_i[3])
207          divider[`SPI_DIVIDER_LEN-1:24] <= #Tp wb_dat_i[`SPI_DIVIDER_LEN-1:24];
208      `endif
209      end
210  end
211 
212  // Ctrl register
213  always @(posedge wb_clk_i or posedge wb_rst_i)
214  begin
215    if (wb_rst_i)
216      ctrl <= #Tp {`SPI_CTRL_BIT_NB{1'b0}};
217    else if(spi_ctrl_sel && wb_we_i && !tip)
218      begin
219        if (wb_sel_i[0])
220          ctrl[7:0] <= #Tp wb_dat_i[7:0] | {7'b0, ctrl[0]};
221        if (wb_sel_i[1])
222          ctrl[`SPI_CTRL_BIT_NB-1:8] <= #Tp wb_dat_i[`SPI_CTRL_BIT_NB-1:8];
223      end
224    else if(tip && last_bit && pos_edge)
225      ctrl[`SPI_CTRL_GO] <= #Tp 1'b0;
226  end
227 
228  assign rx_negedge = ctrl[`SPI_CTRL_RX_NEGEDGE];
229  assign tx_negedge = ctrl[`SPI_CTRL_TX_NEGEDGE];
230  assign go         = ctrl[`SPI_CTRL_GO];
231  assign char_len   = ctrl[`SPI_CTRL_CHAR_LEN];
232  assign lsb        = ctrl[`SPI_CTRL_LSB];
233  assign ie         = ctrl[`SPI_CTRL_IE];
234  assign ass        = ctrl[`SPI_CTRL_ASS];
235 
236  // Slave select register
237  always @(posedge wb_clk_i or posedge wb_rst_i)
238  begin
239    if (wb_rst_i)
240      ss <= #Tp {`SPI_SS_NB{1'b0}};
241    else if(spi_ss_sel && wb_we_i && !tip)
242      begin
243      `ifdef SPI_SS_NB_8
244        if (wb_sel_i[0])
245          ss <= #Tp wb_dat_i[`SPI_SS_NB-1:0];
246      `endif
247      `ifdef SPI_SS_NB_16
248        if (wb_sel_i[0])
249          ss[7:0] <= #Tp wb_dat_i[7:0];
250        if (wb_sel_i[1])
251          ss[`SPI_SS_NB-1:8] <= #Tp wb_dat_i[`SPI_SS_NB-1:8];
252      `endif
253      `ifdef SPI_SS_NB_24
254        if (wb_sel_i[0])
255          ss[7:0] <= #Tp wb_dat_i[7:0];
256        if (wb_sel_i[1])
257          ss[15:8] <= #Tp wb_dat_i[15:8];
258        if (wb_sel_i[2])
259          ss[`SPI_SS_NB-1:16] <= #Tp wb_dat_i[`SPI_SS_NB-1:16];
260      `endif
261      `ifdef SPI_SS_NB_32
262        if (wb_sel_i[0])
263          ss[7:0] <= #Tp wb_dat_i[7:0];
264        if (wb_sel_i[1])
265          ss[15:8] <= #Tp wb_dat_i[15:8];
266        if (wb_sel_i[2])
267          ss[23:16] <= #Tp wb_dat_i[23:16];
268        if (wb_sel_i[3])
269          ss[`SPI_SS_NB-1:24] <= #Tp wb_dat_i[`SPI_SS_NB-1:24];
270      `endif
271      end
272  end
273 
274  assign ss_pad_o = ~((ss & {`SPI_SS_NB{tip & ass}}) | (ss & {`SPI_SS_NB{!ass}}));
275 
276  spi_clgen clgen (.clk_in(wb_clk_i), .rst(wb_rst_i), .go(go), .enable(tip), .last_clk(last_bit),
277                   .divider(divider), .clk_out(sclk_pad_o), .pos_edge(pos_edge), 
278                   .neg_edge(neg_edge));
279 
280  spi_shift shift (.clk(wb_clk_i), .rst(wb_rst_i), .len(char_len[`SPI_CHAR_LEN_BITS-1:0]),
281                   .latch(spi_tx_sel[3:0] & {4{wb_we_i}}), .byte_sel(wb_sel_i), .lsb(lsb), 
282                   .go(go), .pos_edge(pos_edge), .neg_edge(neg_edge), 
283                   .rx_negedge(rx_negedge), .tx_negedge(tx_negedge),
284                   .tip(tip), .last(last_bit), 
285                   .p_in(wb_dat_i), .p_out(rx), 
286                   .s_clk(sclk_pad_o), .s_in(miso_pad_i), .s_out(mosi_pad_o));
287endmodule
288 
Note: See TracBrowser for help on using the repository browser.