hw/ip/flash_ctrl/rtl/flash_rd_ctrl.sv Cov: 100%

   1: // Copyright lowRISC contributors.
   2: // Licensed under the Apache License, Version 2.0, see LICENSE for details.
   3: // SPDX-License-Identifier: Apache-2.0
   4: //
   5: // Faux Flash Read Control
   6: //
   7: 
   8: module flash_rd_ctrl #(
   9:   parameter int AddrW = 10,
  10:   parameter int DataW = 32
  11: ) (
  12:   input clk_i,
  13:   input rst_ni,
  14: 
  15:   // Software Interface
  16:   input                    op_start_i,
  17:   input  [11:0]            op_num_words_i,
  18:   output logic             op_done_o,
  19:   output logic             op_err_o,
  20:   input [AddrW-1:0]        op_addr_i,
  21: 
  22:   // FIFO Interface
  23:   input                    data_rdy_i,
  24:   output logic [DataW-1:0] data_o,
  25:   output logic             data_wr_o,
  26: 
  27:   // Flash Macro Interface
  28:   output logic             flash_req_o,
  29:   output logic [AddrW-1:0] flash_addr_o,
  30:   output logic             flash_ovfl_o,
  31:   input [DataW-1:0]        flash_data_i,
  32:   input                    flash_done_i,
  33:   input                    flash_error_i
  34: );
  35: 
  36:   typedef enum logic {
  37:     StNorm  = 'h0,
  38:     StErr   = 'h1
  39:   } state_e;
  40: 
  41:   state_e st, st_nxt;
  42:   logic [11:0] cnt, cnt_nxt;
  43:   logic cnt_hit;
  44:   logic [AddrW:0] int_addr;
  45:   logic txn_done;
  46:   logic err_sel; //1 selects error data, 0 selects normal data
  47: 
  48:   always_ff @(posedge clk_i or negedge rst_ni) begin
  49:     if (!rst_ni) begin
  50:       cnt <= '0;
  51:       st <= StNorm;
  52:     end else begin
  53:       cnt <= cnt_nxt;
  54:       st <= st_nxt;
  55:     end
  56:   end
  57: 
  58:   assign txn_done = flash_req_o & flash_done_i;
  59:   assign cnt_hit = (cnt == op_num_words_i);
  60: 
  61:   // when error'd, continue to complete existing read transaction but fill in with all 1's
  62:   // if this is not done, software may continue to attempt to read out of the fifo
  63:   // and eventually cause a bus deadlock as the fifo would be empty
  64:   // This scheme is similar to burst completion up an error
  65:   always_comb begin
  66:     st_nxt = st;
  67:     cnt_nxt = cnt;
  68:     flash_req_o = 1'b0;
  69:     data_wr_o = 1'b0;
  70:     op_done_o = 1'b0;
  71:     op_err_o = 1'b0;
  72:     err_sel = 1'b0;
  73: 
  74:     unique case (st)
  75:       StNorm: begin
  76:         flash_req_o = op_start_i & data_rdy_i;
  77: 
  78:         if (txn_done && cnt_hit) begin
  79:           cnt_nxt = '0;
  80:           data_wr_o = 1'b1;
  81:           op_done_o = 1'b1;
  82:           op_err_o = flash_error_i;
  83:         end else if (txn_done) begin
  84:           cnt_nxt = cnt + 1'b1;
  85:           data_wr_o = 1'b1;
  86:           err_sel = flash_error_i;
  87:           st_nxt = flash_error_i ? StErr : StNorm;
  88:         end
  89:       end
  90:       StErr: begin
  91:         data_wr_o = data_rdy_i;
  92:         err_sel = 1'b1;
  93: 
  94:         if (data_rdy_i && cnt_hit) begin
  95:           st_nxt = StNorm;
  96:           cnt_nxt = '0;
  97:           op_done_o = 1'b1;
  98:           op_err_o = 1'b1;
  99:         end else if (data_rdy_i) begin
 100:           cnt_nxt = cnt + 1'b1;
 101:         end
 102:       end
 103:       default:;
 104:     endcase // unique case (st)
 105:   end
 106: 
 107:   // overflow error detection is not here, but instead handled at memory protection
 108:   assign int_addr = op_addr_i + AddrW'(cnt);
 109:   assign flash_addr_o = int_addr[0 +: AddrW];
 110:   assign flash_ovfl_o = int_addr[AddrW];
 111:   // if error, return "empty" data
 112:   assign data_o = err_sel ? {DataW{1'b1}} : flash_data_i;
 113: 
 114: 
 115: endmodule // flash_rd_ctrl
 116: