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