Skip to content

Commit

Permalink
Merge pull request #24 from zapta/master
Browse files Browse the repository at this point in the history
Assorted examples tweaks.
  • Loading branch information
Obijuan authored Oct 3, 2024
2 parents 42b7300 + 21214df commit ad4b03b
Show file tree
Hide file tree
Showing 14 changed files with 133 additions and 63 deletions.
1 change: 1 addition & 0 deletions Alchitry-Cu/Blinky/info
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Blink all leds
1 change: 0 additions & 1 deletion Alchitry-Cu/Blinky/info.txt

This file was deleted.

2 changes: 1 addition & 1 deletion TinyFPGA-BX/clock_divider/info
Original file line number Diff line number Diff line change
@@ -1 +1 @@
A simple clock divider. It produces two clocks with 1/4 of the input frequency. One with the original phase and one shifted by 90 degrees. This divider by itself could run at >200 MHz.
A 1/4 clock divider with 0 and 90 degress outputs.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
1 change: 1 addition & 0 deletions icezum/frere_jacques/info
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Frère Jacques, a two voices melody (see README.md)
85 changes: 85 additions & 0 deletions upduino31/testbench/apio_testing.vh
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// Utility macros for testbenches that are compatible with apio.

`default_nettype none

`define DUMP_FILE_NAME(x) `"x.vcd`"

// Call this macro at the begining of the testbench macro. It defines
// a clk signal and a variable clk_num that indicates the clock num.
`define DEF_CLK \
reg clk = 0; \
integer clk_num = 0; \
always begin \
#10 clk = ~clk; \
if (clk) clk_num += 1; \
end

// Asserts that the value of 'signal' is 'value'. If not, it prints an error message and aborts
// the simulation. When running under apio sim, the macro INTERACTIVE_SIM is defined
// and the failed assertions does not exist to allow showing the sigmulation results
// in the graphical window.
`define EXPECT(signal, value) \
if (signal !== (value)) begin \
$display("*** ASSERTION FAILED in %m (clk_num=%0d): expected (signal == value), actual: 'h%h", (clk_num), (signal)); \
`ifndef INTERACTIVE_SIM \
$fatal; \
`endif \
end

// Transition from clock low to clock high. Typically this is not
// called directly and clock is managed using `CLK().
`define CLK_HIGH \
begin \
`EXPECT(clk, 0); \
@ (posedge clk); \
#2; \
`EXPECT(clk, 1); \
end

// Transition from clock high to clock low. Typically this is not
// called directly and clock is managed using `CLK().
`define CLK_LOW \
begin \
`EXPECT(clk, 1); \
@ (negedge clk); \
#2; \
`EXPECT(clk, 0); \
end

// Simulate one clock. Wait for low to high and then high to low transition.
`define CLK \
begin \
`CLK_HIGH \
`CLK_LOW \
end

// Simulate n clocks.
`define CLKS(n) \
begin \
repeat(n) begin \
`CLK \
end \
end

// Place this macro immediatly after the 'initial begin' statement of the testbench.
// 'testbench' is the name of the testbench module. The macro sets the file
// that will contains the simulation results.
// The macro VCD_OUTPUT is defined automatically by the apio commands sim and test
// and contains base name of the expected output file.
`define TEST_BEGIN(testbench) \
begin \
`ifdef VCD_OUTPUT \
$dumpfile(`DUMP_FILE_NAME(`VCD_OUTPUT)); \
$dumpvars(0, testbench); \
`else \
$fatal(1, "Automatic macro VCD_OUTPUT not defined."); \
`endif \
end

// Place this macro at the end of the 'initial begin' block of the testbench.
`define TEST_END \
begin \
@ (posedge clk); \
$display("End of simulation"); \
$finish; \
end
106 changes: 45 additions & 61 deletions upduino31/testbench/main_tb.v
Original file line number Diff line number Diff line change
@@ -1,65 +1,44 @@
// An example of an automated test. Run 'apio test' to test and 'apio sim' to examine
// the wave signals.
// An example of an automated test. Run 'apio test' to test and
// 'apio sim' to examine the wave signals.

`timescale 10 ns / 1 ns

