OpenCores
URL https://opencores.org/ocsvn/spi/spi/trunk

Subversion Repositories spi

[/] [spi/] [tags/] [rel_1/] [rtl/] [verilog/] [spi_top.v] - Blame information for rev 27

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 simons
//////////////////////////////////////////////////////////////////////
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
`include "timescale.v"
44
 
45
module spi_top
46
(
47
  // Wishbone signals
48
  wb_clk_i, wb_rst_i, wb_adr_i, wb_dat_i, wb_dat_o, wb_sel_i,
49
  wb_we_i, wb_stb_i, wb_cyc_i, wb_ack_o, wb_err_o, wb_int_o,
50
 
51
  // SPI signals
52
  ss_pad_o, sclk_pad_o, mosi_pad_o, miso_pad_i
53
);
54
 
55
  parameter dw = 32;
56
  parameter Tp = 1;
57
 
58
  // Wishbone signals
59
  input                            wb_clk_i;         // master clock input
60
  input                            wb_rst_i;         // synchronous active high reset
61
  input                      [4:0] wb_adr_i;         // lower address bits
62
  input                   [dw-1:0] wb_dat_i;         // databus input
63
  output                  [dw-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                     [dw-1:0] wb_dat_o;
79
  reg                              wb_ack_o;
80
  reg                              wb_err_o;
81
  reg                              wb_int_o;
82
 
83
  // Internal signals
84
  reg    [`SPI_DIVIDER_BIT_NB-1:0] divider;          // Divider register
85
  reg       [`SPI_CTRL_BIT_NB-1:0] ctrl;             // Control and status register
86
  reg             [`SPI_SS_NB-1:0] ss;               // Slave select register
87
  reg                     [dw-1:0] wb_dat;           // wb data out
88
  wire         [`SPI_MAX_CHAR-1:0] rx;               // Rx register
89
  wire                             rx_negedge;       // miso is sampled on negative edge
90
  wire                             tx_negedge;       // mosi is driven on negative edge
91
  wire    [`SPI_CHAR_LEN_BITS-1:0] char_len;         // char len
92
  wire                             go;               // go
93
  wire                             lsb;              // lsb first on line
94
  wire                             ie;               // interrupt enable
95
  wire                             spi_divider_sel;  // divider register select
96
  wire                             spi_ctrl_sel;     // ctrl register select
97
  wire                             spi_tx_sel;       // tx 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      = wb_cyc_i & wb_stb_i & (wb_adr_i[`SPI_OFS_BITS] == `SPI_TX);
