OpenCores
URL https://opencores.org/ocsvn/aor3000/aor3000/trunk

Subversion Repositories aor3000

[/] [aor3000/] [trunk/] [rtl/] [pipeline/] [pipeline_rf.v] - Rev 2

Compare with Previous | Blame | View Log

/*
 * This file is subject to the terms and conditions of the BSD License. See
 * the file "LICENSE" in the main directory of this archive for more details.
 *
 * Copyright (C) 2014 Aleksander Osman
 */
 
`include "defines.v"
 
module pipeline_rf(
    input               clk,
    input               rst_n,
 
    //
    input               exception_start,
 
    //
    input               if_exc_address_error,
    input               if_exc_tlb_inv,
    input               if_exc_tlb_miss,
    input               if_ready,
    input       [31:0]  if_instr,
    input       [31:0]  if_pc,
 
    //
    output      [6:0]   rf_cmd,
    output reg  [31:0]  rf_instr,
    output reg  [31:0]  rf_pc_plus4,
    output reg  [31:0]  rf_badvpn,
    output      [31:0]  rf_a,
    output      [31:0]  rf_b,
 
    //
    input               mem_stall,
 
    //
    input       [4:0]   exe_result_index,
    input       [31:0]  exe_result,
 
    input       [4:0]   mem_result_index,
    input       [31:0]  mem_result,
 
    input       [4:0]   muldiv_result_index,
    input       [31:0]  muldiv_result
);
 
//------------------------------------------------------------------------------
 
wire rf_load = (if_ready || if_exc_address_error || if_exc_tlb_inv || if_exc_tlb_miss) && ~(mem_stall);
 
//------------------------------------------------------------------------------
 
//rd <- rs OP rt
wire cmd_3arg_add  = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b100000;
wire cmd_3arg_addu = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b100001;
wire cmd_3arg_and  = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b100100;
wire cmd_3arg_nor  = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b100111;
wire cmd_3arg_or   = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b100101;
wire cmd_3arg_slt  = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b101010;
wire cmd_3arg_sltu = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b101011;
wire cmd_3arg_sub  = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b100010;
wire cmd_3arg_subu = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b100011;
wire cmd_3arg_xor  = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b100110;
wire cmd_3arg_sllv = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b000100;
wire cmd_3arg_srav = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b000111;
wire cmd_3arg_srlv = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b000110;
 
//rd <- rt OP imm
wire cmd_sll = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b000000;
wire cmd_sra = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b000011;
wire cmd_srl = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b000010;
 
//rt <- rs OP imm
wire cmd_addi  = rf_instr[31:26] == 6'b001000;
wire cmd_addiu = rf_instr[31:26] == 6'b001001;
wire cmd_andi  = rf_instr[31:26] == 6'b001100;
wire cmd_ori   = rf_instr[31:26] == 6'b001101;
wire cmd_slti  = rf_instr[31:26] == 6'b001010;
wire cmd_sltiu = rf_instr[31:26] == 6'b001011;
wire cmd_xori  = rf_instr[31:26] == 6'b001110;
 
//rd <- hi,lo
wire cmd_muldiv_mfhi  = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b010000;
wire cmd_muldiv_mflo  = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b010010;
 
//hi,lo <- rs
wire cmd_muldiv_mthi  = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b010001 && rf_instr[15:11] == 5'b00000;
wire cmd_muldiv_mtlo  = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b010011 && rf_instr[15:11] == 5'b00000;
 
//hi,lo <- rs OP rt
wire cmd_muldiv_mult  = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b011000  && rf_instr[15:11] == 5'b00000;
wire cmd_muldiv_multu = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b011001  && rf_instr[15:11] == 5'b00000;
wire cmd_muldiv_div   = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b011010;
wire cmd_muldiv_divu  = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b011011;
 
//rt <- imm
wire cmd_lui = rf_instr[31:26] == 6'b001111;
 
//exception
wire cmd_break   = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b001101;
wire cmd_syscall = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b001100;
 
wire cmd_unusable123 = rf_instr[31:28] == 4'b0100 && rf_instr[27:26] != 2'b00 && ~(cmd_cfc1_detect);
wire cmd_lwc123      = rf_instr[31:28] == 4'b1100 && rf_instr[27:26] != 2'b00;
wire cmd_swc123      = rf_instr[31:28] == 4'b1110 && rf_instr[27:26] != 2'b00;
 
//cmd_swc0, cmd_lwc0, cmd_cop0_inv: `CMD_exc_reserved_instr
 
wire exc_coproc_unusable = cmd_unusable123 || cmd_lwc123 || cmd_swc123;
 
// rt <- 0
wire cmd_cfc1_detect = rf_instr[31:28] == 4'b0100 && rf_instr[27:26] == 2'b01 && rf_instr[25:21] == 5'b00010 && rf_instr[15:11] == 5'b00000;
 
