⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 memory_sizer_dual_path.v

📁 硬件方面的源代码-有关IP核的
💻 V
📖 第 1 页 / 共 2 页
字号:
// Internal signal declarationswire [2*N_PP-1:0] memory_be_source;     // Unshifted byte enables for writingwire [2*N_PP-1:0] latch_be_source;      // Unshifted byte enables for readingwire [N_PP-1:0] latch_be;               // "latch_be" is like "memory_be_o" wire [N_PP-1:0] latch_be_lil_endian;    //    but used internally for reads.wire [N_PP-1:0] latch_be_big_endian;wire [LOG2_N_PP-1:0] latch_be_adjust;wire [LOG2_N_PP+1:0] dat_shift_next;    // Next dat_shift value (extra bit                                        //   is for terminal count compare.)wire [LOG2_N_PP-1:0] alignment;         // shows aligment of accesswire terminal_count;                    // signifies last store cycle reg [LOG2_N_PP-1:0] rd_byte_mux_select; // selects which bytes to transferreg [LOG2_N_PP-1:0] wr_byte_mux_select; // selects which bytes to transferreg [LOG2_N_PP:0] dat_shift;            // shift amt. for data and byte enablesreg [`BYTE_SIZE*N_PP-1:0] wr_steer_dat_o; // data from byte steering logicreg [`BYTE_SIZE*N_PP-1:0] wr_revrs_dat_o; // data from byte reversing logicreg [`BYTE_SIZE*N_PP-1:0] rd_revrs_dat_o; // data from byte reversing logicreg [`BYTE_SIZE*N_PP-1:0] rd_steer_dat_o; // data from byte steering logicreg [`BYTE_SIZE*N_PP-1:0] read_dat;     // read data (after latch bypassing)reg [`BYTE_SIZE*N_PP-1:0] latched_read_dat; // read values before latch bypassreg [WATCHDOG_TIMER_BITS_PP-1:0] watchdog_count;//--------------------------------------------------------------------------// Instantiations//--------------------------------------------------------------------------//--------------------------------------------------------------------------// Functions & Tasks//--------------------------------------------------------------------------function [`BYTE_SIZE*N_PP-1:0] byte_reversal;  input [`BYTE_SIZE*N_PP-1:0] din;  integer k;  begin    for (k=0; k<N_PP; k=k+1)      byte_reversal[`BYTE_SIZE*(N_PP-k)-1:`BYTE_SIZE*(N_PP-k-1)]        <= din[`BYTE_SIZE*(k+1)-1:`BYTE_SIZE*k];  endendfunction//--------------------------------------------------------------------------// Module code//--------------------------------------------------------------------------// Mask off the address bits that don't matter for alignmentassign alignment = (memory_width_i - 1) & adr_i[LOG2_N_PP-1:0];// Setting up the basic (alignment shifted) byte enablesassign memory_be_source = ((1<<access_width_i)-1);assign latch_be_source = ((1<<memory_width_i)-1);// Assigning the byte enables and latch enablesassign memory_be_o = we_i?((memory_be_source << alignment) >> dat_shift)                          :{N_PP{1'b1}};                          // (memory byte enables are all high for reads!)// For big_endian reads, the latch byte enables (and indeed the data also)// are shifted using a special mapping, which causes the data to appear at // the opposite end of the "read_data" bus.assign latch_be_lil_endian = ((latch_be_source << dat_shift) >> alignment);assign latch_be_adjust = ~(access_width_i[LOG2_N_PP-1:0]-1);assign latch_be_big_endian = latch_be_lil_endian << latch_be_adjust;assign latch_be = (access_big_endian_i)?latch_be_big_endian                                       :latch_be_lil_endian;// Exceptionsassign exception_be_o = (alignment != 0) && ~memory_has_be_i;assign exception_watchdog_o = (watchdog_count == WATCHDOG_TIMER_VALUE_PP);// Pass signals to memoryassign memory_we_o = we_i;// Enable the data bus outputs in each directionassign dat_io = (sel_i && ~we_i)?rd_revrs_dat_o:{`BYTE_SIZE*N_PP{1'bZ}};assign memory_dat_io = (sel_i && we_i)?wr_steer_dat_o:{`BYTE_SIZE*N_PP{1'bZ}};// THIS LOGIC IS FOR THE WRITING PATH//-------------------------------------// Byte reversal logicalways @(         dat_io              or         access_big_endian_i         )begin  // Reverse the bytes of the data bus, if needed  if (access_big_endian_i) wr_revrs_dat_o <= byte_reversal(dat_io);  else wr_revrs_dat_o <= dat_io;end// Steering logicalways @(         wr_revrs_dat_o      or         dat_shift           or         alignment           or         we_i                or         access_width_i      or         access_big_endian_i         )begin  // If bytes are reversed, an extra "bit inversion mask" is applied  // to reflect a new mapping which is correct for reversed bytes.  if (access_big_endian_i)    wr_byte_mux_select <= (dat_shift[LOG2_N_PP-1:0] ^ ~(access_width_i-1))                           - alignment;  else wr_byte_mux_select <= dat_shift - alignment;  // Rotate the data bus (byte-sized barrel shifter!)  wr_steer_dat_o <= (                     (wr_revrs_dat_o >> `BYTE_SIZE*wr_byte_mux_select)                    |(wr_revrs_dat_o << `BYTE_SIZE*(N_PP-wr_byte_mux_select))                     );end// THIS LOGIC IS FOR THE READING PATH//-------------------------------------// Steering logicalways @(         memory_dat_io       or         dat_shift           or         alignment           or         we_i                or         access_width_i      or         access_big_endian_i         )begin    // For reads, negate the shift amount  if (access_big_endian_i)    rd_byte_mux_select <= alignment                           - (dat_shift[LOG2_N_PP-1:0] ^ ~(access_width_i-1));  else rd_byte_mux_select <= alignment - dat_shift;  // Rotate the data bus (byte-sized barrel shifter!)  rd_steer_dat_o <= (                     (memory_dat_io >> `BYTE_SIZE*rd_byte_mux_select)                    |(memory_dat_io << `BYTE_SIZE*(N_PP-rd_byte_mux_select))                    );end// This logic latches the data bytes which are read during the first cycles// of an access.  During the final cycle of the access, then "terminal_count"// is asserted by the counting logic, which causes the latches which are// "non-dirty" (i.e. which do not yet contain data) to be bypassed by muxes.// This means that for single cycle accesses, the data will flow directly// around the latches and an extra clock cycle will not be needed in order// to latch the data...always @(posedge clk_i)begin: BYTE_LATCHES  integer i;  if (reset_i || terminal_count || ~sel_i)  begin    latched_read_dat <= 0;  end  else if (sel_i && ~we_i && memory_ack_i)  begin    for (i=0;i<N_PP;i=i+1)    begin      if (latch_be[i]) latched_read_dat[`BYTE_SIZE*(i+1)-1:`BYTE_SIZE*i]                       <= rd_steer_dat_o[`BYTE_SIZE*(i+1)-1:`BYTE_SIZE*i];    end  endend// This part handles the bypass muxesalways @(         terminal_count      or         latch_be            or         rd_steer_dat_o      or         latched_read_dat         )begin: LATCH_BYPASS  integer j;  for (j=0;j<N_PP;j=j+1)  begin    if (terminal_count && latch_be[j])          read_dat[`BYTE_SIZE*(j+1)-1:`BYTE_SIZE*j]          <= rd_steer_dat_o[`BYTE_SIZE*(j+1)-1:`BYTE_SIZE*j];    else read_dat[`BYTE_SIZE*(j+1)-1:`BYTE_SIZE*j]         <= latched_read_dat[`BYTE_SIZE*(j+1)-1:`BYTE_SIZE*j];  endend// Byte reversal logicalways @(         read_dat            or         access_big_endian_i         )begin  // Reverse the bytes of the data bus, if needed  if (access_big_endian_i) rd_revrs_dat_o <= byte_reversal(read_dat);  else rd_revrs_dat_o <= read_dat;end// THIS LOGIC IS GENERAL//--------------------------// This is the counting logic.// It is implemented using "count_next" in order to detect when// the last cycle is being performed, which is when the "next" count// equals or exceeds the total size of the access requested in bytes.// (Using the "next" approach avoids issues relating to different//  memory sizes!)always @(posedge clk_i)begin  if (reset_i || terminal_count || ~sel_i) dat_shift <= 0;  else if (memory_ack_i) dat_shift <= dat_shift_next;endassign dat_shift_next = dat_shift + memory_width_i;assign terminal_count = (dat_shift_next >= (access_width_i + alignment));assign memory_adr_o = adr_i + dat_shift;assign access_ack_o = terminal_count && sel_i;// This is the watchdog timer// It runs whenever the memory_sizer is selected for an access, and the// memory has not yet responded with an ack signal.always @(posedge clk_i)begin  if (reset_i || ~sel_i || memory_ack_i) watchdog_count <= 0;  else if (~exception_watchdog_o) watchdog_count <= watchdog_count + 1;endendmodule

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -