Add Pinyon dual port RAM interface
authorRaptor Engineering Development Team <support@raptorengineering.com>
Sun, 6 Mar 2022 20:36:59 +0000 (14:36 -0600)
committerRaptor Engineering Development Team <support@raptorengineering.com>
Sun, 6 Mar 2022 20:36:59 +0000 (14:36 -0600)
LICENSE.pinyon [new file with mode: 0644]
README.pinyon [new file with mode: 0644]
pinyon/wishbone_interface.v [new file with mode: 0644]

diff --git a/LICENSE.pinyon b/LICENSE.pinyon
new file mode 100644 (file)
index 0000000..b8ecd35
--- /dev/null
@@ -0,0 +1 @@
+Pinyon is licensed under the terms of the GPU LGPLv3+
diff --git a/README.pinyon b/README.pinyon
new file mode 100644 (file)
index 0000000..15fd0c2
--- /dev/null
@@ -0,0 +1,3 @@
+# ARCHITECTURE
+
+Pinyon is a Wishbone-compatible lightweight dual-port RAM instance, with modular backend support.
diff --git a/pinyon/wishbone_interface.v b/pinyon/wishbone_interface.v
new file mode 100644 (file)
index 0000000..1eebc67
--- /dev/null
@@ -0,0 +1,79 @@
+// © 2022 Raptor Engineering, LLC
+//
+// Released under the terms of the LGPL v3+
+// See the LICENSE file for full details
+//
+// This module provides a standard RAM interface for various FPGA, simulation, and ASIC SRAM blocks
+//
+// CURRENT BACKENDS
+//  - Generic (relies on Yosys memory_libmap)
+//
+// PLANNED BACKENDS
+//  - 45nm ASIC (cycle-accurate simulation HDL)
+
+// Default to GENERIC backend
+`ifndef PINYON_RAM_BACKEND
+`define PINYON_RAM_BACKEND_GENERIC
+`define PINYON_RAM_BACKEND GENERIC
+`endif
+
+module pinyon_ram_wishbone(
+               // Wishbone read port signals
+               input wire wb_read_port_clk,
+               input wire [(BLOCK_RAM_ADDR_BUS_WIDTH-1):0] wb_read_port_adr,
+               output wire [(BLOCK_RAM_DATA_BUS_WIDTH-1):0] wb_read_port_dat_r,
+
+               // Wishbone write port signals
+               input wire wb_write_port_clk,
+               input wire wb_write_port_cyc,
+               input wire wb_write_port_stb,
+               input wire wb_write_port_we,
+               input wire [(BLOCK_RAM_ADDR_BUS_WIDTH-1):0] wb_write_port_adr,
+               input wire [(BLOCK_RAM_DATA_BUS_WIDTH-1):0] wb_write_port_dat_w,
+               output wire wb_write_port_ack
+       );
+
+       // Wishbone port parameters
+       parameter BLOCK_RAM_ADDR_BUS_WIDTH = 8;
+       parameter BLOCK_RAM_DATA_BUS_WIDTH = 8;
+
+`ifdef PINYON_RAM_BACKEND_GENERIC
+       // Infer appropriate block RAM
+       reg [(BLOCK_RAM_DATA_BUS_WIDTH-1):0] data_array [((2**BLOCK_RAM_ADDR_BUS_WIDTH)-1):0];
+
+       integer i;
+       initial begin
+               for (i=0; i<((2**BLOCK_RAM_ADDR_BUS_WIDTH)-1); i=i+1) begin
+                       data_array[i] = 0;
+               end
+       end
+
+       reg [(BLOCK_RAM_DATA_BUS_WIDTH-1):0] wb_read_port_dat_r_reg = 0;
+       always @(posedge wb_read_port_clk) begin
+               wb_read_port_dat_r_reg <= data_array[wb_read_port_adr];
+       end
+
+       always @(posedge wb_write_port_clk) begin
+               if (wb_write_port_cyc && wb_write_port_stb && wb_write_port_we) begin
+                       data_array[wb_write_port_adr] <= wb_write_port_dat_w;
+               end
+       end
+
+       // Try not to confuse simple-minded synthesis tooling with the ACK logic
+       reg wb_write_port_ack_reg = 0;
+       always @(posedge wb_write_port_clk) begin
+               if (wb_write_port_cyc && wb_write_port_stb) begin
+                       wb_write_port_ack_reg <= 1;
+               end else begin
+                       wb_write_port_ack_reg <= 0;
+               end
+       end
+
+       // Assign registered outputs
+       assign wb_read_port_dat_r = wb_read_port_dat_r_reg;
+       assign wb_write_port_ack = wb_write_port_ack_reg;
+`else
+       `error_invalid_pinyon_backend_requested
+`endif
+
+endmodule
\ No newline at end of file