//rd_cp0 <- rt
wire cmd_mtc0  = rf_instr[31:28] == 4'b0100 && rf_instr[27:26] == 2'b00 && rf_instr[25:21] == 5'b00100;
//rt <- rd_cp0 
wire cmd_mfc0  = rf_instr[31:28] == 4'b0100 && rf_instr[27:26] == 2'b00 && rf_instr[25:21] == 5'b00000;
 
wire cmd_bc0f    = rf_instr[31:28] == 4'b0100 && rf_instr[27:26] == 2'b00 && rf_instr[25:21] == 5'b01000 && rf_instr[20:16] == 5'd0;
wire cmd_bc0t    = rf_instr[31:28] == 4'b0100 && rf_instr[27:26] == 2'b00 && rf_instr[25:21] == 5'b01000 && rf_instr[20:16] == 5'd1;
wire cmd_bc0_ign = rf_instr[31:28] == 4'b0100 && rf_instr[27:26] == 2'b00 && rf_instr[25:21] == 5'b01000 && (rf_instr[20:16] == 5'd2 || rf_instr[20:16] == 5'd3);
 
wire cmd_rfe   = rf_instr[31:28] == 4'b0100 && rf_instr[27:26] == 2'b00 && rf_instr[25] == 1'b1 && rf_instr[5:0] == 6'b010000;
wire cmd_tlbp  = rf_instr[31:28] == 4'b0100 && rf_instr[27:26] == 2'b00 && rf_instr[25] == 1'b1 && rf_instr[5:0] == 6'b001000;
wire cmd_tlbr  = rf_instr[31:28] == 4'b0100 && rf_instr[27:26] == 2'b00 && rf_instr[25] == 1'b1 && rf_instr[5:0] == 6'b000001;
wire cmd_tlbwi = rf_instr[31:28] == 4'b0100 && rf_instr[27:26] == 2'b00 && rf_instr[25] == 1'b1 && rf_instr[5:0] == 6'b000010;
wire cmd_tlbwr = rf_instr[31:28] == 4'b0100 && rf_instr[27:26] == 2'b00 && rf_instr[25] == 1'b1 && rf_instr[5:0] == 6'b000110;
 
//rt <- mem
wire cmd_lb  = rf_instr[31:26] == 6'b100000;
wire cmd_lbu = rf_instr[31:26] == 6'b100100;
wire cmd_lh  = rf_instr[31:26] == 6'b100001;
wire cmd_lhu = rf_instr[31:26] == 6'b100101;
wire cmd_lw  = rf_instr[31:26] == 6'b100011;
wire cmd_lwl = rf_instr[31:26] == 6'b100010;
wire cmd_lwr = rf_instr[31:26] == 6'b100110;
 
//mem <- rt
wire cmd_sb  = rf_instr[31:26] == 6'b101000;
wire cmd_sh  = rf_instr[31:26] == 6'b101001;
wire cmd_sw  = rf_instr[31:26] == 6'b101011;
wire cmd_swl = rf_instr[31:26] == 6'b101010;
wire cmd_swr = rf_instr[31:26] == 6'b101110;
 
//<- rs, rt
wire cmd_beq    = rf_instr[31:26] == 6'b000100;
wire cmd_bne    = rf_instr[31:26] == 6'b000101;
//<- rs
wire cmd_bgez   = rf_instr[31:26] == 6'b000001 && rf_instr[20:16] == 5'b00001;
wire cmd_bgtz   = rf_instr[31:26] == 6'b000111 && rf_instr[20:16] == 5'b00000;
wire cmd_blez   = rf_instr[31:26] == 6'b000110 && rf_instr[20:16] == 5'b00000;
wire cmd_bltz   = rf_instr[31:26] == 6'b000001 && rf_instr[20:16] == 5'b00000;
wire pre_jr     = if_instr[31:26] == 6'b000000 && if_instr[5:0] == 6'b001000;
wire cmd_jr     = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b001000 && rf_jr_check;
//r31 <- rs
wire cmd_bgezal = rf_instr[31:26] == 6'b000001 && rf_instr[20:16] == 5'b10001;
wire cmd_bltzal = rf_instr[31:26] == 6'b000001 && rf_instr[20:16] == 5'b10000;
//rd <- rs
wire cmd_jalr   = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b001001;
//r31 <-
wire cmd_jal    = rf_instr[31:26] == 6'b000011;
//
wire cmd_j      = rf_instr[31:26] == 6'b000010;
 
//------------------------------------------------------------------------------
 
