Commit 5ece31a3 authored by GuillemCabo's avatar GuillemCabo Committed by Guillem
Browse files

add com_tr

Error detection for combinational circuit outputs by means of time delayed sampling
parent 72775395
//-----------------------------------------------------
// ProjectName: De-RISC/SELENE
// Function : Single event transient error detector for comb. logic.
// Description: This module takes a signal coming from a combinational block
// and registers the signal at two different points of the clock cycle.
// To achive that two clocks are needed, one is the regular system clock
// , the other has to be delayed by a given amount based on the type
// of faults and the clock period of the implementation.
//
// Coder : G.Cabo
// References : Fault-Tolerance Techniques for SRAM-Based FPGAs - ISBN 978-0-387-31069-5
`default_nettype none
`timescale 1 ns / 1 ps
`ifndef SYNT
`ifdef FORMAL
`define ASSERTIONS
`endif
`endif
module com_tr #
(
// Width of sampled signal
parameter integer IN_WIDTH = 1
)
(
// Global Clock Signal
input wire clk_i,
// Delayed Clock Signal. Delay can't be larger than clock cycle.
input wire dclk_i,
// Global Reset Signal. This Signal is Active LOW
input wire rstn_i,
// Signal to monitor
input wire [IN_WIDTH-1:0] signal_i,
// Enable for error detection
output reg error_o
);
logic [IN_WIDTH-1:0] reg1;
logic [IN_WIDTH-1:0] reg2;
logic error_int;
//Register sampling at global clock
always_ff @(posedge clk_i) begin
if(rstn_i == 1'b0 ) begin
reg1<='{default:0};
end else begin
reg1<=signal_i;
end
end
//Register sampling at delayed clock
always_ff @(posedge dclk_i) begin
if(rstn_i == 1'b0 ) begin
reg2<='{default:0};
end else begin
reg2<=signal_i;
end
end
//XOR the values of registers to detect errors. OR all XORed bits to rise the
//error signal.
assign error_int = |(reg1 ^ reg2);
//Register the outcome at the next positive edge to avoid false errors
// due to clock and dcloc sync
always_ff @(posedge clk_i) begin
error_o <= error_int;
end
////////////////////////////////////////////////////////////////////////////////
//
// Formal Verification section begins here.
//
////////////////////////////////////////////////////////////////////////////////
`ifdef FORMAL
`endif
endmodule
`default_nettype wire //allow compatibility with legacy code and xilinx ip
IPs for Transient and permanent error detection and correction mechanisms
* com\_tr.sv: Single or multiple event transient error detector for
combinational logic. Registered output error signal.
`define START_GREEN_PRINT $write("%c[1;32m",27);
`define START_RED_PRINT $write("%c[1;31m",27);
`define END_COLOR_PRINT $write("%c[0m",27);
# Use ./runtest.sh -batch to run the simulation in batch mode
TOP=../../..
vlib com_tr
vmap work $PWD/com_tr
vlog +acc=rn +incdir+$TOP/hdl/ $TOP/submodules/seu_ip/com_tr.sv tb_com_tr.sv ./colors.vh
vmake com_tr/ > Makefile
if [ -z "$1" ]
then
vsim work.tb_com_tr -do "do wave.do" -do "run -all"
else
vsim work.tb_com_tr $1 -do "do save_wave.do"
fi
set WildcardFilter ""
log -r /*
run -all
quit
//-----------------------------------------------------
// ProjectName: De-RISC/SELENE
// Function : TB for single event transient error detector for comb. logic.
// Description: This module takes a signal coming from a combinational block
// and registers the signal at two different points of the clock cycle.
// To achive that two clocks are needed, one is the regular system clock
// , the other has to be delayed by a given amount based on the type
// of faults and the clock period of the implementation.
// Designed to be used with QuestaSim.
//
// Coder : G.Cabo
// References : Fault-Tolerance Techniques for SRAM-Based FPGAs - ISBN 978-0-387-31069-5
`timescale 1 ns / 1 ns
`default_nettype none
`include "colors.vh"
//***Headers***
//***Test bench***
module tb_com_tr();
//***Parameters***
parameter CLK_PERIOD = 8;
parameter CLK_HALF_PERIOD = CLK_PERIOD / 2;
parameter CLK_QUARTER_PERIOD = CLK_HALF_PERIOD/ 2;
//***DUT parameters***
parameter TB_IN_WIDTH = 32;
//***Signals***
reg tb_clk_i ;
reg tb_dclk_i ;
reg tb_rstn_i ;
reg [TB_IN_WIDTH-1:0] tb_signal_i;
reg tb_error_o;
//store name of test for easier debug of waveform
reg[64*8:0] tb_test_name;
reg tb_fail = 0;
//***Module***
com_tr #(
.IN_WIDTH(TB_IN_WIDTH)
)dut_com_tr (
.clk_i(tb_clk_i),
.dclk_i(tb_dclk_i),
.rstn_i(tb_rstn_i),
.signal_i(tb_signal_i),
.error_o(tb_error_o)
);
//***clk_gen***
initial tb_clk_i = 1;
initial tb_dclk_i = 1;
always #CLK_HALF_PERIOD tb_dclk_i = !tb_dclk_i;
always @(posedge tb_dclk_i, negedge tb_dclk_i) begin
#CLK_QUARTER_PERIOD;
tb_clk_i= !tb_clk_i;
end
//***task automatic reset_dut***
task automatic reset_dut;
begin
$display("*** Toggle reset.");
tb_test_name = "reset_dut";
tb_rstn_i <= 1'b0;
#CLK_PERIOD;
tb_rstn_i <= 1'b1;
#CLK_PERIOD;
$display("Done");
tb_test_name = "";
end
endtask
//***task automatic init_sim***
//Initialize TB registers to a known state.
task automatic init_sim;
begin
$display("*** init sim.");
tb_test_name = "init_sim";
$display("Done");
tb_test_name = "";
end
endtask
//***task automatic init_dump***
task automatic init_dump;
begin
$dumpfile("test.vcd");
$dumpvars(0,dut_com_tr);
end
endtask
//***task automatic test_sim***
task automatic test_sim;
begin
int unsigned temp=1;
$display("*** test_sim.");
tb_test_name="test_sim";
//Sync with main clock
#CLK_HALF_PERIOD;
#CLK_QUARTER_PERIOD;
//**test***
test_no_seu(100000,temp);
test_meu(100000,temp);
//check results
if(temp!=1) begin
tb_fail = 1;
$error("FAIL test_sim.");
`START_RED_PRINT
$display("FAIL");
`END_COLOR_PRINT
end
$display("Done");
tb_test_name="";
end
endtask
//***task automatic test_no_seu***
// Random input events are generated, but no
// single event upsets are forced.
// Returns 0 if test fails and 1 if test passes
task automatic test_no_seu(input int n_tries, output int rval);
begin
int tmp=0;
$display("*** test_no_seu");
tb_test_name="test_no_seu";
//**test***
for(int i=0;i<n_tries;i++) begin
tb_signal_i = $urandom();
#CLK_PERIOD;
//check results
if(tb_error_o!=0) begin
tmp=1;
end
end
//check results
if(tmp!=0) begin
$error("FAIL test_no_seu. SEU detected but no SEU has been generated");
`START_RED_PRINT
$display("FAIL");
`END_COLOR_PRINT
rval=0;
end
$display("Done");
tb_test_name="";
rval=1;
end
endtask
//***task automatic test_meu***
// Random input events are generated, along
// single or multiple event upsets at the rising edge of main clock.
// Returns 0 if test fails and 1 if test passes
task automatic test_meu(input int n_tries, output int rval);
begin
int valid_value;
int upset_value;
int tmp=0;
$display("*** test_meu");
tb_test_name="test_meu";
//**test***
for(int i=0;i<n_tries;i++) begin
valid_value = $urandom();
upset_value = $urandom();
//Ensure that the upset actually changes the value
while(upset_value == valid_value) begin
upset_value = $urandom();
end
//set the invalid value over the rising edge of main clock
tb_signal_i =upset_value;
#CLK_QUARTER_PERIOD
//after a fiven period smaller than the delay of dclock the
//valid value is set to the inputs
tb_signal_i =valid_value;
#CLK_QUARTER_PERIOD
#CLK_QUARTER_PERIOD
#CLK_QUARTER_PERIOD
//Errors are registered and take one extra cycle to be signaled from output register
//check results
#CLK_PERIOD;
if(tb_error_o!=1) begin
tmp=1;
end
end
//check results
if(tmp!=0) begin
$error("FAIL test_meu.Some SEU have not detected");
`START_RED_PRINT
$display("FAIL");
`END_COLOR_PRINT
rval=0;
end
$display("Done");
tb_test_name="";
rval=1;
end
endtask
initial begin
integer retv;
tb_rstn_i<='{default:0};
tb_signal_i <='{default:0};
init_sim();
init_dump();
reset_dut();
test_sim();
$finish;
end
endmodule
`default_nettype wire
onerror {resume}
quietly WaveActivateNextPane {} 0
add wave -noupdate /tb_com_tr/CLK_PERIOD
add wave -noupdate /tb_com_tr/CLK_HALF_PERIOD
add wave -noupdate /tb_com_tr/CLK_QUARTER_PERIOD
add wave -noupdate /tb_com_tr/TB_IN_WIDTH
add wave -noupdate /tb_com_tr/tb_clk_i
add wave -noupdate /tb_com_tr/tb_dclk_i
add wave -noupdate /tb_com_tr/tb_rstn_i
add wave -noupdate /tb_com_tr/tb_signal_i
add wave -noupdate /tb_com_tr/tb_error_o
add wave -noupdate /tb_com_tr/tb_test_name
add wave -noupdate /tb_com_tr/tb_fail
add wave -noupdate -expand -group internal /tb_com_tr/dut_com_tr/IN_WIDTH
add wave -noupdate -expand -group internal /tb_com_tr/dut_com_tr/clk_i
add wave -noupdate -expand -group internal /tb_com_tr/dut_com_tr/dclk_i
add wave -noupdate -expand -group internal /tb_com_tr/dut_com_tr/rstn_i
add wave -noupdate -expand -group internal /tb_com_tr/dut_com_tr/signal_i
add wave -noupdate -expand -group internal /tb_com_tr/dut_com_tr/error_o
add wave -noupdate -expand -group internal /tb_com_tr/dut_com_tr/reg1
add wave -noupdate -expand -group internal /tb_com_tr/dut_com_tr/reg2
add wave -noupdate /tb_com_tr/dut_com_tr/error_int
TreeUpdate [SetDefaultTree]
WaveRestoreCursors {{Cursor 1} {38000 ps} 0}
quietly wave cursor active 1
configure wave -namecolwidth 343
configure wave -valuecolwidth 529
configure wave -justifyvalue left
configure wave -signalnamewidth 0
configure wave -snapdistance 10
configure wave -datasetprefix 0
configure wave -rowmargin 4
configure wave -childrowmargin 2
configure wave -gridoffset 0
configure wave -gridperiod 1
configure wave -griddelta 40
configure wave -timeline 0
configure wave -timelineunits ns
update
WaveRestoreZoom {0 ps} {56700 ps}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment