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

📄 ahbmst.v

📁 appnote65_quickmips_ahb_interface_design_example AHB接口设计
💻 V
📖 第 1 页 / 共 2 页
字号:
		//	needs to be screened		// if INCR then stop at 1Kb boundary		if ((burst_mod == INCR) && (addr_boundary(cur_addr, size) == 1'b1)) begin			// at the boundary, change to SINGLE			hburst_out <= SINGLE;		// if only one more data beat then change to SINGLE		end else if (cur_count == count-1) begin			hburst_out <= SINGLE;		// if INCR4/8/16 but has partially transferred some data, change to INCR		// the assumption is that INCR won't cross 1Kb boundary which has already been checked		end else if (((burst_mod == INCR4) || (burst_mod == INCR8) || (burst_mod == INCR16))				&& (cur_count != 0)) begin			hburst_out <= INCR;		// if WRAP4/8/16 but has partially transferred some data, change to INCR/SINGLE		end else if (((burst_mod == WRAP4) || (burst_mod == WRAP8) || (burst_mod == WRAP16))				&& (cur_count != 0)) begin			// use original addr to calculate			hburst_out <= SINGLE;		end else			hburst_out <= burst_mod;		htrans_out <= NONSEQ;		if (rn_w)			// put data out to hwdata_out			hwdata_out <= put_out_data(size);		// wait until granted and hready_in high (wait at least one clock)		@(posedge hclk);		while (~hgrant_in | ~hready_in) @(posedge hclk);		// first addr phase is out, might be extended by hready_in low (wait at least one clock)		// decide if time to lower hbusreq_out		if (hburst_out == SINGLE)			// current is last addresss phase, remove request			// SINGLE transfers are the only possibility to remove request			//	in the first address phase			hbusreq_out <= LOW;		@(posedge hclk);		while (~hready_in) @(posedge hclk);		// first addr phase complete		// inner loop over the data phases of the AHB transaction		// each round is a data phase (and an address phases too except the last one)		// detect end-of-transfer conditions		// either lose grant, or last data phase completed (hready_i high)		//while (hgrant_in && ~last_dphase) begin		while (~last_dphase) begin			// update address while saving the old one			old_addr = cur_addr;			cur_addr = update_addr(cur_addr, burst_mod, size);			// update address phase signals			// check if already in last data phase			// hburst_out is checked in case the first addr is already at the boundary			//	but there are more data to be transferred			// if cur_count=count-1 then last data to be transferred			// next_last_dphase means address was at the boundary			//	in the previous addr phase and the current data phase			if ((hburst_out == SINGLE) || (cur_count == count-1) || next_last_dphase || ~hgrant_in) begin				// already in last data phase, end of current transfer				last_dphase = 1'b1;				hbusreq_out <= LOW;				htrans_out <= IDLE;			end else begin				// more data phases to come				haddr_out <= cur_addr;				htrans_out <= SEQ;				// hwdata_o updated after seeing hready_i high				// decide whether to remove request				if (cur_count == count-2)					hbusreq_out <= LOW;			end			// mark the current address as the last one in the burst			if (addr_boundary(cur_addr, size)) begin				// next data phase is the last one				next_last_dphase = 1'b1;				// remove request since already in the last address phase				hbusreq_out <= LOW;			end			// wait for target response			@(posedge hclk);			// skip wait states			while (~hready_in && (hresp_in == OKAY)) @(posedge hclk);			if (hresp_in != OKAY) begin				// 2-cycle response, last data phase				last_dphase = 1'b1;				// reverse the address				cur_addr = old_addr;				// remove the current address phase				htrans_out <= IDLE;				hbusreq_out <= LOW;				if (hresp_in == ERROR) begin					// ERROR response, no retry					error_rcvd = 1'b1;					$display("Time = %t", $time);					$display("Error: An error response has been received at address %h", cur_addr);				end else					retry_rcvd = 1'b1;				// make sure target is following the spec				if (hready_in)					$display("Error: Target is not doing 2-cycle response properly.");				@(posedge hclk);				if (~hready_in)					$display("Error: Target is not doing 2-cycle response properly.");				// delay for some time before retrying				if (hresp_in != ERROR)					repeat (DLY_B4_RETRY) @(posedge hclk);			end else begin				// normal completion of current data phase				// process read data if read				if (~rn_w)					process_read_data(size, old_addr[1:0], result_thistime);				// collect pass/fail status, result low/fail makes pass_failn low/fail				pass_failn = pass_failn & result_thistime;				// increment current counter				cur_count = cur_count + 32'h1;				// update hwdata if not last data phase				if (~last_dphase & rn_w)					// put data out to hwdata_out					hwdata_out <= put_out_data(size);			end		end	// while, inner loop	end	// while, outer loopendendtask // ahb_transfer// task to process read data// this must be called after seeing hready_in high and hresp_in == OKAYtask process_read_data;input [2:0] size;input [1:0] addr;// result is high for comparison pass and low for failureoutput result;reg result0, result1, result2, result3;begin	result0 = 1'b1;	result1 = 1'b1;	result2 = 1'b1;	result3 = 1'b1;	result = 1'b1;	if (size == BUS_8) begin		// only get one byte, decide which byte lane from addr		if (addr[1:0] == 2'b00)			comp_store8(2'b00, hrdata_in[7:0], result0);		else if (addr[1:0] == 2'b01)			comp_store8(2'b00, hrdata_in[15:8], result0);		else if (addr[1:0] == 2'b10)			comp_store8(2'b00, hrdata_in[23:16], result0);		else //if (addr[1:0] == 2'b11)			comp_store8(2'b00, hrdata_in[31:24], result0);	end else if (size == BUS_16) begin		// get two bytes		if (addr[1] == 1'b0) begin			comp_store8(2'b01, hrdata_in[15:8], result0);			comp_store8(2'b00, hrdata_in[7:0], result1);		end else begin //if (addr[1] == 1'b1) begin			comp_store8(2'b01, hrdata_in[31:24], result0);			comp_store8(2'b00, hrdata_in[23:16], result1);		end	end else begin //if (size == BUS_32) begin		// get all bytes		comp_store8(2'b11, hrdata_in[31:24], result0);		comp_store8(2'b10, hrdata_in[23:16], result1);		comp_store8(2'b01, hrdata_in[15:8], result2);		comp_store8(2'b00, hrdata_in[7:0], result3);	end	if ((comp_rdata_reg) & (~result0 | ~result1 | ~result2 | ~result3)) begin		result = 1'b0;	endendendtask // process_read_data// task to compare/store a bytetask comp_store8;input [1:0] cur_pointer_offset;input [7:0] hrdata_in_byte;// result is high for comparison pass and low for failureoutput result;reg result;begin	result = 1'b1;	// compare data	if ((comp_rdata_reg) && (data_array[cur_pointer + cur_pointer_offset] != hrdata_in_byte)) begin		// compare failure, report		result = 1'b0;		$display("Time = %t", $time);		// need to refine this address		$display("Error: Data does not match at addr %h. Expected %h and received %h.",			old_addr, data_array[cur_pointer + cur_pointer_offset], hrdata_in_byte);	end	if (store_rdata_reg)		// store data		data_array[cur_pointer + cur_pointer_offset] = hrdata_in_byte;endendtask // comp_store8function addr_boundary;input [31:0] addr;input [2:0] size;begin	if (((size == BUS_8) && (addr[9:0] == 10'h3FF)) ||	    ((size == BUS_16) && (addr[9:1] == 9'h1FF)) ||	    ((size == BUS_32) && (addr[9:2] == 8'hFF)))    		addr_boundary = 1'b1;	else		addr_boundary = 1'b0;endendfunctionfunction [31:0] put_out_data;input [2:0] size;begin	if (size == BUS_8) begin		// put out the same 8-bit data on all 4 byte lanes		put_out_data[31:24] = data_array[cur_count];		put_out_data[23:16] = data_array[cur_count];		put_out_data[15:8] = data_array[cur_count];		put_out_data[7:0] = data_array[cur_count];	end else if (size == BUS_16) begin		// repeat 16-bit data		put_out_data[31:24] = data_array[(cur_count<<1)+1];		put_out_data[23:16] = data_array[(cur_count<<1)];		put_out_data[15:8] = data_array[(cur_count<<1)+1];		put_out_data[7:0] = data_array[(cur_count<<1)];	end else begin		// size == BUS_32		// put out all 4 bytes		put_out_data[31:24] = data_array[(cur_count<<2)+3];		put_out_data[23:16] = data_array[(cur_count<<2)+2];		put_out_data[15:8] = data_array[(cur_count<<2)+1];		put_out_data[7:0] = data_array[(cur_count<<2)];	endendendfunctionfunction [31:0] update_addr;input [31:0] addr;input [2:0] burst;input [2:0] size;reg [5:0] addr_inc;begin	// if SINGLE or INCR* just increment address according to size	if ((burst == SINGLE) || (burst == INCR) || (burst == INCR4) ||	    (burst == INCR8) || (burst == INCR16)) begin		if (size == BUS_8) update_addr = addr + 32'h1;		if (size == BUS_16) update_addr = addr + 32'h2;		if (size == BUS_32) update_addr = addr + 32'h4;	end else if (burst == WRAP4) begin		if (size == BUS_8) begin			addr_inc = addr[5:0] + 6'h1;			// only the lowest 2 bits will increment			update_addr = {addr[31:2], addr_inc[1:0]};		end else if (size == BUS_16) begin			addr_inc = addr[5:0] + 6'h2;			// only the lowest 3 bits will increment			update_addr = {addr[31:3], addr_inc[2:0]};		end else if (size == BUS_32) begin			addr_inc = addr[5:0] + 6'h4;			// only the lowest 4 bits will increment			update_addr = {addr[31:4], addr_inc[3:0]};		end	end else if (burst == WRAP8) begin		if (size == BUS_8) begin			addr_inc = addr[5:0] + 6'h1;			// only the lowest 3 bits will increment			update_addr = {addr[31:3], addr_inc[2:0]};		end else if (size == BUS_16) begin			addr_inc = addr[5:0] + 6'h2;			// only the lowest 4 bits will increment			update_addr = {addr[31:4], addr_inc[3:0]};		end else if (size == BUS_32) begin			addr_inc = addr[5:0] + 6'h4;			// only the lowest 5 bits will increment			update_addr = {addr[31:5], addr_inc[4:0]};		end	end else begin		// burst == WRAP16		if (size == BUS_8) begin			addr_inc = addr[5:0] + 6'h1;			// only the lowest 4 bits will increment			update_addr = {addr[31:4], addr_inc[3:0]};		end else if (size == BUS_16) begin			addr_inc = addr[5:0] + 6'h2;			// only the lowest 5 bits will increment			update_addr = {addr[31:5], addr_inc[4:0]};		end else if (size == BUS_32) begin			addr_inc = addr[5:0] + 6'h4;			// only the lowest 6 bits will increment			update_addr = {addr[31:6], addr_inc[5:0]};		end	endendendfunctionendmodule

⌨️ 快捷键说明

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