OpenCores
URL https://opencores.org/ocsvn/tiny_spi/tiny_spi/trunk

Subversion Repositories tiny_spi

[/] [tiny_spi/] [trunk/] [rtl/] [verilog/] [tiny_spi.v] - Rev 2

Compare with Previous | Blame | View Log

//////////////////////////////////////////////////////////////////////
////                                                              ////
////  tiny_spi.v                                                  ////
////                                                              ////
////  This file is part of the TINY SPI IP core project           ////
////  http://www.opencores.org/projects/tiny_spi/                 ////
////                                                              ////
////  Author(s):                                                  ////
////      - Thomas Chou <thomas@wytron.com.tw>                    ////
////                                                              ////
////  All additional information is avaliable in the README       ////
////  file.                                                       ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
////                                                              ////
//// Copyright (C) 2010 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                     ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
 
module tiny_spi(
   // system
   input	  rst_i,
   input	  clk_i,
   // memory mapped
   input	  stb_i,
   input	  we_i,
   output [31:0]  dat_o,
   input [31:0]   dat_i,
   output	  int_o,
   input [2:0]	  adr_i,
   input 	  cyc_i, // comment out for avalon
   output 	  ack_o, // comment out for avalon
 
   // spi
   output	  MOSI,
   output	  SCLK,
   input	  MISO
   );
 
   parameter BAUD_WIDTH = 8;
   parameter BAUD_DIV = 0;
   parameter SPI_MODE = 0;
   parameter BC_WIDTH = 3;
   parameter DIV_WIDTH = BAUD_DIV ? $clog2(BAUD_DIV / 2 - 1) : BAUD_WIDTH;
 
 
   reg [7:0]	  sr8, bb8;
   wire [7:0]	  sr8_sf;
   reg [BC_WIDTH - 1:0]		bc, bc_next;
   reg [DIV_WIDTH - 1:0]	ccr;
   reg [DIV_WIDTH - 1:0]	cc, cc_next;
   wire		  misod;
   wire		  cstb, wstb, bstb, istb;
   reg		  sck;
   reg		  sf, ld;
   reg		  bba;   // buffer flag
   reg		  txren, txeen;
   wire 	  txr, txe;
   wire		  cpol, cpha;
   reg		  cpolr, cphar;
   wire 	  wr;
   // wire 	  cyc_i; // comment out for wishbone
   // wire 	  ack_o; // comment out for wishbone
   // assign cyc_i = 1'b1;  // comment out for wishbone
   assign ack_o = stb_i & cyc_i; // zero wait
   assign wr = stb_i & cyc_i & we_i & ack_o;
   assign wstb = wr & (adr_i == 1);
   assign istb = wr & (adr_i == 2);
   assign cstb = wr & (adr_i == 3);
   assign bstb = wr & (adr_i == 4);
   assign sr8_sf = { sr8[6:0],misod };
   assign dat_o =
		      (sr8 & {8{(adr_i == 0)}})
		    | (bb8 & {8{(adr_i == 1)}})
		    | ({ txr, txe } & {8{(adr_i == 2)}})
		      ;
 
   parameter
     IDLE = 0,
     PHASE1 = 1,
     PHASE2 = 2
     ;
 
   reg [1:0] spi_seq, spi_seq_next;
   always @(posedge clk_i or posedge rst_i)
     if (rst_i)
       spi_seq <= IDLE;
     else
       spi_seq <= spi_seq_next;
 
   always @(posedge clk_i)
     begin
	cc <= cc_next;
	bc <= bc_next;
     end
 
   always @(/*AS*/bba or bc or cc or ccr or cpha or cpol or spi_seq)
     begin
	sck = cpol;
	cc_next = BAUD_DIV ? (BAUD_DIV / 2 - 1) : ccr;
	bc_next = bc;
	ld = 1'b0;
	sf = 1'b0;
 
	case (spi_seq)
	  IDLE:
	    begin
	       if (bba)
		 begin
		    bc_next = 7;
		    ld = 1'b1;
		    spi_seq_next = PHASE2;
		 end
	       else
		 spi_seq_next = IDLE;
	    end
	  PHASE2:
	    begin
	       sck = (cpol ^ cpha);
	       if (cc == 0)
		 spi_seq_next = PHASE1;
	       else
		 begin
		    cc_next = cc - 1;
		    spi_seq_next = PHASE2;
		 end
	    end
	  PHASE1:
	    begin
	       sck = ~(cpol ^ cpha);
	       if (cc == 0)
		 begin
		    bc_next = bc -1;
		    sf = 1'b1;
		    if (bc == 0)
		      begin
			 if (bba)
			   begin
			      bc_next = 7;
			      ld = 1'b1;
			      spi_seq_next = PHASE2;
			   end
			 else
			   spi_seq_next = IDLE;
		      end
		    else
		      spi_seq_next = PHASE2;
		 end
	       else
		 begin
		    cc_next = cc - 1;
		    spi_seq_next = PHASE1;
		 end
	    end
	endcase
     end // always @ (...
 
   always @(posedge clk_i)
     begin
	if (cstb) // control reg
	  { cpolr, cphar } <= dat_i;
	else
	  { cpolr, cphar } <= { cpolr, cphar };
 
	if (istb) // irq enable reg
	  { txren, txeen } <= dat_i;
	else
	  { txren, txeen } <= { txren, txeen };
 
	if (bstb) // baud reg
	  ccr <= dat_i;
	else
	  ccr <= ccr;
 
	if (ld)   // shift reg
	  sr8 <= bb8;
	else if (sf)
	  sr8 <= sr8_sf;
	else
	  sr8 <= sr8;
 
	if (wstb) // buffer reg
	  bb8 <= dat_i;
	else if (ld)
	  bb8 <= (spi_seq == IDLE) ? sr8 : sr8_sf;
	else
	  bb8 <= bb8;
     end // always @ (posedge clk_i)
 
   always @(posedge clk_i or posedge rst_i)
     begin
	if (rst_i)
	  bba <= 1'b0;
	else if (wstb)
	  bba <= 1'b1;
	else if (ld)
	  bba <= 1'b0;
	else
	  bba <= bba;
     end
 
   assign { cpol, cpha } = ((SPI_MODE >= 0) & (SPI_MODE < 4)) ?
			   SPI_MODE : { cpolr, cphar };
   assign txe = (spi_seq == IDLE);
   assign txr = ~bba;
   assign int_o = (txr & txren) | (txe & txeen);
   assign SCLK = sck;
   assign MOSI = sr8[7];
   assign misod = MISO;
 
endmodule
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.