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

Subversion Repositories aor3000

[/] [aor3000/] [trunk/] [rtl/] [memory/] [memory_tlb_ram.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 memory_tlb_ram(
    input               clk,
    input               rst_n,
 
    //
    input               tlb_ram_read_do,
    input       [5:0]   tlb_ram_read_index,
    output reg          tlb_ram_read_result_ready,
    output      [49:0]  tlb_ram_read_result,
 
    //
    input               tlb_ram_write_do,
    input       [5:0]   tlb_ram_write_index,
    input       [49:0]  tlb_ram_write_value,
 
    //
    input       [5:0]   entryhi_asid,
 
    //
    input               tlb_ram_data_start,
    input       [19:0]  tlb_ram_data_vpn,
    output reg          tlb_ram_data_hit,
    output reg  [5:0]   tlb_ram_data_index,
    output reg  [49:0]  tlb_ram_data_result,
    output              tlb_ram_data_missed,
 
    //
    input               tlb_ram_fetch_start,
    input       [19:0]  tlb_ram_fetch_vpn,
    output reg          tlb_ram_fetch_hit,
    output reg  [49:0]  tlb_ram_fetch_result,
    output              tlb_ram_fetch_missed
); /* verilator public_module */
 
//------------------------------------------------------------------------------
 
/*
[19:0]  vpn
[39:20] pfn
[45:40] asid
[46]    n noncachable
[47]    d dirty = write-enable
[48]    v valid
[49]    g global
*/
 
//------------------------------------------------------------------------------
 
reg invalid_ram_q;
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)   invalid_ram_q <= `FALSE;
    else                invalid_ram_q <= tlb_ram_read_do || tlb_ram_write_do;
end
 
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)   tlb_ram_read_result_ready <= `FALSE;
    else                tlb_ram_read_result_ready <= tlb_ram_read_do;
end
 
//------------------------------------------------------------------------------
 
reg [2:0] index;
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)   index <= 3'd0;
    else                index <= index_next;
end
 
wire [2:0] index_next = (tlb_ram_read_do || tlb_ram_write_do)? index : index + 3'd1;
 
wire [2:0] read_index = (tlb_ram_read_do)? tlb_ram_read_index[5:3] : index_next;
 
//------------------------------------------------------------------------------
 
wire [49:0] tlb0_q_a;
wire [49:0] tlb0_q_b;
wire [49:0] tlb1_q_a;
wire [49:0] tlb1_q_b;
wire [49:0] tlb2_q_a;
wire [49:0] tlb2_q_b;
wire [49:0] tlb3_q_a;
wire [49:0] tlb3_q_b;
 
reg [2:0] read_index_part;
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)   read_index_part <= 3'd0;
    else                read_index_part <= tlb_ram_read_index[2:0];
end
 
