////////////////////////////////////////////////////////////////////// | |
//// //// | |
//// Single SPI Master Interface Module //// | |
//// //// | |
//// This file is part of the riscduino cores project //// | |
//// https://github.com/dineshannayya/riscduino.git //// | |
//// //// | |
//// Description //// | |
//// SPI Clock Gen module //// | |
//// //// | |
//// To Do: //// | |
//// nothing //// | |
//// //// | |
//// Author(s): //// | |
//// - Dinesh Annayya, dinesha@opencores.org //// | |
//// //// | |
//// Revision : //// | |
//// V.0 - 06 Oct 2021 //// | |
//// Initial SpI Module picked from //// | |
//// http://www.opencores.org/cores/turbo8051/ //// | |
//// //// | |
////////////////////////////////////////////////////////////////////// | |
//// //// | |
//// Copyright (C) 2000 Authors and OPENCORES.ORG //// | |
//// //// | |
//// 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 //// | |
//// //// | |
////////////////////////////////////////////////////////////////////// | |
/********************************************************************* | |
Design Implementation Reference | |
Reference: https://www.allaboutcircuits.com/technical-articles/spi-serial-peripheral-interface/ | |
*********************************************************************/ | |
module sspim_clkgen | |
( | |
input logic clk, | |
input logic reset_n, | |
input logic cfg_op_req, | |
input logic cfg_cpol, // CPOL : clock polarity CPOL :0- Clock Idle state low, 1 - Clock idle state high | |
input logic cfg_cpha, // CPHA : Clock Phase | |
input logic [5:0] cfg_sck_period, | |
input logic sck_active, | |
output logic sck_int, // SCLK | |
output logic shift, // Data Shift Phase | |
output logic sample, // Data Sample Phase | |
output logic sck_ne, // sclk negative phase | |
output logic sck_pe // sclk positive phase | |
); | |
//************************************************************************* | |
logic [5:0] clk_cnt; | |
logic [5:0] sck_half_period; | |
assign sck_ne = (cfg_cpha == 0) ? shift : sample; | |
assign sck_pe = (cfg_cpha == 0) ? sample : shift; | |
assign sck_half_period = {1'b0, cfg_sck_period[5:1]}; | |
// The first transition on the sck_toggle happens one SCK period | |
// after op_en or boot_en is asserted | |
always @(posedge clk or negedge reset_n) begin | |
if(!reset_n) begin | |
shift <= 1'b0; | |
sample <= 1'b0; | |
clk_cnt <= 6'h0; | |
sck_int <= 1'b1; | |
end // if (!reset_n) | |
else | |
begin | |
if(cfg_op_req) | |
begin | |
// clock counter | |
if(clk_cnt == cfg_sck_period) begin | |
clk_cnt <= 'h0; | |
end else begin | |
clk_cnt <= clk_cnt + 1'b1; | |
end | |
if(clk_cnt == sck_half_period) | |
begin | |
shift <= 1'b1; | |
sample <= 1'b0; | |
end // if (clk_cnt == sck_half_period) | |
else | |
begin | |
if(clk_cnt == cfg_sck_period) | |
begin | |
shift <= 1'b0; | |
sample <= 1'b1; | |
end // if (clk_cnt == cfg_sck_period) | |
else | |
begin | |
shift <= 1'b0; | |
sample <= 1'b0; | |
end // else: !if(clk_cnt == cfg_sck_period) | |
end // else: !if(clk_cnt == sck_half_period) | |
end // if (op_en) | |
else | |
begin | |
clk_cnt <= 6'h0; | |
shift <= 1'b0; | |
sample <= 1'b0; | |
end // else: !if(op_en) | |
if(sck_active) begin | |
if(sck_ne) sck_int <= 0; | |
else if(sck_pe) sck_int <= 1; | |
end else if (cfg_cpol == 0) begin // CPOL :0- Clock Idle state low | |
sck_int <= 0; | |
end else begin // CPOL :1- Clock Idle state High | |
sck_int <= 1; | |
end | |
end // else: !if(!reset_n) | |
end // always @ (posedge clk or negedge reset_n) | |
endmodule |