OpenCores
URL https://opencores.org/ocsvn/an-fpga-implementation-of-low-latency-noc-based-mpsoc/an-fpga-implementation-of-low-latency-noc-based-mpsoc/trunk

Subversion Repositories an-fpga-implementation-of-low-latency-noc-based-mpsoc

[/] [an-fpga-implementation-of-low-latency-noc-based-mpsoc/] [trunk/] [mpsoc/] [src_processor/] [mor1kx-5.0/] [rtl/] [verilog/] [mor1kx_rf_espresso.v] - Rev 48

Compare with Previous | Blame | View Log

/* ****************************************************************************
  This Source Code Form is subject to the terms of the
  Open Hardware Description License, v. 1.0. If a copy
  of the OHDL was not distributed with this file, You
  can obtain one at http://juliusbaxter.net/ohdl/ohdl.txt
 
  Description: Register file for espresso pipeline
 
  We get addresses for A and B read directly in from the instruction bus
 
  Copyright (C) 2012 Authors
 
  Author(s): Julius Baxter <juliusbaxter@gmail.com>
 
***************************************************************************** */
 
`include "mor1kx-defines.v"
 
module mor1kx_rf_espresso
  (/*AUTOARG*/
   // Outputs
   rfa_o, rfb_o,
   // Inputs
   clk, rst, rfd_adr_i, rfa_adr_i, rfb_adr_i, rf_we_i, rf_re_i,
   result_i
   );
 
   parameter OPTION_RF_ADDR_WIDTH = 5;
   parameter OPTION_RF_WORDS = 32;
 
   parameter OPTION_OPERAND_WIDTH = 32;
 
   input clk, rst;
 
 
   // GPR addresses
   // These two directly from insn bus
   input [OPTION_RF_ADDR_WIDTH-1:0]      rfd_adr_i;
   input [OPTION_RF_ADDR_WIDTH-1:0]      rfa_adr_i;
   // This one from the decode stage
   input [OPTION_RF_ADDR_WIDTH-1:0]      rfb_adr_i;
 
   // WE strobe from control stage
   input 				 rf_we_i;
 
   // Read enable strobe
   input 				 rf_re_i;
 
   input [OPTION_OPERAND_WIDTH-1:0] 	 result_i;
 
 
   output [OPTION_OPERAND_WIDTH-1:0] rfa_o;
   output [OPTION_OPERAND_WIDTH-1:0] rfb_o;
 
   wire [OPTION_OPERAND_WIDTH-1:0]   rfa_o_mux;
   wire [OPTION_OPERAND_WIDTH-1:0]   rfb_o_mux;
 
 
   wire [OPTION_OPERAND_WIDTH-1:0]   rfa_ram_o;
   wire [OPTION_OPERAND_WIDTH-1:0]   rfb_ram_o;
 
   reg [OPTION_OPERAND_WIDTH-1:0]    result_last;
   reg [OPTION_RF_ADDR_WIDTH-1:0]    rfd_last;
   reg [OPTION_RF_ADDR_WIDTH-1:0]    rfd_r;
   reg [OPTION_RF_ADDR_WIDTH-1:0]    rfa_r;
   reg [OPTION_RF_ADDR_WIDTH-1:0]    rfb_r;
 
   wire 			      rfa_o_use_last;
   wire 			      rfb_o_use_last;
   reg 				      rfa_o_using_last;
   reg 				      rfb_o_using_last;
 
   wire 			      rfa_rden;
   wire 			      rfb_rden;
 
   wire 			      rf_wren;
 
   // Read enables to make sure the last write-while-read propagates through
   // once the use_last signal goes away (we might rely on the value remaining
   // what it was, but the last registered result might get written again) so
   // this forces a read to get that value out.
   wire 			      rfa_rden_for_last;
   wire 			      rfb_rden_for_last;
 
   // Avoid read-write
   // Use when this instruction actually will write to its destination
   // register.
   assign rfa_o_use_last = (rfd_last == rfa_r);
   assign rfb_o_use_last = (rfd_last == rfb_r);
 
   assign rfa_o = rfa_o_use_last ? result_last : rfa_ram_o;
 
   assign rfb_o = rfb_o_use_last ? result_last : rfb_ram_o;
 
   assign rfa_rden_for_last = (rfa_o_use_last & !rf_re_i);
   assign rfb_rden_for_last = (rfb_o_use_last & !rf_re_i);
 
   assign rfa_rden = rf_re_i | rfa_rden_for_last;
   assign rfb_rden = rf_re_i | rfb_rden_for_last;
 
   assign rf_wren = rf_we_i;
 
 
   always @(posedge clk `OR_ASYNC_RST)
     if (rst) begin
	rfa_r <= 0;
	rfb_r <= 0;
	rfd_r <= 0;
     end
     else if (rf_re_i)
       begin
	  rfa_r <= rfa_adr_i;
	  rfb_r <= rfb_adr_i;
	  rfd_r <= rfd_adr_i;
       end
 
   always @(posedge clk `OR_ASYNC_RST)
     if (rst)
       rfd_last <= 0;
     else if (rf_wren)
       rfd_last <= rfd_adr_i;
 
   always @(posedge clk `OR_ASYNC_RST)
     if (rst)
       result_last <= 0;
     else if (rf_wren)
       result_last <= result_i;
 
   always @(posedge clk `OR_ASYNC_RST)
     if (rst) begin
	rfa_o_using_last <= 0;
	rfb_o_using_last <= 0;
     end
     else begin
	if (!rfa_o_using_last)
	  rfa_o_using_last <= rfa_o_use_last & !rfa_rden;
	else if (rfa_rden)
	  rfa_o_using_last <= 0;
 
	if (!rfb_o_using_last)
	  rfb_o_using_last <= rfb_o_use_last & !rfb_rden;
	else if (rfb_rden)
	  rfb_o_using_last <= 0;
     end
 
   mor1kx_simple_dpram_sclk
     #(
       .ADDR_WIDTH	(OPTION_RF_ADDR_WIDTH),
       .DATA_WIDTH	(OPTION_OPERAND_WIDTH),
       .ENABLE_BYPASS	(0)
       )
   rfa
     (
      .clk		(clk),
      .dout		(rfa_ram_o),
      .raddr		(rfa_adr_i),
      .re		(rfa_rden),
      .waddr		(rfd_adr_i),
      .we		(rf_wren),
      .din		(result_i)
      );
 
   mor1kx_simple_dpram_sclk
     #(
       .ADDR_WIDTH	(OPTION_RF_ADDR_WIDTH),
       .DATA_WIDTH	(OPTION_OPERAND_WIDTH),
       .ENABLE_BYPASS	(0)
       )
   rfb
     (
      .clk		(clk),
      .dout		(rfb_ram_o),
      .raddr		(rfb_adr_i),
      .re		(rfb_rden),
      .waddr		(rfd_adr_i),
      .we		(rf_wren),
      .din		(result_i)
      );
 
endmodule // mor1kx_execute_alu
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.