| 1 | 2 | dgisselq | ///////////////////////////////////////////////////////////////////////////
 | 
      
         | 2 |  |  | //
 | 
      
         | 3 |  |  | // Filename:    busdelay.v
 | 
      
         | 4 |  |  | //
 | 
      
         | 5 |  |  | // Project:     Zip CPU -- a small, lightweight, RISC CPU soft core
 | 
      
         | 6 |  |  | //
 | 
      
         | 7 |  |  | // Purpose:     Delay any access to the wishbone bus by a single clock.
 | 
      
         | 8 |  |  | //
 | 
      
         | 9 |  |  | //      When the first Zip System would not meet the timing requirements of
 | 
      
         | 10 |  |  | //      the board it was placed upon, this bus delay was added to help out.
 | 
      
         | 11 |  |  | //      It may no longer be necessary, having cleaned some other problems up
 | 
      
         | 12 |  |  | //      first, but it will remain here as a means of alleviating timing
 | 
      
         | 13 |  |  | //      problems.
 | 
      
         | 14 |  |  | //
 | 
      
         | 15 |  |  | //      The specific problem takes place on the stall line: a wishbone master
 | 
      
         | 16 |  |  | //      *must* know on the first clock whether or not the bus will stall.
 | 
      
         | 17 |  |  | //
 | 
      
         | 18 |  |  | //
 | 
      
         | 19 |  |  | //
 | 
      
         | 20 |  |  | //
 | 
      
         | 21 |  |  | // Creator:     Dan Gisselquist, Ph.D.
 | 
      
         | 22 | 69 | dgisselq | //              Gisselquist Technology, LLC
 | 
      
         | 23 | 2 | dgisselq | //
 | 
      
         | 24 |  |  | ///////////////////////////////////////////////////////////////////////////
 | 
      
         | 25 |  |  | //
 | 
      
         | 26 |  |  | // Copyright (C) 2015, Gisselquist Technology, LLC
 | 
      
         | 27 |  |  | //
 | 
      
         | 28 |  |  | // This program is free software (firmware): you can redistribute it and/or
 | 
      
         | 29 |  |  | // modify it under the terms of  the GNU General Public License as published
 | 
      
         | 30 |  |  | // by the Free Software Foundation, either version 3 of the License, or (at
 | 
      
         | 31 |  |  | // your option) any later version.
 | 
      
         | 32 |  |  | //
 | 
      
         | 33 |  |  | // This program is distributed in the hope that it will be useful, but WITHOUT
 | 
      
         | 34 |  |  | // ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
 | 
      
         | 35 |  |  | // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 | 
      
         | 36 |  |  | // for more details.
 | 
      
         | 37 |  |  | //
 | 
      
         | 38 |  |  | // License:     GPL, v3, as defined and found on www.gnu.org,
 | 
      
         | 39 |  |  | //              http://www.gnu.org/licenses/gpl.html
 | 
      
         | 40 |  |  | //
 | 
      
         | 41 |  |  | //
 | 
      
         | 42 |  |  | ///////////////////////////////////////////////////////////////////////////
 | 
      
         | 43 |  |  | //
 | 
      
         | 44 |  |  | module  busdelay(i_clk,
 | 
      
         | 45 |  |  |                 // The input bus
 | 
      
         | 46 |  |  |                 i_wb_cyc, i_wb_stb, i_wb_we, i_wb_addr, i_wb_data,
 | 
      
         | 47 | 36 | dgisselq |                         o_wb_ack, o_wb_stall, o_wb_data, o_wb_err,
 | 
      
         | 48 | 2 | dgisselq |                 // The delayed bus
 | 
      
         | 49 |  |  |                 o_dly_cyc, o_dly_stb, o_dly_we, o_dly_addr, o_dly_data,
 | 
      
         | 50 | 36 | dgisselq |                         i_dly_ack, i_dly_stall, i_dly_data, i_dly_err);
 | 
      
         | 51 | 2 | dgisselq |         parameter       AW=32, DW=32;
 | 
      
         | 52 |  |  |         input   i_clk;
 | 
      
         | 53 |  |  |         // Input/master bus
 | 
      
         | 54 |  |  |         input                           i_wb_cyc, i_wb_stb, i_wb_we;
 | 
      
         | 55 |  |  |         input           [(AW-1):0]       i_wb_addr;
 | 
      
         | 56 |  |  |         input           [(DW-1):0]       i_wb_data;
 | 
      
         | 57 |  |  |         output  reg                     o_wb_ack;
 | 
      
         | 58 |  |  |         output  wire                    o_wb_stall;
 | 
      
         | 59 |  |  |         output  reg     [(DW-1):0]       o_wb_data;
 | 
      
         | 60 | 36 | dgisselq |         output  wire                    o_wb_err;
 | 
      
         | 61 | 2 | dgisselq |         // Delayed bus
 | 
      
         | 62 |  |  |         output  reg                     o_dly_cyc, o_dly_stb, o_dly_we;
 | 
      
         | 63 |  |  |         output  reg     [(AW-1):0]       o_dly_addr;
 | 
      
         | 64 |  |  |         output  reg     [(DW-1):0]       o_dly_data;
 | 
      
         | 65 |  |  |         input                           i_dly_ack;
 | 
      
         | 66 |  |  |         input                           i_dly_stall;
 | 
      
         | 67 |  |  |         input           [(DW-1):0]       i_dly_data;
 | 
      
         | 68 | 36 | dgisselq |         input                           i_dly_err;
 | 
      
         | 69 | 2 | dgisselq |  
 | 
      
         | 70 |  |  |         initial o_dly_cyc = 1'b0;
 | 
      
         | 71 |  |  |         initial o_dly_stb = 1'b0;
 | 
      
         | 72 |  |  |  
 | 
      
         | 73 |  |  |         always @(posedge i_clk)
 | 
      
         | 74 |  |  |                 o_dly_cyc <= i_wb_cyc;
 | 
      
         | 75 | 61 | dgisselq |         // Add the i_wb_cyc criteria here, so we can simplify the o_wb_stall
 | 
      
         | 76 |  |  |         // criteria below, which would otherwise *and* these two.
 | 
      
         | 77 | 2 | dgisselq |         always @(posedge i_clk)
 | 
      
         | 78 |  |  |                 if (~o_wb_stall)
 | 
      
         | 79 | 61 | dgisselq |                         o_dly_stb <= ((i_wb_cyc)&&(i_wb_stb));
 | 
      
         | 80 | 2 | dgisselq |         always @(posedge i_clk)
 | 
      
         | 81 |  |  |                 if (~o_wb_stall)
 | 
      
         | 82 |  |  |                         o_dly_we  <= i_wb_we;
 | 
      
         | 83 |  |  |         always @(posedge i_clk)
 | 
      
         | 84 |  |  |                 if (~o_wb_stall)
 | 
      
         | 85 |  |  |                         o_dly_addr<= i_wb_addr;
 | 
      
         | 86 |  |  |         always @(posedge i_clk)
 | 
      
         | 87 |  |  |                 if (~o_wb_stall)
 | 
      
         | 88 |  |  |                         o_dly_data <= i_wb_data;
 | 
      
         | 89 |  |  |         always @(posedge i_clk)
 | 
      
         | 90 |  |  |                 o_wb_ack  <= (i_dly_ack)&&(o_dly_cyc)&&(i_wb_cyc);
 | 
      
         | 91 |  |  |         always @(posedge i_clk)
 | 
      
         | 92 |  |  |                 o_wb_data <= i_dly_data;
 | 
      
         | 93 |  |  |  
 | 
      
         | 94 | 15 | dgisselq |         // Our only non-delayed line, yet still really delayed.  Perhaps
 | 
      
         | 95 |  |  |         // there's a way to register this?
 | 
      
         | 96 |  |  |         // o_wb_stall <= (i_wb_cyc)&&(i_wb_stb) ... or some such?
 | 
      
         | 97 | 61 | dgisselq |         // assign o_wb_stall=((i_wb_cyc)&&(i_dly_stall)&&(o_dly_stb));//&&o_cyc
 | 
      
         | 98 |  |  |         assign  o_wb_stall = ((i_dly_stall)&&(o_dly_stb));//&&o_cyc
 | 
      
         | 99 | 36 | dgisselq |         assign  o_wb_err   = i_dly_err;
 | 
      
         | 100 | 2 | dgisselq |  
 | 
      
         | 101 |  |  | endmodule
 |