summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlejandro Soto <alejandro@34project.org>2022-11-19 19:36:21 -0600
committerAlejandro Soto <alejandro@34project.org>2022-11-19 19:36:27 -0600
commit8ec66f50c64501e30ed6adae94f89b90b48de7f0 (patch)
treedf0cd1fdd699d179ff87aa40410cabb047f9a9f1
parent0aabf3cb8e11409506bf90d6cd0c1125f3df7c04 (diff)
Implement interval timer simulation
Diffstat (limited to '')
-rw-r--r--tb/interval_timer.cpp97
-rw-r--r--tb/interval_timer.hpp31
-rw-r--r--tb/top/conspiracion.cpp8
3 files changed, 136 insertions, 0 deletions
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 <cstdint>
+
+#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<std::uint32_t> hps_ddr3(0x0000'0000, 512 << 20);
jtag_uart ttyj0(0x3000'0000);
+ interval_timer timer(0x3002'0000);
mem<std::uint32_t> 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;