../src/lowrisc_ip_flash_ctrl_0.1/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: