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

Subversion Repositories m1_core

[/] [m1_core/] [trunk/] [hdl/] [rtl/] [m1_core/] [m1_mmu.v] - Diff between revs 2 and 33

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 2 Rev 33
Line 1... Line 1...
/*
/*
 * Simply RISC M1 Memory Management Unit
 * Simply RISC M1 Memory Management Unit
 *
 *
 * It will include the following components:
 * This block converts Harvard architecture requests to access the
 * - Instruction Cache
 * small internal prefetch buffer, and just in case the external
 * - Data Cache
 * Wishbone bus.
 * - TLB
 * Memory size is 256 word * 4 byte = 1024 byte,
 * but for now it's just a fake MMU.
 * so 10 address bits are required => [9:0]
 
 * and being the lower 2 bits unused the offset in memory is [9:2].
 */
 */
 
 
module m1_mmu (
module m1_mmu (
    sys_clock_i, sys_reset_i,
 
    imem_addr_i, imem_data_o, imem_read_i, imem_busy_o,
 
    dmem_addr_i, dmem_data_o, dmem_data_i, dmem_read_i, dmem_write_i, dmem_busy_o ,dmem_sel_i
 
  );
 
 
 
  // System
  // System
  input sys_clock_i, sys_reset_i;
    input sys_clock_i,                            // System Clock
 
    input sys_reset_i,                            // System Reset
 
 
  // Instruction Memory
  // Instruction Memory
  input[31:0] imem_addr_i;
    input imem_read_i,                            // I$ Read
  output[31:0] imem_data_o;
    input[31:0] imem_addr_i,                      // I$ Address
  input imem_read_i;
    output imem_done_o,                           // I$ Done
  output imem_busy_o;
    output[31:0] imem_data_o,                     // I$ Data
 
 
  // Data Memory
  // Data Memory
  input[31:0] dmem_addr_i;
    input dmem_read_i,                            // D$ Read
  output[31:0] dmem_data_o;
    input dmem_write_i,                           // D$ Write
  input[31:0] dmem_data_i;
    input[31:0] dmem_addr_i,                      // D$ Address
  input dmem_read_i;
    input[31:0] dmem_data_i,                      // D$ Write Data
  input dmem_write_i;
    input[3:0] dmem_sel_i,                        // D$ Byte selector
  output dmem_busy_o;
    output dmem_done_o,                           // D$ Done
 
    output[31:0] dmem_data_o,                     // D$ Read Data
  // Fake Instruction and Data Memories
 
  reg[31:0] imem_data[0:1023];   // 4KB I$
    // Wishbone Master interface
  reg[31:0] dmem_data[0:255];    // 1KB D$
    output wb_cyc_o,                              // Cycle Start
 
    output wb_stb_o,                              // Strobe Request
 
    output wb_we_o,                               // Write Enable
  //Selector
    output[31:0] wb_adr_o,                        // Address Bus
  input[3:0] dmem_sel_i;
    output[31:0] wb_dat_o,                        // Data Out
  reg[31:0] data_temp;
    output[3:0] wb_sel_o,                         // Byte Select
 
    input wb_ack_i,                               // Ack
  // Initialize fake memories
    input[31:0] wb_dat_i                          // Data In
  integer i;
 
  initial begin
 
 
 
    // I$ is initialized from file
 
    $readmemh("code.txt", imem_data);
 
 
 
    // D$ defaults to zeroes
 
    for(i=0; i<256; i=i+1) dmem_data[i] = 0;
 
 
 
  end
 
 
 
  assign imem_busy_o = 0;
 
  assign dmem_busy_o = 0;
 
 
 
 
 
  assign imem_data_o = imem_data[{2'b00, imem_addr_i[31:2]}];
 
  assign dmem_data_o = dmem_data[{2'b00, dmem_addr_i[31:2]}];
 
 
 
 
  );
 
 
  always @(dmem_write_i or dmem_read_i) begin
  /*
 
   * Registers
 
   */
 
 
    if(dmem_write_i) begin
  // Prefetch buffer
 
  reg[31:0] MEM[255:0];
 
 
       if(dmem_sel_i[0]) begin
  // Initialize memory content
                         data_temp = dmem_data[{2'b00, dmem_addr_i[31:2]}];
  initial begin
                         data_temp[7:0] = dmem_data_i[7:0];
`include "m1_mmu_initial.vh"
                         dmem_data[{2'b00, dmem_addr_i[31:2]}] = data_temp;
 
       end
 
       if(dmem_sel_i[1]) begin
 
                         data_temp = dmem_data[{2'b00, dmem_addr_i[31:2]}];
 
                         data_temp[15:8] = dmem_data_i[15:8];
 
                         dmem_data[{2'b00, dmem_addr_i[31:2]}] = data_temp;
 
       end
 
       if(dmem_sel_i[2]) begin
 
                         data_temp = dmem_data[{2'b00, dmem_addr_i[31:2]}];
 
                         data_temp[24:16] = dmem_data_i[24:16];
 
                         dmem_data[{2'b00, dmem_addr_i[31:2]}] = data_temp;
 
       end
 
       if(dmem_sel_i[3]) begin
 
                         data_temp = dmem_data[{2'b00, dmem_addr_i[31:2]}];
 
                         data_temp[31:24] = dmem_data_i[31:24];
 
                         dmem_data[{2'b00, dmem_addr_i[31:2]}] = data_temp;
 
       end
 
       $display("INFO: MEMH(%m): WRITE_ADDR=%X, WRITE_DATA=%X", dmem_addr_i, dmem_data_i);
 
    end
    end
 
 
 
  /*
 
   * Wires
 
   */
 
 
    if(dmem_read_i) begin
  // See if there are pending requests
      $display("INFO: MEMH(%m): READ_ADDR=%X, READ_DATA=%X", dmem_addr_i, dmem_data[{2'b00, dmem_addr_i[31:2]}]);
  wire access_pending_imem = imem_read_i;
    end
  wire access_pending_dmem = 0;
  end
  wire access_pending_ext = (dmem_read_i || dmem_write_i);
 
 
 
  // Default grant for memories
 
  assign imem_done_o = access_pending_imem;
 
  assign dmem_done_o = access_pending_dmem || (access_pending_ext && wb_ack_i);
 
 
 
  // Set Wishbone outputs
 
  assign wb_cyc_o = access_pending_ext;
 
  assign wb_stb_o = access_pending_ext;
 
  assign wb_we_o = access_pending_ext && dmem_write_i;
 
  assign wb_sel_o = dmem_sel_i;
 
  assign wb_adr_o = dmem_addr_i;
 
  assign wb_dat_o = dmem_data_i;
 
 
 
  // Return read data
 
  assign imem_data_o = MEM[imem_addr_i[9:2]];
 
  assign dmem_data_o = wb_dat_i;
 
 
endmodule
endmodule
 
 
 
 
 No newline at end of file
 No newline at end of file

powered by: WebSVN 2.1.0

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