Skip to content
Snippets Groups Projects
Select Git revision
  • cbeeec65d5061485dc996be2caa1b3ec7aa6a09c
  • main default protected
2 results

cmsdk_ahb_ram_beh.v

Blame
  • Forked from SoCLabs / Accelerator Project
    Source project has a limited visibility.
    cmsdk_ahb_ram_beh.v 6.94 KiB
    //-----------------------------------------------------------------------------
    // The confidential and proprietary information contained in this file may
    // only be used by a person authorised under and to the extent permitted
    // by a subsisting licensing agreement from Arm Limited or its affiliates.
    //
    //            (C) COPYRIGHT 2010-2013 Arm Limited or its affiliates.
    //                ALL RIGHTS RESERVED
    //
    // This entire notice must be reproduced on all copies of this file
    // and copies of this file may only be made by a person if such person is
    // permitted to do so under the terms of a subsisting license agreement
    // from Arm Limited or its affiliates.
    //
    //      SVN Information
    //
    //      Checked In          : $Date: 2017-10-10 15:55:38 +0100 (Tue, 10 Oct 2017) $
    //
    //      Revision            : $Revision: 371321 $
    //
    //      Release Information : Cortex-M System Design Kit-r1p1-00rel0
    //
    //-----------------------------------------------------------------------------
    //-----------------------------------------------------------------------------
    // Abstract : Simple AHB RAM behavioral model
    //-----------------------------------------------------------------------------
    module cmsdk_ahb_ram_beh #(
      parameter AW       = 16,// Address width
      parameter filename = "",
      parameter WS_N     = 0, // First access wait state
      parameter WS_S     = 0) // Subsequent access wait state
     (
      input  wire          HCLK,    // Clock
      input  wire          HRESETn, // Reset
      input  wire          HSEL,    // Device select
      input  wire [AW-1:0] HADDR,   // Address
      input  wire [1:0]    HTRANS,  // Transfer control
      input  wire [2:0]    HSIZE,   // Transfer size
      input  wire          HWRITE,  // Write control
      input  wire [31:0]   HWDATA,  // Write data
      input  wire          HREADY,  // Transfer phase done
      output wire          HREADYOUT, // Device ready
      output wire [31:0]   HRDATA,  // Read data output
      output wire          HRESP);   // Device response (always OKAY)
    
      // Internal signals
      reg    [7:0]  ram_data[0:((1<<AW)-1)]; // 64k byte of RAM data
      wire          read_valid;     // Address phase read valid
      wire          write_valid;    // Address phase write valid
      reg           read_enable;    // Data phase read enable
      reg           write_enable;   // Data phase write enable
      reg    [3:0]  reg_byte_lane;  // Data phase byte lane
      reg    [3:0]  next_byte_lane; // Next state of reg_byte_lane
    
      reg    [7:0]  rdata_out_0;    // Read Data Output byte#0
      reg    [7:0]  rdata_out_1;    // Read Data Output byte#1
      reg    [7:0]  rdata_out_2;    // Read Data Output byte#2
      reg    [7:0]  rdata_out_3;    // Read Data Output byte#3
      reg [AW-1:0]  word_addr;      // Word aligned address
      wire [AW-1:0] nxt_word_addr;  // Word aligned address
      integer       i;              // Loop counter
    
      // Wait state control
      wire  [31:0]  nxt_waitstate_cnt;
      reg   [31:0]  reg_waitstate_cnt;
      wire          sequential_access;
    
      // Start of main code
      // Initialize ROM
      initial
        begin
        for (i=0;i<(1<<AW);i=i+1)
          begin
          ram_data[i] = 8'h00; //Initialize all data to 0
          end
          if (filename != "")
            begin
            $readmemh(filename, ram_data); // Then read in program code
            end
        end
    
      // Generate read control (address phase)
      assign read_valid  = HSEL & HREADY & HTRANS[1] & (~HWRITE);
      // Generate write control (address phase)
      assign write_valid = HSEL & HREADY & HTRANS[1] & HWRITE;
    
      // Read enable for each byte (address phase)
      always @(read_valid or write_valid or HADDR or HSIZE)
      begin
      if (read_valid | write_valid)
        begin
        case (HSIZE)
          0 : // Byte
            begin
            case (HADDR[1:0])
              0: next_byte_lane = 4'b0001; // Byte 0
              1: next_byte_lane = 4'b0010; // Byte 1
              2: next_byte_lane = 4'b0100; // Byte 2
              3: next_byte_lane = 4'b1000; // Byte 3
              default:next_byte_lane = 4'b0000; // Address not valid
            endcase
            end
          1 : // Halfword
            begin
            if (HADDR[1])
              next_byte_lane = 4'b1100; // Upper halfword
            else
              next_byte_lane = 4'b0011; // Lower halfword
            end
          default : // Word
            next_byte_lane = 4'b1111; // Whole word
        endcase
        end
      else
        next_byte_lane = 4'b0000; // Not reading
      end
    
      // Registering control signals to data phase
      always @(posedge HCLK or negedge HRESETn)
      begin
        if (~HRESETn)
          begin
          reg_byte_lane <= 4'b0000;
          read_enable   <= 1'b0;
          write_enable  <= 1'b0;
          word_addr     <= {AW{1'b0}};
          end
        else if (HREADY)
          begin
          reg_byte_lane <= next_byte_lane;
          read_enable   <= read_valid;
          write_enable  <= write_valid;
          word_addr     <= nxt_word_addr;
          end
      end
    
      assign nxt_word_addr = {HADDR[AW-1:2], 2'b00};
    
      // Read operation
      always @(read_enable or reg_byte_lane or word_addr)
        if ((read_enable & reg_byte_lane[0]))
          rdata_out_0 = ram_data[word_addr  ];
        else
          rdata_out_0 = 8'h00;
    
      always @(read_enable or reg_byte_lane or word_addr)
        if ((read_enable & reg_byte_lane[1]))
          rdata_out_1 = ram_data[word_addr+1];
        else
          rdata_out_1 = 8'h00;
    
      always @(read_enable or reg_byte_lane or word_addr)
        if ((read_enable & reg_byte_lane[2]))
          rdata_out_2 = ram_data[word_addr+2];
        else
          rdata_out_2 = 8'h00;
    
      always @(read_enable or reg_byte_lane or word_addr)
        if ((read_enable & reg_byte_lane[3]))
          rdata_out_3 = ram_data[word_addr+3];
        else
          rdata_out_3 = 8'h00;
    
      // Registered write
      always @(posedge HCLK)
      begin
        if (write_enable &  reg_byte_lane[0])
          begin
          ram_data[word_addr  ] = HWDATA[ 7: 0];
          end
        if (write_enable &  reg_byte_lane[1])
          begin
          ram_data[word_addr+1] = HWDATA[15: 8];
          end
        if (write_enable &  reg_byte_lane[2])
          begin
          ram_data[word_addr+2] = HWDATA[23:16];
          end
        if (write_enable &  reg_byte_lane[3])
          begin
          ram_data[word_addr+3] = HWDATA[31:24];
          end
      end
    
      // Wait state control
        //  Wait state generate treat access as sequential if
        //  HTRANS = 2'b11, or access address is in the same word,
        //  or if the access is in the next word
      assign sequential_access = (HTRANS==2'b11) |
                                (HADDR[AW-1:2] == word_addr[AW-1:2]) |
                                (HADDR[AW-1:2] == (word_addr[AW-1:2]+1));
      assign nxt_waitstate_cnt = (read_valid|write_valid) ?
                                 ((sequential_access) ? WS_S : WS_N) :
                                 ((reg_waitstate_cnt!=0) ? (reg_waitstate_cnt - 1) : 0);
        // Register wait state counter
      always @(posedge HCLK or negedge HRESETn)
      begin
        if (~HRESETn)
          reg_waitstate_cnt <= 0;
        else
          reg_waitstate_cnt <= nxt_waitstate_cnt;
      end
    
      // Connect to top level
      assign HREADYOUT = (reg_waitstate_cnt==0) ? 1'b1 : 1'b0;
      assign HRESP     = 1'b0; // Always response with OKAY
      // Read data output
      assign HRDATA    = {rdata_out_3, rdata_out_2, rdata_out_1,rdata_out_0};
    
    endmodule