Files
retroSoC/rtl/ip/native/interconnect/nmi2apb.sv
T
maksyuki fb3621e6b8 feat: add QSPI Flash and Flash Read Binder modules
- Introduced  for handling QSPI flash memory operations, including command and address handling.
- Added  to interface with the C++ flash memory implementation, allowing for read operations via DPI-C.
- Created  for the flash memory implementation, supporting initialization, reading, and memory copying.
- Updated  to integrate the new QSPI Flash module and connect it with the existing system.
- Refactored file paths in various filelists and scripts to accommodate the new directory structure under .
- Enhanced the Python scripts for generating memory maps and preparing the environment for the new structure.
- Adjusted test scripts to reflect changes in the directory structure and ensure compatibility with the new modules.
2026-07-20 16:50:57 +08:00

217 lines
7.5 KiB
Systemverilog

// Copyright (c) 2023-2026 Yuchi Miao <miaoyuchi@ict.ac.cn>
// retroSoC is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
// http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
`include "mmap_define.svh"
module nmi2apb (
// verilog_format: off
input logic clk_i,
input logic rst_n_i,
nmi_if.slave nmi,
`ifdef IP_MDD
apb4_pure_if.master user_ip,
`endif
apb4_pure_if.master archinfo,
apb4_pure_if.master rng,
apb4_pure_if.master uart,
apb4_pure_if.master pwm,
apb4_pure_if.master ps2,
apb4_pure_if.master rtc,
apb4_pure_if.master wdg,
apb4_pure_if.master crc,
apb4_pure_if.master tmr
// verilog_format: on
);
localparam FSM_IDLE = 2'd0;
localparam FSM_SETP = 2'd1;
localparam FSM_ENAB = 2'd2;
logic [31:0] s_rd_data;
logic s_xfer_valid, s_xfer_ready;
logic s_mem_valid_re;
logic [1:0] s_fsm_d, s_fsm_q;
// Registered slave-select one-hot for response mux
`ifdef IP_MDD
localparam NSLV = 10;
`else
localparam NSLV = 9;
`endif
logic [NSLV-1:0] s_psel_comb, s_psel_d, s_psel_q;
// verilog_format: off
assign archinfo.paddr = nmi.addr;
assign rng.paddr = nmi.addr;
assign uart.paddr = nmi.addr;
assign pwm.paddr = nmi.addr;
assign ps2.paddr = nmi.addr;
assign rtc.paddr = nmi.addr;
assign wdg.paddr = nmi.addr;
assign crc.paddr = nmi.addr;
assign tmr.paddr = nmi.addr;
assign archinfo.pprot = '0;
assign rng.pprot = '0;
assign uart.pprot = '0;
assign pwm.pprot = '0;
assign ps2.pprot = '0;
assign rtc.pprot = '0;
assign wdg.pprot = '0;
assign crc.pprot = '0;
assign tmr.pprot = '0;
assign archinfo.psel = s_xfer_valid && `SOC_ADDR_IS_APB_ARCHINFO(nmi.addr);
assign rng.psel = s_xfer_valid && `SOC_ADDR_IS_APB_RNG(nmi.addr);
assign uart.psel = s_xfer_valid && `SOC_ADDR_IS_APB_UART1(nmi.addr);
assign pwm.psel = s_xfer_valid && `SOC_ADDR_IS_APB_PWM(nmi.addr);
assign ps2.psel = s_xfer_valid && `SOC_ADDR_IS_APB_PS2(nmi.addr);
assign rtc.psel = s_xfer_valid && `SOC_ADDR_IS_APB_RTC(nmi.addr);
assign wdg.psel = s_xfer_valid && `SOC_ADDR_IS_APB_WDG(nmi.addr);
assign crc.psel = s_xfer_valid && `SOC_ADDR_IS_APB_CRC(nmi.addr);
assign tmr.psel = s_xfer_valid && `SOC_ADDR_IS_APB_TMR(nmi.addr);
assign archinfo.penable = s_fsm_q == FSM_ENAB;
assign rng.penable = s_fsm_q == FSM_ENAB;
assign uart.penable = s_fsm_q == FSM_ENAB;
assign pwm.penable = s_fsm_q == FSM_ENAB;
assign ps2.penable = s_fsm_q == FSM_ENAB;
assign rtc.penable = s_fsm_q == FSM_ENAB;
assign wdg.penable = s_fsm_q == FSM_ENAB;
assign crc.penable = s_fsm_q == FSM_ENAB;
assign tmr.penable = s_fsm_q == FSM_ENAB;
assign archinfo.pwrite = |nmi.wstrb;
assign rng.pwrite = |nmi.wstrb;
assign uart.pwrite = |nmi.wstrb;
assign pwm.pwrite = |nmi.wstrb;
assign ps2.pwrite = |nmi.wstrb;
assign rtc.pwrite = |nmi.wstrb;
assign wdg.pwrite = |nmi.wstrb;
assign crc.pwrite = |nmi.wstrb;
assign tmr.pwrite = |nmi.wstrb;
assign archinfo.pwdata = nmi.wdata;
assign rng.pwdata = nmi.wdata;
assign uart.pwdata = nmi.wdata;
assign pwm.pwdata = nmi.wdata;
assign ps2.pwdata = nmi.wdata;
assign rtc.pwdata = nmi.wdata;
assign wdg.pwdata = nmi.wdata;
assign crc.pwdata = nmi.wdata;
assign tmr.pwdata = nmi.wdata;
assign archinfo.pstrb = nmi.wstrb;
assign rng.pstrb = nmi.wstrb;
assign uart.pstrb = nmi.wstrb;
assign pwm.pstrb = nmi.wstrb;
assign ps2.pstrb = nmi.wstrb;
assign rtc.pstrb = nmi.wstrb;
assign wdg.pstrb = nmi.wstrb;
assign crc.pstrb = nmi.wstrb;
assign tmr.pstrb = nmi.wstrb;
`ifdef IP_MDD
assign user_ip.paddr = nmi.addr;
assign user_ip.pprot = '0;
assign user_ip.psel = s_xfer_valid && `SOC_ADDR_IS_APB_USER_IP(nmi.addr);
assign user_ip.penable = s_fsm_q == FSM_ENAB;
assign user_ip.pwrite = |nmi.wstrb;
assign user_ip.pwdata = nmi.wdata;
assign user_ip.pstrb = nmi.wstrb;
`endif
// verilog_format: on
edge_det_sync_re #(1) u_mem_valid_edge_det_sync_re (
clk_i,
rst_n_i,
nmi.valid,
s_mem_valid_re
);
assign s_xfer_valid = ((s_fsm_q == FSM_IDLE) && s_mem_valid_re) ||
(s_fsm_q == FSM_SETP) || (s_fsm_q == FSM_ENAB);
always_comb begin
s_fsm_d = s_fsm_q;
unique case (s_fsm_q)
FSM_IDLE: if (s_mem_valid_re) s_fsm_d = FSM_SETP;
FSM_SETP: s_fsm_d = FSM_ENAB;
FSM_ENAB: if (s_xfer_ready) s_fsm_d = FSM_IDLE;
default: s_fsm_d = s_fsm_q;
endcase
end
dffr #(2) u_fsm_dffr (
clk_i,
rst_n_i,
s_fsm_d,
s_fsm_q
);
assign nmi.ready = nmi.valid && (s_fsm_q == FSM_ENAB) && s_xfer_ready;
assign nmi.rdata = {32{nmi.ready}} & s_rd_data;
// Capture slave-select one-hot at FSM_SETP for cleaner response mux
// verilog_format: off
assign s_psel_comb[0] = `SOC_ADDR_IS_APB_ARCHINFO(nmi.addr);
assign s_psel_comb[1] = `SOC_ADDR_IS_APB_RNG(nmi.addr);
assign s_psel_comb[2] = `SOC_ADDR_IS_APB_UART1(nmi.addr);
assign s_psel_comb[3] = `SOC_ADDR_IS_APB_PWM(nmi.addr);
assign s_psel_comb[4] = `SOC_ADDR_IS_APB_PS2(nmi.addr);
assign s_psel_comb[5] = `SOC_ADDR_IS_APB_RTC(nmi.addr);
assign s_psel_comb[6] = `SOC_ADDR_IS_APB_WDG(nmi.addr);
assign s_psel_comb[7] = `SOC_ADDR_IS_APB_CRC(nmi.addr);
assign s_psel_comb[8] = `SOC_ADDR_IS_APB_TMR(nmi.addr);
`ifdef IP_MDD
assign s_psel_comb[9] = `SOC_ADDR_IS_APB_USER_IP(nmi.addr);
`endif
assign s_psel_d = (s_fsm_q == FSM_IDLE && s_mem_valid_re) ? s_psel_comb : s_psel_q;
// verilog_format: on
dffr #(NSLV) u_psel_dffr (
clk_i,
rst_n_i,
s_psel_d,
s_psel_q
);
// Response mux using registered slave-select (cleaner timing)
// verilog_format: off
assign s_rd_data = ({32{s_psel_q[0]}} & archinfo.prdata) |
({32{s_psel_q[1]}} & rng.prdata) |
({32{s_psel_q[2]}} & uart.prdata) |
({32{s_psel_q[3]}} & pwm.prdata) |
({32{s_psel_q[4]}} & ps2.prdata) |
({32{s_psel_q[5]}} & rtc.prdata) |
({32{s_psel_q[6]}} & wdg.prdata) |
({32{s_psel_q[7]}} & crc.prdata) |
`ifdef IP_MDD
({32{s_psel_q[9]}} & user_ip.prdata) |
`endif
({32{s_psel_q[8]}} & tmr.prdata);
assign s_xfer_ready = (s_psel_q[0] & archinfo.pready) |
(s_psel_q[1] & rng.pready) |
(s_psel_q[2] & uart.pready) |
(s_psel_q[3] & pwm.pready) |
(s_psel_q[4] & ps2.pready) |
(s_psel_q[5] & rtc.pready) |
(s_psel_q[6] & wdg.pready) |
(s_psel_q[7] & crc.pready) |
`ifdef IP_MDD
(s_psel_q[9] & user_ip.pready) |
`endif
(s_psel_q[8] & tmr.pready);
// verilog_format: on
endmodule