Files
fpga_modem/rtl/core/mcu.v
2026-02-25 20:54:12 +01:00

183 lines
4.6 KiB
Verilog

`timescale 1ns/1ps
`include "../util/clog2.vh"
module mcu #(
parameter memfile = "",
parameter memsize = 8192,
parameter sim = 1'b0
)(
input wire i_clk,
input wire i_rst,
input wire [31:0] i_GPI_A,
input wire [31:0] i_GPI_B,
input wire [31:0] i_GPI_C,
input wire [31:0] i_GPI_D,
output wire [31:0] o_GPO_A,
output wire [31:0] o_GPO_B,
output wire [31:0] o_GPO_C,
output wire [31:0] o_GPO_D,
output wire o_test
);
localparam WITH_CSR = 1;
localparam regs = 32+WITH_CSR*4;
localparam rf_width = 8;
wire rst;
wire rst_mem_reason;
wire timer_irq;
assign rst = i_rst | rst_mem_reason;
assign o_test = timer_irq;
// Busses
// CPU->memory
wire [31:0] wb_mem_adr;
wire [31:0] wb_mem_dat;
wire [3:0] wb_mem_sel;
wire wb_mem_we;
wire wb_mem_stb;
wire [31:0] wb_mem_rdt;
wire wb_mem_ack;
// CPU->peripherals
wire [31:0] wb_ext_adr;
wire [31:0] wb_ext_dat;
wire [3:0] wb_ext_sel;
wire wb_ext_we;
wire wb_ext_stb;
wire [31:0] wb_ext_rdt;
wire wb_ext_ack;
// CPU->RF
wire [6+WITH_CSR:0] rf_waddr;
wire [rf_width-1:0] rf_wdata;
wire rf_wen;
wire [6+WITH_CSR:0] rf_raddr;
wire [rf_width-1:0] rf_rdata;
wire rf_ren;
// combined RF and mem bus to actual RAM
wire [`CLOG2(memsize)-1:0] sram_waddr;
wire [rf_width-1:0] sram_wdata;
wire sram_wen;
wire [`CLOG2(memsize)-1:0] sram_raddr;
wire [rf_width-1:0] sram_rdata;
wire sram_ren;
// GPIO
wire [4*32-1:0] GPO;
wire [4*32-1:0] GPI;
assign o_GPO_A = GPO[32*1-1:32*0];
assign o_GPO_B = GPO[32*2-1:32*1];
assign o_GPO_C = GPO[32*3-1:32*2];
assign o_GPO_D = GPO[32*4-1:32*3];
assign GPI[32*1-1:32*0] = i_GPI_A;
assign GPI[32*2-1:32*1] = i_GPI_B;
assign GPI[32*3-1:32*2] = i_GPI_C;
assign GPI[32*4-1:32*3] = i_GPI_D;
// SERV core with mux splitting dbus into mem and ext and
// arbiter combining mem and ibus
// separate rst line to let other hardware keep core under reset
servile #(
.reset_pc(32'h0000_0000),
.reset_strategy("MINI"),
.rf_width(rf_width),
.sim(sim),
.with_csr(WITH_CSR),
.with_c(0),
.with_mdu(0)
) servile (
.i_clk(i_clk),
.i_rst(rst),
.i_timer_irq(1'b0), //timer_irq),
//Memory interface
.o_wb_mem_adr(wb_mem_adr),
.o_wb_mem_dat(wb_mem_dat),
.o_wb_mem_sel(wb_mem_sel),
.o_wb_mem_we(wb_mem_we),
.o_wb_mem_stb(wb_mem_stb),
.i_wb_mem_rdt(wb_mem_rdt),
.i_wb_mem_ack(wb_mem_ack),
//Extension interface
.o_wb_ext_adr(wb_ext_adr),
.o_wb_ext_dat(wb_ext_dat),
.o_wb_ext_sel(wb_ext_sel),
.o_wb_ext_we(wb_ext_we),
.o_wb_ext_stb(wb_ext_stb),
.i_wb_ext_rdt(wb_ext_rdt),
.i_wb_ext_ack(wb_ext_ack),
//RF IF
.o_rf_waddr(rf_waddr),
.o_rf_wdata(rf_wdata),
.o_rf_wen(rf_wen),
.o_rf_raddr(rf_raddr),
.o_rf_ren(rf_ren),
.i_rf_rdata(rf_rdata)
);
// WB arbiter combining RF and mem interfaces into 1
// Last 128 bytes are used for registers
servile_rf_mem_if #(
.depth(memsize),
.rf_regs(regs)
) rf_mem_if (
.i_clk (i_clk),
.i_rst (rst),
.i_waddr(rf_waddr),
.i_wdata(rf_wdata),
.i_wen(rf_wen),
.i_raddr(rf_raddr),
.o_rdata(rf_rdata),
.i_ren(rf_ren),
.o_sram_waddr(sram_waddr),
.o_sram_wdata(sram_wdata),
.o_sram_wen(sram_wen),
.o_sram_raddr(sram_raddr),
.i_sram_rdata(sram_rdata),
// .o_sram_ren(sram_ren),
.i_wb_adr(wb_mem_adr[`CLOG2(memsize)-1:2]),
.i_wb_stb(wb_mem_stb),
.i_wb_we(wb_mem_we) ,
.i_wb_sel(wb_mem_sel),
.i_wb_dat(wb_mem_dat),
.o_wb_rdt(wb_mem_rdt),
.o_wb_ack(wb_mem_ack)
);
memory #(
.memfile(memfile),
.depth(memsize),
.sim(sim)
) mem (
.i_clk(i_clk),
.i_rst(i_rst),
.i_waddr(sram_waddr),
.i_wdata(sram_wdata),
.i_wen(sram_wen),
.i_raddr(sram_raddr),
.o_rdata(sram_rdata),
.o_core_reset(rst_mem_reason)
);
mcu_peripherals peripherals (
.i_clk(i_clk),
.i_rst(rst),
.i_wb_adr(wb_ext_adr),
.i_wb_dat(wb_ext_dat),
.i_wb_sel(wb_ext_sel),
.i_wb_we(wb_ext_we),
.i_wb_stb(wb_ext_stb),
.o_wb_rdt(wb_ext_rdt),
.o_wb_ack(wb_ext_ack),
// Peripheral IO
.i_gpio(GPI),
.o_gpio(GPO),
.o_timer_irq(timer_irq)
);
endmodule