commit:61e82cde6bc3ea2acb578f87142e1af559ada35e
author:Chip
committer:Chip
date:Wed Aug 28 23:30:23 2024 -0500
parents:439d2792d0fb2044d2aa77cd29d168c5adcfb212
Separate LFSR tests; test only main module
diff --git a/info.yaml b/info.yaml
line changes: +1/-1
index 3ec2971..2f64d62
--- a/info.yaml
+++ b/info.yaml
@@ -52,7 +52,7 @@ pinout:
   uio[4]: ""
   uio[5]: ""
   uio[6]: ""
-  uio[7]: ""
+  uio[7]: "audio (output)"
 
 # Do not change!
 yaml_version: 6

diff --git a/src/video.v b/src/video.v
line changes: +3/-3
index 4bec5ea..2f5da2d
--- a/src/video.v
+++ b/src/video.v
@@ -106,7 +106,7 @@ module text(
   } = str;
 
   chargen chargen(
-    .x(x + char_idx * 64),
+    .x(x + char_idx * 10'd64),
     .y(y),
     .character(str_chars[char_idx]),
     .hpos(hpos),
@@ -132,8 +132,8 @@ module text_sequencer(
   assign words[3] = {C_T, C_A, C_E, C_P, C_E, C_R};
 
   text text_gen(
-    .x(100),
-    .y(280),
+    .x(10'd100),
+    .y(10'd280),
     .str(words[selector]),
     .hpos(hpos),
     .vpos(vpos),

diff --git a/test/Makefile.lfsr b/test/Makefile.lfsr
line changes: +42/-0
index 0000000..d9c1387
--- /dev/null
+++ b/test/Makefile.lfsr
@@ -0,0 +1,42 @@
+# Makefile
+# See https://docs.cocotb.org/en/stable/quickstart.html for more info
+
+# defaults
+SIM ?= icarus
+TOPLEVEL_LANG ?= verilog
+SRC_DIR = $(PWD)/../src
+PROJECT_SOURCES = project.v
+
+ifneq ($(GATES),yes)
+
+# RTL simulation:
+SIM_BUILD				= sim_build/rtl
+VERILOG_SOURCES += $(addprefix $(SRC_DIR)/,$(PROJECT_SOURCES))
+COMPILE_ARGS 		+= -I$(SRC_DIR)
+
+else
+
+# Gate level simulation:
+SIM_BUILD				= sim_build/gl
+COMPILE_ARGS    += -DGL_TEST
+COMPILE_ARGS    += -DFUNCTIONAL
+COMPILE_ARGS    += -DUSE_POWER_PINS
+COMPILE_ARGS    += -DSIM
+COMPILE_ARGS    += -DUNIT_DELAY=\#1
+VERILOG_SOURCES += $(PDK_ROOT)/sky130A/libs.ref/sky130_fd_sc_hd/verilog/primitives.v
+VERILOG_SOURCES += $(PDK_ROOT)/sky130A/libs.ref/sky130_fd_sc_hd/verilog/sky130_fd_sc_hd.v
+
+# this gets copied in by the GDS action workflow
+VERILOG_SOURCES += $(PWD)/gate_level_netlist.v
+
+endif
+
+# Include the testbench sources:
+VERILOG_SOURCES += $(PWD)/tb_lfsr.v
+TOPLEVEL = tb_lfsr
+
+# MODULE is the basename of the Python test file
+MODULE = test_lfsr
+
+# include cocotb's make rules to take care of the simulator setup
+include $(shell cocotb-config --makefiles)/Makefile.sim

diff --git a/test/tb.gtkw b/test/tb.gtkw
line changes: +23/-11
index d5e3954..dc7492e
--- a/test/tb.gtkw
+++ b/test/tb.gtkw
@@ -1,25 +1,37 @@
 [*]
 [*] GTKWave Analyzer v3.4.0 (w)1999-2022 BSI
-[*] Wed Aug 28 04:41:58 2024
+[*] Thu Aug 29 04:46:09 2024
 [*]
 [dumpfile] "/home/chip/projects/tinytapeout/munch/test/tb.vcd"
-[dumpfile_mtime] "Wed Aug 28 04:34:55 2024"
-[dumpfile_size] 2596520
+[dumpfile_mtime] "Thu Aug 29 04:39:17 2024"
+[dumpfile_size] 163326
 [savefile] "/home/chip/projects/tinytapeout/munch/test/tb.gtkw"
 [timestart] 0
 [size] 1711 925
-[pos] 37 -2
-*-37.534531 30000001 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
+[pos] -1 -1
+*-17.534531 120000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
 [treeopen] tb.
 [sst_width] 297
-[signals_width] 230
+[signals_width] 229
 [sst_expanded] 1
 [sst_vpaned_height] 270
 @28
-tb.clock_gen.vsync
-tb.clock_gen.r_atick_clock[2:0]
-tb.clock_gen.audio_tick
-@23
-tb.clock_gen.r_pattern_clock[3:0]
+tb.clk
+tb.rst_n
+@200
+-uo_out
+@28
++{uo_out[7] (HSYNC)} (0)tb.uo_out[7:0]
++{uo_out[6] (B0)} (1)tb.uo_out[7:0]
++{uo_out[5] (G0)} (2)tb.uo_out[7:0]
++{uo_out[4] (R0)} (3)tb.uo_out[7:0]
++{uo_out[3] (VSYNC)} (4)tb.uo_out[7:0]
++{uo_out[2] (B1)} (5)tb.uo_out[7:0]
++{uo_out[1] (G1)} (6)tb.uo_out[7:0]
++{uo_out[0] (R1)} (7)tb.uo_out[7:0]
+@200
+-uio_out
+@28
++{uio_out[7] (audio)} (0)tb.uio_out[7:0]
 [pattern_trace] 1
 [pattern_trace] 0

diff --git a/test/tb_lfsr.gtkw b/test/tb_lfsr.gtkw
line changes: +23/-0
index 0000000..8070250
--- /dev/null
+++ b/test/tb_lfsr.gtkw
@@ -0,0 +1,23 @@
+[*]
+[*] GTKWave Analyzer v3.4.0 (w)1999-2022 BSI
+[*] Thu Aug 29 03:43:44 2024
+[*]
+[dumpfile] "/home/chip/projects/tinytapeout/munch/test/tb_lfsr.vcd"
+[dumpfile_mtime] "Thu Aug 29 03:42:52 2024"
+[dumpfile_size] 147098
+[savefile] "/home/chip/projects/tinytapeout/munch/test/tb_lfsr.gtkw"
+[timestart] 0
+[size] 1340 716
+[pos] -1 -1
+*-17.000000 96300 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
+[sst_width] 276
+[signals_width] 190
+[sst_expanded] 1
+[sst_vpaned_height] 198
+@28
+tb_lfsr.clk
+tb_lfsr.rst_n
+@23
+tb_lfsr.lfsr_bits[10:0]
+[pattern_trace] 1
+[pattern_trace] 0

diff --git a/test/tb_lfsr.v b/test/tb_lfsr.v
line changes: +27/-0
index 0000000..29d8730
--- /dev/null
+++ b/test/tb_lfsr.v
@@ -0,0 +1,27 @@
+`default_nettype none
+`timescale 1ns / 1ps
+
+module tb_lfsr ();
+
+  // Dump the signals to a VCD file. You can view it with gtkwave.
+  initial begin
+    $dumpfile("tb_lfsr.vcd");
+    $dumpvars(0, tb_lfsr);
+    #1;
+  end
+
+  // Wire up the inputs and outputs:
+  reg clk;
+  reg rst_n;
+  wire [5:0] bits;
+  wire [10:0] lfsr_bits;
+
+  lfsr lfsr_dev(
+    .clk(clk),
+    .rst_n(rst_n),
+    .bits(bits)
+  );
+
+  assign lfsr_bits = lfsr_dev.lfsr;
+
+endmodule

diff --git a/test/test.py b/test/test.py
line changes: +27/-8
index 2d4f64d..7c62fa1
--- a/test/test.py
+++ b/test/test.py
@@ -15,7 +15,12 @@ async def reset(dut):
     dut.rst_n.value = 1
 
 @cocotb.test()
-async def test_lfsr(dut):
+async def test_munch(dut):
+    '''
+    Unfortunately this does not test much, as video and audio generation is
+    quite complex. But we do assert a few basic signals at the beginning as a
+    basic sanity check.
+    '''
     dut._log.info("Start")
 
     # Set the clock period to 40ns (25MHz)
@@ -25,13 +30,27 @@ async def test_lfsr(dut):
 
     await reset(dut)
 
-    dut._log.info("Test LFSR module")
+    dut._log.info("Test munch module")
 
-    await ClockCycles(dut.clk, 1)
+    await ClockCycles(dut.clk, 2)
+    # Should be a black pixel at the beginning of scan
+    assert dut.uo_out.value == 0b10001000
+    # Audio is on; PWM output is 50:50 with no output, so this will be high at
+    # the beginning even though two channels are outputting immediately.
+    assert dut.uio_out.value == 0b10000000
 
-    for i in range(1, 2**11 - 1):
-        await ClockCycles(dut.clk, 1)
-        assert dut.munch.lfsr_dev.lfsr.value != 0
+    await ClockCycles(dut.clk, 3)
+    # Pixel should be black now
+    assert dut.uo_out.value == 0b10001000
 
-    await ClockCycles(dut.clk, 1)
-    assert dut.munch.lfsr_dev.lfsr.value == 0
+    # Should put us right at the border between front porch and hsync
+    await ClockCycles(dut.clk, 640 + 16 - 3)
+    assert dut.uo_out.value == 0b00001000
+
+    # border of hsync and back porch
+    await ClockCycles(dut.clk, 96)
+    assert dut.uo_out.value == 0b10001000
+
+    # and back at the beginning of the next line; green pixel again
+    await ClockCycles(dut.clk, 48)
+    assert dut.uo_out.value == 0b10001000

diff --git a/test/test_lfsr.py b/test/test_lfsr.py
line changes: +37/-0
index 0000000..fcf0e0d
--- /dev/null
+++ b/test/test_lfsr.py
@@ -0,0 +1,37 @@
+# SPDX-FileCopyrightText: © 2024 Tiny Tapeout
+# SPDX-License-Identifier: Apache-2.0
+
+import cocotb
+from cocotb.clock import Clock
+from cocotb.triggers import ClockCycles, Timer
+
+async def reset(dut):
+    # Reset
+    dut._log.info("Reset")
+    dut.rst_n.value = 1
+    await ClockCycles(dut.clk, 1);
+    dut.rst_n.value = 0
+    await ClockCycles(dut.clk, 1);
+    dut.rst_n.value = 1
+
+@cocotb.test()
+async def test_lfsr(dut):
+    dut._log.info("Start")
+
+    # Set the clock period to 40ns (25MHz)
+    # Actual clock is 25.175 (39.722ns) but whatever
+    clock = Clock(dut.clk, 40, units="ns")
+    cocotb.start_soon(clock.start())
+
+    await reset(dut)
+
+    dut._log.info("Test LFSR module")
+
+    await ClockCycles(dut.clk, 1)
+
+    for i in range(1, 2**11 - 1):
+        await ClockCycles(dut.clk, 1)
+        assert dut.lfsr_bits.value != 0
+
+    await ClockCycles(dut.clk, 1)
+    assert dut.lfsr_bits.value == 0