/* 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_gpregs: AVR General Purpose Register Bank with 2 read and 2 write ports. */ module wbavr_gpregs( // ---------------------------------------------------------------- // common clk_i, // clock input // ---------------------------------------------------------------- // read register 0 rd_adr_0_i, // address rd_data_0_o, // data output // ---------------------------------------------------------------- // read register 1 rd_adr_1_i, // address rd_data_1_o, // data output // ---------------------------------------------------------------- // write register 0 wr_enable_0_i, // write enable wr_adr_0_i, // address wr_data_0_i, // data input // ---------------------------------------------------------------- // write register 1 wr_enable_1_i, // write enable wr_adr_1_i, // address wr_data_1_i, // data input // ---------------------------------------------------------------- // write conflict output wr_conflict_o ); // interface signals input clk_i; input [4:0] rd_adr_0_i; output [7:0] rd_data_0_o; input [4:0] rd_adr_1_i; output [7:0] rd_data_1_o; input wr_enable_0_i; input [4:0] wr_adr_0_i; input [7:0] wr_data_0_i; input wr_enable_1_i; input [4:0] wr_adr_1_i; input [7:0] wr_data_1_i; output wr_conflict_o; // internal signals reg [7:0] registers [0:31]; integer i; wire wr_conflict; assign rd_data_0_o = registers[rd_adr_0_i]; assign rd_data_1_o = registers[rd_adr_1_i]; assign wr_conflict = &{ wr_enable_0_i, wr_adr_0_i == wr_adr_1_i }; assign wr_conflict_o = &{ wr_enable_1_i, wr_conflict }; always @ ( posedge clk_i ) begin if( wr_enable_0_i == 1'b1 ) begin registers[wr_adr_0_i] <= wr_data_0_i; end if( wr_enable_1_i == 1'b1 && !wr_conflict ) begin registers[wr_adr_1_i] <= wr_data_1_i; end end endmodule