Skip to content

Commit

Permalink
[HW]: Add mem_multibanked_pwrgate for correct power management
Browse files Browse the repository at this point in the history
  • Loading branch information
Lore0599 committed Oct 28, 2024
1 parent 554ebbc commit 9889e5a
Show file tree
Hide file tree
Showing 4 changed files with 428 additions and 0 deletions.
2 changes: 2 additions & 0 deletions Bender.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ sources:
- src/lfsr_8bit.sv
- src/lossy_valid_to_stream.sv
- src/mv_filter.sv
- src/mem_multibank_pwrgate.sv
- src/onehot_to_bin.sv
- src/plru_tree.sv
- src/passthrough_stream_fifo.sv
Expand Down Expand Up @@ -129,6 +130,7 @@ sources:
- test/fifo_tb.sv
- test/graycode_tb.sv
- test/id_queue_tb.sv
- test/mem_multibank_pwrgate_tb.sv
- test/passthrough_stream_fifo_tb.sv
- test/popcount_tb.sv
- test/rr_arb_tree_tb.sv
Expand Down
199 changes: 199 additions & 0 deletions src/mem_multibank_pwrgate.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
// Copyright 2024 ETH Zurich and University of Bologna.
// Solderpad Hardware License, Version 0.51, see LICENSE for details.
// SPDX-License-Identifier: SHL-0.51
//
// Lorenzo Leone <[email protected]>

// ## Description:
// A wrapper for `tc_sram_impl` that instantiates logic banks with retention mode
// or power-off capability.
// This module can be used for power-aware simulations, with control signals driven
// directly by UPF signals.
//
// ## Goal:
// In a memory with multiple banks that support power gating and retention,
// each bank’s addressing must ensure that interleaving remains intact. During retention
// or power-off states, only contiguous addresses should be switched.
// The memory should always appear as a set of contiguous addresses, with no gaps in the
// address mapping.
// This module is responsible for managing the correct memory addressing
//
module mem_multibank_pwrgate #(
parameter int unsigned NumWords = 32'd1024, // Number of Words in data array

Check warning on line 22 in src/mem_multibank_pwrgate.sv

View workflow job for this annotation

GitHub Actions / verible-verilog-lint

[verible-verilog-lint] src/mem_multibank_pwrgate.sv#L22

Line length exceeds max: 100; is: 114 [Style: line-length] [line-length]
Raw output
message:"Line length exceeds max: 100; is: 114 [Style: line-length] [line-length]"  location:{path:"./src/mem_multibank_pwrgate.sv"  range:{start:{line:22  column:101}}}  severity:WARNING  source:{name:"verible-verilog-lint"  url:"https://github.com/chipsalliance/verible"}
parameter int unsigned DataWidth = 32'd128, // Data signal width

Check warning on line 23 in src/mem_multibank_pwrgate.sv

View workflow job for this annotation

GitHub Actions / verible-verilog-lint

[verible-verilog-lint] src/mem_multibank_pwrgate.sv#L23

Line length exceeds max: 100; is: 102 [Style: line-length] [line-length]
Raw output
message:"Line length exceeds max: 100; is: 102 [Style: line-length] [line-length]"  location:{path:"./src/mem_multibank_pwrgate.sv"  range:{start:{line:23  column:101}}}  severity:WARNING  source:{name:"verible-verilog-lint"  url:"https://github.com/chipsalliance/verible"}
parameter int unsigned ByteWidth = 32'd8, // Width of a data byte

Check warning on line 24 in src/mem_multibank_pwrgate.sv

View workflow job for this annotation

GitHub Actions / verible-verilog-lint

[verible-verilog-lint] src/mem_multibank_pwrgate.sv#L24

Line length exceeds max: 100; is: 105 [Style: line-length] [line-length]
Raw output
message:"Line length exceeds max: 100; is: 105 [Style: line-length] [line-length]"  location:{path:"./src/mem_multibank_pwrgate.sv"  range:{start:{line:24  column:101}}}  severity:WARNING  source:{name:"verible-verilog-lint"  url:"https://github.com/chipsalliance/verible"}
parameter int unsigned NumPorts = 32'd2, // Number of read and write ports

