@@ -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