132 lines
4.8 KiB
Systemverilog
132 lines
4.8 KiB
Systemverilog
/// Copyright by Syntacore LLC © 2016-2020. See LICENSE for details
|
|
/// @file <scr1_tcm.sv>
|
|
/// @brief Tightly-Coupled Memory (TCM)
|
|
///
|
|
|
|
`include "scr1_memif.svh"
|
|
`include "scr1_arch_description.svh"
|
|
|
|
`ifdef SCR1_TCM_EN
|
|
module scr1_tcm
|
|
#(
|
|
parameter SCR1_TCM_SIZE = `SCR1_IMEM_AWIDTH'h00010000
|
|
)
|
|
(
|
|
// Control signals
|
|
input logic clk,
|
|
input logic rst_n,
|
|
|
|
// Core instruction interface
|
|
output logic imem_req_ack,
|
|
input logic imem_req,
|
|
input logic [`SCR1_IMEM_AWIDTH-1:0] imem_addr,
|
|
output logic [`SCR1_IMEM_DWIDTH-1:0] imem_rdata,
|
|
output type_scr1_mem_resp_e imem_resp,
|
|
|
|
// Core data interface
|
|
output logic dmem_req_ack,
|
|
input logic dmem_req,
|
|
input type_scr1_mem_cmd_e dmem_cmd,
|
|
input type_scr1_mem_width_e dmem_width,
|
|
input logic [`SCR1_DMEM_AWIDTH-1:0] dmem_addr,
|
|
input logic [`SCR1_DMEM_DWIDTH-1:0] dmem_wdata,
|
|
output logic [`SCR1_DMEM_DWIDTH-1:0] dmem_rdata,
|
|
output type_scr1_mem_resp_e dmem_resp
|
|
);
|
|
|
|
//-------------------------------------------------------------------------------
|
|
// Local signal declaration
|
|
//-------------------------------------------------------------------------------
|
|
logic imem_req_en;
|
|
logic dmem_req_en;
|
|
logic imem_rd;
|
|
logic dmem_rd;
|
|
logic dmem_wr;
|
|
logic [`SCR1_DMEM_DWIDTH-1:0] dmem_writedata;
|
|
logic [`SCR1_DMEM_DWIDTH-1:0] dmem_rdata_local;
|
|
logic [3:0] dmem_byteen;
|
|
logic [1:0] dmem_rdata_shift_reg;
|
|
//-------------------------------------------------------------------------------
|
|
// Core interface
|
|
//-------------------------------------------------------------------------------
|
|
assign imem_req_en = (imem_resp == SCR1_MEM_RESP_RDY_OK) ^ imem_req;
|
|
assign dmem_req_en = (dmem_resp == SCR1_MEM_RESP_RDY_OK) ^ dmem_req;
|
|
|
|
always_ff @(posedge clk, negedge rst_n) begin
|
|
if (~rst_n) begin
|
|
imem_resp <= SCR1_MEM_RESP_NOTRDY;
|
|
end else if (imem_req_en) begin
|
|
imem_resp <= imem_req ? SCR1_MEM_RESP_RDY_OK : SCR1_MEM_RESP_NOTRDY;
|
|
end
|
|
end
|
|
|
|
always_ff @(posedge clk, negedge rst_n) begin
|
|
if (~rst_n) begin
|
|
dmem_resp <= SCR1_MEM_RESP_NOTRDY;
|
|
end else if (dmem_req_en) begin
|
|
dmem_resp <= dmem_req ? SCR1_MEM_RESP_RDY_OK : SCR1_MEM_RESP_NOTRDY;
|
|
end
|
|
end
|
|
|
|
assign imem_req_ack = 1'b1;
|
|
assign dmem_req_ack = 1'b1;
|
|
//-------------------------------------------------------------------------------
|
|
// Memory data composing
|
|
//-------------------------------------------------------------------------------
|
|
assign imem_rd = imem_req;
|
|
assign dmem_rd = dmem_req & (dmem_cmd == SCR1_MEM_CMD_RD);
|
|
assign dmem_wr = dmem_req & (dmem_cmd == SCR1_MEM_CMD_WR);
|
|
|
|
always_comb begin
|
|
dmem_writedata = dmem_wdata;
|
|
dmem_byteen = 4'b1111;
|
|
case ( dmem_width )
|
|
SCR1_MEM_WIDTH_BYTE : begin
|
|
dmem_writedata = {(`SCR1_DMEM_DWIDTH / 8){dmem_wdata[7:0]}};
|
|
dmem_byteen = 4'b0001 << dmem_addr[1:0];
|
|
end
|
|
SCR1_MEM_WIDTH_HWORD : begin
|
|
dmem_writedata = {(`SCR1_DMEM_DWIDTH / 16){dmem_wdata[15:0]}};
|
|
dmem_byteen = 4'b0011 << {dmem_addr[1], 1'b0};
|
|
end
|
|
default : begin
|
|
end
|
|
endcase
|
|
end
|
|
//-------------------------------------------------------------------------------
|
|
// Memory instantiation
|
|
//-------------------------------------------------------------------------------
|
|
scr1_dp_memory #(
|
|
.SCR1_WIDTH ( 32 ),
|
|
.SCR1_SIZE ( SCR1_TCM_SIZE )
|
|
) i_dp_memory (
|
|
.clk ( clk ),
|
|
// Instruction port
|
|
// Port A
|
|
.rena ( imem_rd ),
|
|
.addra ( imem_addr[$clog2(SCR1_TCM_SIZE)-1:2] ),
|
|
.qa ( imem_rdata ),
|
|
// Data port
|
|
// Port B
|
|
.renb ( dmem_rd ),
|
|
.wenb ( dmem_wr ),
|
|
.webb ( dmem_byteen ),
|
|
.addrb ( dmem_addr[$clog2(SCR1_TCM_SIZE)-1:2] ),
|
|
.qb ( dmem_rdata_local ),
|
|
.datab ( dmem_writedata )
|
|
);
|
|
//-------------------------------------------------------------------------------
|
|
// Data memory output generation
|
|
//-------------------------------------------------------------------------------
|
|
always_ff @(posedge clk) begin
|
|
if (dmem_rd) begin
|
|
dmem_rdata_shift_reg <= dmem_addr[1:0];
|
|
end
|
|
end
|
|
|
|
assign dmem_rdata = dmem_rdata_local >> ( 8 * dmem_rdata_shift_reg );
|
|
|
|
endmodule : scr1_tcm
|
|
|
|
`endif // SCR1_TCM_EN
|