| 1 |
3 |
MichaelA |
////////////////////////////////////////////////////////////////////////////////
|
| 2 |
2 |
MichaelA |
//
|
| 3 |
3 |
MichaelA |
// Copyright 2008-2013 by Michael A. Morris, dba M. A. Morris & Associates
|
| 4 |
2 |
MichaelA |
//
|
| 5 |
3 |
MichaelA |
// All rights reserved. The source code contained herein is publicly released
|
| 6 |
|
|
// under the terms and conditions of the GNU Lesser Public License. No part of
|
| 7 |
|
|
// this source code may be reproduced or transmitted in any form or by any
|
| 8 |
|
|
// means, electronic or mechanical, including photocopying, recording, or any
|
| 9 |
|
|
// information storage and retrieval system in violation of the license under
|
| 10 |
|
|
// which the source code is released.
|
| 11 |
2 |
MichaelA |
//
|
| 12 |
3 |
MichaelA |
// The source code contained herein is free; it may be redistributed and/or
|
| 13 |
|
|
// modified in accordance with the terms of the GNU Lesser General Public
|
| 14 |
|
|
// License as published by the Free Software Foundation; either version 2.1 of
|
| 15 |
|
|
// the GNU Lesser General Public License, or any later version.
|
| 16 |
|
|
//
|
| 17 |
|
|
// The source code contained herein is freely released WITHOUT ANY WARRANTY;
|
| 18 |
|
|
// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
| 19 |
|
|
// PARTICULAR PURPOSE. (Refer to the GNU Lesser General Public License for
|
| 20 |
|
|
// more details.)
|
| 21 |
|
|
//
|
| 22 |
|
|
// A copy of the GNU Lesser General Public License should have been received
|
| 23 |
|
|
// along with the source code contained herein; if not, a copy can be obtained
|
| 24 |
|
|
// by writing to:
|
| 25 |
|
|
//
|
| 26 |
|
|
// Free Software Foundation, Inc.
|
| 27 |
|
|
// 51 Franklin Street, Fifth Floor
|
| 28 |
|
|
// Boston, MA 02110-1301 USA
|
| 29 |
|
|
//
|
| 30 |
2 |
MichaelA |
// Further, no use of this source code is permitted in any form or means
|
| 31 |
3 |
MichaelA |
// without inclusion of this banner prominently in any derived works.
|
| 32 |
2 |
MichaelA |
//
|
| 33 |
|
|
// Michael A. Morris
|
| 34 |
3 |
MichaelA |
// Huntsville, AL
|
| 35 |
2 |
MichaelA |
//
|
| 36 |
3 |
MichaelA |
////////////////////////////////////////////////////////////////////////////////
|
| 37 |
2 |
MichaelA |
|
| 38 |
|
|
`timescale 1ns / 1ps
|
| 39 |
|
|
|
| 40 |
|
|
///////////////////////////////////////////////////////////////////////////////
|
| 41 |
|
|
// Company: M. A. Morris & Associates
|
| 42 |
|
|
// Engineer: Michael A. Morris
|
| 43 |
|
|
//
|
| 44 |
|
|
// Create Date: 07:33 05/10/2008
|
| 45 |
3 |
MichaelA |
// Design Name: Synchronous Serial Peripheral (SSP) Interface UART
|
| 46 |
|
|
// Module Name: ../VerilogCoponentsLib/SSP_UART/SSPx_Slv.v
|
| 47 |
|
|
// Project Name: Verilog Components Library
|
| 48 |
|
|
// Target Devices: XC3S50A-4VQG100I, XC3S20A-4VQG100I, XC3S700AN-4FFG484I
|
| 49 |
2 |
MichaelA |
// Tool versions: ISE 10.1i SP3
|
| 50 |
|
|
//
|
| 51 |
|
|
// Description:
|
| 52 |
|
|
//
|
| 53 |
|
|
// This module implements a full-duplex (Slave) SSP interface for 16-bit
|
| 54 |
|
|
// frames. In accordance to standard SPI practice, the module expects that
|
| 55 |
|
|
// data is shifted into it MSB first. The first three bits are address bits,
|
| 56 |
|
|
// the fourth bit is a command (WnR) bit which determines the operations to
|
| 57 |
|
|
// be performed on the register, and the final twelve (12) bits are data bits.
|
| 58 |
|
|
//
|
| 59 |
|
|
// Dependencies: None
|
| 60 |
|
|
//
|
| 61 |
|
|
// Revision History:
|
| 62 |
|
|
//
|
| 63 |
|
|
// 0.01 08E10 MAM File Created
|
| 64 |
|
|
//
|
| 65 |
|
|
// 1.00 08E10 MAM Initial Release
|
| 66 |
|
|
//
|
| 67 |
|
|
// 1.10 08G24 MAM Modified the interface to operate with registered
|
| 68 |
|
|
// shift register data to eliminate transitions on
|
| 69 |
|
|
// MISO after risisng edge of SCK when input register
|
| 70 |
|
|
// written. Register RA[3:0] during fourth clock, and
|
| 71 |
|
|
// register DO[11:0] on falling edge of SCK after RA
|
| 72 |
|
|
// registered. This holds output data constant for the
|
| 73 |
|
|
// entire shift cycle.
|
| 74 |
|
|
//
|
| 75 |
|
|
// 1.11 11B01 MAM Corrected #1 delay statement placement in register
|
| 76 |
|
|
//
|
| 77 |
|
|
// 2.00 11B06 MAM Modified the interface to separate RA[3:1] and
|
| 78 |
|
|
// RA[0] into RA[2:0] address port and a WnR command
|
| 79 |
|
|
// port. This makes the operation of the SSP/SPI I/F
|
| 80 |
|
|
// more clear.
|
| 81 |
|
|
//
|
| 82 |
3 |
MichaelA |
// 2.10 13G06 MAM Changed the asynchronous reset generated by ~SSEL.
|
| 83 |
|
|
// Previously, a number of internal circuits were
|
| 84 |
|
|
// reset asynchronously on system reset, Rst, or ~SSEL.
|
| 85 |
|
|
// Added a FF, clocked on posedge SCK, that is asyn-
|
| 86 |
|
|
// chronously reset as before, but synchronously de-
|
| 87 |
|
|
// asserts on first rising edge of SCK. This signal,
|
| 88 |
|
|
// SSP_Rst, is used to asynchronously reset the same
|
| 89 |
|
|
// circuits as before: BC, EOC, and RDI. SPI Modes 0 or
|
| 90 |
|
|
// 3 are still supported.
|
| 91 |
|
|
//
|
| 92 |
|
|
// 2.20 14D25 MAM Encountered an issue whereby RA[2] held in reset
|
| 93 |
|
|
// after SSEL deasserted and then reasserted. The
|
| 94 |
|
|
// asynchronous reset on the signal SSP_Rst, a FF
|
| 95 |
|
|
// clocked on the falling edge of SCK, was changed to
|
| 96 |
|
|
// the combinatorial signal Rst_SSP. Rst_SSP is the
|
| 97 |
|
|
// source of the asynchronous reset of the SSP_Rst FF.
|
| 98 |
|
|
// The additional delay in the SSP_Rst signal caused
|
| 99 |
|
|
// RA[2] to be kept in reset at the start of a new
|
| 100 |
|
|
// SSP transfer cycle. Also added two additional CE
|
| 101 |
|
|
// signals while tracking down this issue: CE_RA and
|
| 102 |
|
|
// CE_WnR. They were previously driven directly by the
|
| 103 |
|
|
// bit counter.
|
| 104 |
|
|
//
|
| 105 |
2 |
MichaelA |
// Additional Comments:
|
| 106 |
|
|
//
|
| 107 |
3 |
MichaelA |
////////////////////////////////////////////////////////////////////////////////
|
| 108 |
2 |
MichaelA |
|
| 109 |
|
|
module SSPx_Slv(
|
| 110 |
|
|
input Rst, // System Reset
|
| 111 |
|
|
//
|
| 112 |
|
|
input SSEL, // Slave Select
|
| 113 |
|
|
input SCK, // Shift Clock
|
| 114 |
|
|
input MOSI, // Master Out, Slave In: Serial Data In
|
| 115 |
|
|
output reg MISO, // Master In, Slave Out: Serial Data Out
|
| 116 |
|
|
//
|
| 117 |
|
|
output reg [2:0] RA, // SSP Register Address output
|
| 118 |
|
|
output reg WnR, // SSP Command: 1 - Write, 0 - Read
|
| 119 |
|
|
output En, // SSP Enable - asserted during field
|
| 120 |
|
|
output reg EOC, // SSP End of Cycle - asserted on last bit of frame
|
| 121 |
|
|
output reg [11:0] DI, // Input shift register output
|
| 122 |
|
|
input [11:0] DO, // Output shift register input
|
| 123 |
|
|
//
|
| 124 |
|
|
output reg [3:0] BC // Bit Count, 0 - MSB; 15 - LSB
|
| 125 |
|
|
);
|
| 126 |
|
|
|
| 127 |
|
|
///////////////////////////////////////////////////////////////////////////////
|
| 128 |
|
|
//
|
| 129 |
|
|
// Local Declarations
|
| 130 |
|
|
//
|
| 131 |
|
|
|
| 132 |
|
|
reg [15:1] RDI; // Serial Input Shift Register
|
| 133 |
|
|
reg [11:0] rDO; // output data register
|
| 134 |
|
|
|
| 135 |
3 |
MichaelA |
reg SSP_Rst;
|
| 136 |
|
|
|
| 137 |
2 |
MichaelA |
///////////////////////////////////////////////////////////////////////////////
|
| 138 |
|
|
//
|
| 139 |
|
|
// Implementation
|
| 140 |
|
|
//
|
| 141 |
|
|
|
| 142 |
|
|
// Module Reset - asynchronous because SCK not continuous
|
| 143 |
|
|
|
| 144 |
|
|
assign Rst_SSP = (Rst | ~SSEL);
|
| 145 |
|
|
|
| 146 |
3 |
MichaelA |
always @(posedge SCK or posedge Rst_SSP)
|
| 147 |
|
|
begin
|
| 148 |
|
|
if(Rst_SSP)
|
| 149 |
|
|
SSP_Rst <= #1 ~0;
|
| 150 |
|
|
else
|
| 151 |
|
|
SSP_Rst <= #1 0;
|
| 152 |
|
|
end
|
| 153 |
|
|
|
| 154 |
2 |
MichaelA |
// Bit Counter, count from 0 to 15
|
| 155 |
|
|
// Clock on negedge SCK to align MISO in bit cell
|
| 156 |
|
|
|
| 157 |
3 |
MichaelA |
always @(negedge SCK or posedge SSP_Rst)
|
| 158 |
2 |
MichaelA |
begin
|
| 159 |
3 |
MichaelA |
if(SSP_Rst)
|
| 160 |
2 |
MichaelA |
BC <= #1 4'd0;
|
| 161 |
|
|
else
|
| 162 |
|
|
BC <= #1 (BC + 1);
|
| 163 |
|
|
end
|
| 164 |
|
|
|
| 165 |
|
|
// End-Of-Cycle, asserted during last bit of transfer (bit 15)
|
| 166 |
|
|
// Clock on negedge SCK to center rising edge in bit cell
|
| 167 |
|
|
|
| 168 |
3 |
MichaelA |
always @(negedge SCK or posedge SSP_Rst)
|
| 169 |
2 |
MichaelA |
begin
|
| 170 |
3 |
MichaelA |
if(SSP_Rst)
|
| 171 |
2 |
MichaelA |
EOC <= #1 1'b0;
|
| 172 |
|
|
else
|
| 173 |
|
|
EOC <= #1 (BC == 14);
|
| 174 |
|
|
end
|
| 175 |
|
|
|
| 176 |
|
|
// Generate SSP Enable, require four bits for internal addressing
|
| 177 |
|
|
|
| 178 |
|
|
assign En = BC[3] | BC[2];
|
| 179 |
|
|
|
| 180 |
|
|
// Load MOSI into RDI using BC to select the active register
|
| 181 |
|
|
// Use posedge SCK to sample in middle of bit cell
|
| 182 |
|
|
|
| 183 |
|
|
always @(posedge SCK or posedge Rst_SSP)
|
| 184 |
|
|
begin
|
| 185 |
|
|
if(Rst_SSP)
|
| 186 |
|
|
RDI <= #1 15'b0;
|
| 187 |
|
|
else
|
| 188 |
|
|
case(BC)
|
| 189 |
3 |
MichaelA |
4'b0000 : RDI[15] <= #1 MOSI;
|
| 190 |
|
|
4'b0001 : RDI[14] <= #1 MOSI;
|
| 191 |
|
|
4'b0010 : RDI[13] <= #1 MOSI;
|
| 192 |
|
|
4'b0011 : RDI[12] <= #1 MOSI;
|
| 193 |
|
|
4'b0100 : RDI[11] <= #1 MOSI;
|
| 194 |
|
|
4'b0101 : RDI[10] <= #1 MOSI;
|
| 195 |
|
|
4'b0110 : RDI[ 9] <= #1 MOSI;
|
| 196 |
|
|
4'b0111 : RDI[ 8] <= #1 MOSI;
|
| 197 |
|
|
4'b1000 : RDI[ 7] <= #1 MOSI;
|
| 198 |
|
|
4'b1001 : RDI[ 6] <= #1 MOSI;
|
| 199 |
|
|
4'b1010 : RDI[ 5] <= #1 MOSI;
|
| 200 |
|
|
4'b1011 : RDI[ 4] <= #1 MOSI;
|
| 201 |
|
|
4'b1100 : RDI[ 3] <= #1 MOSI;
|
| 202 |
|
|
4'b1101 : RDI[ 2] <= #1 MOSI;
|
| 203 |
|
|
4'b1110 : RDI[ 1] <= #1 MOSI;
|
| 204 |
|
|
default : RDI <= #1 RDI;
|
| 205 |
2 |
MichaelA |
endcase
|
| 206 |
|
|
end
|
| 207 |
|
|
|
| 208 |
|
|
// Assign RA, WnR, and DI bus from RDI and MOSI
|
| 209 |
|
|
|
| 210 |
3 |
MichaelA |
assign CE_RA = (BC == 2);
|
| 211 |
2 |
MichaelA |
|
| 212 |
3 |
MichaelA |
always @(negedge SCK or posedge Rst_SSP)
|
| 213 |
2 |
MichaelA |
begin
|
| 214 |
3 |
MichaelA |
if(Rst_SSP)
|
| 215 |
2 |
MichaelA |
RA <= #1 0;
|
| 216 |
3 |
MichaelA |
else if(CE_RA)
|
| 217 |
2 |
MichaelA |
RA <= #1 RDI[15:13];
|
| 218 |
|
|
end
|
| 219 |
|
|
|
| 220 |
3 |
MichaelA |
assign CE_WnR = (BC == 3);
|
| 221 |
|
|
|
| 222 |
|
|
always @(negedge SCK or posedge Rst_SSP)
|
| 223 |
2 |
MichaelA |
begin
|
| 224 |
3 |
MichaelA |
if(Rst_SSP)
|
| 225 |
2 |
MichaelA |
WnR <= #1 0;
|
| 226 |
|
|
else if(EOC)
|
| 227 |
|
|
WnR <= #1 0;
|
| 228 |
3 |
MichaelA |
else if(CE_WnR)
|
| 229 |
2 |
MichaelA |
WnR <= #1 RDI[12];
|
| 230 |
|
|
end
|
| 231 |
|
|
|
| 232 |
3 |
MichaelA |
always @(*) DI <= {RDI[11:1], MOSI};
|
| 233 |
2 |
MichaelA |
|
| 234 |
|
|
always @(negedge SCK or posedge Rst)
|
| 235 |
|
|
begin
|
| 236 |
|
|
if(Rst)
|
| 237 |
|
|
rDO <= #1 0;
|
| 238 |
|
|
else if(BC == 3)
|
| 239 |
|
|
rDO <= #1 DO;
|
| 240 |
|
|
end
|
| 241 |
|
|
|
| 242 |
|
|
// Generate MISO: multiplex MOSI and DO using En and BC
|
| 243 |
|
|
|
| 244 |
3 |
MichaelA |
always @(*)
|
| 245 |
2 |
MichaelA |
begin
|
| 246 |
|
|
case(BC)
|
| 247 |
|
|
4'b0000 : MISO <= MOSI;
|
| 248 |
|
|
4'b0001 : MISO <= MOSI;
|
| 249 |
|
|
4'b0010 : MISO <= MOSI;
|
| 250 |
|
|
4'b0011 : MISO <= MOSI;
|
| 251 |
|
|
4'b0100 : MISO <= rDO[11];
|
| 252 |
|
|
4'b0101 : MISO <= rDO[10];
|
| 253 |
|
|
4'b0110 : MISO <= rDO[ 9];
|
| 254 |
|
|
4'b0111 : MISO <= rDO[ 8];
|
| 255 |
|
|
4'b1000 : MISO <= rDO[ 7];
|
| 256 |
|
|
4'b1001 : MISO <= rDO[ 6];
|
| 257 |
|
|
4'b1010 : MISO <= rDO[ 5];
|
| 258 |
|
|
4'b1011 : MISO <= rDO[ 4];
|
| 259 |
|
|
4'b1100 : MISO <= rDO[ 3];
|
| 260 |
|
|
4'b1101 : MISO <= rDO[ 2];
|
| 261 |
|
|
4'b1110 : MISO <= rDO[ 1];
|
| 262 |
|
|
4'b1111 : MISO <= rDO[ 0];
|
| 263 |
|
|
endcase
|
| 264 |
|
|
end
|
| 265 |
|
|
|
| 266 |
|
|
endmodule
|