assign rf_cmd =
    (exception_start)?          `CMD_null :
    (rf_exc_address_error)?     `CMD_exc_load_addr_err :
    (rf_exc_tlb_inv)?           `CMD_exc_load_tlb :
    (rf_exc_tlb_miss)?          `CMD_exc_tlb_load_miss :
    (~(rf_ready))?              `CMD_null :
    (cmd_3arg_add)?             `CMD_3arg_add :
    (cmd_3arg_addu)?            `CMD_3arg_addu :
    (cmd_3arg_and)?             `CMD_3arg_and :
    (cmd_3arg_nor)?             `CMD_3arg_nor :
    (cmd_3arg_or)?              `CMD_3arg_or :
    (cmd_3arg_slt)?             `CMD_3arg_slt :
    (cmd_3arg_sltu)?            `CMD_3arg_sltu :
    (cmd_3arg_sub)?             `CMD_3arg_sub :
    (cmd_3arg_subu)?            `CMD_3arg_subu :
    (cmd_3arg_xor)?             `CMD_3arg_xor :
    (cmd_3arg_sllv)?            `CMD_3arg_sllv :
    (cmd_3arg_srav)?            `CMD_3arg_srav :
    (cmd_3arg_srlv)?            `CMD_3arg_srlv :
    (cmd_sll)?                  `CMD_sll :
    (cmd_sra)?                  `CMD_sra :
    (cmd_srl)?                  `CMD_srl :
    (cmd_addi)?                 `CMD_addi :
    (cmd_addiu)?                `CMD_addiu :
    (cmd_andi)?                 `CMD_andi :
    (cmd_ori)?                  `CMD_ori :
    (cmd_slti)?                 `CMD_slti :
    (cmd_sltiu)?                `CMD_sltiu :
    (cmd_xori)?                 `CMD_xori :
    (cmd_muldiv_mfhi)?          `CMD_muldiv_mfhi :
    (cmd_muldiv_mflo)?          `CMD_muldiv_mflo :
    (cmd_muldiv_mthi)?          `CMD_muldiv_mthi :
    (cmd_muldiv_mtlo)?          `CMD_muldiv_mtlo :
    (cmd_muldiv_mult)?          `CMD_muldiv_mult :
    (cmd_muldiv_multu)?         `CMD_muldiv_multu :
    (cmd_muldiv_div)?           `CMD_muldiv_div :
    (cmd_muldiv_divu)?          `CMD_muldiv_divu :
    (cmd_lui)?                  `CMD_lui :
    (cmd_break)?                `CMD_break :
    (cmd_syscall)?              `CMD_syscall :
    (exc_coproc_unusable)?      `CMD_exc_coproc_unusable :
    (cmd_mtc0)?                 `CMD_mtc0 :
    (cmd_mfc0)?                 `CMD_mfc0 :
    (cmd_cfc1_detect)?          `CMD_cfc1_detect :
    (cmd_rfe)?                  `CMD_cp0_rfe :
    (cmd_tlbp)?                 `CMD_cp0_tlbp :
    (cmd_tlbr)?                 `CMD_cp0_tlbr :
    (cmd_tlbwi)?                `CMD_cp0_tlbwi :
    (cmd_tlbwr)?                `CMD_cp0_tlbwr :
    (cmd_bc0f)?                 `CMD_cp0_bc0f :
    (cmd_bc0t)?                 `CMD_cp0_bc0t :
    (cmd_bc0_ign)?              `CMD_cp0_bc0_ign :
    (cmd_lb)?                   `CMD_lb :
    (cmd_lbu)?                  `CMD_lbu :
    (cmd_lh)?                   `CMD_lh :
    (cmd_lhu)?                  `CMD_lhu :
    (cmd_lw)?                   `CMD_lw :
    (cmd_lwl)?                  `CMD_lwl :
    (cmd_lwr)?                  `CMD_lwr :
    (cmd_sb)?                   `CMD_sb :
    (cmd_sh)?                   `CMD_sh :
    (cmd_sw)?                   `CMD_sw :
    (cmd_swl)?                  `CMD_swl :
    (cmd_swr)?                  `CMD_swr :
    (cmd_beq)?                  `CMD_beq :
    (cmd_bne)?                  `CMD_bne :
    (cmd_bgez)?                 `CMD_bgez :
    (cmd_bgtz)?                 `CMD_bgtz :
    (cmd_blez)?                 `CMD_blez :
    (cmd_bltz)?                 `CMD_bltz :
    (cmd_jr)?                   `CMD_jr :
    (cmd_bgezal)?               `CMD_bgezal :
    (cmd_bltzal)?               `CMD_bltzal :
    (cmd_jalr)?                 `CMD_jalr :
    (cmd_jal)?                  `CMD_jal :
    (cmd_j)?                    `CMD_j :
                                `CMD_exc_reserved_instr;
 
reg rf_exc_address_error;
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)           rf_exc_address_error <= `FALSE;
    else if(exception_start)    rf_exc_address_error <= `FALSE;
    else if(rf_load)            rf_exc_address_error <= if_exc_address_error;
end
 
