summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--rtl/bus/master.sv2
-rw-r--r--tb/avalon.hpp15
-rw-r--r--tb/avalon.impl.hpp44
-rw-r--r--tb/top/conspiracion.cpp66
4 files changed, 97 insertions, 30 deletions
diff --git a/rtl/bus/master.sv b/rtl/bus/master.sv
index 5d8c3a8..d350d80 100644
--- a/rtl/bus/master.sv
+++ b/rtl/bus/master.sv
@@ -26,6 +26,7 @@ module bus_master
} state;
assign data_rd = avl_readdata;
+ assign avl_byteenable = 4'b1111;
always_ff @(posedge clk) unique case(state)
REQUEST: if(start) begin
@@ -33,6 +34,7 @@ module bus_master
avl_read <= ~write;
avl_write <= write;
avl_writedata <= data_rw;
+ state <= WAIT;
end
WAIT: if(~avl_waitrequest) begin
diff --git a/tb/avalon.hpp b/tb/avalon.hpp
index 38c8792..8964cdb 100644
--- a/tb/avalon.hpp
+++ b/tb/avalon.hpp
@@ -9,8 +9,8 @@ namespace taller::avalon
class slave
{
public:
- virtual std::uint32_t base_address() = 0;
- virtual std::uint32_t address_mask() = 0;
+ virtual std::uint32_t base_address() noexcept = 0;
+ virtual std::uint32_t address_mask() noexcept = 0;
virtual bool read(std::uint32_t addr, std::uint32_t &data) = 0;
virtual bool write(std::uint32_t addr, std::uint32_t data, unsigned byte_enable) = 0;
@@ -20,11 +20,9 @@ namespace taller::avalon
class interconnect
{
public:
- inline interconnect(Platform &plat) noexcept
- : plat(plat)
- {}
+ interconnect(Platform &plat) noexcept;
- void tick();
+ void tick(bool clk);
void attach(slave &dev);
private:
@@ -38,6 +36,11 @@ namespace taller::avalon
Platform &plat;
slave* active = nullptr;
std::vector<binding> devices;
+ std::uint32_t avl_address = 0;
+ std::uint32_t avl_writedata = 0;
+ unsigned avl_byteenable = 0;
+ bool avl_read = false;
+ bool avl_write = false;
};
}
diff --git a/tb/avalon.impl.hpp b/tb/avalon.impl.hpp
index 7f589ae..cc371a7 100644
--- a/tb/avalon.impl.hpp
+++ b/tb/avalon.impl.hpp
@@ -7,26 +7,44 @@
namespace taller::avalon
{
template<class Platform>
+ inline interconnect<Platform>::interconnect(Platform &plat) noexcept
+ : plat(plat)
+ {}
+
+ template<class Platform>
void interconnect<Platform>::attach(slave &dev)
{
- devices.push_back(binding { dev.base_address(), dev.address_mask(), dev });
+ auto base = dev.base_address();
+ auto mask = dev.address_mask();
+ assert((base & mask) == base);
+
+ devices.push_back(binding { base, mask, dev });
}
template<class Platform>
- void interconnect<Platform>::tick()
+ void interconnect<Platform>::tick(bool clk)
{
- auto addr = plat.avl_address;
+ if(!clk)
+ {
+ avl_address = plat.avl_address;
+ avl_read = plat.avl_read;
+ avl_write = plat.avl_write;
+ avl_writedata = plat.avl_writedata;
+ avl_byteenable = plat.avl_byteenable;
+ return;
+ }
+
if(!active)
{
- if(addr & 0b11)
+ if(avl_address & 0b11)
{
- fprintf(stderr, "[avl] unaligned address: 0x%08x\n", addr);
+ fprintf(stderr, "[avl] unaligned address: 0x%08x\n", avl_address);
assert(false);
}
for(auto &binding : devices)
{
- if((addr & binding.mask) == binding.base)
+ if((avl_address & binding.mask) == binding.base)
{
active = &binding.dev;
break;
@@ -35,21 +53,21 @@ namespace taller::avalon
if(!active)
{
- const char *op = plat.avl_read ? "read" : "write";
- fprintf(stderr, "[avl] attempt to %s memory hole at 0x%08x\n", op, addr);
+ const char *op = avl_read ? "read" : "write";
+ fprintf(stderr, "[avl] attempt to %s memory hole at 0x%08x\n", op, avl_address);
assert(false);
}
}
- assert(!plat.avl_read || !plat.avl_write);
- auto pos = addr >> 2;
+ assert(!avl_read || !avl_write);
+ auto pos = (avl_address & ~active->address_mask()) >> 2;
- if(plat.avl_read)
+ if(avl_read)
{
plat.avl_waitrequest = !active->read(pos, plat.avl_readdata);
- } else if(plat.avl_write)
+ } else if(avl_write)
{
- plat.avl_waitrequest = !active->write(pos, plat.avl_writedata, plat.avl_byteenable);
+ plat.avl_waitrequest = !active->write(pos, avl_writedata, avl_byteenable);
}
if(!plat.avl_waitrequest)
diff --git a/tb/top/conspiracion.cpp b/tb/top/conspiracion.cpp
index b8f803c..bce5546 100644
--- a/tb/top/conspiracion.cpp
+++ b/tb/top/conspiracion.cpp
@@ -1,11 +1,14 @@
-#include <verilated.h>
#include <cstdio>
+#include <verilated.h>
+#include <verilated_vcd_c.h>
+
#include "Vconspiracion.h"
#include "Vconspiracion_conspiracion.h"
#include "Vconspiracion_platform.h"
#include "../avalon.hpp"
+#include "../mem.hpp"
int main(int argc, char **argv)
{
@@ -14,18 +17,49 @@ int main(int argc, char **argv)
Verilated::commandArgs(argc, argv);
Vconspiracion top;
+
+#ifdef TRACE
+ Verilated::traceEverOn(true);
+ VerilatedVcdC trace;
+
+ top.trace(&trace, 0);
+ trace.open("trace.vcd");
+#endif
+
interconnect<Vconspiracion_platform> avl(*top.conspiracion->plat);
+ mem hps_ddr3(0x0000'0000, 512 << 20);
+
+ avl.attach(hps_ddr3);
int time = 0;
+ top.clk_clk = 1;
+
auto tick = [&]()
{
- top.clk_clk = 0;
- top.eval();
- top.clk_clk = 1;
+ top.clk_clk = !top.clk_clk;
top.eval();
- avl.tick();
+ avl.tick(top.clk_clk);
+#ifdef TRACE
+ trace.dump(time++);
+#endif
+ };
+
+ auto cycle = [&]()
+ {
+ tick();
+ tick();
+ std::printf("[%02d] out=0x%02x, done=%d\n", time, top.out, top.done);
+ };
- std::printf("[%02d] out=0x%02x, done=%d\n", ++time, top.out, top.done);
+ auto io = [&]()
+ {
+ top.io = 0;
+ cycle();
+ top.io = 1;
+ for(int i = 0; i < 4; ++i)
+ {
+ cycle();
+ }
};
top.dir = 1;
@@ -36,14 +70,24 @@ int main(int argc, char **argv)
for(int i = 0; i < 5; ++i)
{
top.add = 0;
- tick();
+ cycle();
top.add = 1;
- tick();
+ cycle();
}
- top.io = 0;
- tick();
- tick();
+ io();
+
+ top.clr = 0;
+ cycle();
+ top.clr = 1;
+ cycle();
+
+ top.dir = 0;
+ io();
+
+#ifdef TRACE
+ trace.close();
+#endif
top.final();
}