Compare commits

..

No commits in common. "32deb30c920e2d9bc95c2353ee0caa5045457245" and "2a7908eae932b545a68b86742c81ff98de50b76c" have entirely different histories.

5 changed files with 122 additions and 69 deletions

View file

@ -1,19 +0,0 @@
name: Verilator Unit Tests
on: [push]
defaults:
run:
shell: nix develop --command bash {0}
jobs:
test:
name: Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: DeterminateSystems/nix-installer-action@main
- run: |
cmake -B build/
cmake --build build/
working-directory: ./sim
- run: ./build/sim
working-directory: ./sim

View file

@ -1,7 +1,7 @@
// Project-specific cosimuluated devices. // Project-specific cosimuluated devices.
#pragma once #pragma once
#include "Vhub75e.h"
#include "tests.hpp" #include "tests.hpp"
#include "Vhub75e.h"
// slices the RGB values for us. // slices the RGB values for us.
uint8_t rgb_slice(uint32_t rgb, uint8_t bit) { uint8_t rgb_slice(uint32_t rgb, uint8_t bit) {
@ -73,7 +73,6 @@ public:
this->xsize = xsize; this->xsize = xsize;
this->ysize = ysize; this->ysize = ysize;
row0.clear(); row0.clear();
row1.clear();
prev_oe = out_enable; prev_oe = out_enable;
prev_display_clk = display_clk; prev_display_clk = display_clk;
prev_latch = latch; prev_latch = latch;

View file

@ -59,6 +59,10 @@ public:
for (int i = 0; i < latency; i++) { for (int i = 0; i < latency; i++) {
addr_lookup_q.push(0); addr_lookup_q.push(0);
} }
for (int i = 0; i < ram.size(); i++) {
ram[i] = i + 3;
}
}; };
FakeBRAM(int latency, unsigned char &clk, unsigned short &addr_in, FakeBRAM(int latency, unsigned char &clk, unsigned short &addr_in,

View file

@ -1,12 +1,113 @@
#include "Vhub75e.h" #include "Vhub75e.h"
#include "devices.hpp"
#include "tests.hpp" #include "tests.hpp"
#include "devices.hpp"
#include "verilated.h"
#include "verilated_vcd_c.h"
#include <array> #include <array>
#include <catch2/catch_test_macros.hpp> #include <catch2/catch_test_macros.hpp>
#include <catch2/generators/catch_generators_all.hpp>
#include <memory> #include <memory>
#include <stdio.h>
#include <vector> #include <vector>
void LineDriverTest(VerilatedContext &ctx) {
// create the hub75e driver and run some basic tests
// we generate 512 random color values (24 bits)
// we load them in.
unsigned long posedge = 0; // counts positive edges.
unsigned long simtime = 0;
auto dut = std::make_unique<Vhub75e>(&ctx, "dut");
VerilatedVcdC *m_trace = new VerilatedVcdC;
dut->trace(m_trace, 5);
auto bram = FakeBRAM(1, dut->clk, dut->pixbuf_addr, dut->pixbuf_data);
auto hub75 = HUB75Reciever(128, 64, *dut);
printf("Performing basic test\n");
bool done = false;
m_trace->open("waveform.vcd");
while (!done) {
dut->clk ^= 1; // toggle clock
dut->eval();
if (dut->clk == 1) {
// rising edge.
posedge++;
bram.tick();
}
dut->write_trig = posedge < 2 ? 1 : 0;
if (posedge >= 250000) {
done = true;
}
hub75.tick();
m_trace->dump(simtime);
simtime++;
}
m_trace->close();
};
// int main() {
// auto ctx = std::make_unique<VerilatedContext>();
// ctx->traceEverOn(true);
// printf("hello world!\n");
// LineDriverTest(*ctx);
// };
TEST_CASE("Hub75 Test") {
auto ctx = std::make_unique<VerilatedContext>();
// setup DUT
unsigned long posedge = 0; // counts positive edges.
unsigned long simtime = 0;
auto dut = std::make_unique<Vhub75e>(ctx.get(), "dut");
auto bram = FakeBRAM(1, dut->clk, dut->pixbuf_addr, dut->pixbuf_data);
auto hub75 = HUB75Reciever(128, 64, *dut);
bool done = false;
bool driver_done = false;
while (!done) {
dut->clk ^= 1; // toggle clock
dut->eval();
if (dut->clk == 1) {
// rising edge.
posedge++;
}
dut->write_trig = posedge < 2 ? 1 : 0;
if (dut->done) {
done = true;
driver_done = true;
}
if (posedge >= 250000) {
done = true;
driver_done = false;
}
hub75.tick();
bram.tick();
simtime++;
}
REQUIRE(driver_done);
SECTION("Bit Sizing/Count") {
CHECK(hub75.get_past_rows().size() == 8);
auto rows = hub75.get_past_rows();
for (int i = 0; i < rows.size(); i++) {
auto r = rows[i];
}
}
SECTION("Pulse width") {}
}
TEST_CASE("HUB75E Driver Test") { TEST_CASE("HUB75E Driver Test") {
auto fixture = VerilatorTestFixture<Vhub75e>(); auto fixture = VerilatorTestFixture<Vhub75e>();
// very simple done checker. // very simple done checker.
@ -21,6 +122,7 @@ TEST_CASE("HUB75E Driver Test") {
fixture.add_module(stim); fixture.add_module(stim);
SECTION("Smoke Tests") { SECTION("Smoke Tests") {
fixture.enable_trace("testing.vcd");
auto bram = std::make_shared<FakeBRAM>(1, dut.clk, dut.pixbuf_addr, auto bram = std::make_shared<FakeBRAM>(1, dut.clk, dut.pixbuf_addr,
dut.pixbuf_data); dut.pixbuf_data);
fixture.add_module(bram); fixture.add_module(bram);
@ -57,35 +159,5 @@ TEST_CASE("HUB75E Driver Test") {
SECTION("Line Correctness") { SECTION("Line Correctness") {
// this is the part where we validate that the line in = line out. // this is the part where we validate that the line in = line out.
// we have to generate different values since the // we have to generate different values since the
fixture.enable_trace("testing.vcd");
auto line = GENERATE(take(10, chunk(256, random(0, 0xFFFFFF))));
auto bram = std::make_shared<FakeBRAM>(1, dut.clk, dut.pixbuf_addr,
dut.pixbuf_data);
std::copy(line.begin(), line.end(), bram->get().begin());
fixture.add_module(bram);
auto display = std::make_shared<HUB75Reciever>(128, 64, dut);
fixture.add_module(display);
fixture.exec();
REQUIRE(fixture.get_reason() ==
VerilatorTestFixture<Vhub75e>::FinishReason::Ok);
auto [row0, row1] = display->transpose();
REQUIRE(row0.size() == 128);
REQUIRE(row1.size() == 128);
auto ram_ref = bram->get();
for (int i = 0; i < 128; i++) {
CAPTURE(i);
CAPTURE(ram_ref[i], row0[i]);
REQUIRE(ram_ref[i] == row0[i]);
CAPTURE(ram_ref[i+128], row1[i]);
REQUIRE(ram_ref[i+128] == row1[i]);
}
// CHECK(std::equal(ram_ref.begin(), ram_ref.begin() + 128, row0.begin(),
// row0.end()));
} }
} }

View file

@ -58,9 +58,6 @@ module hub75e (
reg [7:0] pixnum; reg [7:0] pixnum;
reg pixrow = 0;
assign pixbuf_addr = {pixrow, pixnum};
always_ff @(posedge clk) begin always_ff @(posedge clk) begin
counter <= counter + 1; counter <= counter + 1;
@ -70,7 +67,7 @@ module hub75e (
counter <= 0; counter <= 0;
done <= 0; done <= 0;
pixnum <= ROW_DEPTH - 1; pixnum <= ROW_DEPTH - 1;
pixrow <= 0; pixbuf_addr <= {1'b0, pixnum};
// wait for the signal to write out our lines. // wait for the signal to write out our lines.
if (write_trig) begin if (write_trig) begin
state <= StatePreload; state <= StatePreload;
@ -78,19 +75,19 @@ module hub75e (
end end
StatePreload: begin StatePreload: begin
case (counter) case (counter[1:0])
0: begin 2'b00: begin
pixrow <= 0; // wait for pix 1
pixbuf_addr <= {1'b1, pixnum};
end end
1: begin 2'b01: begin
// load pix 1 // load pix 1
panel_rgb0 <= ram_rgb_slice; panel_rgb0 <= ram_rgb_slice;
// wait for pix 1
pixrow <= 1;
end end
2: begin 2'b10: begin // rising edge
// store pix2
panel_rgb1 <= ram_rgb_slice; panel_rgb1 <= ram_rgb_slice;
pixrow <= 0; // go to writerow
counter <= 0; counter <= 0;
state <= StateWriteRow; state <= StateWriteRow;
end end
@ -107,18 +104,17 @@ module hub75e (
case (counter[1:0]) case (counter[1:0])
2'b10: begin // rising edge 2'b10: begin // rising edge
// fetch pixel 1 // fetch pixel 1
pixrow <= 0; pixbuf_addr <= {1'b0, pixnum};
end end
2'b11: begin // midpoint of high clk. 2'b11: begin // midpoint of high clk.
// fetch pixel 2, load pixel 1 // fetch pixel 2, load pixel 1
pixrow <= 1; pixbuf_addr <= {1'b1, pixnum};
panel_rgb0 <= ram_rgb_slice; panel_rgb0 <= ram_rgb_slice;
end end
2'b00: begin // falling edge 2'b00: begin // falling edge
// load pixel 2 // load pixel 2
panel_rgb1 <= ram_rgb_slice; panel_rgb1 <= ram_rgb_slice;
pixnum <= pixnum - 1; pixnum <= pixnum - 1;
pixrow <= 0;
end end
2'b01: begin // midpoint of low clk 2'b01: begin // midpoint of low clk
// decrement pixnum // decrement pixnum
@ -147,6 +143,7 @@ module hub75e (
latch <= 1; latch <= 1;
out_enable <= 1; out_enable <= 1;
pixnum <= ROW_DEPTH - 1; pixnum <= ROW_DEPTH - 1;
counter <= counter + 1;
if (counter > 3) begin if (counter > 3) begin
counter <= 0; counter <= 0;
if (bcm_shift == 0) begin if (bcm_shift == 0) begin
@ -155,7 +152,7 @@ module hub75e (
latch <= 0; latch <= 0;
end else begin end else begin
bcm_shift <= bcm_shift - 1; bcm_shift <= bcm_shift - 1;
state <= StatePreload; state <= StateWriteRow;
latch <= 0; latch <= 0;
end end
end end