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

Subversion Repositories spi

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 6 to Rev 7
    Reverse comparison

Rev 6 → Rev 7

/trunk/bench/verilog/tb_spi_top.v
65,11 → 65,13
 
reg [31:0] q;
 
parameter SPI_RX = 4'h0;
parameter SPI_TX = 4'h0;
parameter SPI_CTRL = 4'h4;
parameter SPI_DEVIDE = 4'h8;
parameter SPI_SS = 4'hc;
parameter SPI_RX_L = 5'h0;
parameter SPI_RX_H = 5'h4;
parameter SPI_TX_L = 5'h0;
parameter SPI_TX_H = 5'h4;
parameter SPI_CTRL = 5'h8;
parameter SPI_DEVIDE = 5'hc;
parameter SPI_SS = 5'h10;
 
// Generate clock
always #5 clk = ~clk;
122,7 → 124,7
 
// Program core
i_wb_master.wb_write(0, SPI_DEVIDE, 32'h05); // set devider register
i_wb_master.wb_write(0, SPI_TX, 32'h5a); // set tx register to 0x5a
i_wb_master.wb_write(0, SPI_TX_L, 32'h5a); // set tx register to 0x5a
i_wb_master.wb_write(0, SPI_CTRL, 32'h40); // set 8 bit transfer
i_wb_master.wb_write(0, SPI_SS, 32'h01); // set ss 0
 
129,7 → 131,7
$display("status: %t programmed registers", $time);
 
i_wb_master.wb_cmp(0, SPI_DEVIDE, 32'h05); // verify devider register
i_wb_master.wb_cmp(0, SPI_TX, 32'h5a); // verify tx register
i_wb_master.wb_cmp(0, SPI_TX_L, 32'h5a); // verify tx register
i_wb_master.wb_cmp(0, SPI_CTRL, 32'h40); // verify tx register
i_wb_master.wb_cmp(0, SPI_SS, 32'h01); // verify ss register
 
151,7 → 153,7
$display("status: %t transfer completed: 0x0000005a != 0x%x nok", $time, i_spi_slave.data);
 
i_spi_slave.rx_negedge = 1'b0;
i_wb_master.wb_write(0, SPI_TX, 32'ha5);
i_wb_master.wb_write(0, SPI_TX_L, 32'ha5);
i_wb_master.wb_write(0, SPI_CTRL, 32'h44); // set 8 bit transfer, tx negedge
i_wb_master.wb_write(0, SPI_CTRL, 32'h45); // set 8 bit transfer, tx negedge, start transfer
 
168,9 → 170,9
$display("status: %t transfer completed: 0x00005aa5 != 0x%x nok", $time, i_spi_slave.data);
 
i_spi_slave.rx_negedge = 1'b0;
i_wb_master.wb_write(0, SPI_TX, 32'h5aa5);
i_wb_master.wb_write(0, SPI_CTRL, 32'h184); // set 16 bit transfer, tx negedge, lsb
i_wb_master.wb_write(0, SPI_CTRL, 32'h185); // set 16 bit transfer, tx negedge, start transfer
i_wb_master.wb_write(0, SPI_TX_L, 32'h5aa5);
i_wb_master.wb_write(0, SPI_CTRL, 32'h284); // set 16 bit transfer, tx negedge, lsb
i_wb_master.wb_write(0, SPI_CTRL, 32'h285); // set 16 bit transfer, tx negedge, start transfer
 
$display("status: %t generate transfer: 16 bit (0x00005aa5), lsb first, tx negedge, rx posedge", $time);
 
187,9 → 189,9
 
i_spi_slave.rx_negedge = 1'b0;
i_spi_slave.tx_negedge = 1'b1;
i_wb_master.wb_write(0, SPI_TX, 32'h55);
i_wb_master.wb_write(0, SPI_CTRL, 32'h144); // set 8 bit transfer, tx negedge, lsb
i_wb_master.wb_write(0, SPI_CTRL, 32'h145); // set 8 bit transfer, tx negedge, start transfer
i_wb_master.wb_write(0, SPI_TX_L, 32'h55);
i_wb_master.wb_write(0, SPI_CTRL, 32'h244); // set 8 bit transfer, tx negedge, lsb
i_wb_master.wb_write(0, SPI_CTRL, 32'h245); // set 8 bit transfer, tx negedge, start transfer
 
$display("status: %t generate transfer: 8 bit (0x000000a5), lsb first, tx negedge, rx posedge", $time);
 
198,9 → 200,9
while (q[0])
i_wb_master.wb_read(1, SPI_CTRL, q);
 
i_wb_master.wb_read(1, SPI_RX, q);
i_wb_master.wb_read(1, SPI_RX_L, q);
 
if (i_spi_slave.data == 32'ha5a55aaa && q == 32'h00000055)
if (i_spi_slave.data == 32'ha5a55aaa && q == 32'h0000005a)
$display("status: %t transfer completed: 0xa5a55aaa == 0x%x 0x0000005a == 0x%x ok", $time, i_spi_slave.data, q);
else if (i_spi_slave.data == 32'ha5a55aaa)
$display("status: %t transfer completed: 0xa5a55aaa == 0x%x 0x0000005a != 0x%x nok", $time, i_spi_slave.data, q);
211,9 → 213,9
 
i_spi_slave.rx_negedge = 1'b1;
i_spi_slave.tx_negedge = 1'b0;
i_wb_master.wb_write(0, SPI_TX, 32'haa);
i_wb_master.wb_write(0, SPI_CTRL, 32'h142); // set 8 bit transfer, rx negedge, lsb
i_wb_master.wb_write(0, SPI_CTRL, 32'h143); // set 8 bit transfer, rx negedge, start transfer
i_wb_master.wb_write(0, SPI_TX_L, 32'haa);
i_wb_master.wb_write(0, SPI_CTRL, 32'h242); // set 8 bit transfer, rx negedge, lsb
i_wb_master.wb_write(0, SPI_CTRL, 32'h243); // set 8 bit transfer, rx negedge, start transfer
 
$display("status: %t generate transfer: 8 bit (0x000000aa), lsb first, tx posedge, rx negedge", $time);
 
222,7 → 224,7
while (q[0])
i_wb_master.wb_read(1, SPI_CTRL, q);
 
i_wb_master.wb_read(1, SPI_RX, q);
i_wb_master.wb_read(1, SPI_RX_L, q);
 
if (i_spi_slave.data == 32'ha55aaa55 && q == 32'h000000a5)
$display("status: %t transfer completed: 0xa55aaa55 == 0x%x 0x000000a5 == 0x%x ok", $time, i_spi_slave.data, q);
235,7 → 237,7
 
i_spi_slave.rx_negedge = 1'b1;
i_spi_slave.tx_negedge = 1'b0;
i_wb_master.wb_write(0, SPI_TX, 32'haa55);
i_wb_master.wb_write(0, SPI_TX_L, 32'haa55);
i_wb_master.wb_write(0, SPI_CTRL, 32'h82); // set 16 bit transfer, rx negedge
i_wb_master.wb_write(0, SPI_CTRL, 32'h83); // set 16 bit transfer, rx negedge, start transfer
 
246,7 → 248,7
while (q[0])
i_wb_master.wb_read(1, SPI_CTRL, q);
 
i_wb_master.wb_read(1, SPI_RX, q);
i_wb_master.wb_read(1, SPI_RX_L, q);
 
if (i_spi_slave.data == 32'haa55aa55 && q == 32'h0000a55a)
$display("status: %t transfer completed: 0xaa55aa55 == 0x%x 0x0000a55a == 0x%x ok", $time, i_spi_slave.data, q);
259,9 → 261,9
 
i_spi_slave.rx_negedge = 1'b1;
i_spi_slave.tx_negedge = 1'b1;
i_wb_master.wb_write(0, SPI_TX, 32'haa55a5a5);
i_wb_master.wb_write(0, SPI_CTRL, 32'h200); // set 32 bit transfer, ie
i_wb_master.wb_write(0, SPI_CTRL, 32'h201); // set 32 bit transfer, start transfer
i_wb_master.wb_write(0, SPI_TX_L, 32'haa55a5a5);
i_wb_master.wb_write(0, SPI_CTRL, 32'h500); // set 32 bit transfer, ie
i_wb_master.wb_write(0, SPI_CTRL, 32'h501); // set 32 bit transfer, start transfer
 
$display("status: %t generate transfer: 32 bit (0xaa55a5a5), msb first, tx negedge, rx negedge", $time);
 
269,7 → 271,7
while (!int)
@(posedge clk);
 
i_wb_master.wb_read(1, SPI_RX, q);
i_wb_master.wb_read(1, SPI_RX_L, q);
@(posedge clk);
if (int)
286,8 → 288,8
 
i_spi_slave.rx_negedge = 1'b0;
i_spi_slave.tx_negedge = 1'b0;
i_wb_master.wb_write(0, SPI_CTRL, 32'h306); // set 32 bit transfer, ie, lsb, rx negedge, tx negedge
i_wb_master.wb_write(0, SPI_CTRL, 32'h307); // set 32 bit transfer, start transfer
i_wb_master.wb_write(0, SPI_CTRL, 32'h706); // set 32 bit transfer, ie, lsb, rx negedge, tx negedge
i_wb_master.wb_write(0, SPI_CTRL, 32'h707); // set 32 bit transfer, start transfer
 
$display("status: %t generate transfer: 32 bit (0xaa55a5a5), msb first, tx negedge, rx negedge", $time);
 
295,7 → 297,7
while (!int)
@(posedge clk);
 
i_wb_master.wb_read(1, SPI_RX, q);
i_wb_master.wb_read(1, SPI_RX_L, q);
 
@(posedge clk);
if (int)
310,6 → 312,32
else
$display("status: %t transfer completed: 0x54ab54aa != 0x%x 0xa5a5aa55 != 0x%x nok", $time, i_spi_slave.data, q);
 
i_wb_master.wb_write(0, SPI_TX_L, 32'h01234567);
i_wb_master.wb_write(0, SPI_TX_H, 32'h89abcdef);
i_wb_master.wb_write(0, SPI_CTRL, 32'h606); // set 64 bit transfer, ie, lsb, rx negedge, tx negedge
i_wb_master.wb_write(0, SPI_CTRL, 32'h607); // set 64 bit transfer, start transfer
 
$display("status: %t generate transfer: 64 bit (0x0123456789abcdef), msb first, tx negedge, rx negedge", $time);
 
// Check interrupt signal
while (!int)
@(posedge clk);
 
i_wb_master.wb_read(1, SPI_RX_H, q);
 
@(posedge clk);
if (int)
$display("status: %t transfer completed: interrupt still active nok", $time, i_spi_slave.data, q);
 
if (i_spi_slave.data == 32'hf7b3d591 && q == 32'h01234567)
$display("status: %t transfer completed: 0xf7b3d591 == 0x%x 0x01234567 == 0x%x ok", $time, i_spi_slave.data, q);
else if (i_spi_slave.data == 32'hf7b3d591)
$display("status: %t transfer completed: 0xf7b3d591 == 0x%x 0x01234567 != 0x%x nok", $time, i_spi_slave.data, q);
else if (q == 32'hf7b3d591)
$display("status: %t transfer completed: 0xf7b3d591 != 0x%x 0x01234567 == 0x%x nok", $time, i_spi_slave.data, q);
else
$display("status: %t transfer completed: 0xf7b3d591 != 0x%x 0x01234567 != 0x%x nok", $time, i_spi_slave.data, q);
 
$display("\n\nstatus: %t Testbench done", $time);
 
#25000; // wait 25us
/trunk/rtl/verilog/spi_top.v
52,7 → 52,6
ss_pad_o, sclk_pad_o, mosi_pad_o, miso_pad_i
);
 
parameter dw = 32;
parameter Tp = 1;
 
// Wishbone signals
59,8 → 58,8
input wb_clk_i; // master clock input
input wb_rst_i; // synchronous active high reset
input [4:0] wb_adr_i; // lower address bits
input [dw-1:0] wb_dat_i; // databus input
output [dw-1:0] wb_dat_o; // databus output
input [32-1:0] wb_dat_i; // databus input
output [32-1:0] wb_dat_o; // databus output
input [3:0] wb_sel_i; // byte select inputs
input wb_we_i; // write enable input
input wb_stb_i; // stobe/core select signal
75,7 → 74,7
output mosi_pad_o; // master out slave in
input miso_pad_i; // master in slave out
reg [dw-1:0] wb_dat_o;
reg [32-1:0] wb_dat_o;
reg wb_ack_o;
reg wb_err_o;
reg wb_int_o;
84,7 → 83,7
reg [`SPI_DIVIDER_BIT_NB-1:0] divider; // Divider register
reg [`SPI_CTRL_BIT_NB-1:0] ctrl; // Control and status register
reg [`SPI_SS_NB-1:0] ss; // Slave select register
reg [dw-1:0] wb_dat; // wb data out
reg [32-1:0] wb_dat; // wb data out
wire [`SPI_MAX_CHAR-1:0] rx; // Rx register
wire rx_negedge; // miso is sampled on negative edge
wire tx_negedge; // mosi is driven on negative edge
94,7 → 93,8
wire ie; // interrupt enable
wire spi_divider_sel; // divider register select
wire spi_ctrl_sel; // ctrl register select
wire spi_tx_sel; // tx register select
wire spi_tx_sel_l; // tx_l register select
wire spi_tx_sel_h; // tx_h register select
wire spi_ss_sel; // ss register select
wire tip; // transfer in progress
wire pos_edge; // recognize posedge of sclk
104,7 → 104,8
// Address decoder
assign spi_divider_sel = wb_cyc_i & wb_stb_i & (wb_adr_i[`SPI_OFS_BITS] == `SPI_DEVIDE);
assign spi_ctrl_sel = wb_cyc_i & wb_stb_i & (wb_adr_i[`SPI_OFS_BITS] == `SPI_CTRL);
assign spi_tx_sel = wb_cyc_i & wb_stb_i & (wb_adr_i[`SPI_OFS_BITS] == `SPI_TX);
assign spi_tx_sel_h = wb_cyc_i & wb_stb_i & (wb_adr_i[`SPI_OFS_BITS] == `SPI_TX_H);
assign spi_tx_sel_l = wb_cyc_i & wb_stb_i & (wb_adr_i[`SPI_OFS_BITS] == `SPI_TX_L);
assign spi_ss_sel = wb_cyc_i & wb_stb_i & (wb_adr_i[`SPI_OFS_BITS] == `SPI_SS);
// Read from registers
111,10 → 112,16
always @(wb_adr_i or rx or ctrl or divider or ss)
begin
case (wb_adr_i[`SPI_OFS_BITS])
`SPI_RX: wb_dat = {{dw-`SPI_MAX_CHAR{1'b0}}, rx};
`SPI_CTRL: wb_dat = {{dw-`SPI_CTRL_BIT_NB{1'b0}}, ctrl};
`SPI_DEVIDE: wb_dat = {{dw-`SPI_DIVIDER_BIT_NB{1'b0}}, divider};
`SPI_SS: wb_dat = {{dw-`SPI_SS_NB{1'b0}}, ss};
`ifdef SPI_MAX_CHAR_64
`SPI_RX_L: wb_dat = rx[31:0];
`SPI_RX_H: wb_dat = rx[63:32];
`else
`SPI_RX_L: wb_dat = {{32-`SPI_MAX_CHAR{1'b0}}, rx};
`SPI_RX_H: wb_dat = 32'b0;
`endif
`SPI_CTRL: wb_dat = {{32-`SPI_CTRL_BIT_NB{1'b0}}, ctrl};
`SPI_DEVIDE: wb_dat = {{32-`SPI_DIVIDER_BIT_NB{1'b0}}, divider};
`SPI_SS: wb_dat = {{32-`SPI_SS_NB{1'b0}}, ss};
endcase
end
122,7 → 129,7
always @(posedge wb_clk_i or posedge wb_rst_i)
begin
if (wb_rst_i)
wb_dat_o <= #Tp {dw{1'b0}};
wb_dat_o <= #Tp 32'b0;
else
wb_dat_o <= #Tp wb_dat;
end
206,8 → 213,8
.neg_edge(neg_edge));
spi_shift shift (.clk(wb_clk_i), .rst(wb_rst_i), .len(char_len[`SPI_CHAR_LEN_BITS-1:0]),
.latch(spi_tx_sel && wb_we_i), .lsb(lsb), .go(go),
.pos_edge(pos_edge), .neg_edge(neg_edge),
.latch_h(spi_tx_sel_h && wb_we_i), .latch_l(spi_tx_sel_l && wb_we_i), .lsb(lsb),
.go(go), .pos_edge(pos_edge), .neg_edge(neg_edge),
.rx_negedge(rx_negedge), .tx_negedge(tx_negedge),
.tip(tip), .last(last_bit),
.p_in(wb_dat_i), .p_out(rx),
/trunk/rtl/verilog/spi_defines.v
47,11 → 47,13
 
//
// Maximum nuber of bits that can be send/received at once. Alloved values are
// 32, 16 and 8. SPI_CHAR_LEN_BITS must be also set to 5, 4 or 3 respectively.
// Default is 32.
// 64, 32, 16 and 8. SPI_CHAR_LEN_BITS must be also set to 6, 5, 4 or 3 respectively.
// Default is 64.
// If SPI_MAX_CHAR is 64, SPI_MAX_CHAR_64 must be defined, otherwise comment it
//
`define SPI_MAX_CHAR 32
`define SPI_CHAR_LEN_BITS 5
`define SPI_MAX_CHAR_64 1
`define SPI_MAX_CHAR 64
`define SPI_CHAR_LEN_BITS 6
 
//
// Number of device select signals.
60,28 → 62,30
//
// Bits of WISHBONE address used for partial decoding of SPI registers.
//
`define SPI_OFS_BITS 3:2
`define SPI_OFS_BITS 4:2
 
//
// Register offset
//
`define SPI_RX 0
`define SPI_TX 0
`define SPI_CTRL 1
`define SPI_DEVIDE 2
`define SPI_SS 3
`define SPI_RX_L 0
`define SPI_RX_H 1
`define SPI_TX_L 0
`define SPI_TX_H 1
`define SPI_CTRL 2
`define SPI_DEVIDE 3
`define SPI_SS 4
 
//
// Number of bits in ctrl register
//
`define SPI_CTRL_BIT_NB 10
`define SPI_CTRL_BIT_NB 11
 
//
// Control register bit position
//
`define SPI_CTRL_IE 9
`define SPI_CTRL_LSB 8
`define SPI_CTRL_CHAR_LEN 7:3
`define SPI_CTRL_IE 10
`define SPI_CTRL_LSB 9
`define SPI_CTRL_CHAR_LEN 8:3
`define SPI_CTRL_TX_NEGEDGE 2
`define SPI_CTRL_RX_NEGEDGE 1
`define SPI_CTRL_GO 0
/trunk/rtl/verilog/spi_shift.v
41,7 → 41,7
`include "spi_defines.v"
`include "timescale.v"
 
module spi_shift (clk, rst, latch, len, lsb, go,
module spi_shift (clk, rst, latch_h, latch_l, len, lsb, go,
pos_edge, neg_edge, rx_negedge, tx_negedge,
tip, last,
p_in, p_out, s_clk, s_in, s_out);
50,7 → 50,8
input clk; // system clock
input rst; // reset
input latch; // latch signal for storing the data in shift register
input latch_h; // latch_h signal for storing the data in shift register
input latch_l; // latch_l signal for storing the data in shift register
input [`SPI_CHAR_LEN_BITS-1:0] len; // data len in bits (minus one)
input lsb; // lbs first on the line
input go; // start stansfer
60,7 → 61,7
input tx_negedge; // s_out is driven on negative edge
output tip; // transfer in progress
output last; // last bit
input [`SPI_MAX_CHAR-1:0] p_in; // parallel in
input [31:0] p_in; // parallel in
output [`SPI_MAX_CHAR-1:0] p_out; // parallel out
input s_clk; // serial clock
input s_in; // serial in
126,8 → 127,15
begin
if (rst)
data <= #Tp {`SPI_MAX_CHAR{1'b0}};
else if (latch && !tip)
data <= #Tp p_in;
`ifdef SPI_MAX_CHAR_64
else if (latch_l && !tip)
data[31:0] <= #Tp p_in[31:0];
else if (latch_h && !tip)
data[63:32] <= #Tp p_in[31:0];
`else
else if (latch_l && !tip)
data <= #Tp p_in[`SPI_MAX_CHAR-1:0];
`endif
else
data[rx_bit_pos[`SPI_CHAR_LEN_BITS-1:0]] <= #Tp rx_clk ? s_in : data[rx_bit_pos[`SPI_CHAR_LEN_BITS-1:0]];
end
/trunk/doc/src/spi.doc Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream

powered by: WebSVN 2.1.0

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