108
  assign spi_ss_sel      = wb_cyc_i & wb_stb_i & (wb_adr_i[`SPI_OFS_BITS] == `SPI_SS);
109
 
110
  // Read from registers
111
  always @(wb_adr_i or rx or ctrl or divider or ss)
112
  begin
113
    case (wb_adr_i[`SPI_OFS_BITS])
114
      `SPI_RX:      wb_dat = {{dw-`SPI_MAX_CHAR{1'b0}}, rx};
115
      `SPI_CTRL:    wb_dat = {{dw-`SPI_CTRL_BIT_NB{1'b0}}, ctrl};
116
      `SPI_DEVIDE:  wb_dat = {{dw-`SPI_DIVIDER_BIT_NB{1'b0}}, divider};
117
      `SPI_SS:      wb_dat = {{dw-`SPI_SS_NB{1'b0}}, ss};
118
    endcase
119
  end
120
 
121
  // Wb data out
122
  always @(posedge wb_clk_i or posedge wb_rst_i)
123
  begin
124
    if (wb_rst_i)
125
      wb_dat_o <= #Tp {dw{1'b0}};
126
    else
127
      wb_dat_o <= #Tp wb_dat;
128
  end
129
 
130
  // Wb acknowledge
131
  always @(posedge wb_clk_i or posedge wb_rst_i)
132
  begin
133
    if (wb_rst_i)
134
      wb_ack_o <= #Tp 1'b0;
135
    else
136
      wb_ack_o <= #Tp wb_cyc_i & wb_stb_i & ~wb_ack_o;
137
  end
138
 
139
  // Wb error
140
  always @(posedge wb_clk_i or posedge wb_rst_i)
141
  begin
142
    if (wb_rst_i)
143
      wb_err_o <= #Tp 1'b0;
144
    else
145
      wb_err_o <= #Tp wb_cyc_i & wb_stb_i & (wb_sel_i != 4'b1111) & ~wb_err_o;
146
  end
147
 
148
  // Interrupt
149
  always @(posedge wb_clk_i or posedge wb_rst_i)
150
  begin
151
    if (wb_rst_i)
152
      wb_int_o <= #Tp 1'b0;
153
    else if (ie && tip && last_bit && pos_edge)
154
      wb_int_o <= #Tp 1'b1;
155
    else if (wb_ack_o)
156
      wb_int_o <= #Tp 1'b0;
157
  end
158
 
159
  // Divider register
160
  always @(posedge wb_clk_i or posedge wb_rst_i)
161
  begin
162
    if (wb_rst_i)
163
      divider <= #Tp {`SPI_DIVIDER_BIT_NB{1'b0}};
164
    else if (spi_divider_sel && wb_we_i && !tip)
165
      divider <= #Tp wb_dat_i[`SPI_DIVIDER_BIT_NB-1:0];
166
  end
167
 
168
  // Ctrl register
169
  always @(posedge wb_clk_i or posedge wb_rst_i)
170
  begin
171
    if (wb_rst_i)
172
      ctrl <= #Tp {`SPI_CTRL_BIT_NB{1'b0}};
173
    else if(spi_ctrl_sel && wb_we_i && !tip)
174
      begin
175
        ctrl[`SPI_CTRL_GO]         <= #Tp wb_dat_i[`SPI_CTRL_GO] | ctrl[`SPI_CTRL_GO];
176
        ctrl[`SPI_CTRL_RX_NEGEDGE] <= #Tp wb_dat_i[`SPI_CTRL_RX_NEGEDGE];
177
        ctrl[`SPI_CTRL_TX_NEGEDGE] <= #Tp wb_dat_i[`SPI_CTRL_TX_NEGEDGE];
178
        ctrl[`SPI_CTRL_CHAR_LEN]   <= #Tp wb_dat_i[`SPI_CTRL_CHAR_LEN];
179
        ctrl[`SPI_CTRL_LSB]        <= #Tp wb_dat_i[`SPI_CTRL_LSB];
180
        ctrl[`SPI_CTRL_IE]         <= #Tp wb_dat_i[`SPI_CTRL_IE];
181
      end
182
    else if(tip && last_bit && pos_edge)
183
      ctrl[`SPI_CTRL_GO] <= #Tp 1'b0;
184
  end
185
 
186
  assign rx_negedge = ctrl[`SPI_CTRL_RX_NEGEDGE];
187
  assign tx_negedge = ctrl[`SPI_CTRL_TX_NEGEDGE];
188
  assign go         = ctrl[`SPI_CTRL_GO];
189
  assign char_len   = ctrl[`SPI_CTRL_CHAR_LEN];
190
  assign lsb        = ctrl[`SPI_CTRL_LSB];
191
  assign ie         = ctrl[`SPI_CTRL_IE];
192
 
193
  // Slave select register
194
  always @(posedge wb_clk_i or posedge wb_rst_i)
195
  begin
196
    if (wb_rst_i)
197
      ss <= #Tp {`SPI_SS_NB{1'b0}};
198
    else if(spi_ss_sel && wb_we_i && !tip)
199
      ss <= #Tp wb_dat_i[`SPI_SS_NB-1:0];
200
  end
201
 
202
  assign ss_pad_o = ~ss;
203
 
204
  spi_clgen clgen (.clk_in(wb_clk_i), .rst(wb_rst_i), .enable(tip), .last_clk(last_bit),
205
                   .divider(divider), .clk_out(sclk_pad_o), .pos_edge(pos_edge),
206
                   .neg_edge(neg_edge));
207
 
208
  spi_shift shift (.clk(wb_clk_i), .rst(wb_rst_i), .len(char_len[`SPI_CHAR_LEN_BITS-1:0]),
209
                   .latch(spi_tx_sel && wb_we_i), .lsb(lsb), .go(go),
210
                   .pos_edge(pos_edge), .neg_edge(neg_edge),
211
                   .rx_negedge(rx_negedge), .tx_negedge(tx_negedge),
212
                   .tip(tip), .last(last_bit),
213
                   .p_in(wb_dat_i), .p_out(rx),
214
                   .s_clk(sclk_pad_o), .s_in(miso_pad_i), .s_out(mosi_pad_o));
215
endmodule
216
 
217
 
218
 
219
 
220
 
221
 
222
 
223
 
224
 
225
 
226
 
227
 
228
 
229
 
230
 
231
 
232
 
233
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.