From 8ec66f50c64501e30ed6adae94f89b90b48de7f0 Mon Sep 17 00:00:00 2001 From: Alejandro Soto Date: Sat, 19 Nov 2022 19:36:21 -0600 Subject: Implement interval timer simulation --- tb/interval_timer.cpp | 97 +++++++++++++++++++++++++++++++++++++++++++++++++ tb/interval_timer.hpp | 31 ++++++++++++++++ tb/top/conspiracion.cpp | 8 ++++ 3 files changed, 136 insertions(+) create mode 100644 tb/interval_timer.cpp create mode 100644 tb/interval_timer.hpp diff --git a/tb/interval_timer.cpp b/tb/interval_timer.cpp new file mode 100644 index 0000000..f593894 --- /dev/null +++ b/tb/interval_timer.cpp @@ -0,0 +1,97 @@ +#include "avalon.hpp" +#include "interval_timer.hpp" + +namespace taller::avalon +{ + interval_timer::interval_timer(std::uint32_t base) noexcept + : slave(base, 32, 4) + {} + + void interval_timer::tick() noexcept + { + if(!status_run) + { + return; + } else if(count > 0) + { + --count; + } else + { + count = period; + status_to = 1; + status_run = control_cont; + } + } + + bool interval_timer::read(std::uint32_t addr, std::uint32_t &data) noexcept + { + switch(addr) + { + case 0: + data + = status_run << 1 + | status_to << 0; + + break; + + case 1: + data + = control_cont << 1 + | control_ito << 0; + + break; + + case 2: + data = period & 0xffff; + break; + + case 3: + data = period >> 16; + break; + + case 4: + data = snap & 0xffff; + break; + + case 5: + data = snap >> 16; + break; + } + + return true; + } + + bool interval_timer::write(std::uint32_t addr, std::uint32_t data, unsigned byte_enable) noexcept + { + switch(addr) + { + case 0: + status_to = 0; + break; + + case 1: + control_ito = !!(data & (1 << 0)); + control_cont = !!(data & (1 << 1)); + + status_run = (status_run && !!(data << (1 << 3))) || !!(data << (1 << 2)); + break; + + case 2: + period = (period & 0xffff'0000) | (data & 0xffff); + count = period; + break; + + case 3: + period = (period & 0xffff) | (data & 0xffff) << 16; + count = period; + break; + + case 4: + case 5: + snap = count; + break; + } + + return true; + } +} diff --git a/tb/interval_timer.hpp b/tb/interval_timer.hpp new file mode 100644 index 0000000..7cce265 --- /dev/null +++ b/tb/interval_timer.hpp @@ -0,0 +1,31 @@ +#ifndef TALLER_INTERVAL_TIMER_HPP +#define TALLER_INTERVAL_TIMER_HPP + +#include + +#include "avalon.hpp" + +namespace taller::avalon +{ + class interval_timer : public slave + { + public: + interval_timer(std::uint32_t base) noexcept; + + void tick() noexcept; + + virtual bool read(std::uint32_t addr, std::uint32_t &data) noexcept final override; + virtual bool write(std::uint32_t addr, std::uint32_t data, unsigned byte_enable) noexcept final override; + + private: + std::uint32_t count; + std::uint32_t period; + std::uint32_t snap; + bool status_to = false; + bool status_run = false; + bool control_ito = false; + bool control_cont = false; + }; +} + +#endif diff --git a/tb/top/conspiracion.cpp b/tb/top/conspiracion.cpp index 984cb58..d710bde 100644 --- a/tb/top/conspiracion.cpp +++ b/tb/top/conspiracion.cpp @@ -25,6 +25,7 @@ #include "../const.hpp" #include "../mem.hpp" #include "../jtag_uart.hpp" +#include "../interval_timer.hpp" #include "../null.hpp" #include "../window.hpp" #include "../vga.hpp" @@ -251,6 +252,7 @@ int main(int argc, char **argv) mem hps_ddr3(0x0000'0000, 512 << 20); jtag_uart ttyj0(0x3000'0000); + interval_timer timer(0x3002'0000); mem vram(0x3800'0000, 64 << 20); null vram_null(0x3800'0000, 64 << 20, 2); window vram_window(vram, 0x0000'0000); @@ -266,6 +268,7 @@ int main(int argc, char **argv) avl.attach(hps_ddr3); avl.attach(ttyj0); + avl.attach(timer); for(auto &slave : consts) { @@ -329,6 +332,11 @@ int main(int argc, char **argv) top.clk_clk = !top.clk_clk; top.eval(); + if(top.clk_clk) + { + timer.tick(); + } + if(!avl.tick(top.clk_clk)) { failed = true; -- cgit v1.2.3