📄 ahb_master.v
字号:
// 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 + -