Commit dc2397bc authored by GuillemCabo's avatar GuillemCabo
Browse files

Crossbar integration, TB and Docs

Integrate crossbar
Add crossbar test case

Add specs
parent 68c3d99f
No preview for this file type
\section{General purpose of the module}
This module allows to map N inputs from the SoC in to M counters without restrictions.
All SoC signals can be routed to each counter of the PMU.\\
Note that even if the amount of inputs is smaller than the amount of counters it is still interesting to have the crossbar since it allows to map any event to counters that support advanced capabilities such as the MCCU and RDC. At the moment to identify if a counter has MCCU or RDC support is required to check the source code of PMU\ in order to see the assignments. By default the quad-core configuration with two events for each core maps this features to events 0 to 7.\\
\section{Design placement}
This modules is meant to be instantiated by the interface agnostic PMU (PMU\ Only one instance of this module is required.
%This module is meant to be a blackbox inside the chisel code. It belongs to the Drac class in the \emph{rocket.scala} file. We can have as many instances of this module as cores are instantiated in the SoC. Currently only single core operation has been tested.
This module requires two integer parameters. \textbf{N\_IN} defines the number of inputs provided by the SoC.
\textbf{N\_OUT} defines the number of outputs of the Crossbar and matches the amount of counters in the PMU.\\
The amount of bits required for each configuration field of each output is stored in the local parameter \textbf{N\_BITS\_CFG} and its value is the ceiling of the base 2 logarithm of N\_IN.
\label{chapter 4}
Port Name & Direction & Width & Index & Comment & Comment Source
clk\_i & INPUT & 1 & - & Global clock signal & module port
rstn\_i & INPUT & 1 & - & Global active low reset signal & module port
vector\_i & INPUT & 32 & [0:31] & Input vector & module port
vector\_o & OUTPUT & 24 & [0:23] & Output vector & module port
cfg\_i & INPUT & 120 & [0:23][4:0] & Configuration registers & module port
\caption{Ports of module crossbar}
Interface signals of the module are listed in table \ref{port:crossbar}. Default parameter values are used for width and Index fields but they may change for each implementation.
% \centering
% \begin{tabular}{lllll}
% \hline
% Port\_Name & Direction & Width & Index & Description \\
% \hline
% CLK & INPUT & 1 & - & Main clock, up to 200MHz \\
% RST & INPUT & 1 & - & Hard reset. Active LOW \\
% SOFT\_RST & INPUT & 1 & - & Soft reset. Active LOW \\
% RESET\_ADDRESS & INPUT & 40 & - & Inital address of PC after soft or hard reset \\
% CSR\_RW\_RDATA & INPUT & 64 & - & - \\
% \end{tabular}
\section{Reset behavior}
When reset is active (LOW), internal registers are set to 0. In the next cycle outputs of the crossbar will become 0.\\
When reset is not active (HIGH) input signals selected by the configuration fields are routed to the output. Since outputs are registered, we see one cycle of latency.
\section{What could not happen}
The number of inputs (N\_IN), shall be larger than the outputs (N\_OUT). If this is not the case padding signals can be added in the SoC side, but the unit will take more resources than strictly needed and it is not recommended for final applications or resource evaluation.
\ No newline at end of file
The unit allows to route N input signals in to M output signals. Unused inputs are unconnected.\\
The crossbar routes the signals based on the values of cfg\_i. Each output has one configuration field that indicates the input that is routing. The value for the configuration field of each output matches the the position in vector\_i of the signal that you want to route through.\\
Each configuration field takes\textit{ \$clog2(N)} bits. In the default integration with PMU\_raw the fields are\textbf{ contiguous and consecutive} to each other. Due to this arrangement it may be the case for \textbf{configuration fields to not be aligned with data words} of the target processor or cross address boundaries. It is up to the software developers to provide function calls to handle this scenarios.\\
Outputs of the crossbar are registered.
\subsection{Packages and structures}
No packages and structures are used in this module.
\section{Special cases, corner cases}
After reset of a top module (PMU\_raw for instance) you may experience that all the outputs route the event in the first position of vector\_i. This is intended behavior and happens due to the reset of the configuration registers (cfg\_i).\\
In the default integration with PMU\ there is a self-test capability that bypasses the crossbar with certain test patterns. This \textbf{self-test capability} is configured in the main configuration register of PMU\ Be sure to have this function disabled if you plan to use the crossbar.
\ No newline at end of file
all: spec
spec: main.tex 1-Section.tex 2-Section.tex 3-Section.tex 4-Section.tex 5-Section.tex 6-Section.tex 7-Section.tex 8-Section.tex
$(CC) main.tex
rm *.aux *.log *.blg *.bbl *.out
rm *.aux *.log *.blg *.bbl *.out *.pdf
% License:
% CC BY-NC-SA 3.0 (
\documentclass[paper=a4, fontsize=11pt]{scrartcl} % A4 paper and 11pt font size
\usepackage[T1]{fontenc} % Use 8-bit encoding that has 256 glyphs
\usepackage{fourier} % Use the Adobe Utopia font for the document - comment this line to return to the LaTeX default
\usepackage[english]{babel} % English language/hyphenation
\usepackage{amsmath,amsfonts,amsthm} % Math packages
\usepackage{lipsum} % Used for inserting dummy 'Lorem ipsum' text into the template
\usepackage{blindtext} %for enumarations
\usepackage[]{hyperref} %link collor
%talbe layout to the right
\usepackage{sectsty} % Allows customizing section commands
\allsectionsfont{\centering \normalfont\scshape} % Make all sections centered, the default font and small caps
\usepackage{fancyhdr} % Custom headers and footers
\pagestyle{fancyplain} % Makes all pages in the document conform to the custom headers and footers
\fancyhead{} % No page header - if you want one, create it in the same way as the footers below
\fancyfoot[L]{} % Empty left footer
\fancyfoot[C]{} % Empty center footer
\fancyfoot[R]{\thepage} % Page numbering for right footer
\renewcommand{\headrulewidth}{0pt} % Remove header underlines
\renewcommand{\footrulewidth}{0pt} % Remove footer underlines
\setlength{\headheight}{13.6pt} % Customize the height of the header
\numberwithin{equation}{section} % Number equations within sections (i.e. 1.1, 1.2, 2.1, 2.2 instead of 1, 2, 3, 4)
\numberwithin{figure}{section} % Number figures within sections (i.e. 1.1, 1.2, 2.1, 2.2 instead of 1, 2, 3, 4)
\numberwithin{table}{section} % Number tables within sections (i.e. 1.1, 1.2, 2.1, 2.2 instead of 1, 2, 3, 4)
%\setlength\parindent{0pt} % Removes all indentation from paragraphs - comment this line for an assignment with lots of text
\newcommand{\horrule}[1]{\rule{\linewidth}{#1}} % Create horizontal rule command with 1 argument of height
\normalfont \normalsize
\horrule{0.5pt} \\[0.4cm] % Thin top horizontal rule
\huge Crossbar specification version v1 \\ % The assignment title
\horrule{2pt} \\[0.5cm] % Thick bottom horizontal rule
\author{ Guillem Cabo Pitarch} % Your name
\date{\today} % Today's date or a custom date
\maketitle % Print the title
% Section 1
% Section 2
......@@ -2,7 +2,7 @@
// ProjectName: LEON3_kc705_pmu
// Function : Integrate PMU features under one module
// Description: Interface agnostic implementation of the PMU. Values of the
// PMU are registered in this module.
// PMU are not registered in this module.
// This module is responsible of configure the memory map, handle
// write / read syncronization with a higher level module that
......@@ -32,6 +32,8 @@
parameter integer REG_WIDTH = 32,
// Amount of counters
parameter integer N_COUNTERS = 9,
// Amount of SoC events going through the crossbar
parameter integer N_SOC_EV = 32,
// Configuration registers
parameter integer N_CONF_REGS = 1,
......@@ -46,6 +48,8 @@
localparam integer MCCU = 1, //Yes/No
//---- RDC - Request Duration Counters
localparam integer RDC = 1, //Yes/No
//---- Crossbar
localparam integer CROSSBAR = 1, //Yes/No
// *** Memory map related features
......@@ -143,11 +147,21 @@
// General parameters feature
//---- CROSSBAR registers and parameters.
// General parameters feature
//number of bits for each configuration field
//---- Total of registers used
localparam integer TOTAL_NREGS =
// Global Clock Signal
......@@ -162,7 +176,7 @@
// uploads the content with external values
input wire wrapper_we_i,
// Event signals
input wire [N_COUNTERS-1:0] events_i,
input wire [N_SOC_EV-1:0] events_i,
//interruption rises when one of the counters overflows
output wire intr_overflow_o,
//interruption rises when overall events quota is exceeded
......@@ -179,7 +193,7 @@
(* MARK_DEBUG = "TRUE" *) logic [REG_WIDTH-1:0] debug_regs_i [0:TOTAL_NREGS-1];
(* MARK_DEBUG = "TRUE" *) logic [REG_WIDTH-1:0] debug_regs_o [0:TOTAL_NREGS-1];
(* MARK_DEBUG = "TRUE" *) wire debug_wrapper_we_i;
(* MARK_DEBUG = "TRUE" *) wire [N_COUNTERS-1:0] debug_events_i;
(* MARK_DEBUG = "TRUE" *) wire [N_SOC_EV-1:0] debug_events_i;
(* MARK_DEBUG = "TRUE" *) wire debug_intr_overflow_o;
(* MARK_DEBUG = "TRUE" *) wire debug_intr_quota_o;
(* MARK_DEBUG = "TRUE" *) wire [MCCU_N_CORES-1:0] debug_intr_MCCU_o;
......@@ -304,6 +318,57 @@
assign regs_o[BASE_RDC_WATERMARK+1][4*MCCU_WEIGHTS_WIDTH-1:3*MCCU_WEIGHTS_WIDTH] = MCCU_watermark_int [3][1] ;
//------------- Crossbar
logic [CROSSBAR_CFG_BITS-1:0]crossbar_cfg [0:CROSSBAR_OUTPUTS-1];
logic [CROSSBAR_OUTPUTS-1:0] crossbar_o;
logic [N_CROSSBAR_CFG*REG_WIDTH-1:0] concat_cfg_crossbar;
//Concatenate all the registers to have easier access with missaligned registers
integer i;
always_comb begin
for (i=0; i < N_CROSSBAR_CFG; i++) begin
concat_cfg_crossbar[i*REG_WIDTH+:REG_WIDTH] = regs_i[BASE_CROSSBAR+i];
//map configuration fields to each mux
genvar q; // each Crossbar output
for (q=0;q<CROSSBAR_OUTPUTS;q++) begin
assign crossbar_cfg[q] = concat_cfg_crossbar [q*CROSSBAR_CFG_BITS+:CROSSBAR_CFG_BITS];
//Unpack crossbar inputs
logic unpacked_cbi_int[0:CROSSBAR_INPUTS-1];
for(q=0;q<CROSSBAR_INPUTS;q++) begin
assign unpacked_cbi_int[q] = events_i[q];
//Pack crossbar output
logic unpacked_cbo_int [0:CROSSBAR_OUTPUTS-1] ;
for(q=0;q<CROSSBAR_OUTPUTS;q++) begin
assign crossbar_o[q] = unpacked_cbo_int[q];
//Crossbar instance
crossbar # (
inst_cross (
//------------- Selftest configuration
logic [N_COUNTERS-1:0] events_int;
......@@ -316,7 +381,7 @@ localparam ONE_ON = 2'b11;
always_comb begin
case (selftest_mode)
NO_SELF_TEST : begin
events_int = events_i;
events_int = crossbar_o;
ALL_ACTIVE : begin
events_int = {N_COUNTERS{1'b1}};
......@@ -413,13 +478,13 @@ end
//be hardcoded to specific corssbars outputs
wire [MCCU_N_EVENTS-1:0] MCCU_events_int[0:MCCU_N_CORES-1];
assign MCCU_events_int [0] = {{events_int[5]},{events_int[12]}};
assign MCCU_events_int [0] = {{events_int[0]},{events_int[1]}};
assign MCCU_events_int [1] = {{events_int[6]},{events_int[9]}};
assign MCCU_events_int [1] = {{events_int[2]},{events_int[3]}};
assign MCCU_events_int [2] = {{events_int[7]},{events_int[10]}};
assign MCCU_events_int [2] = {{events_int[4]},{events_int[5]}};
assign MCCU_events_int [3] = {{events_int[8]},{events_int[11]}};
assign MCCU_events_int [3] = {{events_int[6]},{events_int[7]}};
//NON-PARAMETRIC This can be autogenenerated TODO
wire [MCCU_WEIGHTS_WIDTH-1:0] MCCU_events_weights_int [0:MCCU_N_CORES-1]
......@@ -41,6 +41,8 @@
localparam PMU_CFG = 1,
// Number of counters
localparam PMU_COUNTERS = 24
// Number of SoC events
localparam N_SOC_EV = 32
input wire rstn_i,
......@@ -73,7 +75,7 @@
// read data bus
output wire [HDATA_WIDTH-1:0] hrdata_o,
// -- PMU specific signales
input wire [PMU_COUNTERS-1:0] events_i,
input wire [N_SOC_EV-1:0] events_i,
//interruption rises when one of the counters overflows
output wire intr_overflow_o,
//interruption rises when overal events quota is exceeded
......@@ -100,7 +102,7 @@
(* MARK_DEBUG = "TRUE" *) wire debug_hreadyo_o ;
(* MARK_DEBUG = "TRUE" *) wire [1:0] debug_hresp_o ;
(* MARK_DEBUG = "TRUE" *) wire [HDATA_WIDTH-1:0] debug_hrdata_o ;
(* MARK_DEBUG = "TRUE" *) wire [PMU_COUNTERS-1:0] debug_events_i ;
(* MARK_DEBUG = "TRUE" *) wire [N_SOC_EV-1:0] debug_events_i ;
(* MARK_DEBUG = "TRUE" *) wire debug_intr_overflow_o;
(* MARK_DEBUG = "TRUE" *) wire debug_intr_quota_o;
(* MARK_DEBUG = "TRUE" *) wire [MCCU_N_CORES-1:0] debug_intr_MCCU_o;
......@@ -324,6 +326,7 @@ end
PMU_raw #(
)inst_pmu_raw (
......@@ -37,25 +37,25 @@ module crossbar #
// Global Reset Signal. This Signal is Active LOW
input wire rstn_i,
// Input vector
input logic vector_i [0:N_IN] ,
// Input vector
output logic vector_o [0:N_OUT],
input logic vector_i [0:N_IN-1] ,
// Output vector
output logic vector_o [0:N_OUT-1],
// Configuration
input wire [N_BITS_CFG:0] cfg_i [0:N_OUT]
input logic [N_BITS_CFG-1:0] cfg_i [0:N_OUT-1]
genvar x;
//Model muxes
logic mux_int[0:N_OUT];
logic mux_int[0:N_OUT-1];
for(x=0;x<=N_OUT;x++) begin : mux
for(x=0;x<N_OUT;x++) begin : mux
//Assign the input based on the configuration value
assign mux_int[x]=vector_i[(cfg_i [x])];
//Register output and assign muxes output
for(x=0;x<=N_OUT;x++) begin : reg_out
for(x=0;x<N_OUT;x++) begin : reg_out
always_ff @(posedge clk_i, negedge rstn_i) begin
if (!rstn_i) begin
vector_o[x] <= 0;
......@@ -76,5 +76,5 @@ module crossbar #
`default_nettype wire //allow compatibility with legacy code and xilinx ip
......@@ -32,9 +32,9 @@ module tb_crossbar();
reg tb_clk_i ;
reg tb_rstn_i ;
reg tb_vector_i [0:TB_SOC_EVENTS];
wire tb_vector_o [0:TB_PMU_EVENTS];
reg [N_BITS_CFG:0] tb_cfg_i [0:TB_PMU_EVENTS];
reg tb_vector_i [0:TB_SOC_EVENTS-1];
wire tb_vector_o [0:TB_PMU_EVENTS-1];
reg [N_BITS_CFG-1:0] tb_cfg_i [0:TB_PMU_EVENTS-1];
//store name of test for easier debug of waveform
reg[64*8:0] tb_test_name;
reg tb_fail = 0;
......@@ -133,8 +133,8 @@ task automatic init_sim;
// try all the input and output combinations
integer i; //inputs iterator
integer j; // output iterator
for(i=0;i<=TB_SOC_EVENTS;i++) begin
for(j=0;j<=TB_PMU_EVENTS;j++) begin
for(i=0;i<TB_SOC_EVENTS;i++) begin
for(j=0;j<TB_PMU_EVENTS;j++) begin
test_fail = rval + test_fail;
......@@ -8,10 +8,22 @@ add wave -noupdate {/tb_crossbar/tb_vector_o[1]}
add wave -noupdate {/tb_crossbar/tb_cfg_i[1]}
add wave -noupdate /tb_crossbar/tb_vector_i
add wave -noupdate /tb_crossbar/tb_vector_o
add wave -noupdate {/tb_crossbar/tb_vector_i[5]}
add wave -noupdate {/tb_crossbar/tb_cfg_i[6]}
add wave -noupdate /tb_crossbar/tb_cfg_i
add wave -noupdate /tb_crossbar/tb_fail
add wave -noupdate /tb_crossbar/dut_crossbar/N_OUT
add wave -noupdate /tb_crossbar/dut_crossbar/N_IN
add wave -noupdate /tb_crossbar/dut_crossbar/N_BITS_CFG
add wave -noupdate /tb_crossbar/dut_crossbar/clk_i
add wave -noupdate /tb_crossbar/dut_crossbar/rstn_i
add wave -noupdate /tb_crossbar/dut_crossbar/vector_i
add wave -noupdate /tb_crossbar/dut_crossbar/vector_o
add wave -noupdate /tb_crossbar/dut_crossbar/cfg_i
add wave -noupdate /tb_crossbar/dut_crossbar/mux_int
add wave -noupdate {/tb_crossbar/dut_crossbar/mux[6]/x}
TreeUpdate [SetDefaultTree]
WaveRestoreCursors {{Cursor 1} {17884 ps} 0}
WaveRestoreCursors {{Cursor 1} {1043 ps} 0}
quietly wave cursor active 1
configure wave -namecolwidth 334
configure wave -valuecolwidth 169
......@@ -27,4 +39,4 @@ configure wave -griddelta 40
configure wave -timeline 0
configure wave -timelineunits ns
WaveRestoreZoom {7575 ps} {51540 ps}
WaveRestoreZoom {0 ps} {12600 ps}
......@@ -3,12 +3,12 @@ TOP=../../..
vlib PMU_raw
vmap work $PWD/PMU_raw
vlog +acc=rn +incdir+$TOP/hdl/ $TOP/hdl/ $TOP/submodules/MCCU/hdl/* $TOP/submodules/RDC/hdl/*.sv $TOP/submodules/overflow/*.sv $TOP/submodules/quota/*.sv $TOP/submodules/counters/*.sv ./colors.vh
vlog +acc=rn +incdir+$TOP/hdl/ $TOP/hdl/ $TOP/submodules/MCCU/hdl/* $TOP/submodules/crossbar/hdl/*.sv $TOP/submodules/RDC/hdl/*.sv $TOP/submodules/overflow/*.sv $TOP/submodules/quota/*.sv $TOP/submodules/counters/*.sv ./colors.vh
vmake PMU_raw/ > Makefile
if [ -z "$1" ]
vsim work.tb_PMU_raw -do "view wave -new" -do "do" -do "run 40000"
vsim work.tb_PMU_raw -do "view wave -new" -do "do" -do "run -all"
vsim work.tb_PMU_raw $1 -do "do"
......@@ -28,16 +28,17 @@ module tb_PMU_raw();
//***DUT parameters***
parameter TB_DATA_WIDTH = 32;
parameter TB_N_COUNTERS = 24;
parameter TB_N_SOC_EV = 32;
parameter TB_N_CFG = 1;
parameter TB_N_CORES= 4;
//WARNIGN: if N_counters or cores change this value needs to change
parameter TB_TOTAL_NREGS= 43;
parameter TB_TOTAL_NREGS= 47;
reg tb_clk_i ;
reg tb_rstn_i ;
reg [TB_N_COUNTERS-1:0] tb_events_i;
reg [TB_DATA_WIDTH-1:0] tb_regs_i [0:TB_TOTAL_NREGS-1];
reg [TB_N_SOC_EV-1:0] tb_events_i;
logic [TB_DATA_WIDTH-1:0] tb_regs_i [0:TB_TOTAL_NREGS-1];
wire [TB_DATA_WIDTH-1:0] tb_regs_o [0:TB_TOTAL_NREGS-1];
reg tb_wrapper_we_i;
wire tb_intr_overflow_o;
......@@ -52,6 +53,7 @@ reg tb_fail = 0;
PMU_raw #(
)dut_PMU_raw (
......@@ -139,6 +141,84 @@ task automatic test_MCCU_1;
//***task automatic route_ito***
// This taks takes two parameters. First parameter
// is the input event. The second parameter is the
// selected output. The function enables the input
// sets the configuration register and checks if
// the signal reaches the output.
//NOT-PARAMETRIC: fails if input parameters change
//All functions enabled (Overflo,Quota,MCCU,RDC,Crossbar), RDC and MCCU parameters equal
localparam CROSSBAR_CFG_BITS= $clog2(TB_N_SOC_EV);
localparam BASE_CROSSBAR = 43;
localparam N_CROSSBAR_CFG = 4;
logic [TB_N_SOC_EV-1:0] unpack_crossbar_cfg [0:TB_N_COUNTERS];
logic [N_CROSSBAR_CFG*TB_DATA_WIDTH-1:0] concat_cfg_crossbar;
//Map unpacked configuration registers to concatenation
integer i;
always_comb begin
for (i=0; i < TB_N_COUNTERS; i++) begin
concat_cfg_crossbar[CROSSBAR_CFG_BITS*i+:CROSSBAR_CFG_BITS] = unpack_crossbar_cfg[i];
//Map concatenation to configuration registers
integer j;
always_comb begin
for (j=0; j < N_CROSSBAR_CFG; j++) begin
// Now we can drive unpack_crossbar_cfg with route_ito and get the values in tb_regs_i without
//any conversion
task automatic route_ito (input int in, out, output int tb_fail);
//set all other signals to 0
tb_events_i <='{default:0};
//enable signal that we want to route