blob: bb1a8b47ed6273e4d55220f9af29e05f86e7547c [file] [log] [blame]
//////////////////////////////////////////////////////////////////////
//// ////
//// 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