URL
https://opencores.org/ocsvn/yifive/yifive/trunk
Subversion Repositories yifive
[/] [yifive/] [trunk/] [caravel_yifive/] [verilog/] [rtl/] [syntacore/] [scr1/] [src/] [top/] [scr1_mem_axi.sv] - Rev 21
Compare with Previous | Blame | View Log
/// Copyright by Syntacore LLC © 2016-2020. See LICENSE for details/// @file <scr1_mem_axi.sv>/// @brief Memory AXI bridge///`include "scr1_memif.svh"`include "scr1_arch_description.svh"module scr1_mem_axi#(parameter SCR1_REQ_BUF_SIZE = 2, // Power of 2 valueparameter SCR1_AXI_IDWIDTH = 4,parameter SCR1_ADDR_WIDTH = 32,parameter SCR1_AXI_REQ_BP = 1,parameter SCR1_AXI_RESP_BP = 1)(// Clock and Resetinput logic clk,input logic rst_n,input logic axi_reinit,// Core Interfaceoutput logic core_idle,output logic core_req_ack,input logic core_req,input logic core_cmd,input logic [1:0] core_width,input logic [SCR1_ADDR_WIDTH-1:0] core_addr,input logic [31:0] core_wdata,output logic [31:0] core_rdata,output logic [1:0] core_resp,// AXIoutput logic [SCR1_AXI_IDWIDTH-1:0] awid,output logic [SCR1_ADDR_WIDTH-1:0] awaddr,output logic [ 7:0] awlen,output logic [ 2:0] awsize,output logic [ 1:0] awburst,output logic awlock,output logic [ 3:0] awcache,output logic [ 2:0] awprot,output logic [ 3:0] awregion,output logic [ 3:0] awuser,output logic [ 3:0] awqos,output logic awvalid,input logic awready,output logic [31:0] wdata,output logic [3:0] wstrb,output logic wlast,output logic [3:0] wuser,output logic wvalid,input logic wready,input logic [SCR1_AXI_IDWIDTH-1:0] bid,input logic [ 1:0] bresp,input logic bvalid,input logic [ 3:0] buser,output logic bready,output logic [SCR1_AXI_IDWIDTH-1:0] arid,output logic [SCR1_ADDR_WIDTH-1:0] araddr,output logic [ 7:0] arlen,output logic [ 2:0] arsize,output logic [ 1:0] arburst,output logic arlock,output logic [ 3:0] arcache,output logic [ 2:0] arprot,output logic [ 3:0] arregion,output logic [ 3:0] aruser,output logic [ 3:0] arqos,output logic arvalid,input logic arready,input logic [SCR1_AXI_IDWIDTH-1:0] rid,input logic [31:0] rdata,input logic [ 1:0] rresp,input logic rlast,input logic [ 3:0] ruser,input logic rvalid,output logic rready);// Local functionsfunction automatic logic [2:0] width2axsize (input logic [1:0] width );logic [2:0] axsize;begincase (width)SCR1_MEM_WIDTH_BYTE : axsize = 3'b000;SCR1_MEM_WIDTH_HWORD: axsize = 3'b001;SCR1_MEM_WIDTH_WORD : axsize = 3'b010;default: axsize = 'x;endcasewidth2axsize = axsize; // cp.11endendfunctiontypedef struct packed {logic [1:0] axi_width;logic [SCR1_ADDR_WIDTH-1:0] axi_addr;logic [31:0] axi_wdata;} type_scr1_request_s;typedef struct packed {logic req_write;logic req_addr;logic req_data;logic req_resp;} type_scr1_req_status_s;//type_scr1_request_s [SCR1_REQ_BUF_SIZE-1:0] req_fifo;logic [1:0] req_fifo_axi_width[SCR1_REQ_BUF_SIZE-1:0];logic [SCR1_ADDR_WIDTH-1:0] req_fifo_axi_addr [SCR1_REQ_BUF_SIZE-1:0];logic [31:0] req_fifo_axi_wdata [SCR1_REQ_BUF_SIZE-1:0];//type_scr1_req_status_s [SCR1_REQ_BUF_SIZE-1:0] req_status;logic [SCR1_REQ_BUF_SIZE-1:0] req_status_req_write ;logic [SCR1_REQ_BUF_SIZE-1:0] req_status_req_addr ;logic [SCR1_REQ_BUF_SIZE-1:0] req_status_req_data ;logic [SCR1_REQ_BUF_SIZE-1:0] req_status_req_resp ;//type_scr1_req_status_s [SCR1_REQ_BUF_SIZE-1:0] req_status_new;logic [SCR1_REQ_BUF_SIZE-1:0] req_status_new_req_write ;logic [SCR1_REQ_BUF_SIZE-1:0] req_status_new_req_addr ;logic [SCR1_REQ_BUF_SIZE-1:0] req_status_new_req_data ;logic [SCR1_REQ_BUF_SIZE-1:0] req_status_new_req_resp ;logic [SCR1_REQ_BUF_SIZE-1:0] req_status_en;logic [$clog2(SCR1_REQ_BUF_SIZE)-1:0] req_aval_ptr;logic [$clog2(SCR1_REQ_BUF_SIZE)-1:0] req_proc_ptr;logic [$clog2(SCR1_REQ_BUF_SIZE)-1:0] req_done_ptr;logic rresp_err;logic [31:0] rcvd_rdata;logic [1:0] rcvd_resp;logic force_read;logic force_write;assign core_req_ack = ~axi_reinit &~req_status_req_resp[req_aval_ptr] &core_resp!=SCR1_MEM_RESP_RDY_ER;assign rready = ~req_status_req_write[req_done_ptr];assign bready = req_status_req_write[req_done_ptr];assign force_read = SCR1_AXI_REQ_BP & core_req & core_req_ack & req_aval_ptr==req_proc_ptr & core_cmd==SCR1_MEM_CMD_RD;assign force_write = SCR1_AXI_REQ_BP & core_req & core_req_ack & req_aval_ptr==req_proc_ptr & core_cmd==SCR1_MEM_CMD_WR;integer i;always_comb begin: idle_statuscore_idle = 1'b1;for (i=0; i<SCR1_REQ_BUF_SIZE; i=i+1) begincore_idle &= req_status_req_resp[i]==1'b0;endendalways_ff @(posedge clk) beginif (core_req & core_req_ack) beginreq_fifo_axi_width[req_aval_ptr] <= core_width;req_fifo_axi_addr[req_aval_ptr] <= core_addr;req_fifo_axi_wdata[req_aval_ptr] <= core_wdata;endend// Request Status Queue// It is used for holding control info of processing requests// Combinational logic of Request Status Queuealways_comb begin// Defaultreq_status_en = '0; // No updatereq_status_new_req_write = req_status_req_write; // Hold request inforeq_status_new_req_addr = req_status_req_addr; // Hold request inforeq_status_new_req_data = req_status_req_data; // Hold request inforeq_status_new_req_resp = req_status_req_resp; // Hold request info// Update status on new core requestif( core_req & core_req_ack ) beginreq_status_en[req_aval_ptr] = 1'd1;req_status_new_req_resp[req_aval_ptr] = 1'd1;req_status_new_req_write[req_aval_ptr] = core_cmd == SCR1_MEM_CMD_WR;req_status_new_req_addr[req_aval_ptr] = ~( (force_read & arready) |(force_write & awready) );req_status_new_req_data[req_aval_ptr] = ~( (force_write & wready & awlen == 8'd0) |(~force_write & core_cmd == SCR1_MEM_CMD_RD) );end// Update status on AXI address phaseif ( (awvalid & awready) | (arvalid & arready) ) beginreq_status_en[req_proc_ptr] = 1'd1;req_status_new_req_addr[req_proc_ptr] = 1'd0;end// Update status on AXI data phaseif ( wvalid & wready & wlast ) beginreq_status_en[req_proc_ptr] = 1'd1;req_status_new_req_data[req_proc_ptr] = 1'd0;end// Update status when AXI finish transactionif ( (bvalid & bready) | (rvalid & rready & rlast) ) beginreq_status_en[req_done_ptr] = 1'd1;req_status_new_req_resp[req_done_ptr] = 1'd0;endend// Request Status Queue registerinteger j;always_ff @(negedge rst_n, posedge clk) beginif (~rst_n) beginreq_status_req_write <= '0;req_status_req_addr <= '0;req_status_req_data <= '0;req_status_req_resp <= '0;end else beginfor (j = 0; j < SCR1_REQ_BUF_SIZE; j = j+1) begin // cp.4if ( req_status_en[j] ) beginreq_status_req_write[j] <= req_status_new_req_write[j];req_status_req_addr[j] <= req_status_new_req_addr[j];req_status_req_data[j] <= req_status_new_req_data[j];req_status_req_resp[j] <= req_status_new_req_resp[j];endendendendalways_ff @(negedge rst_n, posedge clk) beginif (~rst_n) req_aval_ptr <= '0;else if (core_req & core_req_ack) req_aval_ptr <= req_aval_ptr + 1'b1;endalways_ff @(negedge rst_n, posedge clk) beginif (~rst_n) beginreq_proc_ptr <= '0;end else beginif (( awvalid & awready & wvalid & wready & wlast) |(~force_write & ~req_status_req_data[req_proc_ptr] & awvalid & awready ) |(~force_write & ~req_status_req_addr[req_proc_ptr] & wvalid & wready & wlast) |( ~req_status_req_data[req_proc_ptr] & arvalid & arready ) ) beginreq_proc_ptr <= req_proc_ptr + 1'b1;endendendalways_ff @(negedge rst_n, posedge clk) beginif (~rst_n) beginreq_done_ptr <= '0;end else beginif ((bvalid & bready | rvalid & rready & rlast) & req_status_req_resp[req_done_ptr]) beginreq_done_ptr <= req_done_ptr + 1'b1;endendendassign arvalid = req_status_req_addr[req_proc_ptr] & ~req_status_req_write[req_proc_ptr] | force_read;assign awvalid = req_status_req_addr[req_proc_ptr] & req_status_req_write[req_proc_ptr] | force_write;assign wvalid = req_status_req_data[req_proc_ptr] & req_status_req_write[req_proc_ptr] | force_write;assign araddr = (~force_read )? req_fifo_axi_addr[req_proc_ptr] : core_addr;assign awaddr = (~force_write)? req_fifo_axi_addr[req_proc_ptr] : core_addr;always_comb beginif (bvalid & bready & req_status_req_resp[req_done_ptr]) beginrcvd_resp = (bresp==2'b00)? SCR1_MEM_RESP_RDY_OK :SCR1_MEM_RESP_RDY_ER;end else beginif (rvalid & rready & rlast & req_status_req_resp[req_done_ptr]) beginrcvd_resp = (rresp==2'b00)? SCR1_MEM_RESP_RDY_OK :SCR1_MEM_RESP_RDY_ER;end else beginrcvd_resp = SCR1_MEM_RESP_NOTRDY;endendendwire [SCR1_ADDR_WIDTH-1:0] CurAddr1 = req_fifo_axi_addr[req_proc_ptr];wire [1:0] bShift1 = CurAddr1[1:0];// Write data signals adaptationalways_comb beginif (force_write)case (core_width)SCR1_MEM_WIDTH_BYTE : wstrb = 4'h1 << core_addr[1:0];SCR1_MEM_WIDTH_HWORD: wstrb = 4'h3 << core_addr[1:0];SCR1_MEM_WIDTH_WORD : wstrb = 4'hf << core_addr[1:0];default: wstrb = 'x;endcaseelsecase (req_fifo_axi_width[req_proc_ptr])SCR1_MEM_WIDTH_BYTE : wstrb = 4'h1 << bShift1;SCR1_MEM_WIDTH_HWORD: wstrb = 4'h3 << bShift1;SCR1_MEM_WIDTH_WORD : wstrb = 4'hf << bShift1;default: wstrb = 'x;endcaseendassign wdata = (force_write)? core_wdata << (8* core_addr[1:0]) :req_fifo_axi_wdata[req_proc_ptr] << (8* bShift1);wire [SCR1_ADDR_WIDTH-1:0] CurAddr2 = req_fifo_axi_addr[req_done_ptr];wire [1:0] bShift2 = CurAddr2[1:0];// Read data adaptationalways_comb begincase (req_fifo_axi_width[req_done_ptr])SCR1_MEM_WIDTH_BYTE : rcvd_rdata = rdata >> (8*bShift2);SCR1_MEM_WIDTH_HWORD: rcvd_rdata = rdata >> (8*bShift2);SCR1_MEM_WIDTH_WORD : rcvd_rdata = rdata >> (8*bShift2);default: rcvd_rdata = 'x;endcaseendgenerateif (SCR1_AXI_RESP_BP == 1) begin : axi_resp_bpassign core_rdata = (rvalid & rready & rlast) ? rcvd_rdata : '0;assign core_resp = (axi_reinit) ? SCR1_MEM_RESP_NOTRDY : rcvd_resp;end else begin : axi_resp_no_bpalways_ff @(negedge rst_n, posedge clk) beginif (~rst_n) core_resp <= SCR1_MEM_RESP_NOTRDY;else core_resp <= (axi_reinit) ? SCR1_MEM_RESP_NOTRDY : rcvd_resp;endalways_ff @(posedge clk) beginif (rvalid & rready & rlast) core_rdata <= rcvd_rdata;endendendgenerate// AXI interface assignmentsassign awid = SCR1_AXI_IDWIDTH'(1);assign awlen = 8'd0;assign awsize = (force_write) ? width2axsize(core_width) : width2axsize(req_fifo_axi_width[req_proc_ptr]);assign awburst = 2'd1;assign awcache = 4'd2;assign awlock = '0;assign awprot = '0;assign awregion = '0;assign awuser = '0;assign awqos = '0;assign arid = SCR1_AXI_IDWIDTH'(0);assign arlen = 8'd0;assign arsize = (force_read) ? width2axsize(core_width) : width2axsize(req_fifo_axi_width[req_proc_ptr]);assign arburst = 2'd1;assign arcache = 4'd2;assign arprot = '0;assign arregion = '0;assign arlock = '0;assign arqos = '0;assign aruser = '0;assign wlast = 1'd1;assign wuser = '0;`ifdef SCR1_TRGT_SIMULATION//-------------------------------------------------------------------------------// Assertion//-------------------------------------------------------------------------------// X checksSCR1_SVA_AXI_X_CHECK0 : assert property (@(negedge clk) disable iff (~rst_n) !$isunknown({core_req, awready, wready, bvalid, arready, rvalid}) )else $error("AXI bridge: X state on input");SCR1_SVA_AXI_X_CHECK1 : assert property (@(negedge clk) disable iff (~rst_n) core_req |->!$isunknown({core_cmd, core_width, core_addr}) )else $error("AXI bridge: X state on input");SCR1_SVA_AXI_X_CHECK2 : assert property (@(negedge clk) disable iff (~rst_n) bvalid |->!$isunknown({bid, bresp}) )else $error("AXI bridge: X state on input");SCR1_SVA_AXI_X_CHECK3 : assert property (@(negedge clk) disable iff (~rst_n) rvalid |->!$isunknown({rid, rresp}) )else $error("AXI bridge: X state on input");`endif // SCR1_TRGT_SIMULATIONendmodule : scr1_mem_axi
