1
0
mirror of https://github.com/aolofsson/oh.git synced 2025-01-17 20:02:53 +08:00

Debugged most of SPI

-Changed to FIFO on TX path (cleaner)
-No good solution on RX with CDC since clock can stop, so you can't use an async fifo.
-Slave needs cleanup, rethink...
-Using commong par2ser and ser2par blocks
This commit is contained in:
Andreas Olofsson 2016-03-09 22:46:24 -05:00
parent ef790c1a59
commit 8c350eed91
10 changed files with 445 additions and 219 deletions

View File

@ -1,37 +1,75 @@
//#############################################################################
//# Purpose: Serial to Parallel Converter #
//#############################################################################
//# Author: Andreas Olofsson #
//# License: MIT (see below) #
//#############################################################################
//convert serial stream to parallel
module oh_ser2par (/*AUTOARG*/
// Outputs
dout,
// Inputs
clk, din, dout
clk, din, lsbfirst, shift
);
//###############################################################
//# Interface
//###############################################################
//###########################
//# INTERFACE
//###########################
input clk; //sampling clock
input din; //serial data
output [DW-1:0] dout; //parallel data
parameter DW = 64; //width of converter
parameter TYPE = "MSB"; //MSB first or LSB first
//###############################################################
// parameters
parameter PW = 64; // parallel packet width
parameter SW = 1; // serial packet width
localparam CW = $clog2(PW/SW); // serialization factor (for counter)
// reset, clk
input clk; // sampling clock
//data interface
input [SW-1:0] din; // serial data
output [PW-1:0] dout; // parallel data
// control interface
input lsbfirst; // lsb first order
input shift; // shift the shifter
//##############################
//# BODY
//###############################################################
reg [DW-1:0] dout;
generate
if(TYPE=="MSB")
begin
always @ (posedge clk)
dout[DW-1:0] = {dout[DW-2:0],din};
end
else
begin
always @ (posedge clk)
dout[DW-1:0] = {din,dout[DW-1:1]};
end
endgenerate
//##############################
reg [PW-1:0] dout;
reg [CW-1:0] count;
wire [PW-1:0] shiftdata;
always @ (posedge clk)
if(shift & lsbfirst)
dout[PW-1:0] <= {din[SW-1:0],dout[PW-1:SW]};
else if(shift)
dout[PW-1:0] <= {dout[PW-SW-1:0],din[SW-1:0]};
endmodule // oh_ser2par
///////////////////////////////////////////////////////////////////////////////
// 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. //
// //
///////////////////////////////////////////////////////////////////////////////

View File

@ -1,11 +1,14 @@
DEADBEEF_99999999_00000000_05_0010 //write gpio_oen
DEADBEEF_FFFFFFFF_00000008_05_0010 //write gpio_out
DEADBEEF_BBBBBBBB_00000010_05_0010 //write gpio_ien
DEADBEEF_CCCCCCCC_00000018_05_0010 //write gpio_in
DEADBEEF_11111111_00000020_05_0010 //write gpio_outand
DEADBEEF_22222222_00000028_05_0010 //write gpio_outorr
DEADBEEF_FFFFFFFF_00000030_05_0010 //write gpio_outxor
DEADBEEF_55555555_00000038_05_0010 //write gpio_irqmask
DEADBEEF_00000000_00000000_01_0000 //CONFIG (DEFAULT)
DEADBEEF_00000000_00000004_01_0000 //STATUS (CLEAR)
DEADBEEF_00000003_00000008_01_0020 //CLKDIV (BAUDRATE, DIVIDE by 8)
DEADBEEF_00000021_00000020_01_0000 //TX DATA (B0)
DEADBEEF_00000043_00000020_01_0000 //TX DATA (B1)
DEADBEEF_00000065_00000020_01_0000 //TX DATA (B2)
DEADBEEF_00000087_00000020_01_0000 //TX DATA (B3)

View File

@ -1,5 +1,5 @@
//#############################################################################
//# Purpose: SPI top (configuravbe as master or slave) #
//# Purpose: SPI top (configurable as master or slave) #
//#############################################################################
//# Author: Andreas Olofsson #
//# License: MIT (see below) #

View File

@ -13,6 +13,7 @@ module spi_master(/*AUTOARG*/
);
//parameters
parameter DEPTH = 16; // fifo depth
parameter REGS = 16; // total regs
parameter AW = 32; // addresss width
localparam PW = (2*AW+40); // packet width
@ -43,28 +44,32 @@ module spi_master(/*AUTOARG*/
/*AUTOWIRE*/
// Beginning of automatic wires (for undeclared instantiated-module outputs)
wire [7:0] clkdiv_reg; // From spi_master_regs of spi_master_regs.v
wire [7:0] cmd_reg; // From spi_master_regs of spi_master_regs.v
wire cpha; // From spi_master_regs of spi_master_regs.v
wire cpol; // From spi_master_regs of spi_master_regs.v
wire [7:0] psize_reg; // From spi_master_regs of spi_master_regs.v
wire emode; // From spi_master_regs of spi_master_regs.v
wire [7:0] fifo_dout; // From spi_master_fifo of spi_master_fifo.v
wire fifo_empty; // From spi_master_fifo of spi_master_fifo.v
wire fifo_read; // From spi_master_io of spi_master_io.v
wire lsbfirst; // From spi_master_regs of spi_master_regs.v
wire rx_access; // From spi_master_io of spi_master_io.v
wire [7:0] rx_data; // From spi_master_io of spi_master_io.v
wire spi_en; // From spi_master_regs of spi_master_regs.v
wire [2:0] spi_state; // From spi_master_io of spi_master_io.v
wire tx_access; // From spi_master_regs of spi_master_regs.v
wire [PW-1:0] tx_data; // From spi_master_regs of spi_master_regs.v
wire [1:0] spi_state; // From spi_master_io of spi_master_io.v
// End of automatics
//#####################################################
//# Master control registers
//#####################################################
spi_master_regs #(.AW(AW))
spi_master_regs (/*AUTOINST*/
// Outputs
.tx_access (tx_access),
.cmd_reg (cmd_reg[7:0]),
.tx_data (tx_data[PW-1:0]),
.cpol (cpol),
.cpha (cpha),
.lsbfirst (lsbfirst),
.emode (emode),
.spi_en (spi_en),
.psize_reg (psize_reg[7:0]),
.clkdiv_reg (clkdiv_reg[7:0]),
.wait_out (wait_out),
.access_out (access_out),
@ -74,16 +79,44 @@ module spi_master(/*AUTOARG*/
.nreset (nreset),
.rx_data (rx_data[PW-1:0]),
.rx_access (rx_access),
.spi_state (spi_state[2:0]),
.spi_state (spi_state[1:0]),
.access_in (access_in),
.packet_in (packet_in[PW-1:0]),
.wait_in (wait_in));
spi_master_io #(.AW(AW)
)
//#####################################################
//# Transmit FIFO (SPI_TX)
//#####################################################
/* spi_master_fifo AUTO_TEMPLATE (.fifo_dout (fifo_dout[7:0]),
);
*/
spi_master_fifo #(.AW(AW),
.DEPTH(DEPTH))
spi_master_fifo(/*AUTOINST*/
// Outputs
.wait_out (wait_out),
.fifo_empty (fifo_empty),
.fifo_dout (fifo_dout[7:0]), // Templated
// Inputs
.clk (clk),
.nreset (nreset),
.emode (emode),
.access_in (access_in),
.packet_in (packet_in[PW-1:0]),
.fifo_read (fifo_read));
//#####################################################
//# SPI IO (8 bit)
//#####################################################
spi_master_io #(.AW(AW))
spi_master_io (/*AUTOINST*/
// Outputs
.spi_state (spi_state[2:0]),
.spi_state (spi_state[1:0]),
.fifo_read (fifo_read),
.rx_data (rx_data[7:0]),
.rx_access (rx_access),
.sclk (sclk),
@ -95,16 +128,14 @@ module spi_master(/*AUTOARG*/
.spi_en (spi_en),
.cpol (cpol),
.cpha (cpha),
.lsbfirst (lsbfirst),
.clkdiv_reg (clkdiv_reg[7:0]),
.psize_reg (psize_reg[7:0]),
.cmd_reg (cmd_reg[7:0]),
.tx_data (tx_data[PW-1:0]),
.tx_access (tx_access),
.fifo_dout (fifo_dout[7:0]),
.fifo_empty (fifo_empty),
.miso (miso));
endmodule // spi_slave
endmodule // spi_master
//////////////////////////////////////////////////////////////////////////////
// The MIT License (MIT) //

133
spi/hdl/spi_master_fifo.v Normal file
View File

@ -0,0 +1,133 @@
`include "spi_regmap.vh"
module spi_master_fifo (/*AUTOARG*/
// Outputs
wait_out, fifo_empty, fifo_dout,
// Inputs
clk, nreset, emode, access_in, packet_in, fifo_read
);
//#####################################################################
//# INTERFACE
//#####################################################################
//parameters
parameter DEPTH = 16; // fifo entries
parameter AW = 32; // architecture address width
parameter SW = 8; // output packet width
localparam PW = 2*AW+40; // input packet width
localparam FAW = $clog2(DEPTH); // fifo address width
localparam SRW = $clog2(PW/SW); // serializer cycle count width
//clk,reset, cfg
input clk; // clk
input nreset; // async active low reset
input emode; // epiphany transfer mode
// Incoming interface
input access_in; // access by core
input [PW-1:0] packet_in;
output wait_out;
// IO interface
input fifo_read;
output fifo_empty;
output [SW-1:0] fifo_dout;
//##################################
//# BODY
//##################################
wire [SRW-1:0] datasize;
wire [PW-1:0] tx_data;
wire [SW-1:0] fifo_din;
/*AUTOWIRE*/
// Beginning of automatic wires (for undeclared instantiated-module outputs)
wire [4:0] ctrlmode_in; // From p2e of packet2emesh.v
wire [AW-1:0] data_in; // From p2e of packet2emesh.v
wire [1:0] datamode_in; // From p2e of packet2emesh.v
wire [AW-1:0] dstaddr_in; // From p2e of packet2emesh.v
wire [AW-1:0] srcaddr_in; // From p2e of packet2emesh.v
wire write_in; // From p2e of packet2emesh.v
// End of automatics
//##################################
//# DECODE
//###################################
packet2emesh p2e (/*AUTOINST*/
// Outputs
.write_in (write_in),
.datamode_in (datamode_in[1:0]),
.ctrlmode_in (ctrlmode_in[4:0]),
.dstaddr_in (dstaddr_in[AW-1:0]),
.srcaddr_in (srcaddr_in[AW-1:0]),
.data_in (data_in[AW-1:0]),
// Inputs
.packet_in (packet_in[PW-1:0]));
assign datasize[SRW-1:0] = emode ? (PW/SW) :
(1<<datamode_in[1:0]);
assign tx_write = write_in &
access_in &
(dstaddr_in[7:2]==`SPI_TX);
//epiphany mode works in msb or lsb mode
//data mode up to 64 bits works in lsb mode
//for msb transfer, use byte writes only
assign tx_data[PW-1:0] = emode ? packet_in[PW-1:0] :
{{(40){1'b0}},
srcaddr_in[AW-1:0],
data_in[AW-1:0]};
//##################################
//# FIFO PACKET WRITE
//##################################
oh_par2ser #(.PW(PW),
.SW(SW))
oh_par2ser (// Outputs
.dout (fifo_din[SW-1:0]),
.access_out (fifo_wr),
.wait_out (wait_out),
// Inputs
.clk (clk),
.nreset (nreset),
.din (tx_data[PW-1:0]),
.shift (1'b1),
.datasize (datasize[SRW-1:0]),
.load (tx_write),
.lsbfirst (1'b1),
.fill (1'b0),
.wait_in (fifo_prog_full)
);
//##################################
//# FIFO
//###################################
oh_fifo_sync #(.DEPTH(DEPTH),
.DW(SW))
fifo(// Outputs
.dout (fifo_dout[7:0]),
.full (),
.prog_full (fifo_prog_full),
.empty (fifo_empty),
.rd_count (),
// Inputs
.clk (clk),
.nreset (nreset),
.din (fifo_din[7:0]),
.wr_en (fifo_wr),
.rd_en (fifo_read));
endmodule // spi_master_fifo
// Local Variables:
// verilog-library-directories:("." "../../common/hdl" "../../emesh/hdl")
// End:

View File

@ -7,10 +7,10 @@
module spi_master_io(/*AUTOARG*/
// Outputs
spi_state, rx_data, rx_access, sclk, mosi, ss,
spi_state, fifo_read, rx_data, rx_access, sclk, mosi, ss,
// Inputs
clk, nreset, spi_en, cpol, cpha, clkdiv_reg, psize_reg, cmd_reg,
tx_data, tx_access, miso
clk, nreset, spi_en, cpol, cpha, lsbfirst, clkdiv_reg, fifo_dout,
fifo_empty, miso
);
//#################################
@ -30,16 +30,16 @@ module spi_master_io(/*AUTOARG*/
input spi_en; // spi enable
input cpol; // cpol
input cpha; // cpha
input lsbfirst; // send lsbfirst
input [7:0] clkdiv_reg; // baudrate
input [7:0] psize_reg; // packetsize
output [2:0] spi_state; // current spi tx state
output [1:0] spi_state; // current spi tx state
//data to transmit
input [7:0] cmd_reg; // 8 bit command
input [PW-1:0] tx_data; // data payload
input tx_access; // start transfer
input [7:0] fifo_dout; // data payload
input fifo_empty; //
output fifo_read; // read new byte
//receive data
//receive data (for sregs)
output [7:0] rx_data; // rx data
output rx_access; // rx ready pulse
@ -50,48 +50,60 @@ module spi_master_io(/*AUTOARG*/
input miso; // slave output
reg [7:0] baud_counter = 'b0; //works b/c of free running counter!
reg [2:0] spi_state;
reg [PW-1:0] tx_shiftreg;
reg [7:0] bit_count;
reg [1:0] spi_state;
reg [2:0] bit_count;
reg sclk;
//#################################
//# STATE MACHINE
//#################################
`define SPI_IDLE 3'b000 // clear ss
`define SPI_SETUP 3'b001 // load tx
`define SPI_CMD 3'b010 // send command
`define SPI_DATA 3'b011 // send packet
`define SPI_FINISH 3'b100 // raise
`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
//state machine
//NOTE: tx access pulse is lost if there is ongoing transactio (makes sense..)
always @ (posedge clk or negedge nreset)
if(!nreset)
spi_state[1:0] <= `SPI_IDLE;
else if(baud_match)
case (spi_state[1:0])
`SPI_IDLE :
spi_state[2:0] <= tx_access ? `SPI_CMD : `SPI_IDLE;
spi_state[1:0] <= ~fifo_empty ? `SPI_SETUP : `SPI_IDLE;
`SPI_SETUP :
spi_state[2:0] <=`SPI_CMD;
`SPI_CMD :
spi_state[2:0] <= byte_done ? `SPI_DATA : `SPI_CMD;
spi_state[1:0] <=`SPI_DATA;
`SPI_DATA :
spi_state[2:0] <= packet_done ? `SPI_FINISH : `SPI_DATA;
`SPI_FINISH :
spi_state[2:0] <= `SPI_IDLE;
endcase // case (spi_state[1:0])
always @ (posedge sclk)
if(spi_state[2:0]==`SPI_IDLE)
bit_count[7:0] <= 'b0;
spi_state[1:0] <= fifo_empty_reg & byte_done ? `SPI_HOLD : `SPI_DATA;
`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(baud_match)
bit_count[7:0] <= bit_count[7:0] + 1'b1;
bit_count[2:0] <= bit_count[2:0] + 1'b1;
assign byte_done = &bit_count[2:0];
assign byte_done = (bit_count[2:0]==3'b000);
assign packet_done = (bit_count[7:0]==psize_reg[7:0]);
assign fifo_read = ((spi_state[1:0]==`SPI_IDLE) & phase_match ) |
((spi_state[1:0]==`SPI_DATA) & phase_match & byte_done);
assign load_byte = baud_match & byte_done & (spi_state[1:0]!=`SPI_IDLE);
assign shift = baud_match & (spi_state[1:0]==`SPI_DATA);
//TODO: Ugly Fifo goes empty on one clk cycle, need to add hold time using baud match
//better solution?
reg fifo_empty_reg;
always @ (posedge clk)
if(baud_match)
fifo_empty_reg <= fifo_empty;
//#################################
//# BAUD COUNTER
@ -103,37 +115,79 @@ module spi_master_io(/*AUTOARG*/
else
baud_counter[7:0] <= baud_counter[7:0] + 1'b1;
assign baud_match = (baud_counter[7:0]==clkdiv_reg[7:0]);
assign phase_match = (baud_counter[7:0]==(clkdiv_reg[7:0]>>1));
assign baud_match = (baud_counter[7:0]==((1 << clkdiv_reg[7:0]) - 1'b1));
assign phase_match = (baud_counter[7:0]==((1 << (clkdiv_reg[7:0]) >> 1) - 1'b1));
//#################################
//# CHIP SELECT
//#################################
assign ss = (spi_state==`SPI_IDLE);
assign ss = (spi_state[1:0]==`SPI_IDLE);
//#################################
//# SCLK GENERATOR
//#################################
//TODO!!
//TODO: implement cpol/cpha (cpha=0 for now)
always @ (posedge clk)
if(spi_state[1:0]!=`SPI_DATA)
sclk <= 1'b0;
else if(phase_match)
sclk <= 1'b1;
else if(baud_match)
sclk <= 1'b0;
//#################################
//# RX/TX SHIFT REGISTER
//#################################
always @ (posedge clk)
if (tx_access)
tx_shiftreg[PW-1:0] <= tx_data[PW-1:0];
else if(baud_match)
tx_shiftreg[PW-1:0] <= {tx_shiftreg[PW-2:0],miso};
assign mosi = tx_shiftreg[PW-1];
assign rx_data[7:0] = tx_shiftreg[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 (fifo_dout[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 (miso), // fill with slave data
.wait_in (1'b0) // no wait
);
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. //
// //
///////////////////////////////////////////////////////////////////////////////

View File

@ -7,16 +7,16 @@
`include "spi_regmap.vh"
module spi_master_regs (/*AUTOARG*/
// Outputs
tx_access, cmd_reg, tx_data, cpol, cpha, spi_en, psize_reg,
clkdiv_reg, wait_out, access_out, packet_out,
cpol, cpha, lsbfirst, emode, spi_en, clkdiv_reg, wait_out,
access_out, packet_out,
// Inputs
clk, nreset, rx_data, rx_access, spi_state, access_in, packet_in,
wait_in
);
//parameters
parameter CLKDIV = 16; // default clkdiv
parameter PSIZE = 32; // default is 32 bits
parameter CLKDIV = 1; // default clkdiv
parameter PSIZE = 0; // default is 32 bits
parameter AW = 32; // addresss width
localparam PW = (2*AW+40); // packet width
@ -25,20 +25,17 @@ module spi_master_regs (/*AUTOARG*/
input nreset; // async active low reset
//io interface
output tx_access; // start the transfer
output [7:0] cmd_reg; // first 8 bites to send
output [PW-1:0] tx_data; // data payload
input [PW-1:0] rx_data; // rx data
input rx_access; // rx access pulse
//control
output cpol;
output cpha;
output cpha;
output lsbfirst; // send lsbfirst
output emode; // send emesh transaction
output spi_en; // enable transmitter
output [7:0] psize_reg; // packet size
output [7:0] clkdiv_reg; // baud rate setting
input [2:0] spi_state; // transmit state
input [1:0] spi_state; // transmit state
//packet to transmit
input access_in; // access from core
@ -57,7 +54,7 @@ module spi_master_regs (/*AUTOARG*/
reg [7:0] config_reg;
reg [7:0] status_reg;
reg [7:0] cmd_reg;
reg [7:0] psize_reg;
reg [31:0] psize_reg;
reg [7:0] clkdiv_reg;
reg [63:0] tx_reg[3:0];
reg [7:0] rx_reg;
@ -100,14 +97,7 @@ module spi_master_regs (/*AUTOARG*/
assign config_write = reg_write & (dstaddr_in[7:2]==`SPI_CONFIG);
assign status_write = reg_write & (dstaddr_in[7:2]==`SPI_STATUS);
assign cmd_write = reg_write & (dstaddr_in[7:2]==`SPI_CMD);
assign psize_write = reg_write & (dstaddr_in[7:2]==`SPI_PSIZE);
assign clkdiv_write = reg_write & (dstaddr_in[7:2]==`SPI_CLKDIV);
assign tx_write = reg_write & (dstaddr_in[7:2]==`SPI_TX);
assign tx_manualstart = reg_write & (dstaddr_in[7:2]==`SPI_START);
//autostart on write to lowest tx register
assign tx_autostart = tx_write & (dstaddr_in[4:3]==2'b00);
//####################################
//# CONFIG
@ -119,15 +109,15 @@ module spi_master_regs (/*AUTOARG*/
else if(config_write)
config_reg[7:0] <= data_in[7:0];
assign spi_en = config_reg[0]; // enable spi
assign irq_en = config_reg[1]; // enable interrupt
assign cpol = config_reg[2]; // cpol
assign cpha = config_reg[3]; // cpha
assign auto_mode = config_reg[4]; // auto starts transfer on tx write
assign tx_access = auto_mode ? tx_autostart :
tx_manualstart;
assign spi_en = config_reg[0]; // enable spi
assign irq_en = config_reg[1]; // enable interrupt
assign cpol = config_reg[2]; // cpol
assign cpha = config_reg[3]; // cpha
assign lsbfirst = config_reg[4]; // send lsb first
assign manual_ss = config_reg[5]; // manually control ss pin
assign rxauto_mode = config_reg[6]; // rx auto return mode
assign emode = config_reg[7]; // emesh transfer mode
//####################################
//# STATUS
//####################################
@ -138,21 +128,10 @@ module spi_master_regs (/*AUTOARG*/
else if(status_write)
status_reg[7:0] <= reg_wdata[7:0];
else
status_reg[7:0] <= {4'b0, //7:4
spi_state[2:0], //3:1
status_reg[7:0] <= {4'b0, //7:3
spi_state[1:0], //2:1
(rx_access | status_reg[0])};//0
//####################################
//# PSIZE (packet size)
//####################################
always @ (posedge clk or negedge nreset)
if (~nreset)
psize_reg[7:0] <= PSIZE;
else if(psize_write)
psize_reg[7:0] <= reg_wdata[7:0];
//####################################
//# CLKDIV
//####################################
@ -160,16 +139,9 @@ module spi_master_regs (/*AUTOARG*/
always @ (posedge clk or negedge nreset)
if (~nreset)
clkdiv_reg[7:0] <= CLKDIV;
else if(psize_write)
else if(clkdiv_write)
clkdiv_reg[7:0] <= reg_wdata[7:0];
//####################################
//# COMMAND REG
//####################################
always @ (posedge clk or negedge nreset)
if(cmd_write)
cmd_reg[7:0] <= reg_wdata[7:0];
//####################################
//# RX REG
//####################################
@ -177,30 +149,6 @@ module spi_master_regs (/*AUTOARG*/
if(rx_access)
rx_reg[7:0] <= rx_data[7:0];
//####################################
//# TX REGS
//####################################
//auto start on writing to lowest tx data register
assign write_mask[63:0] = (datamode_in[1:0]==2'b00) ? 64'h00000000000000FF :
(datamode_in[1:0]==2'b01) ? 64'h000000000000FFFF :
(datamode_in[1:0]==2'b10) ? 64'h00000000FFFFFFFF :
64'hFFFFFFFFFFFFFFFF;
always @ (posedge clk)
for(i=0;i<64;i=i+1)
if(tx_write & write_mask[i])
tx_reg[dstaddr_in[4:3]][i] <= reg_wdata[i];
assign tx_vector[255:0]= {tx_reg[3],
tx_reg[2],
tx_reg[1],
tx_reg[0]};
//only taking
assign tx_data[PW-1:0] = tx_vector[PW-1:0];
endmodule // spi_master_regs
// Local Variables:

View File

@ -3,14 +3,12 @@
`define GPIO_REGMAP_V_
`define SPI_CONFIG 6'd0 // config register
`define SPI_STATUS 6'd1 // status register
`define SPI_CMD 6'd2 // command register (first byte)
`define SPI_PSIZE 6'd3 // package size (32 bits)
`define SPI_CLKDIV 6'd4 // baud rate (master)
`define SPI_START 6'd5 // manual transfer (master)
`define SPI_JUNK 6'd6 // reserved
`define SPI_JUNK 6'd7 // reserved
`define SPI_TX 6'd8 // 4 regs for tx x 32
`define SPI_RX 6'd12 // 4 regs for rx x 32
`define SPI_CLKDIV 6'd2 // baud rate (master)
`define SPI_CMD 6'd3 // manual ss control (master)
`define SPI_RXADDR0 6'd4 // auto return address (31:0)
`define SPI_RXADDR1 6'd6 // auto return address (63:32)
`define SPI_TX 6'd8 // TX FIFO
`define SPI_RX 6'd12 // RX FIFO
`endif // `ifndef GPIO_REGMAP_V_

View File

@ -46,23 +46,31 @@ module spi_slave_io(/*AUTOARG*/
//#################################
reg [2:0] spi_state;
reg [7:0] bit_count;
reg [PW-1:0] spi_rx;
reg [7:0] bit_count;
reg [PW-1:0] spi_tx;
reg spi_access;
reg packet_done_reg;
reg spi_request;
reg [PW-1:0] packet_out;
wire [7:0] psize;
wire [PW-1:0] rx_data;
//#################################
//# RX SHIFT REGISTER
//#################################
always @ (posedge sclk)
if(~ss)
spi_rx[PW-1:0] <= {spi_rx[PW-2:0],mosi};
oh_ser2par #(.PW(PW),
.SW(1))
ser2par (// Outputs
.dout (rx_data[PW-1:0]),
// Inputs
.clk (sclk),
.din (mosi),
.lsbfirst (1'b0), //msb first
.shift (~ss)
);
//#################################
//# STATE MACHINE
//#################################
@ -106,17 +114,18 @@ module spi_slave_io(/*AUTOARG*/
else
bit_count[7:0] <= bit_count[7:0] + 1'b1;
assign read_cmd = (spi_rx[7:6]==2'b10) &
assign read_cmd = (rx_data[7:6]==2'b10) &
(spi_state[2:0]==`SPI_CMD);
assign write_cmd = (spi_rx[7:6]==2'b00) &
assign write_cmd = (rx_data[7:6]==2'b00) &
(spi_state[2:0]==`SPI_CMD);
assign remote_cmd = (spi_rx[7:6]==2'b11) &
assign remote_cmd = (rx_data[7:6]==2'b11) &
(spi_state[2:0]==`SPI_CMD);
assign byte_done = &bit_count[2:0];
//change to sl?
assign packet_done = (bit_count[7:0]==psize[7:0]);
//#################################
@ -127,7 +136,7 @@ module spi_slave_io(/*AUTOARG*/
always @ (posedge sclk)
if(load_tx)
spi_tx[7:0] <= spi_regs[spi_rx[6:0]]; //
spi_tx[7:0] <= spi_regs[rx_data[6:0]]; //
else if(~ss)
spi_tx[7:0] <= {spi_tx[6:0],1'b0};
@ -137,10 +146,10 @@ module spi_slave_io(/*AUTOARG*/
//# REGISTER FILE INTERFACE
//#################################
assign spi_clk = sclk;
assign spi_addr[5:0] = spi_rx[5:0];
assign spi_addr[5:0] = rx_data[5:0];
assign spi_write = byte_done & (spi_state[2:0]==`SPI_WRITE);
assign spi_read = byte_done & (spi_state[2:0]==`SPI_READ);
assign spi_data[7:0] = spi_rx[7:0];
assign spi_data[7:0] = rx_data[7:0];
//#################################
//# CLOCK SYNCHRONIZATION
@ -173,9 +182,34 @@ module spi_slave_io(/*AUTOARG*/
//sample rx data
always @ (posedge clk)
if(spi_access_pulse)
packet_out[PW-1:0] <= spi_rx[PW-1:0];
packet_out[PW-1:0] <= rx_data[PW-1:0];
endmodule // spi_slave_io
// Local Variables:
// verilog-library-directories:("." "../../common/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. //
// //
///////////////////////////////////////////////////////////////////////////////

View File

@ -61,7 +61,6 @@ module spi_slave_regs (/*AUTOARG*/
//#####################################
assign spi_config_write = spi_write & (spi_addr[5:0]==`SPI_CONFIG);
assign spi_psize_write = spi_write & (spi_addr[5:0]==`SPI_PSIZE);
assign spi_user_write = spi_write & (|spi_addr[5:4]);
//#####################################
@ -108,17 +107,7 @@ module spi_slave_regs (/*AUTOARG*/
//#####################################
//TBD
//#####################################
//# PACKET SIZE [3]
//#####################################
always @ (posedge spi_clk or negedge nreset)
if(!nreset)
spi_psize[7:0] <= PW;
else if(spi_psize_write)
spi_psize[7:0] <= spi_data[7:0];
//#####################################
//# CORE DATA [15:8]
//#####################################
@ -147,10 +136,10 @@ module spi_slave_regs (/*AUTOARG*/
//8 standard regs
spi_vector[7:0] = spi_config[7:0]; //0
spi_vector[15:8] = spi_status[7:0]; //1
spi_vector[23:16] = spi_cmd[7:0]; //2
spi_vector[31:24] = spi_psize[7:0]; //3
spi_vector[23:16] = 8'b0; //2
spi_vector[31:24] = spi_cmd[7:0]; //3
spi_vector[63:32] = 32'b0; //7:4
spi_vector[127:64] = 64'b0; //15:8
spi_vector[127:64] = 64'b0; //15:8
//16 core data tx vector
spi_vector[255:128] = core_regs[63:0];
//16 core data rx vector
@ -160,8 +149,6 @@ module spi_slave_regs (/*AUTOARG*/
spi_vector[512+i*8 +:8] = user_regs[i];
end
endmodule // spi_slave_regs
// Local Variables: