1
0
mirror of https://github.com/aolofsson/oh.git synced 2025-02-07 06:44:09 +08:00
oh/spi/hdl/spi_master_io.v
Andreas Olofsson 63b56d9ec9 Adding command reg to spi master
- Makes the emode more efficient, only setup command once
2016-03-10 14:20:25 -05:00

219 lines
7.7 KiB
Verilog

//#############################################################################
//# Purpose: SPI slave IO and statemachine #
//#############################################################################
//# Author: Andreas Olofsson #
//# License: MIT (see below) #
//#############################################################################
module spi_master_io(/*AUTOARG*/
// Outputs
spi_state, fifo_read, rx_data, rx_access, sclk, mosi, ss,
// Inputs
clk, nreset, spi_en, cpol, cpha, lsbfirst, clkdiv_reg, cmd_reg,
emode, fifo_dout, fifo_empty, miso
);
//#################################
//# INTERFACE
//#################################
//parameters
parameter REGS = 16; // total regs (16/32/64)
parameter AW = 32; // address width
localparam PW = (2*AW+40); // packet width
//clk, reset, cfg
input clk; // core clock
input nreset; // async active low reset
//cfg
input spi_en; // spi enable
input cpol; // cpol
input cpha; // cpha
input lsbfirst; // send lsbfirst
input [7:0] clkdiv_reg; // baudrate
input [7:0] cmd_reg;
input emode;
output [1:0] spi_state; // current spi tx state
//data to transmit
input [7:0] fifo_dout; // data payload
input fifo_empty; //
output fifo_read; // read new byte
//receive data (for sregs)
output [63:0] rx_data; // rx data
output rx_access; // transfer done
//IO interface
output sclk; // spi clock
output mosi; // slave input
output ss; // slave select
input miso; // slave output
reg [1:0] spi_state;
reg [2:0] bit_count;
reg fifo_empty_reg;
wire [7:0] data_out;
/*AUTOWIRE*/
// Beginning of automatic wires (for undeclared instantiated-module outputs)
wire clkout; // From oh_clockdiv of oh_clockdiv.v
wire period_match; // From oh_clockdiv of oh_clockdiv.v
wire phase_match; // From oh_clockdiv of oh_clockdiv.v
// End of automatics
//#################################
//# CLOCK GENERATOR
//#################################
oh_clockdiv #(.DW(8))
oh_clockdiv (.clkdiv (clkdiv_reg[2:0]),
.en (1'b1),
/*AUTOINST*/
// Outputs
.period_match (period_match),
.phase_match (phase_match),
.clkout (clkout),
// Inputs
.clk (clk),
.nreset (nreset));
//#################################
//# STATE MACHINE
//#################################
`define SPI_IDLE 2'b00 // set ss to 1
`define SPI_SETUP 2'b01 // setup time
`define SPI_DATA 2'b10 // send data
`define SPI_HOLD 2'b11 // hold time
always @ (posedge clk or negedge nreset)
if(!nreset)
spi_state[1:0] <= `SPI_IDLE;
else if(period_match)
case (spi_state[1:0])
`SPI_IDLE :
spi_state[1:0] <= ~fifo_empty ? `SPI_SETUP : `SPI_IDLE;
`SPI_SETUP :
spi_state[1:0] <=`SPI_DATA;
`SPI_DATA :
begin
spi_state[1:0] <= fifo_empty_reg & byte_done ? `SPI_HOLD : `SPI_DATA;
fifo_empty_reg <= fifo_empty;
end
`SPI_HOLD :
spi_state[1:0] <= `SPI_IDLE;
endcase // case (spi_state[1:0])
//Bit counter
always @ (posedge clk)
if(spi_state[1:0]==`SPI_IDLE)
bit_count[2:0] <= 'b0;
else if(period_match)
bit_count[2:0] <= bit_count[2:0] + 1'b1;
//byte done indicator
assign byte_done = (bit_count[2:0]==3'b000);
//read fifo on phase match (due to one cycle pipeline latency
assign fifo_read = ((spi_state[1:0]==`SPI_IDLE) & phase_match ) |
((spi_state[1:0]==`SPI_DATA) & phase_match & byte_done);
//load once per byte
assign load_byte = period_match & byte_done & (spi_state[1:0]!=`SPI_IDLE);
//shift on every clock cycle while in datamode
assign shift = period_match & (spi_state[1:0]==`SPI_DATA);
//#################################
//# CHIP SELECT
//#################################
assign ss = (spi_state[1:0]==`SPI_IDLE);
//#################################
//# DRIVE OUTPUT CLOCK
//#################################
assign sclk = clkout & (spi_state[1:0]==`SPI_DATA);
//#################################
//# TX SHIFT REGISTER
//#################################
assign data_out[7:0] = (emode & spi_state[1:0]==`SPI_IDLE) ? cmd_reg[7:0] :
fifo_dout[7:0];
oh_par2ser #(.PW(8),
.SW(1))
par2ser (// Outputs
.dout (mosi), // serial output
.access_out (),
.wait_out (),
// Inputs
.clk (clk),
.nreset (nreset), // async active low reset
.din (data_out[7:0] ), // 8 bit data from fifo
.shift (shift), // shift on neg edge
.datasize (3'b111), // 8 bits
.load (load_byte), // load data from fifo
.lsbfirst (lsbfirst), // serializer direction
.fill (1'b0), // fill with slave data
.wait_in (1'b0) // no wait
);
//#################################
//# RX SHIFT REGISTER
//#################################
//generate access pulse at rise of ss
oh_rise2pulse
pulse (.out (rx_access),
.clk (clk),
.in (ss));
oh_ser2par #(.PW(64))
ser2par (//output
.dout (rx_data[63:0]), // parallel data out
//inputs
.din (miso), // serial data in
.clk (clk), // shift clk
.lsbfirst (lsbfirst), // shift direction
.shift (shift)); // shift data
endmodule // spi_slave_io
// Local Variables:
// verilog-library-directories:("." "../../common/hdl" "../../emesh/hdl")
// End:
///////////////////////////////////////////////////////////////////////////////
// The MIT License (MIT) //
// //
// Copyright (c) 2015-2016, Adapteva, Inc. //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software") //
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included //
// in all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS //
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF //
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. //
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY //
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT //
// OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR //
// THE USE OR OTHER DEALINGS IN THE SOFTWARE. //
// //
///////////////////////////////////////////////////////////////////////////////