📄 spi_shift.v
字号:
////////////////////////////////////////////////////////////////////////// //////// spi_shift.v //////// //////// This file is part of the SPI IP core project //////// http://www.opencores.org/projects/spi/ //////// //////// Author(s): //////// - Simon Srot (simons@opencores.org) //////// //////// All additional information is avaliable in the Readme.txt //////// file. //////// ////////////////////////////////////////////////////////////////////////////// //////// Copyright (C) 2002 Authors //////// //////// This source file may be used and distributed without //////// restriction provided that this copyright statement is not //////// removed from the file and that any derivative work contains //////// the original copyright notice and the associated disclaimer. //////// //////// This source file is free software; you can redistribute it //////// and/or modify it under the terms of the GNU Lesser General //////// Public License as published by the Free Software Foundation; //////// either version 2.1 of the License, or (at your option) any //////// later version. //////// //////// This source is distributed in the hope that it will be //////// useful, but WITHOUT ANY WARRANTY; without even the implied //////// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //////// PURPOSE. See the GNU Lesser General Public License for more //////// details. //////// //////// You should have received a copy of the GNU Lesser General //////// Public License along with this source; if not, download it //////// from http://www.opencores.org/lgpl.shtml //////// //////////////////////////////////////////////////////////////////////////`include "spi_defines.v"`include "timescale.v"module spi_shift (clk, rst, latch, byte_sel, len, lsb, go, pos_edge, neg_edge, rx_negedge, tx_negedge, tip, last, p_in, p_out, s_clk, s_in, s_out); parameter Tp = 1; input clk; // system clock input rst; // reset input [3:0] latch; // latch signal for storing the data in shift register input [3:0] byte_sel; // byte select signals for storing the data in shift register input [`SPI_CHAR_LEN_BITS-1:0] len; // data len in bits (minus one) input lsb; // lbs first on the line input go; // start stansfer input pos_edge; // recognize posedge of sclk input neg_edge; // recognize negedge of sclk input rx_negedge; // s_in is sampled on negative edge input tx_negedge; // s_out is driven on negative edge output tip; // transfer in progress output last; // last bit input [31:0] p_in; // parallel in output [`SPI_MAX_CHAR-1:0] p_out; // parallel out input s_clk; // serial clock input s_in; // serial in output s_out; // serial out reg s_out; reg tip; reg [`SPI_CHAR_LEN_BITS:0] cnt; // data bit count reg [`SPI_MAX_CHAR-1:0] data; // shift register wire [`SPI_CHAR_LEN_BITS:0] tx_bit_pos; // next bit position wire [`SPI_CHAR_LEN_BITS:0] rx_bit_pos; // next bit position wire rx_clk; // rx clock enable wire tx_clk; // tx clock enable assign p_out = data; assign tx_bit_pos = lsb ? {!(|len), len} - cnt : cnt - {{`SPI_CHAR_LEN_BITS{1'b0}},1'b1}; assign rx_bit_pos = lsb ? {!(|len), len} - (rx_negedge ? cnt + {{`SPI_CHAR_LEN_BITS{1'b0}},1'b1} : cnt) : (rx_negedge ? cnt : cnt - {{`SPI_CHAR_LEN_BITS{1'b0}},1'b1}); assign last = !(|cnt); assign rx_clk = (rx_negedge ? neg_edge : pos_edge) && (!last || s_clk); assign tx_clk = (tx_negedge ? neg_edge : pos_edge) && !last; // Character bit counter always @(posedge clk or posedge rst) begin if(rst) cnt <= #Tp {`SPI_CHAR_LEN_BITS+1{1'b0}}; else begin if(tip) cnt <= #Tp pos_edge ? (cnt - {{`SPI_CHAR_LEN_BITS{1'b0}}, 1'b1}) : cnt; else cnt <= #Tp !(|len) ? {1'b1, {`SPI_CHAR_LEN_BITS{1'b0}}} : {1'b0, len}; end end // Transfer in progress always @(posedge clk or posedge rst) begin if(rst) tip <= #Tp 1'b0; else if(go && ~tip) tip <= #Tp 1'b1; else if(tip && last && pos_edge) tip <= #Tp 1'b0; end // Sending bits to the line always @(posedge clk or posedge rst) begin if (rst) s_out <= #Tp 1'b0; else s_out <= #Tp (tx_clk || !tip) ? data[tx_bit_pos[`SPI_CHAR_LEN_BITS-1:0]] : s_out; end // Receiving bits from the line always @(posedge clk or posedge rst) begin if (rst) data <= #Tp {`SPI_MAX_CHAR{1'b0}};`ifdef SPI_MAX_CHAR_128 else if (latch[0] && !tip) begin if (byte_sel[3]) data[31:24] <= #Tp p_in[31:24]; if (byte_sel[2]) data[23:16] <= #Tp p_in[23:16]; if (byte_sel[1]) data[15:8] <= #Tp p_in[15:8]; if (byte_sel[0]) data[7:0] <= #Tp p_in[7:0]; end else if (latch[1] && !tip) begin if (byte_sel[3]) data[63:56] <= #Tp p_in[31:24]; if (byte_sel[2]) data[55:48] <= #Tp p_in[23:16]; if (byte_sel[1]) data[47:40] <= #Tp p_in[15:8]; if (byte_sel[0]) data[39:32] <= #Tp p_in[7:0]; end else if (latch[2] && !tip) begin if (byte_sel[3]) data[95:88] <= #Tp p_in[31:24]; if (byte_sel[2]) data[87:80] <= #Tp p_in[23:16]; if (byte_sel[1]) data[79:72] <= #Tp p_in[15:8]; if (byte_sel[0]) data[71:64] <= #Tp p_in[7:0]; end else if (latch[3] && !tip) begin if (byte_sel[3]) data[127:120] <= #Tp p_in[31:24]; if (byte_sel[2]) data[119:112] <= #Tp p_in[23:16]; if (byte_sel[1]) data[111:104] <= #Tp p_in[15:8]; if (byte_sel[0]) data[103:96] <= #Tp p_in[7:0]; end`else`ifdef SPI_MAX_CHAR_64 else if (latch[0] && !tip) begin if (byte_sel[3]) data[31:24] <= #Tp p_in[31:24]; if (byte_sel[2]) data[23:16] <= #Tp p_in[23:16]; if (byte_sel[1]) data[15:8] <= #Tp p_in[15:8]; if (byte_sel[0]) data[7:0] <= #Tp p_in[7:0]; end else if (latch[1] && !tip) begin if (byte_sel[3]) data[63:56] <= #Tp p_in[31:24]; if (byte_sel[2]) data[55:48] <= #Tp p_in[23:16]; if (byte_sel[1]) data[47:40] <= #Tp p_in[15:8]; if (byte_sel[0]) data[39:32] <= #Tp p_in[7:0]; end`else else if (latch[0] && !tip) begin `ifdef SPI_MAX_CHAR_8 if (byte_sel[0]) data[`SPI_MAX_CHAR-1:0] <= #Tp p_in[`SPI_MAX_CHAR-1:0]; `endif `ifdef SPI_MAX_CHAR_16 if (byte_sel[0]) data[7:0] <= #Tp p_in[7:0]; if (byte_sel[1]) data[`SPI_MAX_CHAR-1:8] <= #Tp p_in[`SPI_MAX_CHAR-1:8]; `endif `ifdef SPI_MAX_CHAR_24 if (byte_sel[0]) data[7:0] <= #Tp p_in[7:0]; if (byte_sel[1]) data[15:8] <= #Tp p_in[15:8]; if (byte_sel[2]) data[`SPI_MAX_CHAR-1:16] <= #Tp p_in[`SPI_MAX_CHAR-1:16]; `endif `ifdef SPI_MAX_CHAR_32 if (byte_sel[0]) data[7:0] <= #Tp p_in[7:0]; if (byte_sel[1]) data[15:8] <= #Tp p_in[15:8]; if (byte_sel[2]) data[23:16] <= #Tp p_in[23:16]; if (byte_sel[3]) data[`SPI_MAX_CHAR-1:24] <= #Tp p_in[`SPI_MAX_CHAR-1:24]; `endif end`endif`endif else data[rx_bit_pos[`SPI_CHAR_LEN_BITS-1:0]] <= #Tp rx_clk ? s_in : data[rx_bit_pos[`SPI_CHAR_LEN_BITS-1:0]]; end endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -