diff options
| author | Alejandro Soto <alejandro@34project.org> | 2022-09-18 17:16:46 -0600 |
|---|---|---|
| committer | Alejandro Soto <alejandro@34project.org> | 2022-09-18 17:16:46 -0600 |
| commit | 503957e2883e754fc8424c420c3d9838bd639ed3 (patch) | |
| tree | f4b0bad5928fee6a43b73f246df875e14b3f6728 | |
| parent | 54544911601351465a6a887a045f3baddcb90dc6 (diff) | |
Fix memory simulation
| -rw-r--r-- | rtl/bus/master.sv | 2 | ||||
| -rw-r--r-- | tb/avalon.hpp | 15 | ||||
| -rw-r--r-- | tb/avalon.impl.hpp | 44 | ||||
| -rw-r--r-- | tb/top/conspiracion.cpp | 66 |
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(); } |
