diff --git a/modules/wishbone/wb_spi/spi_clgen.v b/modules/wishbone/wb_spi/spi_clgen.v index 7bc4f6e5e4a67f9a20557b6bed8f397e8202c783..f5b6ed7b732b79c94f5e9089d6c076453954629b 100644 --- a/modules/wishbone/wb_spi/spi_clgen.v +++ b/modules/wishbone/wb_spi/spi_clgen.v @@ -44,13 +44,14 @@ module spi_clgen (clk_in, rst, go, enable, last_clk, divider, clk_out, pos_edge, neg_edge); parameter Tp = 1; + parameter SPI_DIVIDER_LEN = 8; input clk_in; // input clock (system clock) input rst; // reset input enable; // clock enable input go; // start transfer input last_clk; // last clock - input [`SPI_DIVIDER_LEN-1:0] divider; // clock divider (output clock is divided by this value) + input [SPI_DIVIDER_LEN-1:0] divider; // clock divider (output clock is divided by this value) output clk_out; // output clock output pos_edge; // pulse marking positive edge of clk_out output neg_edge; // pulse marking negative edge of clk_out @@ -59,25 +60,25 @@ module spi_clgen (clk_in, rst, go, enable, last_clk, divider, clk_out, pos_edge, reg pos_edge; reg neg_edge; - reg [`SPI_DIVIDER_LEN-1:0] cnt; // clock counter + reg [SPI_DIVIDER_LEN-1:0] cnt; // clock counter wire cnt_zero; // conter is equal to zero wire cnt_one; // conter is equal to one - assign cnt_zero = cnt == {`SPI_DIVIDER_LEN{1'b0}}; - assign cnt_one = cnt == {{`SPI_DIVIDER_LEN-1{1'b0}}, 1'b1}; + assign cnt_zero = cnt == {SPI_DIVIDER_LEN{1'b0}}; + assign cnt_one = cnt == {{SPI_DIVIDER_LEN-1{1'b0}}, 1'b1}; // Counter counts half period always @(posedge clk_in or posedge rst) begin if(rst) - cnt <= #Tp {`SPI_DIVIDER_LEN{1'b1}}; + cnt <= #Tp {SPI_DIVIDER_LEN{1'b1}}; else begin if(!enable || cnt_zero) cnt <= #Tp divider; else - cnt <= #Tp cnt - {{`SPI_DIVIDER_LEN-1{1'b0}}, 1'b1}; + cnt <= #Tp cnt - {{SPI_DIVIDER_LEN-1{1'b0}}, 1'b1}; end end diff --git a/modules/wishbone/wb_spi/spi_defines.v b/modules/wishbone/wb_spi/spi_defines.v index a6925918e0d06404f6b41e9fa18fef67d643b112..f9afa0f478d50ba540e0016f5a97d5e28fda6832 100644 --- a/modules/wishbone/wb_spi/spi_defines.v +++ b/modules/wishbone/wb_spi/spi_defines.v @@ -38,87 +38,95 @@ //// //// ////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////// +// +// Modified to use parameters in spi_top instead of constants in this +// file for divider length, max char length and number of slaves, +// G.Daniluk, CERN 2013 +// +////////////////////////////////////////////////////////////////////// + // // Number of bits used for devider register. If used in system with // low frequency of system clock this can be reduced. // Use SPI_DIVIDER_LEN for fine tuning theexact number. // //`define SPI_DIVIDER_LEN_8 -`define SPI_DIVIDER_LEN_16 +//`define SPI_DIVIDER_LEN_16 //`define SPI_DIVIDER_LEN_24 //`define SPI_DIVIDER_LEN_32 - -`ifdef SPI_DIVIDER_LEN_8 - `define SPI_DIVIDER_LEN 8 // Can be set from 1 to 8 -`endif -`ifdef SPI_DIVIDER_LEN_16 - `define SPI_DIVIDER_LEN 16 // Can be set from 9 to 16 -`endif -`ifdef SPI_DIVIDER_LEN_24 - `define SPI_DIVIDER_LEN 24 // Can be set from 17 to 24 -`endif -`ifdef SPI_DIVIDER_LEN_32 - `define SPI_DIVIDER_LEN 32 // Can be set from 25 to 32 -`endif +// +//`ifdef SPI_DIVIDER_LEN_8 +// `define SPI_DIVIDER_LEN 8 // Can be set from 1 to 8 +//`endif +//`ifdef SPI_DIVIDER_LEN_16 +// `define SPI_DIVIDER_LEN 16 // Can be set from 9 to 16 +//`endif +//`ifdef SPI_DIVIDER_LEN_24 +// `define SPI_DIVIDER_LEN 24 // Can be set from 17 to 24 +//`endif +//`ifdef SPI_DIVIDER_LEN_32 +// `define SPI_DIVIDER_LEN 32 // Can be set from 25 to 32 +//`endif // // Maximum nuber of bits that can be send/received at once. // Use SPI_MAX_CHAR for fine tuning the exact number, when using // SPI_MAX_CHAR_32, SPI_MAX_CHAR_24, SPI_MAX_CHAR_16, SPI_MAX_CHAR_8. // -`define SPI_MAX_CHAR_128 +//`define SPI_MAX_CHAR_128 //`define SPI_MAX_CHAR_64 //`define SPI_MAX_CHAR_32 //`define SPI_MAX_CHAR_24 //`define SPI_MAX_CHAR_16 //`define SPI_MAX_CHAR_8 - -`ifdef SPI_MAX_CHAR_128 - `define SPI_MAX_CHAR 128 // Can only be set to 128 - `define SPI_CHAR_LEN_BITS 7 -`endif -`ifdef SPI_MAX_CHAR_64 - `define SPI_MAX_CHAR 64 // Can only be set to 64 - `define SPI_CHAR_LEN_BITS 6 -`endif -`ifdef SPI_MAX_CHAR_32 - `define SPI_MAX_CHAR 32 // Can be set from 25 to 32 - `define SPI_CHAR_LEN_BITS 5 -`endif -`ifdef SPI_MAX_CHAR_24 - `define SPI_MAX_CHAR 24 // Can be set from 17 to 24 - `define SPI_CHAR_LEN_BITS 5 -`endif -`ifdef SPI_MAX_CHAR_16 - `define SPI_MAX_CHAR 16 // Can be set from 9 to 16 - `define SPI_CHAR_LEN_BITS 4 -`endif -`ifdef SPI_MAX_CHAR_8 - `define SPI_MAX_CHAR 8 // Can be set from 1 to 8 - `define SPI_CHAR_LEN_BITS 3 -`endif +// +//`ifdef SPI_MAX_CHAR_128 +// `define SPI_MAX_CHAR 128 // Can only be set to 128 +// `define SPI_CHAR_LEN_BITS 7 +//`endif +//`ifdef SPI_MAX_CHAR_64 +// `define SPI_MAX_CHAR 64 // Can only be set to 64 +// `define SPI_CHAR_LEN_BITS 6 +//`endif +//`ifdef SPI_MAX_CHAR_32 +// `define SPI_MAX_CHAR 32 // Can be set from 25 to 32 +// `define SPI_CHAR_LEN_BITS 5 +//`endif +//`ifdef SPI_MAX_CHAR_24 +// `define SPI_MAX_CHAR 24 // Can be set from 17 to 24 +// `define SPI_CHAR_LEN_BITS 5 +//`endif +//`ifdef SPI_MAX_CHAR_16 +// `define SPI_MAX_CHAR 16 // Can be set from 9 to 16 +// `define SPI_CHAR_LEN_BITS 4 +//`endif +//`ifdef SPI_MAX_CHAR_8 +// `define SPI_MAX_CHAR 8 // Can be set from 1 to 8 +// `define SPI_CHAR_LEN_BITS 3 +//`endif // // Number of device select signals. Use SPI_SS_NB for fine tuning the // exact number. // -`define SPI_SS_NB_8 +//`define SPI_SS_NB_8 //`define SPI_SS_NB_16 //`define SPI_SS_NB_24 //`define SPI_SS_NB_32 - -`ifdef SPI_SS_NB_8 - `define SPI_SS_NB 8 // Can be set from 1 to 8 -`endif -`ifdef SPI_SS_NB_16 - `define SPI_SS_NB 16 // Can be set from 9 to 16 -`endif -`ifdef SPI_SS_NB_24 - `define SPI_SS_NB 24 // Can be set from 17 to 24 -`endif -`ifdef SPI_SS_NB_32 - `define SPI_SS_NB 32 // Can be set from 25 to 32 -`endif +// +//`ifdef SPI_SS_NB_8 +// `define SPI_SS_NB 8 // Can be set from 1 to 8 +//`endif +//`ifdef SPI_SS_NB_16 +// `define SPI_SS_NB 16 // Can be set from 9 to 16 +//`endif +//`ifdef SPI_SS_NB_24 +// `define SPI_SS_NB 24 // Can be set from 17 to 24 +//`endif +//`ifdef SPI_SS_NB_32 +// `define SPI_SS_NB 32 // Can be set from 25 to 32 +//`endif // // Bits of WISHBONE address used for partial decoding of SPI registers. diff --git a/modules/wishbone/wb_spi/spi_shift.v b/modules/wishbone/wb_spi/spi_shift.v index b17ac8b1f3662bb593d013e664744d74e4a6db6b..7a1c2e4874a58e18a149593d3d373f03f6021e58 100644 --- a/modules/wishbone/wb_spi/spi_shift.v +++ b/modules/wishbone/wb_spi/spi_shift.v @@ -47,12 +47,14 @@ module spi_shift (clk, rst, latch, byte_sel, len, lsb, go, p_in, p_out, s_clk, s_in, s_out); parameter Tp = 1; + parameter SPI_MAX_CHAR = 128; + parameter SPI_CHAR_LEN_BITS = 7; input clk; // system clock input rst; // reset input [3:0] latch; // latch signal for storing the data in shift register input [3:0] byte_sel; // byte select signals for storing the data in shift register - input [`SPI_CHAR_LEN_BITS-1:0] len; // data len in bits (minus one) + 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 input pos_edge; // recognize posedge of sclk @@ -62,7 +64,7 @@ module spi_shift (clk, rst, latch, byte_sel, len, lsb, go, output tip; // transfer in progress output last; // last bit input [31:0] p_in; // parallel in - output [`SPI_MAX_CHAR-1:0] p_out; // parallel out + output [SPI_MAX_CHAR-1:0] p_out; // parallel out input s_clk; // serial clock input s_in; // serial in output s_out; // serial out @@ -70,18 +72,18 @@ module spi_shift (clk, rst, latch, byte_sel, len, lsb, go, reg s_out; reg tip; - reg [`SPI_CHAR_LEN_BITS:0] cnt; // data bit count - reg [`SPI_MAX_CHAR-1:0] data; // shift register - wire [`SPI_CHAR_LEN_BITS:0] tx_bit_pos; // next bit position - wire [`SPI_CHAR_LEN_BITS:0] rx_bit_pos; // next bit position + reg [SPI_CHAR_LEN_BITS:0] cnt; // data bit count + reg [SPI_MAX_CHAR-1:0] data; // shift register + wire [SPI_CHAR_LEN_BITS:0] tx_bit_pos; // next bit position + wire [SPI_CHAR_LEN_BITS:0] rx_bit_pos; // next bit position wire rx_clk; // rx clock enable wire tx_clk; // tx clock enable assign p_out = data; - assign tx_bit_pos = lsb ? {!(|len), len} - cnt : cnt - {{`SPI_CHAR_LEN_BITS{1'b0}},1'b1}; - assign rx_bit_pos = lsb ? {!(|len), len} - (rx_negedge ? cnt + {{`SPI_CHAR_LEN_BITS{1'b0}},1'b1} : cnt) : - (rx_negedge ? cnt : cnt - {{`SPI_CHAR_LEN_BITS{1'b0}},1'b1}); + assign tx_bit_pos = lsb ? {!(|len), len} - cnt : cnt - {{SPI_CHAR_LEN_BITS{1'b0}},1'b1}; + assign rx_bit_pos = lsb ? {!(|len), len} - (rx_negedge ? cnt + {{SPI_CHAR_LEN_BITS{1'b0}},1'b1} : cnt) : + (rx_negedge ? cnt : cnt - {{SPI_CHAR_LEN_BITS{1'b0}},1'b1}); assign last = !(|cnt); @@ -92,13 +94,13 @@ module spi_shift (clk, rst, latch, byte_sel, len, lsb, go, always @(posedge clk or posedge rst) begin if(rst) - cnt <= #Tp {`SPI_CHAR_LEN_BITS+1{1'b0}}; + cnt <= #Tp {SPI_CHAR_LEN_BITS+1{1'b0}}; else begin if(tip) - cnt <= #Tp pos_edge ? (cnt - {{`SPI_CHAR_LEN_BITS{1'b0}}, 1'b1}) : cnt; + cnt <= #Tp pos_edge ? (cnt - {{SPI_CHAR_LEN_BITS{1'b0}}, 1'b1}) : cnt; else - cnt <= #Tp !(|len) ? {1'b1, {`SPI_CHAR_LEN_BITS{1'b0}}} : {1'b0, len}; + cnt <= #Tp !(|len) ? {1'b1, {SPI_CHAR_LEN_BITS{1'b0}}} : {1'b0, len}; end end @@ -119,120 +121,166 @@ module spi_shift (clk, rst, latch, byte_sel, len, lsb, go, if (rst) s_out <= #Tp 1'b0; else - s_out <= #Tp (tx_clk || !tip) ? data[tx_bit_pos[`SPI_CHAR_LEN_BITS-1:0]] : s_out; + s_out <= #Tp (tx_clk || !tip) ? data[tx_bit_pos[SPI_CHAR_LEN_BITS-1:0]] : s_out; end // Receiving bits from the line - always @(posedge clk or posedge rst) - begin - if (rst) - data <= #Tp {`SPI_MAX_CHAR{1'b0}}; -`ifdef SPI_MAX_CHAR_128 - else if (latch[0] && !tip) - begin - if (byte_sel[3]) - data[31:24] <= #Tp p_in[31:24]; - if (byte_sel[2]) - data[23:16] <= #Tp p_in[23:16]; - if (byte_sel[1]) - data[15:8] <= #Tp p_in[15:8]; - if (byte_sel[0]) - data[7:0] <= #Tp p_in[7:0]; - end - else if (latch[1] && !tip) - begin - if (byte_sel[3]) - data[63:56] <= #Tp p_in[31:24]; - if (byte_sel[2]) - data[55:48] <= #Tp p_in[23:16]; - if (byte_sel[1]) - data[47:40] <= #Tp p_in[15:8]; - if (byte_sel[0]) - data[39:32] <= #Tp p_in[7:0]; - end - else if (latch[2] && !tip) - begin - if (byte_sel[3]) - data[95:88] <= #Tp p_in[31:24]; - if (byte_sel[2]) - data[87:80] <= #Tp p_in[23:16]; - if (byte_sel[1]) - data[79:72] <= #Tp p_in[15:8]; - if (byte_sel[0]) - data[71:64] <= #Tp p_in[7:0]; - end - else if (latch[3] && !tip) - begin - if (byte_sel[3]) - data[127:120] <= #Tp p_in[31:24]; - if (byte_sel[2]) - data[119:112] <= #Tp p_in[23:16]; - if (byte_sel[1]) - data[111:104] <= #Tp p_in[15:8]; - if (byte_sel[0]) - data[103:96] <= #Tp p_in[7:0]; - end -`else -`ifdef SPI_MAX_CHAR_64 - else if (latch[0] && !tip) - begin - if (byte_sel[3]) - data[31:24] <= #Tp p_in[31:24]; - if (byte_sel[2]) - data[23:16] <= #Tp p_in[23:16]; - if (byte_sel[1]) - data[15:8] <= #Tp p_in[15:8]; - if (byte_sel[0]) - data[7:0] <= #Tp p_in[7:0]; - end - else if (latch[1] && !tip) - begin - if (byte_sel[3]) - data[63:56] <= #Tp p_in[31:24]; - if (byte_sel[2]) - data[55:48] <= #Tp p_in[23:16]; - if (byte_sel[1]) - data[47:40] <= #Tp p_in[15:8]; - if (byte_sel[0]) - data[39:32] <= #Tp p_in[7:0]; - end -`else - else if (latch[0] && !tip) - begin - `ifdef SPI_MAX_CHAR_8 - if (byte_sel[0]) - data[`SPI_MAX_CHAR-1:0] <= #Tp p_in[`SPI_MAX_CHAR-1:0]; - `endif - `ifdef SPI_MAX_CHAR_16 - if (byte_sel[0]) - data[7:0] <= #Tp p_in[7:0]; - if (byte_sel[1]) - data[`SPI_MAX_CHAR-1:8] <= #Tp p_in[`SPI_MAX_CHAR-1:8]; - `endif - `ifdef SPI_MAX_CHAR_24 - if (byte_sel[0]) - data[7:0] <= #Tp p_in[7:0]; - if (byte_sel[1]) - data[15:8] <= #Tp p_in[15:8]; - if (byte_sel[2]) - data[`SPI_MAX_CHAR-1:16] <= #Tp p_in[`SPI_MAX_CHAR-1:16]; - `endif - `ifdef SPI_MAX_CHAR_32 - if (byte_sel[0]) - data[7:0] <= #Tp p_in[7:0]; - if (byte_sel[1]) - data[15:8] <= #Tp p_in[15:8]; - if (byte_sel[2]) - data[23:16] <= #Tp p_in[23:16]; - if (byte_sel[3]) - data[`SPI_MAX_CHAR-1:24] <= #Tp p_in[`SPI_MAX_CHAR-1:24]; - `endif - end -`endif -`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 + generate if (SPI_MAX_CHAR == 128) + always @(posedge clk or posedge rst) + begin + if (rst) + data <= #Tp {SPI_MAX_CHAR{1'b0}}; + else if (latch[0] && !tip) + begin + if (byte_sel[3]) + data[31:24] <= #Tp p_in[31:24]; + if (byte_sel[2]) + data[23:16] <= #Tp p_in[23:16]; + if (byte_sel[1]) + data[15:8] <= #Tp p_in[15:8]; + if (byte_sel[0]) + data[7:0] <= #Tp p_in[7:0]; + end + else if (latch[1] && !tip) + begin + if (byte_sel[3]) + data[63:56] <= #Tp p_in[31:24]; + if (byte_sel[2]) + data[55:48] <= #Tp p_in[23:16]; + if (byte_sel[1]) + data[47:40] <= #Tp p_in[15:8]; + if (byte_sel[0]) + data[39:32] <= #Tp p_in[7:0]; + end + else if (latch[2] && !tip) + begin + if (byte_sel[3]) + data[95:88] <= #Tp p_in[31:24]; + if (byte_sel[2]) + data[87:80] <= #Tp p_in[23:16]; + if (byte_sel[1]) + data[79:72] <= #Tp p_in[15:8]; + if (byte_sel[0]) + data[71:64] <= #Tp p_in[7:0]; + end + else if (latch[3] && !tip) + begin + if (byte_sel[3]) + data[127:120] <= #Tp p_in[31:24]; + if (byte_sel[2]) + data[119:112] <= #Tp p_in[23:16]; + if (byte_sel[1]) + data[111:104] <= #Tp p_in[15:8]; + if (byte_sel[0]) + data[103:96] <= #Tp p_in[7:0]; + end + 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 + endgenerate + + generate if (SPI_MAX_CHAR == 64) + always @(posedge clk or posedge rst) + begin + if (rst) + data <= #Tp {SPI_MAX_CHAR{1'b0}}; + else if (latch[0] && !tip) + begin + if (byte_sel[3]) + data[31:24] <= #Tp p_in[31:24]; + if (byte_sel[2]) + data[23:16] <= #Tp p_in[23:16]; + if (byte_sel[1]) + data[15:8] <= #Tp p_in[15:8]; + if (byte_sel[0]) + data[7:0] <= #Tp p_in[7:0]; + end + else if (latch[1] && !tip) + begin + if (byte_sel[3]) + data[63:56] <= #Tp p_in[31:24]; + if (byte_sel[2]) + data[55:48] <= #Tp p_in[23:16]; + if (byte_sel[1]) + data[47:40] <= #Tp p_in[15:8]; + if (byte_sel[0]) + data[39:32] <= #Tp p_in[7:0]; + end + 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 + endgenerate + + generate if (SPI_MAX_CHAR >=25 && SPI_MAX_CHAR <= 32) + always @(posedge clk or posedge rst) + begin + if (rst) + data <= #Tp {SPI_MAX_CHAR{1'b0}}; + else if (latch[0] && !tip) + begin + if (byte_sel[0]) + data[7:0] <= #Tp p_in[7:0]; + if (byte_sel[1]) + data[15:8] <= #Tp p_in[15:8]; + if (byte_sel[2]) + data[23:16] <= #Tp p_in[23:16]; + if (byte_sel[3]) + data[SPI_MAX_CHAR-1:24] <= #Tp p_in[SPI_MAX_CHAR-1:24]; + end + 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 + endgenerate + + generate if (SPI_MAX_CHAR >=17 && SPI_MAX_CHAR <= 24) + always @(posedge clk or posedge rst) + begin + if (rst) + data <= #Tp {SPI_MAX_CHAR{1'b0}}; + else if (latch[0] && !tip) + begin + if (byte_sel[0]) + data[7:0] <= #Tp p_in[7:0]; + if (byte_sel[1]) + data[15:8] <= #Tp p_in[15:8]; + if (byte_sel[2]) + data[SPI_MAX_CHAR-1:16] <= #Tp p_in[SPI_MAX_CHAR-1:16]; + end + 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 + endgenerate + + generate if (SPI_MAX_CHAR >=9 && SPI_MAX_CHAR <= 16) + always @(posedge clk or posedge rst) + begin + if (rst) + data <= #Tp {SPI_MAX_CHAR{1'b0}}; + else if (latch[0] && !tip) + begin + if (byte_sel[0]) + data[7:0] <= #Tp p_in[7:0]; + if (byte_sel[1]) + data[SPI_MAX_CHAR-1:8] <= #Tp p_in[SPI_MAX_CHAR-1:8]; + end + 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 + endgenerate + + generate if (SPI_MAX_CHAR <= 8) + always @(posedge clk or posedge rst) + begin + if (rst) + data <= #Tp {SPI_MAX_CHAR{1'b0}}; + else if (latch[0] && !tip && byte_sel[0]) + data[SPI_MAX_CHAR-1:0] <= #Tp p_in[SPI_MAX_CHAR-1:0]; + 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 + endgenerate + + endmodule diff --git a/modules/wishbone/wb_spi/spi_top.v b/modules/wishbone/wb_spi/spi_top.v index 09b2e50e130afadcbacb2c7d62b4deb6e3fc7d1f..72c255362f5b93999e55ea9fdb4871d0ad10dc24 100644 --- a/modules/wishbone/wb_spi/spi_top.v +++ b/modules/wishbone/wb_spi/spi_top.v @@ -39,6 +39,14 @@ ////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////// +// +// Modified to use parameters (generics) for configuration rather +// than constants from spi_defines file, G.Daniluk CERN 2013 +// +////////////////////////////////////////////////////////////////////// + + `include "spi_defines.v" `include "timescale.v" @@ -53,6 +61,10 @@ module spi_top ); parameter Tp = 1; + parameter SPI_DIVIDER_LEN = 16; + parameter SPI_MAX_CHAR = 128; + parameter SPI_CHAR_LEN_BITS = 7; + parameter SPI_SS_NB = 8; // Wishbone signals input wb_clk_i; // master clock input @@ -69,7 +81,7 @@ module spi_top output wb_int_o; // interrupt request signal output // SPI signals - output [`SPI_SS_NB-1:0] ss_pad_o; // slave select + output [SPI_SS_NB-1:0] ss_pad_o; // slave select output sclk_pad_o; // serial clock output mosi_pad_o; // master out slave in input miso_pad_i; // master in slave out @@ -79,14 +91,14 @@ module spi_top reg wb_int_o; // Internal signals - reg [`SPI_DIVIDER_LEN-1:0] divider; // Divider register + reg [SPI_DIVIDER_LEN-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 [SPI_SS_NB-1:0] ss; // Slave select register reg [32-1:0] wb_dat; // wb data out - wire [`SPI_MAX_CHAR-1:0] rx; // Rx register + 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 - wire [`SPI_CHAR_LEN_BITS-1:0] char_len; // char len + wire [SPI_CHAR_LEN_BITS-1:0] char_len; // char len wire go; // go wire lsb; // lsb first on line wire ie; // interrupt enable @@ -99,7 +111,8 @@ module spi_top wire pos_edge; // recognize posedge of sclk wire neg_edge; // recognize negedge of sclk wire last_bit; // marks last character bit - + + // 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); @@ -110,34 +123,54 @@ module spi_top assign spi_ss_sel = wb_cyc_i & wb_stb_i & (wb_adr_i[`SPI_OFS_BITS] == `SPI_SS); // Read from registers - always @(wb_adr_i or rx or ctrl or divider or ss) - begin - case (wb_adr_i[`SPI_OFS_BITS]) -`ifdef SPI_MAX_CHAR_128 - `SPI_RX_0: wb_dat = rx[31:0]; - `SPI_RX_1: wb_dat = rx[63:32]; - `SPI_RX_2: wb_dat = rx[95:64]; - `SPI_RX_3: wb_dat = {{128-`SPI_MAX_CHAR{1'b0}}, rx[`SPI_MAX_CHAR-1:96]}; -`else -`ifdef SPI_MAX_CHAR_64 - `SPI_RX_0: wb_dat = rx[31:0]; - `SPI_RX_1: wb_dat = {{64-`SPI_MAX_CHAR{1'b0}}, rx[`SPI_MAX_CHAR-1:32]}; - `SPI_RX_2: wb_dat = 32'b0; - `SPI_RX_3: wb_dat = 32'b0; -`else - `SPI_RX_0: wb_dat = {{32-`SPI_MAX_CHAR{1'b0}}, rx[`SPI_MAX_CHAR-1:0]}; - `SPI_RX_1: wb_dat = 32'b0; - `SPI_RX_2: wb_dat = 32'b0; - `SPI_RX_3: wb_dat = 32'b0; -`endif -`endif - `SPI_CTRL: wb_dat = {{32-`SPI_CTRL_BIT_NB{1'b0}}, ctrl}; - `SPI_DEVIDE: wb_dat = {{32-`SPI_DIVIDER_LEN{1'b0}}, divider}; - `SPI_SS: wb_dat = {{32-`SPI_SS_NB{1'b0}}, ss}; - default: wb_dat = 32'bx; - endcase - end - + generate if (SPI_MAX_CHAR == 128) + always @(wb_adr_i or rx or ctrl or divider or ss) + begin + case (wb_adr_i[`SPI_OFS_BITS]) + `SPI_RX_0: wb_dat = rx[31:0]; + `SPI_RX_1: wb_dat = rx[63:32]; + `SPI_RX_2: wb_dat = rx[95:64]; + `SPI_RX_3: wb_dat = {{128-SPI_MAX_CHAR{1'b0}}, rx[SPI_MAX_CHAR-1:96]}; + `SPI_CTRL: wb_dat = {{32-`SPI_CTRL_BIT_NB{1'b0}}, ctrl}; + `SPI_DEVIDE: wb_dat = {{32-SPI_DIVIDER_LEN{1'b0}}, divider}; + `SPI_SS: wb_dat = {{32-SPI_SS_NB{1'b0}}, ss}; + default: wb_dat = 32'bx; + endcase + end + endgenerate + + generate if (SPI_MAX_CHAR == 64) + always @(wb_adr_i or rx or ctrl or divider or ss) + begin + case (wb_adr_i[`SPI_OFS_BITS]) + `SPI_RX_0: wb_dat = rx[31:0]; + `SPI_RX_1: wb_dat = {{64-SPI_MAX_CHAR{1'b0}}, rx[SPI_MAX_CHAR-1:32]}; + `SPI_RX_2: wb_dat = 32'b0; + `SPI_RX_3: wb_dat = 32'b0; + `SPI_CTRL: wb_dat = {{32-`SPI_CTRL_BIT_NB{1'b0}}, ctrl}; + `SPI_DEVIDE: wb_dat = {{32-SPI_DIVIDER_LEN{1'b0}}, divider}; + `SPI_SS: wb_dat = {{32-SPI_SS_NB{1'b0}}, ss}; + default: wb_dat = 32'bx; + endcase + end + endgenerate + + generate if (SPI_MAX_CHAR <=32) + always @(wb_adr_i or rx or ctrl or divider or ss) + begin + case (wb_adr_i[`SPI_OFS_BITS]) + `SPI_RX_0: wb_dat = {{32-SPI_MAX_CHAR{1'b0}}, rx[SPI_MAX_CHAR-1:0]}; + `SPI_RX_1: wb_dat = 32'b0; + `SPI_RX_2: wb_dat = 32'b0; + `SPI_RX_3: wb_dat = 32'b0; + `SPI_CTRL: wb_dat = {{32-`SPI_CTRL_BIT_NB{1'b0}}, ctrl}; + `SPI_DEVIDE: wb_dat = {{32-SPI_DIVIDER_LEN{1'b0}}, divider}; + `SPI_SS: wb_dat = {{32-SPI_SS_NB{1'b0}}, ss}; + default: wb_dat = 32'bx; + endcase + end + endgenerate + // Wb data out always @(posedge wb_clk_i or posedge wb_rst_i) begin @@ -171,31 +204,55 @@ module spi_top end // Divider register - always @(posedge wb_clk_i or posedge wb_rst_i) - begin - if (wb_rst_i) - divider <= #Tp {`SPI_DIVIDER_LEN{1'b0}}; - else if (spi_divider_sel && wb_we_i && !tip) + generate if (SPI_DIVIDER_LEN < 9) + always @(posedge wb_clk_i or posedge wb_rst_i) + begin + if (wb_rst_i) + divider <= #Tp {SPI_DIVIDER_LEN{1'b0}}; + else if (spi_divider_sel && wb_we_i && !tip && wb_sel_i[0]) + divider <= #Tp wb_dat_i[SPI_DIVIDER_LEN-1:0]; + end + endgenerate + + generate if (SPI_DIVIDER_LEN >= 9 && SPI_DIVIDER_LEN <= 16) + always @(posedge wb_clk_i or posedge wb_rst_i) + begin + if (wb_rst_i) + divider <= #Tp {SPI_DIVIDER_LEN{1'b0}}; + else if (spi_divider_sel && wb_we_i && !tip) begin - `ifdef SPI_DIVIDER_LEN_8 - if (wb_sel_i[0]) - divider <= #Tp wb_dat_i[`SPI_DIVIDER_LEN-1:0]; - `endif - `ifdef SPI_DIVIDER_LEN_16 if (wb_sel_i[0]) divider[7:0] <= #Tp wb_dat_i[7:0]; if (wb_sel_i[1]) - divider[`SPI_DIVIDER_LEN-1:8] <= #Tp wb_dat_i[`SPI_DIVIDER_LEN-1:8]; - `endif - `ifdef SPI_DIVIDER_LEN_24 + divider[SPI_DIVIDER_LEN-1:8] <= #Tp wb_dat_i[SPI_DIVIDER_LEN-1:8]; + end + end + endgenerate + + generate if (SPI_DIVIDER_LEN >= 17 && SPI_DIVIDER_LEN <= 24) + always @(posedge wb_clk_i or posedge wb_rst_i) + begin + if (wb_rst_i) + divider <= #Tp {SPI_DIVIDER_LEN{1'b0}}; + else if (spi_divider_sel && wb_we_i && !tip) + begin if (wb_sel_i[0]) divider[7:0] <= #Tp wb_dat_i[7:0]; if (wb_sel_i[1]) divider[15:8] <= #Tp wb_dat_i[15:8]; if (wb_sel_i[2]) - divider[`SPI_DIVIDER_LEN-1:16] <= #Tp wb_dat_i[`SPI_DIVIDER_LEN-1:16]; - `endif - `ifdef SPI_DIVIDER_LEN_32 + divider[SPI_DIVIDER_LEN-1:16] <= #Tp wb_dat_i[SPI_DIVIDER_LEN-1:16]; + end + end + endgenerate + + generate if (SPI_DIVIDER_LEN >= 25 && SPI_DIVIDER_LEN <= 32) + always @(posedge wb_clk_i or posedge wb_rst_i) + begin + if (wb_rst_i) + divider <= #Tp {SPI_DIVIDER_LEN{1'b0}}; + else if (spi_divider_sel && wb_we_i && !tip) + begin if (wb_sel_i[0]) divider[7:0] <= #Tp wb_dat_i[7:0]; if (wb_sel_i[1]) @@ -203,10 +260,11 @@ module spi_top if (wb_sel_i[2]) divider[23:16] <= #Tp wb_dat_i[23:16]; if (wb_sel_i[3]) - divider[`SPI_DIVIDER_LEN-1:24] <= #Tp wb_dat_i[`SPI_DIVIDER_LEN-1:24]; - `endif + divider[SPI_DIVIDER_LEN-1:24] <= #Tp wb_dat_i[SPI_DIVIDER_LEN-1:24]; end - end + end + endgenerate + // Ctrl register always @(posedge wb_clk_i or posedge wb_rst_i) @@ -233,31 +291,55 @@ module spi_top assign ass = ctrl[`SPI_CTRL_ASS]; // Slave select register - always @(posedge wb_clk_i or posedge wb_rst_i) - begin - if (wb_rst_i) - ss <= #Tp {`SPI_SS_NB{1'b0}}; - else if(spi_ss_sel && wb_we_i && !tip) + generate if (SPI_SS_NB <= 8) + always @(posedge wb_clk_i or posedge wb_rst_i) + begin + if (wb_rst_i) + ss <= #Tp {SPI_SS_NB{1'b0}}; + else if(spi_ss_sel && wb_we_i && !tip && wb_sel_i[0]) + ss <= #Tp wb_dat_i[SPI_SS_NB-1:0]; + end + endgenerate + + generate if (SPI_SS_NB >= 9 && SPI_SS_NB <= 16) + always @(posedge wb_clk_i or posedge wb_rst_i) + begin + if (wb_rst_i) + ss <= #Tp {SPI_SS_NB{1'b0}}; + else if(spi_ss_sel && wb_we_i && !tip) begin - `ifdef SPI_SS_NB_8 - if (wb_sel_i[0]) - ss <= #Tp wb_dat_i[`SPI_SS_NB-1:0]; - `endif - `ifdef SPI_SS_NB_16 if (wb_sel_i[0]) ss[7:0] <= #Tp wb_dat_i[7:0]; if (wb_sel_i[1]) - ss[`SPI_SS_NB-1:8] <= #Tp wb_dat_i[`SPI_SS_NB-1:8]; - `endif - `ifdef SPI_SS_NB_24 + ss[SPI_SS_NB-1:8] <= #Tp wb_dat_i[SPI_SS_NB-1:8]; + end + end + endgenerate + + generate if (SPI_SS_NB >= 17 && SPI_SS_NB <= 24) + always @(posedge wb_clk_i or posedge wb_rst_i) + begin + if (wb_rst_i) + ss <= #Tp {SPI_SS_NB{1'b0}}; + else if(spi_ss_sel && wb_we_i && !tip) + begin if (wb_sel_i[0]) ss[7:0] <= #Tp wb_dat_i[7:0]; if (wb_sel_i[1]) ss[15:8] <= #Tp wb_dat_i[15:8]; if (wb_sel_i[2]) - ss[`SPI_SS_NB-1:16] <= #Tp wb_dat_i[`SPI_SS_NB-1:16]; - `endif - `ifdef SPI_SS_NB_32 + ss[SPI_SS_NB-1:16] <= #Tp wb_dat_i[SPI_SS_NB-1:16]; + end + end + endgenerate + + generate if (SPI_SS_NB >= 25 && SPI_SS_NB <= 32) + always @(posedge wb_clk_i or posedge wb_rst_i) + begin + if (wb_rst_i) + ss <= #Tp {SPI_SS_NB{1'b0}}; + else if(spi_ss_sel && wb_we_i && !tip) + begin if (wb_sel_i[0]) ss[7:0] <= #Tp wb_dat_i[7:0]; if (wb_sel_i[1]) @@ -265,18 +347,20 @@ module spi_top if (wb_sel_i[2]) ss[23:16] <= #Tp wb_dat_i[23:16]; if (wb_sel_i[3]) - ss[`SPI_SS_NB-1:24] <= #Tp wb_dat_i[`SPI_SS_NB-1:24]; - `endif + ss[SPI_SS_NB-1:24] <= #Tp wb_dat_i[SPI_SS_NB-1:24]; end - end - - assign ss_pad_o = ~((ss & {`SPI_SS_NB{tip & ass}}) | (ss & {`SPI_SS_NB{!ass}})); + end + endgenerate + + assign ss_pad_o = ~((ss & {SPI_SS_NB{tip & ass}}) | (ss & {SPI_SS_NB{!ass}})); - spi_clgen clgen (.clk_in(wb_clk_i), .rst(wb_rst_i), .go(go), .enable(tip), .last_clk(last_bit), + spi_clgen #(.SPI_DIVIDER_LEN(SPI_DIVIDER_LEN)) clgen + (.clk_in(wb_clk_i), .rst(wb_rst_i), .go(go), .enable(tip), .last_clk(last_bit), .divider(divider), .clk_out(sclk_pad_o), .pos_edge(pos_edge), .neg_edge(neg_edge)); - spi_shift shift (.clk(wb_clk_i), .rst(wb_rst_i), .len(char_len[`SPI_CHAR_LEN_BITS-1:0]), + spi_shift #(.SPI_MAX_CHAR(SPI_MAX_CHAR), .SPI_CHAR_LEN_BITS(SPI_CHAR_LEN_BITS)) shift + (.clk(wb_clk_i), .rst(wb_rst_i), .len(char_len[SPI_CHAR_LEN_BITS-1:0]), .latch(spi_tx_sel[3:0] & {4{wb_we_i}}), .byte_sel(wb_sel_i), .lsb(lsb), .go(go), .pos_edge(pos_edge), .neg_edge(neg_edge), .rx_negedge(rx_negedge), .tx_negedge(tx_negedge), diff --git a/modules/wishbone/wb_spi/wb_spi.vhd b/modules/wishbone/wb_spi/wb_spi.vhd index 3aa6d1a05d1ce8a085265a5ef6b9092032b83837..b31d8a6d8e91387e3a2af1282c1b35809c8994bc 100644 --- a/modules/wishbone/wb_spi/wb_spi.vhd +++ b/modules/wishbone/wb_spi/wb_spi.vhd @@ -6,7 +6,10 @@ use work.wishbone_pkg.all; entity wb_spi is generic ( g_interface_mode : t_wishbone_interface_mode := CLASSIC; - g_address_granularity : t_wishbone_address_granularity := WORD + g_address_granularity : t_wishbone_address_granularity := WORD; + g_divider_len : integer := 16; + g_max_char_len : integer := 128; + g_num_slaves : integer := 8 ); port( clk_sys_i : in std_logic; @@ -24,7 +27,7 @@ entity wb_spi is wb_int_o : out std_logic; wb_stall_o : out std_logic; - pad_cs_o : out std_logic_vector(7 downto 0); + pad_cs_o : out std_logic_vector(g_num_slaves-1 downto 0); pad_sclk_o : out std_logic; pad_mosi_o : out std_logic; pad_miso_i : in std_logic @@ -35,6 +38,12 @@ end wb_spi; architecture rtl of wb_spi is component spi_top + generic ( + SPI_DIVIDER_LEN : integer := 16; + SPI_MAX_CHAR : integer := 128; + SPI_CHAR_LEN_BITS : integer := 7; + SPI_SS_NB : integer := 8 + ); port ( wb_clk_i : in std_logic; wb_rst_i : in std_logic; @@ -49,7 +58,7 @@ architecture rtl of wb_spi is wb_err_o : out std_logic; wb_int_o : out std_logic; - ss_pad_o : out std_logic_vector(7 downto 0); + ss_pad_o : out std_logic_vector(SPI_SS_NB-1 downto 0); sclk_pad_o : out std_logic; mosi_pad_o : out std_logic; miso_pad_i : in std_logic); @@ -95,6 +104,11 @@ begin rst <= not rst_n_i; Wrapped_SPI : spi_top -- byte-aligned + generic map( + SPI_DIVIDER_LEN => g_divider_len, + SPI_MAX_CHAR => g_max_char_len, + SPI_CHAR_LEN_BITS => f_ceil_log2(g_max_char_len), + SPI_SS_NB => g_num_slaves) port map ( wb_clk_i => clk_sys_i, wb_rst_i => rst, diff --git a/modules/wishbone/wb_spi/xwb_spi.vhd b/modules/wishbone/wb_spi/xwb_spi.vhd index 26c2193351a568b76284b21b8d74c084b3692978..e54b3708003688fc55b61168287414e181a1788f 100644 --- a/modules/wishbone/wb_spi/xwb_spi.vhd +++ b/modules/wishbone/wb_spi/xwb_spi.vhd @@ -6,7 +6,10 @@ use work.wishbone_pkg.all; entity xwb_spi is generic( g_interface_mode : t_wishbone_interface_mode := CLASSIC; - g_address_granularity : t_wishbone_address_granularity := WORD + g_address_granularity : t_wishbone_address_granularity := WORD; + g_divider_len : integer := 16; + g_max_char_len : integer := 128; + g_num_slaves : integer := 8 ); port( @@ -18,7 +21,7 @@ entity xwb_spi is slave_o : out t_wishbone_slave_out; desc_o : out t_wishbone_device_descriptor; - pad_cs_o : out std_logic_vector(7 downto 0); + pad_cs_o : out std_logic_vector(g_num_slaves-1 downto 0); pad_sclk_o : out std_logic; pad_mosi_o : out std_logic; pad_miso_i : in std_logic @@ -31,7 +34,10 @@ architecture rtl of xwb_spi is component wb_spi generic ( g_interface_mode : t_wishbone_interface_mode; - g_address_granularity : t_wishbone_address_granularity); + g_address_granularity : t_wishbone_address_granularity; + g_divider_len : integer := 16; + g_max_char_len : integer := 128; + g_num_slaves : integer := 8); port ( clk_sys_i : in std_logic; rst_n_i : in std_logic; @@ -46,7 +52,7 @@ architecture rtl of xwb_spi is wb_err_o : out std_logic; wb_int_o : out std_logic; wb_stall_o : out std_logic; - pad_cs_o : out std_logic_vector(7 downto 0); + pad_cs_o : out std_logic_vector(g_num_slaves-1 downto 0); pad_sclk_o : out std_logic; pad_mosi_o : out std_logic; pad_miso_i : in std_logic); @@ -57,7 +63,10 @@ begin U_Wrapped_SPI: wb_spi generic map ( g_interface_mode => g_interface_mode, - g_address_granularity => g_address_granularity) + g_address_granularity => g_address_granularity, + g_divider_len => g_divider_len, + g_max_char_len => g_max_char_len, + g_num_slaves => g_num_slaves) port map ( clk_sys_i => clk_sys_i, rst_n_i => rst_n_i, diff --git a/modules/wishbone/wishbone_pkg.vhd b/modules/wishbone/wishbone_pkg.vhd index 33f22c1bf75d404af9b29dce82bb7ff93e1d9660..9423b57b4544174cb4776f4ef793e41b6e34ea99 100644 --- a/modules/wishbone/wishbone_pkg.vhd +++ b/modules/wishbone/wishbone_pkg.vhd @@ -674,7 +674,10 @@ package wishbone_pkg is component wb_spi generic ( g_interface_mode : t_wishbone_interface_mode := CLASSIC; - g_address_granularity : t_wishbone_address_granularity := WORD); + g_address_granularity : t_wishbone_address_granularity := WORD; + g_divider_len : integer := 16; + g_max_char_len : integer := 128; + g_num_slaves : integer := 8); port ( clk_sys_i : in std_logic; rst_n_i : in std_logic; @@ -689,7 +692,7 @@ package wishbone_pkg is wb_err_o : out std_logic; wb_int_o : out std_logic; wb_stall_o : out std_logic; - pad_cs_o : out std_logic_vector(7 downto 0); + pad_cs_o : out std_logic_vector(g_num_slaves-1 downto 0); pad_sclk_o : out std_logic; pad_mosi_o : out std_logic; pad_miso_i : in std_logic); @@ -698,14 +701,17 @@ package wishbone_pkg is component xwb_spi generic ( g_interface_mode : t_wishbone_interface_mode := CLASSIC; - g_address_granularity : t_wishbone_address_granularity := WORD); + g_address_granularity : t_wishbone_address_granularity := WORD; + g_divider_len : integer := 16; + g_max_char_len : integer := 128; + g_num_slaves : integer := 8); port ( clk_sys_i : in std_logic; rst_n_i : in std_logic; slave_i : in t_wishbone_slave_in; slave_o : out t_wishbone_slave_out; desc_o : out t_wishbone_device_descriptor; - pad_cs_o : out std_logic_vector(7 downto 0); + pad_cs_o : out std_logic_vector(g_num_slaves-1 downto 0); pad_sclk_o : out std_logic; pad_mosi_o : out std_logic; pad_miso_i : in std_logic);