diff --git a/hw/ip/dma/data/dma.hjson b/hw/ip/dma/data/dma.hjson index 0067a88572952..5a09f8a13d112 100644 --- a/hw/ip/dma/data/dma.hjson +++ b/hw/ip/dma/data/dma.hjson @@ -470,6 +470,15 @@ No explicit clearing necessary. ''' } + { bits: "5" + name: "digest_swap" + resval: 0x0 + desc: '''Digest register byte swap. + + If 1 the value in each digest output register is converted to big-endian byte order. + This setting does not affect the order of the digest output registers, !!SHA2_DIGEST_0 still contains the first 4 bytes of the digest. + ''' + } { bits: "8" name: "initial_transfer" resval: 0x0 diff --git a/hw/ip/dma/doc/registers.md b/hw/ip/dma/doc/registers.md index 6ebfde83930fe..86fc36aa040ec 100644 --- a/hw/ip/dma/doc/registers.md +++ b/hw/ip/dma/doc/registers.md @@ -458,12 +458,12 @@ Other values are reserved. Control register for DMA data movement. - Offset: `0x44` - Reset default: `0x0` -- Reset mask: `0x8800011f` +- Reset mask: `0x8800013f` ### Fields ```wavejson -{"reg": [{"name": "opcode", "bits": 4, "attr": ["rw"], "rotate": 0}, {"name": "hardware_handshake_enable", "bits": 1, "attr": ["rw"], "rotate": -90}, {"bits": 3}, {"name": "initial_transfer", "bits": 1, "attr": ["rw"], "rotate": -90}, {"bits": 18}, {"name": "abort", "bits": 1, "attr": ["wo"], "rotate": -90}, {"bits": 3}, {"name": "go", "bits": 1, "attr": ["rw"], "rotate": -90}], "config": {"lanes": 1, "fontsize": 10, "vspace": 270}} +{"reg": [{"name": "opcode", "bits": 4, "attr": ["rw"], "rotate": 0}, {"name": "hardware_handshake_enable", "bits": 1, "attr": ["rw"], "rotate": -90}, {"name": "digest_swap", "bits": 1, "attr": ["rw"], "rotate": -90}, {"bits": 2}, {"name": "initial_transfer", "bits": 1, "attr": ["rw"], "rotate": -90}, {"bits": 18}, {"name": "abort", "bits": 1, "attr": ["wo"], "rotate": -90}, {"bits": 3}, {"name": "go", "bits": 1, "attr": ["rw"], "rotate": -90}], "config": {"lanes": 1, "fontsize": 10, "vspace": 270}} ``` | Bits | Type | Reset | Name | @@ -473,7 +473,8 @@ Control register for DMA data movement. | 27 | wo | 0x0 | [abort](#control--abort) | | 26:9 | | | Reserved | | 8 | rw | 0x0 | [initial_transfer](#control--initial_transfer) | -| 7:5 | | | Reserved | +| 7:6 | | | Reserved | +| 5 | rw | 0x0 | [digest_swap](#control--digest_swap) | | 4 | rw | 0x0 | [hardware_handshake_enable](#control--hardware_handshake_enable) | | 3:0 | rw | 0x0 | [opcode](#control--opcode) | @@ -493,6 +494,12 @@ Marks the initial transfer to initialize the DMA and SHA engine for one transfer Used for hardware handshake and ordinary transfers, in which multiple transfers contribute to a final digest. Note, for non-handshake transfers with inline hashing mode enabled, this bit must be set to also mark the first transfer. +### CONTROL . digest_swap +Digest register byte swap. + +If 1 the value in each digest output register is converted to big-endian byte order. +This setting does not affect the order of the digest output registers, [`SHA2_DIGEST_0`](#sha2_digest_0) still contains the first 4 bytes of the digest. + ### CONTROL . hardware_handshake_enable Enable hardware handshake mode. Used to clear FIFOs from low speed IO peripherals receiving data, e.g., I3C receive buffer. diff --git a/hw/ip/dma/rtl/dma.sv b/hw/ip/dma/rtl/dma.sv index 493a5b237e8f5..77e97639a1bd4 100644 --- a/hw/ip/dma/rtl/dma.sv +++ b/hw/ip/dma/rtl/dma.sv @@ -268,6 +268,7 @@ module dma always_comb begin control_d.opcode = opcode_e'(reg2hw.control.opcode.q); control_d.cfg_handshake_en = reg2hw.control.hardware_handshake_enable.q; + control_d.cfg_digest_swap = reg2hw.control.digest_swap.q; control_d.range_valid = reg2hw.range_valid.q; control_d.enabled_memory_range_base = reg2hw.enabled_memory_range_base.q; control_d.enabled_memory_range_limit = reg2hw.enabled_memory_range_limit.q; @@ -1254,17 +1255,22 @@ module dma for (int unsigned i = 0; i < NR_SHA_DIGEST_ELEMENTS / 2; i++) begin unique case (control_q.opcode) OpcSha256: begin - hw2reg.sha2_digest[i].d = sha2_digest[i][0 +: 32]; + hw2reg.sha2_digest[i].d = conv_endian32(sha2_digest[i][0 +: 32], + control_q.cfg_digest_swap); end OpcSha384: begin if (i < 6) begin - hw2reg.sha2_digest[i*2].d = sha2_digest[i][32 +: 32]; - hw2reg.sha2_digest[(i*2)+1].d = sha2_digest[i][0 +: 32]; + hw2reg.sha2_digest[i*2].d = conv_endian32(sha2_digest[i][32 +: 32], + control_q.cfg_digest_swap); + hw2reg.sha2_digest[(i*2)+1].d = conv_endian32(sha2_digest[i][0 +: 32], + control_q.cfg_digest_swap); end end default: begin // SHA2-512 - hw2reg.sha2_digest[i*2].d = sha2_digest[i][32 +: 32]; - hw2reg.sha2_digest[(i*2)+1].d = sha2_digest[i][0 +: 32]; + hw2reg.sha2_digest[i*2].d = conv_endian32(sha2_digest[i][32 +: 32], + control_q.cfg_digest_swap); + hw2reg.sha2_digest[(i*2)+1].d = conv_endian32(sha2_digest[i][0 +: 32], + control_q.cfg_digest_swap); end endcase end diff --git a/hw/ip/dma/rtl/dma_pkg.sv b/hw/ip/dma/rtl/dma_pkg.sv index c22ab9a080ead..1f8ab99d3e1cd 100644 --- a/hw/ip/dma/rtl/dma_pkg.sv +++ b/hw/ip/dma/rtl/dma_pkg.sv @@ -55,6 +55,7 @@ package dma_pkg; // Control register opcode_e opcode; logic cfg_handshake_en; + logic cfg_digest_swap; logic range_valid; // Enabled memory base register logic [31:0] enabled_memory_range_base; diff --git a/hw/ip/dma/rtl/dma_reg_pkg.sv b/hw/ip/dma/rtl/dma_reg_pkg.sv index 00a039ba8baba..377de81e17b8d 100644 --- a/hw/ip/dma/rtl/dma_reg_pkg.sv +++ b/hw/ip/dma/rtl/dma_reg_pkg.sv @@ -130,6 +130,9 @@ package dma_reg_pkg; struct packed { logic q; } initial_transfer; + struct packed { + logic q; + } digest_swap; struct packed { logic q; } hardware_handshake_enable; @@ -319,23 +322,23 @@ package dma_reg_pkg; // Register -> HW type typedef struct packed { - dma_reg2hw_intr_state_reg_t intr_state; // [1043:1041] - dma_reg2hw_intr_enable_reg_t intr_enable; // [1040:1038] - dma_reg2hw_intr_test_reg_t intr_test; // [1037:1032] - dma_reg2hw_alert_test_reg_t alert_test; // [1031:1030] - dma_reg2hw_src_addr_lo_reg_t src_addr_lo; // [1029:998] - dma_reg2hw_src_addr_hi_reg_t src_addr_hi; // [997:966] - dma_reg2hw_dst_addr_lo_reg_t dst_addr_lo; // [965:934] - dma_reg2hw_dst_addr_hi_reg_t dst_addr_hi; // [933:902] - dma_reg2hw_addr_space_id_reg_t addr_space_id; // [901:894] - dma_reg2hw_enabled_memory_range_base_reg_t enabled_memory_range_base; // [893:861] - dma_reg2hw_enabled_memory_range_limit_reg_t enabled_memory_range_limit; // [860:828] - dma_reg2hw_range_valid_reg_t range_valid; // [827:827] - dma_reg2hw_range_regwen_reg_t range_regwen; // [826:823] - dma_reg2hw_total_data_size_reg_t total_data_size; // [822:791] - dma_reg2hw_chunk_data_size_reg_t chunk_data_size; // [790:759] - dma_reg2hw_transfer_width_reg_t transfer_width; // [758:757] - dma_reg2hw_control_reg_t control; // [756:748] + dma_reg2hw_intr_state_reg_t intr_state; // [1044:1042] + dma_reg2hw_intr_enable_reg_t intr_enable; // [1041:1039] + dma_reg2hw_intr_test_reg_t intr_test; // [1038:1033] + dma_reg2hw_alert_test_reg_t alert_test; // [1032:1031] + dma_reg2hw_src_addr_lo_reg_t src_addr_lo; // [1030:999] + dma_reg2hw_src_addr_hi_reg_t src_addr_hi; // [998:967] + dma_reg2hw_dst_addr_lo_reg_t dst_addr_lo; // [966:935] + dma_reg2hw_dst_addr_hi_reg_t dst_addr_hi; // [934:903] + dma_reg2hw_addr_space_id_reg_t addr_space_id; // [902:895] + dma_reg2hw_enabled_memory_range_base_reg_t enabled_memory_range_base; // [894:862] + dma_reg2hw_enabled_memory_range_limit_reg_t enabled_memory_range_limit; // [861:829] + dma_reg2hw_range_valid_reg_t range_valid; // [828:828] + dma_reg2hw_range_regwen_reg_t range_regwen; // [827:824] + dma_reg2hw_total_data_size_reg_t total_data_size; // [823:792] + dma_reg2hw_chunk_data_size_reg_t chunk_data_size; // [791:760] + dma_reg2hw_transfer_width_reg_t transfer_width; // [759:758] + dma_reg2hw_control_reg_t control; // [757:748] dma_reg2hw_src_config_reg_t src_config; // [747:746] dma_reg2hw_dst_config_reg_t dst_config; // [745:744] dma_reg2hw_status_reg_t status; // [743:737] diff --git a/hw/ip/dma/rtl/dma_reg_top.sv b/hw/ip/dma/rtl/dma_reg_top.sv index 779dd96347efe..e474b68dfc8ed 100644 --- a/hw/ip/dma/rtl/dma_reg_top.sv +++ b/hw/ip/dma/rtl/dma_reg_top.sv @@ -182,6 +182,8 @@ module dma_reg_top ( logic [3:0] control_opcode_wd; logic control_hardware_handshake_enable_qs; logic control_hardware_handshake_enable_wd; + logic control_digest_swap_qs; + logic control_digest_swap_wd; logic control_initial_transfer_qs; logic control_initial_transfer_wd; logic control_abort_wd; @@ -1009,7 +1011,7 @@ module dma_reg_top ( // R[control]: V(False) logic control_qe; - logic [4:0] control_flds_we; + logic [5:0] control_flds_we; prim_flop #( .Width(1), .ResetValue(0) @@ -1073,6 +1075,33 @@ module dma_reg_top ( .qs (control_hardware_handshake_enable_qs) ); + // F[digest_swap]: 5:5 + prim_subreg #( + .DW (1), + .SwAccess(prim_subreg_pkg::SwAccessRW), + .RESVAL (1'h0), + .Mubi (1'b0) + ) u_control_digest_swap ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (control_we), + .wd (control_digest_swap_wd), + + // from internal hardware + .de (1'b0), + .d ('0), + + // to internal hardware + .qe (control_flds_we[2]), + .q (reg2hw.control.digest_swap.q), + .ds (), + + // to register interface (read) + .qs (control_digest_swap_qs) + ); + // F[initial_transfer]: 8:8 prim_subreg #( .DW (1), @@ -1092,7 +1121,7 @@ module dma_reg_top ( .d (hw2reg.control.initial_transfer.d), // to internal hardware - .qe (control_flds_we[2]), + .qe (control_flds_we[3]), .q (reg2hw.control.initial_transfer.q), .ds (), @@ -1119,7 +1148,7 @@ module dma_reg_top ( .d (hw2reg.control.abort.d), // to internal hardware - .qe (control_flds_we[3]), + .qe (control_flds_we[4]), .q (reg2hw.control.abort.q), .ds (), @@ -1146,7 +1175,7 @@ module dma_reg_top ( .d (hw2reg.control.go.d), // to internal hardware - .qe (control_flds_we[4]), + .qe (control_flds_we[5]), .q (reg2hw.control.go.q), .ds (), @@ -3186,6 +3215,8 @@ module dma_reg_top ( assign control_hardware_handshake_enable_wd = reg_wdata[4]; + assign control_digest_swap_wd = reg_wdata[5]; + assign control_initial_transfer_wd = reg_wdata[8]; assign control_abort_wd = reg_wdata[27]; @@ -3436,6 +3467,7 @@ module dma_reg_top ( addr_hit[17]: begin reg_rdata_next[3:0] = control_opcode_qs; reg_rdata_next[4] = control_hardware_handshake_enable_qs; + reg_rdata_next[5] = control_digest_swap_qs; reg_rdata_next[8] = control_initial_transfer_qs; reg_rdata_next[27] = '0; reg_rdata_next[31] = control_go_qs;