mirror of
https://github.com/pConst/basic_verilog.git
synced 2025-01-28 07:02:55 +08:00
249 lines
6.3 KiB
Verilog
249 lines
6.3 KiB
Verilog
// Copyright 2007 Altera Corporation. All rights reserved.
|
|
// Altera products are protected under numerous U.S. and foreign patents,
|
|
// maskwork rights, copyrights and other intellectual property laws.
|
|
//
|
|
// This reference design file, and your use thereof, is subject to and governed
|
|
// by the terms and conditions of the applicable Altera Reference Design
|
|
// License Agreement (either as signed by you or found at www.altera.com). By
|
|
// using this reference design file, you indicate your acceptance of such terms
|
|
// and conditions between you and Altera Corporation. In the event that you do
|
|
// not agree with such terms and conditions, you may not use the reference
|
|
// design file and please promptly destroy any copies you have made.
|
|
//
|
|
// This reference design file is being provided on an "as-is" basis and as an
|
|
// accommodation and therefore all warranties, representations or guarantees of
|
|
// any kind (whether express, implied or statutory) including, without
|
|
// limitation, warranties of merchantability, non-infringement, or fitness for
|
|
// a particular purpose, are specifically disclaimed. By making this reference
|
|
// design file available, Altera expressly does not recommend, suggest or
|
|
// require that this reference design file be used in combination with any
|
|
// other product not provided by Altera.
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// baeckler - 07-20-2006
|
|
|
|
module ecc_8bit_tb ();
|
|
|
|
// this should be the sum of encode and
|
|
// decode registers
|
|
parameter TOTAL_LATENCY = 2;
|
|
|
|
reg [7:0] data_in,next_data_in;
|
|
wire [12:0] code_out;
|
|
reg [12:0] error_sig,next_error_sig;
|
|
wire [12:0] damaged_code;
|
|
wire [7:0] recovered_data;
|
|
wire no_err,err_corrected,err_fatal;
|
|
|
|
reg clk,rst;
|
|
|
|
///////////////////////
|
|
// encoder unit
|
|
///////////////////////
|
|
ecc_encode_8bit enc
|
|
(
|
|
.d(data_in),
|
|
.c(code_out)
|
|
);
|
|
|
|
///////////////////////
|
|
// insert optional error
|
|
///////////////////////
|
|
reg [2:0] num_errors, next_num_errors;
|
|
assign damaged_code = code_out ^ error_sig;
|
|
|
|
///////////////////////
|
|
// decoder unit
|
|
///////////////////////
|
|
ecc_decode_8bit dec
|
|
(
|
|
.clk(clk),
|
|
.rst(rst),
|
|
.c(damaged_code),
|
|
.d(recovered_data),
|
|
.no_err(no_err),
|
|
.err_corrected(err_corrected),
|
|
.err_fatal(err_fatal)
|
|
);
|
|
defparam dec .MIDDLE_REG = 1;
|
|
defparam dec .OUTPUT_REG = 1;
|
|
|
|
|
|
////////////////////////
|
|
// main control
|
|
////////////////////////
|
|
reg fail;
|
|
reg [TOTAL_LATENCY:0] flushing;
|
|
|
|
initial begin
|
|
clk = 0;
|
|
rst = 0;
|
|
num_errors = 0;
|
|
error_sig = 0;
|
|
data_in = 8'b0;
|
|
fail = 0;
|
|
|
|
#10 rst = 1;
|
|
#10 rst = 0;
|
|
|
|
// wait for the pipe to fill
|
|
#10
|
|
if (!flushing[TOTAL_LATENCY]) begin
|
|
@(posedge flushing[TOTAL_LATENCY]);
|
|
end
|
|
fail = 0;
|
|
|
|
#10000000 if (!fail) $display ("PASS");
|
|
else $display ("FAIL");
|
|
$stop();
|
|
end
|
|
|
|
integer n = 0;
|
|
reg [6:0] which_bit;
|
|
|
|
////////////////////////
|
|
// new random stimulus
|
|
////////////////////////
|
|
always @(negedge clk or posedge rst) begin
|
|
next_data_in = {$random,$random};
|
|
|
|
// create an error signal with a few randomly
|
|
// placed 1's.
|
|
next_num_errors = $random;
|
|
next_num_errors = next_num_errors % 5;
|
|
|
|
next_error_sig = 13'b0;
|
|
for (n=0; n<next_num_errors; n=n+1)
|
|
begin
|
|
which_bit = $random;
|
|
which_bit = which_bit % 13;
|
|
while (next_error_sig[which_bit])
|
|
begin
|
|
which_bit = (which_bit + 1) % 13;
|
|
end
|
|
next_error_sig[which_bit] = 1'b1;
|
|
end
|
|
end
|
|
|
|
always @(posedge clk or posedge rst) begin
|
|
if (rst) begin
|
|
num_errors <= 0;
|
|
error_sig <= 0;
|
|
data_in <= 0;
|
|
end
|
|
else begin
|
|
num_errors <= next_num_errors;
|
|
data_in <= next_data_in;
|
|
error_sig <= next_error_sig;
|
|
end
|
|
end
|
|
|
|
///////////////////////
|
|
// latency matching
|
|
///////////////////////
|
|
reg [12:0] delayed_data [TOTAL_LATENCY:0];
|
|
reg [2:0] delayed_num_errors [TOTAL_LATENCY:0];
|
|
integer i ;
|
|
|
|
always @(posedge clk or posedge rst) begin
|
|
if (rst) begin
|
|
flushing <= 1'b1;
|
|
end
|
|
else begin
|
|
flushing <= flushing | (flushing << 1'b1);
|
|
for (i=TOTAL_LATENCY; i>0; i=i-1) begin
|
|
delayed_data[i] <= delayed_data[i-1];
|
|
delayed_num_errors[i] <= delayed_num_errors[i-1];
|
|
end
|
|
end
|
|
end
|
|
|
|
always @(*) begin
|
|
delayed_num_errors[0] = num_errors;
|
|
delayed_data[0] = data_in;
|
|
end
|
|
|
|
///////////////////////////////
|
|
// capture and check results
|
|
///////////////////////////////
|
|
|
|
integer wrong_bits = 0;
|
|
reg [12:0] recovered_error;
|
|
|
|
integer stats_3bit_pass = 0;
|
|
integer stats_3bit_one = 0;
|
|
integer stats_3bit_two = 0;
|
|
|
|
integer stats_4bit_pass = 0;
|
|
integer stats_4bit_one = 0;
|
|
integer stats_4bit_two = 0;
|
|
|
|
integer z;
|
|
|
|
always @(posedge clk or posedge rst) begin
|
|
#20
|
|
|
|
// count the number of wrong bits in the
|
|
// recovered data.
|
|
wrong_bits = 0;
|
|
recovered_error = delayed_data[TOTAL_LATENCY] ^ recovered_data;
|
|
for (z=0;z<13;z=z+1)
|
|
begin
|
|
if (recovered_error[z]) wrong_bits = wrong_bits + 1;
|
|
end
|
|
|
|
#1
|
|
|
|
if (delayed_num_errors[TOTAL_LATENCY] == 0) begin
|
|
if (wrong_bits !== 0) fail = 1;
|
|
if ({no_err,err_corrected,err_fatal} !== 3'b100) fail = 1;
|
|
end
|
|
else if (delayed_num_errors[TOTAL_LATENCY] == 1) begin
|
|
// 1 bit errors need to be flagged and repaired
|
|
if (wrong_bits !== 0) begin
|
|
$display ("Single bit error was not corrected");
|
|
fail = 1;
|
|
end
|
|
if ({no_err,err_corrected,err_fatal} !== 3'b010) begin
|
|
$display ("Single bit error was not flagged");
|
|
fail = 1;
|
|
end
|
|
end
|
|
else if (delayed_num_errors[TOTAL_LATENCY] == 2) begin
|
|
// 2 bit errors need to be detected
|
|
// and not made any worse
|
|
if (wrong_bits > 2) fail = 1;
|
|
if ({no_err,err_corrected,err_fatal} !== 3'b001) fail = 1;
|
|
end
|
|
else if (delayed_num_errors[TOTAL_LATENCY] == 3) begin
|
|
// 3 bit errors need to be detected as parity error
|
|
// they will be mistakenly corrected as 1 bit errors
|
|
if ({no_err,err_corrected,err_fatal} == 3'b100)
|
|
stats_3bit_pass = stats_3bit_pass + 1;
|
|
else if ({no_err,err_corrected,err_fatal} == 3'b010)
|
|
stats_3bit_one = stats_3bit_one + 1;
|
|
else if ({no_err,err_corrected,err_fatal} == 3'b001)
|
|
stats_3bit_two = stats_3bit_two + 1;
|
|
end
|
|
else begin
|
|
// 4 + bit errors
|
|
if ({no_err,err_corrected,err_fatal} == 3'b100)
|
|
stats_4bit_pass = stats_4bit_pass + 1;
|
|
else if ({no_err,err_corrected,err_fatal} == 3'b010)
|
|
stats_4bit_one = stats_4bit_one + 1;
|
|
else if ({no_err,err_corrected,err_fatal} == 3'b001)
|
|
stats_4bit_two = stats_4bit_two + 1;
|
|
end
|
|
|
|
// early exit for failure
|
|
if (fail) begin
|
|
#100 $display ("Mismatch at time %d",$time);
|
|
$stop();
|
|
end
|
|
end
|
|
|
|
always begin
|
|
#100 clk = ~clk;
|
|
end
|
|
|
|
endmodule |