dineshannayya | 913410a | 2021-10-13 22:29:46 +0530 | [diff] [blame] | 1 | ////////////////////////////////////////////////////////////////////////////// |
| 2 | // SPDX-FileCopyrightText: 2021 , Dinesh Annayya |
| 3 | // |
| 4 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | // you may not use this file except in compliance with the License. |
| 6 | // You may obtain a copy of the License at |
| 7 | // |
| 8 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | // |
| 10 | // Unless required by applicable law or agreed to in writing, software |
| 11 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | // See the License for the specific language governing permissions and |
| 14 | // limitations under the License. |
| 15 | // SPDX-License-Identifier: Apache-2.0 |
| 16 | // SPDX-FileContributor: Created by Dinesh Annayya <dinesha@opencores.org> |
| 17 | // |
| 18 | ////////////////////////////////////////////////////////////////////// |
| 19 | //// //// |
| 20 | //// Async Wishbone Interface //// |
| 21 | //// //// |
| 22 | //// This file is part of the YIFive cores project //// |
| 23 | //// http://www.opencores.org/cores/yifive/ //// |
| 24 | //// //// |
| 25 | //// Description //// |
| 26 | //// This block does async Wishbone from one clock to other //// |
| 27 | //// clock domain |
| 28 | //// //// |
| 29 | //// To Do: //// |
| 30 | //// nothing //// |
| 31 | //// //// |
| 32 | //// Author(s): //// |
| 33 | //// - Dinesh Annayya, dinesha@opencores.org //// |
| 34 | //// //// |
| 35 | //// Revision : //// |
| 36 | //// 0.1 - 25th Feb 2021, Dinesh A //// |
| 37 | //// initial version //// |
| 38 | //// 0.2 - 28th Feb 2021, Dinesh A //// |
| 39 | //// reduced the response FIFO path depth to 2 as //// |
| 40 | //// return path used by only read logic and read is //// |
| 41 | //// blocking request and expect only one location will //// |
| 42 | //// be used //// |
| 43 | ////////////////////////////////////////////////////////////////////// |
| 44 | //// //// |
| 45 | //// Copyright (C) 2000 Authors and OPENCORES.ORG //// |
| 46 | //// //// |
| 47 | //// This source file may be used and distributed without //// |
| 48 | //// restriction provided that this copyright statement is not //// |
| 49 | //// removed from the file and that any derivative work contains //// |
| 50 | //// the original copyright notice and the associated disclaimer. //// |
| 51 | //// //// |
| 52 | //// This source file is free software; you can redistribute it //// |
| 53 | //// and/or modify it under the terms of the GNU Lesser General //// |
| 54 | //// Public License as published by the Free Software Foundation; //// |
| 55 | //// either version 2.1 of the License, or (at your option) any //// |
| 56 | //// later version. //// |
| 57 | //// //// |
| 58 | //// This source is distributed in the hope that it will be //// |
| 59 | //// useful, but WITHOUT ANY WARRANTY; without even the implied //// |
| 60 | //// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// |
| 61 | //// PURPOSE. See the GNU Lesser General Public License for more //// |
| 62 | //// details. //// |
| 63 | //// //// |
| 64 | //// You should have received a copy of the GNU Lesser General //// |
| 65 | //// Public License along with this source; if not, download it //// |
| 66 | //// from http://www.opencores.org/lgpl.shtml //// |
| 67 | //// //// |
| 68 | ////////////////////////////////////////////////////////////////////// |
| 69 | |
| 70 | module async_wb |
| 71 | #(parameter AW = 32, |
| 72 | parameter BW = 4, |
| 73 | parameter DW = 32) |
| 74 | ( |
| 75 | |
| 76 | // Master Port |
| 77 | input logic wbm_rst_n , // Regular Reset signal |
| 78 | input logic wbm_clk_i , // System clock |
| 79 | input logic wbm_cyc_i , // strobe/request |
| 80 | input logic wbm_stb_i , // strobe/request |
| 81 | input logic [AW-1:0] wbm_adr_i , // address |
| 82 | input logic wbm_we_i , // write |
| 83 | input logic [DW-1:0] wbm_dat_i , // data output |
| 84 | input logic [BW-1:0] wbm_sel_i , // byte enable |
| 85 | output logic [DW-1:0] wbm_dat_o , // data input |
| 86 | output logic wbm_ack_o , // acknowlegement |
| 87 | output logic wbm_err_o , // error |
| 88 | |
| 89 | // Slave Port |
| 90 | input logic wbs_rst_n , // Regular Reset signal |
| 91 | input logic wbs_clk_i , // System clock |
| 92 | output logic wbs_cyc_o , // strobe/request |
| 93 | output logic wbs_stb_o , // strobe/request |
| 94 | output logic [AW-1:0] wbs_adr_o , // address |
| 95 | output logic wbs_we_o , // write |
| 96 | output logic [DW-1:0] wbs_dat_o , // data output |
| 97 | output logic [BW-1:0] wbs_sel_o , // byte enable |
| 98 | input logic [DW-1:0] wbs_dat_i , // data input |
| 99 | input logic wbs_ack_i , // acknowlegement |
| 100 | input logic wbs_err_i // error |
| 101 | |
| 102 | ); |
| 103 | |
| 104 | |
| 105 | |
| 106 | parameter CFW = AW+DW+BW+1 ; // COMMAND FIFO WIDTH |
| 107 | |
| 108 | //------------------------------------------------- |
| 109 | // Master Interface |
| 110 | // ------------------------------------------------- |
| 111 | logic PendingRd ; // Pending Read Transaction |
| 112 | logic m_cmd_wr_en ; |
| 113 | logic [CFW-1:0] m_cmd_wr_data ; |
| 114 | logic m_cmd_wr_full ; |
| 115 | logic m_cmd_wr_afull ; |
| 116 | |
| 117 | logic m_resp_rd_empty ; |
| 118 | logic m_resp_rd_aempty ; |
| 119 | logic m_resp_rd_en ; |
| 120 | logic [DW:0] m_resp_rd_data ; |
| 121 | |
| 122 | // Master Write Interface |
| 123 | |
| 124 | |
| 125 | assign m_cmd_wr_en = (!PendingRd) && wbm_stb_i && !m_cmd_wr_full && !m_cmd_wr_afull; |
| 126 | |
| 127 | assign m_cmd_wr_data = {wbm_adr_i,wbm_we_i,wbm_dat_i,wbm_sel_i}; |
| 128 | |
| 129 | always@(negedge wbm_rst_n or posedge wbm_clk_i) |
| 130 | begin |
| 131 | if(wbm_rst_n == 0) begin |
| 132 | PendingRd <= 1'b0; |
| 133 | end else begin |
| 134 | if((!PendingRd) && wbm_stb_i && (!wbm_we_i) && m_cmd_wr_en) begin |
| 135 | PendingRd <= 1'b1; |
| 136 | end else if(PendingRd && wbm_stb_i && (!wbm_we_i) && wbm_ack_o) begin |
| 137 | PendingRd <= 1'b0; |
| 138 | end |
| 139 | end |
| 140 | end |
| 141 | |
| 142 | |
| 143 | // Master Read Interface |
| 144 | // For Write is feed through, if there is space in fifo the ack |
| 145 | // For Read, Wait for Response Path FIFO status |
| 146 | assign wbm_ack_o = (wbm_stb_i && wbm_we_i) ? m_cmd_wr_en : // Write Logic |
dineshannayya | 1c06214 | 2021-11-05 21:15:43 +0530 | [diff] [blame^] | 147 | (wbm_stb_i && (!wbm_we_i)) ? !m_resp_rd_empty : 1'b0; // Read Logic |
dineshannayya | 913410a | 2021-10-13 22:29:46 +0530 | [diff] [blame] | 148 | |
| 149 | assign m_resp_rd_en = !m_resp_rd_empty; |
| 150 | assign wbm_dat_o = m_resp_rd_data[DW-1:0]; |
| 151 | assign wbm_err_o = m_resp_rd_data[DW]; |
| 152 | |
| 153 | |
| 154 | //------------------------------ |
| 155 | // Slave Interface |
| 156 | //------------------------------- |
| 157 | |
| 158 | logic [CFW-1:0] s_cmd_rd_data ; |
| 159 | logic s_cmd_rd_empty ; |
| 160 | logic s_cmd_rd_aempty ; |
| 161 | logic s_cmd_rd_en ; |
| 162 | logic s_resp_wr_en ; |
| 163 | logic [DW:0] s_resp_wr_data ; |
| 164 | logic s_resp_wr_full ; |
| 165 | logic s_resp_wr_afull ; |
| 166 | logic wbs_ack_f ; |
| 167 | |
| 168 | |
| 169 | always@(negedge wbs_rst_n or posedge wbs_clk_i) |
| 170 | begin |
| 171 | if(wbs_rst_n == 0) begin |
| 172 | wbs_ack_f <= 1'b0; |
| 173 | end else begin |
| 174 | wbs_ack_f <= wbs_ack_i; |
| 175 | end |
| 176 | end |
| 177 | |
| 178 | |
| 179 | // Read Interface |
| 180 | assign {wbs_adr_o,wbs_we_o,wbs_dat_o,wbs_sel_o} = (s_cmd_rd_empty) ? '0: s_cmd_rd_data; |
| 181 | // All the downstream logic expect Stobe is getting de-asserted |
| 182 | // atleast for 1 cycle after ack is generated |
| 183 | assign wbs_stb_o = (wbs_ack_f) ? 1'b0 : (s_cmd_rd_empty) ? 1'b0: 1'b1; |
| 184 | assign wbs_cyc_o = (wbs_ack_f) ? 1'b0 : (s_cmd_rd_empty) ? 1'b0: 1'b1; |
| 185 | |
| 186 | assign s_cmd_rd_en = wbs_ack_i; |
| 187 | |
| 188 | // Write Interface |
| 189 | // response send only for read logic |
| 190 | assign s_resp_wr_en = wbs_stb_o & (!wbs_we_o) & wbs_ack_i & !s_resp_wr_full; |
| 191 | assign s_resp_wr_data = {wbs_err_i,wbs_dat_i}; |
| 192 | |
| 193 | async_fifo #(.W(CFW), .DP(4), .WR_FAST(1), .RD_FAST(1)) u_cmd_if ( |
| 194 | // Sync w.r.t WR clock |
| 195 | .wr_clk (wbm_clk_i ), |
| 196 | .wr_reset_n (wbm_rst_n ), |
| 197 | .wr_en (m_cmd_wr_en ), |
| 198 | .wr_data (m_cmd_wr_data ), |
| 199 | .full (m_cmd_wr_full ), |
| 200 | .afull (m_cmd_wr_afull ), |
| 201 | |
| 202 | // Sync w.r.t RD Clock |
| 203 | .rd_clk (wbs_clk_i ), |
| 204 | .rd_reset_n (wbs_rst_n ), |
| 205 | .rd_en (s_cmd_rd_en ), |
| 206 | .empty (s_cmd_rd_empty ), // sync'ed to rd_clk |
| 207 | .aempty (s_cmd_rd_aempty ), // sync'ed to rd_clk |
| 208 | .rd_data (s_cmd_rd_data ) |
| 209 | ); |
| 210 | |
| 211 | |
| 212 | // Response used only read path, read is blocking access, expect |
| 213 | // only one location used in return path - reduced the depth to 2 |
dineshannayya | 1c06214 | 2021-11-05 21:15:43 +0530 | [diff] [blame^] | 214 | async_fifo #(.W(DW+1), .DP(2), .WR_FAST(1), .RD_FAST(0)) u_resp_if ( |
dineshannayya | 913410a | 2021-10-13 22:29:46 +0530 | [diff] [blame] | 215 | // Sync w.r.t WR clock |
| 216 | .wr_clk (wbs_clk_i ), |
| 217 | .wr_reset_n (wbs_rst_n ), |
| 218 | .wr_en (s_resp_wr_en ), |
| 219 | .wr_data (s_resp_wr_data ), |
| 220 | .full (s_resp_wr_full ), |
| 221 | .afull (s_resp_wr_afull ), |
| 222 | |
| 223 | // Sync w.r.t RD Clock |
| 224 | .rd_clk (wbm_clk_i ), |
| 225 | .rd_reset_n (wbm_rst_n ), |
| 226 | .rd_en (m_resp_rd_en ), |
| 227 | .empty (m_resp_rd_empty ), // sync'ed to rd_clk |
| 228 | .aempty (m_resp_rd_aempty ), // sync'ed to rd_clk |
| 229 | .rd_data (m_resp_rd_data ) |
| 230 | ); |
| 231 | |
| 232 | |
| 233 | |
| 234 | endmodule |