Add examples. Add more info to README

This commit is contained in:
Nikolay Puzanov
2022-07-09 12:34:40 +03:00
parent e917908049
commit 8e2514e895
7 changed files with 288 additions and 29 deletions

View File

@@ -0,0 +1,37 @@
`timescale 1ps/1ps
`default_nettype none
module simple_counter #(parameter COUNT = 16,
localparam WIDTH = $clog2(COUNT-1)) // <-- ERROR
(input wire clock,
input wire reset,
input wire i_inc,
input wire i_dec,
output reg [WIDTH-1:0] o_count);
logic [WIDTH-1:0] count_next;
always_comb
case ({i_inc, i_dec})
2'b01:
if (o_count == '0)
count_next = WIDTH'(COUNT-1);
else
count_next = o_count - 1'b1;
2'b10:
if (o_count == WIDTH'(COUNT-1))
count_next = '0;
else
count_next = o_count + 1'b1;
default: count_next = o_count;
endcase
always_ff @(posedge clock)
if (reset) o_count <= '0;
else o_count <= count_next;
endmodule // simple_counter

View File

@@ -0,0 +1,67 @@
`timescale 1ps/1ps
`include "utest.vh"
module simple_counter_tb;
logic clock = 1'b0;
logic reset = 1'b1;
always #(10ns/2) clock = ~clock;
parameter COUNT = 16;
parameter ITERATIONS = 100;
parameter DIRECTION = 1; // 1 - increment, -1 - decrement, 0 - random
localparam WIDTH = $clog2(COUNT-1); // <-- ERROR
logic i_inc;
logic i_dec;
logic [WIDTH-1:0] o_count;
simple_counter #(.COUNT(COUNT))
DUT (.*);
int gold_count;
//// Shows that a `UTEST_BASE_DIR define exists
// initial begin
// `log_info(("From verilog code. Base dir: %s", `UTEST_BASE_DIR));
// end
initial begin
i_inc = 1'b0;
i_dec = 1'b0;
reset = 1'b1;
repeat(2) @(posedge clock) #1;
reset = 1'b0;
@(posedge clock) #1;
gold_count = '0;
for (int i = 0; i < ITERATIONS; i += 1) begin
case (DIRECTION)
-1: {i_inc, i_dec} = 2'b01;
1: {i_inc, i_dec} = 2'b10;
default: {i_inc, i_dec} = 2'($urandom);
endcase
@(posedge clock) #1;
if (i_inc && !i_dec)
gold_count ++;
else if (!i_inc && i_dec)
gold_count --;
if (gold_count >= COUNT) gold_count = 0;
if (gold_count < 0) gold_count = COUNT-1;
if (gold_count != int'(o_count))
`log_error(("#%0t: Gold count = %0d, DUT count = %0d", $time, gold_count, o_count));
end
repeat(2) @(posedge clock) #1;
$finish;
end
endmodule // simple_counter_tb

View File

@@ -0,0 +1,44 @@
;; -*- scheme -*-
;;; Make lists combinations
;;; Example: (combinations '(1 2 3) '(a b)) -> '((1 a) (1 b) (2 a) (2 b) (3 a) (3 b))
(define (combinations . lists)
(cond
((null? lists) '())
((null? (cdr lists)) (car lists))
(else
(fold (lambda (comb out)
(append out
(map (lambda (x)
(if (list? comb)
(cons x comb)
(list x comb)))
(car lists))))
'() (apply combinations (cdr lists))))))
;;; Testbenches
(map
(lambda (l)
(let ((count (car l))
(direction (cadr l)))
(utest/tb
((format "c~a_d~a" count direction)
"More complex testbench for Simple Counter"
(format "COUNT=~a\tDIRECTION=~a" count direction))
;; Instead of a description, you can display the message in log
;; (utest/log 'info "COUNT = ~a" count)
;; testbench body
(utest/run-simulation-iverilog
(utest/find-files ".*\\.sv$")
"simple_counter_tb"
#:parameters `((COUNT ,count)
(ITERATIONS ,(* count 3))
(DIRECTION ,direction))))))
(combinations
(append '(10 100 1000 16 64 256)
(let ((state (seed->random-state 0)))
(map (lambda (x) (+ 2 (random 200 state))) (iota 100))))
'(1 -1 0)))

View File

@@ -0,0 +1,12 @@
;; -*- scheme -*-
;; ^^^ this comment tells Emacs to use Scheme mode
(utest/tb
("simple_counter_tb"
"Simplest testbench Simple Counter")
(utest/run-simulation-iverilog
;; sources
'("simple_counter.sv" "simple_counter_tb.sv")
;; top module name
"simple_counter_tb"))

View File

@@ -0,0 +1,25 @@
;; -*- scheme -*-
;; ^^^ this comment tells Emacs to use Scheme mode
(utest/tb
("simple_counter_permanent"
"Testbench for Simple Counter with permanent work dir")
;; get base dir and make work dir
(let* ((base (utest/base-path))
(work (format "~a/work" base)))
(when (not (file-exists? work))
(mkdir work))
;; parameterize work dir
(parameterize
((utest/work-path work)
(utest/force-dump #t))
;; testbench body
(utest/run-simulation-iverilog
;; sources
'("simple_counter.sv" "simple_counter_tb.sv")
;; top module name
"simple_counter_tb"))))

View File

@@ -0,0 +1,15 @@
`ifndef UTEST_VERILOG_DEFINES
`define UTEST_VERILOG_DEFINES
// Log level string prefixes for use with $display function.
// Example usage: $display("%sError message", `LOG_ERR);
`define LOG_INFO "INFO#"
`define LOG_WARN "WARN#"
`define LOG_ERR "FAIL#"
// Dirty hacked redefine of $display function. Must be used with two parentheses.
// Example usage: `log_info(("Information message"));
`define log_info(msg) begin $display({`LOG_INFO, $sformatf msg}); end
`define log_warn(msg) begin $display({`LOG_WARN, $sformatf msg}); end
`define log_error(msg) begin $display({`LOG_ERR, $sformatf msg}); end
`endif