blob: 2f9e0e30756296e4c3e9b544b6bbed5576255c36 [file] [log] [blame]
// SPDX-FileCopyrightText: 2020 Efabless Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// 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.
// SPDX-License-Identifier: Apache-2.0
`default_nettype none
module soomrv #(
parameter BITS = 32
)(
`ifdef USE_POWER_PINS
inout vccd1, // User area 1 1.8V supply
inout vssd1, // User area 1 digital ground
`endif
// Wishbone Slave ports (WB MI A)
input wb_clk_i,
input wb_rst_i,
input wbs_stb_i,
input wbs_cyc_i,
input wbs_we_i,
input [3:0] wbs_sel_i,
input [31:0] wbs_dat_i,
input [31:0] wbs_adr_i,
output reg wbs_ack_o,
output reg [31:0] wbs_dat_o,
// Logic Analyzer Signals
//input [127:0] la_data_in,
output [127:0] la_data_out,
//input [127:0] la_oenb,
// IOs
input wire [`MPRJ_IO_PADS-1:0] io_in,
output wire [`MPRJ_IO_PADS-1:0] io_out,
output wire [`MPRJ_IO_PADS-1:0] io_oeb,
inout [`MPRJ_IO_PADS-10:0] analog_io,
input wire user_clock2,
output wire mem_ce,
output wire mem_we,
output wire[12:0] mem_waddr,
output wire[31:0] mem_wdata,
input wire[31:0] mem_rdata0,
output wire[3:0] mem_wm,
output wire mem_re,
output wire[12:0] mem_raddr,
input wire[31:0] mem_rdata,
output wire[10:0] instr_addr,
input wire[63:0] instr_dataIn,
output wire[63:0] instr_dataOut,
output wire instr_ce,
output wire instr_we,
output wire[7:0] instr_wm,
output wire zero,
// IRQ
output wire [2:0] irq
);
wire[31:0] CORE_robPCsample = 0;
assign la_data_out[31:0] = CORE_robPCsample;
assign la_data_out[63:32] = {CORE_pramAddr, 3'b0};
assign la_data_out[127:64] = 64'b0;
assign zero = 1'b0;
// IRQ
assign irq = 3'b000; // Unused
wire[15:0] CORE_GPIO_oe;
wire[15:0] CORE_GPIO_in = io_in[15:0];
wire[15:0] CORE_GPIO_out;
wire CORE_spi_clk;
wire CORE_spi_mosi;
wire CORE_spi_miso = io_in[26];
assign io_oeb = {12'b100, CORE_GPIO_oe, 8'hff};
assign io_out = {10'b0, CORE_spi_mosi, CORE_spi_clk, CORE_GPIO_out, 8'h00};
// Control Register entries
reg coreEn;
reg coreRst;
reg usingDataRAM;
reg coreInstrMappingHalfSize;
wire coreHlt;
wire coreInstrMappingMiss;
reg[31:0] coreInstrMapping;
// Multiplexing for Data SRAM
wire[29:0] CORE_writeAddr;
wire[31:0] CORE_writeData;
wire[3:0] CORE_writeMask;
wire CORE_writeEnable;
wire CORE_readEnable;
wire[29:0] CORE_readAddr;
reg[29:0] MGMT_sramAddr;
reg[31:0] MGMT_sramData;
reg[3:0] MGMT_sramWM;
reg MGMT_sramWE;
reg MGMT_sramCE;
assign mem_waddr = !usingDataRAM ? CORE_sramAddr[12:0] : MGMT_sramAddr[12:0];
assign mem_wdata = !usingDataRAM ? CORE_sramData : MGMT_sramData;
assign mem_wm = !usingDataRAM ? CORE_sramWM : MGMT_sramWM;
assign mem_we = !usingDataRAM ? 1'b0 : MGMT_sramWE;
assign mem_ce = !usingDataRAM ? CORE_writeEnable : MGMT_sramCE;
assign mem_re = CORE_readEnable;
assign mem_raddr = CORE_readAddr;
// Multiplexing for Program SRAM
wire[28:0] CORE_pramAddr;
wire CORE_pramCE;
reg[28:0] MGMT_pramAddr;
reg[63:0] MGMT_pramData;
reg[7:0] MGMT_pramWM;
reg MGMT_pramWE;
reg MGMT_pramCE;
assign instr_addr = coreEn ? CORE_pramAddr[10:0] : MGMT_pramAddr[10:0];
assign instr_dataOut = MGMT_pramData;
assign instr_wm = MGMT_pramWM;
assign instr_ce = coreEn ? CORE_pramCE : MGMT_pramCE;
assign instr_we = coreEn ? 1'b1 : MGMT_pramWE;
// Wishbone State
reg sramRead;
reg pramRead;
reg pramReadUpper;
reg readCnt;
// SRAM macros output on falling,
// sample on rising for clean signal
reg[63:0] instr_dataInSample;
reg[31:0] mem_dataInSample;
reg[31:0] mem_dataInSample1;
reg instr_ceSample;
reg mem_ceSample;
reg instr_weSample;
reg mem_weSample;
reg mem_reSample;
always@(posedge wb_clk_i) begin
if (!instr_ceSample)
instr_dataInSample <= instr_dataIn;
if (!instr_ceSample && instr_weSample)
instr_dataInSample <= instr_dataIn;
if (!mem_ceSample && mem_weSample)
mem_dataInSample <= mem_rdata0;
if (!mem_reSample)
mem_dataInSample1 <= mem_rdata;
instr_ceSample <= instr_ce;
mem_ceSample <= mem_ce;
instr_weSample <= instr_we;
mem_weSample <= mem_we;
mem_reSample <= mem_re;
end
always@(posedge wb_clk_i) begin
// defaults
wbs_ack_o <= 0;
MGMT_sramCE <= 1;
MGMT_pramCE <= 1;
wbs_dat_o <= 0;
if (coreHlt) begin
coreEn <= 0;
end
if (wb_rst_i) begin
coreEn <= 0;
coreRst <= 1;
sramRead <= 0;
pramRead <= 0;
coreInstrMappingHalfSize <= 0;
coreInstrMapping <= 0;
end
else if (sramRead) begin
if (readCnt)
readCnt <= 0;
else begin
wbs_dat_o <= mem_dataIn;
wbs_ack_o <= 1;
sramRead <= 0;
end
end
else if (pramRead) begin
if (readCnt)
readCnt <= 0;
else begin
wbs_dat_o <= pramReadUpper ? instr_dataIn[63:32] : instr_dataIn[31:0];
wbs_ack_o <= 1;
pramRead <= 0;
end
end
// User Area Base is 0x 30 00 00 0
else if (wbs_cyc_i && wbs_stb_i && !wbs_ack_o) begin
// Wisbone always needs ack as there's no error line
wbs_ack_o <= 1;
// Control Register
if (wbs_adr_i[19:16] == 4'h0) begin
if (wbs_adr_i[1:0] == 2'b00) begin
if (wbs_we_i && wbs_sel_i[0]) begin
coreEn <= wbs_dat_i[0];
coreRst <= wbs_dat_i[1];
usingDataRAM <= wbs_dat_i[2];
coreInstrMappingHalfSize <= wbs_dat_i[3];
end
else if (wbs_sel_i[0]) begin
wbs_dat_o[0] <= coreEn;
wbs_dat_o[1] <= coreRst;
wbs_dat_o[2] <= usingDataRAM;
wbs_dat_o[3] <= coreInstrMappingHalfSize;
wbs_dat_o[4] <= coreInstrMappingMiss;
wbs_dat_o[5] <= coreHlt;
wbs_dat_o[31:4] <= 0;
end
end
else if (wbs_adr_i[1:0] == 2'b01) begin
if (!wbs_we_i)
wbs_dat_o <= {CORE_pramAddr, 3'b0};
end
else begin
if (wbs_we_i) begin
if (wbs_sel_i[0]) coreInstrMapping[7:0] <= wbs_dat_i[7:0];
if (wbs_sel_i[1]) coreInstrMapping[15:8] <= wbs_dat_i[15:8];
if (wbs_sel_i[2]) coreInstrMapping[23:16] <= wbs_dat_i[23:16];
if (wbs_sel_i[3]) coreInstrMapping[31:24] <= wbs_dat_i[31:24];
end
else begin
wbs_dat_o <= coreInstrMapping;
end
end
end
// Data SRAM access
else if (usingDataRAM && wbs_adr_i[19:16] == 4'h1) begin
if (wbs_we_i) begin
MGMT_sramAddr <= {8'b0, wbs_adr_i[23:2]};
MGMT_sramCE <= 0;
MGMT_sramWE <= 0;
MGMT_sramWM <= wbs_sel_i;
MGMT_sramData <= wbs_dat_i;
end
else begin
MGMT_sramAddr <= {8'b0, wbs_adr_i[23:2]};
MGMT_sramCE <= 0;
MGMT_sramWE <= 1;
sramRead <= 1;
readCnt <= 1;
// We need a few cycles for lookup, don't ack yet
wbs_ack_o <= 0;
end
end
// Program SRAM access
else if (!coreEn && wbs_adr_i[19:16] == 4'h2) begin
if (wbs_we_i) begin
MGMT_pramAddr <= {9'b0, wbs_adr_i[23:3]};
MGMT_pramCE <= 0;
MGMT_pramWE <= 0;
if (wbs_adr_i[2])
MGMT_pramWM <= {wbs_sel_i, 4'b0};
else
MGMT_pramWM <= {4'b0, wbs_sel_i};
MGMT_pramData[31:0] <= wbs_dat_i;
MGMT_pramData[63:32] <= wbs_dat_i;
end
else begin
MGMT_pramAddr <= {9'b0, wbs_adr_i[23:3]};
MGMT_pramCE <= 0;
MGMT_pramWE <= 1;
pramRead <= 1;
pramReadUpper <= wbs_adr_i[3];
readCnt <= 1;
// We need a few cycles for lookup, don't ack yet
wbs_ack_o <= 0;
end
end
end
end
Core core
(
.clk(wb_clk_i),
.en(coreEn),
.rst(coreRst),
.IN_instrRaw(instr_dataInSample),
.OUT_MEM_writeAddr(CORE_writeAddr),
.OUT_MEM_writeData(CORE_writeData),
.OUT_MEM_writeEnable(CORE_writeEnable),
.OUT_MEM_writeMask(CORE_writeMask),
.OUT_MEM_readEnable(CORE_readEnable),
.OUT_MEM_readAddr(CORE_readAddr),
.IN_MEM_readData(mem_dataInSample1),
.OUT_instrAddr(CORE_pramAddr),
.OUT_instrReadEnable(CORE_pramCE),
.OUT_halt(coreHlt),
.OUT_GPIO_oe(CORE_GPIO_oe),
.OUT_GPIO(CORE_GPIO_out),
.IN_GPIO(CORE_GPIO_in),
.OUT_SPI_clk(CORE_spi_clk),
.OUT_SPI_mosi(CORE_spi_mosi),
.IN_SPI_miso(CORE_spi_miso),
.OUT_instrMappingMiss(coreInstrMappingMiss),
.IN_instrMappingBase(coreInstrMapping),
.IN_instrMappingHalfSize(coreInstrMappingHalfSize)
);
endmodule
`default_nettype wire