diff --git a/hw/ip/spi_host/data/spi_host.hjson b/hw/ip/spi_host/data/spi_host.hjson index 86389e5879fc0..a196d4668620a 100644 --- a/hw/ip/spi_host/data/spi_host.hjson +++ b/hw/ip/spi_host/data/spi_host.hjson @@ -445,7 +445,22 @@ the device.''', resval: "0x0" }, - { bits: "8:0", + ], + tags: [// Triggers exceptions if registers are improperly configured + // Exclude from RW tests + "excl:CsrAllTests:CsrExclWrite"] + }, + { name: "COMMAND_LEN", + desc: '''Command length Register for a single command segment. + + Parameters specific to each command segment. Unlike the !!CONFIGOPTS multi-register, + there is only one command length register for controlling all attached SPI devices''', + swaccess: "wo", + hwaccess: "hro", + hwext: "true", + hwqe: "true", + fields: [ + { bits: "31:0", name: "LEN", desc: '''Segment Length. @@ -460,10 +475,7 @@ resval: "0x0" }, ], - tags: [// Triggers exceptions if registers are improperly configured - // Exclude from RW tests - "excl:CsrAllTests:CsrExclWrite"] - }, + } { window: { name: "RXDATA", items: "1", diff --git a/hw/ip/spi_host/doc/registers.md b/hw/ip/spi_host/doc/registers.md index df17ebc3a29d1..be5ddced40e64 100644 --- a/hw/ip/spi_host/doc/registers.md +++ b/hw/ip/spi_host/doc/registers.md @@ -14,11 +14,12 @@ | spi_host.[`CONFIGOPTS`](#configopts) | 0x18 | 4 | Configuration options register. | | spi_host.[`CSID`](#csid) | 0x1c | 4 | Chip-Select ID | | spi_host.[`COMMAND`](#command) | 0x20 | 4 | Command Register | -| spi_host.[`RXDATA`](#rxdata) | 0x24 | 4 | SPI Receive Data. | -| spi_host.[`TXDATA`](#txdata) | 0x28 | 4 | SPI Transmit Data. | -| spi_host.[`ERROR_ENABLE`](#error_enable) | 0x2c | 4 | Controls which classes of errors raise an interrupt. | -| spi_host.[`ERROR_STATUS`](#error_status) | 0x30 | 4 | Indicates that any errors that have occurred. | -| spi_host.[`EVENT_ENABLE`](#event_enable) | 0x34 | 4 | Controls which classes of SPI events raise an interrupt. | +| spi_host.[`COMMAND_LEN`](#command_len) | 0x24 | 4 | Command length Register for a single command segment. | +| spi_host.[`RXDATA`](#rxdata) | 0x28 | 4 | SPI Receive Data. | +| spi_host.[`TXDATA`](#txdata) | 0x2c | 4 | SPI Transmit Data. | +| spi_host.[`ERROR_ENABLE`](#error_enable) | 0x30 | 4 | Controls which classes of errors raise an interrupt. | +| spi_host.[`ERROR_STATUS`](#error_status) | 0x34 | 4 | Indicates that any errors that have occurred. | +| spi_host.[`EVENT_ENABLE`](#event_enable) | 0x38 | 4 | Controls which classes of SPI events raise an interrupt. | ## INTR_STATE Interrupt State Register @@ -276,12 +277,12 @@ Command Register there is only one command register for controlling all attached SPI devices - Offset: `0x20` - Reset default: `0x0` -- Reset mask: `0x3fff` +- Reset mask: `0x3e00` ### Fields ```wavejson -{"reg": [{"name": "LEN", "bits": 9, "attr": ["wo"], "rotate": 0}, {"name": "CSAAT", "bits": 1, "attr": ["wo"], "rotate": -90}, {"name": "SPEED", "bits": 2, "attr": ["wo"], "rotate": -90}, {"name": "DIRECTION", "bits": 2, "attr": ["wo"], "rotate": -90}, {"bits": 18}], "config": {"lanes": 1, "fontsize": 10, "vspace": 110}} +{"reg": [{"bits": 9}, {"name": "CSAAT", "bits": 1, "attr": ["wo"], "rotate": -90}, {"name": "SPEED", "bits": 2, "attr": ["wo"], "rotate": -90}, {"name": "DIRECTION", "bits": 2, "attr": ["wo"], "rotate": -90}, {"bits": 18}], "config": {"lanes": 1, "fontsize": 10, "vspace": 110}} ``` | Bits | Type | Reset | Name | @@ -290,7 +291,7 @@ Command Register | 13:12 | wo | 0x0 | [DIRECTION](#command--direction) | | 11:10 | wo | 0x0 | [SPEED](#command--speed) | | 9 | wo | 0x0 | [CSAAT](#command--csaat) | -| 8:0 | wo | 0x0 | [LEN](#command--len) | +| 8:0 | | | Reserved | ### COMMAND . DIRECTION The direction for the following command: "0" = Dummy cycles @@ -312,7 +313,26 @@ The speed for this command segment: "0" = Standard SPI. "1" = Dual SPI. pausing for dummy cycles, and transmitting or receiving data from the device. -### COMMAND . LEN +## COMMAND_LEN +Command length Register for a single command segment. + + Parameters specific to each command segment. Unlike the [`CONFIGOPTS`](#configopts) multi-register, + there is only one command length register for controlling all attached SPI devices +- Offset: `0x24` +- Reset default: `0x0` +- Reset mask: `0xffffffff` + +### Fields + +```wavejson +{"reg": [{"name": "LEN", "bits": 32, "attr": ["wo"], "rotate": 0}], "config": {"lanes": 1, "fontsize": 10, "vspace": 80}} +``` + +| Bits | Type | Reset | Name | +|:------:|:------:|:-------:|:-------------------------| +| 31:0 | wo | 0x0 | [LEN](#command_len--len) | + +### COMMAND_LEN . LEN Segment Length. For read or write segments, this field controls the @@ -342,7 +362,7 @@ SPI Receive Data. each byte the most significant bit is always pulled from the bus first.) -- Word Aligned Offset Range: `0x24`to`0x24` +- Word Aligned Offset Range: `0x28`to`0x28` - Size (words): `1` - Access: `ro` - Byte writes are *not* supported. @@ -365,14 +385,14 @@ SPI Transmit Data. byte-order of multi-byte data writes. (Though within each byte the most significant bit is always sent first.) -- Word Aligned Offset Range: `0x28`to`0x28` +- Word Aligned Offset Range: `0x2c`to`0x2c` - Size (words): `1` - Access: `wo` - Byte writes are supported. ## ERROR_ENABLE Controls which classes of errors raise an interrupt. -- Offset: `0x2c` +- Offset: `0x30` - Reset default: `0x1f` - Reset mask: `0x1f` @@ -396,7 +416,7 @@ Indicates that any errors that have occurred. When an error occurs, the corresponding bit must be cleared here before issuing any further commands. -- Offset: `0x30` +- Offset: `0x34` - Reset default: `0x0` - Reset mask: `0x3f` @@ -418,7 +438,7 @@ Indicates that any errors that have occurred. ## EVENT_ENABLE Controls which classes of SPI events raise an interrupt. -- Offset: `0x34` +- Offset: `0x38` - Reset default: `0x0` - Reset mask: `0x3f` diff --git a/hw/ip/spi_host/dv/README.md b/hw/ip/spi_host/dv/README.md index 5fc7c9974cde2..a892073996250 100644 --- a/hw/ip/spi_host/dv/README.md +++ b/hw/ip/spi_host/dv/README.md @@ -104,7 +104,7 @@ All common types and methods defined at the package level can be found in rand spi_mode_e mode; rand spi_dir_e direction; rand bit csaat; - rand bit [8:0] len; + rand bit [31:0] len; } spi_host_command_t; typedef struct packed { diff --git a/hw/ip/spi_host/dv/env/spi_host_env_pkg.sv b/hw/ip/spi_host/dv/env/spi_host_env_pkg.sv index c582cda61205a..7ca7b1957ac64 100644 --- a/hw/ip/spi_host/dv/env/spi_host_env_pkg.sv +++ b/hw/ip/spi_host/dv/env/spi_host_env_pkg.sv @@ -31,7 +31,7 @@ package spi_host_env_pkg; parameter uint SPI_HOST_RX_FIFO_END = (SPI_HOST_RX_FIFO_START - 1) + spi_host_reg_pkg::SPI_HOST_RXDATA_SIZE; - parameter uint SPI_HOST_COMMAND_LEN_SIZE_BITS = 9; + parameter uint SPI_HOST_COMMAND_LEN_SIZE_BITS = 32; // macro includes `include "uvm_macros.svh" `include "dv_macros.svh" diff --git a/hw/ip/spi_host/rtl/spi_host.sv b/hw/ip/spi_host/rtl/spi_host.sv index ab91529fe902f..f15c32aee5cfa 100644 --- a/hw/ip/spi_host/rtl/spi_host.sv +++ b/hw/ip/spi_host/rtl/spi_host.sv @@ -236,7 +236,7 @@ module spi_host assign command.configopts.cpha = configopts.cpha.q; assign command.configopts.cpol = configopts.cpol.q; - assign command.segment.len = reg2hw.command.len.q; + assign command.segment.len = reg2hw.command_len.q; assign command.segment.csaat = reg2hw.command.csaat.q; assign command.segment.speed = reg2hw.command.speed.q; @@ -244,7 +244,7 @@ module spi_host logic [3:0] cmd_qes; assign cmd_qes = { - reg2hw.command.len.qe, + reg2hw.command_len.qe, reg2hw.command.speed.qe, reg2hw.command.direction.qe, reg2hw.command.csaat.qe diff --git a/hw/ip/spi_host/rtl/spi_host_cmd_pkg.sv b/hw/ip/spi_host/rtl/spi_host_cmd_pkg.sv index c0eb40be1572a..89a395a645c9a 100644 --- a/hw/ip/spi_host/rtl/spi_host_cmd_pkg.sv +++ b/hw/ip/spi_host/rtl/spi_host_cmd_pkg.sv @@ -8,7 +8,7 @@ package spi_host_cmd_pkg; parameter int CSW = prim_util_pkg::vbits(spi_host_reg_pkg::NumCS); - parameter int CmdSize = CSW + 45; + parameter int CmdSize = CSW + 68; // For decoding the direction register typedef enum logic [1:0] { @@ -37,11 +37,11 @@ package spi_host_cmd_pkg; } configopts_t; typedef struct packed { - logic [1:0] speed; - logic cmd_wr_en; - logic cmd_rd_en; - logic [8:0] len; - logic csaat; + logic [1:0] speed; + logic cmd_wr_en; + logic cmd_rd_en; + logic [31:0] len; + logic csaat; } segment_t; typedef struct packed { diff --git a/hw/ip/spi_host/rtl/spi_host_fsm.sv b/hw/ip/spi_host/rtl/spi_host_fsm.sv index 6c8df111c0235..bd85ad95fcd34 100644 --- a/hw/ip/spi_host/rtl/spi_host_fsm.sv +++ b/hw/ip/spi_host/rtl/spi_host_fsm.sv @@ -62,13 +62,13 @@ module spi_host_fsm logic [1:0] cmd_speed_d, cmd_speed_q; logic cmd_wr_en_d, cmd_wr_en_q; logic cmd_rd_en_d, cmd_rd_en_q; - logic [8:0] cmd_len_d, cmd_len_q; + logic [31:0] cmd_len_d, cmd_len_q; logic csaat; logic csaat_q; logic [2:0] bit_cntr_d, bit_cntr_q; - logic [8:0] byte_cntr_cpha0_d, byte_cntr_cpha1_d, byte_cntr_cpha0_q, byte_cntr_cpha1_q; - logic [8:0] byte_cntr_early, byte_cntr_late; + logic [31:0] byte_cntr_cpha0_d, byte_cntr_cpha1_d, byte_cntr_cpha0_q, byte_cntr_cpha1_q; + logic [31:0] byte_cntr_early, byte_cntr_late; logic [3:0] wait_cntr_d, wait_cntr_q; logic last_bit, last_byte; @@ -157,7 +157,7 @@ module spi_host_fsm cmd_rd_en_q <= 1'b0; cmd_wr_en_q <= 1'b0; cmd_speed_q <= 2'b00; - cmd_len_q <= 9'h0; + cmd_len_q <= 32'h0; end else begin csid_q <= (new_command && !stall) ? csid : csid_q; cpol_q <= (new_command && !stall) ? cpol : cpol_q; @@ -442,21 +442,21 @@ module spi_host_fsm // always_comb begin if (cpha_q) begin - last_byte = (byte_cntr_cpha1_q == 9'h0); + last_byte = (byte_cntr_cpha1_q == 32'h0); end else begin - last_byte = (byte_cntr_cpha0_q == 9'h0); + last_byte = (byte_cntr_cpha0_q == 32'h0); end end // Note: when updating the byte_cntr in CPHA=0 mode with a new command value, the length must // be pulled in directly from the command bus, cmd_len_d; - assign byte_cntr_cpha0_d = sw_rst_i ? 9'h0 : + assign byte_cntr_cpha0_d = sw_rst_i ? 32'h0 : !fsm_en ? byte_cntr_cpha0_q : new_command ? cmd_len_d : byte_ending_cpha0 ? byte_cntr_cpha0_q - 1 : byte_cntr_cpha0_q; - assign byte_cntr_cpha1_d = sw_rst_i ? 9'h0 : + assign byte_cntr_cpha1_d = sw_rst_i ? 32'h0 : !fsm_en ? byte_cntr_cpha1_q : new_command ? cmd_len_d : byte_ending_cpha1 ? byte_cntr_cpha1_q - 1 : @@ -497,8 +497,8 @@ module spi_host_fsm always_ff @(posedge clk_i or negedge rst_ni) begin if (!rst_ni) begin bit_cntr_q <= 3'h0; - byte_cntr_cpha0_q <= 9'h0; - byte_cntr_cpha1_q <= 9'h0; + byte_cntr_cpha0_q <= 32'h0; + byte_cntr_cpha1_q <= 32'h0; wait_cntr_q <= 4'h0; end else begin bit_cntr_q <= stall ? bit_cntr_q : bit_cntr_d; diff --git a/hw/ip/spi_host/rtl/spi_host_reg_pkg.sv b/hw/ip/spi_host/rtl/spi_host_reg_pkg.sv index 97e30acf97af3..6f0cc14e21f8a 100644 --- a/hw/ip/spi_host/rtl/spi_host_reg_pkg.sv +++ b/hw/ip/spi_host/rtl/spi_host_reg_pkg.sv @@ -114,12 +114,13 @@ package spi_host_reg_pkg; logic q; logic qe; } csaat; - struct packed { - logic [8:0] q; - logic qe; - } len; } spi_host_reg2hw_command_reg_t; + typedef struct packed { + logic [31:0] q; + logic qe; + } spi_host_reg2hw_command_len_reg_t; + typedef struct packed { struct packed { logic q; @@ -279,14 +280,15 @@ package spi_host_reg_pkg; // Register -> HW type typedef struct packed { - spi_host_reg2hw_intr_state_reg_t intr_state; // [126:125] - spi_host_reg2hw_intr_enable_reg_t intr_enable; // [124:123] - spi_host_reg2hw_intr_test_reg_t intr_test; // [122:119] - spi_host_reg2hw_alert_test_reg_t alert_test; // [118:117] - spi_host_reg2hw_control_reg_t control; // [116:98] - spi_host_reg2hw_configopts_mreg_t [0:0] configopts; // [97:67] - spi_host_reg2hw_csid_reg_t csid; // [66:35] - spi_host_reg2hw_command_reg_t command; // [34:17] + spi_host_reg2hw_intr_state_reg_t intr_state; // [149:148] + spi_host_reg2hw_intr_enable_reg_t intr_enable; // [147:146] + spi_host_reg2hw_intr_test_reg_t intr_test; // [145:142] + spi_host_reg2hw_alert_test_reg_t alert_test; // [141:140] + spi_host_reg2hw_control_reg_t control; // [139:121] + spi_host_reg2hw_configopts_mreg_t [0:0] configopts; // [120:90] + spi_host_reg2hw_csid_reg_t csid; // [89:58] + spi_host_reg2hw_command_reg_t command; // [57:50] + spi_host_reg2hw_command_len_reg_t command_len; // [49:17] spi_host_reg2hw_error_enable_reg_t error_enable; // [16:12] spi_host_reg2hw_error_status_reg_t error_status; // [11:6] spi_host_reg2hw_event_enable_reg_t event_enable; // [5:0] @@ -309,9 +311,10 @@ package spi_host_reg_pkg; parameter logic [BlockAw-1:0] SPI_HOST_CONFIGOPTS_OFFSET = 6'h 18; parameter logic [BlockAw-1:0] SPI_HOST_CSID_OFFSET = 6'h 1c; parameter logic [BlockAw-1:0] SPI_HOST_COMMAND_OFFSET = 6'h 20; - parameter logic [BlockAw-1:0] SPI_HOST_ERROR_ENABLE_OFFSET = 6'h 2c; - parameter logic [BlockAw-1:0] SPI_HOST_ERROR_STATUS_OFFSET = 6'h 30; - parameter logic [BlockAw-1:0] SPI_HOST_EVENT_ENABLE_OFFSET = 6'h 34; + parameter logic [BlockAw-1:0] SPI_HOST_COMMAND_LEN_OFFSET = 6'h 24; + parameter logic [BlockAw-1:0] SPI_HOST_ERROR_ENABLE_OFFSET = 6'h 30; + parameter logic [BlockAw-1:0] SPI_HOST_ERROR_STATUS_OFFSET = 6'h 34; + parameter logic [BlockAw-1:0] SPI_HOST_EVENT_ENABLE_OFFSET = 6'h 38; // Reset values for hwext registers and their fields parameter logic [1:0] SPI_HOST_INTR_TEST_RESVAL = 2'h 0; @@ -320,16 +323,17 @@ package spi_host_reg_pkg; parameter logic [0:0] SPI_HOST_ALERT_TEST_RESVAL = 1'h 0; parameter logic [0:0] SPI_HOST_ALERT_TEST_FATAL_FAULT_RESVAL = 1'h 0; parameter logic [13:0] SPI_HOST_COMMAND_RESVAL = 14'h 0; - parameter logic [8:0] SPI_HOST_COMMAND_LEN_RESVAL = 9'h 0; parameter logic [0:0] SPI_HOST_COMMAND_CSAAT_RESVAL = 1'h 0; parameter logic [1:0] SPI_HOST_COMMAND_SPEED_RESVAL = 2'h 0; parameter logic [1:0] SPI_HOST_COMMAND_DIRECTION_RESVAL = 2'h 0; + parameter logic [31:0] SPI_HOST_COMMAND_LEN_RESVAL = 32'h 0; + parameter logic [31:0] SPI_HOST_COMMAND_LEN_LEN_RESVAL = 32'h 0; // Window parameters - parameter logic [BlockAw-1:0] SPI_HOST_RXDATA_OFFSET = 6'h 24; + parameter logic [BlockAw-1:0] SPI_HOST_RXDATA_OFFSET = 6'h 28; parameter int unsigned SPI_HOST_RXDATA_SIZE = 'h 4; parameter int unsigned SPI_HOST_RXDATA_IDX = 0; - parameter logic [BlockAw-1:0] SPI_HOST_TXDATA_OFFSET = 6'h 28; + parameter logic [BlockAw-1:0] SPI_HOST_TXDATA_OFFSET = 6'h 2c; parameter int unsigned SPI_HOST_TXDATA_SIZE = 'h 4; parameter int unsigned SPI_HOST_TXDATA_IDX = 1; @@ -344,13 +348,14 @@ package spi_host_reg_pkg; SPI_HOST_CONFIGOPTS, SPI_HOST_CSID, SPI_HOST_COMMAND, + SPI_HOST_COMMAND_LEN, SPI_HOST_ERROR_ENABLE, SPI_HOST_ERROR_STATUS, SPI_HOST_EVENT_ENABLE } spi_host_id_e; // Register width information to check illegal writes - parameter logic [3:0] SPI_HOST_PERMIT [12] = '{ + parameter logic [3:0] SPI_HOST_PERMIT [13] = '{ 4'b 0001, // index[ 0] SPI_HOST_INTR_STATE 4'b 0001, // index[ 1] SPI_HOST_INTR_ENABLE 4'b 0001, // index[ 2] SPI_HOST_INTR_TEST @@ -360,9 +365,10 @@ package spi_host_reg_pkg; 4'b 1111, // index[ 6] SPI_HOST_CONFIGOPTS 4'b 1111, // index[ 7] SPI_HOST_CSID 4'b 0011, // index[ 8] SPI_HOST_COMMAND - 4'b 0001, // index[ 9] SPI_HOST_ERROR_ENABLE - 4'b 0001, // index[10] SPI_HOST_ERROR_STATUS - 4'b 0001 // index[11] SPI_HOST_EVENT_ENABLE + 4'b 1111, // index[ 9] SPI_HOST_COMMAND_LEN + 4'b 0001, // index[10] SPI_HOST_ERROR_ENABLE + 4'b 0001, // index[11] SPI_HOST_ERROR_STATUS + 4'b 0001 // index[12] SPI_HOST_EVENT_ENABLE }; endpackage diff --git a/hw/ip/spi_host/rtl/spi_host_reg_top.sv b/hw/ip/spi_host/rtl/spi_host_reg_top.sv index 75ce27dc226d2..785cf80053fdc 100644 --- a/hw/ip/spi_host/rtl/spi_host_reg_top.sv +++ b/hw/ip/spi_host/rtl/spi_host_reg_top.sv @@ -57,9 +57,9 @@ module spi_host_reg_top ( // also check for spurious write enables logic reg_we_err; - logic [11:0] reg_we_check; + logic [12:0] reg_we_check; prim_reg_we_check #( - .OneHotWidth(12) + .OneHotWidth(13) ) u_prim_reg_we_check ( .clk_i(clk_i), .rst_ni(rst_ni), @@ -130,8 +130,8 @@ module spi_host_reg_top ( // Create steering logic always_comb begin reg_steer = - tl_i.a_address[AW-1:0] inside {[36:39]} ? 2'd0 : - tl_i.a_address[AW-1:0] inside {[40:43]} ? 2'd1 : + tl_i.a_address[AW-1:0] inside {[40:43]} ? 2'd0 : + tl_i.a_address[AW-1:0] inside {[44:47]} ? 2'd1 : // Default set to register 2'd2; @@ -231,10 +231,11 @@ module spi_host_reg_top ( logic [31:0] csid_qs; logic [31:0] csid_wd; logic command_we; - logic [8:0] command_len_wd; logic command_csaat_wd; logic [1:0] command_speed_wd; logic [1:0] command_direction_wd; + logic command_len_we; + logic [31:0] command_len_wd; logic error_enable_we; logic error_enable_cmdbusy_qs; logic error_enable_cmdbusy_wd; @@ -1182,24 +1183,8 @@ module spi_host_reg_top ( // R[command]: V(True) logic command_qe; - logic [3:0] command_flds_we; + logic [2:0] command_flds_we; assign command_qe = &command_flds_we; - // F[len]: 8:0 - prim_subreg_ext #( - .DW (9) - ) u_command_len ( - .re (1'b0), - .we (command_we), - .wd (command_len_wd), - .d ('0), - .qre (), - .qe (command_flds_we[0]), - .q (reg2hw.command.len.q), - .ds (), - .qs () - ); - assign reg2hw.command.len.qe = command_qe; - // F[csaat]: 9:9 prim_subreg_ext #( .DW (1) @@ -1209,7 +1194,7 @@ module spi_host_reg_top ( .wd (command_csaat_wd), .d ('0), .qre (), - .qe (command_flds_we[1]), + .qe (command_flds_we[0]), .q (reg2hw.command.csaat.q), .ds (), .qs () @@ -1225,7 +1210,7 @@ module spi_host_reg_top ( .wd (command_speed_wd), .d ('0), .qre (), - .qe (command_flds_we[2]), + .qe (command_flds_we[1]), .q (reg2hw.command.speed.q), .ds (), .qs () @@ -1241,7 +1226,7 @@ module spi_host_reg_top ( .wd (command_direction_wd), .d ('0), .qre (), - .qe (command_flds_we[3]), + .qe (command_flds_we[2]), .q (reg2hw.command.direction.q), .ds (), .qs () @@ -1249,6 +1234,26 @@ module spi_host_reg_top ( assign reg2hw.command.direction.qe = command_qe; + // R[command_len]: V(True) + logic command_len_qe; + logic [0:0] command_len_flds_we; + assign command_len_qe = &command_len_flds_we; + prim_subreg_ext #( + .DW (32) + ) u_command_len ( + .re (1'b0), + .we (command_len_we), + .wd (command_len_wd), + .d ('0), + .qre (), + .qe (command_len_flds_we[0]), + .q (reg2hw.command_len.q), + .ds (), + .qs () + ); + assign reg2hw.command_len.qe = command_len_qe; + + // R[error_enable]: V(False) // F[cmdbusy]: 0:0 prim_subreg #( @@ -1715,7 +1720,7 @@ module spi_host_reg_top ( - logic [11:0] addr_hit; + logic [12:0] addr_hit; always_comb begin addr_hit = '0; addr_hit[ 0] = (reg_addr == SPI_HOST_INTR_STATE_OFFSET); @@ -1727,9 +1732,10 @@ module spi_host_reg_top ( addr_hit[ 6] = (reg_addr == SPI_HOST_CONFIGOPTS_OFFSET); addr_hit[ 7] = (reg_addr == SPI_HOST_CSID_OFFSET); addr_hit[ 8] = (reg_addr == SPI_HOST_COMMAND_OFFSET); - addr_hit[ 9] = (reg_addr == SPI_HOST_ERROR_ENABLE_OFFSET); - addr_hit[10] = (reg_addr == SPI_HOST_ERROR_STATUS_OFFSET); - addr_hit[11] = (reg_addr == SPI_HOST_EVENT_ENABLE_OFFSET); + addr_hit[ 9] = (reg_addr == SPI_HOST_COMMAND_LEN_OFFSET); + addr_hit[10] = (reg_addr == SPI_HOST_ERROR_ENABLE_OFFSET); + addr_hit[11] = (reg_addr == SPI_HOST_ERROR_STATUS_OFFSET); + addr_hit[12] = (reg_addr == SPI_HOST_EVENT_ENABLE_OFFSET); end assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ; @@ -1748,7 +1754,8 @@ module spi_host_reg_top ( (addr_hit[ 8] & (|(SPI_HOST_PERMIT[ 8] & ~reg_be))) | (addr_hit[ 9] & (|(SPI_HOST_PERMIT[ 9] & ~reg_be))) | (addr_hit[10] & (|(SPI_HOST_PERMIT[10] & ~reg_be))) | - (addr_hit[11] & (|(SPI_HOST_PERMIT[11] & ~reg_be))))); + (addr_hit[11] & (|(SPI_HOST_PERMIT[11] & ~reg_be))) | + (addr_hit[12] & (|(SPI_HOST_PERMIT[12] & ~reg_be))))); end // Generate write-enables @@ -1799,14 +1806,15 @@ module spi_host_reg_top ( assign csid_wd = reg_wdata[31:0]; assign command_we = addr_hit[8] & reg_we & !reg_error; - assign command_len_wd = reg_wdata[8:0]; - assign command_csaat_wd = reg_wdata[9]; assign command_speed_wd = reg_wdata[11:10]; assign command_direction_wd = reg_wdata[13:12]; - assign error_enable_we = addr_hit[9] & reg_we & !reg_error; + assign command_len_we = addr_hit[9] & reg_we & !reg_error; + + assign command_len_wd = reg_wdata[31:0]; + assign error_enable_we = addr_hit[10] & reg_we & !reg_error; assign error_enable_cmdbusy_wd = reg_wdata[0]; @@ -1817,7 +1825,7 @@ module spi_host_reg_top ( assign error_enable_cmdinval_wd = reg_wdata[3]; assign error_enable_csidinval_wd = reg_wdata[4]; - assign error_status_we = addr_hit[10] & reg_we & !reg_error; + assign error_status_we = addr_hit[11] & reg_we & !reg_error; assign error_status_cmdbusy_wd = reg_wdata[0]; @@ -1830,7 +1838,7 @@ module spi_host_reg_top ( assign error_status_csidinval_wd = reg_wdata[4]; assign error_status_accessinval_wd = reg_wdata[5]; - assign event_enable_we = addr_hit[11] & reg_we & !reg_error; + assign event_enable_we = addr_hit[12] & reg_we & !reg_error; assign event_enable_rxfull_wd = reg_wdata[0]; @@ -1856,9 +1864,10 @@ module spi_host_reg_top ( reg_we_check[6] = configopts_we; reg_we_check[7] = csid_we; reg_we_check[8] = command_we; - reg_we_check[9] = error_enable_we; - reg_we_check[10] = error_status_we; - reg_we_check[11] = event_enable_we; + reg_we_check[9] = command_len_we; + reg_we_check[10] = error_enable_we; + reg_we_check[11] = error_status_we; + reg_we_check[12] = event_enable_we; end // Read data return @@ -1924,13 +1933,16 @@ module spi_host_reg_top ( end addr_hit[8]: begin - reg_rdata_next[8:0] = '0; reg_rdata_next[9] = '0; reg_rdata_next[11:10] = '0; reg_rdata_next[13:12] = '0; end addr_hit[9]: begin + reg_rdata_next[31:0] = '0; + end + + addr_hit[10]: begin reg_rdata_next[0] = error_enable_cmdbusy_qs; reg_rdata_next[1] = error_enable_overflow_qs; reg_rdata_next[2] = error_enable_underflow_qs; @@ -1938,7 +1950,7 @@ module spi_host_reg_top ( reg_rdata_next[4] = error_enable_csidinval_qs; end - addr_hit[10]: begin + addr_hit[11]: begin reg_rdata_next[0] = error_status_cmdbusy_qs; reg_rdata_next[1] = error_status_overflow_qs; reg_rdata_next[2] = error_status_underflow_qs; @@ -1947,7 +1959,7 @@ module spi_host_reg_top ( reg_rdata_next[5] = error_status_accessinval_qs; end - addr_hit[11]: begin + addr_hit[12]: begin reg_rdata_next[0] = event_enable_rxfull_qs; reg_rdata_next[1] = event_enable_txempty_qs; reg_rdata_next[2] = event_enable_rxwm_qs; diff --git a/hw/top_earlgrey/data/autogen/outgoing_alerts_ext.hjson b/hw/top_earlgrey/data/autogen/outgoing_alerts_ext.hjson new file mode 100644 index 0000000000000..3a3d4ca8a060f --- /dev/null +++ b/hw/top_earlgrey/data/autogen/outgoing_alerts_ext.hjson @@ -0,0 +1,19 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// Generated by topgen.py + +{ + ext: [ + { + name: i2c2_fatal_fault + module_name: i2c2 + index: 0 + type: alert + async: 1 + width: 1 + lpg_idx: 0 + } + ] +} diff --git a/sw/device/lib/dif/dif_spi_host.c b/sw/device/lib/dif/dif_spi_host.c index e741f978705ed..c86ccf17643d0 100644 --- a/sw/device/lib/dif/dif_spi_host.c +++ b/sw/device/lib/dif/dif_spi_host.c @@ -289,7 +289,8 @@ static void write_command_reg(const dif_spi_host_t *spi_host, uint16_t length, dif_spi_host_direction_t direction, bool last_segment) { uint32_t reg = 0; - reg = bitfield_field32_write(reg, SPI_HOST_COMMAND_LEN_FIELD, length - 1); + mmio_region_write32(spi_host->base_addr, SPI_HOST_COMMAND_LEN_REG_OFFSET, + length - 1); reg = bitfield_field32_write(reg, SPI_HOST_COMMAND_SPEED_FIELD, speed); reg = bitfield_field32_write(reg, SPI_HOST_COMMAND_DIRECTION_FIELD, direction); diff --git a/sw/device/lib/dif/dif_spi_host_unittest.cc b/sw/device/lib/dif/dif_spi_host_unittest.cc index 587fc9d78a81f..06a14dc817e14 100644 --- a/sw/device/lib/dif/dif_spi_host_unittest.cc +++ b/sw/device/lib/dif/dif_spi_host_unittest.cc @@ -50,7 +50,6 @@ using testing::Test; #define EXPECT_COMMAND_REG(length, width, direction, last_segment) \ EXPECT_WRITE32(SPI_HOST_COMMAND_REG_OFFSET, \ { \ - {SPI_HOST_COMMAND_LEN_OFFSET, (length)-1}, \ {SPI_HOST_COMMAND_SPEED_OFFSET, width}, \ {SPI_HOST_COMMAND_DIRECTION_OFFSET, direction}, \ {SPI_HOST_COMMAND_CSAAT_BIT, !(last_segment)}, \ @@ -295,7 +294,8 @@ TEST_F(TransactionTest, IssueOpcode) { EXPECT_TXQD(0); // Opcodes are written directly to the FIFO register. EXPECT_WRITE8(SPI_HOST_TXDATA_REG_OFFSET, 0x5a); - EXPECT_COMMAND_REG(/*length=*/1, /*width=*/kDifSpiHostWidthStandard, + EXPECT_WRITE32(SPI_HOST_COMMAND_LEN_REG_OFFSET, 0); + EXPECT_COMMAND_REG(/*width=*/kDifSpiHostWidthStandard, /*direction=*/kDifSpiHostDirectionTx, /*last=*/true); EXPECT_DIF_OK(dif_spi_host_transaction(&spi_host_, 0, &segment, 1)); @@ -314,7 +314,8 @@ TEST_F(TransactionTest, IssueAddressMode3b) { EXPECT_TXQD(0); // SPI addresses are written directly to the FIFO register. EXPECT_WRITE32(SPI_HOST_TXDATA_REG_OFFSET, 0x332211); - EXPECT_COMMAND_REG(/*length=*/3, /*width=*/kDifSpiHostWidthStandard, + EXPECT_WRITE32(SPI_HOST_COMMAND_LEN_REG_OFFSET, 2); + EXPECT_COMMAND_REG(/*width=*/kDifSpiHostWidthStandard, /*direction=*/kDifSpiHostDirectionTx, /*last=*/true); EXPECT_DIF_OK(dif_spi_host_transaction(&spi_host_, 0, &segment, 1)); @@ -333,7 +334,8 @@ TEST_F(TransactionTest, IssueAddressMode4b) { EXPECT_TXQD(0); // SPI addresses are written directly to the FIFO register. EXPECT_WRITE32(SPI_HOST_TXDATA_REG_OFFSET, 0x44332211); - EXPECT_COMMAND_REG(/*length=*/4, /*width=*/kDifSpiHostWidthStandard, + EXPECT_WRITE32(SPI_HOST_COMMAND_LEN_REG_OFFSET, 3); + EXPECT_COMMAND_REG(/*width=*/kDifSpiHostWidthStandard, /*direction=*/kDifSpiHostDirectionTx, /*last=*/true); EXPECT_DIF_OK(dif_spi_host_transaction(&spi_host_, 0, &segment, 1)); @@ -348,7 +350,8 @@ TEST_F(TransactionTest, IssueDummy) { EXPECT_WRITE32(SPI_HOST_CSID_REG_OFFSET, 0); EXPECT_READY(true); - EXPECT_COMMAND_REG(/*length=*/8, /*width=*/kDifSpiHostWidthStandard, + EXPECT_WRITE32(SPI_HOST_COMMAND_LEN_REG_OFFSET, 7); + EXPECT_COMMAND_REG(/*width=*/kDifSpiHostWidthStandard, /*direction=*/kDifSpiHostDirectionDummy, /*last=*/true); EXPECT_DIF_OK(dif_spi_host_transaction(&spi_host_, 0, &segment, 1)); @@ -365,7 +368,8 @@ TEST_F(TransactionTest, TransmitDual) { EXPECT_WRITE32(SPI_HOST_CSID_REG_OFFSET, 0); EXPECT_READY(true); - EXPECT_COMMAND_REG(/*length=*/sizeof(buf), /*width=*/kDifSpiHostWidthDual, + EXPECT_WRITE32(SPI_HOST_COMMAND_LEN_REG_OFFSET, sizeof(buf) - 1); + EXPECT_COMMAND_REG(/*width=*/kDifSpiHostWidthDual, /*direction=*/kDifSpiHostDirectionTx, /*last=*/true); EXPECT_CALL(fifo_, write(&spi_host_, buf, sizeof(buf))); @@ -383,7 +387,8 @@ TEST_F(TransactionTest, ReceiveQuad) { EXPECT_WRITE32(SPI_HOST_CSID_REG_OFFSET, 0); EXPECT_READY(true); - EXPECT_COMMAND_REG(/*length=*/sizeof(buf), /*width=*/kDifSpiHostWidthQuad, + EXPECT_WRITE32(SPI_HOST_COMMAND_LEN_REG_OFFSET, sizeof(buf) - 1); + EXPECT_COMMAND_REG(/*width=*/kDifSpiHostWidthQuad, /*direction=*/kDifSpiHostDirectionRx, /*last=*/true); EXPECT_CALL(fifo_, read(&spi_host_, buf, sizeof(buf))); @@ -403,9 +408,9 @@ TEST_F(TransactionTest, Transceive) { EXPECT_WRITE32(SPI_HOST_CSID_REG_OFFSET, 0); EXPECT_READY(true); - EXPECT_COMMAND_REG( - /*length=*/sizeof(txbuf), /*width=*/kDifSpiHostWidthStandard, - /*direction=*/kDifSpiHostDirectionBidirectional, /*last=*/true); + EXPECT_WRITE32(SPI_HOST_COMMAND_LEN_REG_OFFSET, sizeof(txbuf) - 1); + EXPECT_COMMAND_REG(/*width=*/kDifSpiHostWidthStandard, + /*direction=*/kDifSpiHostDirectionBidirectional, /*last=*/true); EXPECT_CALL(fifo_, write(&spi_host_, txbuf, sizeof(txbuf))); EXPECT_CALL(fifo_, read(&spi_host_, rxbuf, sizeof(rxbuf))); @@ -429,11 +434,13 @@ TEST_F(TransactionTest, MultiSegmentTxRx) { EXPECT_WRITE32(SPI_HOST_CSID_REG_OFFSET, 0); EXPECT_READY(true); - EXPECT_COMMAND_REG(/*length=*/sizeof(txbuf), /*width=*/kDifSpiHostWidthDual, + EXPECT_WRITE32(SPI_HOST_COMMAND_LEN_REG_OFFSET, sizeof(txbuf) - 1); + EXPECT_COMMAND_REG(/*width=*/kDifSpiHostWidthDual, /*direction=*/kDifSpiHostDirectionTx, /*last=*/false); EXPECT_CALL(fifo_, write(&spi_host_, txbuf, sizeof(txbuf))); EXPECT_READY(true); - EXPECT_COMMAND_REG(/*length=*/sizeof(rxbuf), /*width=*/kDifSpiHostWidthDual, + EXPECT_WRITE32(SPI_HOST_COMMAND_LEN_REG_OFFSET, sizeof(rxbuf) - 1); + EXPECT_COMMAND_REG(/*width=*/kDifSpiHostWidthDual, /*direction=*/kDifSpiHostDirectionRx, /*last=*/true); EXPECT_CALL(fifo_, read(&spi_host_, rxbuf, sizeof(rxbuf)));