generated from saji/ecp5-template
Compare commits
No commits in common. "32deb30c920e2d9bc95c2353ee0caa5045457245" and "2a7908eae932b545a68b86742c81ff98de50b76c" have entirely different histories.
32deb30c92
...
2a7908eae9
|
@ -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
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
|
|
136
sim/src/main.cpp
136
sim/src/main.cpp
|
@ -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()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue