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

📄 ahb_master.v

📁 appnote65_quickmips_ahb_interface_design_example AHB接口设计
💻 V
📖 第 1 页 / 共 2 页
字号:
               // error indicated on AHB
               // in current design it is unrecoverable
               // system needs to be reset
               else if(~hready_i & hresp_i == ERROR) begin
                  rddf_wren           <= 1'b0;
                  ahb_master_state    <= AHM_IDLE;
                  ahm_busreq_reg      <= 1'b0;
               end
               else begin
                  rddf_wren           <= 1'b1;
               end
         end
         // first address phase of write transfer
         AHM_NSEQWR:  begin
               if(hready_i) begin
                  // If it is single write cycle go to WAIT as
                  // current data is last data phase
                  if (hburst_o == SINGLE) begin
                     ahb_master_state    <= AHM_WRWAIT;
                  end
                  else if(~hgrant_i) begin
                     ahb_master_state    <= AHM_LASTWR;
                  end
                  else begin
                     ahb_master_state    <= AHM_SEQWR;
                  end
               end
         end
         // data phase of either single read cycle
         // or last data phase of burst read cycle
         AHM_RDWAIT:  begin
               // target is ready
               if(hready_i == 1'b1 & hresp_i == OKAY) begin
                  ahb_master_state    <= AHM_GOIDLE;
//	  				req_done			<= 1'b1;
                  // disable data fifo write logic
                  rddf_wren           <= 1'b0;
                  // read the address fifo as it is last data phase
                  // so that application can strobe new cycle if any
                  ahm_busreq_reg      <= 1'b0;
               end
               else if(~hready_i & (hresp_i == RETRY | hresp_i == SPLIT) ) begin
                     ahb_master_state    <= AHM_BREQ;
                     ahm_busreq_reg      <= 1'b1;
                  // disable data fifo write logic
                  rddf_wren           <= 1'b0;
//                  latch_prevaddr      <= 1'b1;
               end
               // error indicated on AHB
               // in current design it is unrecoverable
               // system needs to be reset
               else if(~hready_i & hresp_i == ERROR) begin
                  ahb_master_state    <= AHM_IDLE;
                  ahm_busreq_reg      <= 1'b0;
               end
         end
         // last data phase of write transfer(single/burst)
         // if successful S/M goes to idle
         // if unsuccessful(RETRY/SPLIT) transfer is retried
         AHM_WRWAIT:  begin
               // target is ready
               if(hready_i == 1'b1 & hresp_i == OKAY) begin
                  ahb_master_state    <= AHM_GOIDLE;
                  ahm_busreq_reg      <= 1'b0;
//	  				req_done			<= 1'b1;
               end
               else if(~hready_i & (hresp_i == RETRY | hresp_i == SPLIT) ) begin
                  ahb_master_state    <= AHM_BREQ;
                  ahm_busreq_reg      <= 1'b1;
//                  latch_prevaddr      <= 1'b1;
               end
               // system needs to be reset
               else if(~hready_i & hresp_i == ERROR) begin
                  ahb_master_state    <= AHM_IDLE;
                  ahm_busreq_reg      <= 1'b0;
               end
         end
         // sub-sequent address/data phases of burst write cycle
         AHM_SEQWR:                 // target is ready to accept data
               if(hready_i & hresp_i == OKAY) begin
                  if(htrans_o == BUSY) begin
                        hburst_o          <= INCR;
                     if(hgrant_i) begin
                        ahb_master_state    <= AHM_NSEQWR;
                     end
                     else begin
                        ahb_master_state    <= AHM_BREQ;
                     end
                  end
                  else if(htrans_o == IDLE) begin
                     ahb_master_state    <= AHM_GOIDLE;
                     // read the address fifo as it is last data phase
                     // so that application can strobe new cycle if any
                     ahm_busreq_reg      <= 1'b0;
                  end
				// Finish cycle when last word is written
                  else if(lastbrstwr) begin
                     ahm_busreq_reg      <= 1'b0;
                     ahb_master_state    <= AHM_LASTWR;
                  end  
                  // grant lost while waiting for transfer to finish
                  else if(~hgrant_i) begin
                     ahb_master_state    <= AHM_LASTWR;
                  end
			   end
               else if(~hready_i & (hresp_i == RETRY | hresp_i == SPLIT) ) begin
                  ahb_master_state    <= AHM_BREQ;
                  ahm_busreq_reg      <= 1'b1;
 //                 latch_prevaddr      <= 1'b1;
               end
               // error indicated on AHB
               // in current design it is unrecoverable
               // system needs to be reset
               else if(~hready_i & hresp_i == ERROR) begin
                  ahb_master_state    <= AHM_IDLE;
                  ahm_busreq_reg      <= 1'b0;
               end
         // last data phase of write transfer because of lost ownership
         // of address bus(Grant lost)
         // once current data phase completes(successful or not(retry/split))
         // master re-arbitrates and resumes pending cycle starting with
         // non-sequential
         AHM_LASTWR:  begin
               // target is ready to accept data
               if(hready_i & hresp_i == OKAY) begin
                  // if the current data is last data from current burst
                  // goto idle, emptying the address fifo
                  if(burstwrflag_last_n) begin
                     ahb_master_state    <= AHM_GOIDLE;
                     // read the address fifo as it is last data phase
                     // so that application can strobe new cycle if any
                     ahm_busreq_reg      <= 1'b0;
                  end
                  else begin
                     ahm_busreq_reg      <= 1'b1;
                     ahb_master_state    <= AHM_BREQ;
                  end
               end

               else if(~hready_i & (hresp_i == RETRY | hresp_i == SPLIT) ) begin
                  // assert appropriate flag to be used to generate
                  // hburst signal in retried transaction
                  // intended transfer would be complete(last data phase)
                  // if it was not retried(so only one more data left)
                  ahm_busreq_reg      <= 1'b1;
                  ahb_master_state    <= AHM_BREQ;
//                  latch_prevaddr      <= 1'b1;
               end
               // error indicated on AHB
               // in current design it is unrecoverable
               // system needs to be reset
               else if(~hready_i & hresp_i == ERROR) begin
                  ahb_master_state    <= AHM_IDLE;
                  ahm_busreq_reg      <= 1'b0;
               end
         end
         // master re-arbitrates as it lost grant in the middle of transfer
         // it waits until data fifos are available
         AHM_RETRY:  begin
//               latch_prevaddr         <= 1'b0;
                  ahm_busreq_reg      <= 1'b1;
                  ahb_master_state    <= AHM_BREQ;
         end
         // this state provides time to read address fifo before
         // entering idle state
         AHM_GOIDLE:  begin
               ahb_master_state    <= AHM_IDLE;
         end
      endcase
   end
end

// AHB write burst flag latching
always @(posedge hclk or posedge hreset)
begin
   if(hreset) begin
      burstwrflag_last_n  <= 1'b1;
   end
   else begin //bug fix - illusion of last phase in the burst 
      if(pop | (ahb_master_state == AHM_IDLE)) begin
         burstwrflag_last_n  <= (word_count == 5'b00001);
      end
   end
end

// latching state 
always @(posedge hclk or posedge hreset)
begin
   if(hreset) begin
      state_prev_clk      <= AHM_IDLE;
   end
   else begin
      if(hready_i) begin
         state_prev_clk      <= ahb_master_state;
      end
   end
end

// address generation
always @(posedge hclk or posedge hreset)
begin
   if(hreset) begin
      haddr_reg[29:0]      <= 30'h0000_0000;
      haddr_prev[29:0]     <= 30'h0000_0000;
   end
   else if(latch_addr && rd_req) begin
         haddr_reg[29:0]      <= src_addr[31:2]; 
         haddr_prev[29:0]     <= src_addr[31:2];
   end
   else if(latch_addr && wr_req) begin
         haddr_reg[29:0]      <= dst_addr[31:2]; 
         haddr_prev[29:0]     <= dst_addr[31:2]; 
   end
   else begin
        if( ahb_master_state == AHM_NSEQWR |
             ahb_master_state == AHM_SEQWR |
             ahb_master_state == AHM_NSEQRD | 
             ahb_master_state == AHM_SEQRD) begin
            if(hready_i & hresp_i == OKAY & htrans_o != BUSY ) begin 
               haddr_reg[29:0]      <= nextaddr[29:0];
               haddr_prev[29:0]     <= haddr_o[31:2];
            end
         end
   end
end
// address generation
always @(posedge hclk or posedge hreset)
begin
   if(hreset) begin
         word_count			  <= 5'b00000; 
   end
   else if(latch_addr && rd_req) begin
         word_count			  <= block_size; 
   end
   else if(latch_addr && wr_req) begin
         word_count			  <= block_size; 
   end
   else if (push | pop) begin
         word_count			  <= word_count - 1; 
   end
end
// Final address that gets onto AHB for Read/Write transfers
assign haddr_o[31:0]    =  {haddr_reg[29:0], 2'b00};

// address of next transfer used by address incrementer
assign nextaddr[29:0]  = haddr_reg[29:0] + 1;

assign #1 pop = (ahb_master_state == AHM_SEQWR | ahb_master_state == AHM_NSEQWR)
						&& hready_i && (hresp_i == OKAY);

// DMA Tx fifo write strobe logic
always @(rddf_wren or hready_i or hresp_i)
begin
   if(hready_i == 1'b1 & hresp_i == OKAY) begin
      if(rddf_wren) begin
         push = 1'b1;
      end
      else begin
         push = 1'b0;
      end
   end
   else begin
      push = 1'b0;
   end
end	 

// HTRANS generation logic
// input signal dependencies removed to avoid combinitorial path
// thru the core input signals
// Fix_041601_Rev1.0b_10
//always @(ahb_master_state or hsize_chg or burstwrflag_last_n or
//         busreq_prev or hready_i or hresp_i
//        )
always @(ahb_master_state or busreq_prev)
begin
   case (ahb_master_state)
      AHM_SEQWR : begin
               htrans_o = SEQ;
      end
      AHM_NSEQWR, AHM_NSEQRD : begin
         htrans_o = NONSEQ;
      end
      AHM_SEQRD : begin
         // input signal dependencies removed to avoid combinitorial path
         // thru the core input signals
         // Fix_041601_Rev1.0b_10
         //if(hready_i == 1'b1 & hresp_i == OKAY) begin
            if(~busreq_prev) begin
               htrans_o = IDLE;
            end
            else begin
               htrans_o = SEQ;
            end
        end
      default : begin
         htrans_o = IDLE;
      end
   endcase
end

// removing bus request signal at the beginning of last data phase
// of SEQWR
// input signal dependencies removed to avoid combinitorial path
// thru the core input signals
// Fix_041601_Rev1.0b_10
//always @(ahb_master_state or ai_wrdfrd_n or burstwrflag_n or
//         rddf_second_last_n or htrans_o or
//         hready_i or hresp_i or pgbndry)
always @(ahb_master_state or htrans_o)
begin
   if(ahb_master_state == AHM_SEQWR) begin
      if( htrans_o == IDLE ) begin
         busreq_comb = 1'b0;
      end
      else begin
         busreq_comb = 1'b1;
      end
   end
   else if(ahb_master_state == AHM_SEQRD) begin
      // input signal dependencies removed to avoid combinitorial path
      // thru the core input signals
      // Fix_041601_Rev1.0b_10
      //if(hready_i == 1'b1 & hresp_i == OKAY) begin
         if(htrans_o == IDLE) begin
            busreq_comb = 1'b0;
         end
         else begin
            busreq_comb = 1'b1;
         end
   end
   else begin
      busreq_comb = 1'b1;
   end
end


// final AHB access request signal to arbiter
assign hbusreq_o = ahm_busreq_reg;

// AHB write data generation
always @(posedge hclk or posedge hreset)
begin
   if(hreset) begin
      hwdata_o[31:0]        <= 32'h0000_0000;
   end
   else if(pop) begin
         hwdata_o[31:0]     <= datain[31:0];
   end
end

assign lastbrstrd   = push && (word_count == 5'b00010);
assign lastbrstwr   = pop && (word_count == 5'b00001);

// delayed version of hbusreq_o
// used in htrans_o generation logic
always @(posedge hclk or posedge hreset)
begin
   if(hreset)
      busreq_prev <= 1'b0;
   else
      busreq_prev <= hbusreq_o;
end

endmodule

⌨️ 快捷键说明

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