URL
https://opencores.org/ocsvn/yifive/yifive/trunk
Subversion Repositories yifive
[/] [yifive/] [trunk/] [caravel_yifive/] [verilog/] [rtl/] [syntacore/] [scr1/] [src/] [top/] [scr1_tcm.sv] - Rev 21
Compare with Previous | Blame | View Log
/// 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 logic [1:0] imem_resp,
// Core data interface
output logic dmem_req_ack,
input logic dmem_req,
input logic dmem_cmd,
input logic [1:0] 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 logic [1:0] 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