`define DUMPSTR(x) `"x.vcd`"

// A macro that check that given signal has given value. Normally it abors the simulation
// with an error, except when running with 'apio sim', in which case it prints an error
// message and continues so we can examine the signal with gtkwave.
`define EXPECT(signal, value) \
if (signal !== (value)) begin \
$display("ASSERTION FAILED in %m: signal != value ('h%h)", (signal)); \
`ifndef INTERACTIVE_SIM \
$fatal; \
`endif \
end
`include "apio_testing.vh"

// A macro to wait for N clk positive edges, and then a little bit more for the last clock
// to settle.
`define CLK(n) \
begin \
repeat(n) @ (posedge clk); \
#0.1; \
end
`timescale 10 ns / 1 ns

// A macro to count N times.
`define COUNT(n) \
// A macro to increment the tested counter by n.
`define INCREMENT(n) \
begin \
`CLK(1) \
`CLK \
count_en = 1; \
`CLK(n) \
`CLKS(n) \
count_en = 0; \
`CLK(1) \
`CLK \
end


module main_tb ();
// Declare the 'signal' name that is managed by apio_testings.vh.
`DEF_CLK;

always begin
#10 clk = ~clk;
end
// Inputs to the tested module.
reg reset;
reg count_en;

// Inputs
reg clk = 0;
reg reset = 1;
reg count_en = 0;


// Outputs
// Outputs of the tested module
wire [3:0] digit_1;
wire [3:0] digit_10;
wire carry;

// Counts the number of clocks with carry=1 so far.
// A utility signal that indicates the number of clocks on which
// the carry output of the tested module was high.
reg [5:0] carry_count = 0;

always @(posedge clk) begin
carry_count <= reset ? 0 : carry ? carry_count + 1 : carry_count;
end

main main (
// The instance of the tested module.
main tested (
.clk(clk),
.reset(reset),
.count_en(count_en),
Expand All @@ -68,48 +47,53 @@ module main_tb ();
.carry(carry)
);

// The test sequence.
initial begin
$dumpfile(`DUMPSTR(`VCD_OUTPUT));
$dumpvars(0, main_tb);
`TEST_BEGIN(main_tb)

// Test reset.
`CLK(3)
// Reset the tested module.
count_en = 0;
reset = 1;
`CLKS(3)
reset = 0;
`EXPECT(digit_10, 0) // count = 00
`EXPECT(digit_10, 0) // count = 00
`EXPECT(digit_1, 0)
`EXPECT(carry_count, 0)
`CLKS(3);

// Test transition from 09 to 10,
`CLK(3);
`COUNT(9)
`EXPECT(digit_10, 0) // count = 09
// Count to 09.
`INCREMENT(9)
`EXPECT(digit_10, 0)
`EXPECT(digit_1, 9)
`EXPECT(carry_count, 0)
`COUNT(1)

// Test transition from 09 to 10,
`INCREMENT(1)
`EXPECT(digit_10, 1) // count = 10
`EXPECT(digit_1, 0)
`EXPECT(carry_count, 0)

// Test transition from 99 to 00.
`COUNT(89)
`EXPECT(digit_10, 9) // count = 99
// Count to 99
`INCREMENT(89)
`EXPECT(digit_10, 9) // count = 99
`EXPECT(digit_1, 9)
`EXPECT(carry_count, 0)
`COUNT(1)
`EXPECT(digit_10, 0) // count = 00

// Test transition from 99 to 00.
`INCREMENT(1)
`EXPECT(digit_10, 0) // count = 00
`EXPECT(digit_1, 0)
`EXPECT(carry_count, 1)

// Count a few more
`COUNT(12)
`EXPECT(digit_10, 1) // count = 12
// Count to 12.
`INCREMENT(12)
`EXPECT(digit_10, 1) // count = 12
`EXPECT(digit_1, 2)
`EXPECT(carry_count, 1)

// All done.
`CLK(10)
$display("End of simulation");
$finish;
`CLKS(10)
`TEST_END
end

endmodule

0 comments on commit ad4b03b

Please sign in to comment.