HITDAQ/FPGA_firmware/q_sys/synthesis/submodules/read_burst_control.v
2024-10-11 14:49:54 +02:00

108 lines
4.5 KiB
Verilog

// (C) 2001-2019 Intel Corporation. All rights reserved.
// Your use of Intel Corporation's design tools, logic functions and other
// software and tools, and its AMPP partner logic functions, and any output
// files from 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 Intel Program License Subscription
// Agreement, Intel FPGA IP License Agreement, or other applicable
// license agreement, including, without limitation, that your use is for the
// sole purpose of programming logic devices manufactured by Intel and sold by
// Intel or its authorized distributors. Please refer to the applicable
// agreement for further details.
/*
This block takes the length and forms the appropriate burst count.
Whenever one of the short access enables are asserted this block
will post a burst of one. Posting a burst of one isn't necessary
but it will make it possible to add byte enable support to the
read master at a later date.
Revision History:
1.0 First version
1.1 Added generate logic around the internal burst count logic to prevent zero
replication simulation bug. In the case of a non-bursting master the
burst count is just hardcoded to 1.
*/
// synthesis translate_off
`timescale 1ns / 1ps
// synthesis translate_on
// turn off superfluous verilog processor warnings
// altera message_level Level1
// altera message_off 10034 10035 10036 10037 10230 10240 10030
module read_burst_control (
address,
length,
maximum_burst_count,
short_first_access_enable,
short_last_access_enable,
short_first_and_last_access_enable,
burst_count
);
parameter BURST_ENABLE = 1; // set to 0 to hardwire the address and write signals straight out
parameter BURST_COUNT_WIDTH = 3;
parameter WORD_SIZE_LOG2 = 2; // log2(DATA WIDTH/8)
parameter ADDRESS_WIDTH = 32;
parameter LENGTH_WIDTH = 32;
parameter BURST_WRAPPING_SUPPORT = 1; // set 1 for on, set 0 for off. This parameter can't be enabled when hte master supports programmable burst.
localparam BURST_OFFSET_WIDTH = (BURST_COUNT_WIDTH == 1)? 1: (BURST_COUNT_WIDTH-1);
input [ADDRESS_WIDTH-1:0] address;
input [LENGTH_WIDTH-1:0] length;
input [BURST_COUNT_WIDTH-1:0] maximum_burst_count; // will be either a hardcoded input or programmable
input short_first_access_enable;
input short_last_access_enable;
input short_first_and_last_access_enable;
output wire [BURST_COUNT_WIDTH-1:0] burst_count;
wire [BURST_COUNT_WIDTH-1:0] posted_burst; // when the burst statemachine is used this will be the burst count posted to the fabric
reg [BURST_COUNT_WIDTH-1:0] internal_burst_count; // muxes posted_burst, posted_burst_d1, and '1' since we need to be able to post bursts of '1' for short accesses
wire burst_of_one_enable; // asserted when partial word accesses are occuring
wire short_burst_enable;
wire [BURST_OFFSET_WIDTH-1:0] burst_offset;
assign burst_offset = address[BURST_OFFSET_WIDTH+WORD_SIZE_LOG2-1:WORD_SIZE_LOG2];
// for unaligned or partial transfers we must use a burst length of 1 so that
assign burst_of_one_enable = (short_first_access_enable == 1) | (short_last_access_enable == 1) | (short_first_and_last_access_enable == 1) | // when performing partial accesses use a burst length of 1
((BURST_WRAPPING_SUPPORT == 1) & (burst_offset != 0)); // when the burst boundary offset is non-zero then the master isn't in burst alignment yet as so a burst of 1 needs to be posted
assign short_burst_enable = ((length >> WORD_SIZE_LOG2) < maximum_burst_count);
generate
if ((BURST_ENABLE == 1) & (BURST_COUNT_WIDTH > 1))
begin
always @ (maximum_burst_count or length or short_burst_enable or burst_of_one_enable)
begin
case ({short_burst_enable, burst_of_one_enable})
2'b00 : internal_burst_count = maximum_burst_count;
2'b01 : internal_burst_count = 1; // this is when the master starts unaligned
2'b10 : internal_burst_count = ((length >> WORD_SIZE_LOG2) & {(BURST_COUNT_WIDTH-1){1'b1}}); // this could be followed by a burst of 1 if there are a few bytes leftover
2'b11 : internal_burst_count = 1; // burst of 1 needs to win, this is when the master starts with very little data to transfer
endcase
end
assign burst_count = internal_burst_count;
end
else
begin
assign burst_count = 1; // this will be stubbed at the top level but will be used for the address and pending reads incrementing
end
endgenerate
endmodule