Check warning on line 25 in src/mem_multibank_pwrgate.sv

View workflow job for this annotation

GitHub Actions / verible-verilog-lint

[verible-verilog-lint] src/mem_multibank_pwrgate.sv#L25

Line length exceeds max: 100; is: 115 [Style: line-length] [line-length]
Raw output
message:"Line length exceeds max: 100; is: 115 [Style: line-length] [line-length]"  location:{path:"./src/mem_multibank_pwrgate.sv"  range:{start:{line:25  column:101}}}  severity:WARNING  source:{name:"verible-verilog-lint"  url:"https://github.com/chipsalliance/verible"}
parameter int unsigned Latency = 32'd1, // Latency when the read data is available

Check warning on line 26 in src/mem_multibank_pwrgate.sv

View workflow job for this annotation

GitHub Actions / verible-verilog-lint

[verible-verilog-lint] src/mem_multibank_pwrgate.sv#L26

Line length exceeds max: 100; is: 124 [Style: line-length] [line-length]
Raw output
message:"Line length exceeds max: 100; is: 124 [Style: line-length] [line-length]"  location:{path:"./src/mem_multibank_pwrgate.sv"  range:{start:{line:26  column:101}}}  severity:WARNING  source:{name:"verible-verilog-lint"  url:"https://github.com/chipsalliance/verible"}
parameter int unsigned NumLogicBanks = 32'd1, // Logic bank for Power Management

Check warning on line 27 in src/mem_multibank_pwrgate.sv

View workflow job for this annotation

GitHub Actions / verible-verilog-lint

[verible-verilog-lint] src/mem_multibank_pwrgate.sv#L27

Line length exceeds max: 100; is: 116 [Style: line-length] [line-length]
Raw output
message:"Line length exceeds max: 100; is: 116 [Style: line-length] [line-length]"  location:{path:"./src/mem_multibank_pwrgate.sv"  range:{start:{line:27  column:101}}}  severity:WARNING  source:{name:"verible-verilog-lint"  url:"https://github.com/chipsalliance/verible"}
parameter SimInit = "none", // Simulation initialization

Check warning on line 28 in src/mem_multibank_pwrgate.sv

View workflow job for this annotation

GitHub Actions / verible-verilog-lint

[verible-verilog-lint] src/mem_multibank_pwrgate.sv#L28

Explicitly define a storage type for every parameter and localparam, (SimInit). [Style: constants] [explicit-parameter-storage-type]
Raw output
message:"Explicitly define a storage type for every parameter and localparam, (SimInit). [Style: constants] [explicit-parameter-storage-type]"  location:{path:"./src/mem_multibank_pwrgate.sv"  range:{start:{line:28  column:28}}}  severity:WARNING  source:{name:"verible-verilog-lint"  url:"https://github.com/chipsalliance/verible"}

Check warning on line 28 in src/mem_multibank_pwrgate.sv

View workflow job for this annotation

GitHub Actions / verible-verilog-lint

[verible-verilog-lint] src/mem_multibank_pwrgate.sv#L28

Line length exceeds max: 100; is: 110 [Style: line-length] [line-length]
Raw output
message:"Line length exceeds max: 100; is: 110 [Style: line-length] [line-length]"  location:{path:"./src/mem_multibank_pwrgate.sv"  range:{start:{line:28  column:101}}}  severity:WARNING  source:{name:"verible-verilog-lint"  url:"https://github.com/chipsalliance/verible"}
parameter bit PrintSimCfg = 1'b0, // Print configuration

Check warning on line 29 in src/mem_multibank_pwrgate.sv

View workflow job for this annotation

GitHub Actions / verible-verilog-lint

[verible-verilog-lint] src/mem_multibank_pwrgate.sv#L29

Line length exceeds max: 100; is: 104 [Style: line-length] [line-length]
Raw output
message:"Line length exceeds max: 100; is: 104 [Style: line-length] [line-length]"  location:{path:"./src/mem_multibank_pwrgate.sv"  range:{start:{line:29  column:101}}}  severity:WARNING  source:{name:"verible-verilog-lint"  url:"https://github.com/chipsalliance/verible"}
parameter ImplKey = "none", // Reference to specific implementation

