1
0
mirror of https://github.com/pConst/basic_verilog.git synced 2025-01-14 06:42:54 +08:00

Added Avalon master templates

This commit is contained in:
Konstantin Pavlov 2019-05-24 14:03:34 +03:00
parent 5bde0a502e
commit 7399deb17d
7 changed files with 1501 additions and 0 deletions

View File

@ -0,0 +1,256 @@
/*
Legal Notice: (C)2007 Altera Corporation. All rights reserved. Your
use of Altera Corporation's design tools, logic functions and other
software and tools, and its AMPP partner logic functions, and any
output files any of the foregoing (including device programming or
simulation files), and any associated documentation or information are
expressly subject to the terms and conditions of the Altera Program
License Subscription Agreement or other applicable license agreement,
including, without limitation, that your use is for the sole purpose
of programming logic devices manufactured by Altera and sold by Altera
or its authorized distributors. Please refer to the applicable
agreement for further details.
*/
/*
Author: JCJB
Date: 11/04/2007
This bursting read master is passed a word aligned address, length in bytes,
and a 'go' bit. The master will continue to post full length bursts until
the length register reaches a value less than a full burst. A single final
burst is then posted and when all the reads return the done bit will be asserted.
To use this master you must simply drive the control signals into this block,
and also read the data from the exposed read FIFO. To read from the exposed FIFO
use the 'user_read_buffer' signal to pop data from the FIFO 'user_buffer_data'.
The signal 'user_data_available' is asserted whenever data is available from the
exposed FIFO.
*/
// altera message_off 10230
module burst_read_master (
clk,
reset,
// control inputs and outputs
control_fixed_location,
control_read_base,
control_read_length,
control_go,
control_done,
control_early_done,
// user logic inputs and outputs
user_read_buffer,
user_buffer_data,
user_data_available,
// master inputs and outputs
master_address,
master_read,
master_byteenable,
master_readdata,
master_readdatavalid,
master_burstcount,
master_waitrequest
);
parameter DATAWIDTH = 32;
parameter MAXBURSTCOUNT = 4;
parameter BURSTCOUNTWIDTH = 3;
parameter BYTEENABLEWIDTH = 4;
parameter ADDRESSWIDTH = 32;
parameter FIFODEPTH = 32;
parameter FIFODEPTH_LOG2 = 5;
parameter FIFOUSEMEMORY = 1; // set to 0 to use LEs instead
input clk;
input reset;
// control inputs and outputs
input control_fixed_location;
input [ADDRESSWIDTH-1:0] control_read_base;
input [ADDRESSWIDTH-1:0] control_read_length;
input control_go;
output wire control_done;
output wire control_early_done; // don't use this unless you know what you are doing, it's going to fire when the last read is posted, not when the last data returns!
// user logic inputs and outputs
input user_read_buffer;
output wire [DATAWIDTH-1:0] user_buffer_data;
output wire user_data_available;
// master inputs and outputs
input master_waitrequest;
input master_readdatavalid;
input [DATAWIDTH-1:0] master_readdata;
output wire [ADDRESSWIDTH-1:0] master_address;
output wire master_read;
output wire [BYTEENABLEWIDTH-1:0] master_byteenable;
output wire [BURSTCOUNTWIDTH-1:0] master_burstcount;
// internal control signals
reg control_fixed_location_d1;
wire fifo_empty;
reg [ADDRESSWIDTH-1:0] address;
reg [ADDRESSWIDTH-1:0] length;
reg [FIFODEPTH_LOG2-1:0] reads_pending;
wire increment_address;
wire [BURSTCOUNTWIDTH-1:0] burst_count;
wire [BURSTCOUNTWIDTH-1:0] first_short_burst_count;
wire first_short_burst_enable;
wire [BURSTCOUNTWIDTH-1:0] final_short_burst_count;
wire final_short_burst_enable;
wire [BURSTCOUNTWIDTH-1:0] burst_boundary_word_address;
reg burst_begin;
wire too_many_reads_pending;
wire [FIFODEPTH_LOG2-1:0] fifo_used;
// registering the control_fixed_location bit
always @ (posedge clk or posedge reset)
begin
if (reset == 1)
begin
control_fixed_location_d1 <= 0;
end
else
begin
if (control_go == 1)
begin
control_fixed_location_d1 <= control_fixed_location;
end
end
end
// master address logic
always @ (posedge clk or posedge reset)
begin
if (reset == 1)
begin
address <= 0;
end
else
begin
if(control_go == 1)
begin
address <= control_read_base;
end
else if((increment_address == 1) & (control_fixed_location_d1 == 0))
begin
address <= address + (burst_count * BYTEENABLEWIDTH); // always performing word size accesses, increment by the burst count presented
end
end
end
// master length logic
always @ (posedge clk or posedge reset)
begin
if (reset == 1)
begin
length <= 0;
end
else
begin
if(control_go == 1)
begin
length <= control_read_length;
end
else if(increment_address == 1)
begin
length <= length - (burst_count * BYTEENABLEWIDTH); // always performing word size accesses, decrement by the burst count presented
end
end
end
// controlled signals going to the master/control ports
assign master_address = address;
assign master_byteenable = -1; // all ones, always performing word size accesses
assign master_burstcount = burst_count;
assign control_done = (length == 0) & (reads_pending == 0); // need to make sure that the reads have returned before firing the done bit
assign control_early_done = (length == 0); // advanced feature, you should use 'control_done' if you need all the reads to return first
assign master_read = (too_many_reads_pending == 0) & (length != 0);
assign burst_boundary_word_address = ((address / BYTEENABLEWIDTH) & (MAXBURSTCOUNT - 1));
assign first_short_burst_enable = (burst_boundary_word_address != 0);
assign final_short_burst_enable = (length < (MAXBURSTCOUNT * BYTEENABLEWIDTH));
assign first_short_burst_count = ((burst_boundary_word_address & 1'b1) == 1'b1)? 1 : // if the burst boundary isn't a multiple of 2 then must post a burst of 1 to get to a multiple of 2 for the next burst
(((MAXBURSTCOUNT - burst_boundary_word_address) < (length / BYTEENABLEWIDTH))?
(MAXBURSTCOUNT - burst_boundary_word_address) : (length / BYTEENABLEWIDTH));
assign final_short_burst_count = (length / BYTEENABLEWIDTH);
assign burst_count = (first_short_burst_enable == 1)? first_short_burst_count : // this will get the transfer back on a burst boundary,
(final_short_burst_enable == 1)? final_short_burst_count : MAXBURSTCOUNT;
assign increment_address = (too_many_reads_pending == 0) & (master_waitrequest == 0) & (length != 0);
assign too_many_reads_pending = (reads_pending + fifo_used) >= (FIFODEPTH - MAXBURSTCOUNT - 4); // make sure there are fewer reads posted than room in the FIFO
// tracking FIFO
always @ (posedge clk or posedge reset)
begin
if (reset == 1)
begin
reads_pending <= 0;
end
else
begin
if(increment_address == 1)
begin
if(master_readdatavalid == 0)
begin
reads_pending <= reads_pending + burst_count;
end
else
begin
reads_pending <= reads_pending + burst_count - 1; // a burst read was posted, but a word returned
end
end
else
begin
if(master_readdatavalid == 0)
begin
reads_pending <= reads_pending; // burst read was not posted and no read returned
end
else
begin
reads_pending <= reads_pending - 1; // burst read was not posted but a word returned
end
end
end
end
// read data feeding user logic
assign user_data_available = !fifo_empty;
scfifo the_master_to_user_fifo (
.aclr (reset),
.clock (clk),
.data (master_readdata),
.empty (fifo_empty),
.q (user_buffer_data),
.rdreq (user_read_buffer),
.usedw (fifo_used),
.wrreq (master_readdatavalid)
);
defparam the_master_to_user_fifo.lpm_width = DATAWIDTH;
defparam the_master_to_user_fifo.lpm_numwords = FIFODEPTH;
defparam the_master_to_user_fifo.lpm_showahead = "ON";
defparam the_master_to_user_fifo.use_eab = (FIFOUSEMEMORY == 1)? "ON" : "OFF";
defparam the_master_to_user_fifo.add_ram_output_register = "OFF";
defparam the_master_to_user_fifo.underflow_checking = "OFF";
defparam the_master_to_user_fifo.overflow_checking = "OFF";
endmodule

View File

@ -0,0 +1,305 @@
/*
Legal Notice: (C)2007 Altera Corporation. All rights reserved. Your
use of Altera Corporation's design tools, logic functions and other
software and tools, and its AMPP partner logic functions, and any
output files any of the foregoing (including device programming or
simulation files), and any associated documentation or information are
expressly subject to the terms and conditions of the Altera Program
License Subscription Agreement or other applicable license agreement,
including, without limitation, that your use is for the sole purpose
of programming logic devices manufactured by Altera and sold by Altera
or its authorized distributors. Please refer to the applicable
agreement for further details.
*/
/*
Author: JCJB
Date: 11/04/2007
This bursting write master is passed a word aligned address, length in bytes,
and a 'go' bit. The master will continue to post full length bursts until
the length register reaches a value less than a full burst. A single final
burst is then posted when enough data has been buffered and then the done bit
will be asserted.
To use this master you must simply drive the control signals into this block,
and also write the data to the exposed write FIFO. To read from the exposed FIFO
use the 'user_write_buffer' signal to push data into the FIFO 'user_buffer_data'.
The signal 'user_buffer_full' is asserted whenever the exposed buffer is full.
You should not attempt to write data to the exposed FIFO if it is full.
*/
// altera message_off 10230
module burst_write_master (
clk,
reset,
// control inputs and outputs
control_fixed_location,
control_write_base,
control_write_length,
control_go,
control_done,
// user logic inputs and outputs
user_write_buffer,
user_buffer_data,
user_buffer_full,
// master inputs and outputs
master_address,
master_write,
master_byteenable,
master_writedata,
master_burstcount,
master_waitrequest
);
parameter DATAWIDTH = 32;
parameter MAXBURSTCOUNT = 4;
parameter BURSTCOUNTWIDTH = 3;
parameter BYTEENABLEWIDTH = 4;
parameter ADDRESSWIDTH = 32;
parameter FIFODEPTH = 32; // must be at least twice MAXBURSTCOUNT in order to be efficient
parameter FIFODEPTH_LOG2 = 5;
parameter FIFOUSEMEMORY = 1; // set to 0 to use LEs instead
input clk;
input reset;
// control inputs and outputs
input control_fixed_location; // this only makes sense to enable when MAXBURSTCOUNT = 1
input [ADDRESSWIDTH-1:0] control_write_base;
input [ADDRESSWIDTH-1:0] control_write_length;
input control_go;
output wire control_done;
// user logic inputs and outputs
input user_write_buffer;
input [DATAWIDTH-1:0] user_buffer_data;
output wire user_buffer_full;
// master inputs and outputs
input master_waitrequest;
output reg [ADDRESSWIDTH-1:0] master_address;
output wire master_write;
output wire [BYTEENABLEWIDTH-1:0] master_byteenable;
output wire [DATAWIDTH-1:0] master_writedata;
output reg [BURSTCOUNTWIDTH-1:0] master_burstcount;
// internal control signals
reg control_fixed_location_d1;
reg [ADDRESSWIDTH-1:0] length;
wire final_short_burst_enable; // when the length is less than MAXBURSTCOUNT * # of bytes per word (BYTEENABLEWIDTH) (i.e. end of the transfer)
wire final_short_burst_ready; // when there is enough data in the FIFO for the final burst
wire [BURSTCOUNTWIDTH-1:0] burst_boundary_word_address; // represents the word offset within the burst boundary
wire [BURSTCOUNTWIDTH-1:0] first_short_burst_count;
wire [BURSTCOUNTWIDTH-1:0] final_short_burst_count;
wire first_short_burst_enable; // when the transfer doesn't start on a burst boundary
wire first_short_burst_ready; // when there is enough data in the FIFO to get the master back into burst alignment
wire full_burst_ready; // when there is enough data in the FIFO for a full burst
wire increment_address; // this increments the 'address' register when write is asserted and waitrequest is de-asserted
wire burst_begin; // used to register the registers 'burst_address' and 'burst_count_d1' as well as drive the master_address and burst_count muxes
wire read_fifo;
wire [FIFODEPTH_LOG2-1:0] fifo_used; // going to combined used with the full bit
wire [BURSTCOUNTWIDTH-1:0] burst_count; // watermark of the FIFO, it has a latency of 2 cycles
reg [BURSTCOUNTWIDTH-1:0] burst_counter;
reg first_transfer; // need to keep track of the first burst so that we don't incorrectly increment the address
// registering the control_fixed_location bit
always @ (posedge clk or posedge reset)
begin
if (reset == 1)
begin
control_fixed_location_d1 <= 0;
end
else
begin
if (control_go == 1)
begin
control_fixed_location_d1 <= control_fixed_location;
end
end
end
// set when control_go fires, and reset once the first burst starts
always @ (posedge clk or posedge reset)
begin
if (reset == 1)
begin
first_transfer <= 0;
end
else
begin
if (control_go == 1)
begin
first_transfer <= 1;
end
else if (burst_begin == 1)
begin
first_transfer <= 0;
end
end
end
// master address (held constant during burst)
always @ (posedge clk or posedge reset)
begin
if (reset == 1)
begin
master_address <= 0;
end
else
begin
if (control_go == 1)
begin
master_address <= control_write_base;
end
else if ((first_transfer == 0) & (burst_begin == 1) & (control_fixed_location_d1 == 0))
begin
master_address <= master_address + (master_burstcount * BYTEENABLEWIDTH); // we don't want address + BYTEENABLEWIDTH for the first access
end
end
end
// master length logic
always @ (posedge clk or posedge reset)
begin
if (reset == 1)
begin
length <= 0;
end
else
begin
if (control_go == 1)
begin
length <= control_write_length;
end
else if (increment_address == 1)
begin
length <= length - BYTEENABLEWIDTH; // always performing word size accesses
end
end
end
// register the master burstcount (held constant during burst)
always @ (posedge clk or posedge reset)
begin
if (reset == 1)
begin
master_burstcount <= 0;
end
else
begin
if (burst_begin == 1)
begin
master_burstcount <= burst_count;
end
end
end
// burst counter. This is set to the burst count being posted then counts down when each word
// of data goes out. If it reaches 0 (i.e. not reloaded after 1) then the master stalls due to
// a lack of data to post a new burst.
always @ (posedge clk or posedge reset)
begin
if (reset == 1)
begin
burst_counter <= 0;
end
else
begin
if (control_go == 1)
begin
burst_counter <= 0;
end
else if (burst_begin == 1)
begin
burst_counter <= burst_count;
end
else if (increment_address == 1) // decrements each write, burst_counter will only hit 0 if burst begin doesn't fire on the next cycle
begin
burst_counter <= burst_counter - 1;
end
end
end
// burst boundaries are on the master "width * maximum burst count". The burst boundary word address will be used to determine how far off the boundary the transfer starts from.
assign burst_boundary_word_address = ((master_address / BYTEENABLEWIDTH) & (MAXBURSTCOUNT - 1));
// first short burst enable will only be active on the first transfer (if applicable). It will either post the amount of words remaining to reach the end of the burst
// boundary or post the remainder of the transfer whichever is shorter. If the transfer is very short and not aligned on a burst boundary then the same logic as the final short transfer is used
assign first_short_burst_enable = (burst_boundary_word_address != 0) & (first_transfer == 1);
assign first_short_burst_count = ((burst_boundary_word_address & 1'b1) == 1'b1)? 1 : // if the burst boundary isn't a multiple of 2 then must post a burst of 1 to get to a multiple of 2 for the next burst
(((MAXBURSTCOUNT - burst_boundary_word_address) < (length / BYTEENABLEWIDTH))?
(MAXBURSTCOUNT - burst_boundary_word_address) : final_short_burst_count);
assign first_short_burst_ready = (fifo_used > first_short_burst_count) | ((fifo_used == first_short_burst_count) & (burst_counter == 0));
// when there isn't enough data for a full burst at the end of the transfer a short burst is sent out instead
assign final_short_burst_enable = (length < (MAXBURSTCOUNT * BYTEENABLEWIDTH));
assign final_short_burst_count = (length/BYTEENABLEWIDTH);
assign final_short_burst_ready = (fifo_used > final_short_burst_count) | ((fifo_used == final_short_burst_count) & (burst_counter == 0)); // this will add a one cycle stall between bursts, since fifo_used has a cycle of latency, this only affects the last burst
// since the fifo has a latency of 1 we need to make sure we don't under flow
assign full_burst_ready = (fifo_used > MAXBURSTCOUNT) | ((fifo_used == MAXBURSTCOUNT) & (burst_counter == 0)); // when fifo used watermark equals the burst count the statemachine must stall for one cycle, this will make sure that when a burst begins there really is enough data present in the FIFO
assign master_byteenable = -1; // all ones, always performing word size accesses
assign control_done = (length == 0);
assign master_write = (control_done == 0) & (burst_counter != 0); // burst_counter = 0 means the transfer is done, or not enough data in the fifo for a new burst
// fifo controls and the burst_begin responsible for timing most of the circuit, burst_begin starts the writing statemachine
assign burst_begin = (((first_short_burst_enable == 1) & (first_short_burst_ready == 1))
| ((final_short_burst_enable == 1) & (final_short_burst_ready == 1))
| (full_burst_ready == 1))
& (control_done == 0) // since the FIFO can have data before the master starts we need to disable this bit from firing when length = 0
& ((burst_counter == 0) | ((burst_counter == 1) & (master_waitrequest == 0) & (length > (MAXBURSTCOUNT * BYTEENABLEWIDTH)))); // need to make a short final burst doesn't start right after a full burst completes.
assign burst_count = (first_short_burst_enable == 1)? first_short_burst_count : // alignment correction gets priority, if the transfer is short and unaligned this will cover both
(final_short_burst_enable == 1)? final_short_burst_count : MAXBURSTCOUNT;
assign increment_address = (master_write == 1) & (master_waitrequest == 0); // writing is occuring without wait states
assign read_fifo = increment_address;
// write data feed by user logic
scfifo the_user_to_master_fifo (
.aclr (reset),
.usedw (fifo_used),
.clock (clk),
.data (user_buffer_data),
.almost_full (user_buffer_full),
.q (master_writedata),
.rdreq (read_fifo),
.wrreq (user_write_buffer)
);
defparam the_user_to_master_fifo.lpm_width = DATAWIDTH;
defparam the_user_to_master_fifo.lpm_numwords = FIFODEPTH;
defparam the_user_to_master_fifo.lpm_showahead = "ON";
defparam the_user_to_master_fifo.almost_full_value = (FIFODEPTH - 2);
defparam the_user_to_master_fifo.use_eab = (FIFOUSEMEMORY == 1)? "ON" : "OFF";
defparam the_user_to_master_fifo.add_ram_output_register = "OFF"; // makes timing the burst begin single simplier
defparam the_user_to_master_fifo.underflow_checking = "OFF";
defparam the_user_to_master_fifo.overflow_checking = "OFF";
endmodule

View File

@ -0,0 +1,211 @@
/*
This file is a simple top level that will generate one of four types of
Avalon-MM master. As a result all the ports must be declared and it will be
up to the component .tcl file to stub unused signals.
*/
// altera message_off 10034
module custom_master (
clk,
reset,
// control inputs and outputs
control_fixed_location,
control_read_base,
control_read_length,
control_write_base,
control_write_length,
control_go,
control_done,
control_early_done,
// user logic inputs and outputs
user_read_buffer,
user_write_buffer,
user_buffer_input_data,
user_buffer_output_data,
user_data_available,
user_buffer_full,
// master inputs and outputs
master_address,
master_read,
master_write,
master_byteenable,
master_readdata,
master_readdatavalid,
master_writedata,
master_burstcount,
master_waitrequest
);
parameter MASTER_DIRECTION = 0; // 0 for read master, 1 for write master
parameter DATA_WIDTH = 32;
parameter MEMORY_BASED_FIFO = 1; // 0 for LE/ALUT FIFOs, 1 for memory FIFOs (highly recommend 1)
parameter FIFO_DEPTH = 32;
parameter FIFO_DEPTH_LOG2 = 5;
parameter ADDRESS_WIDTH = 32;
parameter BURST_CAPABLE = 0; // 1 to enable burst, 0 to disable it
parameter MAXIMUM_BURST_COUNT = 2;
parameter BURST_COUNT_WIDTH = 2;
input clk;
input reset;
// control inputs and outputs
input control_fixed_location;
input [ADDRESS_WIDTH-1:0] control_read_base; // for read master
input [ADDRESS_WIDTH-1:0] control_read_length; // for read master
input [ADDRESS_WIDTH-1:0] control_write_base; // for write master
input [ADDRESS_WIDTH-1:0] control_write_length; // for write master
input control_go;
output wire control_done;
output wire control_early_done; // for read master
// user logic inputs and outputs
input user_read_buffer; // for read master
input user_write_buffer; // for write master
input [DATA_WIDTH-1:0] user_buffer_input_data; // for write master
output wire [DATA_WIDTH-1:0] user_buffer_output_data; // for read master
output wire user_data_available; // for read master
output wire user_buffer_full; // for write master
// master inputs and outputs
output wire [ADDRESS_WIDTH-1:0] master_address;
output wire master_read; // for read master
output wire master_write; // for write master
output wire [(DATA_WIDTH/8)-1:0] master_byteenable;
input [DATA_WIDTH-1:0] master_readdata; // for read master
input master_readdatavalid; // for read master
output wire [DATA_WIDTH-1:0] master_writedata; // for write master
output wire [BURST_COUNT_WIDTH-1:0] master_burstcount; // for bursting read and write masters
input master_waitrequest;
generate // big generate if statement to select the approprate master depending on the direction and burst parameters
if(MASTER_DIRECTION == 0)
begin
if(BURST_CAPABLE == 1)
begin
burst_read_master a_burst_read_master(
.clk (clk),
.reset (reset),
.control_fixed_location (control_fixed_location),
.control_read_base (control_read_base),
.control_read_length (control_read_length),
.control_go (control_go),
.control_done (control_done),
.control_early_done (control_early_done),
.user_read_buffer (user_read_buffer),
.user_buffer_data (user_buffer_output_data),
.user_data_available (user_data_available),
.master_address (master_address),
.master_read (master_read),
.master_byteenable (master_byteenable),
.master_readdata (master_readdata),
.master_readdatavalid (master_readdatavalid),
.master_burstcount (master_burstcount),
.master_waitrequest (master_waitrequest)
);
defparam a_burst_read_master.DATAWIDTH = DATA_WIDTH;
defparam a_burst_read_master.MAXBURSTCOUNT = MAXIMUM_BURST_COUNT;
defparam a_burst_read_master.BURSTCOUNTWIDTH = BURST_COUNT_WIDTH;
defparam a_burst_read_master.BYTEENABLEWIDTH = DATA_WIDTH/8;
defparam a_burst_read_master.ADDRESSWIDTH = ADDRESS_WIDTH;
defparam a_burst_read_master.FIFODEPTH = FIFO_DEPTH;
defparam a_burst_read_master.FIFODEPTH_LOG2 = FIFO_DEPTH_LOG2;
defparam a_burst_read_master.FIFOUSEMEMORY = MEMORY_BASED_FIFO;
end
else
begin
latency_aware_read_master a_latency_aware_read_master(
.clk (clk),
.reset (reset),
.control_fixed_location (control_fixed_location),
.control_read_base (control_read_base),
.control_read_length (control_read_length),
.control_go (control_go),
.control_done (control_done),
.control_early_done (control_early_done),
.user_read_buffer (user_read_buffer),
.user_buffer_data (user_buffer_output_data),
.user_data_available (user_data_available),
.master_address (master_address),
.master_read (master_read),
.master_byteenable (master_byteenable),
.master_readdata (master_readdata),
.master_readdatavalid (master_readdatavalid),
.master_waitrequest (master_waitrequest)
);
defparam a_latency_aware_read_master.DATAWIDTH = DATA_WIDTH;
defparam a_latency_aware_read_master.BYTEENABLEWIDTH = DATA_WIDTH/8;
defparam a_latency_aware_read_master.ADDRESSWIDTH = ADDRESS_WIDTH;
defparam a_latency_aware_read_master.FIFODEPTH = FIFO_DEPTH;
defparam a_latency_aware_read_master.FIFODEPTH_LOG2 = FIFO_DEPTH_LOG2;
defparam a_latency_aware_read_master.FIFOUSEMEMORY = MEMORY_BASED_FIFO;
end
end
else
begin
if(BURST_CAPABLE == 1)
begin
burst_write_master a_burst_write_master(
.clk (clk),
.reset (reset),
.control_fixed_location (control_fixed_location),
.control_write_base (control_write_base),
.control_write_length (control_write_length),
.control_go (control_go),
.control_done (control_done),
.user_write_buffer (user_write_buffer),
.user_buffer_data (user_buffer_input_data),
.user_buffer_full (user_buffer_full),
.master_address (master_address),
.master_write (master_write),
.master_byteenable (master_byteenable),
.master_writedata (master_writedata),
.master_burstcount (master_burstcount),
.master_waitrequest (master_waitrequest)
);
defparam a_burst_write_master.DATAWIDTH = DATA_WIDTH;
defparam a_burst_write_master.MAXBURSTCOUNT = MAXIMUM_BURST_COUNT;
defparam a_burst_write_master.BURSTCOUNTWIDTH = BURST_COUNT_WIDTH;
defparam a_burst_write_master.BYTEENABLEWIDTH = DATA_WIDTH/8;
defparam a_burst_write_master.ADDRESSWIDTH = ADDRESS_WIDTH;
defparam a_burst_write_master.FIFODEPTH = FIFO_DEPTH;
defparam a_burst_write_master.FIFODEPTH_LOG2 = FIFO_DEPTH_LOG2;
defparam a_burst_write_master.FIFOUSEMEMORY = MEMORY_BASED_FIFO;
end
else
begin
write_master a_write_master(
.clk (clk),
.reset (reset),
.control_fixed_location (control_fixed_location),
.control_write_base (control_write_base),
.control_write_length (control_write_length),
.control_go (control_go),
.control_done (control_done),
.user_write_buffer (user_write_buffer),
.user_buffer_data (user_buffer_input_data),
.user_buffer_full (user_buffer_full),
.master_address (master_address),
.master_write (master_write),
.master_byteenable (master_byteenable),
.master_writedata (master_writedata),
.master_waitrequest (master_waitrequest)
);
defparam a_write_master.DATAWIDTH = DATA_WIDTH;
defparam a_write_master.BYTEENABLEWIDTH = DATA_WIDTH/8;
defparam a_write_master.ADDRESSWIDTH = ADDRESS_WIDTH;
defparam a_write_master.FIFODEPTH = FIFO_DEPTH;
defparam a_write_master.FIFODEPTH_LOG2 = FIFO_DEPTH_LOG2;
defparam a_write_master.FIFOUSEMEMORY = MEMORY_BASED_FIFO;
end
end
endgenerate
endmodule

View File

@ -0,0 +1,291 @@
# TCL File Generated by Component Editor 8.0
# Sat May 31 20:41:17 PDT 2008
# DO NOT MODIFY
# +-----------------------------------
# | module burst_read_master
# |
set_module_property DESCRIPTION "Custom Avalon-MM Masters"
set_module_property NAME master_template
set_module_property VERSION 1.0
set_module_property GROUP "Templates"
set_module_property AUTHOR JCJB
set_module_property ICON_PATH ALTERA_LOGO_ANIM.gif
set_module_property DISPLAY_NAME master_template
set_module_property TOP_LEVEL_HDL_FILE custom_master.v
set_module_property TOP_LEVEL_HDL_MODULE custom_master
set_module_property INSTANTIATE_IN_SYSTEM_MODULE true
set_module_property EDITABLE false
set_module_property SIMULATION_MODEL_IN_VERILOG false
set_module_property SIMULATION_MODEL_IN_VHDL false
set_module_property SIMULATION_MODEL_HAS_TULIPS false
set_module_property SIMULATION_MODEL_IS_OBFUSCATED false
# |
# +-----------------------------------
set_module_property ELABORATION_CALLBACK elaborate_me
set_module_property VALIDATION_CALLBACK validate_me
# +-----------------------------------
# | files
# |
add_file custom_master.v {SYNTHESIS SIMULATION}
add_file burst_write_master.v {SYNTHESIS SIMULATION}
add_file burst_read_master.v {SYNTHESIS SIMULATION}
add_file write_master.v {SYNTHESIS SIMULATION}
add_file latency_aware_read_master.v {SYNTHESIS SIMULATION}
# |
# +-----------------------------------
# +-----------------------------------
# | parameters
# |
# Avalon Master Settings
add_parameter MASTER_DIRECTION Integer 0 "Sets the master direction between read (0) and write (1) transfers"
set_parameter_property MASTER_DIRECTION VISIBLE true
set_parameter_property MASTER_DIRECTION DISPLAY_NAME "Master Direction"
set_parameter_property MASTER_DIRECTION GROUP "Avalon-MM Master Properties"
set_parameter_property MASTER_DIRECTION AFFECTS_PORT_WIDTHS true
set_parameter_property MASTER_DIRECTION ALLOWED_RANGES {"0:Read" "1:Write"}
add_parameter DATA_WIDTH Integer 32 "Width of the data path"
set_parameter_property DATA_WIDTH VISIBLE true
set_parameter_property DATA_WIDTH DISPLAY_NAME "Data Width"
set_parameter_property DATA_WIDTH GROUP "Avalon-MM Master Properties"
set_parameter_property DATA_WIDTH AFFECTS_PORT_WIDTHS true
set_parameter_property DATA_WIDTH ALLOWED_RANGES {8 16 32 64 128 256 512 1024}
add_parameter ADDRESS_WIDTH Integer "32" "Address Width"
set_parameter_property ADDRESS_WIDTH VISIBLE true
set_parameter_property ADDRESS_WIDTH DISPLAY_NAME "Address Width"
set_parameter_property ADDRESS_WIDTH GROUP "Avalon-MM Master Properties"
set_parameter_property ADDRESS_WIDTH AFFECTS_PORT_WIDTHS true
set_parameter_property ADDRESS_WIDTH ALLOWED_RANGES {32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 14 13 12 11 10 9 8 7 6 5 4}
# Burst Settings
add_parameter BURST_CAPABLE Integer 0 "Enable bursting"
set_parameter_property BURST_CAPABLE VISIBLE true
set_parameter_property BURST_CAPABLE DISPLAY_NAME "Burst Capable"
set_parameter_property BURST_CAPABLE GROUP "Burst Properties"
set_parameter_property BURST_CAPABLE AFFECTS_PORT_WIDTHS true
set_parameter_property BURST_CAPABLE ALLOWED_RANGES {"0:Disabled" "1:Enabled"}
add_parameter MAXIMUM_BURST_COUNT Integer "2" "Maximum Burst Count"
set_parameter_property MAXIMUM_BURST_COUNT VISIBLE true
set_parameter_property MAXIMUM_BURST_COUNT DISPLAY_NAME "Maximum Burst Count"
set_parameter_property MAXIMUM_BURST_COUNT GROUP "Burst Properties"
set_parameter_property MAXIMUM_BURST_COUNT AFFECTS_PORT_WIDTHS false
set_parameter_property MAXIMUM_BURST_COUNT ALLOWED_RANGES {1 2 4 8 16 32 64 128}
add_parameter BURST_COUNT_WIDTH Integer "2" "Enable bursting"
set_parameter_property BURST_COUNT_WIDTH VISIBLE false
set_parameter_property BURST_COUNT_WIDTH DISPLAY_NAME "Burst Count Width"
set_parameter_property BURST_COUNT_WIDTH GROUP "Burst Properties"
set_parameter_property BURST_COUNT_WIDTH AFFECTS_PORT_WIDTHS true
set_parameter_property BURST_COUNT_WIDTH ALLOWED_RANGES {1:8}
# Other Settings
add_parameter FIFO_DEPTH Integer "32" "FIFO depth"
set_parameter_property FIFO_DEPTH VISIBLE true
set_parameter_property FIFO_DEPTH DISPLAY_NAME "FIFO Depth"
set_parameter_property FIFO_DEPTH GROUP "Other Properties"
set_parameter_property FIFO_DEPTH AFFECTS_PORT_WIDTHS false
set_parameter_property FIFO_DEPTH ALLOWED_RANGES {4 8 16 32 64 128 256}
add_parameter FIFO_DEPTH_LOG2 Integer "5" "log2(FIFO Depth)"
set_parameter_property FIFO_DEPTH_LOG2 VISIBLE false
set_parameter_property FIFO_DEPTH_LOG2 DISPLAY_NAME "log2(FIFO Depth)"
set_parameter_property FIFO_DEPTH_LOG2 GROUP "Other Properties"
set_parameter_property FIFO_DEPTH_LOG2 AFFECTS_PORT_WIDTHS false
set_parameter_property FIFO_DEPTH_LOG2 ALLOWED_RANGES {2:8}
add_parameter MEMORY_BASED_FIFO Integer 1 "Select false if you want register based (0) FIFO instead of memory (1)"
set_parameter_property MEMORY_BASED_FIFO VISIBLE true
set_parameter_property MEMORY_BASED_FIFO DISPLAY_NAME "Memory based FIFO"
set_parameter_property MEMORY_BASED_FIFO GROUP "Other Properties"
set_parameter_property MEMORY_BASED_FIFO AFFECTS_PORT_WIDTHS false
set_parameter_property MEMORY_BASED_FIFO ALLOWED_RANGES {"1:Memory" "0:Logic"}
# |
# +-----------------------------------
# +-----------------------------------
# | connection point clock_reset
# |
add_interface clock_reset clock end
set_interface_property clock_reset ptfSchematicName ""
add_interface_port clock_reset clk clk Input 1
add_interface_port clock_reset reset reset Input 1
# |
# +-----------------------------------
# +-----------------------------------
# | connection point avalon_master
# |
add_interface avalon_master avalon start
set_interface_property avalon_master linewrapBursts false
set_interface_property avalon_master adaptsTo ""
set_interface_property avalon_master doStreamReads false
set_interface_property avalon_master doStreamWrites false
set_interface_property avalon_master burstOnBurstBoundariesOnly false
set_interface_property avalon_master ASSOCIATED_CLOCK clock_reset
add_interface_port avalon_master master_address address Output -1
add_interface_port avalon_master master_read read Output 1
add_interface_port avalon_master master_write write Output 1
add_interface_port avalon_master master_byteenable byteenable Output -1
add_interface_port avalon_master master_readdata readdata Input -1
add_interface_port avalon_master master_readdatavalid readdatavalid Input 1
add_interface_port avalon_master master_writedata writedata Output -1
add_interface_port avalon_master master_burstcount burstcount Output -1
add_interface_port avalon_master master_waitrequest waitrequest Input 1
# |
# +-----------------------------------
# +-----------------------------------
# | connection point control
# |
add_interface control conduit end
set_interface_property control ASSOCIATED_CLOCK clock_reset
add_interface_port control control_fixed_location export Input 1
add_interface_port control control_read_base export Input -1
add_interface_port control control_write_base export Input -1
add_interface_port control control_read_length export Input -1
add_interface_port control control_write_length export Input -1
add_interface_port control control_go export Input 1
add_interface_port control control_done export Output 1
add_interface_port control control_early_done export Output 1
# |
# +-----------------------------------
# +-----------------------------------
# | connection point user
# |
add_interface user conduit end
set_interface_property user ASSOCIATED_CLOCK clock_reset
add_interface_port user user_read_buffer export Input 1
add_interface_port user user_buffer_output_data export Output -1
add_interface_port user user_data_available export Output 1
add_interface_port user user_write_buffer export Input 1
add_interface_port user user_buffer_input_data export Input -1
add_interface_port user user_buffer_full export Output 1
# |
# +-----------------------------------
proc elaborate_me {} {
# set all the new port widths
set the_data_width [get_parameter_value DATA_WIDTH]
set the_byteenable_width [expr {$the_data_width / 8} ]
set the_address_width [get_parameter_value ADDRESS_WIDTH]
set the_burst_count_width [get_parameter_value BURST_COUNT_WIDTH]
set_port_property control_read_base WIDTH $the_address_width
set_port_property control_read_length WIDTH $the_address_width
set_port_property control_write_base WIDTH $the_address_width
set_port_property control_write_length WIDTH $the_address_width
set_port_property user_buffer_input_data WIDTH $the_data_width
set_port_property user_buffer_output_data WIDTH $the_data_width
set_port_property master_address WIDTH $the_address_width
set_port_property master_byteenable WIDTH $the_byteenable_width
set_port_property master_readdata WIDTH $the_data_width
set_port_property master_writedata WIDTH $the_data_width
set_port_property master_burstcount WIDTH $the_burst_count_width
# determine the master direction and burst capabilities
set the_master_direction [get_parameter_value MASTER_DIRECTION]
set the_burst_capable [get_parameter_value BURST_CAPABLE]
# switch between read and write master signals (excluding burstcount)
if { $the_master_direction == 0 } {
set_port_property control_read_base TERMINATION false
set_port_property control_read_length TERMINATION false
set_port_property control_write_base TERMINATION true
set_port_property control_write_length TERMINATION true
set_port_property control_early_done TERMINATION false
set_port_property user_read_buffer TERMINATION false
set_port_property user_write_buffer TERMINATION true
set_port_property user_buffer_input_data TERMINATION true
set_port_property user_buffer_output_data TERMINATION false
set_port_property user_data_available TERMINATION false
set_port_property user_buffer_full TERMINATION true
set_port_property master_read TERMINATION false
set_port_property master_write TERMINATION true
set_port_property master_readdata TERMINATION false
set_port_property master_readdatavalid TERMINATION false
set_port_property master_writedata TERMINATION true
} else {
set_port_property control_read_base TERMINATION true
set_port_property control_read_length TERMINATION true
set_port_property control_write_base TERMINATION false
set_port_property control_write_length TERMINATION false
set_port_property control_early_done TERMINATION true
set_port_property user_read_buffer TERMINATION true
set_port_property user_write_buffer TERMINATION false
set_port_property user_buffer_input_data TERMINATION false
set_port_property user_buffer_output_data TERMINATION true
set_port_property user_data_available TERMINATION true
set_port_property user_buffer_full TERMINATION false
set_port_property master_read TERMINATION true
set_port_property master_write TERMINATION false
set_port_property master_readdata TERMINATION true
set_port_property master_readdatavalid TERMINATION true
set_port_property master_writedata TERMINATION false
}
# enable/disable the burstcount signal
if { $the_burst_capable == 0 } {
set_port_property master_burstcount TERMINATION true
} else {
set_port_property master_burstcount TERMINATION false
}
}
proc validate_me {} {
# read in all the parameter that matter for validation
set the_burst_capable [get_parameter_value BURST_CAPABLE]
set the_maximum_burst_count [get_parameter_value MAXIMUM_BURST_COUNT]
set the_fifo_depth [get_parameter_value FIFO_DEPTH]
# when burst is enabled check to make sure FIFO depth is at least twice as large (also enable/disable burst count)
if { $the_burst_capable == 1 } {
set_parameter_property MAXIMUM_BURST_COUNT ENABLED true
if { $the_fifo_depth < [expr {$the_maximum_burst_count * 2}] } {
send_message Error "The FIFO Depth must be at least twice as large as Maximum Burst Count."
}
} else {
set_parameter_property MAXIMUM_BURST_COUNT ENABLED false
}
set the_burst_count [get_parameter_value MAXIMUM_BURST_COUNT]
set the_burst_count_width [expr {(log($the_burst_count) / log(2)) + 1}]
set the_fifo_depth [get_parameter_value FIFO_DEPTH]
set the_fifo_depth_log2 [expr {log($the_fifo_depth) / log(2)}]
set_parameter_value BURST_COUNT_WIDTH $the_burst_count_width
set_parameter_value FIFO_DEPTH_LOG2 $the_fifo_depth_log2
}

View File

@ -0,0 +1,247 @@
/*
Legal Notice: (C)2007 Altera Corporation. All rights reserved. Your
use of Altera Corporation's design tools, logic functions and other
software and tools, and its AMPP partner logic functions, and any
output files any of the foregoing (including device programming or
simulation files), and any associated documentation or information are
expressly subject to the terms and conditions of the Altera Program
License Subscription Agreement or other applicable license agreement,
including, without limitation, that your use is for the sole purpose
of programming logic devices manufactured by Altera and sold by Altera
or its authorized distributors. Please refer to the applicable
agreement for further details.
*/
/*
Author: JCJB
Date: 11/04/2007
This latency aware read master is passed a word aligned address, length in bytes,
and a 'go' bit. The master will continue to post reads until the length register
reaches a value of zero. When all the reads return the done bit will be asserted.
To use this master you must simply drive the control signals into this block,
and also read the data from the exposed read FIFO. To read from the exposed FIFO
use the 'user_read_buffer' signal to pop data from the FIFO 'user_buffer_data'.
The signal 'user_data_available' is asserted whenever data is available from the
exposed FIFO.
*/
// altera message_off 10230
module latency_aware_read_master (
clk,
reset,
// control inputs and outputs
control_fixed_location,
control_read_base,
control_read_length,
control_go,
control_done,
control_early_done,
// user logic inputs and outputs
user_read_buffer,
user_buffer_data,
user_data_available,
// master inputs and outputs
master_address,
master_read,
master_byteenable,
master_readdata,
master_readdatavalid,
master_waitrequest
);
parameter DATAWIDTH = 32;
parameter BYTEENABLEWIDTH = 4;
parameter ADDRESSWIDTH = 32;
parameter FIFODEPTH = 32;
parameter FIFODEPTH_LOG2 = 5;
parameter FIFOUSEMEMORY = 1; // set to 0 to use LEs instead
input clk;
input reset;
// control inputs and outputs
input control_fixed_location;
input [ADDRESSWIDTH-1:0] control_read_base;
input [ADDRESSWIDTH-1:0] control_read_length;
input control_go;
output wire control_done;
output wire control_early_done; // don't use this unless you know what you are doing!
// user logic inputs and outputs
input user_read_buffer;
output wire [DATAWIDTH-1:0] user_buffer_data;
output wire user_data_available;
// master inputs and outputs
input master_waitrequest;
input master_readdatavalid;
input [DATAWIDTH-1:0] master_readdata;
output wire [ADDRESSWIDTH-1:0] master_address;
output wire master_read;
output wire [BYTEENABLEWIDTH-1:0] master_byteenable;
// internal control signals
reg control_fixed_location_d1;
wire fifo_empty;
reg [ADDRESSWIDTH-1:0] address;
reg [ADDRESSWIDTH-1:0] length;
reg [FIFODEPTH_LOG2-1:0] reads_pending;
wire increment_address;
wire too_many_pending_reads;
reg too_many_pending_reads_d1;
wire [FIFODEPTH_LOG2-1:0] fifo_used;
// registering the control_fixed_location bit
always @ (posedge clk or posedge reset)
begin
if (reset == 1)
begin
control_fixed_location_d1 <= 0;
end
else
begin
if (control_go == 1)
begin
control_fixed_location_d1 <= control_fixed_location;
end
end
end
// master address logic
assign master_address = address;
assign master_byteenable = -1; // all ones, always performing word size accesses
always @ (posedge clk or posedge reset)
begin
if (reset == 1)
begin
address <= 0;
end
else
begin
if(control_go == 1)
begin
address <= control_read_base;
end
else if((increment_address == 1) & (control_fixed_location_d1 == 0))
begin
address <= address + BYTEENABLEWIDTH; // always performing word size accesses
end
end
end
// master length logic
always @ (posedge clk or posedge reset)
begin
if (reset == 1)
begin
length <= 0;
end
else
begin
if(control_go == 1)
begin
length <= control_read_length;
end
else if(increment_address == 1)
begin
length <= length - BYTEENABLEWIDTH; // always performing word size accesses
end
end
end
// control logic
assign too_many_pending_reads = (fifo_used + reads_pending) >= (FIFODEPTH - 4);
assign master_read = (length != 0) & (too_many_pending_reads_d1 == 0);
assign increment_address = (length != 0) & (too_many_pending_reads_d1 == 0) & (master_waitrequest == 0);
assign control_done = (reads_pending == 0) & (length == 0); // master done posting reads and all reads have returned
assign control_early_done = (length == 0); // if you need all the pending reads to return then use 'control_done' instead of this signal
always @ (posedge clk)
begin
if (reset == 1)
begin
too_many_pending_reads_d1 <= 0;
end
else
begin
too_many_pending_reads_d1 <= too_many_pending_reads;
end
end
always @ (posedge clk or posedge reset)
begin
if (reset == 1)
begin
reads_pending <= 0;
end
else
begin
if(increment_address == 1)
begin
if(master_readdatavalid == 0)
begin
reads_pending <= reads_pending + 1;
end
else
begin
reads_pending <= reads_pending; // a read was posted, but another returned
end
end
else
begin
if(master_readdatavalid == 0)
begin
reads_pending <= reads_pending; // read was not posted and no read returned
end
else
begin
reads_pending <= reads_pending - 1; // read was not posted but a read returned
end
end
end
end
// read data feeding user logic
assign user_data_available = !fifo_empty;
scfifo the_master_to_user_fifo (
.aclr (reset),
.clock (clk),
.data (master_readdata),
.empty (fifo_empty),
.q (user_buffer_data),
.rdreq (user_read_buffer),
.usedw (fifo_used),
.wrreq (master_readdatavalid)
);
defparam the_master_to_user_fifo.lpm_width = DATAWIDTH;
defparam the_master_to_user_fifo.lpm_numwords = FIFODEPTH;
defparam the_master_to_user_fifo.lpm_showahead = "ON";
defparam the_master_to_user_fifo.use_eab = (FIFOUSEMEMORY == 1)? "ON" : "OFF";
defparam the_master_to_user_fifo.add_ram_output_register = "OFF";
defparam the_master_to_user_fifo.underflow_checking = "OFF";
defparam the_master_to_user_fifo.overflow_checking = "OFF";
endmodule

View File

@ -0,0 +1,191 @@
/*
Legal Notice: (C)2007 Altera Corporation. All rights reserved. Your
use of Altera Corporation's design tools, logic functions and other
software and tools, and its AMPP partner logic functions, and any
output files any of the foregoing (including device programming or
simulation files), and any associated documentation or information are
expressly subject to the terms and conditions of the Altera Program
License Subscription Agreement or other applicable license agreement,
including, without limitation, that your use is for the sole purpose
of programming logic devices manufactured by Altera and sold by Altera
or its authorized distributors. Please refer to the applicable
agreement for further details.
*/
/*
Author: JCJB
Date: 11/04/2007
This simple write master is passed a word aligned address, length in bytes,
and a 'go' bit. The master will continue to post writes until the length register
reaches zero. When the length register reaches zero the 'done' bit is asserted.
To use this master you must simply drive the control signals into this block,
and also write the data to the exposed write FIFO. To read from the exposed FIFO
use the 'user_write_buffer' signal to push data into the FIFO 'user_buffer_data'.
The signal 'user_buffer_full' is asserted whenever the exposed buffer is full.
You should not attempt to write data to the exposed FIFO if it is full.
*/
// altera message_off 10230
module write_master (
clk,
reset,
// control inputs and outputs
control_fixed_location,
control_write_base,
control_write_length,
control_go,
control_done,
// user logic inputs and outputs
user_write_buffer,
user_buffer_data,
user_buffer_full,
// master inputs and outputs
master_address,
master_write,
master_byteenable,
master_writedata,
master_waitrequest
);
parameter DATAWIDTH = 32;
parameter BYTEENABLEWIDTH = 4;
parameter ADDRESSWIDTH = 32;
parameter FIFODEPTH = 32;
parameter FIFODEPTH_LOG2 = 5;
parameter FIFOUSEMEMORY = 1; // set to 0 to use LEs instead
input clk;
input reset;
// control inputs and outputs
input control_fixed_location; // this only makes sense to enable when MAXBURSTCOUNT = 1
input [ADDRESSWIDTH-1:0] control_write_base;
input [ADDRESSWIDTH-1:0] control_write_length;
input control_go;
output wire control_done;
// user logic inputs and outputs
input user_write_buffer;
input [DATAWIDTH-1:0] user_buffer_data;
output wire user_buffer_full;
// master inputs and outputs
input master_waitrequest;
output wire [ADDRESSWIDTH-1:0] master_address;
output wire master_write;
output wire [BYTEENABLEWIDTH-1:0] master_byteenable;
output wire [DATAWIDTH-1:0] master_writedata;
// internal control signals
reg control_fixed_location_d1;
reg [ADDRESSWIDTH-1:0] address; // this increments for each word
reg [ADDRESSWIDTH-1:0] length;
wire increment_address; // this increments the 'address' register when write is asserted and waitrequest is de-asserted
wire read_fifo;
wire user_buffer_empty;
// registering the control_fixed_location bit
always @ (posedge clk or posedge reset)
begin
if (reset == 1)
begin
control_fixed_location_d1 <= 0;
end
else
begin
if (control_go == 1)
begin
control_fixed_location_d1 <= control_fixed_location;
end
end
end
// master word increment counter
always @ (posedge clk or posedge reset)
begin
if (reset == 1)
begin
address <= 0;
end
else
begin
if (control_go == 1)
begin
address <= control_write_base;
end
else if ((increment_address == 1) & (control_fixed_location_d1 == 0))
begin
address <= address + BYTEENABLEWIDTH; // always performing word size accesses
end
end
end
// master length logic
always @ (posedge clk or posedge reset)
begin
if (reset == 1)
begin
length <= 0;
end
else
begin
if (control_go == 1)
begin
length <= control_write_length;
end
else if (increment_address == 1)
begin
length <= length - BYTEENABLEWIDTH; // always performing word size accesses
end
end
end
// controlled signals going to the master/control ports
assign master_address = address;
assign master_byteenable = -1; // all ones, always performing word size accesses
assign control_done = (length == 0);
assign master_write = (user_buffer_empty == 0) & (control_done == 0);
assign increment_address = (user_buffer_empty == 0) & (master_waitrequest == 0) & (control_done == 0);
assign read_fifo = increment_address;
// write data feed by user logic
scfifo the_user_to_master_fifo (
.aclr (reset),
.clock (clk),
.data (user_buffer_data),
.full (user_buffer_full),
.empty (user_buffer_empty),
.q (master_writedata),
.rdreq (read_fifo),
.wrreq (user_write_buffer)
);
defparam the_user_to_master_fifo.lpm_width = DATAWIDTH;
defparam the_user_to_master_fifo.lpm_numwords = FIFODEPTH;
defparam the_user_to_master_fifo.lpm_showahead = "ON";
defparam the_user_to_master_fifo.use_eab = (FIFOUSEMEMORY == 1)? "ON" : "OFF";
defparam the_user_to_master_fifo.add_ram_output_register = "OFF";
defparam the_user_to_master_fifo.underflow_checking = "OFF";
defparam the_user_to_master_fifo.overflow_checking = "OFF";
endmodule