mirror of
https://github.com/openhwgroup/cve2.git
synced 2025-04-19 11:44:58 -04:00
Use vendored-in primitives from OpenTitan
Instead of using copies of primitives from OpenTitan, vendor the files in directly from OpenTitan, and use them. Benefits: - Less potential for diverging code between OpenTitan and Ibex, causing problems when importing Ibex into OT. - Use of the abstract primitives instead of the generic ones. The abstract primitives are replaced during synthesis time with target-dependent implementations. For simulation, nothing changes. For synthesis for a given target technology (e.g. a specific ASIC or FPGA technology), the primitives system can be instructed to choose optimized versions (if available). This is most relevant for the icache, which hard-coded the generic SRAM primitive before. This primitive is always implemented as registers. By using the abstract primitive (prim_ram_1p) instead, the RAMs can be replaced with memory-compiler-generated ones if necessary. There are no real draw-backs, but a couple points to be aware of: - Our ram_1p and ram_2p implementations are kept as wrapper around the primitives, since their interface deviates slightly from the one in prim_ram*. This also includes a rather unfortunate naming confusion around rvalid, which means "read data valid" in the OpenTitan advanced RAM primitives (prim_ram_1p_adv for example), but means "ack" in PULP-derived IP and in our bus implementation. - The core_ibex UVM DV doesn't use FuseSoC to generate its file list, but uses a hard-coded list in `ibex_files.f` instead. Since the dynamic primitives system requires the use of FuseSoC we need to provide a stop-gap until this file is removed. Issue #893 tracks progress on that. - Dynamic primitives depend no a not-yet-merged feature of FuseSoC (https://github.com/olofk/fusesoc/pull/391). We depend on the same functionality in OpenTitan and have instructed users to use a patched branch of FuseSoC for a long time through `python-requirements.txt`, so no action is needed for users which are either successfully interacting with the OpenTitan source code, or have followed our instructions. All other users will see a reasonably descriptive error message during a FuseSoC run. - This commit is massive, but there are no good ways to split it into bisectable, yet small, chunks. I'm sorry. Reviewers can safely ignore all code in `vendor/lowrisc_ip`, it's an import from OpenTitan. - The check_tool_requirements tooling isn't easily vendor-able from OpenTitan at the moment. I've filed https://github.com/lowRISC/opentitan/issues/2309 to get that sorted. - The LFSR primitive doesn't have a own core file, forcing us to include the catch-all `lowrisc:prim:all` core. I've filed https://github.com/lowRISC/opentitan/issues/2310 to get that sorted.
This commit is contained in:
parent
3f4e706062
commit
8b42024cd5
190 changed files with 11808 additions and 252 deletions
|
@ -2,7 +2,7 @@ CAPI=2:
|
|||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
name: "lowrisc:ibex:check_tool_requirements:0.1"
|
||||
name: "lowrisc:tool:check_tool_requirements:0.1"
|
||||
description: "Check tool requirements"
|
||||
|
||||
filesets:
|
||||
|
|
|
@ -13,7 +13,9 @@ int main(int argc, char **argv) {
|
|||
simctrl.SetTop(&top, &top.IO_CLK, &top.IO_RST_N,
|
||||
VerilatorSimCtrlFlags::ResetPolarityNegative);
|
||||
|
||||
memutil.RegisterMemoryArea("ram", "TOP.ibex_riscv_compliance.u_ram.u_ram");
|
||||
memutil.RegisterMemoryArea(
|
||||
"ram",
|
||||
"TOP.ibex_riscv_compliance.u_ram.u_ram.gen_generic.u_impl_generic");
|
||||
simctrl.RegisterExtension(&memutil);
|
||||
|
||||
return simctrl.Exec(argc, argv);
|
||||
|
|
35
dv/uvm/core_ibex/common/prim/prim_clock_gating.sv
Normal file
35
dv/uvm/core_ibex/common/prim/prim_clock_gating.sv
Normal file
|
@ -0,0 +1,35 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Abstract primitives wrapper.
|
||||
//
|
||||
// This file is a stop-gap until the DV file list is generated by FuseSoC.
|
||||
// Its contents are taken from the file which would be generated by FuseSoC.
|
||||
// https://github.com/lowRISC/ibex/issues/893
|
||||
|
||||
`ifndef PRIM_DEFAULT_IMPL
|
||||
`define PRIM_DEFAULT_IMPL prim_pkg::ImplGeneric
|
||||
`endif
|
||||
|
||||
module prim_clock_gating (
|
||||
input clk_i,
|
||||
input en_i,
|
||||
input test_en_i,
|
||||
output logic clk_o
|
||||
);
|
||||
parameter prim_pkg::impl_e Impl = `PRIM_DEFAULT_IMPL;
|
||||
|
||||
if (Impl == prim_pkg::ImplGeneric) begin : gen_generic
|
||||
prim_generic_clock_gating u_impl_generic (
|
||||
.*
|
||||
);
|
||||
end else if (Impl == prim_pkg::ImplXilinx) begin : gen_xilinx
|
||||
prim_xilinx_clock_gating u_impl_xilinx (
|
||||
.*
|
||||
);
|
||||
end else begin : gen_failure
|
||||
// TODO: Find code that works across tools and causes a compile failure
|
||||
end
|
||||
|
||||
endmodule
|
18
dv/uvm/core_ibex/common/prim/prim_pkg.sv
Normal file
18
dv/uvm/core_ibex/common/prim/prim_pkg.sv
Normal file
|
@ -0,0 +1,18 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// Constants for use in primitives
|
||||
//
|
||||
// This file is a stop-gap until the DV file list is generated by FuseSoC.
|
||||
// Its contents are taken from the file which would be generated by FuseSoC.
|
||||
// https://github.com/lowRISC/ibex/issues/893
|
||||
|
||||
package prim_pkg;
|
||||
|
||||
// Implementation target specialization
|
||||
typedef enum integer {
|
||||
ImplGeneric,
|
||||
ImplXilinx
|
||||
} impl_e;
|
||||
endpackage : prim_pkg
|
40
dv/uvm/core_ibex/common/prim/prim_ram_1p.sv
Normal file
40
dv/uvm/core_ibex/common/prim/prim_ram_1p.sv
Normal file
|
@ -0,0 +1,40 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Abstract primitives wrapper.
|
||||
//
|
||||
// This file is a stop-gap until the DV file list is generated by FuseSoC.
|
||||
// Its contents are taken from the file which would be generated by FuseSoC.
|
||||
// https://github.com/lowRISC/ibex/issues/893
|
||||
|
||||
`ifndef PRIM_DEFAULT_IMPL
|
||||
`define PRIM_DEFAULT_IMPL prim_pkg::ImplGeneric
|
||||
`endif
|
||||
|
||||
module prim_ram_1p #(
|
||||
parameter int Width = 32, // bit
|
||||
parameter int Depth = 128,
|
||||
parameter int DataBitsPerMask = 1, // Number of data bits per bit of write mask
|
||||
localparam int Aw = $clog2(Depth) // derived parameter
|
||||
) (
|
||||
input logic clk_i,
|
||||
|
||||
input logic req_i,
|
||||
input logic write_i,
|
||||
input logic [Aw-1:0] addr_i,
|
||||
input logic [Width-1:0] wdata_i,
|
||||
input logic [Width-1:0] wmask_i,
|
||||
output logic [Width-1:0] rdata_o // Read data. Data is returned one cycle after req_i is high.
|
||||
);
|
||||
parameter prim_pkg::impl_e Impl = `PRIM_DEFAULT_IMPL;
|
||||
|
||||
if (Impl == prim_pkg::ImplGeneric) begin : gen_generic
|
||||
prim_generic_ram_1p u_impl_generic (
|
||||
.*
|
||||
);
|
||||
end else begin : gen_failure
|
||||
// TODO: Find code that works across tools and causes a compile failure
|
||||
end
|
||||
|
||||
endmodule
|
|
@ -7,19 +7,27 @@
|
|||
+define+BOOT_ADDR=2147483648 // 32'h8000_0000
|
||||
+define+TRACE_EXECUTION
|
||||
+define+RVFI
|
||||
+incdir+${PRJ_DIR}/ibex/shared/rtl
|
||||
|
||||
${PRJ_DIR}/ibex/shared/rtl/prim_clock_gating.sv
|
||||
// Shared lowRISC code
|
||||
+incdir+${PRJ_DIR}/ibex/vendor/lowrisc_ip/prim/rtl
|
||||
${PRJ_DIR}/ibex/vendor/lowrisc_ip/prim/rtl/prim_assert.sv
|
||||
${PRJ_DIR}/ibex/vendor/lowrisc_ip/prim/rtl/prim_lfsr.sv
|
||||
${PRJ_DIR}/ibex/vendor/lowrisc_ip/prim/rtl/prim_secded_28_22_enc.sv
|
||||
${PRJ_DIR}/ibex/vendor/lowrisc_ip/prim/rtl/prim_secded_28_22_dec.sv
|
||||
${PRJ_DIR}/ibex/vendor/lowrisc_ip/prim/rtl/prim_secded_72_64_enc.sv
|
||||
${PRJ_DIR}/ibex/vendor/lowrisc_ip/prim/rtl/prim_secded_72_64_dec.sv
|
||||
|
||||
// Until this list is generated by FuseSoC, we have to use manually generated
|
||||
// wrappers around the prim_* modules to instantiate the prim_generic_* ones,
|
||||
// see https://github.com/lowRISC/ibex/issues/893.
|
||||
${PRJ_DIR}/ibex/dv/uvm/core_ibex/common/prim/prim_pkg.sv
|
||||
${PRJ_DIR}/ibex/vendor/lowrisc_ip/prim_generic/rtl/prim_generic_ram_1p.sv
|
||||
${PRJ_DIR}/ibex/dv/uvm/core_ibex/common/prim/prim_ram_1p.sv
|
||||
${PRJ_DIR}/ibex/vendor/lowrisc_ip/prim_generic/rtl/prim_generic_clock_gating.sv
|
||||
${PRJ_DIR}/ibex/dv/uvm/core_ibex/common/prim/prim_clock_gating.sv
|
||||
|
||||
// ibex CORE RTL files
|
||||
+incdir+${PRJ_DIR}/ibex/rtl
|
||||
${PRJ_DIR}/ibex/shared/rtl/prim_assert.sv
|
||||
${PRJ_DIR}/ibex/shared/rtl/prim_generic_ram_1p.sv
|
||||
${PRJ_DIR}/ibex/shared/rtl/prim_lfsr.sv
|
||||
${PRJ_DIR}/ibex/shared/rtl/prim_secded_28_22_enc.sv
|
||||
${PRJ_DIR}/ibex/shared/rtl/prim_secded_28_22_dec.sv
|
||||
${PRJ_DIR}/ibex/shared/rtl/prim_secded_72_64_enc.sv
|
||||
${PRJ_DIR}/ibex/shared/rtl/prim_secded_72_64_dec.sv
|
||||
${PRJ_DIR}/ibex/rtl/ibex_pkg.sv
|
||||
${PRJ_DIR}/ibex/rtl/ibex_tracer_pkg.sv
|
||||
${PRJ_DIR}/ibex/rtl/ibex_tracer.sv
|
||||
|
|
|
@ -17,7 +17,8 @@ int main(int argc, char **argv) {
|
|||
simctrl.SetTop(&top, &top.IO_CLK, &top.IO_RST_N,
|
||||
VerilatorSimCtrlFlags::ResetPolarityNegative);
|
||||
|
||||
memutil.RegisterMemoryArea("ram", "TOP.ibex_simple_system.u_ram");
|
||||
memutil.RegisterMemoryArea(
|
||||
"ram", "TOP.ibex_simple_system.u_ram.u_ram.gen_generic.u_impl_generic");
|
||||
simctrl.RegisterExtension(&memutil);
|
||||
|
||||
std::cout << "Simulation of Ibex" << std::endl
|
||||
|
|
|
@ -9,7 +9,9 @@ filesets:
|
|||
files_rtl:
|
||||
depend:
|
||||
- lowrisc:prim:assert
|
||||
- lowrisc:prim:lfsr
|
||||
# TODO: Only lfsr is needed. Replace with a more specific dependency
|
||||
# once available.
|
||||
- lowrisc:prim:all
|
||||
- lowrisc:ibex:ibex_pkg
|
||||
- lowrisc:ibex:ibex_icache
|
||||
files:
|
||||
|
@ -48,7 +50,7 @@ filesets:
|
|||
|
||||
files_check_tool_requirements:
|
||||
depend:
|
||||
- lowrisc:ibex:check_tool_requirements
|
||||
- lowrisc:tool:check_tool_requirements
|
||||
|
||||
parameters:
|
||||
RVFI:
|
||||
|
|
|
@ -152,3 +152,7 @@ lint_off -rule UNUSED -file "*/rtl/ibex_decoder.sv" -match "*instr_alu*"
|
|||
// ibex_core.cs_registers_i.mie_q
|
||||
// Issue lowrisc/ibex#212
|
||||
lint_off -rule UNOPTFLAT -file "*/rtl/ibex_cs_registers.sv" -match "*ibex_core.cs_registers_i.mie_q*"
|
||||
|
||||
// Temporary waivers until OpenTitan primitives are lint-clean
|
||||
// https://github.com/lowRISC/opentitan/issues/2313
|
||||
lint_off -file "*/lowrisc_prim_*/rtl/*.sv"
|
||||
|
|
|
@ -9,3 +9,4 @@ git+https://github.com/lowRISC/edalize.git@ot
|
|||
git+https://github.com/lowRISC/fusesoc.git@ot
|
||||
|
||||
pyyaml
|
||||
mako
|
||||
|
|
|
@ -300,33 +300,29 @@ module ibex_icache #(
|
|||
|
||||
for (genvar way = 0; way < NumWays; way++) begin : gen_rams
|
||||
// Tag RAM instantiation
|
||||
prim_generic_ram_1p #(
|
||||
prim_ram_1p #(
|
||||
.Width (TAG_SIZE_ECC),
|
||||
.Depth (NUM_LINES)
|
||||
) tag_bank (
|
||||
.clk_i (clk_i),
|
||||
.rst_ni (rst_ni),
|
||||
.req_i (tag_req_ic0 & tag_banks_ic0[way]),
|
||||
.write_i (tag_write_ic0),
|
||||
.wmask_i ({TAG_SIZE_ECC{1'b1}}),
|
||||
.addr_i (tag_index_ic0),
|
||||
.wdata_i (tag_wdata_ic0),
|
||||
.rvalid_o (),
|
||||
.rdata_o (tag_rdata_ic1[way])
|
||||
);
|
||||
// Data RAM instantiation
|
||||
prim_generic_ram_1p #(
|
||||
prim_ram_1p #(
|
||||
.Width (LINE_SIZE_ECC),
|
||||
.Depth (NUM_LINES)
|
||||
) data_bank (
|
||||
.clk_i (clk_i),
|
||||
.rst_ni (rst_ni),
|
||||
.req_i (data_req_ic0 & data_banks_ic0[way]),
|
||||
.write_i (data_write_ic0),
|
||||
.wmask_i ({LINE_SIZE_ECC{1'b1}}),
|
||||
.addr_i (data_index_ic0),
|
||||
.wdata_i (data_wdata_ic0),
|
||||
.rvalid_o (),
|
||||
.rdata_o (data_rdata_ic1[way])
|
||||
);
|
||||
end
|
||||
|
|
|
@ -6,8 +6,9 @@ name: "lowrisc:ibex:fpga_xilinx_shared"
|
|||
description: "Collection of useful RTL for Xilinx based examples"
|
||||
filesets:
|
||||
files_sv:
|
||||
depend:
|
||||
- lowrisc:prim:clock_gating
|
||||
files:
|
||||
- rtl/fpga/xilinx/prim_clock_gating.sv
|
||||
- rtl/fpga/xilinx/clkgen_xil7series.sv
|
||||
- rtl/ram_1p.sv
|
||||
file_type: systemVerilogSource
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// Dummy clock gating module compatible with latch-based register file
|
||||
|
||||
module prim_clock_gating (
|
||||
input clk_i,
|
||||
input en_i,
|
||||
input test_en_i,
|
||||
output logic clk_o
|
||||
);
|
||||
|
||||
logic clk_en;
|
||||
|
||||
always_latch begin
|
||||
if (clk_i == 1'b0) begin
|
||||
clk_en <= en_i | test_en_i;
|
||||
end
|
||||
end
|
||||
|
||||
assign clk_o = clk_i & clk_en;
|
||||
|
||||
endmodule
|
|
@ -1,109 +0,0 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// Synchronous single-port SRAM model
|
||||
|
||||
`include "prim_assert.sv"
|
||||
|
||||
module prim_generic_ram_1p #(
|
||||
parameter int Width = 32, // bit
|
||||
parameter int Depth = 128,
|
||||
parameter int DataBitsPerMask = 1, // Number of data bits per bit of write mask
|
||||
localparam int Aw = $clog2(Depth) // derived parameter
|
||||
) (
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
|
||||
input logic req_i,
|
||||
input logic write_i,
|
||||
input logic [Aw-1:0] addr_i,
|
||||
input logic [Width-1:0] wdata_i,
|
||||
input logic [Width-1:0] wmask_i,
|
||||
output logic rvalid_o,
|
||||
output logic [Width-1:0] rdata_o
|
||||
);
|
||||
|
||||
// Width of internal write mask. Note wmask_i input into the module is always assumed
|
||||
// to be the full bit mask
|
||||
localparam int MaskWidth = Width / DataBitsPerMask;
|
||||
|
||||
logic [Width-1:0] mem [Depth];
|
||||
logic [MaskWidth-1:0] wmask;
|
||||
|
||||
always_comb begin
|
||||
for (int i=0; i < MaskWidth; i = i + 1) begin : create_wmask
|
||||
wmask[i] = &wmask_i[i*DataBitsPerMask +: DataBitsPerMask];
|
||||
end
|
||||
end
|
||||
|
||||
// using always instead of always_ff to avoid 'ICPD - illegal combination of drivers' error
|
||||
// thrown when using $readmemh system task to backdoor load an image
|
||||
always @(posedge clk_i) begin
|
||||
if (req_i) begin
|
||||
if (write_i) begin
|
||||
for (int i=0; i < MaskWidth; i = i + 1) begin
|
||||
if (wmask[i]) begin
|
||||
mem[addr_i][i*DataBitsPerMask +: DataBitsPerMask] <=
|
||||
wdata_i[i*DataBitsPerMask +: DataBitsPerMask];
|
||||
end
|
||||
end
|
||||
end else begin
|
||||
rdata_o <= mem[addr_i];
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge clk_i, negedge rst_ni) begin
|
||||
if (!rst_ni) begin
|
||||
rvalid_o <= '0;
|
||||
end else begin
|
||||
rvalid_o <= req_i & ~write_i;
|
||||
end
|
||||
end
|
||||
|
||||
`ifdef VERILATOR
|
||||
// Task for loading 'mem' with SystemVerilog system task $readmemh()
|
||||
export "DPI-C" task simutil_verilator_memload;
|
||||
|
||||
task simutil_verilator_memload;
|
||||
input string file;
|
||||
$readmemh(file, mem);
|
||||
endtask
|
||||
|
||||
// Width must be a multiple of 32bit for this function to work
|
||||
// Note that the DPI export and function definition must both be in the same generate
|
||||
// context to get the correct name.
|
||||
if ((Width % 32) == 0) begin : gen_set_mem
|
||||
// Function for setting a specific element in |mem|
|
||||
// Returns 1 (true) for success, 0 (false) for errors.
|
||||
export "DPI-C" function simutil_verilator_set_mem;
|
||||
|
||||
function int simutil_verilator_set_mem(input int index,
|
||||
input bit [Width-1:0] val);
|
||||
if (index >= Depth) begin
|
||||
return 0;
|
||||
end
|
||||
|
||||
mem[index] = val;
|
||||
return 1;
|
||||
endfunction
|
||||
end else begin : gen_other
|
||||
// Function doesn't work unless Width % 32 so just return 0
|
||||
export "DPI-C" function simutil_verilator_set_mem;
|
||||
|
||||
function int simutil_verilator_set_mem(input int index,
|
||||
input bit [Width-1:0] val);
|
||||
return 0;
|
||||
endfunction
|
||||
end
|
||||
`endif
|
||||
|
||||
`ifdef SRAM_INIT_FILE
|
||||
localparam MEM_FILE = `PRIM_STRINGIFY(`SRAM_INIT_FILE);
|
||||
initial begin
|
||||
$display("Initializing SRAM from %s", MEM_FILE);
|
||||
$readmemh(MEM_FILE, mem);
|
||||
end
|
||||
`endif
|
||||
endmodule
|
|
@ -39,32 +39,28 @@ module ram_1p #(
|
|||
end
|
||||
end
|
||||
|
||||
// |rvalid| in the bus module is an "ack", while prim_ram_1p associates the
|
||||
// meaning "returned read data is valid" with this signal.
|
||||
// Convert the RAM meaning to the meaning assumed by the bus module.
|
||||
logic read_valid, we_q;
|
||||
// |rvalid| in the bus module is an "ack" (which is a different meaning than
|
||||
// in the prim_ram_*_adv modules). prim_ram_1p is guaranteed to return data
|
||||
// in the next cycle.
|
||||
always_ff @(posedge clk_i, negedge rst_ni) begin
|
||||
if (!rst_ni) begin
|
||||
we_q <= 1'b0;
|
||||
rvalid_o <= 1'b0;
|
||||
end else begin
|
||||
we_q <= we_i;
|
||||
rvalid_o <= req_i;
|
||||
end
|
||||
end
|
||||
assign rvalid_o = read_valid | we_q;
|
||||
|
||||
prim_generic_ram_1p #(
|
||||
prim_ram_1p #(
|
||||
.Width(32),
|
||||
.DataBitsPerMask(8),
|
||||
.Depth(Depth)
|
||||
) u_ram (
|
||||
.clk_i (clk_i),
|
||||
.rst_ni (rst_ni),
|
||||
.req_i (req_i),
|
||||
.write_i (we_i),
|
||||
.wmask_i (wmask),
|
||||
.addr_i (addr_idx),
|
||||
.wdata_i (wdata_i),
|
||||
.rvalid_o (read_valid),
|
||||
.rdata_o (rdata_o)
|
||||
);
|
||||
endmodule
|
||||
|
|
|
@ -4,13 +4,6 @@
|
|||
|
||||
/**
|
||||
* Dual-port RAM with 1 cycle read/write delay, 32 bit words.
|
||||
*
|
||||
* The two ports are in Read-First Mode: when reading from and writing to the same address
|
||||
* simultaneously, the old content is returned, before the new content is written. New content
|
||||
* is made available to both ports with one cycle delay.
|
||||
*
|
||||
* Simultaneous write operations by both ports to the same address are to be avoided: The data
|
||||
* written to memory is not determined.
|
||||
*/
|
||||
|
||||
`include "prim_assert.sv"
|
||||
|
@ -40,8 +33,6 @@ module ram_2p #(
|
|||
|
||||
localparam int Aw = $clog2(Depth);
|
||||
|
||||
logic [31:0] mem [Depth];
|
||||
|
||||
logic [Aw-1:0] a_addr_idx;
|
||||
assign a_addr_idx = a_addr_i[Aw-1+2:2];
|
||||
logic [31-Aw:0] unused_a_addr_parts;
|
||||
|
@ -52,77 +43,45 @@ module ram_2p #(
|
|||
logic [31-Aw:0] unused_b_addr_parts;
|
||||
assign unused_b_addr_parts = {b_addr_i[31:Aw+2], b_addr_i[1:0]};
|
||||
|
||||
always @(posedge clk_i) begin
|
||||
if (a_req_i) begin
|
||||
if (a_we_i) begin
|
||||
for (int i = 0; i < 4; i = i + 1) begin
|
||||
if (a_be_i[i] == 1'b1) begin
|
||||
mem[a_addr_idx][i*8 +: 8] <= a_wdata_i[i*8 +: 8];
|
||||
end
|
||||
end
|
||||
end
|
||||
a_rdata_o <= mem[a_addr_idx];
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk_i) begin
|
||||
if (b_req_i) begin
|
||||
if (b_we_i) begin
|
||||
for (int i = 0; i < 4; i = i + 1) begin
|
||||
if (b_be_i[i] == 1'b1) begin
|
||||
mem[b_addr_idx][i*8 +: 8] <= b_wdata_i[i*8 +: 8];
|
||||
end
|
||||
end
|
||||
end
|
||||
b_rdata_o <= mem[b_addr_idx];
|
||||
// Convert byte mask to SRAM bit mask.
|
||||
logic [31:0] a_wmask;
|
||||
logic [31:0] b_wmask;
|
||||
always_comb begin
|
||||
for (int i = 0 ; i < 4 ; i++) begin
|
||||
// mask for read data
|
||||
a_wmask[8*i+:8] = {8{a_be_i[i]}};
|
||||
b_wmask[8*i+:8] = {8{b_be_i[i]}};
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if (!rst_ni) begin
|
||||
a_rvalid_o <= '0;
|
||||
end else begin
|
||||
a_rvalid_o <= a_req_i;
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if (!rst_ni) begin
|
||||
b_rvalid_o <= '0;
|
||||
end else begin
|
||||
a_rvalid_o <= a_req_i;
|
||||
b_rvalid_o <= b_req_i;
|
||||
end
|
||||
end
|
||||
|
||||
`ifdef VERILATOR
|
||||
// Task for loading 'mem' with SystemVerilog system task $readmemh()
|
||||
export "DPI-C" task simutil_verilator_memload;
|
||||
// Function for setting a specific 32 bit element in |mem|
|
||||
// Returns 1 (true) for success, 0 (false) for errors.
|
||||
export "DPI-C" function simutil_verilator_set_mem;
|
||||
prim_ram_2p #(
|
||||
.Width(32),
|
||||
.Depth(Depth)
|
||||
) u_ram (
|
||||
.clk_a_i (clk_i),
|
||||
.clk_b_i (clk_i),
|
||||
.a_req_i (a_req_i),
|
||||
.a_write_i (a_we_i),
|
||||
.a_addr_i (a_addr_idx),
|
||||
.a_wdata_i (a_wdata_i),
|
||||
.a_wmask_i (a_wmask),
|
||||
.a_rdata_o (a_rdata_o),
|
||||
.b_req_i (b_req_i),
|
||||
.b_write_i (b_we_i),
|
||||
.b_wmask_i (b_wmask),
|
||||
.b_addr_i (b_addr_idx),
|
||||
.b_wdata_i (b_wdata_i),
|
||||
.b_rdata_o (b_rdata_o)
|
||||
);
|
||||
|
||||
task simutil_verilator_memload;
|
||||
input string file;
|
||||
$readmemh(file, mem);
|
||||
endtask
|
||||
|
||||
// TODO: Allow 'val' to have other widths than 32 bit
|
||||
function int simutil_verilator_set_mem(input int index,
|
||||
input logic[31:0] val);
|
||||
if (index >= Depth) begin
|
||||
return 0;
|
||||
end
|
||||
|
||||
mem[index] = val;
|
||||
return 1;
|
||||
endfunction
|
||||
`endif
|
||||
|
||||
`ifdef SRAM_INIT_FILE
|
||||
localparam MEM_FILE = `PRIM_STRINGIFY(`SRAM_INIT_FILE);
|
||||
initial begin
|
||||
$display("Initializing SRAM from %s", MEM_FILE);
|
||||
$readmemh(MEM_FILE, mem);
|
||||
end
|
||||
`endif
|
||||
endmodule
|
||||
|
|
|
@ -8,9 +8,10 @@ filesets:
|
|||
files_sim_sv:
|
||||
depend:
|
||||
- lowrisc:prim:assert
|
||||
- lowrisc:prim_generic:ram_1p
|
||||
- lowrisc:prim:ram_1p
|
||||
- lowrisc:prim:ram_2p
|
||||
- lowrisc:prim:clock_gating
|
||||
files:
|
||||
- ./rtl/prim_clock_gating.sv
|
||||
- ./rtl/ram_1p.sv
|
||||
- ./rtl/ram_2p.sv
|
||||
- ./rtl/bus.sv
|
||||
|
|
|
@ -15,7 +15,7 @@ log.basicConfig(level=log.INFO, format="%(levelname)s: %(message)s")
|
|||
|
||||
|
||||
def get_tool_requirements_path():
|
||||
'''Return the path to tool_requirements.py, at the top of the Ibex repo'''
|
||||
'''Return the path to tool_requirements.py, at the top of the repo'''
|
||||
# top_src_dir is the top of the repository
|
||||
top_src_dir = os.path.normpath(os.path.join(os.path.dirname(__file__),
|
||||
'..'))
|
||||
|
|
6
vendor/lowrisc_ip.vendor.hjson
vendored
6
vendor/lowrisc_ip.vendor.hjson
vendored
|
@ -17,6 +17,12 @@
|
|||
{from: "hw/dv/sv/dv_utils", to: "dv_utils"},
|
||||
{from: "hw/dv/verilator", to: "dv_verilator"},
|
||||
|
||||
{from: "hw/ip/prim", to: "prim"},
|
||||
{from: "hw/ip/prim_generic", to: "prim_generic"},
|
||||
{from: "hw/ip/prim_xilinx", to: "prim_xilinx"},
|
||||
|
||||
{from: "hw/lint", to: "lint"},
|
||||
|
||||
{from: "util/dvsim", to: "dvsim"},
|
||||
{from: "util/uvmdvgen", to: "uvmdvgen"},
|
||||
]
|
||||
|
|
3
vendor/lowrisc_ip/lint/.gitignore
vendored
Normal file
3
vendor/lowrisc_ip/lint/.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
build
|
||||
reports
|
||||
ascentlint.policy
|
133
vendor/lowrisc_ip/lint/Makefile
vendored
Normal file
133
vendor/lowrisc_ip/lint/Makefile
vendored
Normal file
|
@ -0,0 +1,133 @@
|
|||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Makefile with ascentlint, verilator-lint and verible style lint
|
||||
# targets for OpenTitan
|
||||
#
|
||||
# TODO: currently we cannot support parallel builds since some fusesoc cores
|
||||
# define filesets with files outside the current folder (e.g. using relative
|
||||
# path prefixes such as "../../"). this can cause collisions between parallel
|
||||
# builds since they are not nicely contained within the same folder. This should
|
||||
# be solved by reworking the fusesoc core files (especially the top-level one).
|
||||
|
||||
CORE_ROOT ?= ../../
|
||||
REPORT_DIR ?= reports
|
||||
|
||||
IPS ?= ip-aes \
|
||||
ip-alert_handler \
|
||||
ip-clkmgr \
|
||||
ip-flash_ctrl \
|
||||
ip-gpio \
|
||||
ip-hmac \
|
||||
ip-i2c \
|
||||
ip-otp_ctrl \
|
||||
ip-nmi_gen \
|
||||
ip-padctrl \
|
||||
ip-pinmux \
|
||||
ip-pwrmgr \
|
||||
ip-rv_core_ibex \
|
||||
ip-rv_dm \
|
||||
ip-rv_plic_example \
|
||||
ip-rv_timer \
|
||||
ip-spi_device \
|
||||
ip-uart \
|
||||
ip-usbdev \
|
||||
ip-usb_fs_nb_pe \
|
||||
ip-usbuart \
|
||||
ip-rstmgr \
|
||||
tlul-socket_1n \
|
||||
tlul-socket_m1 \
|
||||
tlul-adapter_reg \
|
||||
tlul-adapter_sram \
|
||||
tlul-sram2tlul \
|
||||
systems-top_earlgrey
|
||||
|
||||
ips_lint = $(addsuffix _lint, $(IPS))
|
||||
ips_vlint = $(addsuffix _vlint, $(IPS))
|
||||
ips_slint = $(addsuffix _slint, $(IPS))
|
||||
|
||||
######################
|
||||
# ascentlint targets #
|
||||
######################
|
||||
|
||||
# lint all discovered targets and make a report
|
||||
all: lint
|
||||
$(MAKE) report
|
||||
|
||||
lint: clean
|
||||
@echo Discovered lint targets:
|
||||
@echo -e "\n $(patsubst %,%\\n,$(strip $(ips_lint)))"
|
||||
$(MAKE) $(ips_lint)
|
||||
|
||||
$(ips_lint):
|
||||
rm -rf build
|
||||
mkdir -p ${REPORT_DIR}
|
||||
-fusesoc --cores-root ${CORE_ROOT} run --target=lint --tool=ascentlint lowrisc:$(subst -,:,$(patsubst %_lint,%,$@))
|
||||
cp build/lowrisc_*$(subst -,_,$(patsubst %_lint,%,$@))*/lint-ascentlint/ascentlint.log ${REPORT_DIR}/$(patsubst %_lint,%,$@).log
|
||||
cp build/lowrisc_*$(subst -,_,$(patsubst %_lint,%,$@))*/lint-ascentlint/ascentlint.rpt ${REPORT_DIR}/$(patsubst %_lint,%,$@).rpt
|
||||
|
||||
# creates a (filtered) summary report from all available ascentlint logs/rpts
|
||||
# note that lint reports have to be filtered using this script before publishing
|
||||
# any information from these reports publicly
|
||||
# note, the filtering script is simplistic ATM and just looks for *.rpt files
|
||||
# hence we have to temporarily write the output to a file with a different extension
|
||||
# since otherwise the gen_report script will try to process the summary report as well.
|
||||
report:
|
||||
$(eval TMPFILE=$(shell mktemp))
|
||||
rm -f ${REPORT_DIR}/lint_summary.rpt
|
||||
./util/gen-report.sh | tee $(TMPFILE)
|
||||
cp $(TMPFILE) ${REPORT_DIR}/lint_summary.rpt
|
||||
rm -f $(TMPFILE)
|
||||
|
||||
#####################
|
||||
# verilator targets #
|
||||
#####################
|
||||
|
||||
vall: vlint
|
||||
$(MAKE) vreport
|
||||
|
||||
vlint: clean
|
||||
@echo Discovered vlint targets:
|
||||
@echo -e "\n $(patsubst %,%\\n,$(strip $(ips_vlint)))"
|
||||
$(MAKE) $(ips_vlint)
|
||||
|
||||
$(ips_vlint):
|
||||
rm -rf build
|
||||
mkdir -p ${REPORT_DIR}
|
||||
-fusesoc --cores-root ${CORE_ROOT} run --target=lint lowrisc:$(subst -,:,$(patsubst %_vlint,%,$@))
|
||||
|
||||
# TODO: add summary reporting
|
||||
vreport:
|
||||
|
||||
##############################
|
||||
# verible style lint targets #
|
||||
##############################
|
||||
|
||||
sall: slint
|
||||
$(MAKE) sreport
|
||||
|
||||
slint: clean
|
||||
@echo Discovered vlint targets:
|
||||
@echo -e "\n $(patsubst %,%\\n,$(strip $(ips_vlint)))"
|
||||
$(MAKE) $(ips_vlint)
|
||||
|
||||
# TODO(#1727): pass Verible config file to FuseSoC, once supported by Verible
|
||||
$(ips_slint):
|
||||
rm -rf build
|
||||
mkdir -p ${REPORT_DIR}
|
||||
-fusesoc --cores-root ${CORE_ROOT} run --target=lint --tool=veriblelint lowrisc:$(subst -,:,$(patsubst %_slint,%,$@))
|
||||
|
||||
# TODO: add summary reporting
|
||||
sreport:
|
||||
|
||||
##################
|
||||
# common targets #
|
||||
##################
|
||||
|
||||
clean:
|
||||
rm -rf build
|
||||
rm -rf ${REPORT_DIR}/*
|
||||
|
||||
.PHONY: all lint $(ips_lint) report vall vlint $(ips_vlint) \
|
||||
vreport sall slint $(ips_slint) clean sreport
|
32
vendor/lowrisc_ip/lint/common.core
vendored
Normal file
32
vendor/lowrisc_ip/lint/common.core
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
CAPI=2:
|
||||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
name: "lowrisc:lint:common:0.1"
|
||||
description: "Common waivers"
|
||||
filesets:
|
||||
files_verilator:
|
||||
files:
|
||||
- tools/verilator/common.vlt
|
||||
file_type: vlt
|
||||
|
||||
files_ascentlint:
|
||||
files:
|
||||
- tools/ascentlint/common.waiver: {file_type: waiver}
|
||||
- tools/ascentlint/ascentlint-config.tcl: {file_type: tclSource}
|
||||
|
||||
files_veriblelint:
|
||||
files:
|
||||
- tools/veriblelint/rules.vbl: {file_type: veribleLintRules}
|
||||
|
||||
files_check_tool_requirements:
|
||||
depend:
|
||||
- lowrisc:tool:check_tool_requirements
|
||||
|
||||
targets:
|
||||
default: &default_target
|
||||
filesets:
|
||||
- tool_verilator ? (files_verilator)
|
||||
- tool_ascentlint ? (files_ascentlint)
|
||||
- tool_veriblelint ? (files_veriblelint)
|
||||
- files_check_tool_requirements
|
24
vendor/lowrisc_ip/lint/comportable.core
vendored
Normal file
24
vendor/lowrisc_ip/lint/comportable.core
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
CAPI=2:
|
||||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
name: "lowrisc:lint:comportable:0.1"
|
||||
description: "Waiver files for comportable IPs"
|
||||
filesets:
|
||||
files_verilator_waiver:
|
||||
files:
|
||||
- tools/verilator/comportable.vlt
|
||||
file_type: vlt
|
||||
|
||||
files_ascentlint_waiver:
|
||||
files:
|
||||
- tools/ascentlint/comportable.waiver
|
||||
file_type: waiver
|
||||
|
||||
targets:
|
||||
default: &default_target
|
||||
filesets:
|
||||
- tool_verilator ? (files_verilator_waiver)
|
||||
- tool_ascentlint ? (files_ascentlint_waiver)
|
||||
|
||||
|
9
vendor/lowrisc_ip/lint/data/ascentlint.hjson
vendored
Normal file
9
vendor/lowrisc_ip/lint/data/ascentlint.hjson
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
{
|
||||
// Ascentlint-specific results parsing script that is called after running lint
|
||||
report_cmd: "{proj_root}/hw/lint/tools/{tool}/parse-lint-report.py "
|
||||
report_opts: ["--repdir={build_dir}/lint-{tool}",
|
||||
"--outdir={build_dir}"]
|
||||
}
|
33
vendor/lowrisc_ip/lint/data/common_lint_cfg.hjson
vendored
Normal file
33
vendor/lowrisc_ip/lint/data/common_lint_cfg.hjson
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
{
|
||||
flow: lint
|
||||
flow_makefile: "{proj_root}/hw/lint/data/lint.mk"
|
||||
|
||||
import_cfgs: [// common server configuration for results upload
|
||||
"{proj_root}/hw/data/common_project_cfg.hjson"
|
||||
// tool-specific configuration
|
||||
"{proj_root}/hw/lint/data/{tool}.hjson"]
|
||||
|
||||
// Name of the DUT / top-level to be run through lint
|
||||
dut: "{name}"
|
||||
|
||||
// Default directory structure for the output
|
||||
build_dir: "{scratch_path}/{build_mode}"
|
||||
build_log: "{build_dir}/lint.log"
|
||||
// We rely on fusesoc to run lint for us
|
||||
build_cmd: "fusesoc"
|
||||
build_opts: ["--cores-root {proj_root}",
|
||||
"run",
|
||||
"--target={flow}",
|
||||
"--tool={tool}",
|
||||
"--build-root={build_dir}",
|
||||
"{fusesoc_core}"]
|
||||
|
||||
// these are not needed currently, but have to be defined
|
||||
sv_flist_gen_cmd: ""
|
||||
sv_flist_gen_opts: []
|
||||
sv_flist_gen_dir: ""
|
||||
tool_srcs: []
|
||||
}
|
41
vendor/lowrisc_ip/lint/data/lint.mk
vendored
Normal file
41
vendor/lowrisc_ip/lint/data/lint.mk
vendored
Normal file
|
@ -0,0 +1,41 @@
|
|||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
.DEFAULT_GOAL := all
|
||||
|
||||
all: build
|
||||
|
||||
###################
|
||||
## build targets ##
|
||||
###################
|
||||
build: compile_result
|
||||
|
||||
pre_compile:
|
||||
@echo "[make]: pre_compile"
|
||||
mkdir -p ${build_dir} && env | sort > ${build_dir}/env_vars
|
||||
mkdir -p ${tool_srcs_dir}
|
||||
-cp -Ru ${tool_srcs} ${tool_srcs_dir}
|
||||
|
||||
compile: pre_compile
|
||||
@echo "[make]: compile"
|
||||
# we check the status in the parse script below
|
||||
-cd ${build_dir} && ${build_cmd} ${build_opts} 2>&1 | tee ${build_log}
|
||||
|
||||
post_compile: compile
|
||||
@echo "[make]: post_compile"
|
||||
|
||||
# Parse out result
|
||||
compile_result: post_compile
|
||||
@echo "[make]: compile_result"
|
||||
${report_cmd} ${report_opts}
|
||||
|
||||
clean:
|
||||
echo "[make]: clean"
|
||||
rm -rf ${scratch_root}/${dut}/*
|
||||
|
||||
.PHONY: build \
|
||||
run \
|
||||
pre_compile \
|
||||
compile \
|
||||
post_compile \
|
||||
compile_result
|
13
vendor/lowrisc_ip/lint/data/veriblelint.hjson
vendored
Normal file
13
vendor/lowrisc_ip/lint/data/veriblelint.hjson
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
{
|
||||
// TODO(#1342): switch over to native structured tool output, once supported by Verible
|
||||
// Verible lint-specific results parsing script that is called after running lint
|
||||
report_cmd: "{proj_root}/hw/lint/tools/{tool}/parse-lint-report.py "
|
||||
report_opts: ["--repdir={build_dir}",
|
||||
"--outdir={build_dir}"]
|
||||
|
||||
// This customizes the report format for style lint
|
||||
is_style_lint: True
|
||||
}
|
121
vendor/lowrisc_ip/lint/doc/README.md
vendored
Normal file
121
vendor/lowrisc_ip/lint/doc/README.md
vendored
Normal file
|
@ -0,0 +1,121 @@
|
|||
# RTL Linting
|
||||
|
||||
Linting is a productivity tool for designers to quickly find typos and bugs at the time when the RTL is written.
|
||||
Running lint is important when using SystemVerilog, a weakly-typed language, unlike other hardware description languages.
|
||||
We consider linting to be critical for conformance to our goals of high quality designs.
|
||||
|
||||
We have standardized on the [AscentLint](https://www.realintent.com/rtl-linting-ascent-lint/) tool from RealIntent for this task due to its fast run-times and comprehensive set of rules that provide concise error and warning messages.
|
||||
|
||||
The lint flow leverages a new lint rule policy named _"lowRISC Lint Rules"_ that has been tailored towards our [Verilog Style Guide](https://github.com/lowRISC/style-guides/blob/master/VerilogCodingStyle.md).
|
||||
The lint flow run scripts and waiver files are available in the GitHub repository of this project, but due to the proprietary nature of the lint rules and their configuration, the _"lowRISC Lint Rules"_ lint policy file can not be publicly provided.
|
||||
However, the _"lowRISC Lint Rules"_ are available as part of the default policies in AscentLint release 2019.A.p3 or newer (as `LRLR-v1.0.policy`).
|
||||
This enables designers that have access to this tool to run the lint flow provided locally on their premises.
|
||||
|
||||
Our linting flow leverages FuseSoC to resolve dependencies, build file lists and call the linting tools. See [here](https://github.com/olofk/fusesoc) for an introduction to this opensource package manager and [here](https://docs.opentitan.org/doc/ug/install_instructions/) for installation instructions.
|
||||
|
||||
In order to run lint on a [comportable IP](https://docs.opentitan.org/doc/rm/comportability_specification/) block, the corresponding FuseSoC core file must have a lint target and include (optional) waiver files as shown in the following example taken from the FuseSoC core of the AES comportable IP:
|
||||
```
|
||||
filesets:
|
||||
|
||||
[...]
|
||||
|
||||
files_verilator_waiver:
|
||||
depend:
|
||||
# common waivers
|
||||
- lowrisc:lint:common
|
||||
- lowrisc:lint:comportable
|
||||
files:
|
||||
- lint/aes.vlt
|
||||
file_type: vlt
|
||||
|
||||
files_ascentlint_waiver:
|
||||
depend:
|
||||
# common waivers
|
||||
- lowrisc:lint:common
|
||||
- lowrisc:lint:comportable
|
||||
files:
|
||||
- lint/aes.waiver
|
||||
file_type: waiver
|
||||
|
||||
files_veriblelint_waiver:
|
||||
depend:
|
||||
# common waivers
|
||||
- lowrisc:lint:common
|
||||
- lowrisc:lint:comportable
|
||||
[...]
|
||||
|
||||
targets:
|
||||
default: &default_target
|
||||
filesets:
|
||||
- tool_verilator ? (files_verilator_waiver)
|
||||
- tool_ascentlint ? (files_ascentlint_waiver)
|
||||
- tool_veriblelint ? (files_veriblelint_waiver)
|
||||
- files_rtl
|
||||
toplevel: aes
|
||||
|
||||
lint:
|
||||
<<: *default_target
|
||||
default_tool: verilator
|
||||
parameters:
|
||||
- SYNTHESIS=true
|
||||
tools:
|
||||
verilator:
|
||||
mode: lint-only
|
||||
verilator_options:
|
||||
- "-Wall"
|
||||
```
|
||||
Note that the setup shown above also supports RTL style linting with the open source tool [Verible](https://github.com/google/verible/) and RTL linting with [Verilator](https://www.veripool.org/wiki/verilator) in order to complement the sign-off lint flow with AscentLint.
|
||||
In particular, Verible lint focuses on different aspects of the code, and detects style elements that are in violation with our [Verilog Style Guide](https://github.com/lowRISC/style-guides/blob/master/VerilogCodingStyle.md).
|
||||
|
||||
The same lint target is reused for all three tools (we override the tool selection when invoking FuseSoC).
|
||||
Lint waivers can be added to the flow by placing them in the corresponding waiver file.
|
||||
In this example this would be `lint/aes.waiver` for AscentLint and `lint/aes.vlt` for Verilator.
|
||||
|
||||
In order to manually run lint on a specific block, make sure AscentLint is properly installed and step into the `hw/lint` folder.
|
||||
The makefile in that folder contains all targets that can be manually invoked.
|
||||
For example, to run lint on AES, do:
|
||||
```
|
||||
make ip-aes_lint
|
||||
```
|
||||
This run will exit with PASSED status on the command line if there are no lint errors or warnings.
|
||||
Otherwise it will exit with ERROR status, in which case you can get more information by running
|
||||
```
|
||||
make clean
|
||||
make ip-aes_lint
|
||||
make report
|
||||
```
|
||||
In order to build all lint targets and produce a summary report, the `make all` target can be invoked.
|
||||
For more detailed information on a particular lint run you can inspect the tool output inside the build folder that is created by FuseSoC.
|
||||
|
||||
Note that all AscentLint targets have a Verilator and Verible counterparts that are suffixed with `_vlint` and `_slint`, respectively.
|
||||
This enables designers without access to AscentLint to iterate with open-source tools before making their first Pull Request.
|
||||
|
||||
For batch regressions we have integrated this flow into the `dvsim` tool, which can be invoked as follows from the root of the project repository:
|
||||
```
|
||||
util/dvsim.py hw/top_earlgrey/lint/ascentlint/top_earlgrey_lint_cfgs.hjson --tool "ascentlint" --purge -mp 1
|
||||
```
|
||||
where the `top_earlgrey_lint_cfgs.hjson` file contains all the lint targets to be run in that regression (currently all available comportable IPs and the top-level are run).
|
||||
The `purge` option ensures that the scratch directory is fully erased before starting the build, and `mp 1` sets the number of parallel workers to one (should be set depending on your licensing situation).
|
||||
|
||||
The batch regression is regularly run on the master branch at eight-hour intervals, and the results are published on a public dashboard such that everybody can inspect the current lint status of all IPs on the project website.
|
||||
The dashboard can be found by following the appropriate link on the [hardware IP overview page](https://docs.opentitan.org/hw).
|
||||
|
||||
# CDC Linting
|
||||
|
||||
Logic designs that have signals that cross from one clock domain to
|
||||
another unrelated clock domain are notorious for introducing hard to
|
||||
debug problems. The reason is that design verification, with its constant
|
||||
and idealized timing relationships on signals, does not represent the
|
||||
variability and uncertainty of real world systems. For this reason,
|
||||
maintaining a robust Clock Domain Crossing verification strategy ("CDC
|
||||
methodology") is critical to the success of any multi-clock design.
|
||||
|
||||
Currently, due to the proprietary nature of tool collateral, all CDC linting
|
||||
activity is done offline and reported back to designers. The project will
|
||||
standardize on a particular CDC linting tool, and results will be shared in
|
||||
some form through continuous integration build results, published tool
|
||||
outputs, pre-submit checks, and/or linting summaries of tool output
|
||||
(TODO: publication details). At that time this README will be updated
|
||||
with setup and run instructions.
|
||||
|
||||
This holds for *Reset Domain Crossing* ("RDC") methodology as well.
|
9
vendor/lowrisc_ip/lint/tools/ascentlint/ascentlint-config.tcl
vendored
Normal file
9
vendor/lowrisc_ip/lint/tools/ascentlint/ascentlint-config.tcl
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# get installation path of ascentlint
|
||||
set RI_INSTALL [file dirname [exec which ascentlint]]
|
||||
|
||||
# source the policy file containing the lowrisc lint rules
|
||||
source "$RI_INSTALL/../Ascent/Lint/lib/policies/lowRISC/LRLR-v1.0.policy"
|
11
vendor/lowrisc_ip/lint/tools/ascentlint/common.waiver
vendored
Normal file
11
vendor/lowrisc_ip/lint/tools/ascentlint/common.waiver
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# common waiver rules for ascentlint
|
||||
|
||||
# waiver for unused_* signals for HIER_* rules (note that our policy file has a
|
||||
# similar exception list for rule NOT_READ)
|
||||
waive -rules {HIER_NET_NOT_READ HIER_BRANCH_NOT_READ} -pattern {unused_*}
|
||||
waive -rules {HIER_NET_NOT_READ HIER_BRANCH_NOT_READ} -pattern {gen_*.unused_*}
|
||||
|
21
vendor/lowrisc_ip/lint/tools/ascentlint/comportable.waiver
vendored
Normal file
21
vendor/lowrisc_ip/lint/tools/ascentlint/comportable.waiver
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# comportable IP waiver rules for ascentlint
|
||||
|
||||
# auto-generated register files
|
||||
|
||||
waive -rules CONST_FF -location {*_reg_top*} -regexp {rsp_opcode.*is driven by constant zeros} \
|
||||
-comment "makes the code more readable"
|
||||
waive -rules CONST_OUTPUT -location {*_reg_top*} -regexp {Output 'tl_o.d_(param|size|sink|user)' is driven by constant} \
|
||||
-comment "makes the code more readable"
|
||||
waive -rules INPUT_NOT_READ -location {*_reg_top*} -regexp {Input port.*a_(address|param|user).*not read from} \
|
||||
-comment "several TLUL signals are not used by register file"
|
||||
waive -rules HIER_NET_NOT_READ -location {*_reg_top*} -regexp {Net 'tl_reg_h2d.a_(address|param|user).* is not read from} \
|
||||
-comment "several TLUL signals are not used by register file"
|
||||
waive -rules CASE_SEL_CONST -location {*_reg_top*} \
|
||||
-comment "addr_hit is one hot encoded."
|
||||
waive -rules LINE_LENGTH -location {*_reg_top*} -regexp {Line length of .* exceeds .* character limit} \
|
||||
-comment "These files are one-liners in order to comply with our SV style guide."
|
||||
|
125
vendor/lowrisc_ip/lint/tools/ascentlint/parse-lint-report.py
vendored
Executable file
125
vendor/lowrisc_ip/lint/tools/ascentlint/parse-lint-report.py
vendored
Executable file
|
@ -0,0 +1,125 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
r"""Parses lint report and dump filtered messages in hjson format.
|
||||
"""
|
||||
import argparse
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import hjson
|
||||
|
||||
|
||||
def extract_messages(full_file, patterns, results):
|
||||
"""
|
||||
This extracts messages from the sting buffer full_file.
|
||||
The argument patterns needs to be a list of tuples with
|
||||
(<error_severity>, <pattern_to_match_for>).
|
||||
"""
|
||||
for severity, pattern in patterns:
|
||||
results[severity] += re.findall(pattern, full_file, flags=re.MULTILINE)
|
||||
|
||||
return results
|
||||
|
||||
|
||||
def get_results(resdir):
|
||||
"""
|
||||
Parse report and corresponding logfiles and extract error, warning
|
||||
and info messages for each IP present in the result folder
|
||||
"""
|
||||
results = {
|
||||
"tool": "ascentlint",
|
||||
"errors": [],
|
||||
"warnings": [],
|
||||
"lint_errors": [],
|
||||
"lint_warnings": [],
|
||||
"lint_infos": []
|
||||
}
|
||||
try:
|
||||
# check the log file for flow errors and warnings
|
||||
with Path(resdir).joinpath('ascentlint.log').open() as f:
|
||||
full_file = f.read()
|
||||
err_warn_patterns = [("errors", r"^FlexNet Licensing error.*"),
|
||||
("errors", r"^Error: .*"),
|
||||
("errors", r"^ ERR .*"),
|
||||
("warnings", r"^Warning: .*"),
|
||||
("warnings", r"^ WARN .*")]
|
||||
extract_messages(full_file, err_warn_patterns, results)
|
||||
except IOError as err:
|
||||
results["errors"] += ["IOError: %s" % err]
|
||||
|
||||
try:
|
||||
# check the report file for lint INFO, WARNING and ERRORs
|
||||
with Path(resdir).joinpath('ascentlint.rpt').open() as f:
|
||||
full_file = f.read()
|
||||
err_warn_patterns = {("lint_errors", r"^E .*"),
|
||||
("lint_warnings", r"^W .*"),
|
||||
("lint_infos", r"^I .*")}
|
||||
extract_messages(full_file, err_warn_patterns, results)
|
||||
except IOError as err:
|
||||
results["errors"] += ["IOError: %s" % err]
|
||||
|
||||
return results
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description="""This script parses AscentLint log and report files from
|
||||
a lint run, filters the messages and creates an aggregated result
|
||||
.hjson file with the following fields:
|
||||
|
||||
{"tool": "ascentlint",
|
||||
"errors" : [],
|
||||
"warnings" : [],
|
||||
"lint_errors" : [],
|
||||
"lint_warnings" : [],
|
||||
"lint_infos" : []}
|
||||
|
||||
The fields 'errors' and 'warnings' contain file IO messages or
|
||||
messages output by the tool itself, whereas the fields prefixed with
|
||||
'lint_' contain lint-related messages.
|
||||
|
||||
The script returns nonzero status if any warnings or errors are present.
|
||||
""")
|
||||
parser.add_argument('--repdir',
|
||||
type=str,
|
||||
default="./",
|
||||
help="""The script searches the 'ascentlint.log' and
|
||||
'ascentlint.rpt' files in this directory.
|
||||
Defaults to './'""")
|
||||
|
||||
parser.add_argument('--outdir',
|
||||
type=str,
|
||||
default="./",
|
||||
help="""Output directory for the 'results.hjson' file.
|
||||
Defaults to './'""")
|
||||
|
||||
args = parser.parse_args()
|
||||
results = get_results(args.repdir)
|
||||
|
||||
with Path(args.outdir).joinpath("results.hjson").open("w") as results_file:
|
||||
hjson.dump(results,
|
||||
results_file,
|
||||
ensure_ascii=False,
|
||||
for_json=True,
|
||||
use_decimal=True)
|
||||
|
||||
# return nonzero status if any warnings or errors are present
|
||||
# lint infos do not count as failures
|
||||
nr_errors = len(results["errors"]) + len(results["lint_errors"])
|
||||
nr_warnings = len(results["warnings"]) + len(results["lint_warnings"])
|
||||
if nr_errors > 0 and nr_warnings > 0:
|
||||
print("Lint not successful, got %d warnings and %d errors." %
|
||||
(nr_warnings, nr_errors))
|
||||
sys.exit(1)
|
||||
|
||||
print("Lint successful, got %d warnings and %d errors." %
|
||||
(nr_warnings, nr_errors))
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
127
vendor/lowrisc_ip/lint/tools/veriblelint/parse-lint-report.py
vendored
Executable file
127
vendor/lowrisc_ip/lint/tools/veriblelint/parse-lint-report.py
vendored
Executable file
|
@ -0,0 +1,127 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
r"""Parses lint report and dump filtered messages in hjson format.
|
||||
"""
|
||||
import argparse
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import hjson
|
||||
|
||||
|
||||
def extract_messages(full_file, patterns, results):
|
||||
"""
|
||||
This extracts messages from the sting buffer full_file.
|
||||
The argument patterns needs to be a list of tuples with
|
||||
(<error_severity>, <pattern_to_match_for>).
|
||||
"""
|
||||
for severity, pattern in patterns:
|
||||
results[severity] += re.findall(pattern, full_file, flags=re.MULTILINE)
|
||||
|
||||
return results
|
||||
|
||||
|
||||
def get_results(resdir):
|
||||
"""
|
||||
Parse report and corresponding logfiles and extract error, warning
|
||||
and info messages for each IP present in the result folder
|
||||
"""
|
||||
results = {
|
||||
"tool": "veriblelint",
|
||||
"errors": [],
|
||||
"warnings": [],
|
||||
"lint_errors": [],
|
||||
"lint_warnings": [],
|
||||
"lint_infos": []
|
||||
}
|
||||
try:
|
||||
# check the report file for lint INFO, WARNING and ERRORs
|
||||
with Path(resdir).joinpath('lint.log').open() as f:
|
||||
full_file = f.read()
|
||||
err_warn_patterns = {
|
||||
# The lint failed error can be ignored, since
|
||||
# Fusesoc will always return this error if lint warnings have
|
||||
# been found. We have a way of capturing the lint warnings
|
||||
# explicitly in this parsing script, hence this error is redundant
|
||||
# and we decided not to report it in the dashboard.
|
||||
("errors",
|
||||
r"^(?!ERROR: Failed to run .* Lint failed)ERROR: .*"),
|
||||
("errors", r"^Error: .*"),
|
||||
("errors", r"^E .*"),
|
||||
# TODO(https://github.com/olofk/edalize/issues/90):
|
||||
# this is a workaround until we actually have native Edalize
|
||||
# support for JasperGold and "formal" targets
|
||||
("warnings",
|
||||
r"^(?!WARNING: Unknown item formal in section Target)WARNING: .*"
|
||||
),
|
||||
("warnings", r"^Warning: .* "),
|
||||
("warnings", r"^W .*"),
|
||||
("lint_warnings", r"^.*\[Style:.*")
|
||||
}
|
||||
extract_messages(full_file, err_warn_patterns, results)
|
||||
except IOError as err:
|
||||
results["errors"] += ["IOError: %s" % err]
|
||||
|
||||
return results
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description="""This script parses verible lint log files from
|
||||
a lint run, filters the messages and creates an aggregated result
|
||||
.hjson file with the following fields:
|
||||
|
||||
{"tool": "veriblelint",
|
||||
"errors" : [],
|
||||
"warnings" : [],
|
||||
"lint_errors" : [],
|
||||
"lint_warnings" : [],
|
||||
"lint_infos" : []}
|
||||
|
||||
The fields 'errors' and 'warnings' contain file IO messages or
|
||||
messages output by the tool itself, whereas the fields prefixed with
|
||||
'lint_' contain lint-related messages.
|
||||
|
||||
The script returns nonzero status if any warnings or errors are present.
|
||||
""")
|
||||
parser.add_argument('--repdir',
|
||||
type=str,
|
||||
default="./",
|
||||
help="""The script searches the 'lint.log'
|
||||
files in this directory.
|
||||
Defaults to './'""")
|
||||
|
||||
parser.add_argument('--outdir',
|
||||
type=str,
|
||||
default="./",
|
||||
help="""
|
||||
Output directory for the 'results.hjson' file.
|
||||
Defaults to '%(default)s'""")
|
||||
|
||||
args = parser.parse_args()
|
||||
results = get_results(args.repdir)
|
||||
|
||||
with Path(args.outdir).joinpath("results.hjson").open("w") as results_file:
|
||||
hjson.dump(results,
|
||||
results_file,
|
||||
ensure_ascii=False,
|
||||
for_json=True,
|
||||
use_decimal=True)
|
||||
|
||||
# return nonzero status if any warnings or errors are present
|
||||
# lint infos do not count as failures
|
||||
nr_errors = len(results["errors"]) + len(results["lint_errors"])
|
||||
nr_warnings = len(results["warnings"]) + len(results["lint_warnings"])
|
||||
print("Lint not successful, got %d warnings and %d errors." %
|
||||
(nr_warnings, nr_errors))
|
||||
if nr_errors > 0 and nr_warnings > 0:
|
||||
sys.exit(1)
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
19
vendor/lowrisc_ip/lint/tools/veriblelint/rules.vbl
vendored
Normal file
19
vendor/lowrisc_ip/lint/tools/veriblelint/rules.vbl
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# OpenTitan-specific style lint rule configurations
|
||||
|
||||
# line length currently set to 150 to remove clutter in reports.
|
||||
# set this back to 100 once we can waive this rule for generated
|
||||
# files or once the file generators can respect this constraint
|
||||
line-length=length:150
|
||||
|
||||
# we allow "classic" verilog string parameters without explicit type
|
||||
explicit-parameter-storage-type=exempt_type:string
|
||||
|
||||
# localparam can be both ALL_CAPS and CamelCase according to our style
|
||||
parameter-name-style=localparam_style:CamelCase|ALL_CAPS
|
||||
|
||||
# we allow nested struct definitions
|
||||
-typedef-structs-unions
|
6
vendor/lowrisc_ip/lint/tools/verilator/common.vlt
vendored
Normal file
6
vendor/lowrisc_ip/lint/tools/verilator/common.vlt
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// common waiver rules for verilator
|
||||
|
6
vendor/lowrisc_ip/lint/tools/verilator/comportable.vlt
vendored
Normal file
6
vendor/lowrisc_ip/lint/tools/verilator/comportable.vlt
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// comportable IP waiver rules for verilator
|
||||
|
54
vendor/lowrisc_ip/lint/util/gen-report.sh
vendored
Executable file
54
vendor/lowrisc_ip/lint/util/gen-report.sh
vendored
Executable file
|
@ -0,0 +1,54 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Ascentlint report summary generation script.
|
||||
#
|
||||
|
||||
REPORT_DIR=reports
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# print header
|
||||
#-------------------------------------------------------------------------
|
||||
printf "NUMBER OF LINT ERRORS PER BLOCK:\n\n"
|
||||
format="%20s %10s %10s \n"
|
||||
printf "${format}" "Block" "Errors" "Warnings"
|
||||
echo "-------------------------------------------"
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# run lint and summarize results
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
for report in ${REPORT_DIR}/*.rpt ; do
|
||||
|
||||
# summarize results
|
||||
crash=`grep "Exiting with error status" "${report%.*}.log"`
|
||||
if [[ ! -z "$crash" ]]; then
|
||||
error_cnt="CRASH"
|
||||
warni_cnt="CRASH"
|
||||
else
|
||||
error_cnt=`grep "^E " "${report%.*}.rpt" | wc -l`
|
||||
warni_cnt=`grep "^W " "${report%.*}.rpt" | wc -l`
|
||||
fi
|
||||
printf "${format}" `basename "${report%.*}"` $error_cnt $warni_cnt
|
||||
done
|
||||
|
||||
echo "-------------------------------------------"
|
||||
echo "END SUMMARY"
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# generate detailed reports
|
||||
#-------------------------------------------------------------------------
|
||||
printf "\n\nLIST OF ERRORS (E) AND WARNINGS (W) FOR EACH BLOCK:"
|
||||
for report in ${REPORT_DIR}/*.rpt ; do
|
||||
|
||||
printf "\n\n`basename "${report%.*}"`\n"
|
||||
|
||||
# grep for lint crashes and lint errors, and limit line length
|
||||
grep "^ ERR" -A 2 "${report%.*}.log" | cut -c -200
|
||||
grep "^E " "${report%.*}.rpt" | cut -c -200
|
||||
grep "^W " "${report%.*}.rpt" | cut -c -200
|
||||
|
||||
done
|
199
vendor/lowrisc_ip/prim/README.md
vendored
Normal file
199
vendor/lowrisc_ip/prim/README.md
vendored
Normal file
|
@ -0,0 +1,199 @@
|
|||
# lowRISC Hardware Primitives
|
||||
|
||||
## Concepts
|
||||
|
||||
This directory contains basic building blocks to create a hardware design,
|
||||
called primitives. A primitive is described by its name, and has a well-defined
|
||||
list of ports and parameters.
|
||||
|
||||
Under the hood, primitives are slightly special, as they can have multiple
|
||||
implementations. In contrast to many other modules in a hardware design,
|
||||
primitives must often be implemented in technology-dependent ways. For example,
|
||||
a clock multiplexer for a Xilinx FPGA is implemented differently than one for
|
||||
a specific ASIC technology.
|
||||
|
||||
Not all primitives need to have multiple implementations.
|
||||
|
||||
* Primitives with a single, generic, implementation are normal SystemVerilog
|
||||
modules inside the `hw/ip/prim/rtl` directory. We call these primitives
|
||||
"technology-independent primitives".
|
||||
* Primitives with multiple implementations have only a FuseSoC core file in the
|
||||
`hw/ip/prim` directory. The actual implementations are in "technology
|
||||
libraries". We call these primitives "technology-dependent primitives".
|
||||
|
||||
### Abstract primitives
|
||||
|
||||
Abstract primitives are wrappers around technology-dependent implementations of
|
||||
primitives, with the ability to select a specific implementation if needed.
|
||||
|
||||
In more technical terms, abstract primitives are SystemVerilog modules. The
|
||||
example below shows one.
|
||||
|
||||
```systemverilog
|
||||
`ifndef PRIM_DEFAULT_IMPL
|
||||
`define PRIM_DEFAULT_IMPL prim_pkg::ImplGeneric
|
||||
`endif
|
||||
|
||||
module prim_pad_wrapper
|
||||
#(
|
||||
parameter int unsigned AttrDw = 6
|
||||
) (
|
||||
inout wire inout_io, // bidirectional pad
|
||||
output logic in_o, // input data
|
||||
input out_i, // output data
|
||||
input oe_i, // output enable
|
||||
// additional attributes {drive strength, keeper, pull-up, pull-down, open-drain, invert}
|
||||
input [AttrDw-1:0] attr_i
|
||||
);
|
||||
parameter prim_pkg::impl_e Impl = `PRIM_DEFAULT_IMPL;
|
||||
|
||||
if (Impl == prim_pkg::ImplGeneric) begin : gen_generic
|
||||
prim_generic_pad_wrapper u_impl_generic (
|
||||
.*
|
||||
);
|
||||
end else if (Impl == prim_pkg::ImplXilinx) begin : gen_xilinx
|
||||
prim_xilinx_pad_wrapper u_impl_xilinx (
|
||||
.*
|
||||
);
|
||||
end else begin : gen_failure
|
||||
// TODO: Find code that works across tools and causes a compile failure
|
||||
end
|
||||
|
||||
endmodule
|
||||
```
|
||||
|
||||
As seen from the source code snippet, abstract primitives have the following
|
||||
properties:
|
||||
|
||||
- They have an `Impl` parameter which can be set to choose a specific
|
||||
implementation of the primitive.
|
||||
- The `Impl` parameter is set to a system-wide default determined by the
|
||||
`PRIM_DEFAULT_IMPL` define.
|
||||
- All ports and parameters of the abstract primitive are forwarded to the
|
||||
implementations.
|
||||
|
||||
### Technology libraries
|
||||
|
||||
Technology libraries collect implementations of primitives.
|
||||
|
||||
At least one technology library must exist: the `generic` technology library,
|
||||
which contains a pure-SystemVerilog implementation of the functionality. This
|
||||
library is commonly used for simulations and as functional reference. The
|
||||
`generic` technology library is contained in the `hw/ip/prim_generic` directory.
|
||||
|
||||
In addition to the implementation in the `generic` library, primitives may be
|
||||
implemented by as many other libraries as needed.
|
||||
|
||||
Technology libraries are referenced by their name.
|
||||
|
||||
### Technology library discovery
|
||||
|
||||
In many cases, technology libraries contain vendor-specific code which cannot be
|
||||
shared widely or openly. Therefore, a FuseSoC looks for available technology
|
||||
libraries at build time, and makes all libraries it finds available.
|
||||
|
||||
The discovery is performed based on the agreed-on naming scheme for primitives.
|
||||
|
||||
- FuseSoC scans all libraries (e.g. as specified by its `--cores-root` command
|
||||
line argument) for cores.
|
||||
- All cores with a name matching `lowrisc:prim_TECHLIBNAME:PRIMNAME`
|
||||
are considered. `TECHLIBNAME` is then added to the list of technology
|
||||
libraries.
|
||||
|
||||
After the discovery process has completed, a script (`primgen`) creates
|
||||
- an abstract primitive (see above), and
|
||||
- an entry in the `prim_pkg` package in the form of `prim_pkg::ImplTechlibname`
|
||||
to identify the technology library by its name.
|
||||
|
||||
## User Guide
|
||||
|
||||
### Use primitives
|
||||
|
||||
Primitives are normal SystemVerilog modules, and can be used as usual:
|
||||
* instantiate it like a normal SystemVerilog module, and
|
||||
* add a dependency in the FuseSoC core file.
|
||||
|
||||
Technology-dependent primitives have an additional parameter called `Impl`.
|
||||
Set this parameter to use a specific implementation of the primitive for this
|
||||
specific instance. For example:
|
||||
|
||||
```systemverilog
|
||||
prim_ram_2p #(
|
||||
.Width (TotalWidth),
|
||||
.Depth (Depth),
|
||||
// Force the use of the tsmc40lp technology library for this instance, instead
|
||||
// of using the build-time default.
|
||||
.Impl(prim_pkg::ImplTsmc40lp)
|
||||
) u_mem (
|
||||
.clk_a_i (clk_i),
|
||||
...
|
||||
)
|
||||
```
|
||||
|
||||
|
||||
### Set the default technology library
|
||||
|
||||
If no specific technology library is chosen for an instantiated primitive the
|
||||
default library is used. The SystemVerilog define `PRIM_DEFAULT_IMPL` can be
|
||||
used to set the default for the whole design. Set this define to one of the enum
|
||||
values in `prim_pkg.sv` in the form `prim_pkg::ImplTechlibname`. `Techlibname`
|
||||
is the capitalized name of the technology library.
|
||||
|
||||
In the top-level FuseSoC core file the default technology library can be chosen
|
||||
like this:
|
||||
|
||||
```yaml
|
||||
# my_toplevel.core
|
||||
|
||||
# Declare filesets and other things (omitted)
|
||||
|
||||
parameters:
|
||||
# Make the parameter known to FuseSoC to enable overrides from the
|
||||
# command line. If not overwritten, use the generic technology library.
|
||||
PRIM_DEFAULT_IMPL:
|
||||
datatype: str
|
||||
paramtype: vlogdefine
|
||||
description: Primitives implementation to use, e.g. "prim_pkg::ImplGeneric".
|
||||
default: prim_pkg::ImplGeneric
|
||||
|
||||
targets:
|
||||
fpga_synthesis:
|
||||
filesets:
|
||||
- my_rtl_files
|
||||
parameters:
|
||||
# Use the xilinx technology library for this target by default.
|
||||
- PRIM_DEFAULT_IMPL=prim_pkg::ImplXilinx
|
||||
toplevel: my_toplevel
|
||||
```
|
||||
|
||||
|
||||
### Create a technology library
|
||||
|
||||
To create a technology library follow these steps:
|
||||
|
||||
- Choose a name for the new technology library. Names are all lower-case.
|
||||
To ease sharing of technology libraries it is encouraged to pick a very
|
||||
specific name, e.g. `tsmc40lp`, and not `asic`.
|
||||
- Copy the `prim_generic` folder into an arbitrary location (can be outside
|
||||
of this repository). Name the folder `prim_YOURLIBRARYNAME`.
|
||||
- Replace the word `generic` everywhere with the name of your technology
|
||||
library. This includes
|
||||
- file and directory names (e.g. `prim_generic_ram1p.sv` becomes
|
||||
`prim_tsmc40lp_ram1p.sv`),
|
||||
- module names (e.g. `prim_generic_ram1p` becomes `prim_tsmc40lp_ram1p`), and
|
||||
- all other references (grep for it!).
|
||||
- Implement all primitives. Replace the module body of the generic
|
||||
implementation with a technology-specific implementation as needed. Do *not*
|
||||
modify the list of ports or parameters in any way!
|
||||
|
||||
## Implementation details
|
||||
|
||||
Technology-dependent primitives are implemented as a FuseSoC generator. The
|
||||
core of the primitive (e.g. `lowrisc:prim:rom` in `prim/prim_rom.core`) calls
|
||||
a FuseSoC generator. This generator is the script `util/primgen.py`. As input,
|
||||
the script receives a list of all cores found by FuseSoC anywhere in its search
|
||||
path. The script then looks through the cores FuseSoC discovered and extracts
|
||||
a list of technology libraries out of it. It then goes on to create the
|
||||
abstract primitive (copying over the list of parameters and ports from the
|
||||
generic implementation), and an associated core file, which depends on all
|
||||
technology-dependent libraries that were found.
|
89
vendor/lowrisc_ip/prim/doc/prim_keccak.md
vendored
Normal file
89
vendor/lowrisc_ip/prim/doc/prim_keccak.md
vendored
Normal file
|
@ -0,0 +1,89 @@
|
|||
---
|
||||
title: "Primitive Component: Keccak permutation"
|
||||
---
|
||||
|
||||
# Overview
|
||||
|
||||
`prim_keccak` is a single round implementation of the permutation stage in [SHA3 algorithm][fibs-pub-202].
|
||||
Keccak primitive module assumes the number of rounds is less than or equal to 12 + 2L.
|
||||
It supports all combinations of the data width described in the [spec][fibs-pub-202].
|
||||
This implementation is not currently hardened against side-channel or fault injection attacks.
|
||||
It implements the Keccak_p function.
|
||||
|
||||
[fibs-pub-202]: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf
|
||||
|
||||
## Parameters
|
||||
|
||||
Name | Type | Description
|
||||
------|------|----------------------------------------------------------------
|
||||
Width | int | state width in bits. can be 25, 50, 100, 200, 400, 800, or 1600
|
||||
|
||||
### Derived Parameters
|
||||
|
||||
The parameters below are derived parameter from `Width` parameter.
|
||||
|
||||
Name | Type | Description
|
||||
---------|------|-------------------------------------------------------
|
||||
W | int | number of slices in state. `Width/25`
|
||||
L | int | log2 of `W`
|
||||
MaxRound | int | maximum allowed round value. `12 + 2L`
|
||||
RndW | int | bit-width to represent MaxRound. log2 of `MaxRound`
|
||||
|
||||
## Signal Interfaces
|
||||
|
||||
Signal | Type | Description
|
||||
-------|---------------|------------------------------
|
||||
rnd_i | input [RndW] | current round number [0..(MaxRound-1)]
|
||||
s_i | input [Width] | state input
|
||||
s_o | output[Width] | permutated state output
|
||||
|
||||
`s_i` and `s_o` are little-endian bitarrays.
|
||||
The [SHA3 spec][fibs-pub-202] shows how to convert the bitstream into the 5x5xW state cube.
|
||||
For instance, bit 0 of the stream maps to `A[0,0,0]`.
|
||||
The bit 0 in the spec is the first bit of the bitstream.
|
||||
In `prim_keccak`, `s_i[0]` is the first bit and `s_i[Width-1]` is the last bit.
|
||||
|
||||
# Theory of Operations
|
||||
|
||||
```
|
||||
| |
|
||||
rnd_i | |
|
||||
---/---->| -----------------------------------------\ |
|
||||
[RndW] | | |
|
||||
| | |
|
||||
s_i | V | s_o
|
||||
===/====>| bit2s() -> chi(pi(rho(theta))) -> iota( ,rnd) -> s2bit() |==/==>
|
||||
[Width] | |-----------keccak_p--------------| |[Width]
|
||||
| |
|
||||
```
|
||||
|
||||
`prim_keccak` implements "Step Mappings" section in [SHA3 spec][fibs-pub-202].
|
||||
It is composed of five unique permutation functions, theta, rho, pi, chi, and iota.
|
||||
Also it has functions that converts bitstream of `Width` into `5x5xW` state and vice versa.
|
||||
|
||||
Three constant parameters are defined inside the keccak primitive module.
|
||||
The rotate position described in phi function is hard-coded as below.
|
||||
The value is described in the SHA3 specification.
|
||||
|
||||
```systemverilog
|
||||
localparam int PiRotate [5][5] = '{
|
||||
//y 0 1 2 3 4 x
|
||||
'{ 0, 3, 1, 4, 2},// 0
|
||||
'{ 1, 4, 2, 0, 3},// 1
|
||||
'{ 2, 0, 3, 1, 4},// 2
|
||||
'{ 3, 1, 4, 2, 0},// 3
|
||||
'{ 4, 2, 0, 3, 1} // 4
|
||||
};
|
||||
```
|
||||
|
||||
The shift amount in rho function is defined as `RhoOffset` parameter.
|
||||
The value is same as in the specification, but it is used as `RhoOffset % W`.
|
||||
For instance, `RhoOffset[2][2]` is 171.
|
||||
If `Width` is 1600, the value used in the design is `171%64`, which is `43`.
|
||||
|
||||
The round constant is calculated by the tool `hw/ip/prim/util/keccak_rc.py`.
|
||||
The recommended default value of 24 rounds is used in this design,
|
||||
but an argument (changed with the `-r` flag) is provided for reference.
|
||||
The `keccak_rc.py` script creates 64 bit of constants and the `prim_keccak` module uses only lower bits of the constants if the `Width` is less than 1600.
|
||||
For instance, if `Width` is 800, lower 32bits of the round constant are used.
|
||||
|
91
vendor/lowrisc_ip/prim/doc/prim_lfsr.md
vendored
Normal file
91
vendor/lowrisc_ip/prim/doc/prim_lfsr.md
vendored
Normal file
|
@ -0,0 +1,91 @@
|
|||
---
|
||||
title: "Primitive Component: LFSR"
|
||||
---
|
||||
|
||||
# Overview
|
||||
|
||||
`prim_lfsr` is a parameterized linear feedback shift register (LFSR)
|
||||
implementation that supports Galois (XOR form) and Fibonacci (XNOR form)
|
||||
polynomials. The main difference between Galois and Fibonacci is that the
|
||||
former has a shorter critical timing path since the XOR Gates are interleaved
|
||||
with the shift register, whereas the latter combines several shift register taps
|
||||
and reduces them with an XNOR tree. For more information, refer to
|
||||
[this page](https://en.wikipedia.org/wiki/Linear-feedback_shift_register). Both
|
||||
LFSR flavors have maximal period (`2^LfsrDw - 1`). The recommendation is to use
|
||||
the Galois type and fall back to the Fibonacci type depending on the polynomial
|
||||
width availability in the lookup table (see below).
|
||||
|
||||
|
||||
## Parameters
|
||||
|
||||
Name | type | Description
|
||||
-------------|--------|----------------------------------------------------------
|
||||
LfsrType | string | LFSR form, can be `"GAL_XOR"` or `"FIB_XNOR"`
|
||||
LfsrDw | int | Width of the LFSR
|
||||
EntropyDw | int | Width of the entropy input
|
||||
StateOutDw | int | Width of the LFSR state to be output (`lfsr_q[StateOutDw-1:0]`)
|
||||
DefaultSeed | logic | Initial state of the LFSR, must be nonzero for XOR and non-all-ones for XNOR forms.
|
||||
CustomCoeffs | logic | Custom polynomial coefficients of length LfsrDw.
|
||||
MaxLenSVA | bit | Enables maximum length assertions, use only in sim and FPV.
|
||||
|
||||
## Signal Interfaces
|
||||
|
||||
Name | In/Out | Description
|
||||
---------------------|--------|---------------------------------
|
||||
seed_en_i | input | External seed input enable
|
||||
seed_i[LfsrDw] | input | External seed input
|
||||
lfsr_en_i | input | Lfsr enable
|
||||
entropy_i[EntropyDw] | input | Entropy input
|
||||
state_o[StateOutDw] | output | LFSR state output.
|
||||
|
||||
# Theory of Operations
|
||||
|
||||
```
|
||||
/----------------\
|
||||
seed_en_i | |
|
||||
------------>| lfsr |
|
||||
seed_i | |
|
||||
=====/======>| LfsrDw |
|
||||
[LfsrDw] | LfsrType |
|
||||
lfsr_en_i | EntropyDw |
|
||||
------------>| StateOutDw |
|
||||
entropy_i | DefaultSeed | state_o
|
||||
=====/======>| CustomCoeffs |=====/=======>
|
||||
[EntropyDw] | MaxLenSVA | [StateOutDw]
|
||||
| |
|
||||
\----------------/
|
||||
```
|
||||
|
||||
The LFSR module has an enable input and an additional entropy input that is
|
||||
XOR'ed into the LFSR state (connect to zero if this feature is unused). The
|
||||
state output contains the lower bits of the LFSR state from `StateOutDw-1`
|
||||
downto `0`. As the entropy input may cause the LFSR to jump into its parasitic
|
||||
state (all-zero for XOR, all-ones for XNOR), the LFSR state transition function
|
||||
contains a lockup protection which re-seeds the state with `DefaultSeed` once
|
||||
this condition is detected.
|
||||
|
||||
The LFSR contains an external seed input `seed_i` which can be used to load a
|
||||
custom seed into the LFSR by asserting `seed_en_i`. This operation takes
|
||||
precedence over internal state updates. If the external seed happens to be a
|
||||
parasitic state, the lockup protection feature explained above will reseed the
|
||||
LFSR with the `DefaultSeed` in the next cycle.
|
||||
|
||||
The LFSR coefficients are taken from an internal set of lookup tables with
|
||||
precomputed coefficients. Alternatively, a custom polynomial can be provided
|
||||
using the `Custom` parameter. The lookup tables contain polynomials for both
|
||||
LFSR forms and range from 4bit to 64bit for the Galois form and 3bit to 168bit
|
||||
for the Fibonacci form. The polynomial coefficients have been obtained from
|
||||
[this page](https://users.ece.cmu.edu/~koopman/lfsr/) and
|
||||
[Xilinx application note 52](https://www.xilinx.com/support/documentation/application_notes/xapp052.pdf).
|
||||
The script `./script/get-lfsr-coeffs.py` can be used to download, parse and dump
|
||||
these coefficients in SV format as follows:
|
||||
```
|
||||
$ script/get-lfsr-coeffs.py -o <output_file>
|
||||
```
|
||||
The default is to get the Galois coefficients. If the Fibonacci coefficients
|
||||
are needed, add the `--fib` switch to the above command.
|
||||
|
||||
The implementation of the state transition function of both polynomials have
|
||||
been formally verified. Further, all polynomials up to 34bit in length have been
|
||||
swept through in simulation in order to ensure that they are of
|
||||
maximal-length.
|
106
vendor/lowrisc_ip/prim/doc/prim_packer.md
vendored
Normal file
106
vendor/lowrisc_ip/prim/doc/prim_packer.md
vendored
Normal file
|
@ -0,0 +1,106 @@
|
|||
---
|
||||
title: "Primitive Component: Packer"
|
||||
---
|
||||
|
||||
# Overview
|
||||
|
||||
`prim_packer` is a module that receives partial writes then packs and creates
|
||||
full configurable width writes. It is one of a set of shared primitive modules
|
||||
available for use within OpenTitan as referred to in the Comportability
|
||||
Specification section on shared primitives.
|
||||
|
||||
## Parameters
|
||||
|
||||
Name | type | Description
|
||||
-----|------|-------------
|
||||
InW | int | Input data width
|
||||
OutW | int | Output data width
|
||||
|
||||
## Signal Interfaces
|
||||
|
||||
Name | In/Out | Description
|
||||
-------------|--------|-------------
|
||||
valid_i | input | Input data available.
|
||||
data_i[InW] | input | Input data.
|
||||
mask_i[InW] | input | Input bit mask. Ones in the mask must be contiguous.
|
||||
ready_o | output | Indicates if prim_packer is able to accept data.
|
||||
valid_o | output | Indicates if output data is available.
|
||||
data_o[OutW] | output | Output data.
|
||||
mask_o[OutW] | output | Output bit mask.
|
||||
ready_i | input | Output data can be drained.
|
||||
flush_i | input | Send out stored data and clear state.
|
||||
flush_done_o | output | Indicates flush operation is completed.
|
||||
|
||||
# Theory of Opeations
|
||||
|
||||
```code
|
||||
/----------\
|
||||
valid_i | | valid_o
|
||||
---------->| |--------------->
|
||||
data_i | stacked | data_o
|
||||
=====/====>| register |=======/=======>
|
||||
[InW] | | [OutW]
|
||||
mask_i | | mask_o
|
||||
=====/====>| InW+OutW |=======/=======>
|
||||
ready_o |----------| ready_i
|
||||
<----------| |<---------------
|
||||
| |
|
||||
\----------/
|
||||
```
|
||||
|
||||
`prim_packer` accepts `InW` bits of data and bitmask signals. On a `valid_i`/
|
||||
`ready_o` handshake, `data_i` is stored to internal registers and accumulated
|
||||
until `OutW` data has been gathered. In the normal case, `mask_o` will be a
|
||||
full width write (`{OutW{1'b1}}`). However, when `flush_i` is asserted,
|
||||
`prim_packer` attempts to drain out all remaining data in the internal
|
||||
storage. In this case, `mask_o` might be partial.
|
||||
|
||||
The internal register size is `InW + OutW` bits to safely store the incoming
|
||||
data and send outgoing data to the `data_o` port.
|
||||
|
||||
|
||||
{{< wavejson >}}
|
||||
{ signal: [
|
||||
{ name: 'valid_i', wave: '01.01......0.'},
|
||||
{ name: 'data_i[3:0]', wave: 'x==x===.===x.', data:'0h 1h 2h 3h 4h 5h 6h 7h'},
|
||||
{ name: 'mask_i[3:0]', wave: 'x==x===.===x.', data:'Fh Fh Fh Fh Fh Fh Ch Ch'},
|
||||
{ name: 'ready_o', wave: '1.....01.....'},
|
||||
{ name: 'valid_o', wave: '0.10101..0.10'},
|
||||
{ name: 'data_o[5:0]', wave: 'x.=x=x=.=x.=x', data:'10h 08h 03h 15h 05h'},
|
||||
{ name: 'mask_o[5:0]', wave: 'x.=x=x=.=x.=x', data:'3Fh 3Fh 3Fh 3Fh 0Fh '},
|
||||
{ name: 'ready_i', wave: '1.....01.....'},
|
||||
{ name: 'flush_i', wave: '0..........10'},
|
||||
{ name: 'flush_done_o', wave: '0..........10'},
|
||||
],
|
||||
|
||||
head:{
|
||||
text: 'prim_packer',
|
||||
tick: ['0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ']
|
||||
}
|
||||
}
|
||||
{{< /wavejson >}}
|
||||
|
||||
The above waveform shows the case of InW := 4 and OutW := 6. After the first
|
||||
transaction, `prim_packer` has `0h` in the storage. When the second `valid_i`
|
||||
is asserted, it combines `0h` and incoming data `1h` and creates output `10h`
|
||||
(`6'b01_0000`). The remaining `2'b00` is put into the internal storage from
|
||||
`data_i[3:2]`. The next transaction combines this and input data `2h` to create
|
||||
`6'b00_1000`.
|
||||
|
||||
`prim_packer` deasserts `ready_o` to indicate it cannot accept further data.
|
||||
`ready_o` is deasserted when `ready_i` is deasserted and there is insufficient
|
||||
internal storage available to store incoming data, as shown in cycle 6 above.
|
||||
|
||||
At cycle 9 and 10, `mask_i` is used to only load 2 bits of data into the packer
|
||||
each cycle. This is to show how the packer allows misaligned writes (smaller
|
||||
than `InW`) to be packed together.
|
||||
|
||||
At the end of the sequence, `flush_i` is asserted, and the remaining data is
|
||||
drained. In this case, `mask_o` isn't full to indicate only partial data is
|
||||
available (`6'b00_1111`). `flush_done_o` is asserted as soon as the remaining
|
||||
data is drained.
|
||||
|
||||
`prim_packer` only supports packing to the right. To use `prim_packer` in a
|
||||
design requiring packing to the left (filling MSB first), the design needs to
|
||||
reverse the bit order (and in some cases, the byte order) before pushing to the
|
||||
packer, then reverse the data output.
|
70
vendor/lowrisc_ip/prim/doc/prim_present.md
vendored
Normal file
70
vendor/lowrisc_ip/prim/doc/prim_present.md
vendored
Normal file
|
@ -0,0 +1,70 @@
|
|||
---
|
||||
title: "Primitive Component: PRESENT Scrambler"
|
||||
---
|
||||
|
||||
# Overview
|
||||
|
||||
`prim_present` is an (unhardened) implementation of the encryption pass of the [64bit PRESENT block cipher](https://en.wikipedia.org/wiki/PRESENT).
|
||||
It is a fully unrolled combinational implementation that supports both key lengths specified in the paper (80bit and 128bit).
|
||||
Further, the number of rounds is fully configurable, and the primitive supports a 32bit block cipher flavor which is not specified in the original paper.
|
||||
|
||||
It should be noted, however, that reduced-round and/or 32bit versions **are not secure** and must not be used in a setting where cryptographic cipher strength is required.
|
||||
I.e., this primitive is only intended to be used as a lightweight data scrambling device.
|
||||
|
||||
## Parameters
|
||||
|
||||
Name | type | Description
|
||||
-------------|--------|----------------------------------------------------------
|
||||
DataWidth | int | Block size, can be 32 or 64
|
||||
KeyWidth | int | Key size, can be 64, 80 or 128
|
||||
NumRounds | int | Number of PRESENT rounds, has to be greater than 0
|
||||
|
||||
## Signal Interfaces
|
||||
|
||||
Name | In/Out | Description
|
||||
-------------|--------|---------------------------------
|
||||
data_i | input | Plaintext input
|
||||
key_i | input | Key input
|
||||
data_o | output | Output of the ciphertext
|
||||
|
||||
# Theory of Operations
|
||||
|
||||
```
|
||||
/---------------\
|
||||
| |
|
||||
| PRESENT |
|
||||
key_i | |
|
||||
=====/======>| DataWidth |
|
||||
[KeyWidth] | KeyWidth |
|
||||
| NumRounds |
|
||||
data_i | | data_o
|
||||
=====/======>| |=====/=======>
|
||||
[DataWidth] | | [DataWidth]
|
||||
| |
|
||||
\---------------/
|
||||
```
|
||||
|
||||
The PRESENT module is fully unrolled and combinational, meaning that it does not have any clock, reset or handshaking inputs.
|
||||
The only inputs are the key and the plaintext, and the only output is the ciphertext.
|
||||
|
||||
The internal construction follows the the algorithm described in the original [paper](http://www.lightweightcrypto.org/present/present_ches2007.pdf).
|
||||
The block size is 64bit and the key size can be either 80bit or 128bit, depending on the security requirements.
|
||||
In its original formulation, this cipher has 31 rounds comprised of an XOR operation with a round key, followed by the application of an s-box and a permutation layer:
|
||||
|
||||
```c++
|
||||
|
||||
round_keys = key_derivation(key_i);
|
||||
|
||||
state = data_i;
|
||||
|
||||
for (int i=1; i < 32; i++) {
|
||||
state = state ^ round_keys[i];
|
||||
state = sbox4_layer(state);
|
||||
state = perm_layer(state);
|
||||
}
|
||||
|
||||
data_o = state ^ round_keys[32];
|
||||
```
|
||||
|
||||
The reduced 32bit block-size variant implemented is non-standard and should only be used for scrambling purposes, since it **is not secure**.
|
||||
It leverages the same crypto primitives and key derivation functions as the 64bit variant, with the difference that the permutation layer is formulated for 32 instead of 64 elements.
|
112
vendor/lowrisc_ip/prim/doc/prim_prince.md
vendored
Normal file
112
vendor/lowrisc_ip/prim/doc/prim_prince.md
vendored
Normal file
|
@ -0,0 +1,112 @@
|
|||
---
|
||||
title: "Primitive Component: PRINCE Scrambler"
|
||||
---
|
||||
|
||||
# Overview
|
||||
|
||||
`prim_prince` is an (unhardened) implementation of the [64bit PRINCE block cipher](https://en.wikipedia.org/wiki/Prince_(cipher)).
|
||||
It is a fully unrolled combinational implementation with a configurable number of rounds.
|
||||
Due to the mirrored construction of this cipher, the same circuit can be used for encryption and decryption, as described below.
|
||||
Further, the primitive supports a 32bit block cipher flavor which is not specified in the original paper.
|
||||
|
||||
It should be noted, however, that reduced-round and/or 32bit versions **are not secure** and must not be used in a setting where cryptographic cipher strength is required.
|
||||
I.e., this primitive is only intended to be used as a lightweight data scrambling device.
|
||||
|
||||
This [paper](https://csrc.nist.gov/csrc/media/events/lightweight-cryptography-workshop-2015/documents/papers/session7-maene-paper.pdf) compares several lightweight ciphers, where PRINCE has been found to be the fastest candidate with the lowest circuit complexity among the algorithms compared.
|
||||
|
||||
## Parameters
|
||||
|
||||
Name | type | Description
|
||||
---------------|--------|----------------------------------------------------------
|
||||
DataWidth | int | Block size, can be 32 or 64.
|
||||
KeyWidth | int | Key size, can be 64 for block size 32, or 128 for block size 64
|
||||
NumRounds | int | Half the number of the reflected PRINCE rounds. Can range from 1 to 5. The effective number of non-linear layers is 2 + 2 * NumRounds.
|
||||
UseOldKeySched | bit | If set to 1, fall back to the original keyschedule (not recommended). Defaults to 0.
|
||||
|
||||
## Signal Interfaces
|
||||
|
||||
Name | In/Out | Description
|
||||
-------------|--------|---------------------------------
|
||||
data_i | input | Plaintext input
|
||||
key_i | input | Key input
|
||||
dec_i | input | Assert for decryption
|
||||
data_o | output | Output of the ciphertext
|
||||
|
||||
# Theory of Operations
|
||||
|
||||
```
|
||||
/----------------\
|
||||
dec_i | |
|
||||
------------>| PRINCE |
|
||||
key_i | |
|
||||
=====/======>| DataWidth |
|
||||
[KeyWidth] | KeyWidth |
|
||||
| NumRounds |
|
||||
data_i | UseOldKeySched | data_o
|
||||
=====/======>| |=====/=======>
|
||||
[DataWidth] | | [DataWidth]
|
||||
| |
|
||||
\----------------/
|
||||
```
|
||||
|
||||
The PRINCE module is fully unrolled and combinational, meaning that it does not have any clock, reset or handshaking inputs.
|
||||
The only inputs are the key and the plaintext, and the only output is the ciphertext.
|
||||
|
||||
The internal construction follows the the algorithm described in the original [paper](https://eprint.iacr.org/2012/529.pdf).
|
||||
The block size is 64bit and the key size is 128bit.
|
||||
In its original formulation, this cipher has 11 rounds (but 12 non-linear layers), which are arranged in a mirrored structure, which allows the same circuit to be used for encryption and decryption with a lightweight tweak applied to the key:
|
||||
|
||||
```c++
|
||||
k0, k0_prime, k1 = key_derivation(key_i, dec_i);
|
||||
|
||||
// decryption mode
|
||||
if (dec_i) {
|
||||
swap(k0, k0_prime);
|
||||
k1 ^= ALPHA_CONSTANT;
|
||||
}
|
||||
|
||||
state = data_i ^ k0;
|
||||
|
||||
state ^= k1;
|
||||
state ^= ROUND_CONSTANT[0];
|
||||
|
||||
// forward pass
|
||||
for (int i=1; i < 6; i++) {
|
||||
state = sbox4_layer(state);
|
||||
state = mult_layer(state);
|
||||
state = shiftrows_layer(state);
|
||||
state ^= ROUND_CONSTANT[i]
|
||||
data_state ^= (k & 0x1) ? k0 : k1;
|
||||
}
|
||||
|
||||
// middle part
|
||||
state = sbox4_layer(state);
|
||||
state = mult_layer(state);
|
||||
state = sbox4_inverse_layer(state);
|
||||
|
||||
// reverse pass
|
||||
for (int i=6; i < 11; i++) {
|
||||
data_state ^= (k & 0x1) ? k1 : k0;
|
||||
state ^= ROUND_CONSTANT[i]
|
||||
state = shiftrows_inverse_layer(state);
|
||||
state = mult_layer(state);
|
||||
state = sbox4_inverse_layer(state);
|
||||
}
|
||||
|
||||
state ^= ROUND_CONSTANT[11];
|
||||
state ^= k1;
|
||||
|
||||
data_o = state ^ k0_prime;
|
||||
```
|
||||
The multiplicative layer is an involution, meaning that it is its own inverse and it can hence be used in the reverse pass without inversion.
|
||||
|
||||
It should be noted that the actual choice of the `ALPHA_CONSTANT` used in the key tweak can have security impacts as detailed in [this paper](https://eprint.iacr.org/2015/372.pdf).
|
||||
The constant chosen by the designers of PRINCE does not have these issues - but proper care should be taken if it is decided to modify this constant.
|
||||
Also, [this paper](https://eprint.iacr.org/2014/656.pdf) proposes an improved key schedule to fend against attacks on the FX structure of PRINCE (see Appendix C), and this improvement has been incorporated in this design.
|
||||
The improvement involves alternating the keys `k0` and `k1` between rounds, as opposed to always using the same key `k1`.
|
||||
|
||||
|
||||
The reduced 32bit variant mentioned above and all reduced round variants are non-standard and must only be used for scrambling purposes, since they **are not secure**.
|
||||
The 32bit variant leverages the same crypto primitives and key derivation functions as the 64bit variant, with the difference that the multiplication matrix is only comprised of the first two block diagonal submatrices (^M0 and ^M1 in the paper), and the shiftrows operation does not operate on nibbles but pairs of 2 bits instead.
|
||||
|
||||
|
46
vendor/lowrisc_ip/prim/dv/Makefile
vendored
Normal file
46
vendor/lowrisc_ip/prim/dv/Makefile
vendored
Normal file
|
@ -0,0 +1,46 @@
|
|||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
# Entry point test Makefile for building and running tests.
|
||||
# These are generic set of option groups that apply to all testbenches.
|
||||
# This flow requires the following options to be set:
|
||||
# DV_DIR - current dv directory that contains the test Makefile
|
||||
# DUT_TOP - top level dut module name
|
||||
# TB_TOP - top level tb module name
|
||||
# DOTF - .f file used for compilation
|
||||
# COMPILE_KEY - compile option set
|
||||
# TEST_NAME - name of the test to run - this is supplied on the command line
|
||||
DV_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
|
||||
COMPILE_KEY ?= default
|
||||
|
||||
##########################################################
|
||||
# A D D I N D I V I D U A L T E S T S B E L O W #
|
||||
##########################################################
|
||||
|
||||
ifeq (${TEST_NAME},prim_lfsr_gal_xor)
|
||||
export DUT_TOP := prim_lfsr
|
||||
export TB_TOP := prim_lfsr_tb
|
||||
FUSESOC_CORE := lowrisc:dv:prim_lfsr_sim:0.1
|
||||
COMPILE_KEY := gal_xor
|
||||
endif
|
||||
|
||||
ifeq (${TEST_NAME},prim_lfsr_fib_xnor)
|
||||
export DUT_TOP := prim_lfsr
|
||||
export TB_TOP := prim_lfsr_tb
|
||||
FUSESOC_CORE := lowrisc:dv:prim_lfsr_sim:0.1
|
||||
COMPILE_KEY := fib_xnor
|
||||
endif
|
||||
|
||||
ifeq (${COMPILE_KEY},gal_xor)
|
||||
BUILD_OPTS := +define+LFSR_TYPE="\"GAL_XOR\""+MAX_LFSR_DW=28+MIN_LFSR_DW=4
|
||||
endif
|
||||
|
||||
ifeq (${COMPILE_KEY},fib_xnor)
|
||||
BUILD_OPTS := +define+LFSR_TYPE="\"FIB_XNOR\""+MAX_LFSR_DW=28+MIN_LFSR_DW=3
|
||||
endif
|
||||
|
||||
####################################
|
||||
# Include the tool Makefile below #
|
||||
# Dont add anything else below it! #
|
||||
####################################
|
||||
include ${DV_DIR}/../../../dv/tools/Makefile
|
28
vendor/lowrisc_ip/prim/dv/prim_lfsr_sim.core
vendored
Normal file
28
vendor/lowrisc_ip/prim/dv/prim_lfsr_sim.core
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
CAPI=2:
|
||||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
name: "lowrisc:dv:prim_lfsr_sim:0.1"
|
||||
description: "LFSR DV sim target"
|
||||
filesets:
|
||||
files_rtl:
|
||||
depend:
|
||||
- lowrisc:prim:all
|
||||
file_type: systemVerilogSource
|
||||
|
||||
files_dv:
|
||||
depend:
|
||||
- lowrisc:dv:dv_utils
|
||||
- lowrisc:dv:common_ifs
|
||||
files:
|
||||
- tb/prim_lfsr_tb.sv
|
||||
- tb/prim_lfsr_bind.sv
|
||||
file_type: systemVerilogSource
|
||||
|
||||
targets:
|
||||
sim:
|
||||
toplevel: prim_lfsr_tb
|
||||
filesets:
|
||||
- files_rtl
|
||||
- files_dv
|
||||
default_tool: vcs
|
9
vendor/lowrisc_ip/prim/dv/tb/prim_lfsr_bind.sv
vendored
Normal file
9
vendor/lowrisc_ip/prim/dv/tb/prim_lfsr_bind.sv
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
module prim_lfsr_bind;
|
||||
|
||||
// nothing to bind here yet
|
||||
|
||||
endmodule : prim_lfsr_bind
|
149
vendor/lowrisc_ip/prim/dv/tb/prim_lfsr_tb.sv
vendored
Normal file
149
vendor/lowrisc_ip/prim/dv/tb/prim_lfsr_tb.sv
vendored
Normal file
|
@ -0,0 +1,149 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// Testbench module for prim_lfsr, sweeps through all implementations
|
||||
// within a certain range to check whether they are max length.
|
||||
|
||||
module prim_lfsr_tb;
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// config
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
// this can be overriden on the command line
|
||||
// supported types are GAL_XOR, FIB_XNOR
|
||||
`ifdef LFSR_TYPE
|
||||
localparam string LfsrType = `LFSR_TYPE;
|
||||
`else
|
||||
localparam string LfsrType = "GAL_XOR";
|
||||
`endif
|
||||
`ifdef MIN_LFSR_DW
|
||||
localparam int unsigned MinLfsrDw = `MIN_LFSR_DW;
|
||||
`else
|
||||
localparam int unsigned MinLfsrDw = 4;
|
||||
`endif
|
||||
`ifdef MAX_LFSR_DW
|
||||
localparam int unsigned MaxLfsrDw = `MAX_LFSR_DW;
|
||||
`else
|
||||
localparam int unsigned MaxLfsrDw = 32;
|
||||
`endif
|
||||
|
||||
// leave this constant
|
||||
localparam logic SEED = 1'b1;
|
||||
|
||||
localparam time ClkPeriod = 10000;
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// clock
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
wire clk, rst_n;
|
||||
|
||||
clk_rst_if main_clk (
|
||||
.clk,
|
||||
.rst_n
|
||||
);
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// DUTs
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
logic [MaxLfsrDw:0] lfsr_en, err;
|
||||
logic [MaxLfsrDw:MinLfsrDw][MaxLfsrDw-1:0] state_out;
|
||||
logic [MaxLfsrDw:MinLfsrDw][MaxLfsrDw-1:0] lfsr_periods;
|
||||
|
||||
for (genvar k = MinLfsrDw; k <= MaxLfsrDw; k++) begin : gen_duts
|
||||
prim_lfsr #(
|
||||
.LfsrType ( LfsrType ),
|
||||
.LfsrDw ( k ),
|
||||
.EntropyDw ( 1 ),
|
||||
.StateOutDw ( k ),
|
||||
.DefaultSeed ( k'(SEED) ),
|
||||
// enable internal max length check
|
||||
.MaxLenSVA ( 1'b1 )
|
||||
) i_prim_lfsr (
|
||||
.clk_i ( clk ),
|
||||
.rst_ni ( rst_n ),
|
||||
.seed_en_i ( 1'b0 ),
|
||||
.seed_i ( '0 ),
|
||||
.lfsr_en_i ( lfsr_en[k] ),
|
||||
.entropy_i ( 1'b0 ),
|
||||
.state_o ( state_out[k][k-1:0] )
|
||||
);
|
||||
|
||||
if (k < MaxLfsrDw) begin : gen_tie_off
|
||||
assign state_out[k][MaxLfsrDw-1:k] = '0;
|
||||
end
|
||||
|
||||
// calculate period of LFSR:
|
||||
assign lfsr_periods[k] = MaxLfsrDw'({{(k-1){1'b1}}, 1'b0});
|
||||
end
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// stimuli application / response checking
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
initial begin : p_stimuli
|
||||
lfsr_en = '0;
|
||||
err = '0;
|
||||
|
||||
main_clk.set_period_ns(ClkPeriod);
|
||||
main_clk.set_active();
|
||||
main_clk.apply_reset();
|
||||
|
||||
$display("LFSR maxlen test started for %s (%0d bit to %0d bit).",
|
||||
LfsrType, MinLfsrDw, MaxLfsrDw);
|
||||
|
||||
main_clk.wait_clks(10);
|
||||
|
||||
// enable all LFSRs
|
||||
lfsr_en = '1;
|
||||
|
||||
$display("Running for 2**%0d-1 cycles...", MaxLfsrDw);
|
||||
for (longint unsigned k = 0; k <= lfsr_periods[MaxLfsrDw]; k++ ) begin
|
||||
|
||||
main_clk.wait_clks(1);
|
||||
|
||||
for (int unsigned j = MinLfsrDw; j <= MaxLfsrDw; j++) begin
|
||||
// check if we reached the initial state again
|
||||
if (state_out[j] == MaxLfsrDw'(SEED) && lfsr_en[j]) begin
|
||||
// $display("cycle: %d -- lfsr: %d -- %x ?= %x, %x",
|
||||
// k, j, state_out[j], SEED, lfsr_en);
|
||||
lfsr_en[j] = 1'b0;
|
||||
// we expect this to occur only after the maximum length period
|
||||
if (lfsr_periods[j] == k) begin
|
||||
$display("Maxlen check for LFSR %0d succeeded!", j);
|
||||
end else begin
|
||||
err[j] = 1'b1;
|
||||
$error("Error LFSR %0d is not maximal length!", j);
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
main_clk.wait_clks(10);
|
||||
|
||||
for (int unsigned j = MinLfsrDw; j <= MaxLfsrDw; j++) begin
|
||||
if (lfsr_en[j]) begin
|
||||
$error("Error LFSR %0d never got back to initial state!", j);
|
||||
err[j] = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
if (!err) begin
|
||||
$display("All LFSRs from %0d bit to %0d have maximum length!",
|
||||
MinLfsrDw, MaxLfsrDw);
|
||||
// signature for makefile
|
||||
$display("TEST PASSED CHECKS");
|
||||
end else begin
|
||||
$display("One or more checks have failed!");
|
||||
// signature for makefile
|
||||
$display("TEST FAILED CHECKS");
|
||||
end
|
||||
|
||||
$finish();
|
||||
end
|
||||
|
||||
|
||||
endmodule : prim_lfsr_tb
|
28
vendor/lowrisc_ip/prim/fpv/prim_alert_rxtx_async_fpv.core
vendored
Normal file
28
vendor/lowrisc_ip/prim/fpv/prim_alert_rxtx_async_fpv.core
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
CAPI=2:
|
||||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
name: "lowrisc:fpv:prim_alert_rxtx_async_fpv:0.1"
|
||||
description: "ALERT_HANDLER rxtx async FPV target"
|
||||
filesets:
|
||||
files_formal:
|
||||
depend:
|
||||
- lowrisc:prim:all
|
||||
files:
|
||||
- vip/prim_alert_rxtx_async_assert_fpv.sv
|
||||
- tb/prim_alert_rxtx_async_fpv.sv
|
||||
- tb/prim_alert_rxtx_async_bind_fpv.sv
|
||||
file_type: systemVerilogSource
|
||||
|
||||
targets:
|
||||
default: &default_target
|
||||
# note, this setting is just used
|
||||
# to generate a file list for jg
|
||||
default_tool: icarus
|
||||
filesets:
|
||||
- files_formal
|
||||
toplevel:
|
||||
- prim_alert_rxtx_async_fpv
|
||||
|
||||
formal:
|
||||
<<: *default_target
|
28
vendor/lowrisc_ip/prim/fpv/prim_alert_rxtx_fpv.core
vendored
Normal file
28
vendor/lowrisc_ip/prim/fpv/prim_alert_rxtx_fpv.core
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
CAPI=2:
|
||||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
name: "lowrisc:fpv:prim_alert_rxtx_fpv:0.1"
|
||||
description: "ALERT_HANDLER FPV target"
|
||||
filesets:
|
||||
files_formal:
|
||||
depend:
|
||||
- lowrisc:prim:all
|
||||
files:
|
||||
- vip/prim_alert_rxtx_assert_fpv.sv
|
||||
- tb/prim_alert_rxtx_fpv.sv
|
||||
- tb/prim_alert_rxtx_bind_fpv.sv
|
||||
file_type: systemVerilogSource
|
||||
|
||||
targets:
|
||||
default: &default_target
|
||||
# note, this setting is just used
|
||||
# to generate a file list for jg
|
||||
default_tool: icarus
|
||||
filesets:
|
||||
- files_formal
|
||||
toplevel:
|
||||
- prim_alert_rxtx_fpv
|
||||
|
||||
formal:
|
||||
<<: *default_target
|
28
vendor/lowrisc_ip/prim/fpv/prim_arbiter_ppc_fpv.core
vendored
Normal file
28
vendor/lowrisc_ip/prim/fpv/prim_arbiter_ppc_fpv.core
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
CAPI=2:
|
||||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
name: "lowrisc:fpv:prim_arbiter_ppc_fpv:0.1"
|
||||
description: "prim_arbiter_ppc FPV target"
|
||||
filesets:
|
||||
files_formal:
|
||||
depend:
|
||||
- lowrisc:prim:all
|
||||
# TODO: add more dependencies here if needed
|
||||
files:
|
||||
- vip/prim_arbiter_ppc_assert_fpv.sv
|
||||
- tb/prim_arbiter_ppc_bind_fpv.sv
|
||||
- tb/prim_arbiter_ppc_fpv.sv
|
||||
file_type: systemVerilogSource
|
||||
|
||||
targets:
|
||||
default: &default_target
|
||||
# note, this setting is just used
|
||||
# to generate a file list for jg
|
||||
default_tool: icarus
|
||||
filesets:
|
||||
- files_formal
|
||||
toplevel: prim_arbiter_ppc_fpv
|
||||
|
||||
formal:
|
||||
<<: *default_target
|
28
vendor/lowrisc_ip/prim/fpv/prim_arbiter_tree_fpv.core
vendored
Normal file
28
vendor/lowrisc_ip/prim/fpv/prim_arbiter_tree_fpv.core
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
CAPI=2:
|
||||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
name: "lowrisc:fpv:prim_arbiter_tree_fpv:0.1"
|
||||
description: "prim_arbiter_tree FPV target"
|
||||
filesets:
|
||||
files_formal:
|
||||
depend:
|
||||
- lowrisc:prim:all
|
||||
# TODO: add more dependencies here if needed
|
||||
files:
|
||||
- vip/prim_arbiter_tree_assert_fpv.sv
|
||||
- tb/prim_arbiter_tree_bind_fpv.sv
|
||||
- tb/prim_arbiter_tree_fpv.sv
|
||||
file_type: systemVerilogSource
|
||||
|
||||
targets:
|
||||
default: &default_target
|
||||
# note, this setting is just used
|
||||
# to generate a file list for jg
|
||||
default_tool: icarus
|
||||
filesets:
|
||||
- files_formal
|
||||
toplevel: prim_arbiter_tree_fpv
|
||||
|
||||
formal:
|
||||
<<: *default_target
|
28
vendor/lowrisc_ip/prim/fpv/prim_esc_rxtx_fpv.core
vendored
Normal file
28
vendor/lowrisc_ip/prim/fpv/prim_esc_rxtx_fpv.core
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
CAPI=2:
|
||||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
name: "lowrisc:fpv:prim_esc_rxtx_fpv:0.1"
|
||||
description: "ALERT_HANDLER FPV target"
|
||||
filesets:
|
||||
files_formal:
|
||||
depend:
|
||||
- lowrisc:prim:all
|
||||
files:
|
||||
- vip/prim_esc_rxtx_assert_fpv.sv
|
||||
- tb/prim_esc_rxtx_bind_fpv.sv
|
||||
- tb/prim_esc_rxtx_fpv.sv
|
||||
file_type: systemVerilogSource
|
||||
|
||||
targets:
|
||||
default: &default_target
|
||||
# note, this setting is just used
|
||||
# to generate a file list for jg
|
||||
formal: icarus
|
||||
filesets:
|
||||
- files_formal
|
||||
toplevel:
|
||||
- prim_esc_rxtx_fpv
|
||||
|
||||
formal:
|
||||
<<: *default_target
|
27
vendor/lowrisc_ip/prim/fpv/prim_fifo_sync_fpv.core
vendored
Normal file
27
vendor/lowrisc_ip/prim/fpv/prim_fifo_sync_fpv.core
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
CAPI=2:
|
||||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
name: "lowrisc:fpv:prim_fifo_sync_fpv:0.1"
|
||||
description: "prim_fifo_sync FPV target"
|
||||
filesets:
|
||||
files_formal:
|
||||
depend:
|
||||
- lowrisc:prim:all
|
||||
files:
|
||||
- vip/prim_fifo_sync_assert_fpv.sv
|
||||
- tb/prim_fifo_sync_bind_fpv.sv
|
||||
- tb/prim_fifo_sync_fpv.sv
|
||||
file_type: systemVerilogSource
|
||||
|
||||
targets:
|
||||
default: &default_target
|
||||
# note, this setting is just used
|
||||
# to generate a file list for jg
|
||||
default_tool: icarus
|
||||
filesets:
|
||||
- files_formal
|
||||
toplevel: prim_fifo_sync_fpv
|
||||
|
||||
formal:
|
||||
<<: *default_target
|
23
vendor/lowrisc_ip/prim/fpv/prim_keccak_fpv.core
vendored
Normal file
23
vendor/lowrisc_ip/prim/fpv/prim_keccak_fpv.core
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
CAPI=2:
|
||||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
name: "lowrisc:fpv:prim_keccak_fpv:0.1"
|
||||
description: "Keccak_f FPV target"
|
||||
filesets:
|
||||
files_fpv:
|
||||
depend:
|
||||
- lowrisc:prim:all
|
||||
files:
|
||||
- tb/prim_keccak_fpv.sv
|
||||
file_type: systemVerilogSource
|
||||
|
||||
targets:
|
||||
default:
|
||||
# note, this setting is just used
|
||||
# to generate a file list for jg
|
||||
default_tool: icarus
|
||||
filesets:
|
||||
- files_fpv
|
||||
toplevel:
|
||||
- prim_keccak_fpv
|
26
vendor/lowrisc_ip/prim/fpv/prim_lfsr_fpv.core
vendored
Normal file
26
vendor/lowrisc_ip/prim/fpv/prim_lfsr_fpv.core
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
CAPI=2:
|
||||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
name: "lowrisc:fpv:prim_lfsr_fpv:0.1"
|
||||
description: "ALERT_HANDLER FPV target"
|
||||
filesets:
|
||||
files_formal:
|
||||
depend:
|
||||
- lowrisc:prim:all
|
||||
files:
|
||||
- tb/prim_lfsr_fpv.sv
|
||||
file_type: systemVerilogSource
|
||||
|
||||
targets:
|
||||
default: &default_target
|
||||
# note, this setting is just used
|
||||
# to generate a file list for jg
|
||||
default_tool: icarus
|
||||
filesets:
|
||||
- files_formal
|
||||
toplevel:
|
||||
- prim_lfsr_fpv
|
||||
|
||||
formal:
|
||||
<<: *default_target
|
28
vendor/lowrisc_ip/prim/fpv/tb/prim_alert_rxtx_async_bind_fpv.sv
vendored
Normal file
28
vendor/lowrisc_ip/prim/fpv/tb/prim_alert_rxtx_async_bind_fpv.sv
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
module prim_alert_rxtx_async_bind_fpv;
|
||||
|
||||
bind prim_alert_rxtx_async_fpv
|
||||
prim_alert_rxtx_async_assert_fpv prim_alert_rxtx_async_assert_fpv (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
.ping_err_pi,
|
||||
.ping_err_ni,
|
||||
.ping_skew_i,
|
||||
.ack_err_pi,
|
||||
.ack_err_ni,
|
||||
.ack_skew_i,
|
||||
.alert_err_pi,
|
||||
.alert_err_ni,
|
||||
.alert_skew_i,
|
||||
.alert_i,
|
||||
.ping_en_i,
|
||||
.ping_ok_o,
|
||||
.integ_fail_o,
|
||||
.alert_o
|
||||
);
|
||||
|
||||
endmodule : prim_alert_rxtx_async_bind_fpv
|
109
vendor/lowrisc_ip/prim/fpv/tb/prim_alert_rxtx_async_fpv.sv
vendored
Normal file
109
vendor/lowrisc_ip/prim/fpv/tb/prim_alert_rxtx_async_fpv.sv
vendored
Normal file
|
@ -0,0 +1,109 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// Testbench module for alert sender/receiver pair. Intended to use with
|
||||
// a formal tool.
|
||||
|
||||
module prim_alert_rxtx_async_fpv
|
||||
import prim_alert_pkg::*;
|
||||
import prim_esc_pkg::*;
|
||||
(
|
||||
input clk_i,
|
||||
input rst_ni,
|
||||
// for sigint error and skew injection only
|
||||
input ping_err_pi,
|
||||
input ping_err_ni,
|
||||
input [1:0] ping_skew_i,
|
||||
input ack_err_pi,
|
||||
input ack_err_ni,
|
||||
input [1:0] ack_skew_i,
|
||||
input alert_err_pi,
|
||||
input alert_err_ni,
|
||||
input [1:0] alert_skew_i,
|
||||
// normal I/Os
|
||||
input alert_i,
|
||||
input ping_en_i,
|
||||
output logic ping_ok_o,
|
||||
output logic integ_fail_o,
|
||||
output logic alert_o
|
||||
);
|
||||
|
||||
// asynchronous case
|
||||
localparam bit AsyncOn = 1'b1;
|
||||
|
||||
logic ping_pd;
|
||||
logic ping_nd;
|
||||
logic ack_pd;
|
||||
logic ack_nd;
|
||||
logic alert_pd;
|
||||
logic alert_nd;
|
||||
|
||||
alert_rx_t alert_rx_out, alert_rx_in;
|
||||
alert_tx_t alert_tx_out, alert_tx_in;
|
||||
|
||||
// for the purposes of FPV, we currently emulate the asynchronous transition
|
||||
// only in terms of the skew it may introduce (which is limited to +- 1 cycle)
|
||||
logic [1:0] ping_pq;
|
||||
logic [1:0] ping_nq;
|
||||
logic [1:0] ack_pq;
|
||||
logic [1:0] ack_nq;
|
||||
logic [1:0] alert_pq;
|
||||
logic [1:0] alert_nq;
|
||||
|
||||
assign ping_pd = alert_rx_out.ping_p;
|
||||
assign ping_nd = alert_rx_out.ping_n;
|
||||
assign ack_pd = alert_rx_out.ack_p;
|
||||
assign ack_nd = alert_rx_out.ack_n;
|
||||
assign alert_rx_in.ping_p = ping_pq[ping_skew_i[0]] ^ ping_err_pi;
|
||||
assign alert_rx_in.ping_n = ping_nq[ping_skew_i[1]] ^ ping_err_ni;
|
||||
assign alert_rx_in.ack_p = ack_pq[ack_skew_i[0]] ^ ack_err_pi;
|
||||
assign alert_rx_in.ack_n = ack_nq[ack_skew_i[1]] ^ ack_err_ni;
|
||||
|
||||
assign alert_pd = alert_tx_out.alert_p;
|
||||
assign alert_nd = alert_tx_out.alert_n;
|
||||
assign alert_tx_in.alert_p = alert_pq[alert_skew_i[0]] ^ alert_err_pi;
|
||||
assign alert_tx_in.alert_n = alert_nq[alert_skew_i[1]] ^ alert_err_ni;
|
||||
|
||||
prim_alert_sender #(
|
||||
.AsyncOn ( AsyncOn )
|
||||
) i_prim_alert_sender (
|
||||
.clk_i ,
|
||||
.rst_ni ,
|
||||
.alert_i ,
|
||||
.alert_rx_i ( alert_rx_in ),
|
||||
.alert_tx_o ( alert_tx_out )
|
||||
);
|
||||
|
||||
prim_alert_receiver #(
|
||||
.AsyncOn ( AsyncOn )
|
||||
) i_prim_alert_receiver (
|
||||
.clk_i ,
|
||||
.rst_ni ,
|
||||
.ping_en_i ,
|
||||
.ping_ok_o ,
|
||||
.integ_fail_o ,
|
||||
.alert_o ,
|
||||
.alert_rx_o ( alert_rx_out ),
|
||||
.alert_tx_i ( alert_tx_in )
|
||||
);
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : p_skew_delay
|
||||
if (!rst_ni) begin
|
||||
ping_pq <= '0;
|
||||
ping_nq <= '1;
|
||||
ack_pq <= '0;
|
||||
ack_nq <= '1;
|
||||
alert_pq <= '0;
|
||||
alert_nq <= '1;
|
||||
end else begin
|
||||
ping_pq <= {ping_pq [$high(ping_pq )-1:0], ping_pd};
|
||||
ping_nq <= {ping_nq [$high(ping_nq )-1:0], ping_nd};
|
||||
ack_pq <= {ack_pq [$high(ack_pq )-1:0], ack_pd};
|
||||
ack_nq <= {ack_nq [$high(ack_nq )-1:0], ack_nd};
|
||||
alert_pq <= {alert_pq[$high(alert_pq)-1:0], alert_pd};
|
||||
alert_nq <= {alert_nq[$high(alert_nq)-1:0], alert_nd};
|
||||
end
|
||||
end
|
||||
|
||||
endmodule : prim_alert_rxtx_async_fpv
|
25
vendor/lowrisc_ip/prim/fpv/tb/prim_alert_rxtx_bind_fpv.sv
vendored
Normal file
25
vendor/lowrisc_ip/prim/fpv/tb/prim_alert_rxtx_bind_fpv.sv
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
module prim_alert_rxtx_bind_fpv;
|
||||
|
||||
bind prim_alert_rxtx_fpv
|
||||
prim_alert_rxtx_assert_fpv prim_alert_rxtx_assert_fpv (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
.ping_err_pi,
|
||||
.ping_err_ni,
|
||||
.ack_err_pi,
|
||||
.ack_err_ni,
|
||||
.alert_err_pi,
|
||||
.alert_err_ni,
|
||||
.alert_i,
|
||||
.ping_en_i,
|
||||
.ping_ok_o,
|
||||
.integ_fail_o,
|
||||
.alert_o
|
||||
);
|
||||
|
||||
endmodule : prim_alert_rxtx_bind_fpv
|
66
vendor/lowrisc_ip/prim/fpv/tb/prim_alert_rxtx_fpv.sv
vendored
Normal file
66
vendor/lowrisc_ip/prim/fpv/tb/prim_alert_rxtx_fpv.sv
vendored
Normal file
|
@ -0,0 +1,66 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// Testbench module for alert sender/receiver pair. Intended to use with
|
||||
// a formal tool.
|
||||
|
||||
module prim_alert_rxtx_fpv
|
||||
import prim_alert_pkg::*;
|
||||
import prim_esc_pkg::*;
|
||||
(
|
||||
input clk_i,
|
||||
input rst_ni,
|
||||
// for sigint error injection only
|
||||
input ping_err_pi,
|
||||
input ping_err_ni,
|
||||
input ack_err_pi,
|
||||
input ack_err_ni,
|
||||
input alert_err_pi,
|
||||
input alert_err_ni,
|
||||
// normal I/Os
|
||||
input alert_i,
|
||||
input ping_en_i,
|
||||
output logic ping_ok_o,
|
||||
output logic integ_fail_o,
|
||||
output logic alert_o
|
||||
);
|
||||
|
||||
// synchronous case
|
||||
localparam bit AsyncOn = 1'b0;
|
||||
|
||||
alert_rx_t alert_rx_out, alert_rx_in;
|
||||
alert_tx_t alert_tx_out, alert_tx_in;
|
||||
|
||||
assign alert_rx_in.ping_p = alert_rx_out.ping_p ^ ping_err_pi;
|
||||
assign alert_rx_in.ping_n = alert_rx_out.ping_n ^ ping_err_ni;
|
||||
assign alert_rx_in.ack_p = alert_rx_out.ack_p ^ ack_err_pi;
|
||||
assign alert_rx_in.ack_n = alert_rx_out.ack_n ^ ack_err_ni;
|
||||
|
||||
assign alert_tx_in.alert_p = alert_tx_out.alert_p ^ alert_err_pi;
|
||||
assign alert_tx_in.alert_n = alert_tx_out.alert_n ^ alert_err_ni;
|
||||
|
||||
prim_alert_sender #(
|
||||
.AsyncOn ( AsyncOn )
|
||||
) i_prim_alert_sender (
|
||||
.clk_i ,
|
||||
.rst_ni ,
|
||||
.alert_i ,
|
||||
.alert_rx_i ( alert_rx_in ),
|
||||
.alert_tx_o ( alert_tx_out )
|
||||
);
|
||||
|
||||
prim_alert_receiver #(
|
||||
.AsyncOn ( AsyncOn )
|
||||
) i_prim_alert_receiver (
|
||||
.clk_i ,
|
||||
.rst_ni ,
|
||||
.ping_en_i ,
|
||||
.ping_ok_o ,
|
||||
.integ_fail_o ,
|
||||
.alert_o ,
|
||||
.alert_rx_o ( alert_rx_out ),
|
||||
.alert_tx_i ( alert_tx_in )
|
||||
);
|
||||
|
||||
endmodule : prim_alert_rxtx_fpv
|
25
vendor/lowrisc_ip/prim/fpv/tb/prim_arbiter_ppc_bind_fpv.sv
vendored
Normal file
25
vendor/lowrisc_ip/prim/fpv/tb/prim_arbiter_ppc_bind_fpv.sv
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
module prim_arbiter_ppc_bind_fpv;
|
||||
|
||||
|
||||
bind prim_arbiter_ppc prim_arbiter_ppc_assert_fpv #(
|
||||
.N(N),
|
||||
.DW(DW)
|
||||
) i_prim_arbiter_ppc_assert_fpv (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
.req_i,
|
||||
.data_i,
|
||||
.gnt_o,
|
||||
.idx_o,
|
||||
.valid_o,
|
||||
.data_o,
|
||||
.ready_i
|
||||
);
|
||||
|
||||
|
||||
endmodule : prim_arbiter_ppc_bind_fpv
|
40
vendor/lowrisc_ip/prim/fpv/tb/prim_arbiter_ppc_fpv.sv
vendored
Normal file
40
vendor/lowrisc_ip/prim/fpv/tb/prim_arbiter_ppc_fpv.sv
vendored
Normal file
|
@ -0,0 +1,40 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// Testbench module for prim_arbiter_ppc.
|
||||
// Intended to be used with a formal tool.
|
||||
|
||||
module prim_arbiter_ppc_fpv #(
|
||||
parameter int unsigned N = 4,
|
||||
parameter int unsigned DW = 32
|
||||
) (
|
||||
input clk_i,
|
||||
input rst_ni,
|
||||
input [N-1:0] req_i,
|
||||
input [DW-1:0]data_i [N],
|
||||
output logic[N-1:0] gnt_o,
|
||||
output logic[$clog2(N)-1:0] idx_o,
|
||||
output logic valid_o,
|
||||
output logic[DW-1:0] data_o,
|
||||
input ready_i
|
||||
);
|
||||
|
||||
|
||||
prim_arbiter_ppc #(
|
||||
.N(N),
|
||||
.DW(DW)
|
||||
) i_prim_arbiter_ppc (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
.req_i,
|
||||
.data_i,
|
||||
.gnt_o,
|
||||
.idx_o,
|
||||
.valid_o,
|
||||
.data_o,
|
||||
.ready_i
|
||||
);
|
||||
|
||||
|
||||
endmodule : prim_arbiter_ppc_fpv
|
26
vendor/lowrisc_ip/prim/fpv/tb/prim_arbiter_tree_bind_fpv.sv
vendored
Normal file
26
vendor/lowrisc_ip/prim/fpv/tb/prim_arbiter_tree_bind_fpv.sv
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
module prim_arbiter_tree_bind_fpv;
|
||||
|
||||
|
||||
bind prim_arbiter_tree prim_arbiter_tree_assert_fpv #(
|
||||
.N(N),
|
||||
.DW(DW),
|
||||
.Lock(Lock)
|
||||
) i_prim_arbiter_tree_assert_fpv (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
.req_i,
|
||||
.data_i,
|
||||
.gnt_o,
|
||||
.idx_o,
|
||||
.valid_o,
|
||||
.data_o,
|
||||
.ready_i
|
||||
);
|
||||
|
||||
|
||||
endmodule : prim_arbiter_tree_bind_fpv
|
40
vendor/lowrisc_ip/prim/fpv/tb/prim_arbiter_tree_fpv.sv
vendored
Normal file
40
vendor/lowrisc_ip/prim/fpv/tb/prim_arbiter_tree_fpv.sv
vendored
Normal file
|
@ -0,0 +1,40 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// Testbench module for prim_arbiter_tree.
|
||||
// Intended to be used with a formal tool.
|
||||
|
||||
module prim_arbiter_tree_fpv #(
|
||||
parameter int unsigned N = 4,
|
||||
parameter int unsigned DW = 32,
|
||||
parameter bit Lock = 1'b1
|
||||
) (
|
||||
input clk_i,
|
||||
input rst_ni,
|
||||
input [N-1:0] req_i,
|
||||
input [DW-1:0]data_i [N],
|
||||
output logic[N-1:0] gnt_o,
|
||||
output logic[$clog2(N)-1:0] idx_o,
|
||||
output logic valid_o,
|
||||
output logic[DW-1:0] data_o,
|
||||
input ready_i
|
||||
);
|
||||
|
||||
prim_arbiter_tree #(
|
||||
.N(N),
|
||||
.DW(DW),
|
||||
.Lock(Lock)
|
||||
) i_prim_arbiter_tree (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
.req_i,
|
||||
.data_i,
|
||||
.gnt_o,
|
||||
.idx_o,
|
||||
.valid_o,
|
||||
.data_o,
|
||||
.ready_i
|
||||
);
|
||||
|
||||
endmodule : prim_arbiter_tree_fpv
|
23
vendor/lowrisc_ip/prim/fpv/tb/prim_esc_rxtx_bind_fpv.sv
vendored
Normal file
23
vendor/lowrisc_ip/prim/fpv/tb/prim_esc_rxtx_bind_fpv.sv
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
module prim_esc_rxtx_bind_fpv;
|
||||
|
||||
bind prim_esc_rxtx_fpv
|
||||
prim_esc_rxtx_assert_fpv prim_esc_rxtx_assert_fpv (
|
||||
.clk_i ,
|
||||
.rst_ni ,
|
||||
.resp_err_pi ,
|
||||
.resp_err_ni ,
|
||||
.esc_err_pi ,
|
||||
.esc_err_ni ,
|
||||
.esc_en_i ,
|
||||
.ping_en_i ,
|
||||
.ping_ok_o ,
|
||||
.integ_fail_o,
|
||||
.esc_en_o
|
||||
);
|
||||
|
||||
endmodule : prim_esc_rxtx_bind_fpv
|
54
vendor/lowrisc_ip/prim/fpv/tb/prim_esc_rxtx_fpv.sv
vendored
Normal file
54
vendor/lowrisc_ip/prim/fpv/tb/prim_esc_rxtx_fpv.sv
vendored
Normal file
|
@ -0,0 +1,54 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// Testbench module for escalation sender/receiver pair. Intended to use with
|
||||
// a formal tool.
|
||||
|
||||
module prim_esc_rxtx_fpv
|
||||
import prim_alert_pkg::*;
|
||||
import prim_esc_pkg::*;
|
||||
(
|
||||
input clk_i,
|
||||
input rst_ni,
|
||||
// for sigint error injection only
|
||||
input resp_err_pi,
|
||||
input resp_err_ni,
|
||||
input esc_err_pi,
|
||||
input esc_err_ni,
|
||||
// normal I/Os
|
||||
input esc_en_i,
|
||||
input ping_en_i,
|
||||
output logic ping_ok_o,
|
||||
output logic integ_fail_o,
|
||||
output logic esc_en_o
|
||||
);
|
||||
|
||||
esc_rx_t esc_rx_in, esc_rx_out;
|
||||
esc_tx_t esc_tx_in, esc_tx_out;
|
||||
|
||||
assign esc_rx_in.resp_p = esc_rx_out.resp_p ^ resp_err_pi;
|
||||
assign esc_rx_in.resp_n = esc_rx_out.resp_n ^ resp_err_ni;
|
||||
assign esc_tx_in.esc_p = esc_tx_out.esc_p ^ esc_err_pi;
|
||||
assign esc_tx_in.esc_n = esc_tx_out.esc_n ^ esc_err_ni;
|
||||
|
||||
prim_esc_sender i_prim_esc_sender (
|
||||
.clk_i ,
|
||||
.rst_ni ,
|
||||
.ping_en_i ,
|
||||
.ping_ok_o ,
|
||||
.integ_fail_o ,
|
||||
.esc_en_i ,
|
||||
.esc_rx_i ( esc_rx_in ),
|
||||
.esc_tx_o ( esc_tx_out )
|
||||
);
|
||||
|
||||
prim_esc_receiver i_prim_esc_receiver (
|
||||
.clk_i ,
|
||||
.rst_ni ,
|
||||
.esc_en_o ,
|
||||
.esc_rx_o ( esc_rx_out ),
|
||||
.esc_tx_i ( esc_tx_in )
|
||||
);
|
||||
|
||||
endmodule : prim_esc_rxtx_fpv
|
219
vendor/lowrisc_ip/prim/fpv/tb/prim_fifo_sync_bind_fpv.sv
vendored
Normal file
219
vendor/lowrisc_ip/prim/fpv/tb/prim_fifo_sync_bind_fpv.sv
vendored
Normal file
|
@ -0,0 +1,219 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
module prim_fifo_sync_bind_fpv;
|
||||
|
||||
localparam int unsigned Width = 4;
|
||||
|
||||
// need to instantiate by hand since bind statements inside
|
||||
// generate blocks are currently not supported
|
||||
|
||||
////////////////////
|
||||
// non-pass FIFOs //
|
||||
////////////////////
|
||||
|
||||
bind i_nopass1 prim_fifo_sync_assert_fpv #(
|
||||
.Width(Width),
|
||||
.Pass(1'b0),
|
||||
.Depth(1),
|
||||
.EnableDataCheck(1'b1)
|
||||
) i_nopass1_assert_fpv (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
.clr_i,
|
||||
.wvalid,
|
||||
.wready,
|
||||
.wdata,
|
||||
.rvalid,
|
||||
.rready,
|
||||
.rdata,
|
||||
.depth
|
||||
);
|
||||
|
||||
bind i_nopass7 prim_fifo_sync_assert_fpv #(
|
||||
.Width(Width),
|
||||
.Pass(1'b0),
|
||||
.Depth(7),
|
||||
.EnableDataCheck(1'b1)
|
||||
) i_nopass7_assert_fpv (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
.clr_i,
|
||||
.wvalid,
|
||||
.wready,
|
||||
.wdata,
|
||||
.rvalid,
|
||||
.rready,
|
||||
.rdata,
|
||||
.depth
|
||||
);
|
||||
|
||||
bind i_nopass8 prim_fifo_sync_assert_fpv #(
|
||||
.Width(Width),
|
||||
.Pass(1'b0),
|
||||
.Depth(8),
|
||||
.EnableDataCheck(1'b1)
|
||||
) i_nopass8_assert_fpv (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
.clr_i,
|
||||
.wvalid,
|
||||
.wready,
|
||||
.wdata,
|
||||
.rvalid,
|
||||
.rready,
|
||||
.rdata,
|
||||
.depth
|
||||
);
|
||||
|
||||
bind i_nopass15 prim_fifo_sync_assert_fpv #(
|
||||
.Width(Width),
|
||||
.Pass(1'b0),
|
||||
.Depth(15),
|
||||
.EnableDataCheck(1'b0)
|
||||
) i_nopass15_assert_fpv (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
.clr_i,
|
||||
.wvalid,
|
||||
.wready,
|
||||
.wdata,
|
||||
.rvalid,
|
||||
.rready,
|
||||
.rdata,
|
||||
.depth
|
||||
);
|
||||
|
||||
bind i_nopass16 prim_fifo_sync_assert_fpv #(
|
||||
.Width(Width),
|
||||
.Pass(1'b0),
|
||||
.Depth(16),
|
||||
.EnableDataCheck(1'b0)
|
||||
) i_nopass16_assert_fpv (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
.clr_i,
|
||||
.wvalid,
|
||||
.wready,
|
||||
.wdata,
|
||||
.rvalid,
|
||||
.rready,
|
||||
.rdata,
|
||||
.depth
|
||||
);
|
||||
|
||||
////////////////
|
||||
// pass FIFOs //
|
||||
////////////////
|
||||
|
||||
bind i_pass0 prim_fifo_sync_assert_fpv #(
|
||||
.Width(Width),
|
||||
.Pass(1'b1),
|
||||
.Depth(0),
|
||||
.EnableDataCheck(1'b1)
|
||||
) i_pass0_assert_fpv (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
.clr_i,
|
||||
.wvalid,
|
||||
.wready,
|
||||
.wdata,
|
||||
.rvalid,
|
||||
.rready,
|
||||
.rdata,
|
||||
.depth
|
||||
);
|
||||
|
||||
bind i_pass1 prim_fifo_sync_assert_fpv #(
|
||||
.Width(Width),
|
||||
.Pass(1'b1),
|
||||
.Depth(1),
|
||||
.EnableDataCheck(1'b1)
|
||||
) i_pass1_assert_fpv (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
.clr_i,
|
||||
.wvalid,
|
||||
.wready,
|
||||
.wdata,
|
||||
.rvalid,
|
||||
.rready,
|
||||
.rdata,
|
||||
.depth
|
||||
);
|
||||
|
||||
bind i_pass7 prim_fifo_sync_assert_fpv #(
|
||||
.Width(Width),
|
||||
.Pass(1'b1),
|
||||
.Depth(7),
|
||||
.EnableDataCheck(1'b1)
|
||||
) i_pass7_assert_fpv (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
.clr_i,
|
||||
.wvalid,
|
||||
.wready,
|
||||
.wdata,
|
||||
.rvalid,
|
||||
.rready,
|
||||
.rdata,
|
||||
.depth
|
||||
);
|
||||
|
||||
bind i_pass8 prim_fifo_sync_assert_fpv #(
|
||||
.Width(Width),
|
||||
.Pass(1'b1),
|
||||
.Depth(8),
|
||||
.EnableDataCheck(1'b1)
|
||||
) i_pass8_assert_fpv (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
.clr_i,
|
||||
.wvalid,
|
||||
.wready,
|
||||
.wdata,
|
||||
.rvalid,
|
||||
.rready,
|
||||
.rdata,
|
||||
.depth
|
||||
);
|
||||
|
||||
bind i_pass15 prim_fifo_sync_assert_fpv #(
|
||||
.Width(Width),
|
||||
.Pass(1'b1),
|
||||
.Depth(15),
|
||||
.EnableDataCheck(1'b0)
|
||||
) i_pass15_assert_fpv (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
.clr_i,
|
||||
.wvalid,
|
||||
.wready,
|
||||
.wdata,
|
||||
.rvalid,
|
||||
.rready,
|
||||
.rdata,
|
||||
.depth
|
||||
);
|
||||
|
||||
bind i_pass16 prim_fifo_sync_assert_fpv #(
|
||||
.Width(Width),
|
||||
.Pass(1'b1),
|
||||
.Depth(16),
|
||||
.EnableDataCheck(1'b0)
|
||||
) i_pass16_assert_fpv (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
.clr_i,
|
||||
.wvalid,
|
||||
.wready,
|
||||
.wdata,
|
||||
.rvalid,
|
||||
.rready,
|
||||
.rdata,
|
||||
.depth
|
||||
);
|
||||
|
||||
endmodule : prim_fifo_sync_bind_fpv
|
236
vendor/lowrisc_ip/prim/fpv/tb/prim_fifo_sync_fpv.sv
vendored
Normal file
236
vendor/lowrisc_ip/prim/fpv/tb/prim_fifo_sync_fpv.sv
vendored
Normal file
|
@ -0,0 +1,236 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// Testbench module for prim_fifo_sync.
|
||||
// Intended to be used with a formal tool.
|
||||
//
|
||||
// This formal testbench instantiates a set of differently parameterized FIFOs:
|
||||
//
|
||||
// - a depth 0 pass through FIFO
|
||||
// - depth 1, 7, 8, 15, 16 pass through FIFOs
|
||||
// - depth 1, 7, 8, 15, 16 non-pass through FIFOs
|
||||
//
|
||||
// Data/depth value checks are enabled up to depth 8 in order to constrain the
|
||||
// runtime.
|
||||
|
||||
module prim_fifo_sync_fpv #(
|
||||
// number of DUTs instantiated in this FPV testbench
|
||||
parameter int unsigned NumDuts = 11,
|
||||
// fifo params
|
||||
parameter int unsigned Width = 4,
|
||||
parameter int unsigned MaxDepth = 16, // max depth used in this destbench
|
||||
localparam int unsigned DepthW = ($clog2(MaxDepth+1) == 0) ? 1 : $clog2(MaxDepth+1)
|
||||
) (
|
||||
input clk_i,
|
||||
input rst_ni,
|
||||
input clr_i,
|
||||
input wvalid [NumDuts],
|
||||
output wready [NumDuts],
|
||||
input [Width-1:0] wdata [NumDuts],
|
||||
output rvalid [NumDuts],
|
||||
input rready [NumDuts],
|
||||
output [Width-1:0] rdata [NumDuts],
|
||||
output [DepthW-1:0] depth [NumDuts]
|
||||
);
|
||||
|
||||
// need to instantiate by hand since bind statements inside
|
||||
// generate blocks are currently not supported
|
||||
|
||||
////////////////////
|
||||
// non-pass FIFOs //
|
||||
////////////////////
|
||||
|
||||
prim_fifo_sync #(
|
||||
.Width(Width),
|
||||
.Pass(1'b0),
|
||||
.Depth(1)
|
||||
) i_nopass1 (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
.clr_i,
|
||||
.wvalid(wvalid[0]),
|
||||
.wready(wready[0]),
|
||||
.wdata(wdata[0]),
|
||||
.rvalid(rvalid[0]),
|
||||
.rready(rready[0]),
|
||||
.rdata(rdata[0]),
|
||||
.depth(depth[0][0])
|
||||
);
|
||||
|
||||
prim_fifo_sync #(
|
||||
.Width(Width),
|
||||
.Pass(1'b0),
|
||||
.Depth(7)
|
||||
) i_nopass7 (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
.clr_i,
|
||||
.wvalid(wvalid[1]),
|
||||
.wready(wready[1]),
|
||||
.wdata(wdata[1]),
|
||||
.rvalid(rvalid[1]),
|
||||
.rready(rready[1]),
|
||||
.rdata(rdata[1]),
|
||||
.depth(depth[1][2:0])
|
||||
);
|
||||
|
||||
prim_fifo_sync #(
|
||||
.Width(Width),
|
||||
.Pass(1'b0),
|
||||
.Depth(8)
|
||||
) i_nopass8 (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
.clr_i,
|
||||
.wvalid(wvalid[2]),
|
||||
.wready(wready[2]),
|
||||
.wdata(wdata[2]),
|
||||
.rvalid(rvalid[2]),
|
||||
.rready(rready[2]),
|
||||
.rdata(rdata[2]),
|
||||
.depth(depth[2][3:0])
|
||||
);
|
||||
|
||||
prim_fifo_sync #(
|
||||
.Width(Width),
|
||||
.Pass(1'b0),
|
||||
.Depth(15)
|
||||
) i_nopass15 (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
.clr_i,
|
||||
.wvalid(wvalid[3]),
|
||||
.wready(wready[3]),
|
||||
.wdata(wdata[3]),
|
||||
.rvalid(rvalid[3]),
|
||||
.rready(rready[3]),
|
||||
.rdata(rdata[3]),
|
||||
.depth(depth[3][3:0])
|
||||
);
|
||||
|
||||
prim_fifo_sync #(
|
||||
.Width(Width),
|
||||
.Pass(1'b0),
|
||||
.Depth(16)
|
||||
) i_nopass16 (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
.clr_i,
|
||||
.wvalid(wvalid[4]),
|
||||
.wready(wready[4]),
|
||||
.wdata(wdata[4]),
|
||||
.rvalid(rvalid[4]),
|
||||
.rready(rready[4]),
|
||||
.rdata(rdata[4]),
|
||||
.depth(depth[4][4:0])
|
||||
);
|
||||
|
||||
////////////////
|
||||
// pass FIFOs //
|
||||
////////////////
|
||||
|
||||
// depth-zero is per definition a pass-through FIFO
|
||||
prim_fifo_sync #(
|
||||
.Width(Width),
|
||||
.Pass(1'b1),
|
||||
.Depth(0)
|
||||
) i_pass0 (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
.clr_i,
|
||||
.wvalid(wvalid[5]),
|
||||
.wready(wready[5]),
|
||||
.wdata(wdata[5]),
|
||||
.rvalid(rvalid[5]),
|
||||
.rready(rready[5]),
|
||||
.rdata(rdata[5]),
|
||||
.depth(depth[5][0])
|
||||
);
|
||||
|
||||
prim_fifo_sync #(
|
||||
.Width(Width),
|
||||
.Pass(1'b1),
|
||||
.Depth(1)
|
||||
) i_pass1 (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
.clr_i,
|
||||
.wvalid(wvalid[6]),
|
||||
.wready(wready[6]),
|
||||
.wdata(wdata[6]),
|
||||
.rvalid(rvalid[6]),
|
||||
.rready(rready[6]),
|
||||
.rdata(rdata[6]),
|
||||
.depth(depth[6][0])
|
||||
);
|
||||
|
||||
prim_fifo_sync #(
|
||||
.Width(Width),
|
||||
.Pass(1'b1),
|
||||
.Depth(7)
|
||||
) i_pass7 (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
.clr_i,
|
||||
.wvalid(wvalid[7]),
|
||||
.wready(wready[7]),
|
||||
.wdata(wdata[7]),
|
||||
.rvalid(rvalid[7]),
|
||||
.rready(rready[7]),
|
||||
.rdata(rdata[7]),
|
||||
.depth(depth[7][2:0])
|
||||
);
|
||||
|
||||
prim_fifo_sync #(
|
||||
.Width(Width),
|
||||
.Pass(1'b1),
|
||||
.Depth(8)
|
||||
) i_pass8 (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
.clr_i,
|
||||
.wvalid(wvalid[8]),
|
||||
.wready(wready[8]),
|
||||
.wdata(wdata[8]),
|
||||
.rvalid(rvalid[8]),
|
||||
.rready(rready[8]),
|
||||
.rdata(rdata[8]),
|
||||
.depth(depth[8][3:0])
|
||||
);
|
||||
|
||||
prim_fifo_sync #(
|
||||
.Width(Width),
|
||||
.Pass(1'b1),
|
||||
.Depth(15)
|
||||
) i_pass15 (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
.clr_i,
|
||||
.wvalid(wvalid[9]),
|
||||
.wready(wready[9]),
|
||||
.wdata(wdata[9]),
|
||||
.rvalid(rvalid[9]),
|
||||
.rready(rready[9]),
|
||||
.rdata(rdata[9]),
|
||||
.depth(depth[9][3:0])
|
||||
);
|
||||
|
||||
prim_fifo_sync #(
|
||||
.Width(Width),
|
||||
.Pass(1'b1),
|
||||
.Depth(16)
|
||||
) i_pass16 (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
.clr_i,
|
||||
.wvalid(wvalid[10]),
|
||||
.wready(wready[10]),
|
||||
.wdata(wdata[10]),
|
||||
.rvalid(rvalid[10]),
|
||||
.rready(rready[10]),
|
||||
.rdata(rdata[10]),
|
||||
.depth(depth[10][4:0])
|
||||
);
|
||||
|
||||
endmodule : prim_fifo_sync_fpv
|
74
vendor/lowrisc_ip/prim/fpv/tb/prim_keccak_fpv.sv
vendored
Normal file
74
vendor/lowrisc_ip/prim/fpv/tb/prim_keccak_fpv.sv
vendored
Normal file
|
@ -0,0 +1,74 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// Testbench module for prim_keccak. Intended to be used with a formal tool.
|
||||
|
||||
module prim_keccak_fpv #(
|
||||
parameter int Width = 1600
|
||||
) (
|
||||
input clk_i,
|
||||
input rst_ni,
|
||||
input valid_i,
|
||||
input [Width-1:0] state_i,
|
||||
output logic done_o,
|
||||
output logic [Width-1:0] state_o
|
||||
);
|
||||
|
||||
localparam int W = Width/25;
|
||||
localparam int L = $clog2(W);
|
||||
localparam int NumRound = 12 + 2*L; // Keccak-f only
|
||||
localparam int RndW = $clog2(NumRound+1);
|
||||
logic [RndW-1:0] round;
|
||||
logic active;
|
||||
logic [Width-1:0] state, state_d;
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if (!rst_ni) state <= '0;
|
||||
else if (valid_i) state <= state_i;
|
||||
else if (active) state <= state_d;
|
||||
end
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if (!rst_ni) round <= '0;
|
||||
else if (valid_i) round <= '0;
|
||||
else if (active) round <= round + 1'b 1;
|
||||
end
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if (!rst_ni) active <= 1'b 0;
|
||||
else if (valid_i) active <= 1'b 1;
|
||||
else if (round == (NumRound -1)) active <= 1'b 0;
|
||||
end
|
||||
|
||||
assign done_o = (round == NumRound);
|
||||
assign state_o = state;
|
||||
|
||||
prim_keccak #(
|
||||
.Width (Width)
|
||||
) u_keccak (
|
||||
.rnd_i (round),
|
||||
.s_i (state),
|
||||
.s_o (state_d)
|
||||
);
|
||||
|
||||
|
||||
`ASSUME_FPV(ValidSequence_A, ##1 valid_i |=> !valid_i)
|
||||
`ASSUME_FPV(ValidValid_A, active |-> !valid_i)
|
||||
|
||||
// Test with value 0
|
||||
logic [1599:0] data_0 ;
|
||||
always_comb begin
|
||||
data_0 = '0;
|
||||
// SHA3-256 ==> r : 1088
|
||||
data_0[1087] = 1'b 1;
|
||||
data_0[2:0] = 3'b 110;
|
||||
end
|
||||
logic [255:0] digest_0;
|
||||
// Big-Endian a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a
|
||||
assign digest_0 = 256'h 4a43_f880_4b0a_d882_fa49_3be4_4dff_80f5_62d6_61a0_5647_c151_66d7_1ebf_f8c6_ffa7;
|
||||
`ASSUME_FPV(Data0TestSHA3_256_A, state_i == data_0)
|
||||
`ASSERT(DigestForData0TestSHA3_256_A, done_o |-> state_o[255:0] == digest_0)
|
||||
|
||||
endmodule
|
||||
|
75
vendor/lowrisc_ip/prim/fpv/tb/prim_lfsr_fpv.sv
vendored
Normal file
75
vendor/lowrisc_ip/prim/fpv/tb/prim_lfsr_fpv.sv
vendored
Normal file
|
@ -0,0 +1,75 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// Testbench module for prim_lfsr. Intended to be used with a formal tool.
|
||||
|
||||
module prim_lfsr_fpv #(
|
||||
// LFSR entropy and output bitwidths (set to 1 here as they are unused)
|
||||
parameter int unsigned EntropyDw = 1,
|
||||
parameter int unsigned StateOutDw = 1,
|
||||
// this specifies the range of differently
|
||||
// parameterized LFSRs to instantiate and check
|
||||
parameter int unsigned GalXorMinLfsrDw = 4,
|
||||
parameter int unsigned GalXorMaxLfsrDw = 64,
|
||||
parameter int unsigned FibXnorMinLfsrDw = 3,
|
||||
parameter int unsigned FibXnorMaxLfsrDw = 168,
|
||||
// LFSRs up to this bitwidth are checked for maximum length
|
||||
parameter int unsigned MaxLenSVAThresh = 10,
|
||||
// derived params
|
||||
localparam int unsigned GalMaxGtFibMax = GalXorMaxLfsrDw > FibXnorMaxLfsrDw,
|
||||
localparam int unsigned MaxLfsrDw = GalXorMaxLfsrDw * GalMaxGtFibMax +
|
||||
FibXnorMaxLfsrDw * (1 - GalMaxGtFibMax),
|
||||
localparam int unsigned NumDuts = FibXnorMaxLfsrDw - FibXnorMinLfsrDw + 1 +
|
||||
GalXorMaxLfsrDw - GalXorMinLfsrDw + 1
|
||||
) (
|
||||
input clk_i,
|
||||
input rst_ni,
|
||||
input [NumDuts-1:0] load_ext_en_i,
|
||||
input [NumDuts-1:0][MaxLfsrDw-1:0] seed_ext_i,
|
||||
input [NumDuts-1:0] lfsr_en_i,
|
||||
input [NumDuts-1:0][EntropyDw-1:0] entropy_i,
|
||||
output logic [NumDuts-1:0][StateOutDw-1:0] state_o
|
||||
);
|
||||
|
||||
for (genvar k = GalXorMinLfsrDw; k <= GalXorMaxLfsrDw; k++) begin : gen_gal_xor_duts
|
||||
localparam int unsigned idx = k - GalXorMinLfsrDw;
|
||||
prim_lfsr #(.LfsrType("GAL_XOR"),
|
||||
.LfsrDw ( k ),
|
||||
.EntropyDw ( EntropyDw ),
|
||||
.StateOutDw ( StateOutDw ),
|
||||
.DefaultSeed ( 1 ),
|
||||
// disabled for large LFSRs since this becomes prohibitive in runtime
|
||||
.MaxLenSVA ( k <= MaxLenSVAThresh )
|
||||
) i_prim_lfsr (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
.seed_en_i ( load_ext_en_i[idx] ),
|
||||
.seed_i ( k'(seed_ext_i[idx]) ),
|
||||
.lfsr_en_i ( lfsr_en_i[idx] ),
|
||||
.entropy_i ( entropy_i[idx] ),
|
||||
.state_o ( state_o[idx] )
|
||||
);
|
||||
end
|
||||
|
||||
for (genvar k = FibXnorMinLfsrDw; k <= FibXnorMaxLfsrDw; k++) begin : gen_fib_xnor_duts
|
||||
localparam int unsigned idx = k - FibXnorMinLfsrDw + GalXorMaxLfsrDw - GalXorMinLfsrDw + 1;
|
||||
prim_lfsr #(.LfsrType("FIB_XNOR"),
|
||||
.LfsrDw ( k ),
|
||||
.EntropyDw ( EntropyDw ),
|
||||
.StateOutDw ( StateOutDw ),
|
||||
.DefaultSeed ( 1 ),
|
||||
// disabled for large LFSRs since this becomes prohibitive in runtime
|
||||
.MaxLenSVA ( k <= MaxLenSVAThresh )
|
||||
) i_prim_lfsr (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
.seed_en_i ( load_ext_en_i[idx] ),
|
||||
.seed_i ( k'(seed_ext_i[idx]) ),
|
||||
.lfsr_en_i ( lfsr_en_i[idx] ),
|
||||
.entropy_i ( entropy_i[idx] ),
|
||||
.state_o ( state_o[idx] )
|
||||
);
|
||||
end
|
||||
|
||||
endmodule : prim_lfsr_fpv
|
92
vendor/lowrisc_ip/prim/fpv/vip/prim_alert_rxtx_assert_fpv.sv
vendored
Normal file
92
vendor/lowrisc_ip/prim/fpv/vip/prim_alert_rxtx_assert_fpv.sv
vendored
Normal file
|
@ -0,0 +1,92 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// Assertions for alert sender/receiver pair. Intended to use with
|
||||
// a formal tool.
|
||||
|
||||
`include "prim_assert.sv"
|
||||
|
||||
module prim_alert_rxtx_assert_fpv (
|
||||
input clk_i,
|
||||
input rst_ni,
|
||||
// for sigint error injection only
|
||||
input ping_err_pi,
|
||||
input ping_err_ni,
|
||||
input ack_err_pi,
|
||||
input ack_err_ni,
|
||||
input alert_err_pi,
|
||||
input alert_err_ni,
|
||||
// normal I/Os
|
||||
input alert_i,
|
||||
input ping_en_i,
|
||||
input ping_ok_o,
|
||||
input integ_fail_o,
|
||||
input alert_o
|
||||
);
|
||||
|
||||
logic error_present;
|
||||
assign error_present = ping_err_pi | ping_err_ni |
|
||||
ack_err_pi | ack_err_ni |
|
||||
alert_err_pi | alert_err_ni;
|
||||
|
||||
// note: we can only detect sigint errors where one wire is flipped.
|
||||
`ASSUME_FPV(PingErrorsAreOH_M, $onehot0({ping_err_pi, ping_err_ni}), clk_i, !rst_ni)
|
||||
`ASSUME_FPV(AckErrorsAreOH_M, $onehot0({ack_err_pi, ack_err_ni}), clk_i, !rst_ni)
|
||||
`ASSUME_FPV(AlertErrorsAreOH_M, $onehot0({alert_err_pi, alert_err_ni}), clk_i, !rst_ni)
|
||||
|
||||
// ping will stay high until ping ok received, then it must be deasserted
|
||||
// TODO: this excludes the case where no ping ok will be returned due to an error
|
||||
`ASSUME_FPV(PingDeassert_M, ping_en_i && ping_ok_o |=> !ping_en_i, clk_i, !rst_ni)
|
||||
`ASSUME_FPV(PingEnStaysAsserted0_M, ping_en_i |=> (ping_en_i && !ping_ok_o) or
|
||||
(ping_en_i && ping_ok_o ##1 $fell(ping_en_i)), clk_i, !rst_ni || error_present)
|
||||
|
||||
sequence FullHandshake_S;
|
||||
$rose(prim_alert_rxtx_fpv.alert_tx_out.alert_p) ##1
|
||||
$rose(prim_alert_rxtx_fpv.alert_rx_out.ack_p) &&
|
||||
$stable(prim_alert_rxtx_fpv.alert_tx_out.alert_p) ##1
|
||||
$fell(prim_alert_rxtx_fpv.alert_tx_out.alert_p) &&
|
||||
$stable(prim_alert_rxtx_fpv.alert_rx_out.ack_p) ##1
|
||||
$fell(prim_alert_rxtx_fpv.alert_rx_out.ack_p) &&
|
||||
$stable(prim_alert_rxtx_fpv.alert_tx_out.alert_p) ;
|
||||
endsequence
|
||||
|
||||
// note: injected errors may lockup the FSMs, and hence the full HS can
|
||||
// only take place if both FSMs are in a sane state
|
||||
`ASSERT(PingHs_A, ##1 $changed(prim_alert_rxtx_fpv.alert_rx_out.ping_p) &&
|
||||
(prim_alert_rxtx_fpv.i_prim_alert_sender.state_q ==
|
||||
prim_alert_rxtx_fpv.i_prim_alert_sender.Idle ) &&
|
||||
(prim_alert_rxtx_fpv.i_prim_alert_receiver.state_q ==
|
||||
prim_alert_rxtx_fpv.i_prim_alert_receiver.Idle )|=> FullHandshake_S,
|
||||
clk_i, !rst_ni || error_present)
|
||||
`ASSERT(AlertHs_A, alert_i &&
|
||||
(prim_alert_rxtx_fpv.i_prim_alert_sender.state_q ==
|
||||
prim_alert_rxtx_fpv.i_prim_alert_sender.Idle) &&
|
||||
(prim_alert_rxtx_fpv.i_prim_alert_receiver.state_q ==
|
||||
prim_alert_rxtx_fpv.i_prim_alert_receiver.Idle) |=>
|
||||
FullHandshake_S, clk_i, !rst_ni || error_present)
|
||||
|
||||
// transmission of pings
|
||||
`ASSERT(AlertPing_A, !error_present ##1 $rose(ping_en_i) |->
|
||||
##[1:9] ping_ok_o, clk_i, !rst_ni || error_present)
|
||||
// transmission of alerts in case of no collision with ping enable
|
||||
`ASSERT(AlertCheck0_A, !ping_en_i [*3] ##0 $rose(alert_i) &&
|
||||
(prim_alert_rxtx_fpv.i_prim_alert_sender.state_q ==
|
||||
prim_alert_rxtx_fpv.i_prim_alert_sender.Idle) |=>
|
||||
alert_o, clk_i, !rst_ni || error_present || ping_en_i)
|
||||
// transmission of alerts in the general case which can include ping collisions
|
||||
`ASSERT(AlertCheck1_A, alert_i |-> ##[1:9] alert_o, clk_i, !rst_ni || error_present)
|
||||
|
||||
// basic liveness of FSMs in case no errors are present
|
||||
`ASSERT(FsmLivenessSender_A,
|
||||
(prim_alert_rxtx_fpv.i_prim_alert_sender.state_q !=
|
||||
prim_alert_rxtx_fpv.i_prim_alert_sender.Idle) |->
|
||||
strong(##[1:$] (prim_alert_rxtx_fpv.i_prim_alert_sender.state_q ==
|
||||
prim_alert_rxtx_fpv.i_prim_alert_sender.Idle)), clk_i, !rst_ni || error_present)
|
||||
`ASSERT(FsmLivenessReceiver_A,
|
||||
(prim_alert_rxtx_fpv.i_prim_alert_receiver.state_q !=
|
||||
prim_alert_rxtx_fpv.i_prim_alert_receiver.Idle) |->
|
||||
strong(##[1:$] (prim_alert_rxtx_fpv.i_prim_alert_receiver.state_q ==
|
||||
prim_alert_rxtx_fpv.i_prim_alert_receiver.Idle)),clk_i, !rst_ni || error_present)
|
||||
|
||||
endmodule : prim_alert_rxtx_assert_fpv
|
121
vendor/lowrisc_ip/prim/fpv/vip/prim_alert_rxtx_async_assert_fpv.sv
vendored
Normal file
121
vendor/lowrisc_ip/prim/fpv/vip/prim_alert_rxtx_async_assert_fpv.sv
vendored
Normal file
|
@ -0,0 +1,121 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// Assertions for alert sender/receiver pair for the asynchronous case.
|
||||
// Intended to use with a formal tool.
|
||||
|
||||
`include "prim_assert.sv"
|
||||
|
||||
module prim_alert_rxtx_async_assert_fpv (
|
||||
input clk_i,
|
||||
input rst_ni,
|
||||
// for sigint error and skew injection only
|
||||
input ping_err_pi,
|
||||
input ping_err_ni,
|
||||
input [1:0] ping_skew_i,
|
||||
input ack_err_pi,
|
||||
input ack_err_ni,
|
||||
input [1:0] ack_skew_i,
|
||||
input alert_err_pi,
|
||||
input alert_err_ni,
|
||||
input [1:0] alert_skew_i,
|
||||
// normal I/Os
|
||||
input alert_i,
|
||||
input ping_en_i,
|
||||
input ping_ok_o,
|
||||
input integ_fail_o,
|
||||
input alert_o
|
||||
);
|
||||
|
||||
logic error_present;
|
||||
assign error_present = ping_err_pi | ping_err_ni |
|
||||
ack_err_pi | ack_err_ni |
|
||||
alert_err_pi | alert_err_ni;
|
||||
|
||||
// used to check that an error has never occured so far
|
||||
// this is used to check the handshake below. the handshake can lock up
|
||||
// the protocol FSMs causing the handshake to never complete.
|
||||
// note that this will block any ping messages and hence it can be
|
||||
// eventually detected by the alert handler.
|
||||
logic error_setreg_d, error_setreg_q;
|
||||
assign error_setreg_d = error_present | error_setreg_q;
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : p_reg
|
||||
if (!rst_ni) begin
|
||||
error_setreg_q <= 1'b0;
|
||||
end else begin
|
||||
error_setreg_q <= error_setreg_d;
|
||||
end
|
||||
end
|
||||
|
||||
// Note: we can only detect sigint errors where one wire is flipped.
|
||||
`ASSUME_FPV(PingErrorsAreOH_M, $onehot0({ping_err_pi, ping_err_ni}) )
|
||||
`ASSUME_FPV(AckErrorsAreOH_M, $onehot0({ack_err_pi, ack_err_ni}) )
|
||||
`ASSUME_FPV(AlertErrorsAreOH_M, $onehot0({alert_err_pi, alert_err_ni}))
|
||||
|
||||
// ping will stay high until ping ok received, then it must be deasserted
|
||||
// TODO: this excludes the case where no ping ok will be returned due to an error
|
||||
`ASSUME_FPV(PingDeassert_M, ping_en_i && ping_ok_o |=> !ping_en_i, clk_i, !rst_ni)
|
||||
`ASSUME_FPV(PingEnStaysAsserted0_M, ping_en_i |=>
|
||||
(ping_en_i && !ping_ok_o) or
|
||||
(ping_en_i && ping_ok_o ##1 $fell(ping_en_i)),
|
||||
clk_i, !rst_ni || error_present)
|
||||
|
||||
// Note: the sequence lengths of the handshake and the following properties needs to
|
||||
// be parameterized accordingly if different clock ratios are to be used here.
|
||||
// TODO: tighten bounds if possible
|
||||
sequence FullHandshake_S;
|
||||
$rose(prim_alert_rxtx_async_fpv.alert_pd) ##[3:5]
|
||||
$rose(prim_alert_rxtx_async_fpv.ack_pd) &&
|
||||
$stable(prim_alert_rxtx_async_fpv.alert_pd) ##[3:5]
|
||||
$fell(prim_alert_rxtx_async_fpv.alert_pd) &&
|
||||
$stable(prim_alert_rxtx_async_fpv.ack_pd) ##[3:5]
|
||||
$fell(prim_alert_rxtx_async_fpv.ack_pd) &&
|
||||
$stable(prim_alert_rxtx_async_fpv.alert_pd);
|
||||
endsequence
|
||||
|
||||
// note: injected errors may lockup the FSMs, and hence the full HS can
|
||||
// only take place if both FSMs are in a sane state
|
||||
`ASSERT(PingHs_A, ##1 $changed(prim_alert_rxtx_async_fpv.ping_pd) &&
|
||||
(prim_alert_rxtx_async_fpv.i_prim_alert_sender.state_q ==
|
||||
prim_alert_rxtx_async_fpv.i_prim_alert_sender.Idle) &&
|
||||
(prim_alert_rxtx_async_fpv.i_prim_alert_receiver.state_q ==
|
||||
prim_alert_rxtx_async_fpv.i_prim_alert_receiver.Idle) |-> ##[0:5] FullHandshake_S,
|
||||
clk_i, !rst_ni || error_setreg_q)
|
||||
`ASSERT(AlertHs_A, alert_i &&
|
||||
(prim_alert_rxtx_async_fpv.i_prim_alert_sender.state_q ==
|
||||
prim_alert_rxtx_async_fpv.i_prim_alert_sender.Idle) &&
|
||||
(prim_alert_rxtx_async_fpv.i_prim_alert_receiver.state_q ==
|
||||
prim_alert_rxtx_async_fpv.i_prim_alert_receiver.Idle) |-> ##[0:5] FullHandshake_S,
|
||||
clk_i, !rst_ni || error_setreg_q)
|
||||
|
||||
// transmission of pings
|
||||
// this bound is relatively large as in the worst case, we need to resolve
|
||||
// staggered differential signal patterns on all three differential channels
|
||||
`ASSERT(AlertPing_A, $rose(ping_en_i) |-> ##[1:23] ping_ok_o,
|
||||
clk_i, !rst_ni || error_setreg_q)
|
||||
// transmission of first alert assertion (no ping collision)
|
||||
`ASSERT(AlertCheck0_A, !ping_en_i [*10] ##1 $rose(alert_i) &&
|
||||
(prim_alert_rxtx_async_fpv.i_prim_alert_sender.state_q ==
|
||||
prim_alert_rxtx_async_fpv.i_prim_alert_sender.Idle) |->
|
||||
##[3:5] alert_o, clk_i, !rst_ni || ping_en_i || error_setreg_q)
|
||||
// eventual transmission of alerts in the general case which can include ping collisions
|
||||
`ASSERT(AlertCheck1_A, alert_i |-> ##[1:25] alert_o,
|
||||
clk_i, !rst_ni || error_setreg_q)
|
||||
|
||||
// basic liveness of FSMs in case no errors are present
|
||||
`ASSERT(FsmLivenessSender_A, !error_present [*2] ##1 !error_present &&
|
||||
(prim_alert_rxtx_async_fpv.i_prim_alert_sender.state_q !=
|
||||
prim_alert_rxtx_async_fpv.i_prim_alert_sender.Idle) |->
|
||||
strong(##[1:$] (prim_alert_rxtx_async_fpv.i_prim_alert_sender.state_q ==
|
||||
prim_alert_rxtx_async_fpv.i_prim_alert_sender.Idle)), clk_i, !rst_ni || error_present)
|
||||
`ASSERT(FsmLivenessReceiver_A, !error_present [*2] ##1 !error_present &&
|
||||
(prim_alert_rxtx_async_fpv.i_prim_alert_receiver.state_q !=
|
||||
prim_alert_rxtx_async_fpv.i_prim_alert_receiver.Idle) |->
|
||||
strong(##[1:$] (prim_alert_rxtx_async_fpv.i_prim_alert_receiver.state_q ==
|
||||
prim_alert_rxtx_async_fpv.i_prim_alert_receiver.Idle)),clk_i, !rst_ni || error_present)
|
||||
|
||||
// TODO: add FSM liveness of 3x diff decoder instances
|
||||
|
||||
endmodule : prim_alert_rxtx_async_assert_fpv
|
47
vendor/lowrisc_ip/prim/fpv/vip/prim_arbiter_ppc_assert_fpv.sv
vendored
Normal file
47
vendor/lowrisc_ip/prim/fpv/vip/prim_arbiter_ppc_assert_fpv.sv
vendored
Normal file
|
@ -0,0 +1,47 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// Assertions for prim_arbiter_ppc.
|
||||
// Intended to be used with a formal tool.
|
||||
|
||||
`include "prim_assert.sv"
|
||||
|
||||
module prim_arbiter_ppc_assert_fpv #(
|
||||
parameter int unsigned N = 4,
|
||||
parameter int unsigned DW = 32
|
||||
) (
|
||||
input clk_i,
|
||||
input rst_ni,
|
||||
input [N-1:0] req_i,
|
||||
input [DW-1:0]data_i [N],
|
||||
input logic[N-1:0] gnt_o,
|
||||
input logic[$clog2(N)-1:0] idx_o,
|
||||
input logic valid_o,
|
||||
input logic[DW-1:0] data_o,
|
||||
input ready_i
|
||||
);
|
||||
|
||||
///////////////////////////////
|
||||
// Declarations & Parameters //
|
||||
///////////////////////////////
|
||||
|
||||
/////////////////
|
||||
// Assumptions //
|
||||
/////////////////
|
||||
|
||||
// `ASSUME(MyAssumption_M, ..., clk_i, !rst_ni)
|
||||
|
||||
////////////////////////
|
||||
// Forward Assertions //
|
||||
////////////////////////
|
||||
|
||||
// `ASSERT(MyFwdAssertion_A, ..., clk_i, !rst_ni)
|
||||
|
||||
/////////////////////////
|
||||
// Backward Assertions //
|
||||
/////////////////////////
|
||||
|
||||
// `ASSERT(MyBkwdAssertion_A, ..., clk_i, !rst_ni)
|
||||
|
||||
endmodule : prim_arbiter_ppc_assert_fpv
|
48
vendor/lowrisc_ip/prim/fpv/vip/prim_arbiter_tree_assert_fpv.sv
vendored
Normal file
48
vendor/lowrisc_ip/prim/fpv/vip/prim_arbiter_tree_assert_fpv.sv
vendored
Normal file
|
@ -0,0 +1,48 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// Assertions for prim_arbiter_tree.
|
||||
// Intended to be used with a formal tool.
|
||||
|
||||
`include "prim_assert.sv"
|
||||
|
||||
module prim_arbiter_tree_assert_fpv #(
|
||||
parameter int unsigned N = 4,
|
||||
parameter int unsigned DW = 32,
|
||||
parameter bit Lock = 1'b1
|
||||
) (
|
||||
input clk_i,
|
||||
input rst_ni,
|
||||
input [N-1:0] req_i,
|
||||
input [DW-1:0]data_i [N],
|
||||
input logic[N-1:0] gnt_o,
|
||||
input logic[$clog2(N)-1:0] idx_o,
|
||||
input logic valid_o,
|
||||
input logic[DW-1:0] data_o,
|
||||
input ready_i
|
||||
);
|
||||
|
||||
///////////////////////////////
|
||||
// Declarations & Parameters //
|
||||
///////////////////////////////
|
||||
|
||||
/////////////////
|
||||
// Assumptions //
|
||||
/////////////////
|
||||
|
||||
// `ASSUME(MyAssumption_M, ..., clk_i, !rst_ni)
|
||||
|
||||
////////////////////////
|
||||
// Forward Assertions //
|
||||
////////////////////////
|
||||
|
||||
// `ASSERT(MyFwdAssertion_A, ..., clk_i, !rst_ni)
|
||||
|
||||
/////////////////////////
|
||||
// Backward Assertions //
|
||||
/////////////////////////
|
||||
|
||||
// `ASSERT(MyBkwdAssertion_A, ..., clk_i, !rst_ni)
|
||||
|
||||
endmodule : prim_arbiter_tree_assert_fpv
|
70
vendor/lowrisc_ip/prim/fpv/vip/prim_esc_rxtx_assert_fpv.sv
vendored
Normal file
70
vendor/lowrisc_ip/prim/fpv/vip/prim_esc_rxtx_assert_fpv.sv
vendored
Normal file
|
@ -0,0 +1,70 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// Assertions for escalation sender/receiver pair. Intended to use with
|
||||
// a formal tool.
|
||||
|
||||
`include "prim_assert.sv"
|
||||
|
||||
module prim_esc_rxtx_assert_fpv (
|
||||
input clk_i,
|
||||
input rst_ni,
|
||||
// for sigint error injection only
|
||||
input resp_err_pi,
|
||||
input resp_err_ni,
|
||||
input esc_err_pi,
|
||||
input esc_err_ni,
|
||||
// normal I/Os
|
||||
input esc_en_i,
|
||||
input ping_en_i,
|
||||
input ping_ok_o,
|
||||
input integ_fail_o,
|
||||
input esc_en_o
|
||||
);
|
||||
|
||||
logic error_present;
|
||||
assign error_present = resp_err_pi | resp_err_ni |
|
||||
esc_err_pi | esc_err_ni;
|
||||
|
||||
// ping will stay high until ping ok received, then it must be deasserted
|
||||
// TODO: this escludes the case where no ping ok will be returned due to an error
|
||||
`ASSUME_FPV(PingDeassert_M, ping_en_i && ping_ok_o |=> ping_en_i, clk_i, !rst_ni)
|
||||
`ASSUME_FPV(PingEnStaysAsserted0_M, ping_en_i |=>
|
||||
(ping_en_i && !ping_ok_o) or (ping_en_i && ping_ok_o ##1 $fell(ping_en_i)),
|
||||
clk_i, !rst_ni || error_present)
|
||||
|
||||
// assume that the ping enable and escalation enable signals will eventually be deasserted (and
|
||||
// esc will stay low for more than 2 cycles)
|
||||
`ASSUME_FPV(FiniteEsc_M, esc_en_i |-> strong(##[1:$] !esc_en_i [*2]))
|
||||
`ASSUME_FPV(FinitePing_M, ping_en_i |-> strong(##[1:$] !ping_en_i))
|
||||
|
||||
// ping response mus occur within 4 cycles (given that no
|
||||
// error occured within the previous cycles)
|
||||
`ASSERT(PingRespCheck_A, !error_present [*4] ##1 $rose(ping_en_i) |->
|
||||
##[0:4] ping_ok_o, clk_i, !rst_ni || error_present)
|
||||
|
||||
// be more specific (i.e. use throughout)
|
||||
`ASSERT(EscRespCheck_A, ##1 esc_en_i |-> ##[0:1] prim_esc_rxtx_fpv.esc_rx_out.resp_p ##1
|
||||
!prim_esc_rxtx_fpv.esc_rx_out.resp_p, clk_i, !rst_ni || error_present)
|
||||
|
||||
// check correct transmission of escalation within 0-1 cycles
|
||||
`ASSERT(EscCheck_A, ##1 esc_en_i |-> ##[0:1] esc_en_o, clk_i, !rst_ni || error_present)
|
||||
|
||||
// check that a single error on the diffpairs is detected
|
||||
`ASSERT(SingleSigIntDetected0_A, {esc_err_pi, esc_err_ni} == '0 ##1
|
||||
$onehot({resp_err_pi, resp_err_ni}) |-> integ_fail_o)
|
||||
`ASSERT(SingleSigIntDetected1_A, $onehot({esc_err_pi, esc_err_ni}) ##1
|
||||
{resp_err_pi, resp_err_ni} == '0 |-> integ_fail_o)
|
||||
|
||||
// basic liveness of FSMs in case no errors are present
|
||||
`ASSERT(FsmLivenessSender_A, (prim_esc_rxtx_fpv.i_prim_esc_sender.state_q !=
|
||||
prim_esc_rxtx_fpv.i_prim_esc_sender.Idle) |->
|
||||
strong(##[1:$] (prim_esc_rxtx_fpv.i_prim_esc_sender.state_q
|
||||
== prim_esc_rxtx_fpv.i_prim_esc_sender.Idle)), clk_i, !rst_ni || error_present)
|
||||
`ASSERT(FsmLivenessReceiver_A, (prim_esc_rxtx_fpv.i_prim_esc_receiver.state_q !=
|
||||
prim_esc_rxtx_fpv.i_prim_esc_receiver.Idle) |->
|
||||
strong(##[1:$] (prim_esc_rxtx_fpv.i_prim_esc_receiver.state_q
|
||||
== prim_esc_rxtx_fpv.i_prim_esc_receiver.Idle)), clk_i, !rst_ni || error_present)
|
||||
|
||||
endmodule : prim_esc_rxtx_assert_fpv
|
213
vendor/lowrisc_ip/prim/fpv/vip/prim_fifo_sync_assert_fpv.sv
vendored
Normal file
213
vendor/lowrisc_ip/prim/fpv/vip/prim_fifo_sync_assert_fpv.sv
vendored
Normal file
|
@ -0,0 +1,213 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// Assertions for prim_fifo_sync.
|
||||
// Intended to be used with a formal tool.
|
||||
|
||||
`include "prim_assert.sv"
|
||||
|
||||
module prim_fifo_sync_assert_fpv #(
|
||||
// can be desabled for deeper FIFOs
|
||||
parameter bit EnableDataCheck = 1'b1,
|
||||
parameter int unsigned Width = 16,
|
||||
parameter bit Pass = 1'b1,
|
||||
parameter int unsigned Depth = 4,
|
||||
localparam int unsigned DepthWNorm = $clog2(Depth+1),
|
||||
localparam int unsigned DepthW = (DepthWNorm == 0) ? 1 : DepthWNorm
|
||||
) (
|
||||
input clk_i,
|
||||
input rst_ni,
|
||||
input clr_i,
|
||||
input wvalid,
|
||||
input wready,
|
||||
input [Width-1:0] wdata,
|
||||
input rvalid,
|
||||
input rready,
|
||||
input [Width-1:0] rdata,
|
||||
input [DepthW-1:0] depth
|
||||
);
|
||||
|
||||
/////////////////
|
||||
// Assumptions //
|
||||
/////////////////
|
||||
|
||||
// no need to consider all possible input words
|
||||
// 2-3 different values suffice
|
||||
`ASSUME(WdataValues_M, wdata inside {Width'(1'b0), Width'(1'b1), {Width{1'b1}}}, clk_i, !rst_ni)
|
||||
|
||||
////////////////////////////////
|
||||
// Data and Depth Value Check //
|
||||
////////////////////////////////
|
||||
|
||||
if (EnableDataCheck && Depth > 0) begin : gen_data_check
|
||||
|
||||
logic [DepthW+2:0] ref_depth;
|
||||
logic [Width-1:0] ref_rdata;
|
||||
|
||||
// no pointers needed in this case
|
||||
if (Depth == 1) begin : gen_no_ptrs
|
||||
|
||||
logic [Width-1:0] fifo;
|
||||
logic [DepthW+2:0] wptr, rptr;
|
||||
|
||||
// this only models the data flow, since the control logic is tested below
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : p_fifo_model
|
||||
if (!rst_ni) begin
|
||||
ref_depth <= 0;
|
||||
end else begin
|
||||
if (clr_i) begin
|
||||
ref_depth <= 0;
|
||||
end else begin
|
||||
if (wvalid && wready && rvalid && rready) begin
|
||||
fifo <= wdata;
|
||||
end else if (wvalid && wready) begin
|
||||
fifo <= wdata;
|
||||
ref_depth <= ref_depth + 1;
|
||||
end else if (rvalid && rready) begin
|
||||
ref_depth <= ref_depth - 1;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if (Pass) begin : gen_pass
|
||||
assign ref_rdata = (ref_depth == 0) ? wdata : fifo;
|
||||
end else begin : no_pass
|
||||
assign ref_rdata = fifo;
|
||||
end
|
||||
|
||||
// general case
|
||||
end else begin : gen_ptrs
|
||||
|
||||
logic [Width-1:0] fifo [Depth];
|
||||
logic [DepthW+2:0] wptr, rptr;
|
||||
|
||||
// implements (++val) mod Depth
|
||||
function automatic logic [DepthW+2:0] modinc(logic [DepthW+2:0] val, int modval);
|
||||
if (val == Depth-1) return 0;
|
||||
else return val + 1;
|
||||
endfunction
|
||||
|
||||
// this only models the data flow, since the control logic is tested below
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : p_fifo_model
|
||||
if (!rst_ni) begin
|
||||
wptr <= 0;
|
||||
rptr <= 0;
|
||||
ref_depth <= 0;
|
||||
end else begin
|
||||
if (clr_i) begin
|
||||
wptr <= 0;
|
||||
rptr <= 0;
|
||||
ref_depth <= 0;
|
||||
end else begin
|
||||
if (wvalid && wready && rvalid && rready) begin
|
||||
fifo[wptr] <= wdata;
|
||||
wptr <= modinc(wptr, Depth);
|
||||
rptr <= modinc(rptr, Depth);
|
||||
end else if (wvalid && wready) begin
|
||||
fifo[wptr] <= wdata;
|
||||
wptr <= modinc(wptr, Depth);
|
||||
ref_depth <= ref_depth + 1;
|
||||
end else if (rvalid && rready) begin
|
||||
rptr <= modinc(rptr, Depth);
|
||||
ref_depth <= ref_depth - 1;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if (Pass) begin : gen_pass
|
||||
assign ref_rdata = (ref_depth == 0) ? wdata : fifo[rptr];
|
||||
end else begin : no_pass
|
||||
assign ref_rdata = fifo[rptr];
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
// check the data
|
||||
`ASSERT(DataCheck_A, rvalid |-> rdata == ref_rdata)
|
||||
// check the depth
|
||||
`ASSERT(DepthCheck_A, ref_depth == depth)
|
||||
|
||||
end
|
||||
|
||||
////////////////////////
|
||||
// Forward Assertions //
|
||||
////////////////////////
|
||||
|
||||
// assert depth of FIFO
|
||||
`ASSERT(Depth_A, depth <= Depth)
|
||||
// if we clear the FIFO, it must be empty in the next cycle
|
||||
`ASSERT(CheckClrDepth_A, clr_i |=> depth == 0)
|
||||
// check write on full
|
||||
`ASSERT(WriteFull_A, depth == Depth && wvalid && !rready |=> depth == $past(depth),
|
||||
clk_i, !rst_ni || clr_i)
|
||||
// read empty
|
||||
`ASSERT(ReadEmpty_A, depth == 0 && rready && !wvalid |=> depth == 0,
|
||||
clk_i, !rst_ni || clr_i)
|
||||
|
||||
// this is unreachable in depth 1 no-pass through mode
|
||||
if (Depth == 1 && Pass) begin : gen_d1_passthru
|
||||
// check simultaneous write and read
|
||||
`ASSERT(WriteAndRead_A, wready && wvalid && rvalid && rready |=> depth == $past(depth),
|
||||
clk_i, !rst_ni || clr_i)
|
||||
end
|
||||
|
||||
if (Depth == 0) begin : gen_depth0
|
||||
// if there is no register, the FIFO is per definition pass-through
|
||||
`ASSERT_INIT(ZeroDepthNeedsPass_A, Pass == 1)
|
||||
// depth must remain zero
|
||||
`ASSERT(DepthAlwaysZero_A, depth == 0)
|
||||
// data is just passed through
|
||||
`ASSERT(DataPassThru_A, wdata == rdata)
|
||||
// FIFO is ready if downstream logic is ready
|
||||
`ASSERT(Wready_A, rready == wready)
|
||||
// valid input is valid output
|
||||
`ASSERT(Rvalid_A, rvalid == wvalid)
|
||||
// ensure full coverage
|
||||
`ASSERT(UnusedClr_A, prim_fifo_sync.gen_passthru_fifo.unused_clr == clr_i)
|
||||
end else begin : gen_depth_gt0
|
||||
// check wready
|
||||
`ASSERT(Wready_A, depth < Depth |-> wready)
|
||||
// check rvalid
|
||||
`ASSERT(Rvalid_A, depth > 0 |-> rvalid)
|
||||
// check write only
|
||||
`ASSERT(WriteOnly_A, wvalid && wready && !rready && depth < Depth |=>
|
||||
depth == $past(depth) + 1, clk_i, !rst_ni || clr_i)
|
||||
// check read only
|
||||
`ASSERT(ReadOnly_A, !wvalid && rready && rvalid && depth > 0 |=>
|
||||
depth == $past(depth) - 1, clk_i, !rst_ni || clr_i)
|
||||
end
|
||||
|
||||
if (Pass) begin : gen_pass_fwd
|
||||
// if we clear the FIFO, it must be empty in the next cycle
|
||||
// but we may also get a pass through
|
||||
`ASSERT(CheckClrValid_A, clr_i |=> wvalid == rvalid)
|
||||
end else begin : gen_nopass_fwd
|
||||
// if we clear the FIFO, it must be empty in the next cycle
|
||||
`ASSERT(CheckClrValid_A, clr_i |=> !rvalid)
|
||||
end
|
||||
|
||||
/////////////////////////
|
||||
// Backward Assertions //
|
||||
/////////////////////////
|
||||
|
||||
if (Pass) begin : gen_pass_bkwd
|
||||
// there is still space in the FIFO or downstream logic is ready
|
||||
`ASSERT(WreadySpacekBkwd_A, wready |-> depth < Depth || rready)
|
||||
// elements ready to be read or upstream data is valid
|
||||
`ASSERT(RvalidElemskBkwd_A, rvalid |-> depth > 0 || wvalid)
|
||||
end else begin : gen_nopass_bkwd
|
||||
// there is still space in the FIFO
|
||||
`ASSERT(WreadySpacekBkwd_A, wready |-> depth < Depth)
|
||||
// elements ready to be read
|
||||
`ASSERT(RvalidElemskBkwd_A, rvalid |-> depth > 0)
|
||||
end
|
||||
|
||||
// no more space in the FIFO
|
||||
`ASSERT(WreadyNoSpaceBkwd_A, !wready |-> depth == Depth)
|
||||
// elements ready to be read
|
||||
`ASSERT(RvalidNoElemskBkwd_A, !rvalid |-> depth == 0)
|
||||
|
||||
endmodule : prim_fifo_sync_assert_fpv
|
4
vendor/lowrisc_ip/prim/lint/prim.vlt
vendored
Normal file
4
vendor/lowrisc_ip/prim/lint/prim.vlt
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
63
vendor/lowrisc_ip/prim/lint/prim.waiver
vendored
Normal file
63
vendor/lowrisc_ip/prim/lint/prim.waiver
vendored
Normal file
|
@ -0,0 +1,63 @@
|
|||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# waiver file for prim
|
||||
|
||||
# prim_fifo_sync
|
||||
waive -rules {ONE_BIT_MEM_WIDTH} -location {prim_fifo_sync.sv} -msg {Memory 'gen_normal_fifo.storage' has word width which is single bit wide} \
|
||||
-comment "It is permissible that a FIFO has a wordwidth of 1bit"
|
||||
|
||||
# prim_fifo_async
|
||||
waive -rules {ASSIGN_SIGN} -location {prim_fifo_async.sv} -msg {Signed target 'i' assigned unsigned value 'PTR_WIDTH - 3'} \
|
||||
-comment "Parameter PTR_WIDTH is unsigned, but integer i is signed. This is fine. Changing the integer to unsigned might \
|
||||
cause issues with the for loop never exiting, because an unsigned integer can never become < 0."
|
||||
|
||||
# prim_assert
|
||||
waive -rules {UNDEF_MACRO_REF} -location {prim_assert.sv} -regexp {Macro definition for 'ASSERT_RPT' includes expansion of undefined macro '__(FILE|LINE)__'} \
|
||||
-comment "This is an UVM specific macro inside our assertion shortcuts"
|
||||
# unfortunately most tools do not support line wrapping within the declaration of macro functions, hence we have to waive
|
||||
# line length violations.
|
||||
waive -rules {LINE_LENGTH} -location {prim_assert.sv} -msg {Line length of} \
|
||||
-comment "Some macros cannot be line-wrapped, as some tools do not support that."
|
||||
|
||||
# prim_packer
|
||||
waive -rules INTEGER -location {prim_packer.sv} -msg {'i' of type int used as a non-constant value} \
|
||||
-comment "This assigns int i (signed) to a multibit logic variable (unsigned), which is fine"
|
||||
|
||||
# primitives: prim_subreg
|
||||
waive -rules INPUT_NOT_READ -location {prim_subreg.sv} -regexp {Input port 'wd' is not read from} \
|
||||
-comment "for RO wd is not used"
|
||||
|
||||
# primitives: prim_arbiter_*
|
||||
waive -rules PARTIAL_CONST_ASSIGN -location {prim_arbiter_*.sv} -regexp {'mask.0.' is conditionally assigned a constant} \
|
||||
-comment "makes the code more readable"
|
||||
waive -rules CONST_FF -location {prim_arbiter_*.sv} -regexp {Flip-flop 'mask.0.' is driven by constant} \
|
||||
-comment "makes the code more readable"
|
||||
|
||||
# primitives: prim_sram_arbiter
|
||||
waive -rules CONST_OUTPUT -location {prim_sram_arbiter.sv} -regexp {rsp_error.* is driven by constant} \
|
||||
-comment "SRAM protection is not yet implemented"
|
||||
|
||||
# primitives: prim_fifos
|
||||
|
||||
waive -rules VAR_INDEX_RANGE -location {prim_fifo_*sync.sv} -regexp {maximum value .* may be too large for 'storage'} \
|
||||
-comment "index is protected by control logic"
|
||||
waive -rules EXPLICIT_BITLEN -location {prim_fifo_*sync.sv} -regexp {Bit length not specified for constant '1'} \
|
||||
-comment "index is protected by control logic"
|
||||
waive -rules NOT_READ -location {prim_fifo_async.sv} -regexp {Signal 'nc_decval_msb' is not read} \
|
||||
-comment "Store temporary values. Not used intentionally"
|
||||
|
||||
waive -rules {INPUT_NOT_READ} -location {prim_fifo_sync.sv} -regexp {Input port '(clk_i|rst_ni)' is not read from, instance.*Depth=0\)} \
|
||||
-comment "In passthrough mode, clk and reset are not read form within this module"
|
||||
|
||||
# TL-UL fifo
|
||||
waive -rules {HIER_BRANCH_NOT_READ} -location {tlul_fifo_sync.sv} -regexp {Connected net '(clk_i|rst_ni)' at prim_fifo_sync.sv:.* is not read from in module 'prim_fifo_sync'} \
|
||||
-comment "In passthrough mode, clk and reset are not read form within this module"
|
||||
|
||||
# primitivies: prim_ram_2p_wrapper
|
||||
#
|
||||
#waive -rules INPUT_NOT_READ -location {prim_ram_*_wrapper*} -regexp {cfg_i} \
|
||||
# -comment "Register model doesn't need config port"
|
||||
#waive -rules NOT_READ -location {prim_ram_*_wrapper*} -regexp {(a|b)_rdata_(q|d)\[38} \
|
||||
# -comment "Syndrome is not going out to the interface"
|
34
vendor/lowrisc_ip/prim/pre_dv/prim_sync_reqack/README.md
vendored
Normal file
34
vendor/lowrisc_ip/prim/pre_dv/prim_sync_reqack/README.md
vendored
Normal file
|
@ -0,0 +1,34 @@
|
|||
REQ/ACK Syncronizer Verilator Testbench
|
||||
=======================================
|
||||
|
||||
This directory contains a basic, scratch Verilator testbench targeting
|
||||
functional verification of the REQ/ACK synchronizer primitive during
|
||||
development.
|
||||
|
||||
How to build and run the testbench
|
||||
----------------------------------
|
||||
|
||||
From the OpenTitan top level execute
|
||||
|
||||
```sh
|
||||
fusesoc --cores-root=. run --setup --build \
|
||||
lowrisc:dv_verilator:prim_sync_reqack_tb
|
||||
```
|
||||
to build the testbench and afterwards
|
||||
|
||||
```sh
|
||||
./build/lowrisc_dv_verilator_prim_sync_reqack_tb_0/default-verilator/Vprim_sync_reqack_tb \
|
||||
--trace
|
||||
```
|
||||
to run it.
|
||||
|
||||
Details of the testbench
|
||||
------------------------
|
||||
|
||||
- `rtl/prim_sync_reqack_tb.sv`: SystemVerilog testbench, instantiates and
|
||||
drives the DUT, counts handshakes in both domains, signals test end and
|
||||
result (pass/fail) to C++ via output ports. Change this file to e.g.
|
||||
for a different clock ratio or more transactions.
|
||||
- `cpp/prim_sync_reqack_tb.cc`: Contains main function and instantiation of
|
||||
SimCtrl, reads output ports of DUT and signals simulation termination to
|
||||
Verilator.
|
62
vendor/lowrisc_ip/prim/pre_dv/prim_sync_reqack/cpp/prim_sync_reqack_tb.cc
vendored
Normal file
62
vendor/lowrisc_ip/prim/pre_dv/prim_sync_reqack/cpp/prim_sync_reqack_tb.cc
vendored
Normal file
|
@ -0,0 +1,62 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#include "Vprim_sync_reqack_tb.h"
|
||||
#include "verilated_toplevel.h"
|
||||
#include "verilator_sim_ctrl.h"
|
||||
|
||||
#include <signal.h>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
|
||||
#include "sim_ctrl_extension.h"
|
||||
|
||||
class PrimSyncReqAckTB : public SimCtrlExtension {
|
||||
using SimCtrlExtension::SimCtrlExtension;
|
||||
|
||||
public:
|
||||
PrimSyncReqAckTB(prim_sync_reqack_tb *top);
|
||||
|
||||
void OnClock(unsigned long sim_time);
|
||||
|
||||
private:
|
||||
prim_sync_reqack_tb *top_;
|
||||
};
|
||||
|
||||
// Constructor:
|
||||
// - Set up top_ ptr
|
||||
PrimSyncReqAckTB::PrimSyncReqAckTB(prim_sync_reqack_tb *top)
|
||||
: SimCtrlExtension{}, top_(top) {}
|
||||
|
||||
// Function called once every clock cycle from SimCtrl
|
||||
void PrimSyncReqAckTB::OnClock(unsigned long sim_time) {
|
||||
if (top_->test_done_o) {
|
||||
VerilatorSimCtrl::GetInstance().RequestStop(top_->test_passed_o);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int ret_code;
|
||||
|
||||
// Init verilog instance
|
||||
prim_sync_reqack_tb top;
|
||||
|
||||
// Init sim
|
||||
VerilatorSimCtrl &simctrl = VerilatorSimCtrl::GetInstance();
|
||||
simctrl.SetTop(&top, &top.clk_i, &top.rst_ni,
|
||||
VerilatorSimCtrlFlags::ResetPolarityNegative);
|
||||
|
||||
// Create and register VerilatorSimCtrl extension
|
||||
PrimSyncReqAckTB primsyncreqacktb(&top);
|
||||
simctrl.RegisterExtension(&primsyncreqacktb);
|
||||
|
||||
std::cout << "Simulation of REQ/ACK Synchronizer primitive" << std::endl
|
||||
<< "============================================" << std::endl
|
||||
<< std::endl;
|
||||
|
||||
// Get pass / fail from Verilator
|
||||
ret_code = simctrl.Exec(argc, argv);
|
||||
|
||||
return ret_code;
|
||||
}
|
52
vendor/lowrisc_ip/prim/pre_dv/prim_sync_reqack/prim_sync_reqack_tb.core
vendored
Normal file
52
vendor/lowrisc_ip/prim/pre_dv/prim_sync_reqack/prim_sync_reqack_tb.core
vendored
Normal file
|
@ -0,0 +1,52 @@
|
|||
CAPI=2:
|
||||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
name: "lowrisc:dv_verilator:prim_sync_reqack_tb"
|
||||
description: "REQ/ACK Synchronizer Verilator TB"
|
||||
filesets:
|
||||
files_rtl:
|
||||
depend:
|
||||
- lowrisc:prim:all
|
||||
files:
|
||||
- rtl/prim_sync_reqack_tb.sv
|
||||
file_type: systemVerilogSource
|
||||
|
||||
files_dv_verilator:
|
||||
depend:
|
||||
- lowrisc:dv_verilator:simutil_verilator
|
||||
|
||||
files:
|
||||
- cpp/prim_sync_reqack_tb.cc
|
||||
file_type: cppSource
|
||||
|
||||
targets:
|
||||
default:
|
||||
default_tool: verilator
|
||||
filesets:
|
||||
- files_rtl
|
||||
- files_dv_verilator
|
||||
toplevel: prim_sync_reqack_tb
|
||||
tools:
|
||||
verilator:
|
||||
mode: cc
|
||||
verilator_options:
|
||||
# Disabling tracing reduces compile times by multiple times, but doesn't have a
|
||||
# huge influence on runtime performance. (Based on early observations.)
|
||||
- '--trace'
|
||||
- '--trace-fst' # this requires -DVM_TRACE_FMT_FST in CFLAGS below!
|
||||
- '--trace-structs'
|
||||
- '--trace-params'
|
||||
- '--trace-max-array 1024'
|
||||
# compiler flags
|
||||
#
|
||||
# -O
|
||||
# Optimization levels have a large impact on the runtime performance of the
|
||||
# simulation model. -O2 and -O3 are pretty similar, -Os is slower than -O2/-O3
|
||||
- '-CFLAGS "-std=c++11 -Wall -DVM_TRACE_FMT_FST -DTOPLEVEL_NAME=prim_sync_reqack_tb -g -O0"'
|
||||
- '-LDFLAGS "-pthread -lutil -lelf"'
|
||||
- "-Wall"
|
||||
- "-Wno-PINCONNECTEMPTY"
|
||||
# XXX: Cleanup all warnings and remove this option
|
||||
# (or make it more fine-grained at least)
|
||||
- "-Wno-fatal"
|
173
vendor/lowrisc_ip/prim/pre_dv/prim_sync_reqack/rtl/prim_sync_reqack_tb.sv
vendored
Normal file
173
vendor/lowrisc_ip/prim/pre_dv/prim_sync_reqack/rtl/prim_sync_reqack_tb.sv
vendored
Normal file
|
@ -0,0 +1,173 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// Scratch verification testbench for REQ/ACK synchronizer primitive
|
||||
|
||||
module prim_sync_reqack_tb #(
|
||||
) (
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
|
||||
output logic test_done_o,
|
||||
output logic test_passed_o
|
||||
);
|
||||
|
||||
// TB configuration
|
||||
localparam int unsigned NumTransactions = 8;
|
||||
localparam logic FastToSlow = 1'b1; // Select 1'b0 for SlowToFast
|
||||
localparam int unsigned Ratio = 4; // must be even and greater equal 2
|
||||
|
||||
// Derivation of parameters
|
||||
localparam int unsigned Ticks = Ratio/2;
|
||||
localparam int unsigned WidthTicks = $clog2(Ticks)+1;
|
||||
localparam int unsigned WidthTrans = $clog2(NumTransactions)+1;
|
||||
|
||||
// Derive slow clock (using a counter)
|
||||
logic [WidthTicks-1:0] count_clk_d, count_clk_q;
|
||||
assign count_clk_d = count_clk_q == (Ticks[WidthTicks-1:0]-1) ? '0 : count_clk_q + {{WidthTicks-1{1'b0}},{1'b1}};
|
||||
always_ff @(posedge clk_i) begin : reg_count_clk
|
||||
count_clk_q <= count_clk_d;
|
||||
end
|
||||
|
||||
logic clk_slow_d, clk_slow_q, clk_slow;
|
||||
assign clk_slow_d = count_clk_q == (Ticks[WidthTicks-1:0]-1) ? !clk_slow_q : clk_slow_q;
|
||||
always_ff @(posedge clk_i) begin : reg_clk_slow
|
||||
clk_slow_q <= clk_slow_d;
|
||||
end
|
||||
assign clk_slow = clk_slow_q;
|
||||
|
||||
// Sync reset to slow clock
|
||||
logic [1:0] rst_slow_nq;
|
||||
logic rst_slow_n;
|
||||
always_ff @(posedge clk_slow) begin
|
||||
rst_slow_nq <= {rst_slow_nq[0], rst_ni};
|
||||
end
|
||||
assign rst_slow_n = rst_ni & rst_slow_nq[1];
|
||||
|
||||
// Connect clocks
|
||||
logic clk_src, clk_dst;
|
||||
assign clk_src = FastToSlow ? clk_i : clk_slow;
|
||||
assign clk_dst = FastToSlow ? clk_slow : clk_i;
|
||||
|
||||
logic src_req, dst_req;
|
||||
logic src_ack, dst_ack;
|
||||
logic rst_done;
|
||||
|
||||
// Instantiate DUT
|
||||
prim_sync_reqack prim_sync_reqack (
|
||||
.clk_src_i (clk_src),
|
||||
.rst_src_ni (rst_slow_n),
|
||||
.clk_dst_i (clk_dst),
|
||||
.rst_dst_ni (rst_slow_n),
|
||||
|
||||
.src_req_i (src_req),
|
||||
.src_ack_o (src_ack),
|
||||
.dst_req_o (dst_req),
|
||||
.dst_ack_i (dst_ack)
|
||||
);
|
||||
|
||||
// Make sure we do not apply stimuli before the reset.
|
||||
always_ff @(posedge clk_slow or negedge rst_slow_n) begin
|
||||
if (!rst_slow_n) begin
|
||||
rst_done <= '1;
|
||||
end else begin
|
||||
rst_done <= rst_done;
|
||||
end
|
||||
end
|
||||
|
||||
// Create randomized ACK delay
|
||||
localparam int WIDTH_COUNT = 3;
|
||||
logic [31:0] tmp;
|
||||
logic [31-WIDTH_COUNT:0] unused_tmp;
|
||||
assign unused_tmp = tmp[31:WIDTH_COUNT];
|
||||
logic [WIDTH_COUNT-1:0] dst_count_clk_d, dst_count_clk_q;
|
||||
logic [WIDTH_COUNT-1:0] dst_count_clk_max_d, dst_count_clk_max_q;
|
||||
logic count_exp;
|
||||
assign count_exp = dst_count_clk_q == dst_count_clk_max_q;
|
||||
always_comb begin
|
||||
dst_count_clk_d = dst_count_clk_q;
|
||||
dst_count_clk_max_d = dst_count_clk_max_q;
|
||||
tmp = '0;
|
||||
if (dst_req && count_exp) begin
|
||||
// Clear counter
|
||||
dst_count_clk_d = '0;
|
||||
// Get new max
|
||||
tmp = $random;
|
||||
dst_count_clk_max_d = tmp[2:0];
|
||||
end else if (dst_req) begin
|
||||
// Increment
|
||||
dst_count_clk_d = dst_count_clk_q + {{WIDTH_COUNT-1{1'b0}},{1'b1}};
|
||||
end
|
||||
end
|
||||
always_ff @(posedge clk_dst or negedge rst_slow_n) begin : reg_dst_count_clk
|
||||
if (!rst_slow_n) begin
|
||||
dst_count_clk_q <= '0;
|
||||
dst_count_clk_max_q <= '0;
|
||||
end else begin
|
||||
dst_count_clk_q <= dst_count_clk_d;
|
||||
dst_count_clk_max_q <= dst_count_clk_max_d;
|
||||
end
|
||||
end
|
||||
|
||||
// Apply stimuli
|
||||
always_comb begin
|
||||
|
||||
src_req = 1'b0;
|
||||
dst_ack = 1'b0;
|
||||
|
||||
if (rst_done && rst_slow_n) begin
|
||||
// The source wants to perform handshakes at maximum rate.
|
||||
src_req = 1'b1;
|
||||
end
|
||||
|
||||
if (dst_req && count_exp) begin
|
||||
// The destination sends the ACK after a random delay.
|
||||
dst_ack = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
// Count handshakes on both sides
|
||||
logic [WidthTrans-1:0] src_count_d, src_count_q;
|
||||
logic [WidthTrans-1:0] dst_count_d, dst_count_q;
|
||||
assign src_count_d = (src_req && src_ack) ? src_count_q + 1'b1 : src_count_q;
|
||||
always_ff @(posedge clk_src or negedge rst_slow_n) begin : reg_src_count
|
||||
if (!rst_slow_n) begin
|
||||
src_count_q <= '0;
|
||||
end else begin
|
||||
src_count_q <= src_count_d;
|
||||
end
|
||||
end
|
||||
assign dst_count_d = (dst_req && dst_ack) ? dst_count_q + 1'b1 : dst_count_q;
|
||||
always_ff @(posedge clk_dst or negedge rst_slow_n) begin : reg_dst_count
|
||||
if (!rst_slow_n) begin
|
||||
dst_count_q <= '0;
|
||||
end else begin
|
||||
dst_count_q <= dst_count_d;
|
||||
end
|
||||
end
|
||||
|
||||
// Check responses, signal end of simulation
|
||||
always_ff @(posedge clk_i) begin : tb_ctrl
|
||||
test_done_o <= 1'b0;
|
||||
test_passed_o <= 1'b1;
|
||||
|
||||
if ((src_count_q == NumTransactions[WidthTrans-1:0]) &&
|
||||
(dst_count_q == NumTransactions[WidthTrans-1:0])) begin // Success
|
||||
|
||||
$display("\nSUCCESS: Performed %0d handshakes in both source and destination domain.",
|
||||
NumTransactions);
|
||||
$display("Finishing simulation now.\n");
|
||||
test_passed_o <= 1'b1;
|
||||
test_done_o <= 1'b1;
|
||||
end else if (((src_count_q > dst_count_q) && ((src_count_q - dst_count_q) > 1)) ||
|
||||
((dst_count_q > src_count_q) && ((dst_count_q - src_count_q) > 1))) begin // Failed
|
||||
$display("\nERROR: Performed %0d handshakes in source domain, and %0d in destination domain.",
|
||||
src_count_q, dst_count_q);
|
||||
$display("Finishing simulation now.\n");
|
||||
test_passed_o <= 1'b0;
|
||||
test_done_o <= 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
80
vendor/lowrisc_ip/prim/prim.core
vendored
Normal file
80
vendor/lowrisc_ip/prim/prim.core
vendored
Normal file
|
@ -0,0 +1,80 @@
|
|||
CAPI=2:
|
||||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# XXX: Split this core into multiple smaller ones.
|
||||
name: "lowrisc:prim:all:0.1"
|
||||
description: "Primitives"
|
||||
filesets:
|
||||
files_rtl:
|
||||
depend:
|
||||
- lowrisc:prim:ram_2p # for prim_ram_2p_adv
|
||||
- lowrisc:prim:secded # for prim_ram_2p_adv
|
||||
- lowrisc:prim:assert
|
||||
- lowrisc:prim:diff_decode # for prim_alert_sender/receiver
|
||||
- lowrisc:prim:pad_wrapper
|
||||
- lowrisc:prim:prim_pkg
|
||||
- lowrisc:prim:clock_mux2
|
||||
files:
|
||||
- rtl/prim_clock_inverter.sv
|
||||
- rtl/prim_clock_gating_sync.sv
|
||||
- rtl/prim_alert_pkg.sv
|
||||
- rtl/prim_alert_receiver.sv
|
||||
- rtl/prim_alert_sender.sv
|
||||
- rtl/prim_arbiter_ppc.sv
|
||||
- rtl/prim_arbiter_tree.sv
|
||||
- rtl/prim_esc_pkg.sv
|
||||
- rtl/prim_esc_receiver.sv
|
||||
- rtl/prim_esc_sender.sv
|
||||
- rtl/prim_sram_arbiter.sv
|
||||
- rtl/prim_fifo_async.sv
|
||||
- rtl/prim_fifo_sync.sv
|
||||
- rtl/prim_flop_2sync.sv
|
||||
- rtl/prim_sync_reqack.sv
|
||||
- rtl/prim_keccak.sv
|
||||
- rtl/prim_lfsr.sv
|
||||
- rtl/prim_packer.sv
|
||||
- rtl/prim_cipher_pkg.sv
|
||||
- rtl/prim_present.sv
|
||||
- rtl/prim_prince.sv
|
||||
- rtl/prim_gate_gen.sv
|
||||
- rtl/prim_pulse_sync.sv
|
||||
- rtl/prim_filter.sv
|
||||
- rtl/prim_filter_ctr.sv
|
||||
- rtl/prim_subreg.sv
|
||||
- rtl/prim_subreg_ext.sv
|
||||
- rtl/prim_intr_hw.sv
|
||||
- rtl/prim_ram_2p_adv.sv
|
||||
- rtl/prim_ram_2p_async_adv.sv
|
||||
file_type: systemVerilogSource
|
||||
|
||||
files_verilator_waiver:
|
||||
depend:
|
||||
# common waivers
|
||||
- lowrisc:lint:common
|
||||
files:
|
||||
- lint/prim.vlt
|
||||
file_type: vlt
|
||||
|
||||
files_ascentlint_waiver:
|
||||
depend:
|
||||
# common waivers
|
||||
- lowrisc:lint:common
|
||||
files:
|
||||
- lint/prim.waiver
|
||||
file_type: waiver
|
||||
|
||||
files_veriblelint_waiver:
|
||||
depend:
|
||||
# common waivers
|
||||
- lowrisc:lint:common
|
||||
- lowrisc:lint:comportable
|
||||
|
||||
targets:
|
||||
default:
|
||||
filesets:
|
||||
- tool_verilator ? (files_verilator_waiver)
|
||||
- tool_ascentlint ? (files_ascentlint_waiver)
|
||||
- tool_veriblelint ? (files_veriblelint_waiver)
|
||||
- files_rtl
|
25
vendor/lowrisc_ip/prim/prim_clock_gating.core
vendored
Normal file
25
vendor/lowrisc_ip/prim/prim_clock_gating.core
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
CAPI=2:
|
||||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
name: "lowrisc:prim:clock_gating"
|
||||
description: "Clock gating primitives"
|
||||
filesets:
|
||||
primgen_dep:
|
||||
depend:
|
||||
- lowrisc:prim:prim_pkg
|
||||
- lowrisc:prim:primgen
|
||||
|
||||
generate:
|
||||
impl:
|
||||
generator: primgen
|
||||
parameters:
|
||||
prim_name: clock_gating
|
||||
|
||||
targets:
|
||||
default:
|
||||
filesets:
|
||||
- primgen_dep
|
||||
generate:
|
||||
- impl
|
25
vendor/lowrisc_ip/prim/prim_clock_mux2.core
vendored
Normal file
25
vendor/lowrisc_ip/prim/prim_clock_mux2.core
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
CAPI=2:
|
||||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
name: "lowrisc:prim:clock_mux2"
|
||||
description: "2-input clock multiplexer"
|
||||
filesets:
|
||||
primgen_dep:
|
||||
depend:
|
||||
- lowrisc:prim:prim_pkg
|
||||
- lowrisc:prim:primgen
|
||||
|
||||
generate:
|
||||
impl:
|
||||
generator: primgen
|
||||
parameters:
|
||||
prim_name: clock_mux2
|
||||
|
||||
targets:
|
||||
default:
|
||||
filesets:
|
||||
- primgen_dep
|
||||
generate:
|
||||
- impl
|
|
@ -3,12 +3,14 @@ CAPI=2:
|
|||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
name: "lowrisc:prim:lfsr:0.1"
|
||||
description: "LFSR primitive"
|
||||
name: "lowrisc:prim:diff_decode"
|
||||
description: "prim"
|
||||
filesets:
|
||||
files_rtl:
|
||||
depend:
|
||||
- lowrisc:prim:assert
|
||||
files:
|
||||
- rtl/prim_lfsr.sv
|
||||
- rtl/prim_diff_decode.sv
|
||||
file_type: systemVerilogSource
|
||||
|
||||
targets:
|
25
vendor/lowrisc_ip/prim/prim_flash.core
vendored
Normal file
25
vendor/lowrisc_ip/prim/prim_flash.core
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
CAPI=2:
|
||||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
name: "lowrisc:prim:flash"
|
||||
description: "Flash memory"
|
||||
filesets:
|
||||
primgen_dep:
|
||||
depend:
|
||||
- lowrisc:prim:prim_pkg
|
||||
- lowrisc:prim:primgen
|
||||
|
||||
generate:
|
||||
impl:
|
||||
generator: primgen
|
||||
parameters:
|
||||
prim_name: flash
|
||||
|
||||
targets:
|
||||
default:
|
||||
filesets:
|
||||
- primgen_dep
|
||||
generate:
|
||||
- impl
|
|
@ -3,12 +3,15 @@ CAPI=2:
|
|||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
name: "lowrisc:prim:ram_1p:0.1"
|
||||
description: "Single port RAM (technology independent)"
|
||||
name: "lowrisc:prim:gf_mult"
|
||||
description: "Galois multiplier"
|
||||
filesets:
|
||||
files_rtl:
|
||||
depend:
|
||||
- lowrisc:prim_generic:ram_1p
|
||||
- lowrisc:prim:assert
|
||||
files:
|
||||
- rtl/prim_gf_mult.sv
|
||||
file_type: systemVerilogSource
|
||||
|
||||
targets:
|
||||
default:
|
25
vendor/lowrisc_ip/prim/prim_otp.core
vendored
Normal file
25
vendor/lowrisc_ip/prim/prim_otp.core
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
CAPI=2:
|
||||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
name: "lowrisc:prim:otp"
|
||||
description: "One-Time Programmable (OTP) memory"
|
||||
filesets:
|
||||
primgen_dep:
|
||||
depend:
|
||||
- lowrisc:prim:prim_pkg
|
||||
- lowrisc:prim:primgen
|
||||
|
||||
generate:
|
||||
impl:
|
||||
generator: primgen
|
||||
parameters:
|
||||
prim_name: otp
|
||||
|
||||
targets:
|
||||
default:
|
||||
filesets:
|
||||
- primgen_dep
|
||||
generate:
|
||||
- impl
|
25
vendor/lowrisc_ip/prim/prim_pad_wrapper.core
vendored
Normal file
25
vendor/lowrisc_ip/prim/prim_pad_wrapper.core
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
CAPI=2:
|
||||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
name: "lowrisc:prim:pad_wrapper"
|
||||
description: "PAD wrapper"
|
||||
filesets:
|
||||
primgen_dep:
|
||||
depend:
|
||||
- lowrisc:prim:prim_pkg
|
||||
- lowrisc:prim:primgen
|
||||
|
||||
generate:
|
||||
impl:
|
||||
generator: primgen
|
||||
parameters:
|
||||
prim_name: pad_wrapper
|
||||
|
||||
targets:
|
||||
default:
|
||||
filesets:
|
||||
- primgen_dep
|
||||
generate:
|
||||
- impl
|
23
vendor/lowrisc_ip/prim/prim_pkg.core
vendored
Normal file
23
vendor/lowrisc_ip/prim/prim_pkg.core
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
CAPI=2:
|
||||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
name: "lowrisc:prim:prim_pkg:0.1"
|
||||
description: "Constants used by the primitives"
|
||||
filesets:
|
||||
primgen_dep:
|
||||
depend:
|
||||
- lowrisc:prim:primgen
|
||||
|
||||
generate:
|
||||
impl:
|
||||
generator: primgen
|
||||
parameters:
|
||||
action: generate_prim_pkg
|
||||
|
||||
targets:
|
||||
default:
|
||||
filesets:
|
||||
- primgen_dep
|
||||
generate:
|
||||
- impl
|
25
vendor/lowrisc_ip/prim/prim_ram_1p.core
vendored
Normal file
25
vendor/lowrisc_ip/prim/prim_ram_1p.core
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
CAPI=2:
|
||||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
name: "lowrisc:prim:ram_1p"
|
||||
description: "1 port random-access memory"
|
||||
filesets:
|
||||
primgen_dep:
|
||||
depend:
|
||||
- lowrisc:prim:prim_pkg
|
||||
- lowrisc:prim:primgen
|
||||
|
||||
generate:
|
||||
impl:
|
||||
generator: primgen
|
||||
parameters:
|
||||
prim_name: ram_1p
|
||||
|
||||
targets:
|
||||
default:
|
||||
filesets:
|
||||
- primgen_dep
|
||||
generate:
|
||||
- impl
|
19
vendor/lowrisc_ip/prim/prim_ram_1p_adv.core
vendored
Normal file
19
vendor/lowrisc_ip/prim/prim_ram_1p_adv.core
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
CAPI=2:
|
||||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
name: "lowrisc:prim:ram_1p_adv:0.1"
|
||||
description: "Single-port RAM primitive with advanced features"
|
||||
filesets:
|
||||
files_rtl:
|
||||
depend:
|
||||
- lowrisc:prim:ram_1p
|
||||
files:
|
||||
- rtl/prim_ram_1p_adv.sv
|
||||
file_type: systemVerilogSource
|
||||
|
||||
targets:
|
||||
default:
|
||||
filesets:
|
||||
- files_rtl
|
25
vendor/lowrisc_ip/prim/prim_ram_2p.core
vendored
Normal file
25
vendor/lowrisc_ip/prim/prim_ram_2p.core
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
CAPI=2:
|
||||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
name: "lowrisc:prim:ram_2p"
|
||||
description: "2 port random-access memory"
|
||||
filesets:
|
||||
primgen_dep:
|
||||
depend:
|
||||
- lowrisc:prim:prim_pkg
|
||||
- lowrisc:prim:primgen
|
||||
|
||||
generate:
|
||||
impl:
|
||||
generator: primgen
|
||||
parameters:
|
||||
prim_name: ram_2p
|
||||
|
||||
targets:
|
||||
default:
|
||||
filesets:
|
||||
- primgen_dep
|
||||
generate:
|
||||
- impl
|
25
vendor/lowrisc_ip/prim/prim_rom.core
vendored
Normal file
25
vendor/lowrisc_ip/prim/prim_rom.core
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
CAPI=2:
|
||||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
name: "lowrisc:prim:rom"
|
||||
description: "Read-only memory (ROM)"
|
||||
filesets:
|
||||
primgen_dep:
|
||||
depend:
|
||||
- lowrisc:prim:prim_pkg
|
||||
- lowrisc:prim:primgen
|
||||
|
||||
generate:
|
||||
impl:
|
||||
generator: primgen
|
||||
parameters:
|
||||
prim_name: rom
|
||||
|
||||
targets:
|
||||
default:
|
||||
filesets:
|
||||
- primgen_dep
|
||||
generate:
|
||||
- impl
|
|
@ -10,6 +10,8 @@ filesets:
|
|||
files:
|
||||
- rtl/prim_secded_28_22_dec.sv
|
||||
- rtl/prim_secded_28_22_enc.sv
|
||||
- rtl/prim_secded_39_32_dec.sv
|
||||
- rtl/prim_secded_39_32_enc.sv
|
||||
- rtl/prim_secded_72_64_dec.sv
|
||||
- rtl/prim_secded_72_64_enc.sv
|
||||
file_type: systemVerilogSource
|
17
vendor/lowrisc_ip/prim/prim_util_memload.core
vendored
Normal file
17
vendor/lowrisc_ip/prim/prim_util_memload.core
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
CAPI=2:
|
||||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
name: "lowrisc:prim:util_memload"
|
||||
description: "Memory loaders for simulation. To be included in a memory primitive."
|
||||
filesets:
|
||||
files_rtl:
|
||||
files:
|
||||
- rtl/prim_util_memload.sv: {is_include_file: true}
|
||||
file_type: systemVerilogSource
|
||||
|
||||
targets:
|
||||
default:
|
||||
filesets:
|
||||
- files_rtl
|
10
vendor/lowrisc_ip/prim/primgen.core
vendored
Normal file
10
vendor/lowrisc_ip/prim/primgen.core
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
CAPI=2:
|
||||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
name: "lowrisc:prim:primgen:0.1"
|
||||
|
||||
generators:
|
||||
primgen:
|
||||
interpreter: python3
|
||||
command: util/primgen.py
|
17
vendor/lowrisc_ip/prim/rtl/prim_alert_pkg.sv
vendored
Normal file
17
vendor/lowrisc_ip/prim/rtl/prim_alert_pkg.sv
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package prim_alert_pkg;
|
||||
typedef struct packed {
|
||||
logic alert_p;
|
||||
logic alert_n;
|
||||
} alert_tx_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic ping_p;
|
||||
logic ping_n;
|
||||
logic ack_p;
|
||||
logic ack_n;
|
||||
} alert_rx_t;
|
||||
endpackage
|
214
vendor/lowrisc_ip/prim/rtl/prim_alert_receiver.sv
vendored
Normal file
214
vendor/lowrisc_ip/prim/rtl/prim_alert_receiver.sv
vendored
Normal file
|
@ -0,0 +1,214 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// The alert receiver primitive decodes alerts that have been differentially
|
||||
// encoded and transmitted via a handshake protocol on alert_p/n and
|
||||
// ack_p/n. In case an alert handshake is initiated, the output alert_o will
|
||||
// immediately be asserted (even before completion of the handshake).
|
||||
//
|
||||
// In case the differential input is not correctly encoded, this module will
|
||||
// raise an error by asserting integ_fail_o.
|
||||
//
|
||||
// Further, the module supports ping testing of the alert diff pair. In order to
|
||||
// initiate a ping test, ping_en_i shall be set to 1'b1 until ping_ok_o is
|
||||
// asserted for one cycle. The signal may be de-asserted (e.g. after a long)
|
||||
// timeout period. However note that all ping responses that come in after
|
||||
// deasserting ping_en_i will be treated as native alerts.
|
||||
//
|
||||
// The protocol works in both asynchronous and synchronous cases. In the
|
||||
// asynchronous case, the parameter AsyncOn must be set to 1'b1 in order to
|
||||
// instantiate additional synchronization logic. Further, it must be ensured
|
||||
// that the timing skew between all diff pairs is smaller than the shortest
|
||||
// clock period of the involved clocks.
|
||||
//
|
||||
// Note that in case of synchronous operation, alerts on the diffpair are
|
||||
// decoded combinationally and forwarded on alert_o within the same cycle.
|
||||
//
|
||||
// See also: prim_alert_sender, prim_diff_decode, alert_handler
|
||||
|
||||
`include "prim_assert.sv"
|
||||
|
||||
module prim_alert_receiver
|
||||
import prim_alert_pkg::*;
|
||||
#(
|
||||
// enables additional synchronization logic
|
||||
parameter bit AsyncOn = 1'b0
|
||||
) (
|
||||
input clk_i,
|
||||
input rst_ni,
|
||||
// this triggers a ping test. keep asserted
|
||||
// until ping_ok_o is asserted.
|
||||
input ping_en_i,
|
||||
output logic ping_ok_o,
|
||||
// asserted if signal integrity issue detected
|
||||
output logic integ_fail_o,
|
||||
// alert output (pulsed high) if a handshake is initiated
|
||||
// on alert_p/n and no ping request is outstanding
|
||||
output logic alert_o,
|
||||
// ping input diff pair and ack diff pair
|
||||
output alert_rx_t alert_rx_o,
|
||||
// alert output diff pair
|
||||
input alert_tx_t alert_tx_i
|
||||
);
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// decode differential signals //
|
||||
/////////////////////////////////
|
||||
logic alert_level, alert_sigint;
|
||||
|
||||
prim_diff_decode #(
|
||||
.AsyncOn(AsyncOn)
|
||||
) i_decode_alert (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
.diff_pi ( alert_tx_i.alert_p ),
|
||||
.diff_ni ( alert_tx_i.alert_n ),
|
||||
.level_o ( alert_level ),
|
||||
.rise_o ( ),
|
||||
.fall_o ( ),
|
||||
.event_o ( ),
|
||||
.sigint_o ( alert_sigint )
|
||||
);
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// main protocol FSM that drives the diff outputs //
|
||||
/////////////////////////////////////////////////////
|
||||
typedef enum logic [1:0] {Idle, HsAckWait, Pause0, Pause1} state_e;
|
||||
state_e state_d, state_q;
|
||||
logic ping_rise;
|
||||
logic ping_tog_d, ping_tog_q, ack_d, ack_q;
|
||||
logic ping_en_d, ping_en_q;
|
||||
logic ping_pending_d, ping_pending_q;
|
||||
|
||||
// signal ping request upon positive transition on ping_en_i
|
||||
// signalling is performed by a level change event on the diff output
|
||||
assign ping_en_d = ping_en_i;
|
||||
assign ping_rise = ping_en_i && !ping_en_q;
|
||||
assign ping_tog_d = (ping_rise) ? ~ping_tog_q : ping_tog_q;
|
||||
|
||||
// the ping pending signal is used to in the FSM to distinguish whether the
|
||||
// incoming handshake shall be treated as an alert or a ping response.
|
||||
// it is important that this is only set on a rising ping_en level change, since
|
||||
// otherwise the ping enable signal could be abused to "mask" all native alerts
|
||||
// as ping responses by constantly tying it to 1.
|
||||
assign ping_pending_d = ping_rise | ((~ping_ok_o) & ping_en_i & ping_pending_q);
|
||||
|
||||
// diff pair outputs
|
||||
assign alert_rx_o.ack_p = ack_q;
|
||||
assign alert_rx_o.ack_n = ~ack_q;
|
||||
assign alert_rx_o.ping_p = ping_tog_q;
|
||||
assign alert_rx_o.ping_n = ~ping_tog_q;
|
||||
|
||||
// this FSM receives the four phase handshakes from the alert receiver
|
||||
// note that the latency of the alert_p/n input diff pair is at least one
|
||||
// cycle until it enters the receiver FSM. the same holds for the ack_* diff
|
||||
// pair outputs.
|
||||
always_comb begin : p_fsm
|
||||
// default
|
||||
state_d = state_q;
|
||||
ack_d = 1'b0;
|
||||
ping_ok_o = 1'b0;
|
||||
integ_fail_o = 1'b0;
|
||||
alert_o = 1'b0;
|
||||
|
||||
unique case (state_q)
|
||||
Idle: begin
|
||||
// wait for handshake to be initiated
|
||||
if (alert_level) begin
|
||||
state_d = HsAckWait;
|
||||
ack_d = 1'b1;
|
||||
// signal either an alert or ping received on the output
|
||||
if (ping_pending_q) begin
|
||||
ping_ok_o = 1'b1;
|
||||
end else begin
|
||||
alert_o = 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
// waiting for deassertion of alert to complete HS
|
||||
HsAckWait: begin
|
||||
if (!alert_level) begin
|
||||
state_d = Pause0;
|
||||
end else begin
|
||||
ack_d = 1'b1;
|
||||
end
|
||||
end
|
||||
// pause cycles between back-to-back handshakes
|
||||
Pause0: state_d = Pause1;
|
||||
Pause1: state_d = Idle;
|
||||
default : ; // full case
|
||||
endcase
|
||||
|
||||
// override in case of sigint
|
||||
if (alert_sigint) begin
|
||||
state_d = Idle;
|
||||
ack_d = 1'b0;
|
||||
ping_ok_o = 1'b0;
|
||||
integ_fail_o = 1'b1;
|
||||
alert_o = 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : p_reg
|
||||
if (!rst_ni) begin
|
||||
state_q <= Idle;
|
||||
ack_q <= 1'b0;
|
||||
ping_tog_q <= 1'b0;
|
||||
ping_en_q <= 1'b0;
|
||||
ping_pending_q <= 1'b0;
|
||||
end else begin
|
||||
state_q <= state_d;
|
||||
ack_q <= ack_d;
|
||||
ping_tog_q <= ping_tog_d;
|
||||
ping_en_q <= ping_en_d;
|
||||
ping_pending_q <= ping_pending_d;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
////////////////
|
||||
// assertions //
|
||||
////////////////
|
||||
|
||||
// check whether all outputs have a good known state after reset
|
||||
`ASSERT_KNOWN(PingOkKnownO_A, ping_ok_o)
|
||||
`ASSERT_KNOWN(IntegFailKnownO_A, integ_fail_o)
|
||||
`ASSERT_KNOWN(AlertKnownO_A, alert_o)
|
||||
`ASSERT_KNOWN(PingPKnownO_A, alert_rx_o)
|
||||
|
||||
// check encoding of outgoing diffpairs
|
||||
`ASSERT(PingDiffOk_A, alert_rx_o.ping_p ^ alert_rx_o.ping_n)
|
||||
`ASSERT(AckDiffOk_A, alert_rx_o.ack_p ^ alert_rx_o.ack_n)
|
||||
// ping request at input -> need to see encoded ping request
|
||||
`ASSERT(PingRequest0_A, ##1 $rose(ping_en_i) |=> $changed(alert_rx_o.ping_p))
|
||||
// ping response implies it has been requested
|
||||
`ASSERT(PingResponse0_A, ping_ok_o |-> ping_pending_q)
|
||||
// correctly latch ping request
|
||||
`ASSERT(PingPending_A, ##1 $rose(ping_en_i) |=> ping_pending_q)
|
||||
|
||||
if (AsyncOn) begin : gen_async_assert
|
||||
// signal integrity check propagation
|
||||
`ASSERT(SigInt_A, alert_tx_i.alert_p == alert_tx_i.alert_n [*2] |->
|
||||
##2 integ_fail_o)
|
||||
// TODO: need to add skewed cases as well, the assertions below assume no skew at the moment
|
||||
// ping response
|
||||
`ASSERT(PingResponse1_A, ##1 $rose(alert_tx_i.alert_p) &&
|
||||
(alert_tx_i.alert_p ^ alert_tx_i.alert_n) ##2 state_q == Idle && ping_pending_q |->
|
||||
ping_ok_o, clk_i, !rst_ni || integ_fail_o)
|
||||
// alert
|
||||
`ASSERT(Alert_A, ##1 $rose(alert_tx_i.alert_p) && (alert_tx_i.alert_p ^ alert_tx_i.alert_n) ##2
|
||||
state_q == Idle && !ping_pending_q |-> alert_o, clk_i, !rst_ni || integ_fail_o)
|
||||
end else begin : gen_sync_assert
|
||||
// signal integrity check propagation
|
||||
`ASSERT(SigInt_A, alert_tx_i.alert_p == alert_tx_i.alert_n |-> integ_fail_o)
|
||||
// ping response
|
||||
`ASSERT(PingResponse1_A, ##1 $rose(alert_tx_i.alert_p) && state_q == Idle && ping_pending_q |->
|
||||
ping_ok_o, clk_i, !rst_ni || integ_fail_o)
|
||||
// alert
|
||||
`ASSERT(Alert_A, ##1 $rose(alert_tx_i.alert_p) && state_q == Idle && !ping_pending_q |->
|
||||
alert_o, clk_i, !rst_ni || integ_fail_o)
|
||||
end
|
||||
|
||||
endmodule : prim_alert_receiver
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue