From e757859b56f4a15b8c99c68f48b36ac5cd96ca11 Mon Sep 17 00:00:00 2001 From: LBFFilho Date: Wed, 8 May 2024 11:19:37 -0300 Subject: [PATCH] SPI Engine: create inverted CS mode (#1301) SPI Engine: create inverted CS mode Add a CS Invert Mask instruction for selecting the polarity of the Chip Select pins. Signed-off-by: Laez Barbosa --- .../library/spi_engine/instruction-format.rst | 62 +++++++++++++++++-- docs/regmap/adi_regmap_spi_engine.txt | 8 +-- .../axi_spi_engine/axi_spi_engine.v | 2 +- .../spi_engine_execution.v | 31 +++++++--- 4 files changed, 85 insertions(+), 18 deletions(-) diff --git a/docs/library/spi_engine/instruction-format.rst b/docs/library/spi_engine/instruction-format.rst index 9c296d603..a0606af45 100644 --- a/docs/library/spi_engine/instruction-format.rst +++ b/docs/library/spi_engine/instruction-format.rst @@ -4,7 +4,7 @@ SPI Engine Instruction Set Specification ================================================================================ The SPI Engine instruction set is a simple 16-bit instruction set of which -12-bit is currently allocated (bits 15,14,11,10 are always 0). +13-bits are currently allocated (bits 15,11,10 are always 0). Instructions -------------------------------------------------------------------------------- @@ -48,7 +48,10 @@ accepted/becomes available. - Length - n + 1 number of words that will be transferred. -Chip-select Instruction + +.. _spi_engine cs-instruction: + +Chip-Select Instruction ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ == == == == == == = = = = = = = = = = @@ -60,6 +63,13 @@ Chip-select Instruction The chip-select instruction updates the value chip-select output signal of the SPI Engine execution module. +The physical outputs on each pin may be inverted relative to the command +according to the mask set by :ref:`spi_engine cs-invert-mask-instruction`. The +Invert Mask acts only on the output registers of the Chip-Select pins. Thus, if +the last 8 bits of the Chip-Select instruction are 0xFE, only CS[0] will be +active regardless of polarity. The polarity inversion process (if needed) is +transparent to the programmer. + Before and after the update is performed the execution module is paused for the specified delay. The length of the delay depends on the module clock frequency, the setting of the prescaler register and the parameter :math:`t` of the @@ -98,7 +108,7 @@ Configuration Write Instruction == == == == == == = = = = = = = = = = The configuration writes instruction updates a -:ref:`spi_engine configutarion-registers` +:ref:`spi_engine configuration-registers` of the SPI Engine execution module with a new value. .. list-table:: @@ -174,7 +184,51 @@ is the minimum, needed by the internal logic. - Time - The amount of time to wait. -.. _spi_engine configutarion-registers: +.. _spi_engine cs-invert-mask-instruction: + +CS Invert Mask Instruction +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +== == == == == == = = = = = = = = = = +15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +== == == == == == = = = = = = = = = = +0 1 0 0 r r r r m m m m m m m m +== == == == == == = = = = = = = = = = + +The CS Invert Mask Instructions allows the user to select on a per-pin basis +whether the Chip Select will be active-low (default) or active-high (inverted). +Note that the Chip-Select instructions should remain the same because the value +of CS is inverted at the output register, and additional logic (e.g. reset +counters) occurs when the CS active state is asserted. + +Since the physical values on the pins are inverted at the output, the current +Invert Mask does not affect the use of the :ref:`spi_engine cs-instruction`. As +an example, a Chip-Select Instruction with the 's' field equal to 0xFE will +always result in only CS[0] being active. For an Invert Mask of 0xFF, this would +result on only CS[0] being high. For an Invert Mask of 0x00, this would result +on only CS[0] being low. For an Invert Mask of 0x01, this would result on all CS +pins being high, but only CS[0] is active in this case (since it's the only one +currently treated as active-high). + +This was introduced in +version 1.02.00 of the core. + +.. list-table:: + :widths: 10 15 75 + :header-rows: 1 + + * - Bits + - Name + - Description + * - r + - reserved + - Reserved for future use. Must always be set to 0. + * - m + - Mask + - Mask for selecting inverted CS channels. For the bits set to 1, the + corresponding channel will be inverted at the output. + +.. _spi_engine configuration-registers: Configuration Registers -------------------------------------------------------------------------------- diff --git a/docs/regmap/adi_regmap_spi_engine.txt b/docs/regmap/adi_regmap_spi_engine.txt index b4793bb94..99192ab42 100644 --- a/docs/regmap/adi_regmap_spi_engine.txt +++ b/docs/regmap/adi_regmap_spi_engine.txt @@ -9,23 +9,23 @@ ENDTITLE REG 0x00 VERSION -Version of the peripheral. Follows semantic versioning. Current version 1.00.71. +Version of the peripheral. Follows semantic versioning. Current version 1.02.00. ENDREG FIELD -[31:16] 0x01 +[31:16] 0x00000001 VERSION_MAJOR RO ENDFIELD FIELD -[15:8] 0x01 +[15:8] 0x00000002 VERSION_MINOR RO ENDFIELD FIELD -[7:0] 0x71 +[7:0] 0x00000000 VERSION_PATCH RO ENDFIELD diff --git a/library/spi_engine/axi_spi_engine/axi_spi_engine.v b/library/spi_engine/axi_spi_engine/axi_spi_engine.v index 45778d711..cafe2e090 100644 --- a/library/spi_engine/axi_spi_engine/axi_spi_engine.v +++ b/library/spi_engine/axi_spi_engine/axi_spi_engine.v @@ -133,7 +133,7 @@ module axi_spi_engine #( input [7:0] offload_sync_data ); - localparam PCORE_VERSION = 'h010171; + localparam PCORE_VERSION = 'h010200; localparam S_AXI = 0; localparam UP_FIFO = 1; diff --git a/library/spi_engine/spi_engine_execution/spi_engine_execution.v b/library/spi_engine/spi_engine_execution/spi_engine_execution.v index 0fc7c3ef6..d046d4dfd 100644 --- a/library/spi_engine/spi_engine_execution/spi_engine_execution.v +++ b/library/spi_engine/spi_engine_execution/spi_engine_execution.v @@ -1,6 +1,6 @@ // *************************************************************************** // *************************************************************************** -// Copyright (C) 2015-2023 Analog Devices, Inc. All rights reserved. +// Copyright (C) 2015-2024 Analog Devices, Inc. All rights reserved. // // In this HDL repository, there are many different and unique modules, consisting // of various HDL (Verilog or VHDL) components. The individual modules are @@ -76,10 +76,11 @@ module spi_engine_execution #( output reg three_wire ); - localparam CMD_TRANSFER = 2'b00; - localparam CMD_CHIPSELECT = 2'b01; - localparam CMD_WRITE = 2'b10; - localparam CMD_MISC = 2'b11; + localparam CMD_TRANSFER = 3'b000; + localparam CMD_CHIPSELECT = 3'b001; + localparam CMD_WRITE = 3'b010; + localparam CMD_MISC = 3'b011; + localparam CMD_CS_INV = 3'b100; localparam MISC_SYNC = 1'b0; localparam MISC_SLEEP = 1'b1; @@ -134,6 +135,8 @@ module spi_engine_execution #( reg cpol = DEFAULT_SPI_CFG[1]; reg [7:0] clk_div = DEFAULT_CLK_DIV; + reg [NUM_OF_CS-1:0] cs_inv_mask_reg = 'h0; + reg sdo_enabled = 1'b0; reg sdi_enabled = 1'b0; @@ -141,12 +144,12 @@ module spi_engine_execution #( reg [SDI_DELAY+1:0] trigger_rx_d = {(SDI_DELAY+2){1'b0}}; - wire [1:0] inst = cmd[13:12]; - wire [1:0] inst_d1 = cmd_d1[13:12]; + wire [2:0] inst = cmd[14:12]; + wire [2:0] inst_d1 = cmd_d1[14:12]; wire exec_cmd = cmd_ready && cmd_valid; wire exec_transfer_cmd = exec_cmd && inst == CMD_TRANSFER; - + wire exec_cs_inv_cmd = exec_cmd && inst == CMD_CS_INV; wire exec_write_cmd = exec_cmd && inst == CMD_WRITE; wire exec_chipselect_cmd = exec_cmd && inst == CMD_CHIPSELECT; wire exec_misc_cmd = exec_cmd && inst == CMD_MISC; @@ -306,11 +309,21 @@ module spi_engine_execution #( end end + always @(posedge clk ) begin + if (resetn == 1'b0) begin + cs_inv_mask_reg <= 'h0; + end else begin + if (exec_cs_inv_cmd == 1'b1) begin + cs_inv_mask_reg <= cmd[NUM_OF_CS-1:0]; + end + end + end + always @(posedge clk) begin if (resetn == 1'b0) begin cs <= 'hff; end else if (cs_gen) begin - cs <= cmd_d1[NUM_OF_CS-1:0]; + cs <= cmd_d1[NUM_OF_CS-1:0]^cs_inv_mask_reg[NUM_OF_CS-1:0]; end end