From b05893647fb1cc192fa5832887a7369b1762c339 Mon Sep 17 00:00:00 2001 From: Marcus Mellor Date: Wed, 28 Feb 2024 15:47:18 -0600 Subject: [PATCH] uncore: Add bsg_dmc and expose DDR PHY interface --- .gitmodules | 3 + src/uncore/ahbxuiconverter.sv | 114 +++++++++++++++++++++++ src/uncore/basejump_stl | 1 + src/uncore/bsg_dmc_ahb.sv | 164 ++++++++++++++++++++++++++++++++++ 4 files changed, 282 insertions(+) create mode 100644 src/uncore/ahbxuiconverter.sv create mode 160000 src/uncore/basejump_stl create mode 100644 src/uncore/bsg_dmc_ahb.sv diff --git a/.gitmodules b/.gitmodules index 4717e75eb..4be9799dc 100644 --- a/.gitmodules +++ b/.gitmodules @@ -29,3 +29,6 @@ [submodule "addins/ahbsdc"] path = addins/ahbsdc url = http://github.com/JacobPease/ahbsdc.git +[submodule "src/uncore/basejump_stl"] + path = src/uncore/basejump_stl + url = https://github.com/bespoke-silicon-group/basejump_stl diff --git a/src/uncore/ahbxuiconverter.sv b/src/uncore/ahbxuiconverter.sv new file mode 100644 index 000000000..cb607889b --- /dev/null +++ b/src/uncore/ahbxuiconverter.sv @@ -0,0 +1,114 @@ +/////////////////////////////////////////// +// ahbxuiconverter.sv +// +// Written: infinitymdm@gmail.com +// +// Purpose: AHB to Xilinx UI converter +// +// Documentation: +// +// A component of the CORE-V-WALLY configurable RISC-V project. +// https://github.com/openhwgroup/cvw +// +// Copyright (C) 2021-24 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file +// except in compliance with the License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work distributed under the +// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions +// and limitations under the License. +//////////////////////////////////////////////////////////////////////////////////////////////// + +module ahbxuiconverter #(parameter ADDR_SIZE = 31, + parameter DATA_SIZE = 64) ( + // AHB signals + input logic HCLK, + input logic HRESETn, + input logic HSEL, + input logic [ADDR_SIZE-1:0] HADDR, + input logic [DATA_SIZE-1:0] HWDATA, + input logic [DATA_SIZE/8-1:0] HWSTRB, + input logic HWRITE, + input logic [1:0] HTRANS, + input logic HREADY, + output logic [DATA_SIZE-1:0] HRDATA, + output logic HRESP, + output logic HREADYOUT, + + // UI signals + output logic sys_reset, + input logic ui_clk, // from PLL + input logic ui_clk_sync_rst, + output logic [ADDR_SIZE-1:0] app_addr, // Double check this width + output logic [2:0] app_cmd, + output logic app_en, + input logic app_rdy, + output logic app_wdf_wren, + output logic [DATA_SIZE-1:0] app_wdf_data, + output logic [DATA_SIZE/8-1:0] app_wdf_mask, + output logic app_wdf_end, + input logic app_wdf_rdy, + input logic [DATA_SIZE-1:0] app_rd_data, + input logic app_rd_data_end, + input logic app_rd_data_valid, + input logic init_calib_complete +); + + assign sys_reset = ~HRESETn; + + // Enable this peripheral when: + // a) selected, AND + // b) a transfer is started, AND + // c) the bus is ready + logic ahbEnable; + assign ahbEnable = HSEL & HTRANS[1] & HREADY; + + // UI is ready for a command when initialized and ready to read and write + logic uiReady; + assign uiReady = app_rdy & app_wdf_rdy & init_calib_complete; + + // Buffer the input down to ui_clk speed + logic [ADDR_SIZE-1:0] addr; + logic [DATA_SIZE-1:0] data; + logic [DATA_SIZE/8-1:0] mask; + logic cmdEnable, cmdWrite; + logic cmdwfull, cmdrempty; + // FIFO needs addr + (data + mask) + (enable + write) + fifo #(ADDR_SIZE + 9*DATA_SIZE/8 + 2, 32) cmdfifo ( + .wdata({HADDR, HWDATA, HWSTRB, ahbEnable, HWRITE}), + .winc(ahbEnable), .wclk(HCLK), .wrst_n(HRESETn), + .rinc(uiReady), .rclk(ui_clk), .rrst_n(~ui_clk_sync_rst), + .rdata({addr, data, mask, cmdEnable, cmdWrite}), + .wfull(cmdwfull), .rempty(cmdrempty) + ); + + // Delay transactions 1 clk so we can set wren on the cycle after write commands + flopen #(ADDR_SIZE) addrreg (ui_clk, uiReady, addr, app_addr); + flopenr #(3) cmdreg (ui_clk, ui_clk_sync_rst, uiReady, {2'b0, ~cmdWrite}, app_cmd); + flopenr #(1) cmdenreg (ui_clk, ui_clk_sync_rst, uiReady, cmdEnable, app_en); + flopenr #(1) wrenreg (ui_clk, ui_clk_sync_rst, uiReady, ~app_cmd[0], app_wdf_wren); + flopenr #(DATA_SIZE) datareg (ui_clk, ui_clk_sync_rst, uiReady, data, app_wdf_data); + flopenr #(DATA_SIZE/8) maskreg (ui_clk, ui_clk_sync_rst, uiReady, mask, app_wdf_mask); + assign app_wdf_end = app_wdf_wren; // Since AHB will always put data on the bus after a write cmd, this is always valid + + // Return read data at HCLK speed TODO: Double check that rinc is correct + logic respwfull, resprempty; + fifo #(DATA_SIZE, 16) respfifo ( + .wdata(app_rd_data), + .winc(app_rd_data_valid), .wclk(ui_clk), .wrst_n(~ui_clk_sync_rst), + .rinc(ahbEnable), .rclk(HCLK), .rrst_n(HRESETn), + .rdata(HRDATA), + .wfull(respwfull), .rempty(resprempty) + ); + + assign HRESP = 0; // do not indicate errors + assign HREADYOUT = uiReady & ~cmdwfull; // TODO: Double check + +endmodule diff --git a/src/uncore/basejump_stl b/src/uncore/basejump_stl new file mode 160000 index 000000000..14f29e4d8 --- /dev/null +++ b/src/uncore/basejump_stl @@ -0,0 +1 @@ +Subproject commit 14f29e4d8a498ad62ec05fe232407f9d887e36a9 diff --git a/src/uncore/bsg_dmc_ahb.sv b/src/uncore/bsg_dmc_ahb.sv new file mode 100644 index 000000000..83de36b86 --- /dev/null +++ b/src/uncore/bsg_dmc_ahb.sv @@ -0,0 +1,164 @@ +/////////////////////////////////////////// +// bsg_dmc_ahb.sv +// +// Written: infinitymdm@gmail.com +// +// Purpose: BSG controller and LPDDRDRAM presenting an AHB interface +// +// Documentation: +// +// A component of the CORE-V-WALLY configurable RISC-V project. +// https://github.com/openhwgroup/cvw +// +// Copyright (C) 2021-24 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file +// except in compliance with the License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work distributed under the +// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions +// and limitations under the License. +//////////////////////////////////////////////////////////////////////////////////////////////// + +`include "bsg_dmc.svh" + +module bsg_dmc_ahb + import bsg_tag_pkg::*; + import bsg_dmc_pkg::*; +#( + parameter ADDR_SIZE = 28, + parameter DATA_SIZE = 64, + parameter BURST_LENGTH = 8, + parameter FIFO_DEPTH = 4, +) ( + input logic HCLK, HRESETn, + input logic HSEL, + input logic [ADDR_SIZE-1:0] HADDR, + input logic [DATA_SIZE-1:0] HWDATA, + input logic [DATA_SIZE/8-1:0] HWSTRB, + input logic HWRITE, + input logic [1:0] HTRANS, + input logic HREADY, + output logic [DATA_SIZE-1:0] HRDATA, + output logic HRESP, HREADYOUT, + //input logic ui_clk // Add this once PLL is integrated + output logic ddr_ck_p, ddr_ck_n, ddr_cke, + output logic [2:0] ddr_ba, + output logic [15:0] ddr_addr, + output logic ddr_cs, ddr_ras, ddr_cas, + output logic ddr_we, ddr_reset, ddr_odt, + output logic [DATA_SIZE/16-1:0] ddr_dm_oen, ddr_dm, + output logic [DATA_SIZE/16-1:0] ddr_dqs_p_oen, ddr_dqs_p_ien, ddr_dqs_p_out, + input logic [DATA_SIZE/16-1:0] ddr_dqs_p_in, + output logic [DATA_SIZE/16-1:0] ddr_dqs_n_oen, ddr_dqs_n_ien, ddr_dqs_n_out, + input logic [DATA_SIZE/16-1:0] ddr_dqs_n_in, + output logic [DATA_SIZE/2-1:0] ddr_dq_oen, ddr_dq_out, + input logic [DATA_SIZE/2-1:0] ddr_dq_in, + input logic dfi_clk_2x, + output logic dfi_clk_1x +); + + localparam BURST_DATA_SIZE = DATA_SIZE * BURST_LENGTH; + // localparam DQ_DATA_SIZE = DATA_SIZE >> 1; + + // Global async reset + logic sys_reset; + + // Memory controller config + bsg_tag_s dmc_rst_tag, dmc_ds_tag; + bsg_tag_s [3:0] dmc_dly_tag, dmc_dly_trigger_tag; + bsg_dmc_s dmc_config; + + // UI signals + logic ui_clk_sync_rst; + logic [ADDR_SIZE-1:0] app_addr; + logic [2:0] app_cmd; + logic app_en, app_rdy, app_wdf_wren; + logic [DATA_SIZE-1:0] app_wdf_data; + logic [DATA_SIZE/8-1:0] app_wdf_mask; + logic app_wdf_end, app_wdf_rdy; + logic [DATA_SIZE-1:0] app_rd_data; + logic app_rd_data_end, app_rd_data_valid; + logic app_ref_ack, app_zq_ack, app_sr_active; // Sink unused UI signals + logic init_calib_complete; + logic [11:0] device_temp; // Reserved + + // Use a /6 clock divider until PLL is integrated. TODO: Replace + logic ui_clk; + integer clk_counter = 0; + always @(posedge HCLK) begin + counter <= counter + 1; + if (counter >= 6) counter <= 0; + ui_clk <= (counter >= 3); + end + + // TODO: Figure out how to initialize dmc_config correctly + always_comb begin: bsg_dmc_config + dmc_p.trefi = 1023; + dmc_p.tmrd = 1; + dmc_p.trfc = 15; + dmc_p.trc = 10; + dmc_p.trp = 2; + dmc_p.tras = 7; + dmc_p.trrd = 1; + dmc_p.trcd = 2; + dmc_p.twr = 10; + dmc_p.twtr = 7; + dmc_p.trtp = 10; + dmc_p.tcas = 3; + dmc_p.col_width = 11; + dmc_p.row_width = 14; + dmc_p.bank_width = 2; + dmc_p.dqs_sel_cal = 3; + dmc_p.init_cycles = 40010; + dmc_p.bank_pos = 25; + end + + ahbxuiconverter #(ADDR_SIZE, DATA_SIZE) bsg_dmc_ahb_ui_converter ( + .HCLK, .HRESETn, .HSEL, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HTRANS, .HREADY, .HRDATA, .HRESP, .HREADYOUT, + .sys_reset, .ui_clk, .ui_clk_sync_rst, + .app_addr, .app_cmd, .app_en, .app_rdy, + .app_wdf_wren, .app_wdf_data, .app_wdf_mask, .app_wdf_end, .app_wdf_rdy, + .app_rd_data, .app_rd_data_end, .app_rd_data_valid, + .init_calib_complete + ); + + bsg_dmc #( + .num_adgs_p(1), + .ui_addr_width_p(ADDR_SIZE), + .ui_data_width_p(DATA_SIZE), + .burst_data_width_p(BURST_DATA_SIZE), + .dq_data_width_p(DQ_DATA_SIZE), + .cmd_afifo_depth(FIFO_DEPTH), + .cmd_sfifo_depth(FIFO_DEPTH) + ) dmc ( + .async_reset_tag_i(dmc_rst_tag), + .bsg_dly_tag_i(dmc_dly_tag), .bsg_dly_trigger_tag_i(dmc_dly_trigger_tag), .bsg_ds_tag_i(dmc_ds_tag), + .dmc_p_i(dmc_config), + .sys_reset_i(sys_reset), + .app_addr_i(app_addr), .app_cmd_i(app_cmd), .app_en_i(app_en), .app_rdy_o(app_rdy), + .app_wdf_wren_i(app_wdf_wren), .app_wdf_data_i(app_wdf_data), .app_wdf_mask_i(app_wdf_mask), .app_wdf_end_i(app_wdf_end), .app_wdf_rdy_o(app_wdf_rdy), + .app_rd_data_valid_o(app_rd_data_valid), .app_rd_data_o(app_rd_data), .app_rd_data_end_o(app_rd_data_end), + .app_ref_req_i(1'b0), .app_ref_ack_o(app_ref_ack), + .app_zq_req_i(1'b0), .app_zq_ack_o(app_zq_ack), + .app_sr_req_i(1'b0), .app_sr_active_o(app_sr_active), + .init_calib_complete_o(init_calib_complete), + .ddr_ck_p_o(ddr_ck_p), .ddr_ck_n_o(ddr_ck_n), .ddr_cke_o(ddr_cke), + .ddr_ba_o(ddr_ba), .ddr_addr_o(ddr_addr), .ddr_cs_n_o(ddr_cs), .ddr_ras_n_o(ddr_ras), .ddr_cas_n_o(ddr_cas), + .ddr_we_n_o(ddr_we), .ddr_reset_n_o(ddr_reset), .ddr_odt_o(ddr_odt), + .ddr_dm_oen_o(ddr_dm_oen), .ddr_dm_o(ddr_dm), + .ddr_dqs_p_oen_o(ddr_dqs_p_oen), .ddr_dqs_p_ien_o(ddr_dqs_p_ien), .ddr_dqs_p_o(ddr_dqs_p_out), .ddr_dqs_p_i(ddr_dqs_p_in), + .ddr_dqs_n_oen_o(ddr_dqs_n_oen), .ddr_dqs_n_ien_o(ddr_dqs_n_ien), .ddr_dqs_n_o(ddr_dqs_n_out), .ddr_dqs_n_i(ddr_dqs_n_in), + .ddr_dq_oen_o(ddr_dq_oen), .ddr_dq_o(ddr_dq_out), .ddr_dq_i(ddr_dq_in), + .ui_clk_i(ui_clk), + .dfi_clk_2x_i(dfi_clk_2x), .dfi_clk_1x_o(dfi_clk_1x), + .ui_clk_sync_rst_o(ui_clk_sync_rst), + .device_temp_o(device_temp) + ); +endmodule