1 | ////////////////////////////////////////////////////////////////////// |
---|
2 | //// //// |
---|
3 | //// spi_shift.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 | // Copyright (C) 2005 Rice University - Rice Open License Fill |
---|
41 | |
---|
42 | `include "spi_defines.v" |
---|
43 | |
---|
44 | module spi_shift (clk, rst, len, lsb, go, |
---|
45 | pos_edge, neg_edge, rx_negedge, tx_negedge, |
---|
46 | tip, last, |
---|
47 | p_in, p_out, s_clk, s_out); |
---|
48 | |
---|
49 | parameter Tp = 1; |
---|
50 | |
---|
51 | input clk; // system clock |
---|
52 | input rst; // reset |
---|
53 | input [`SPI_CHAR_LEN_BITS-1:0] len; // data len in bits (minus one) |
---|
54 | input lsb; // lbs first on the line |
---|
55 | input go; // start stansfer |
---|
56 | input pos_edge; // recognize posedge of sclk |
---|
57 | input neg_edge; // recognize negedge of sclk |
---|
58 | input rx_negedge; // s_in is sampled on negative edge |
---|
59 | input tx_negedge; // s_out is driven on negative edge |
---|
60 | output tip; // transfer in progress |
---|
61 | output last; // last bit |
---|
62 | input /*31*/ [17:0] p_in; // parallel in |
---|
63 | output [`SPI_MAX_CHAR-1:0] p_out; // parallel out |
---|
64 | input s_clk; // serial clock |
---|
65 | output s_out; // serial out |
---|
66 | |
---|
67 | reg s_out; |
---|
68 | reg tip; |
---|
69 | |
---|
70 | reg [`SPI_CHAR_LEN_BITS:0] cnt; // data bit count |
---|
71 | wire [`SPI_MAX_CHAR-1:0] data; // shift register |
---|
72 | wire [`SPI_CHAR_LEN_BITS:0] tx_bit_pos; // next bit position |
---|
73 | wire [`SPI_CHAR_LEN_BITS:0] rx_bit_pos; // next bit position |
---|
74 | wire rx_clk; // rx clock enable |
---|
75 | wire tx_clk; // tx clock enable |
---|
76 | |
---|
77 | //assign p_out = data; |
---|
78 | assign data = p_in; |
---|
79 | |
---|
80 | assign tx_bit_pos = lsb ? {!(|len), len} - cnt : cnt - {{`SPI_CHAR_LEN_BITS{1'b0}},1'b1}; |
---|
81 | assign rx_bit_pos = lsb ? {!(|len), len} - (rx_negedge ? cnt + {{`SPI_CHAR_LEN_BITS{1'b0}},1'b1} : cnt) : |
---|
82 | (rx_negedge ? cnt : cnt - {{`SPI_CHAR_LEN_BITS{1'b0}},1'b1}); |
---|
83 | |
---|
84 | assign last = !(|cnt); |
---|
85 | |
---|
86 | assign rx_clk = (rx_negedge ? neg_edge : pos_edge) && (!last || s_clk); |
---|
87 | assign tx_clk = (tx_negedge ? neg_edge : pos_edge) && !last; |
---|
88 | |
---|
89 | // Character bit counter |
---|
90 | always @(posedge clk or posedge rst) |
---|
91 | begin |
---|
92 | if(rst) |
---|
93 | cnt <= #Tp {`SPI_CHAR_LEN_BITS+1{1'b0}}; |
---|
94 | else |
---|
95 | begin |
---|
96 | if(tip) |
---|
97 | cnt <= #Tp pos_edge ? (cnt - {{`SPI_CHAR_LEN_BITS{1'b0}}, 1'b1}) : cnt; |
---|
98 | else |
---|
99 | cnt <= #Tp !(|len) ? {1'b1, {`SPI_CHAR_LEN_BITS{1'b0}}} : {1'b0, len}; |
---|
100 | end |
---|
101 | end |
---|
102 | |
---|
103 | // Transfer in progress |
---|
104 | always @(posedge clk or posedge rst) |
---|
105 | begin |
---|
106 | if(rst) |
---|
107 | tip <= #Tp 1'b0; |
---|
108 | else if(go && ~tip) |
---|
109 | tip <= #Tp 1'b1; |
---|
110 | else if(tip && last && pos_edge) |
---|
111 | tip <= #Tp 1'b0; |
---|
112 | end |
---|
113 | |
---|
114 | // Sending bits to the line |
---|
115 | always @(posedge clk or posedge rst) |
---|
116 | begin |
---|
117 | if (rst) |
---|
118 | s_out <= #Tp 1'b0; |
---|
119 | else |
---|
120 | s_out <= #Tp (tx_clk || !tip) ? data[tx_bit_pos[`SPI_CHAR_LEN_BITS-1:0]] : s_out; |
---|
121 | end |
---|
122 | |
---|
123 | |
---|
124 | endmodule |
---|
125 | |
---|