blob: ef989dd193cd9ad18543f80014a555fb52a5e12b [file] [log] [blame]
//////////////////////////////////////////////////////////////////////////////
// SPDX-FileCopyrightText: 2021 , Dinesh Annayya
//
// 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
// SPDX-FileContributor: Created by Dinesh Annayya <dinesha@opencores.org>
//
//////////////////////////////////////////////////////////////////////
//
// MBIST wishbone Burst access to SRAM Write and Read access
// Note: BUSRT crossing the SRAM boundary is not supported due to sram
// 2 cycle pipe line delay
//////////////////////////////////////////////////////////////////////
module mbist_wb
#(
parameter BIST_NO_SRAM = 4,
parameter BIST_ADDR_WD = 9,
parameter BIST_DATA_WD = 32) (
`ifdef USE_POWER_PINS
inout vccd1, // User area 1 1.8V supply
inout vssd1, // User area 1 digital ground
`endif
input logic rst_n,
// WB I/F
input logic wb_clk_i, // System clock
input logic wb_stb_i, // strobe/request
input logic [BIST_ADDR_WD-1:0] wb_adr_i, // address
input logic [(BIST_NO_SRAM+1)/2-1:0] wb_cs_i, // address
input logic wb_we_i , // write
input logic [BIST_DATA_WD-1:0] wb_dat_i, // data output
input logic [BIST_DATA_WD/8-1:0] wb_sel_i, // byte enable
input logic [9:0] wb_bl_i, // Burst Length
input logic wb_bry_i, // Burst Ready
output logic [BIST_DATA_WD-1:0] wb_dat_o, // data input
output logic wb_ack_o, // acknowlegement
output logic wb_lack_o, // acknowlegement
output logic wb_err_o, // error
output logic mem_req,
output logic [(BIST_NO_SRAM+1)/2-1:0] mem_cs,
output logic [BIST_ADDR_WD-1:0] mem_addr,
output logic [31:0] mem_wdata,
output logic mem_we,
output logic [3:0] mem_wmask,
input logic [31:0] mem_rdata
);
parameter IDLE = 2'b00;
parameter WRITE_ACTION = 2'b01;
parameter READ_ACTION1 = 2'b10;
parameter READ_ACTION2 = 2'b11;
logic [9:0] mem_bl_cnt ;
logic wb_ack_l ;
logic [BIST_ADDR_WD-1:0] mem_next_addr;
logic [1:0] state;
logic mem_hval; // Mem Hold Data valid
logic [31:0] mem_hdata; // Mem Hold Data
assign mem_wdata = wb_dat_i;
always @(negedge rst_n, posedge wb_clk_i) begin
if (~rst_n) begin
mem_bl_cnt <= 'h0;
mem_addr <= 'h0;
mem_next_addr <= 'h0;
wb_ack_l <= 'b0;
wb_dat_o <= 'h0;
mem_req <= 'b0;
mem_cs <= 'b0;
mem_wmask <= 'h0;
mem_we <= 'h0;
mem_hval <= 'b0;
mem_hdata <= 'h0;
state <= IDLE;
end else begin
case(state)
IDLE: begin
mem_bl_cnt <= 'h1;
wb_ack_o <= 'b0;
wb_lack_o <= 'b0;
if(wb_stb_i && wb_bry_i && ~wb_we_i && !wb_lack_o) begin
mem_cs <= wb_cs_i;
mem_addr <= wb_adr_i;
mem_req <= 'b1;
mem_we <= 'b0;
state <= READ_ACTION1;
end else if(wb_stb_i && wb_bry_i && wb_we_i && !wb_lack_o) begin
mem_cs <= wb_cs_i;
mem_next_addr<= wb_adr_i;
mem_we <= 'b1;
mem_wmask <= wb_sel_i;
state <= WRITE_ACTION;
end else begin
mem_req <= 1'b0;
end
end
WRITE_ACTION: begin
if (wb_stb_i && wb_bry_i ) begin
wb_ack_o <= 'b1;
mem_req <= 1'b1;
mem_addr <= mem_next_addr;
if((wb_stb_i && wb_bry_i ) && (wb_bl_i == mem_bl_cnt)) begin
wb_lack_o <= 'b1;
state <= IDLE;
end else begin
mem_bl_cnt <= mem_bl_cnt+1;
mem_next_addr<= mem_next_addr+1;
end
end else begin
wb_ack_o <= 'b0;
mem_req <= 1'b0;
end
end
READ_ACTION1: begin
mem_addr <= mem_addr +1;
mem_hval <= 1'b0;
wb_ack_l <= 'b1;
mem_bl_cnt <= 'h1;
state <= READ_ACTION2;
end
// Wait for Ack from application layer
READ_ACTION2: begin
// If the not the last ack, update memory pointer
// accordingly
wb_ack_l <= wb_ack_o;
if (wb_stb_i && wb_bry_i ) begin
wb_ack_o <= 1'b1;
mem_bl_cnt <= mem_bl_cnt+1;
mem_addr <= mem_addr +1;
if(wb_ack_l || wb_ack_o ) begin // If back to back ack
wb_dat_o <= mem_rdata;
mem_hval <= 1'b0;
end else begin // Pick from previous holding data
mem_hval <= 1'b1;
wb_dat_o <= mem_hdata;
mem_hdata <= mem_rdata;
end
if((wb_stb_i && wb_bry_i ) && (wb_bl_i == mem_bl_cnt)) begin
wb_lack_o <= 1'b1;
state <= IDLE;
end
end else begin
wb_ack_o <= 1'b0;
if(!mem_hval) begin
mem_hdata <= mem_rdata;
mem_hval <= 1'b1;
end
end
end
endcase
end
end
endmodule