Skip to content

Commit dd83c52

Browse files
committed
library/spi_engine: Update for SDO extension
* Extend SDO support to 8 (symmetrical with SDI support); * Update SDI to use asymmetrical FIFO; * Insert symmetrical FIFO for the SDO; * Insert SDI lane mask configuration instruction to reg 3'b011; * Insert SDO lane mask configuration instruction to reg 3'b100; * Insert offload active interface for interconnect and execution; * Remove register 8'h3b from spi engine regmap; * Improvements on the critical paths of the execution module. Prefetching on offload work iff all lanes are active. Signed-off-by: Carlos Souza <carlos.souza@analog.com>
1 parent 9527efc commit dd83c52

File tree

14 files changed

+530
-225
lines changed

14 files changed

+530
-225
lines changed

library/spi_engine/axi_spi_engine/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ XILINX_DEPS += ../../spi_engine/interfaces/spi_engine_offload_ctrl.xml
2020
XILINX_DEPS += ../../spi_engine/interfaces/spi_engine_offload_ctrl_rtl.xml
2121

2222
XILINX_LIB_DEPS += util_axis_fifo
23+
XILINX_LIB_DEPS += util_axis_fifo_asym
2324
XILINX_LIB_DEPS += util_cdc
2425

2526
XILINX_INTERFACE_DEPS += spi_engine/interfaces

library/spi_engine/axi_spi_engine/axi_spi_engine.v

Lines changed: 132 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -106,11 +106,11 @@ module axi_spi_engine #(
106106

107107
input sdo_data_ready,
108108
output sdo_data_valid,
109-
output [(DATA_WIDTH-1):0] sdo_data,
109+
output [(DATA_WIDTH)-1:0] sdo_data,
110110

111111
output sdi_data_ready,
112112
input sdi_data_valid,
113-
input [(NUM_OF_SDI * DATA_WIDTH-1):0] sdi_data,
113+
input [(NUM_OF_SDI * DATA_WIDTH)-1:0] sdi_data,
114114

115115
output sync_ready,
116116
input sync_valid,
@@ -122,7 +122,7 @@ module axi_spi_engine #(
122122
output [15:0] offload0_cmd_wr_data,
123123

124124
output offload0_sdo_wr_en,
125-
output [(DATA_WIDTH-1):0] offload0_sdo_wr_data,
125+
output [(DATA_WIDTH)-1:0] offload0_sdo_wr_data,
126126

127127
output offload0_mem_reset,
128128
output offload0_enable,
@@ -133,9 +133,10 @@ module axi_spi_engine #(
133133
input [7:0] offload_sync_data
134134
);
135135

136-
localparam PCORE_VERSION = 'h010501;
136+
localparam PCORE_VERSION = 'h010600;
137137
localparam S_AXI = 0;
138138
localparam UP_FIFO = 1;
139+
localparam max_num_of_reads = NUM_OF_SDI-1;
139140

140141
wire clk;
141142
wire rstn;
@@ -152,17 +153,19 @@ module axi_spi_engine #(
152153
wire sdo_fifo_almost_empty;
153154
wire up_sdo_fifo_almost_empty;
154155

155-
wire [(DATA_WIDTH-1):0] sdo_fifo_in_data;
156+
wire [DATA_WIDTH-1:0] sdo_fifo_in_data;
156157
wire sdo_fifo_in_ready;
157158
wire sdo_fifo_in_valid;
158159

159-
wire sdi_fifo_out_data_msb_s;
160-
wire [SDI_FIFO_ADDRESS_WIDTH-1:0] sdi_fifo_level;
160+
wire [31:0] sdi_fifo_level;
161+
reg [NUM_OF_SDI*DATA_WIDTH/8-1:0] sdi_fifo_tkeep_int;
162+
wire [NUM_OF_SDI*DATA_WIDTH/8-1:0] sdi_fifo_tkeep;
161163
wire sdi_fifo_almost_full;
162164
wire up_sdi_fifo_almost_full;
163165

164-
wire [(NUM_OF_SDI * DATA_WIDTH-1):0] sdi_fifo_out_data;
166+
wire [DATA_WIDTH-1:0] sdi_fifo_out_data;
165167
wire sdi_fifo_out_ready;
168+
reg find_next_valid_fifo_value;
166169
wire sdi_fifo_out_valid;
167170

