cvw/soc/ahbxuiconverter.sv
2024-03-27 10:16:31 -05:00

115 lines
4.6 KiB
Systemverilog

///////////////////////////////////////////
// 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