📄 ahbmst.v
字号:
// this is the AHB master modelmodule ahbmst ( hclk, hresetn, haddr_o, htrans_o, hwrite_o, hburst_o, hsize_o, hwdata_o, hready_i, hresp_i, hrdata_i, hbusreq_o, hgrant_i);input hclk;input hresetn;output [31:0] haddr_o;output [1:0] htrans_o;output hwrite_o;output [2:0] hburst_o;output [2:0] hsize_o;output [31:0] hwdata_o;input hready_i;input [1:0] hresp_i;input [31:0] hrdata_i;output hbusreq_o;input hgrant_i;`include "ahb_def.v"reg [31:0] haddr_out;reg [1:0] htrans_out;reg hwrite_out;reg [2:0] hburst_out;reg [2:0] hsize_out;reg [31:0] hwdata_out;reg hbusreq_out;assign #OUT_DLY haddr_o = haddr_out;assign #OUT_DLY htrans_o = htrans_out;assign #OUT_DLY hwrite_o = hwrite_out;assign #OUT_DLY hburst_o = hburst_out;assign #OUT_DLY hsize_o = hsize_out;assign #OUT_DLY hwdata_o = hwdata_out;assign #OUT_DLY hbusreq_o = hbusreq_out;wire #IN_DLY hready_in = hready_i;wire [1:0] #IN_DLY hresp_in = hresp_i;wire [31:0] #IN_DLY hrdata_in = hrdata_i;wire #IN_DLY hgrant_in = hgrant_i;// this is the data buffer// it is 8-bit wide to accomodate 8/16-bit transfersreg [7:0] data_array [AHBMST_BUF_DEPTH-1:0];// this is the wait states bufferreg [MAXWS-1:0] wait_states [AHBMST_BUF_DEPTH-1:0];reg [31:0] cur_count;reg [2:0] burst_mod;reg [31:0] cur_addr;reg last_dphase;reg error_rcvd;reg retry_rcvd;reg [31:0] old_addr;reg latch_data;reg next_last_dphase;reg store_rdata_reg;reg comp_rdata_reg;// generate pointer into the data array based on size and cur_countwire [31:0] cur_pointer = (hsize_out == BUS_8) ? cur_count : ((hsize_out == BUS_16) ? cur_count<<1 : cur_count<<2);initial begin haddr_out <= DEFAULT_ADDR; htrans_out <= IDLE; hwrite_out <= READ; hsize_out <= DEFAULT_SIZE; hburst_out <= SINGLE; hwdata_out <= DEFAULT_WDATA; hbusreq_out <= LOW; cur_addr = 32'h0; old_addr = 32'h0; last_dphase = 1'b0; next_last_dphase = 1'b0; error_rcvd = 1'b0; retry_rcvd = 1'b0; cur_count = 32'h0; burst_mod = SINGLE; latch_data = 1'b0; comp_rdata_reg = 1'b0; store_rdata_reg = 1'b0;end// ahb_transfer(addr,size,burst,rn_w,count,store_rdata,comp_rdata,pass_failn)// addr is the AHB address// size is the transfer size// burst is the burst type// rn_w is read (low) or write (high)// count is the number of beats (data phases), not the # of bytes or words// store_rdata is whether to store data read in data_array// comp_rdata is whether to compare read data with data_array and report error when data compare fails// normally if you want to store data then no compare, if you want to compare then no store,// but you can also want no store and no compare (just to test the flow)// pass_failn is the return value of whether data compare fails// data is read from data_array during write and stored in data_array during read// wait states are stored in wait_states arraytask ahb_transfer;input [31:0] addr;input [2:0] size;input [2:0] burst;input rn_w;input [AHBMST_BUF_SIZE-1:0] count;input store_rdata;input comp_rdata;output pass_failn;reg result_thistime;begin // remember some of the attributes store_rdata_reg <= store_rdata; comp_rdata_reg <= comp_rdata; // assume data comparison passes until it fails pass_failn = 1'b1; burst_mod = burst; // make sure HRESETn is high if (~hresetn) begin $display("Warning: AHB transfer requested at %t when hresetn is active, delayed", $time); @(posedge hresetn); repeat (10) @(posedge hclk); end // sanity checks // size must be 8/16/32-bit if ((size != BUS_8) && (size != BUS_16) && (size != BUS_32)) begin $display("Time = %t", $time); $display("Error: Only 8/16/32-bit transfer sizes are allowed."); repeat (10) @(posedge hclk); $finish; end // check if address is aligned with the transfer size if ((size == BUS_16) && (addr[0] != 1'b0) || (size == BUS_32) && (addr[1:0] != 2'b00)) begin $display("Time = %t", $time); $display("Error: Address must be aligned with the transfer size."); $display("\tFor 16-bit transfers, lowest bit of address must be 1'b0."); $display("\tFor 32-bit transfers, lowest two bits of address must be 2'b00."); repeat (10) @(posedge hclk); $finish; end // count cannot be 0 if (count == 0) begin $display("Time = %t", $time); $display("Error: Transfer count must not be 0."); repeat (10) @(posedge hclk); $finish; end // check if count matches the burst type if ((burst == SINGLE) && (count != 1)) begin $display("Time = %t", $time); $display("Warning: SINGLE transfer must have a count of 1."); $display("\tChange burst type to INCR"); burst_mod = INCR; end if (((burst == INCR4) || (burst == WRAP4)) && (count != 4)) begin $display("Time = %t", $time); $display("Warning: INCR4/WRAP4 transfer must have a count of 4."); $display("\tChange burst type to INCR"); burst_mod = INCR; end if (((burst == INCR8) || (burst == WRAP8)) && (count != 8)) begin $display("Time = %t", $time); $display("Warning: INCR8/WRAP8 transfer must have a count of 8."); $display("\tChange burst type to INCR"); burst_mod = INCR; end if (((burst == INCR16) || (burst == WRAP16)) && (count != 16)) begin $display("Time = %t", $time); $display("Warning: INCR16/WRAP16 transfer must have a count of 16."); $display("\tChange burst type to INCR"); burst_mod = INCR; end // if INCR4/8/16, must not cross 1KB boundary // WRAP8/16/32 transfers won't cross 1KB boundary if (burst_mod == INCR4) begin if (size == BUS_8) begin if ((addr[9:2] == 8'hFF) && (addr[1:0] != 2'h0)) begin $display("Time = %t", $time); $display("Warning: 8-bit INCR4 transfer from address %h will cross 1KB boundary.", addr); $display("\tChange burst type to INCR"); burst_mod = INCR; end end else if (size == BUS_16) begin if ((addr[9:3] == 7'h7F) && (addr[2:0] != 3'h0)) begin $display("Time = %t", $time); $display("Warning: 16-bit INCR4 transfer from address %h will cross 1KB boundary.", addr); $display("\tChange burst type to INCR"); burst_mod = INCR; end end else begin // size is BUS_32 if ((addr[9:4] == 6'h3F) && (addr[3:0] != 4'h0)) begin $display("Time = %t", $time); $display("Warning: 32-bit INCR4 transfer from address %h will cross 1KB boundary.", addr); $display("\tChange burst type to INCR"); burst_mod = INCR; end end end else if (burst_mod == INCR8) begin if (size == BUS_8) begin if ((addr[9:3] == 8'h7F) && (addr[2:0] != 3'h0)) begin $display("Time = %t", $time); $display("Warning: 8-bit INCR8 transfer from address %h will cross 1KB boundary.", addr); $display("\tChange burst type to INCR"); burst_mod = INCR; end end else if (size == BUS_16) begin if ((addr[9:4] == 6'h3F) && (addr[3:0] != 4'h0)) begin $display("Time = %t", $time); $display("Warning: 16-bit INCR8 transfer from address %h will cross 1KB boundary.", addr); $display("\tChange burst type to INCR"); burst_mod = INCR; end end else begin // size is BUS_32 if ((addr[9:5] == 5'h1F) && (addr[4:0] != 5'h0)) begin $display("Time = %t", $time); $display("Warning: 32-bit INCR8 transfer from address %h will cross 1KB boundary.", addr); $display("\tChange burst type to INCR"); burst_mod = INCR; end end end else if (burst_mod == INCR16) begin if (size == BUS_8) begin if ((addr[9:4] == 6'h3F) && (addr[3:0] != 4'h0)) begin $display("Time = %t", $time); $display("Warning: 8-bit INCR16 transfer from address %h will cross 1KB boundary.", addr); $display("\tChange burst type to INCR"); burst_mod = INCR; end end else if (size == BUS_16) begin if ((addr[9:5] == 5'h1F) && (addr[4:0] != 5'h0)) begin $display("Time = %t", $time); $display("Warning: 16-bit INCR16 transfer from address %h will cross 1KB boundary.", addr); $display("\tChange burst type to INCR"); burst_mod = INCR; end end else begin // size is BUS_32 if ((addr[9:6] == 4'hF) && (addr[5:0] != 6'h0)) begin $display("Time = %t", $time); $display("Warning: 32-bit INCR16 transfer from address %h will cross 1KB boundary.", addr); $display("\tChange burst type to INCR"); burst_mod = INCR; end end end // current and old address register cur_addr = addr; old_addr = cur_addr; // reset counter to count data beats transferred cur_count = 32'h0; // reset retry/error flags retry_rcvd = 1'b0; error_rcvd = 1'b0; // reset last data phase flags last_dphase = 1'b0; next_last_dphase = 1'b0; // outside loop over the entire data transfers until all data transferred // each round is an AHB transaction // either all data transferred or error received makes it quit while ((cur_count != count) && ~error_rcvd) begin last_dphase = 1'b0; next_last_dphase = 1'b0; // start requesting bus and driving out all signals hbusreq_out <= HIGH; haddr_out <= cur_addr; hwrite_out <= rn_w; hsize_out <= size; // the assignment of hburst_out needs more scrutiny // once a transfer is force to split at the 1Kbyte boundary or // is split/retried by the slave, the subsequent hburst_out
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -