summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlejandro W. Sior <aho@sior.be>2023-08-19 12:08:26 +0200
committerAlejandro W. Sior <aho@sior.be>2023-08-19 12:08:26 +0200
commit13884426be31ba9cbb298927fcb3727d610a6a22 (patch)
treef28c86eb48ff61b515030896f2a41bdab47adfbd
getting startedHEADmaster
-rw-r--r--.gitignore1
-rw-r--r--DRAM.cpp59
-rw-r--r--DRAM.h32
-rw-r--r--arbiter.v67
-rw-r--r--soc.cpp51
-rw-r--r--system.v33
6 files changed, 243 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..697cf4f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+obj_dir/
diff --git a/DRAM.cpp b/DRAM.cpp
new file mode 100644
index 0000000..5a0faac
--- /dev/null
+++ b/DRAM.cpp
@@ -0,0 +1,59 @@
+#include "DRAM.h"
+
+
+DRAM::DRAM() {
+ buf = new uint8_t[16*1024];
+}
+DRAM::~DRAM() {
+ delete[] buf;
+}
+void DRAM::apply(
+ CData clk,
+ CData we,
+ uint64_t claddr,
+ VlWide<4>* cldata) {
+ this->prev_clk = this->clk;
+ this->clk = clk;
+ this->we = we;
+ this->claddr = claddr;
+ this->cldata = cldata;
+}
+
+void DRAM::eval() {
+ if (!prev_clk && clk)
+ posedge_clk();
+}
+
+void DRAM::posedge_clk() {
+ // Align address on cache line address boundary
+ claddr &= ~0xF;
+
+ // Get a word based pointer to the memory
+ uint32_t *base = (uint32_t*)(buf + claddr);
+
+ if (we) {
+ printf("DRAM: write at %llx: %x%x%x%x\n",
+ claddr,
+ cldata->at(3),
+ cldata->at(2),
+ cldata->at(1),
+ cldata->at(0)
+ );
+
+ // Write the memory from the bus
+ for (int i = 0; i < 4; i++)
+ base[i] = cldata->at(i);
+ } else {
+ // Write the bus from the memory
+ for (int i = 0; i < 4; i++)
+ cldata->at(i) = base[i];
+
+ printf("DRAM: read at %llx: %x%x%x%x\n",
+ claddr,
+ cldata->at(3),
+ cldata->at(2),
+ cldata->at(1),
+ cldata->at(0)
+ );
+ }
+} \ No newline at end of file
diff --git a/DRAM.h b/DRAM.h
new file mode 100644
index 0000000..bc36a93
--- /dev/null
+++ b/DRAM.h
@@ -0,0 +1,32 @@
+#pragma once
+
+#include <verilated.h>
+#include <verilated_vcd_c.h>
+
+#include <stdio.h>
+
+/* DRAM
+ * A basic device simulating DRAM.
+ */
+struct DRAM {
+ uint8_t *buf;
+
+ DRAM();
+ ~DRAM();
+
+ CData prev_clk;
+ CData clk;
+ CData we;
+ uint64_t claddr;
+ VlWide<4>* cldata;
+
+ void apply(
+ CData clk,
+ CData we,
+ uint64_t claddr,
+ VlWide<4>* cldata);
+
+ void eval();
+
+ void posedge_clk();
+}; \ No newline at end of file
diff --git a/arbiter.v b/arbiter.v
new file mode 100644
index 0000000..0e83403
--- /dev/null
+++ b/arbiter.v
@@ -0,0 +1,67 @@
+/* Arbiter
+ * A module that grants access to a shared ressource (e.g a bus)
+ * to an arbitrary amount of drivers. A driver of the shared resource
+ * has a bit on the `request` line and fires it up when it wants to use
+ * the resource. The arbiter fires the corresponding `grant` bit when
+ * the driver is allowed to use the resource */
+module arbiter #(
+ parameter NUM_CLIENTS = 4
+) (
+ input clk,
+
+ // Request bits, each driver has its request line
+ input[NUM_CLIENTS-1:0] request,
+
+ // Grant bits, each driver has its grant line
+ output[NUM_CLIENTS-1:0] grant
+);
+ // The current round of the arbiter
+ reg[NUM_CLIENTS-1:0] round = 1;
+
+ // A circle of wires used by the arbiter to
+ // indicate that a driver that has the priority
+ // to use the resource yields it to the next driver
+ // because it doesn't need to use the resource
+ wire pass_on_rollover;
+ /* verilator lint_off UNOPTFLAT */
+ logic pass_on;
+ assign pass_on_rollover = pass_on; // NOTE: assign is applied on last assignment to wire
+
+ // Logic bitfield used to generate the grant bus
+ logic[NUM_CLIENTS-1:0] grant_gen;
+ assign grant = grant_gen;
+
+ always @(posedge clk) begin
+ // Keep current grant as round, allowing a selected driver
+ // to freeze the arbiter during the entire duration of its
+ // resource utilization
+ round <= |grant ?
+ grant : { round[NUM_CLIENTS-2:0], round[NUM_CLIENTS-1] };
+ end
+
+ always_comb begin
+ pass_on = pass_on_rollover;
+
+ for (integer i = 0; i < NUM_CLIENTS; i++) begin
+ logic has_priority;
+
+ // Current driver has priority if it's its round
+ // or previous driver has passed on its
+ has_priority = round[i] || pass_on;
+
+ // By default, do not grant to driver
+ grant_gen[i] = 0;
+
+ // By default, do not pass on priority
+ // to next driver (current may not have it)
+ pass_on = 0;
+
+ if (has_priority) begin
+ if (request[i])
+ grant_gen[i] = 1;
+ else
+ pass_on = 1;
+ end
+ end
+ end
+endmodule \ No newline at end of file
diff --git a/soc.cpp b/soc.cpp
new file mode 100644
index 0000000..c6c378b
--- /dev/null
+++ b/soc.cpp
@@ -0,0 +1,51 @@
+#include <verilated.h>
+#include <verilated_vcd_c.h>
+#include "Vsystem.h"
+#include <iostream>
+
+#include "DRAM.h"
+
+struct Bench {
+ Vsystem *system;
+ DRAM *dram;
+
+ Bench() {
+ system = new Vsystem();
+ dram = new DRAM();
+
+ system->eval();
+ eval();
+ }
+ ~Bench() {
+ delete dram;
+ delete system;
+ }
+
+ void eval() {
+ // Apply signals to the DRAM
+ dram->apply(
+ system->clk,
+ system->mem_we,
+ system->mem_claddr,
+ &system->mem_cldata
+ );
+ // Eval the DRAM
+ dram->eval();
+
+ // Eval the system
+ system->eval();
+ }
+
+ void tick() {
+ system->clk ^= 1;
+ eval();
+ }
+};
+
+int main() {
+ Bench bench;
+
+
+ for (int i = 0; i < 10000; i++)
+ bench.tick();
+} \ No newline at end of file
diff --git a/system.v b/system.v
new file mode 100644
index 0000000..edc7b25
--- /dev/null
+++ b/system.v
@@ -0,0 +1,33 @@
+`include "arbiter.v"
+module system(
+ input clk,
+
+ // DRAM device
+ output[63:0] mem_claddr,
+ output mem_we,
+ inout[127:0] mem_cldata);
+
+ reg [3:0] request = 'b0001;
+
+ arbiter arbiter(
+ .clk(clk),
+ .request(request),
+ .grant()
+ );
+
+ reg[127:0] counter = 0;
+ assign mem_we = 0;
+ assign mem_claddr = 17;
+ assign mem_cldata = 42;
+
+ always @(posedge clk) begin
+ if (counter > 1100)
+ request <= 0;
+ else if (counter > 1050)
+ request <= 'b0011;
+ else if (counter > 1000)
+ request <= 'b0100;
+
+ counter <= counter + 1;
+ end
+endmodule \ No newline at end of file