Check warning on line 30 in src/mem_multibank_pwrgate.sv

View workflow job for this annotation

GitHub Actions / verible-verilog-lint

[verible-verilog-lint] src/mem_multibank_pwrgate.sv#L30

Explicitly define a storage type for every parameter and localparam, (ImplKey). [Style: constants] [explicit-parameter-storage-type]
Raw output
message:"Explicitly define a storage type for every parameter and localparam, (ImplKey). [Style: constants] [explicit-parameter-storage-type]"  location:{path:"./src/mem_multibank_pwrgate.sv"  range:{start:{line:30  column:28}}}  severity:WARNING  source:{name:"verible-verilog-lint"  url:"https://github.com/chipsalliance/verible"}

Check warning on line 30 in src/mem_multibank_pwrgate.sv

View workflow job for this annotation

GitHub Actions / verible-verilog-lint

[verible-verilog-lint] src/mem_multibank_pwrgate.sv#L30

Line length exceeds max: 100; is: 121 [Style: line-length] [line-length]
Raw output
message:"Line length exceeds max: 100; is: 121 [Style: line-length] [line-length]"  location:{path:"./src/mem_multibank_pwrgate.sv"  range:{start:{line:30  column:101}}}  severity:WARNING  source:{name:"verible-verilog-lint"  url:"https://github.com/chipsalliance/verible"}
// DEPENDENT PARAMETERS, DO NOT OVERWRITE!
parameter int unsigned AddrWidth = (NumWords > 32'd1) ? $clog2(NumWords) : 32'd1,
parameter int unsigned BeWidth = (DataWidth + ByteWidth - 32'd1) / ByteWidth, // ceil_div
parameter type addr_t = logic [AddrWidth-1:0],
parameter type data_t = logic [DataWidth-1:0],
parameter type be_t = logic [BeWidth-1:0]
) (
input logic clk_i, // Clock
input logic rst_ni, // Asynchronous reset active low
// input ports
input logic [ NumPorts-1:0] req_i, // request
input logic [ NumPorts-1:0] we_i, // write enable
input addr_t [ NumPorts-1:0] addr_i, // request address
input data_t [ NumPorts-1:0] wdata_i, // write data
input be_t [ NumPorts-1:0] be_i, // write byte enable
input logic [NumLogicBanks-1:0] deepsleep_i, // deep sleep enable
input logic [NumLogicBanks-1:0] powergate_i, // power gate enable
// output ports
output data_t [ NumPorts-1:0] rdata_o // read data
);

// Implementation type for Power Gating and Deppesleep ports
typedef struct packed {
logic deepsleep;
logic powergate;
} impl_in_t;


if (NumLogicBanks == 32'd0) begin : gen_no_logic_bank
$fatal("Error: %d logic banks are not supported", NumLogicBanks);
end else if (NumLogicBanks == 32'd1) begin : gen_simple_sram
tc_sram_impl #(
.NumWords (NumWords),
.DataWidth (DataWidth),
.ByteWidth (ByteWidth),
.NumPorts (NumPorts),
.Latency (Latency),
.SimInit (SimInit),
.PrintSimCfg(PrintSimCfg),
.ImplKey (ImplKey),
.impl_in_t (impl_in_t),
.impl_out_t (impl_in_t)
) i_tc_sram_impl (
.clk_i,
.rst_ni,
.impl_i({deepsleep_i, powergate_i}),
.impl_o(),
.req_i,
.we_i,
.addr_i,
.wdata_i,
.be_i,
.rdata_o
);

end else begin : gen_logic_bank // block: gen_simple_sram
localparam int unsigned LogicBankSize = NumWords / NumLogicBanks;
localparam int unsigned BankSelWidth = (NumLogicBanks > 32'd1) ? $clog2(
NumLogicBanks
) : 32'd1;

if (LogicBankSize != 2 ** (AddrWidth - BankSelWidth))
$fatal("Logic Bank size is not a power of two: UNSUPPORTED ");

// Signals from/to logic banks
logic [NumLogicBanks-1:0][ NumPorts-1:0] req_cut;
logic [NumLogicBanks-1:0][ NumPorts-1:0] we_cut;
logic [NumLogicBanks-1:0][ NumPorts-1:0][AddrWidth-BankSelWidth-1:0] addr_cut;
data_t [NumLogicBanks-1:0][ NumPorts-1:0] wdata_cut;
be_t [NumLogicBanks-1:0][ NumPorts-1:0] be_cut;
data_t [NumLogicBanks-1:0][ NumPorts-1:0] rdata_cut;

// Signals to select the right bank
logic [ NumPorts-1:0][BankSelWidth-1:0] bank_sel;
logic [NumPorts-1:0][Latency-1:0][BankSelWidth-1:0] out_mux_sel_d, out_mux_sel_q;

// Identify bank looking at the BankSelWidth-th MSBs of the Address
for (genvar PortIdx = 0; PortIdx < NumPorts; PortIdx++) begin : gen_bank_sel
assign bank_sel[PortIdx] = addr_i[PortIdx][AddrWidth-1-:BankSelWidth];
end

// Read Data Mux Logic:
//
// If the memory has Latency != 0, the read data will arive after a certain delay.
// During this time, the bank_select signal must be stored in order to
// correctly select the output bank after the expected latency.
if (Latency == 32'd0) begin : gen_no_latency
for (genvar PortIdx = 0; PortIdx < NumPorts; PortIdx++) begin : gen_read_mux_signals
assign rdata_o[PortIdx] = rdata_cut[bank_sel[PortIdx]][PortIdx];
end
end else begin : gen_read_latency
always_comb begin
for (int PortIdx = 0; PortIdx < NumPorts; PortIdx++) begin : gen_read_mux_signals
rdata_o[PortIdx] = rdata_cut[out_mux_sel_q[PortIdx][0]][PortIdx];
for (int shift_idx = 0; shift_idx < (Latency - 1); shift_idx++) begin : gen_shift
out_mux_sel_d[PortIdx][shift_idx] = out_mux_sel_q[PortIdx][shift_idx+1];
end
out_mux_sel_d[PortIdx][Latency-1] = bank_sel[PortIdx];
end
end

always_ff @(posedge clk_i or negedge rst_ni) begin
for (int PortIdx = 0; PortIdx < NumPorts; PortIdx++) begin
if (!rst_ni) begin
out_mux_sel_q[PortIdx] = '0;

Check warning on line 135 in src/mem_multibank_pwrgate.sv

View workflow job for this annotation

GitHub Actions / verible-verilog-lint

[verible-verilog-lint] src/mem_multibank_pwrgate.sv#L135

Use blocking assignments, at most, for locals inside 'always_ff' sequential blocks. [Style: sequential-logic] [always-ff-non-blocking]
Raw output
message:"Use blocking assignments, at most, for locals inside 'always_ff' sequential blocks. [Style: sequential-logic] [always-ff-non-blocking]"  location:{path:"./src/mem_multibank_pwrgate.sv"  range:{start:{line:135  column:19}}}  severity:WARNING  source:{name:"verible-verilog-lint"  url:"https://github.com/chipsalliance/verible"}
end else begin
for (int shift_idx = 0; shift_idx < Latency; shift_idx++) begin
out_mux_sel_q[PortIdx][shift_idx] = out_mux_sel_d[PortIdx][shift_idx];

Check warning on line 138 in src/mem_multibank_pwrgate.sv

View workflow job for this annotation

GitHub Actions / verible-verilog-lint

[verible-verilog-lint] src/mem_multibank_pwrgate.sv#L138

Use blocking assignments, at most, for locals inside 'always_ff' sequential blocks. [Style: sequential-logic] [always-ff-non-blocking]
Raw output
message:"Use blocking assignments, at most, for locals inside 'always_ff' sequential blocks. [Style: sequential-logic] [always-ff-non-blocking]"  location:{path:"./src/mem_multibank_pwrgate.sv"  range:{start:{line:138  column:22}}}  severity:WARNING  source:{name:"verible-verilog-lint"  url:"https://github.com/chipsalliance/verible"}
end
end
end
end
end : gen_read_latency

// Write data Mux Logic
//
for (genvar BankIdx = 0; BankIdx < NumLogicBanks; BankIdx++) begin : gen_logic_bank
for (genvar PortIdx = 0; PortIdx < NumPorts; PortIdx++) begin

Check warning on line 148 in src/mem_multibank_pwrgate.sv

View workflow job for this annotation

GitHub Actions / verible-verilog-lint

[verible-verilog-lint] src/mem_multibank_pwrgate.sv#L148

All generate block statements must have a label [Style: generate-statements] [generate-label]
Raw output
message:"All generate block statements must have a label [Style: generate-statements] [generate-label]"  location:{path:"./src/mem_multibank_pwrgate.sv"  range:{start:{line:148  column:66}}}  severity:WARNING  source:{name:"verible-verilog-lint"  url:"https://github.com/chipsalliance/verible"}
// DEMUX the input signals to the correct logic bank
// Assign req channel to the correct logic bank
assign req_cut[BankIdx][PortIdx] = req_i[PortIdx] && (bank_sel[PortIdx] == BankIdx);
// Assign lowest part of the address to the correct logic bank
assign addr_cut[BankIdx][PortIdx] = req_cut[BankIdx][PortIdx] ? addr_i[PortIdx][AddrWidth-BankSelWidth-1:0] : '0;

Check warning on line 153 in src/mem_multibank_pwrgate.sv

View workflow job for this annotation

GitHub Actions / verible-verilog-lint

[verible-verilog-lint] src/mem_multibank_pwrgate.sv#L153

Line length exceeds max: 100; is: 126 [Style: line-length] [line-length]
Raw output
message:"Line length exceeds max: 100; is: 126 [Style: line-length] [line-length]"  location:{path:"./src/mem_multibank_pwrgate.sv"  range:{start:{line:153  column:101}}}  severity:WARNING  source:{name:"verible-verilog-lint"  url:"https://github.com/chipsalliance/verible"}
// Assign data to the correct logic bank
assign wdata_cut[BankIdx][PortIdx] = req_cut[BankIdx][PortIdx] ? wdata_i[PortIdx] : '0;
assign we_cut[BankIdx][PortIdx] = req_cut[BankIdx][PortIdx] ? we_i[PortIdx] : '0;
assign be_cut[BankIdx][PortIdx] = req_cut[BankIdx][PortIdx] ? be_i[PortIdx] : '0;
end

tc_sram_impl #(
.NumWords (LogicBankSize),
.DataWidth (DataWidth),
.ByteWidth (ByteWidth),
.NumPorts (NumPorts),
.Latency (Latency),
.SimInit (SimInit),
.PrintSimCfg(PrintSimCfg),
.ImplKey (ImplKey),
.impl_in_t (impl_in_t),
.impl_out_t (impl_in_t)
) i_tc_sram_impl (
.clk_i,
.rst_ni,
.impl_i ({deepsleep_i[BankIdx], powergate_i[BankIdx]}),
.impl_o (),
.req_i (req_cut[BankIdx]),
.we_i (we_cut[BankIdx]),
.addr_i (addr_cut[BankIdx]),
.wdata_i(wdata_cut[BankIdx]),
.be_i (be_cut[BankIdx]),
.rdata_o(rdata_cut[BankIdx])
);
end
end

// Trigger warnings when power signals (deepsleep_i and powergate_i) are not connected.
// Usually those signals must be linked through the UPF.
`ifndef VERILATOR
`ifndef TARGET_SYNTHESIS
initial begin
assert (!$isunknown(deepsleep_i))
else $warning("deepsleep_i has some unconnected signals");
assert (!$isunknown(powergate_i))
else $warning("powergate_i has some unconnected signals");
end
`endif
`endif

endmodule //endmodule: mem_multibank_pwrgate
Loading

0 comments on commit 9889e5a

Please sign in to comment.