168171
wire [7:0] sync_fifo_data;
@@ -317,23 +320,6 @@ module axi_spi_engine #(
317320
end
318321
end
319322

320-
always @(posedge clk) begin
321-
if (rstn == 1'b0) begin
322-
up_rack_ff <= 'd0;
323-
end else begin
324-
up_rack_ff <= up_rreq_s;
325-
end
326-
end
327-
328-
generate
329-
if (NUM_OF_SDI > 1) begin
330-
// Only the first two SDI data can be recovered through AXI regmap
331-
assign sdi_fifo_out_data_msb_s = sdi_fifo_out_data[DATA_WIDTH+:DATA_WIDTH];
332-
end else begin
333-
assign sdi_fifo_out_data_msb_s = sdi_fifo_out_data;
334-
end
335-
endgenerate
336-
337323
reg [7:0] offload_sdo_mem_address_width = OFFLOAD0_SDO_MEM_ADDRESS_WIDTH;
338324
reg [7:0] offload_cmd_mem_address_width = OFFLOAD0_CMD_MEM_ADDRESS_WIDTH;
339325
reg [7:0] sdi_fifo_address_width = SDI_FIFO_ADDRESS_WIDTH;
@@ -356,10 +342,9 @@ module axi_spi_engine #(
356342
8'h31: up_rdata_ff <= offload_sync_id;
357343
8'h34: up_rdata_ff <= cmd_fifo_room;
358344
8'h35: up_rdata_ff <= sdo_fifo_room;
359-
8'h36: up_rdata_ff <= (sdi_fifo_out_valid == 1) ? sdi_fifo_level + 1 : sdi_fifo_level; /* beacuse of first-word-fall-through */
345+
8'h36: up_rdata_ff <= (sdi_fifo_out_valid == 1) ? sdi_fifo_level + 1 : sdi_fifo_level; /* because of first-word-fall-through */
360346
8'h3a: up_rdata_ff <= sdi_fifo_out_data[DATA_WIDTH-1:0];
361-
8'h3b: up_rdata_ff <= sdi_fifo_out_data_msb_s; /* store SDI's 32 bits MSB, if exists */
362-
8'h3c: up_rdata_ff <= sdi_fifo_out_data; /* PEEK register */
347+
8'h3c: up_rdata_ff <= sdi_fifo_out_data[DATA_WIDTH-1:0]; /* PEEK register */
363348
8'h40: up_rdata_ff <= {offload0_enable_reg};
364349
8'h41: up_rdata_ff <= {offload0_enabled_s};
365350
8'h80: up_rdata_ff <= CFG_INFO_0;
@@ -421,7 +406,9 @@ module axi_spi_engine #(
421406
.ASYNC_CLK(ASYNC_SPI_CLK),
422407
.M_AXIS_REGISTERED(0),
423408
.ALMOST_EMPTY_THRESHOLD(1),
424-
.ALMOST_FULL_THRESHOLD(1)
409+
.ALMOST_FULL_THRESHOLD(1),
410+
.TLAST_EN(0),
411+
.TKEEP_EN(0)
425412
) i_cmd_fifo (
426413
.s_axis_aclk(clk),
427414
.s_axis_aresetn(up_sw_resetn),
@@ -430,22 +417,25 @@ module axi_spi_engine #(
430417
.s_axis_data(cmd_fifo_in_data),
431418
.s_axis_room(cmd_fifo_room),
432419
.s_axis_tlast(1'b0),
420+
.s_axis_tkeep(),
433421
.s_axis_full(),
434422
.s_axis_almost_full(),
423+
435424
.m_axis_aclk(spi_clk),
436425
.m_axis_aresetn(spi_resetn),
437426
.m_axis_ready(cmd_ready),
438427
.m_axis_valid(cmd_valid),
439428
.m_axis_data(cmd_data),
440429
.m_axis_tlast(),
430+
.m_axis_tkeep(),
431+
.m_axis_level(),
441432
.m_axis_empty(),
442-
.m_axis_almost_empty(cmd_fifo_almost_empty),
443-
.m_axis_level());
433+
.m_axis_almost_empty(cmd_fifo_almost_empty));
444434