assign tlb_ram_read_result =
    (read_index_part == 3'd0)?  tlb0_q_a[49:0] :
    (read_index_part == 3'd1)?  tlb0_q_b[49:0] :
    (read_index_part == 3'd2)?  tlb1_q_a[49:0] :
    (read_index_part == 3'd3)?  tlb1_q_b[49:0] :
    (read_index_part == 3'd4)?  tlb2_q_a[49:0] :
    (read_index_part == 3'd5)?  tlb2_q_b[49:0] :
    (read_index_part == 3'd6)?  tlb3_q_a[49:0] :
                                tlb3_q_b[49:0];
 
//------------------------------------------------------------------------------
 
wire match_data0 = tlb_ram_data_vpn == tlb0_q_a[19:0] && (tlb0_q_a[49] || entryhi_asid == tlb0_q_a[45:40]);
wire match_data1 = tlb_ram_data_vpn == tlb0_q_b[19:0] && (tlb0_q_b[49] || entryhi_asid == tlb0_q_b[45:40]);
wire match_data2 = tlb_ram_data_vpn == tlb1_q_a[19:0] && (tlb1_q_a[49] || entryhi_asid == tlb1_q_a[45:40]);
wire match_data3 = tlb_ram_data_vpn == tlb1_q_b[19:0] && (tlb1_q_b[49] || entryhi_asid == tlb1_q_b[45:40]);
wire match_data4 = tlb_ram_data_vpn == tlb2_q_a[19:0] && (tlb2_q_a[49] || entryhi_asid == tlb2_q_a[45:40]);
wire match_data5 = tlb_ram_data_vpn == tlb2_q_b[19:0] && (tlb2_q_b[49] || entryhi_asid == tlb2_q_b[45:40]);
wire match_data6 = tlb_ram_data_vpn == tlb3_q_a[19:0] && (tlb3_q_a[49] || entryhi_asid == tlb3_q_a[45:40]);
wire match_data7 = tlb_ram_data_vpn == tlb3_q_b[19:0] && (tlb3_q_b[49] || entryhi_asid == tlb3_q_b[45:40]);
 
wire match_fetch0 = tlb_ram_fetch_vpn == tlb0_q_a[19:0] && (tlb0_q_a[49] || entryhi_asid == tlb0_q_a[45:40]);
wire match_fetch1 = tlb_ram_fetch_vpn == tlb0_q_b[19:0] && (tlb0_q_b[49] || entryhi_asid == tlb0_q_b[45:40]);
wire match_fetch2 = tlb_ram_fetch_vpn == tlb1_q_a[19:0] && (tlb1_q_a[49] || entryhi_asid == tlb1_q_a[45:40]);
wire match_fetch3 = tlb_ram_fetch_vpn == tlb1_q_b[19:0] && (tlb1_q_b[49] || entryhi_asid == tlb1_q_b[45:40]);
wire match_fetch4 = tlb_ram_fetch_vpn == tlb2_q_a[19:0] && (tlb2_q_a[49] || entryhi_asid == tlb2_q_a[45:40]);
wire match_fetch5 = tlb_ram_fetch_vpn == tlb2_q_b[19:0] && (tlb2_q_b[49] || entryhi_asid == tlb2_q_b[45:40]);
wire match_fetch6 = tlb_ram_fetch_vpn == tlb3_q_a[19:0] && (tlb3_q_a[49] || entryhi_asid == tlb3_q_a[45:40]);
wire match_fetch7 = tlb_ram_fetch_vpn == tlb3_q_b[19:0] && (tlb3_q_b[49] || entryhi_asid == tlb3_q_b[45:40]);
 
wire tlb_ram_data_hit_next  = (data_cnt > 4'd0)                      && (match_data0  || match_data1  || match_data2  || match_data3  || match_data4  || match_data5  || match_data6  || match_data7);
wire tlb_ram_fetch_hit_next = (fetch_cnt > 4'd0 && ~(invalid_ram_q)) && (match_fetch0 || match_fetch1 || match_fetch2 || match_fetch3 || match_fetch4 || match_fetch5 || match_fetch6 || match_fetch7);
 
wire [5:0] tlb_ram_data_index_next =
    (match_data0)?   { index, 3'd0 } :
    (match_data1)?   { index, 3'd1 } :
    (match_data2)?   { index, 3'd2 } :
    (match_data3)?   { index, 3'd3 } :
    (match_data4)?   { index, 3'd4 } :
    (match_data5)?   { index, 3'd5 } :
    (match_data6)?   { index, 3'd6 } :
                     { index, 3'd7 };
 
wire [49:0] tlb_ram_data_result_next =
    (match_data0)?   tlb0_q_a :
    (match_data1)?   tlb0_q_b :
    (match_data2)?   tlb1_q_a :
    (match_data3)?   tlb1_q_b :
    (match_data4)?   tlb2_q_a :
    (match_data5)?   tlb2_q_b :
    (match_data6)?   tlb3_q_a :
                     tlb3_q_b;
 
wire [49:0] tlb_ram_fetch_result_next =
    (match_fetch0)? tlb0_q_a :
    (match_fetch1)? tlb0_q_b :
    (match_fetch2)? tlb1_q_a :
    (match_fetch3)? tlb1_q_b :
    (match_fetch4)? tlb2_q_a :
    (match_fetch5)? tlb2_q_b :
    (match_fetch6)? tlb3_q_a :
                    tlb3_q_b;
 
always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) tlb_ram_data_hit     <= `FALSE; else tlb_ram_data_hit     <= tlb_ram_data_hit_next;     end
always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) tlb_ram_fetch_hit    <= `FALSE; else tlb_ram_fetch_hit    <= tlb_ram_fetch_hit_next;    end
always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) tlb_ram_data_index   <= 6'd0;   else tlb_ram_data_index   <= tlb_ram_data_index_next;   end
always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) tlb_ram_data_result  <= 50'd0;  else tlb_ram_data_result  <= tlb_ram_data_result_next;  end
always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) tlb_ram_fetch_result <= 50'd0;  else tlb_ram_fetch_result <= tlb_ram_fetch_result_next; end
 
//------------------------------------------------------------------------------
 
reg [3:0] data_cnt;
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)               data_cnt <= 4'd0;
    else if(tlb_ram_data_start)     data_cnt <= 4'd1;
    else if(tlb_ram_data_hit)       data_cnt <= 4'd0;
    else if(data_cnt == 4'd9)       data_cnt <= 4'd0;
    else if(data_cnt > 4'd0)        data_cnt <= data_cnt + 4'd1;
end
assign tlb_ram_data_missed = data_cnt == 4'd9 && ~(tlb_ram_data_hit);
 
//------------------------------------------------------------------------------
 
reg [3:0] fetch_cnt;
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)                               fetch_cnt <= 4'd0;
    else if(tlb_ram_fetch_start)                    fetch_cnt <= 4'd1;
    else if(tlb_ram_fetch_hit)                      fetch_cnt <= 4'd0;
    else if(fetch_cnt == 4'd9)                      fetch_cnt <= 4'd0;
    else if(fetch_cnt > 4'd0 && ~(invalid_ram_q))   fetch_cnt <= fetch_cnt + 4'd1;
end
assign tlb_ram_fetch_missed = fetch_cnt == 4'd9 && ~(tlb_ram_fetch_hit);
 
//------------------------------------------------------------------------------
 
model_true_dual_ram #(
    .width          (50),
    .widthad        (4)
)
tlb0_inst(
    .clk            (clk),
 
    .address_a      (tlb_ram_write_do? { 1'b0, tlb_ram_write_index[5:3] } : { 1'b0, read_index }),
    .wren_a         (tlb_ram_write_do && tlb_ram_write_index[2:0] == 3'd0),
    .data_a         (tlb_ram_write_value),
    .q_a            (tlb0_q_a),
 
    .address_b      (tlb_ram_write_do? { 1'b1, tlb_ram_write_index[5:3] } : { 1'b1, read_index }),
    .wren_b         (tlb_ram_write_do && tlb_ram_write_index[2:0] == 3'd1),
    .data_b         (tlb_ram_write_value),
    .q_b            (tlb0_q_b)
);
 
model_true_dual_ram #(
    .width          (50),
    .widthad        (4)
)
tlb1_inst(
    .clk            (clk),
 
    .address_a      (tlb_ram_write_do? { 1'b0, tlb_ram_write_index[5:3] } : { 1'b0, read_index }),
    .wren_a         (tlb_ram_write_do && tlb_ram_write_index[2:0] == 3'd2),
    .data_a         (tlb_ram_write_value),
    .q_a            (tlb1_q_a),
 
    .address_b      (tlb_ram_write_do? { 1'b1, tlb_ram_write_index[5:3] } : { 1'b1, read_index }),
    .wren_b         (tlb_ram_write_do && tlb_ram_write_index[2:0] == 3'd3),
    .data_b         (tlb_ram_write_value),
    .q_b            (tlb1_q_b)
);
 
model_true_dual_ram #(
    .width          (50),
    .widthad        (4)
)
tlb2_inst(
    .clk            (clk),
 
    .address_a      (tlb_ram_write_do? { 1'b0, tlb_ram_write_index[5:3] } : { 1'b0, read_index }),
    .wren_a         (tlb_ram_write_do && tlb_ram_write_index[2:0] == 3'd4),
    .data_a         (tlb_ram_write_value),
    .q_a            (tlb2_q_a),
 
    .address_b      (tlb_ram_write_do? { 1'b1, tlb_ram_write_index[5:3] } : { 1'b1, read_index }),
    .wren_b         (tlb_ram_write_do && tlb_ram_write_index[2:0] == 3'd5),
    .data_b         (tlb_ram_write_value),
    .q_b            (tlb2_q_b)
);
 
model_true_dual_ram #(
    .width          (50),
    .widthad        (4)
)
tlb3_inst(
    .clk            (clk),
 
    .address_a      (tlb_ram_write_do? { 1'b0, tlb_ram_write_index[5:3] } : { 1'b0, read_index }),
    .wren_a         (tlb_ram_write_do && tlb_ram_write_index[2:0] == 3'd6),
    .data_a         (tlb_ram_write_value),
    .q_a            (tlb3_q_a),
 
    .address_b      (tlb_ram_write_do? { 1'b1, tlb_ram_write_index[5:3] } : { 1'b1, read_index }),
    .wren_b         (tlb_ram_write_do && tlb_ram_write_index[2:0] == 3'd7),
    .data_b         (tlb_ram_write_value),
    .q_b            (tlb3_q_b)
);
 
//------------------------------------------------------------------------------
 
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.