55// Authors:
66// - Enrico Zelioli <ezelioli@iis.ee.ethz.ch>
77
8+ `include " common_cells/registers.svh"
9+
810module soc_ctrl_regs # (
911 parameter type obi_req_t = logic ,
1012 parameter type obi_rsp_t = logic ,
@@ -18,122 +20,123 @@ module soc_ctrl_regs #(
1820 output logic fetch_en_o,
1921 output logic sram_dly_o
2022);
21-
23+ import croc_pkg :: * ;
2224 import soc_ctrl_regs_pkg :: * ;
2325
24- // Registers
26+ // Read-only hardware info assembled from compile-time configuration.
27+ // Ordered by what integrators are most likely to change: SoC-level first, then
28+ // core-level, then memory. Reserved bits leave room for future fields in each group.
29+ //
30+ // Field layout (MSB first):
31+ // --- SoC ---
32+ // [31:28] version Croc SoC major version (croc_pkg::PulpJtagIdCode.version + 1)
33+ // [27] idma_present iDMA enabled (croc_pkg::iDMAEnable)
34+ // [26:24] reserved 0 (reserved for future SoC-level features)
35+ // --- Core ---
36+ // [23:22] core_id Core type: 00=CVE2, 01/10=reserved, 11=custom (croc_pkg::CoreId)
37+ // [21] pmp_enable Core specifics, for CVE2: PMP enabled (croc_pkg::CorePMPEnable)
38+ // [20:16] reserved 0 (reserved for future core-level features)
39+ // --- Memory ---
40+ // [15:13] sram_banks Number of SRAM banks (croc_pkg::NumSramBanks)
41+ // [12:5] sram_bank_words Words per SRAM bank / 64 (croc_pkg::SramBankNumWords)
42+ // [4:0] reserved 0 (reserved for future memory config details)
43+
44+ localparam logic [31 : 0 ] HwInfoWord = {
45+ 4 '(PulpJtagIdCode.version), // [31:28] version
46+ 1 '(iDMAEnable), // [27] idma_present
47+ 3'b0 , // [26:24] reserved (SoC features)
48+ 2 '(CoreId), // [23:22] core_id
49+ 1 '(CorePMPEnable), // [21] pmp_enable
50+ 5'b0 , // [20:16] reserved (core features)
51+ 3 '(NumSramBanks), // [15:12] sram_banks
52+ 8 '(SramBankNumWords / 64 ), // [11:5] sram_bank_words (in units of 64 words)
53+ 5'b0 // [4:0] reserved
54+ } ;
55+
56+ // read-write registers
2557 logic [31 : 0 ] boot_addr_d, boot_addr_q;
2658 logic fetch_en_d, fetch_en_q;
2759 logic [31 : 0 ] core_status_d, core_status_q;
2860 logic boot_mode_d, boot_mode_q;
2961 logic sram_dly_d, sram_dly_q;
3062
31- // Internal signals
32- obi_req_t obi_req_d, obi_req_q;
33- logic [31 : 0 ] rdata_d, rdata_q;
34- logic err_d, err_q;
63+ `FF (boot_addr_q, boot_addr_d, BootAddrDefault, clk_i, rst_ni)
64+ `FF (fetch_en_q, fetch_en_d, 1'b1 , clk_i, rst_ni)
65+ `FF (core_status_q, core_status_d, '0 , clk_i, rst_ni)
66+ `FF (boot_mode_q, boot_mode_d, '0 , clk_i, rst_ni)
67+ `FF (sram_dly_q, sram_dly_d, '0 , clk_i, rst_ni)
68+
69+ // OBI handling, A-phase fields needed in the R-phase
70+ logic req_q;
71+ logic we_q;
72+ logic [$bits (obi_req_i.a.aid)- 1 : 0 ] id_q;
73+ logic [IntAddrWidth- 1 : 2 ] addr_q; // word-aligned address bits only
3574
36- // bit enable mask: defines which bits are written to by wdata of the OBI request
75+ `FF (req_q, obi_req_i.req, '0 , clk_i, rst_ni)
76+ `FF (we_q, obi_req_i.a.we, '0 , clk_i, rst_ni)
77+ `FF (id_q, obi_req_i.a.aid, '0 , clk_i, rst_ni)
78+ `FF (addr_q, obi_req_i.a.addr[IntAddrWidth- 1 : 2 ], '0 , clk_i, rst_ni)
79+
80+ // byte-enable mask: expands each BE bit to a full byte for masked writes
3781 logic [31 : 0 ] be_mask;
3882 for (genvar i = 0 ; unsigned '(i) < 32 / 8 ; ++ i ) begin : gen_write_mask
3983 assign be_mask[8 * i + : 8 ] = { 8 { obi_req_i.a.be[i]}} ;
4084 end
4185
42- // Latch OBI request
43- assign obi_req_d = obi_req_i;
44-
45- // Output assignment
46- assign fetch_en_o = fetch_en_q;
47- assign sram_dly_o = sram_dly_q;
86+ assign fetch_en_o = fetch_en_q;
87+ assign sram_dly_o = sram_dly_q;
4888
49- always_comb begin : obi_response
50- obi_rsp_o = '0 ;
51- obi_rsp_o.gnt = 1'b1 ;
52- obi_rsp_o.rvalid = obi_req_q.req;
53- obi_rsp_o.r.err = err_q;
54- obi_rsp_o.r.rid = obi_req_q.a.aid;
55- obi_rsp_o.r.rdata = rdata_q;
56- end
57-
58- always_comb begin : read_write_fsm
59- rdata_d = '0 ;
60- err_d = '0 ;
89+ // Address phase: update writable registers
90+ always_comb begin : write_fsm
6191 boot_addr_d = boot_addr_q;
6292 fetch_en_d = fetch_en_q;
6393 core_status_d = core_status_q;
6494 boot_mode_d = boot_mode_q;
6595 sram_dly_d = sram_dly_q;
6696
67- if (obi_req_i.req) begin
97+ if (obi_req_i.req && obi_req_i.a.we) begin
98+ unique case ({ obi_req_i.a.addr[IntAddrWidth- 1 : 2 ], 2'b00 } )
99+ SOC_CTRL_BOOTADDR_OFFSET : boot_addr_d = obi_req_i.a.wdata & be_mask;
100+ SOC_CTRL_FETCHEN_OFFSET : fetch_en_d = obi_req_i.a.wdata[0 ] & be_mask[0 ];
101+ SOC_CTRL_CORESTATUS_OFFSET : core_status_d = obi_req_i.a.wdata & be_mask;
102+ SOC_CTRL_BOOTMODE_OFFSET : boot_mode_d = obi_req_i.a.wdata[0 ] & be_mask[0 ];
103+ SOC_CTRL_SRAM_DLY_OFFSET : sram_dly_d = obi_req_i.a.wdata[0 ] & be_mask[0 ];
104+ default : ; // invalid address: no write, error signalled in R phase
105+ endcase
106+ end
107+ end
68108
69- if (obi_req_i.a.we) begin : write
70- unique case ({ obi_req_i.a.addr[IntAddrWidth- 1 : 2 ], 2'b00 } )
71- SOC_CTRL_BOOTADDR_OFFSET : begin
72- boot_addr_d = obi_req_i.a.wdata & be_mask;
73- end
74- SOC_CTRL_FETCHEN_OFFSET : begin
75- fetch_en_d = obi_req_i.a.wdata[0 ] & be_mask[0 ];
76- end
77- SOC_CTRL_CORESTATUS_OFFSET : begin
78- core_status_d = obi_req_i.a.wdata & be_mask;
79- end
80- SOC_CTRL_BOOTMODE_OFFSET : begin
81- boot_mode_d = obi_req_i.a.wdata[0 ] & be_mask[0 ];
82- end
83- SOC_CTRL_SRAM_DLY_OFFSET : begin
84- sram_dly_d = obi_req_i.a.wdata[0 ] & be_mask[0 ];
85- end
86- default : begin
87- err_d = 1'b1 ;
88- end
89- endcase
109+ // Response phase: send back read data or acknowledge write
110+ always_comb begin : obi_response
111+ obi_rsp_o = '0 ;
112+ obi_rsp_o.gnt = 1'b1 ;
113+ obi_rsp_o.rvalid = req_q;
114+ obi_rsp_o.r.rid = id_q;
90115
91- end else begin : read
92- unique case ({ obi_req_i.a.addr[IntAddrWidth- 1 : 2 ], 2'b00 } )
93- SOC_CTRL_BOOTADDR_OFFSET : begin
94- rdata_d = boot_addr_q;
95- end
96- SOC_CTRL_FETCHEN_OFFSET : begin
97- rdata_d = { 31'h0 , fetch_en_q} ;
98- end
99- SOC_CTRL_CORESTATUS_OFFSET : begin
100- rdata_d = core_status_q;
101- end
102- SOC_CTRL_BOOTMODE_OFFSET : begin
103- rdata_d = { 31'h0 , boot_mode_q} ;
104- end
105- SOC_CTRL_SRAM_DLY_OFFSET : begin
106- rdata_d = { 31'b0 , sram_dly_q} ;
107- end
116+ if (req_q) begin
117+ if (! we_q) begin
118+ unique case ({ addr_q, 2'b00 } )
119+ SOC_CTRL_BOOTADDR_OFFSET : obi_rsp_o.r.rdata = boot_addr_q;
120+ SOC_CTRL_FETCHEN_OFFSET : obi_rsp_o.r.rdata = { 31'h0 , fetch_en_q} ;
121+ SOC_CTRL_CORESTATUS_OFFSET : obi_rsp_o.r.rdata = core_status_q;
122+ SOC_CTRL_BOOTMODE_OFFSET : obi_rsp_o.r.rdata = { 31'h0 , boot_mode_q} ;
123+ SOC_CTRL_SRAM_DLY_OFFSET : obi_rsp_o.r.rdata = { 31'b0 , sram_dly_q} ;
124+ SOC_CTRL_INFO_OFFSET : obi_rsp_o.r.rdata = HwInfoWord;
108125 default : begin
109- rdata_d = 32'hBADCAB1E ;
110- err_d = 1'b1 ;
126+ obi_rsp_o.r.rdata = 32'hBADCAB1E ;
127+ obi_rsp_o.r.err = 1'b1 ;
111128 end
112129 endcase
130+ end else begin
131+ unique case ({ addr_q, 2'b00 } )
132+ SOC_CTRL_BOOTADDR_OFFSET ,
133+ SOC_CTRL_FETCHEN_OFFSET ,
134+ SOC_CTRL_CORESTATUS_OFFSET ,
135+ SOC_CTRL_BOOTMODE_OFFSET ,
136+ SOC_CTRL_SRAM_DLY_OFFSET : ; // valid write, no error
137+ default : obi_rsp_o.r.err = 1'b1 ;
138+ endcase
113139 end
114-
115- end
116- end
117-
118- always_ff @ (posedge clk_i or negedge rst_ni) begin
119- if (~ rst_ni) begin
120- boot_addr_q <= BootAddrDefault;
121- fetch_en_q <= '1 ;
122- core_status_q <= '0 ;
123- boot_mode_q <= '0 ;
124- sram_dly_q <= '0 ;
125- obi_req_q <= '0 ;
126- rdata_q <= '0 ;
127- err_q <= '0 ;
128- end else begin
129- boot_addr_q <= boot_addr_d;
130- fetch_en_q <= fetch_en_d;
131- core_status_q <= core_status_d;
132- boot_mode_q <= boot_mode_d;
133- sram_dly_q <= sram_dly_d;
134- obi_req_q <= obi_req_d;
135- rdata_q <= rdata_d;
136- err_q <= err_d;
137140 end
138141 end
139142
0 commit comments