summaryrefslogtreecommitdiff
path: root/digital/asserv/src/hdlcounter/test_counter_top.v
diff options
context:
space:
mode:
Diffstat (limited to 'digital/asserv/src/hdlcounter/test_counter_top.v')
-rw-r--r--digital/asserv/src/hdlcounter/test_counter_top.v147
1 files changed, 147 insertions, 0 deletions
diff --git a/digital/asserv/src/hdlcounter/test_counter_top.v b/digital/asserv/src/hdlcounter/test_counter_top.v
new file mode 100644
index 00000000..b0ff69a1
--- /dev/null
+++ b/digital/asserv/src/hdlcounter/test_counter_top.v
@@ -0,0 +1,147 @@
+// test_counter_top.v
+// hdlcounter - Incremental encoder counter on programmable logic. {{{
+//
+// Copyright (C) 2007 Nicolas Schodet
+//
+// Robot APB Team 2008.
+// Web: http://apbteam.org/
+// Email: team AT apbteam DOT org
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// }}}
+`timescale 1ns / 1ps
+
+module test_counter_top();
+ parameter debug = 0;
+ parameter nc = 4;
+ reg clk;
+ reg rst;
+ reg [1:0] q[0:nc-1];
+ reg oe;
+ reg [1:0] sel;
+ wire [7:0] countout;
+
+ `include "common.v"
+
+ // Clock generator.
+ always #5 clk <= !clk;
+
+ // Counter top setup.
+ wire [0:nc-1] quad_full = 4'b0011;
+ reg [31:0] filter_size[0:nc-1];
+ parameter max_filter = 5;
+ initial begin
+ filter_size[0] = 4;
+ filter_size[1] = 4;
+ filter_size[2] = 1;
+ filter_size[3] = 1;
+ end
+
+ // Instantiation.
+ counter_top uut (clk, rst, q[0], q[1], q[2], q[3], oe, sel, countout);
+
+ // The count variable is the true encoder position, multiplied by 32,
+ // which is more than one encoder minimum period with a noise filter of
+ // size 3 to satisfy decoding logic timing constraints.
+ integer i;
+ integer n[0:nc-1], diff[0:nc-1];
+ reg [31:0] count[0:nc-1];
+ reg [27:0] countdiv32[0:nc-1];
+ reg [1:0] q_nat;
+
+ wire [27:0] countdiv32_0 = countdiv32[0],
+ countdiv32_1 = countdiv32[1],
+ countdiv32_2 = countdiv32[2],
+ countdiv32_3 = countdiv32[3];
+
+ initial begin
+ $dumpfile ("test_counter_top.vcd");
+ $dumpvars (1, clk, rst, countdiv32_0, countdiv32_1, countdiv32_2,
+ countdiv32_3, uut, oe, sel, countout, countassert, a);
+ clk <= 1;
+ rst <= 0;
+ for (i = 0; i < nc; i = i + 1) begin
+ q[i] <= 0;
+ n[i] = 0;
+ count[i] = 0;
+ countdiv32[i] <= 0;
+ end
+ #2 rst <= 1;
+ #6 // 2 ns before clock edge.
+ repeat (debug ? 5000 : 100000) begin
+ #1
+ for (i = 0; i < nc; i = i + 1) begin
+ if (n[i] == 0) begin
+ n[i] = $random;
+ n[i] = n[i] > 0 ? n[i] : -n[i];
+ n[i] = n[i] % 50 + 1;
+ diff[i] = $random % 2;
+ if (debug)
+ $display ("%t.%1d: n %1d diff %1d", $time, i, n[i], diff[i]);
+ end
+ n[i] = n[i] - 1;
+ count[i] = count[i] + diff[i];
+ q_nat = (count[i] / 32) % 4;
+ countdiv32[i] <= count[i] / 32;
+ q[i] <= { q_nat[1], q_nat[0] ^ q_nat[1] };
+ end
+ end
+ $finish;
+ end
+
+ // This simulates a two dimension array.
+ reg [27:0] countdiv32_smp[0:nc*max_filter-1];
+ integer j;
+ reg [27:0] countassert;
+ reg [7:0] countassert8;
+
+ wire [27:0] a = countdiv32_smp[0*max_filter+4];
+
+ initial begin
+ forever begin
+ @(posedge clk)
+ // Sample countdiv32 at rising edge.
+ for (j = 1; j < nc*max_filter; j = j + 1)
+ countdiv32_smp[j] <= countdiv32_smp[j-1];
+ for (j = 0; j < nc; j = j + 1)
+ countdiv32_smp[j * max_filter] <= countdiv32[j];
+ @(negedge clk)
+ // Check result *after* rising edge.
+ if (oe) begin
+ countassert = countdiv32_smp[sel*max_filter + filter_size[sel]];
+ countassert8 = quad_full[sel] ? countassert[7:0] : countassert[9:2];
+ // If equiped with a noise filter, accept a difference of 1.
+ // This is more difficult to find the exact expected value (I
+ // mean, without copy-paste the unit under test verbatim).
+ if (filter_size[sel] > 1)
+ assert ((countassert8 - countout) | 1, 1);
+ else
+ assertv8 (countassert8, countout);
+ end
+ else begin
+ assertv8 (8'bz, countout);
+ end
+ // Prepare next check.
+ if (($mti_random & 6'b111111) == 0)
+ oe = 0;
+ else begin
+ oe = 1;
+ sel = $random & 2'b11;
+ end
+ end
+ end
+
+endmodule