445435
assign sdo_fifo_in_valid = up_wreq_s == 1'b1 && up_waddr_s == 8'h39;
446-
assign sdo_fifo_in_data = up_wdata_s[(DATA_WIDTH-1):0];
436+
assign sdo_fifo_in_data = up_wdata_s[DATA_WIDTH-1:0];
447437

448-
util_axis_fifo #(
438+
util_axis_fifo #(
449439
.DATA_WIDTH(DATA_WIDTH),
450440
.ASYNC_CLK(ASYNC_SPI_CLK),
451441
.ADDRESS_WIDTH(SDO_FIFO_ADDRESS_WIDTH),
@@ -460,6 +450,7 @@ module axi_spi_engine #(
460450
.s_axis_data(sdo_fifo_in_data),
461451
.s_axis_room(sdo_fifo_room),
462452
.s_axis_tlast(1'b0),
453+
.s_axis_tkeep(),
463454
.s_axis_full(),
464455
.s_axis_almost_full(),
465456
.m_axis_aclk(spi_clk),
@@ -468,62 +459,128 @@ module axi_spi_engine #(
468459
.m_axis_valid(sdo_data_valid),
469460
.m_axis_data(sdo_data),
470461
.m_axis_tlast(),
462+
.m_axis_tkeep(),
471463
.m_axis_level(),
472464
.m_axis_empty(),
473465
.m_axis_almost_empty(sdo_fifo_almost_empty));
474466

475467
assign sdi_fifo_out_ready = up_rreq_s == 1'b1 && up_raddr_s == 8'h3a;
476468

