Commit 0989e21a authored by Guillem's avatar Guillem
Browse files

WIP integration and FV

Added color output to SBY and SVA assertions
parent 9ff17bdf
hdl/PMU_raw/
*.swp
hdl/tmp*
......@@ -27,6 +27,7 @@
`endif
module PMU_raw #
(
//------------- External parameters
// Width of registers data bus
parameter integer REG_WIDTH = 32,
// Amount of counters
......@@ -34,15 +35,40 @@
// Configuration registers
parameter integer N_CONF_REGS = 1,
// Overflow
parameter integer OVERFLOW = 0, //Yes/No
parameter integer OVERFLOW = 1, //Yes/No
// Quota
parameter integer QUOTA = 0, //Yes/No
// MCCU - Maximum-contention Control Unit mode
parameter integer MCCU = 0, //Yes/No
// MCCU - N_CORES
parameter integer N_CORES = 1,
// Total of registers used
localparam integer TOTAL_NREGS = N_COUNTERS + N_CONF_REGS
parameter integer N_CORES = 1,
//------------- Internal Parameters
//---- configuration registers
localparam BASE_CFG = 0,
localparam END_CFG = BASE_CFG + N_CONF_REGS -1,
//---- Counter registers
localparam BASE_COUNTERS = END_CFG + 1,
localparam END_COUNTERS = BASE_COUNTERS + N_COUNTERS-1,
//---- Quota interruption registers
// General parameters feature
localparam BASE_OVERFLOW_INTR = END_COUNTERS + 1,
// mask feature
// OVERFLOW_INTR_MASK_REGS is equivalent to $ceil(N_COUNTERS/REG_WIDTH)
localparam BASE_OVERFLOW_MASK = BASE_OVERFLOW_INTR,
localparam N_OVERFLOW_MASK_REGS = ((N_COUNTERS-1)/REG_WIDTH+1),
localparam END_OVERFLOW_MASK = BASE_OVERFLOW_MASK + N_OVERFLOW_MASK_REGS -1,
// overflow interruption vector feature
// OVERFLOW_INTR_MASK_REGS is equivalent to $ceil(N_COUNTERS/REG_WIDTH)
localparam BASE_OVERFLOW_VECT = (END_OVERFLOW_MASK+1),
localparam N_OVERFLOW_VECT_REGS = ((N_COUNTERS-1)/REG_WIDTH+1),
localparam END_OVERFLOW_VECT = BASE_OVERFLOW_VECT + N_OVERFLOW_VECT_REGS -1,
// General parameters feature
localparam N_OVERFLOW_REGS = (N_OVERFLOW_VECT_REGS + N_OVERFLOW_VECT_REGS) * OVERFLOW,
localparam END_OVERFLOW_INTR = BASE_OVERFLOW_INTR + N_OVERFLOW_REGS -1,
// Total of registers used
localparam integer TOTAL_NREGS =
N_COUNTERS + N_CONF_REGS + N_OVERFLOW_REGS
)
(
// Global Clock Signal
......@@ -57,14 +83,14 @@
// uploads the content with external values
input wire wrapper_we_i,
// Event signals
input wire [N_COUNTERS-1:0] events_i
input wire [N_COUNTERS-1:0] events_i,
//interruption rises when one of the counters overflows
output reg intr_overflow_o
/* //interruptions risen when one event exceeds it expected max duration
output wire int_rdc_o,
//interruptions risen when cores exceeds the quota of MCCU
output wire MCCU_int_o [N_CORES-1:0],
//interruption rises when one of the counters overflows
output reg int_overflow_o,
//interruption rises when the total of cuota consumed is exceeded
output wire int_quota_o,
//external signals from Soc events
......@@ -80,38 +106,21 @@
//----------------------------------------------
//------------- Declare wires from/to wrapper registers
//----------------------------------------------
//---- configuration registers
//---- configuration signals
reg [REG_WIDTH-1:0] cfg_reg;
wire en_i;
wire softrst_i;
//---- Counter registers
//---- Counter signals
wire [REG_WIDTH-1:0] counter_regs_o [0 : N_COUNTERS-1];
wire [REG_WIDTH-1:0] counter_regs_i [0 : N_COUNTERS-1];
//----------------------------------------------
//------------- Counters instance
//----------------------------------------------
PMU_counters # (
.REG_WIDTH (REG_WIDTH),
.N_COUNTERS (N_COUNTERS)
)
inst_counters (
.clk_i (clk_i),
.rstn_i (rstn_i),
.softrst_i (softrst_i),
.en_i (en_i),
.we_i (wrapper_we_i),
.regs_i (counter_regs_i),
.regs_o (counter_regs_o),
.events_i (events_i)
);
wire [REG_WIDTH-1:0] counter_regs_int [0 : N_COUNTERS-1];
//---- Overflow interruption signals
wire [N_COUNTERS-1:0] overflow_intr_mask_i [0 : N_OVERFLOW_MASK_REGS-1];
wire [N_COUNTERS-1:0] overflow_intr_vect_o [0 : N_OVERFLOW_VECT_REGS-1];
//----------------------------------------------
//------------- Map registers from wrapper to slave functions
//----------------------------------------------
//---- configuration registers
localparam BASE_CFG = 0;
always_ff @(posedge clk_i, negedge rstn_i) begin
if(rstn_i == 1'b0 ) begin
cfg_reg <= {REG_WIDTH{1'b0}};
......@@ -127,31 +136,60 @@
//---- Counter registers
genvar x;
generate
localparam BASE_COUNTERS = BASE_CFG + N_CONF_REGS;
localparam END_COUNTERS = BASE_COUNTERS + N_COUNTERS;
for(x=BASE_COUNTERS;x<END_COUNTERS;x++) begin
assign counter_regs_i[x-BASE_COUNTERS] = regs_i[x];
for(x=BASE_COUNTERS;x<=END_COUNTERS;x++) begin
assign counter_regs_int[x-BASE_COUNTERS] = regs_i[x];
assign regs_o[x] = counter_regs_o[x-BASE_COUNTERS];
end
endgenerate
//---- Overflow interruption registers
generate
for(x=0;x<N_OVERFLOW_MASK_REGS;x++) begin
assign overflow_intr_mask_i[x] = (rstn_i == 1'b0)? '{default:0} :regs_i [x][N_COUNTERS-1:0];
end
for(x=BASE_OVERFLOW_VECT;x<=END_OVERFLOW_VECT;x++) begin
assign regs_o [x] = (rstn_i == 1'b0)? '{default:0} : REG_WIDTH'(overflow_intr_vect_o[x-BASE_OVERFLOW_VECT]);
end
endgenerate
//---- Quota interruption registers
//---- MCCU registers
//---- Request Duration Counter (RDC) registers
//----------------------------------------------
//------------- Counters instance
//----------------------------------------------
PMU_counters # (
.REG_WIDTH (REG_WIDTH),
.N_COUNTERS (N_COUNTERS)
)
inst_counters (
.clk_i (clk_i),
.rstn_i (rstn_i),
.softrst_i (softrst_i),
.en_i (en_i),
.we_i (wrapper_we_i),
.regs_i (counter_regs_int),
.regs_o (counter_regs_o),
.events_i (events_i)
);
//----------------------------------------------
//------------- Overflow interuption instance
//----------------------------------------------
/* PMU_overflow # (
PMU_overflow # (
.REG_WIDTH (REG_WIDTH),
.N_COUNTERS (N_COUNTERS)
)
inst_overflow (
.clk_i (),
.rstn_i (),
.softrst_i (),
.en_i (),
.counter_regs_i (),
.over_intr_mask_i (),
.intr_overflow_o (),
.over_intr_vect_o ()
.clk_i (clk_i),
.rstn_i (rstn_i),
.softrst_i (softrst_i),
.en_i (en_i),
.counter_regs_i (counter_regs_o),
.over_intr_mask_i (overflow_intr_mask_i[0][N_COUNTERS-1:0]),
.intr_overflow_o (intr_overflow_o),
.over_intr_vect_o (overflow_intr_vect_o[0][N_COUNTERS-1:0])
);
*/
//----------------------------------------------
//------------- Quota interruption instance
//----------------------------------------------
......@@ -222,12 +260,27 @@
//Cleared when MCCU is disabled.
);
*/
////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
//
// Formal Verification section begins here.
//
////////////////////////////////////////////////////////////////////////////////
`ifdef FORMAL
//auxiliar registers
reg f_past_valid ;
initial f_past_valid = 1'b0;
//Set f_past_valid after first clock cycle
always@( posedge clk_i )
f_past_valid <= 1'b1;
//assume that if f_past is not valid you have to reset
always @(*) begin
if(0 == f_past_valid) begin
assume(0 == rstn_i);
end
end
`endif
endmodule
......
......@@ -9,7 +9,7 @@
// Coder : G.Cabo
// References : AMBA 3 AHB-lite specifications
// ARM IHI 0033A
// Notes :
// Notes : Burst, protected accesses and lock access are not supported
`default_nettype none
`timescale 1 ns / 1 ps
......@@ -118,6 +118,7 @@ localparam TRANSFER_ERROR_RESP_2CYCLE = 2'b11;
//------------- Data structures
//----------------------------------------------
var struct packed{
//TODO: clean up unused
logic select;
logic write;
logic master_ready;
......@@ -202,26 +203,14 @@ always_ff @(posedge clk_i, negedge rstn_i) begin
TRANS_NONSEQUENTIAL:begin
address_phase.select <= hsel_i;
address_phase.write <= hwrite_i;
address_phase.master_ready <= hreadyi_i;
address_phase.master_addr <= haddr_i;
// address_phase.master_data <= hwdata_i;
address_phase.trans_type <= htrans_i;
//address_phase.trans_size <= hsize_i;
//address_phase.burst_type <= hburst_i;
//address_phase.protection <= hprot_i;
//address_phase.lock <= hmastlock_i;
end
TRANS_SEQUENTIAL:begin
address_phase.select <= hsel_i;
address_phase.write <= hwrite_i;
address_phase.master_ready <= hreadyi_i;
address_phase.master_addr <= haddr_i;
// address_phase.master_data <= hwdata_i;
address_phase.trans_type <= htrans_i;
//address_phase.trans_size <= hsize_i;
//address_phase.burst_type <= hburst_i;
//address_phase.protection <= hprot_i;
//address_phase.lock <= hmastlock_i;
end
endcase
end
......@@ -298,59 +287,3 @@ always_comb begin
end
endmodule
`default_nettype wire //allow compatibility with legacy code and xilinx ip
/*
// -- AHB bus slave interface
// burst type
// write data bus
input wire [HDATA_WIDTH-1:0] hwdata_i,
// prtection control
input wire [3:0] hprot_i,
// transfer done
input wire hreadyi_i,
// current master
input wire [3:0] hmaster_i,
// locked access
input wire hmastlock_i,
// trasfer done
output wire hreadyo_o,
// response type
output wire [1:0] hresp_o,
// read data bus
output wire [HDATA_WIDTH-1:0] hrdata_o,
// split completion
output wire [15:0] hsplit_o
//------------- AHB Basic functions
input wire rstn_i,
input wire clk_i,
input wire hsel_i,
input wire [HADDR_WIDTH-1:0] haddr_i,
input wire hwrite_i,
input wire [1:0] htrans_i,
input wire [2:0] hsize_i,
//------------- AHB Bursts
input wire [1:0] htrans_i,
input wire [2:0] hburst_i,
//------------- AHB Locked transfers
//------------- AHB Protection control
//------------- AHB Bursts
//------------- AHB Bursts
address_phase.select <= hsel_i;
address_phase.write <= hwrite_i;
address_phase.master_ready <= hreadyi_i;
address_phase.master_addr <= haddr_i;
address_phase.master_data <= hwdata_i;
address_phase.trans_type <= htrans_i;
address_phase.trans_size <= hsize_i;
address_phase.burst_type <= hburst_i;
address_phase.protection <= hprot_i;
address_phase.lock <= hmastlock_i;
logic slave_ready;
logic [1:0] slave_resp;
logic [HDATA_WIDTH-1:0] slave_data;
data_phase.slave_ready <= ;
data_phase.slave_resp <= ;
data_phase.slave_data <= ;
* */
......@@ -7,8 +7,9 @@
// AHB master and interface with pmu_ahb module.
//
// Coder : G.Cabo
// References : AHB5 specifications
// https://silver.arm.com/download/download.tm?pv=2646779
// References : AMBA 3 AHB-lite specifications
// ARM IHI 0033A
// Notes :
`default_nettype none
`timescale 1 ns / 1 ps
......@@ -23,10 +24,9 @@
parameter haddr = 0,
parameter hmask = 0,
// Total amount of registers
parameter integer N_REGS = 10,
parameter integer N_REGS = 10,
// Width of registers data bus
parameter integer REG_WIDTH = 32,
//haddr width
localparam integer HADDR_WIDTH = 32,
//hdata width
......@@ -38,6 +38,8 @@
// -- AHB bus slave interface
// slave select
input wire hsel_i,
// previous transfer done
input wire hreadyi_i,
// address bus
input wire [HADDR_WIDTH-1:0] haddr_i,
// read/write
......@@ -52,10 +54,6 @@
input wire [HDATA_WIDTH-1:0] hwdata_i,
// prtection control
input wire [3:0] hprot_i,
// transfer done
input wire hreadyi_i,
// current master
input wire [3:0] hmaster_i,
// locked access
input wire hmastlock_i,
// trasfer done
......@@ -63,22 +61,70 @@
// response type
output wire [1:0] hresp_o,
// read data bus
output wire [HDATA_WIDTH-1:0] hrdata_o,
// split completion
output wire [15:0] hsplit_o
// -- PMU input signals
// -- PMU output signals
output wire [HDATA_WIDTH-1:0] hrdata_o
);
//----------------------------------------------
//------------- Local parameters
//----------------------------------------------
// ** Types of bursts (hburst_i) **
//Single burst
localparam SINGLE = 3'b00;
//Incrementing burst of undefined length
localparam INCR = 3'b01;
//4-beat wrapping burst
localparam WRAP4 = 3'b010;
//4-beat incrementing burst
localparam INCR4 = 3'b011;
//8-beat wrapping burst
localparam WRAP8 = 3'b100;
//8-beat incrementing burst
localparam INCR8 = 3'b101;
//16-beat wrapping burs
localparam WRAP16 = 3'b110;
//16-beat incrementing burst
localparam INCR16 = 3'b111;
// ** Type of transfers (htrans_i) **
localparam TRANS_IDLE = 2'b00;
localparam TRANS_BUSY = 2'b01;
localparam TRANS_NONSEQUENTIAL = 2'b10;
localparam TRANS_SEQUENTIAL = 2'b11;
// ** Type of Ready outputs (hreadyo_o) **
//PENDING. Transfer has to be extended one cycle more
//COMPLETE. Transfer has finish
localparam READY_PENDING = 1'b0;
localparam READY_COMPLETE = 1'b1;
// ** Type of Response outputs (hresp_o)**
//OKAY. Transfer has finish or has to be extended
//ERROR. Transfer is not valid
localparam READYO_OKAY = 1'b0;
localparam READYO_ERROR = 1'b1;
// ** Transfer status **
// **{{hresp_o},{hready_o}}
localparam TRANSFER_PENDING = 2'b00;
localparam TRANSFER_SUCCESS_COMPLETE = 2'b01;
localparam TRANSFER_ERROR_RESP_1CYCLE = 2'b10;
localparam TRANSFER_ERROR_RESP_2CYCLE = 2'b11;
//----------------------------------------------
//------------- Data structures
//----------------------------------------------
var struct packed{
logic select;
logic write;
logic master_ready;
logic [HADDR_WIDTH-1:0] master_addr;
} address_phase;
//----------------------------------------------
//------------- AHB registers
//----------------------------------------------
reg [REG_WIDTH-1:0] slv_reg [0:N_REGS-1];
wire [REG_WIDTH-1:0] slv_reg_D [0:N_REGS-1];
wire [REG_WIDTH-1:0] slv_reg_Q [0:N_REGS-1];
logic [REG_WIDTH-1:0] slv_reg [0:N_REGS-1];
logic [REG_WIDTH-1:0] slv_reg_D [0:N_REGS-1];
logic [REG_WIDTH-1:0] slv_reg_Q [0:N_REGS-1];
assign slv_reg_Q = slv_reg;
......@@ -89,81 +135,114 @@
slv_reg <= slv_reg_D;
end
end
//----------------------------------------------
//------------- AHB control logic
//----------------------------------------------
//basic transfers
//Addres phase 1 cycle unless extended by previous bus transfer
//Data phase 1 + extende by HREADY
//Simple transfer NO WAIT STATES (1 cycle address + 1 cycle data)
//capture Addres - hold address for data phase
reg [HADDR_WIDTH-1:0] haddr_int;
always_ff @(posedge clk_i, negedge rstn_i) begin
if(rstn_i == 1'b0 ) begin
haddr_int <= {HADDR_WIDTH{1'b0}};
end else begin
haddr_int <= haddr_i;
logic [1:0] state, next;
// address phase - state update
always_comb begin
case (htrans_i)
TRANS_IDLE: begin
next = TRANS_IDLE;
end
end
//capture data - hold data for data phase
reg [HDATA_WIDTH-1:0] hdata_int;
always_ff @(posedge clk_i, negedge rstn_i) begin
if(rstn_i == 1'b0 ) begin
hdata_int <= {HDATA_WIDTH{1'b0}};
end else begin
hdata_int <= hwdata_i;
TRANS_BUSY:begin
next = TRANS_BUSY;
end
end
// Detect direction, and register for data stage . HWRITE controls direction
//(HIGH means write transfer from master to slave)
//(LOW means read transfer from slave to master)
wire write_req_d;
wire read_req_d;
assign write_req_d = !hreadyi_i? 1'b0 : hwrite_i ? 1'b1 : 1'b0;
assign read_req_d = !hreadyi_i? 1'b0 : hwrite_i ? 1'b0 : 1'b1;
reg write_req_q;
reg read_req_q;
always_ff @(posedge clk_i, negedge rstn_i) begin
if(rstn_i == 1'b0 ) begin
write_req_q <= 1'b0;
read_req_q <= 1'b0;
end else begin
write_req_q <= write_req_d;
read_req_q <= read_req_d;
TRANS_NONSEQUENTIAL:begin
if(!hsel_i) begin
next = TRANS_IDLE;
end else begin
next = TRANS_NONSEQUENTIAL;
end
end
end
// Generate index of write/read responses
// Assume only 32b acces are done. 2 LSB are not used in address
wire [$clog2(N_REGS)-1:0] slv_index;
assign slv_index = haddr_int[$clog2(N_REGS)+1:2];
//Response in data cycle
reg [REG_WIDTH-1:0] resp_data;
always_ff @(posedge clk_i, negedge rstn_i) begin
if(rstn_i == 1'b0 ) begin
resp_data <= {REG_WIDTH{1'b0}};
end else begin
resp_data <= slv_reg[haddr_i];
TRANS_SEQUENTIAL:begin
if(!hsel_i) begin
next = TRANS_IDLE;
end else begin
next = TRANS_SEQUENTIAL;
end
end
endcase
end
// address phase - register required inputs
always_ff @(posedge clk_i, negedge rstn_i) begin
if(rstn_i == 1'b0 ) begin
//initialize all the structure to 0 at reset
address_phase <= '{default:0};
end else begin
case (next)
TRANS_IDLE:begin
address_phase.select <= hsel_i;
address_phase.write <= hwrite_i;
end
TRANS_BUSY:begin
address_phase.select <= hsel_i;
address_phase.write <= hwrite_i;
end
TRANS_NONSEQUENTIAL:begin
address_phase.select <= hsel_i;
address_phase.write <= hwrite_i;
address_phase.master_addr <= haddr_i;
end
TRANS_SEQUENTIAL:begin
address_phase.select <= hsel_i;
address_phase.write <= hwrite_i;
address_phase.master_addr <= haddr_i;
end
endcase
end
//Write in data cycle - Writes to slave registers are arbitrated due to
//the implementation of my slave
wire [REG_WIDTH-1:0] write_data;
assign write_data = hwdata_i;
end
//Send registerd signals to interface
assign hrdata_o = resp_data;
//data phase - state update
always_ff @(posedge clk_i, negedge rstn_i) begin
if(rstn_i == 1'b0 ) begin
state<=TRANS_IDLE;
end else begin
state <= next;
end
end
//TODO: If the slave can block the requests move it kto
//AHB to PMU_raw synchronization section
//Acknowledge AHB read/write is done
assign hreadyo_o = write_req_q || read_req_q;
//data phase - slave response
wire [$clog2(N_REGS)-1:0] slv_index;
logic [HDATA_WIDTH-1:0] dwrite_slave; //Data master to the register bank
assign slv_index = address_phase.master_addr[$clog2(N_REGS)+1:2];
logic [1:0] complete_transfer_status;
logic [HDATA_WIDTH-1:0] dread_slave; //response from slave
assign hrdata_o = dread_slave;
//TODO report error if reading out of range
assign hreadyo_o = complete_transfer_status [0];
//TODO: review the amount of bits for hresp_o
assign hresp_o = {{complete_transfer_status[1]},{complete_transfer_status[1]}};
//TODO: review
//dread_slave and dwrite_slave can be latched
//They will be ignored by the master and slave registers
always_latch begin
case (state)
TRANS_IDLE: begin
complete_transfer_status = TRANSFER_SUCCESS_COMPLETE;
end
TRANS_BUSY:begin
complete_transfer_status = TRANSFER_SUCCESS_COMPLETE;
end
TRANS_NONSEQUENTIAL:begin
complete_transfer_status = TRANSFER_SUCCESS_COMPLETE;
dwrite_slave = hwdata_i;
if (!address_phase.write) begin
dread_slave = slv_reg_Q[slv_index];
end
end
TRANS_SEQUENTIAL:begin
complete_transfer_status = TRANSFER_SUCCESS_COMPLETE;
dwrite_slave = hwdata_i;
if (!address_phase.write) begin
dread_slave = slv_reg_Q[slv_index];
end
end
endcase
end
//----------------------------------------------
//------------- PMU_raw instance
......@@ -173,6 +252,8 @@
localparam PMU_TOTAL_REGS = PMU_COUNTERS + PMU_CFG;
//assert(PMU_TOTAL_REGS == N_REGS);
wire [REG_WIDTH-1:0] pmu_regs_int [0:PMU_TOTAL_REGS-1];
wire ahb_write_req;
assign ahb_write_req = address_phase.write && address_phase.select;