/* Copyright (C) 2008 Martin Furter This file is part of wbavr. wbavr is free software/hardware; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. wbavr is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with wbavr; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. ==============================================================================*/ /* wbavr_wishbone: Wishbone interface logic. */ module wbavr_wishbone( // ---------------------------------------------------------------- // wishbone common wb_clk_i, // clock input wb_rst_i, // reset input (sync) // ---------------------------------------------------------------- // wishbone code bus, 16 bit wb_c_adr_o, // address output wb_c_dat_rd_i, // data input wb_c_dat_wr_o, // data output wb_c_cyc_o, // cycle in progress output wb_c_stb_o, // strobe output wb_c_we_o, // write enable output wb_c_ack_i, // acknowledge input wb_c_err_i, // error input wb_c_rty_i, // retry input // c_lock_o, // bus lock output // c_sel_o, // 'byte' select output // c_tga_o, // adress tag type output // c_tgc_o, // cycle tag type output // c_tgd_i, // data tag type input // c_tgd_o, // data tag type output // ---------------------------------------------------------------- // wishbone data bus, 8 bit wb_d_adr_o, // address output wb_d_dat_rd_i, // data input wb_d_dat_wr_o, // data output wb_d_cyc_o, // cycle in progress output wb_d_stb_o, // strobe output wb_d_we_o, // write enable output wb_d_ack_i, // acknowledge input wb_d_err_i, // error input wb_d_rty_i, // retry input // d_lock_o, // bus lock output // d_sel_o, // 'byte' select output // d_tga_o, // adress tag type output // d_tgc_o, // cycle tag type output // d_tgd_i, // data tag type input // d_tgd_o, // data tag type output // ---------------------------------------------------------------- // avr common avr_clk_o, // ---------------------------------------------------------------- // avr code bus avr_c_adr_i, avr_c_dat_rd_o, avr_c_dat_wr_i, avr_c_rd_i, avr_c_wr_i, // ---------------------------------------------------------------- // avr data bus avr_d_adr_i, avr_d_dat_rd_o, avr_d_dat_wr_i, avr_d_rd_i, avr_d_wr_i ); // wishbone common input wb_clk_i; input wb_rst_i; // wishbone code bus, 16 bit output [15:1] wb_c_adr_o; input [15:0] wb_c_dat_rd_i; output [15:0] wb_c_dat_wr_o; output wb_c_cyc_o; output wb_c_stb_o; output wb_c_we_o; input wb_c_ack_i; input wb_c_err_i; input wb_c_rty_i; // wishbone data bus, 8 bit output [15:0] wb_d_adr_o; input [7:0] wb_d_dat_rd_i; output [7:0] wb_d_dat_wr_o; output wb_d_cyc_o; output wb_d_stb_o; output wb_d_we_o; input wb_d_ack_i; input wb_d_err_i; input wb_d_rty_i; // avr clock output avr_clk_o; reg avr_clk_o; // avr code bus input [15:1] avr_c_adr_i; input [15:0] avr_c_dat_wr_i; output [15:0] avr_c_dat_rd_o; reg [15:0] avr_c_dat_rd_o; input avr_c_rd_i; input avr_c_wr_i; // avr data bus input [15:0] avr_d_adr_i; input [7:0] avr_d_dat_wr_i; output [7:0] avr_d_dat_rd_o; reg [7:0] avr_d_dat_rd_o; input avr_d_rd_i; input avr_d_wr_i; // internal signals reg c_buffered; reg d_buffered; wire wb_c_reply; wire wb_d_reply; wire avr_c_sel; wire avr_d_sel; wire c_done; wire d_done; // wishbone reply: acknowledge, error or retry assign wb_c_reply = |{ wb_c_ack_i, wb_c_err_i, wb_c_rty_i }; assign wb_d_reply = |{ wb_d_ack_i, wb_d_err_i, wb_d_rty_i }; // bus is selected if read or write is requested assign avr_c_sel = |{ avr_c_rd_i, avr_c_wr_i }; assign avr_d_sel = |{ avr_d_rd_i, avr_d_wr_i }; // done means either wishbone replies or data is already buffered assign c_done = |{ ~avr_c_sel, wb_c_reply, c_buffered }; assign d_done = |{ ~avr_d_sel, wb_d_reply, d_buffered }; // adresses and data assign wb_c_adr_o = avr_c_adr_i; assign wb_d_adr_o = avr_d_adr_i; assign wb_c_dat_wr_o = avr_c_dat_wr_i; assign wb_d_dat_wr_o = avr_d_dat_wr_i; // set wishbone cycle if bus is selected and not buffered assign wb_c_cyc_o = &{ avr_c_sel, !c_buffered }; assign wb_d_cyc_o = &{ avr_d_sel, !d_buffered }; // wishbone strobe is same as cycle (in this case) assign wb_c_stb_o = wb_c_cyc_o; assign wb_d_stb_o = wb_d_cyc_o; // wishbone write enable, only valid in a cycle assign wb_c_we_o = &{ avr_c_wr_i, wb_c_cyc_o }; assign wb_d_we_o = &{ avr_d_wr_i, wb_d_cyc_o }; // clock always @ ( posedge wb_clk_i ) begin // set avr_clk_o if( wb_rst_i == 1'b1 ) begin // reset avr_clk_o <= 1'b0; end else if( avr_clk_o == 1'b1 && c_done == 1'b1 && d_done == 1'b1 ) begin // falling edge if both buses are done avr_clk_o <= 1'b0; end else if( avr_clk_o == 1'b0 ) begin // rising edge avr_clk_o <= 1'b1; end // set c_buffered and d_buffered if( wb_rst_i == 1'b1 ) begin // reset c_buffered <= 1'b0; d_buffered <= 1'b0; avr_c_dat_rd_o <= 0; avr_d_dat_rd_o <= 0; end else if( avr_clk_o == 1'b0 ) begin // begin of new cycle c_buffered <= 1'b0; d_buffered <= 1'b0; avr_c_dat_rd_o <= 0; avr_d_dat_rd_o <= 0; end else begin if( wb_c_reply == 1'b1 ) begin // code bus done c_buffered <= 1'b1; avr_c_dat_rd_o <= wb_c_dat_rd_i; end if( wb_d_reply == 1'b1 ) begin // data bus done d_buffered <= 1'b1; avr_d_dat_rd_o <= wb_d_dat_rd_i; end end end endmodule