477-
util_axis_fifo #(
478-
.DATA_WIDTH(NUM_OF_SDI * DATA_WIDTH),
469+
integer i;
470+
always @(posedge spi_clk) begin
471+
if (!spi_resetn) begin
472+
sdi_fifo_tkeep_int <= {(NUM_OF_SDI*DATA_WIDTH/8){1'b1}};
473+
end else begin
474+
if (cmd_valid && cmd_data[15:8] == 8'h23) begin
475+
for (i = 0; i < NUM_OF_SDI; i = i + 1) begin
476+
sdi_fifo_tkeep_int[i*DATA_WIDTH/8+:DATA_WIDTH/8] <= {DATA_WIDTH/8{cmd_data[i]}};
477+
end
478+
end
479+
end
480+
end
481+
assign sdi_fifo_tkeep = sdi_fifo_tkeep_int;
482+
483+
util_axis_fifo_asym #(
479484
.ASYNC_CLK(ASYNC_SPI_CLK),
480-
.ADDRESS_WIDTH(SDI_FIFO_ADDRESS_WIDTH),
485+
.S_DATA_WIDTH(NUM_OF_SDI * DATA_WIDTH),
486+
.M_DATA_WIDTH(DATA_WIDTH),
487+
.ADDRESS_WIDTH(SDO_FIFO_ADDRESS_WIDTH),
481488
.M_AXIS_REGISTERED(0),
482489
.ALMOST_EMPTY_THRESHOLD(1),
483-
.ALMOST_FULL_THRESHOLD(31)
484-
) i_sdi_fifo (
490+
.ALMOST_FULL_THRESHOLD(1),
491+
.TLAST_EN(0),
492+
.TKEEP_EN(1),
493+
.REDUCED_FIFO(0)
494+
) i_sdi_fifo(
485495
.s_axis_aclk(spi_clk),
486496
.s_axis_aresetn(spi_resetn),
487497
.s_axis_ready(sdi_data_ready),
488498
.s_axis_valid(sdi_data_valid),
489499
.s_axis_data(sdi_data),
490500
.s_axis_room(),
491501
.s_axis_tlast(),
502+
.s_axis_tkeep(sdi_fifo_tkeep),
492503
.s_axis_full(),
493504
.s_axis_almost_full(sdi_fifo_almost_full),
505+
494506
.m_axis_aclk(clk),
495507
.m_axis_aresetn(up_sw_resetn),
496-
.m_axis_ready(sdi_fifo_out_ready),
508+
.m_axis_ready(sdi_fifo_out_ready || find_next_valid_fifo_value),
497509
.m_axis_valid(sdi_fifo_out_valid),
498510
.m_axis_data(sdi_fifo_out_data),
499511
.m_axis_tlast(),
512+
.m_axis_tkeep(),
500513
.m_axis_level(sdi_fifo_level),
501514
.m_axis_empty(),
502515
.m_axis_almost_empty());
503516

517+
assign sdi_fifo_out_ready = up_rreq_s == 1'b1 && up_raddr_s == 8'h3a;
518+
519+
reg [3:0] sdi_out_counter;
520+
reg find_next_valid_fifo_value;
521+
always @(posedge clk) begin
522+
if (rstn == 1'b0) begin
523+
up_rack_ff <= 'd0;
524+
end else begin
525+
if (sdi_fifo_out_ready || find_next_valid_fifo_value) begin
526+
up_rack_ff <= sdi_fifo_out_valid;
527+
end else begin
528+
up_rack_ff <= up_rreq_s;
529+
end
530+
end
531+
end
532+
533+
//the current logic is considering that there is only one active lane in the set of lanes
534+
always @(posedge clk) begin
535+
if (!up_sw_resetn) begin
536+
find_next_valid_fifo_value <= 1'b0;
537+
sdi_out_counter <= 4'hf;
538+
end else if (sdi_fifo_out_ready) begin
539+
find_next_valid_fifo_value <= ~sdi_fifo_out_valid; //only in the next cycle it is possible to check if it is necessary a new read
540+
sdi_out_counter <= sdi_fifo_out_valid ? 4'hf : 0;
541+
end else begin
542+
if (!sdi_fifo_out_valid && sdi_out_counter < max_num_of_reads) begin
543+
find_next_valid_fifo_value <= 1'b1;
544+
sdi_out_counter <= sdi_out_counter + 1'b1;
545+
end else begin
546+
find_next_valid_fifo_value <= 1'b0;
547+
sdi_out_counter <= 4'hf;
548+
end
549+
end
550+
end
551+
504552
generate if (ASYNC_SPI_CLK) begin
505553

506554
// synchronization FIFO for the SYNC interface
507555
util_axis_fifo #(
508556
.DATA_WIDTH(8),
509557
.ASYNC_CLK(ASYNC_SPI_CLK),
510558
.ADDRESS_WIDTH(SYNC_FIFO_ADDRESS_WIDTH),
511-
.M_AXIS_REGISTERED(0)
559+
.M_AXIS_REGISTERED(0),
560+
.TLAST_EN(0),
561+
.TKEEP_EN(0)
512562
) i_sync_fifo (
513563
.s_axis_aclk(spi_clk),
514564
.s_axis_aresetn(spi_resetn),
515565
.s_axis_ready(sync_ready),
516566
.s_axis_valid(sync_valid),
517567
.s_axis_data(sync_data),
518568
.s_axis_room(),
569+
.s_axis_tlast(),
570+
.s_axis_tkeep(),
519571
.s_axis_full(),
572+
.s_axis_almost_full(),
573+
520574
.m_axis_aclk(clk),
521575
.m_axis_aresetn(up_sw_resetn),
522576
.m_axis_ready(1'b1),
523577
.m_axis_valid(sync_fifo_valid),
524578
.m_axis_data(sync_fifo_data),
579+
.m_axis_tlast(),
580+
.m_axis_tkeep(),
525581
.m_axis_level(),
526-
.m_axis_empty());
582+
.m_axis_empty(),
583+
.m_axis_almost_empty());
527584

528585
// synchronization FIFO for the offload command interface
529586
wire up_offload0_cmd_wr_en_s;
@@ -533,50 +590,68 @@ module axi_spi_engine #(
533590
.DATA_WIDTH(16),
534591
.ASYNC_CLK(ASYNC_SPI_CLK),
535592
.ADDRESS_WIDTH(SYNC_FIFO_ADDRESS_WIDTH),
536-
.M_AXIS_REGISTERED(0)
593+
.M_AXIS_REGISTERED(0),
594+
.TLAST_EN(0),
595+
.TKEEP_EN(0)
537596
) i_offload_cmd_fifo (
538597
.s_axis_aclk(clk),
539598
.s_axis_aresetn(up_sw_resetn),
540599
.s_axis_ready(),
541600
.s_axis_valid(up_offload0_cmd_wr_en_s),
542601
.s_axis_data(up_offload0_cmd_wr_data_s),
543602
.s_axis_room(),
603+
.s_axis_tlast(),
604+
.s_axis_tkeep(),
544605
.s_axis_full(),
606+
.s_axis_almost_full(),
607+
545608
.m_axis_aclk(spi_clk),
546609
.m_axis_aresetn(spi_resetn),
547610
.m_axis_ready(1'b1),
548611
.m_axis_valid(offload0_cmd_wr_en),
549612
.m_axis_data(offload0_cmd_wr_data),
613+
.m_axis_tlast(),
614+
.m_axis_tkeep(),
550615
.m_axis_level(),
551-
.m_axis_empty());
616+
.m_axis_empty(),
617+
.m_axis_almost_empty());
552618

553619
assign up_offload0_cmd_wr_en_s = up_wreq_s == 1'b1 && up_waddr_s == 8'h44;
554620
assign up_offload0_cmd_wr_data_s = up_wdata_s[15:0];
555621

556622
// synchronization FIFO for the offload SDO interface
557623
wire up_offload0_sdo_wr_en_s;
558-
wire [DATA_WIDTH-1:0] up_offload0_sdo_wr_data_s;
624+
wire [(DATA_WIDTH-1):0] up_offload0_sdo_wr_data_s;
559625

560626
util_axis_fifo #(
561627
.DATA_WIDTH(DATA_WIDTH),
562628
.ASYNC_CLK(ASYNC_SPI_CLK),
563629
.ADDRESS_WIDTH(SYNC_FIFO_ADDRESS_WIDTH),
564-
.M_AXIS_REGISTERED(0)
630+
.M_AXIS_REGISTERED(0),
631+
.TLAST_EN(0),
632+
.TKEEP_EN(0)
565633
) i_offload_sdo_fifo (
566634
.s_axis_aclk(clk),
567635
.s_axis_aresetn(up_sw_resetn),
568636
.s_axis_ready(),
569637
.s_axis_valid(up_offload0_sdo_wr_en_s),
570638
.s_axis_data(up_offload0_sdo_wr_data_s),
571639
.s_axis_room(),
640+
.s_axis_tlast(),
641+
.s_axis_tkeep(),
572642
.s_axis_full(),
643+
.s_axis_almost_full(),
644+
573645
.m_axis_aclk(spi_clk),
574646
.m_axis_aresetn(spi_resetn),
575647
.m_axis_ready(1'b1),
576648
.m_axis_valid(offload0_sdo_wr_en),
577649
.m_axis_data(offload0_sdo_wr_data),
650+
.m_axis_tlast(),
651+
.m_axis_tkeep(),
578652
.m_axis_level(),
579-
.m_axis_empty());
653+
.m_axis_empty(),
654+
.m_axis_almost_empty());
580655