reg rf_exc_tlb_inv;
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)           rf_exc_tlb_inv <= `FALSE;
    else if(exception_start)    rf_exc_tlb_inv <= `FALSE;
    else if(rf_load)            rf_exc_tlb_inv <= if_exc_tlb_inv;
end
 
reg rf_exc_tlb_miss;
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)           rf_exc_tlb_miss <= `FALSE;
    else if(exception_start)    rf_exc_tlb_miss <= `FALSE;
    else if(rf_load)            rf_exc_tlb_miss <= if_exc_tlb_miss;
end
 
reg rf_ready;
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)           rf_ready <= `FALSE;
    else if(exception_start)    rf_ready <= `FALSE;
    else if(rf_load && if_ready)rf_ready <= `TRUE;
    else if(~(mem_stall))       rf_ready <= `FALSE;
end
 
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)           rf_instr <= 32'd0;
    else if(rf_load)            rf_instr <= if_instr;
end
 
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)           rf_pc_plus4 <= 32'd0;
    else if(rf_load)            rf_pc_plus4 <= if_pc + 32'd4;
end
 
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)           rf_badvpn <= 32'd0;
    else if(rf_load)            rf_badvpn <= if_pc;
end
 
//------------------------------------------------------------------------------
 
wire [4:0] rf_instr_rs = rf_instr[25:21];
wire [4:0] rf_instr_rt = rf_instr[20:16];
wire [4:0] rf_instr_rd = rf_instr[15:11];
 
assign rf_a = 
    (exe_result_index != 5'd0    && rf_instr_rs == exe_result_index)?       exe_result :
    (muldiv_result_index != 5'd0 && rf_instr_rs == muldiv_result_index)?    muldiv_result :
    (mem_result_index != 5'd0    && rf_instr_rs == mem_result_index)?       mem_result :
                                                                            q_a_final;
 
assign rf_b =
    (exe_result_index != 5'd0    && rf_instr_rt == exe_result_index)?       exe_result :
    (muldiv_result_index != 5'd0 && rf_instr_rt == muldiv_result_index)?    muldiv_result :
    (mem_result_index != 5'd0    && rf_instr_rt == mem_result_index)?       mem_result :
                                                                            q_b_final;
 
wire rf_jr_check =
    (exe_result_index != 5'd0    && rf_instr_rd == exe_result_index)?       exe_result == 32'd0 :
    (muldiv_result_index != 5'd0 && rf_instr_rd == muldiv_result_index)?    muldiv_result == 32'd0 :
    (mem_result_index != 5'd0    && rf_instr_rd == mem_result_index)?       mem_result == 32'd0 :
                                                                            q_b_final == 32'd0;
 
//------------------------------------------------------------------------------
 
reg [4:0]  address_a_reg;
reg [4:0]  address_b_reg;
reg [4:0]  written_index_reg;
reg [31:0] written_data_reg;
 
always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) address_a_reg     <= 5'd0;  else if(~(mem_stall)) address_a_reg <= address_a; end
always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) address_b_reg     <= 5'd0;  else if(~(mem_stall)) address_b_reg <= address_b; end
 
always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) written_data_reg  <= 32'd0; else written_data_reg  <= mem_result;       end
always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) written_index_reg <= 5'd0;  else written_index_reg <= mem_result_index; end
 
wire [31:0] q_a_final = (written_index_reg != 5'd0 && address_a_reg == written_index_reg)? written_data_reg : q_a;
wire [31:0] q_b_final = (written_index_reg != 5'd0 && address_b_reg == written_index_reg)? written_data_reg : q_b;
 
//------------------------------------------------------------------------------
wire [4:0] if_instr_rs = if_instr[25:21];
wire [4:0] if_instr_rt = if_instr[20:16];
wire [4:0] if_instr_rd = if_instr[15:11];
 
wire [4:0] address_a = if_instr_rs;
wire [4:0] address_b = (pre_jr)? if_instr_rd : if_instr_rt;
 
wire [31:0] q_a;
wire [31:0] q_b;
 
model_simple_dual_ram #(
    .width          (32),
    .widthad        (5)
)
regs_a_inst(
    .clk            (clk),
 
    .address_a      ((mem_stall)? address_a_reg : address_a),
    .q_a            (q_a),
 
    .address_b      (mem_result_index),
    .wren_b         (mem_result_index != 5'd0),
    .data_b         (mem_result)
);
 
model_simple_dual_ram #(
    .width          (32),
    .widthad        (5)
)
regs_b_inst(
    .clk            (clk),
 
    .address_a      ((mem_stall)? address_b_reg : address_b),
    .q_a            (q_b),
 
    .address_b      (mem_result_index),
    .wren_b         (mem_result_index != 5'd0),
    .data_b         (mem_result)
);
 
 
//------------------------------------------------------------------------------
 
endmodule
 

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.