581656
assign up_offload0_sdo_wr_en_s = up_wreq_s == 1'b1 && up_waddr_s == 8'h45;
582657
assign up_offload0_sdo_wr_data_s = up_wdata_s[DATA_WIDTH-1:0];
@@ -586,22 +661,31 @@ module axi_spi_engine #(
586661
.DATA_WIDTH(8),
587662
.ASYNC_CLK(ASYNC_SPI_CLK),
588663
.ADDRESS_WIDTH(SYNC_FIFO_ADDRESS_WIDTH),
589-
.M_AXIS_REGISTERED(0)
664+
.M_AXIS_REGISTERED(0),
665+
.TLAST_EN(0),
666+
.TKEEP_EN(0)
590667
) i_offload_sync_fifo (
591668
.s_axis_aclk(spi_clk),
592669
.s_axis_aresetn(spi_resetn),
593670
.s_axis_ready(offload_sync_ready),
594671
.s_axis_valid(offload_sync_valid),
595672
.s_axis_data(offload_sync_data),
596673
.s_axis_room(),
674+
.s_axis_tlast(),
675+
.s_axis_tkeep(),
597676
.s_axis_full(),
677+
.s_axis_almost_full(),
678+
598679
.m_axis_aclk(clk),
599680
.m_axis_aresetn(up_sw_resetn),
600681
.m_axis_ready(1'b1),
601682
.m_axis_valid(offload_sync_fifo_valid),
602683
.m_axis_data(offload_sync_fifo_data),
684+
.m_axis_tlast(),
685+
.m_axis_tkeep(),
603686
.m_axis_level(),
604-
.m_axis_empty());
687+
.m_axis_empty(),
688+
.m_axis_almost_empty());
605689

606690
end else begin /* ASYNC_SPI_CLK == 0 */
607691

0 commit comments

Comments
 (0)