Skip to content

Commit c416353

Browse files
OpenCAPI3.0 Reference Design including LPC
1 parent a943618 commit c416353

15 files changed

+9130
-5
lines changed

afu/lpc/flash_sub_system.v

Lines changed: 549 additions & 0 deletions
Large diffs are not rendered by default.

afu/lpc/ip/bram_8192x1.tcl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
## LPC bram 8192x1
2+
create_ip -name blk_mem_gen -vendor xilinx.com -library ip -version 8.4 -module_name bram_native_1P_noOutReg_8192x1_A
3+
4+
set_property -dict [list CONFIG.Interface_Type {Native} CONFIG.Memory_Type {Single_Port_RAM} CONFIG.Write_Width_A {1} CONFIG.Write_Depth_A {8192} CONFIG.Read_Width_A {1} \
5+
CONFIG.Operating_Mode_A {READ_FIRST} CONFIG.Register_PortA_Output_of_Memory_Primitives {false} CONFIG.Use_AXI_ID {false} CONFIG.Use_Byte_Write_Enable {false} \
6+
CONFIG.Byte_Size {9} CONFIG.Assume_Synchronous_Clk {false} CONFIG.Write_Width_B {1} CONFIG.Read_Width_B {1} CONFIG.Operating_Mode_B {WRITE_FIRST} CONFIG.Enable_B {Always_Enabled} \
7+
CONFIG.Register_PortB_Output_of_Memory_Primitives {false} CONFIG.Use_RSTB_Pin {false} CONFIG.Reset_Type {SYNC} CONFIG.Port_B_Clock {0} CONFIG.Port_B_Enable_Rate {0} \
8+
CONFIG.Fill_Remaining_Memory_Locations {true}] [get_ips bram_native_1P_noOutReg_8192x1_A]
9+
10+
generate_target {all} [get_ips bram_native_1P_noOutReg_8192x1_A]

afu/lpc/ip/bram_8192x512.tcl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
## LPC bram 8192x512
2+
3+
create_ip -name blk_mem_gen -vendor xilinx.com -library ip -version 8.4 -module_name bram_native_1P_noOutReg_8192x512_A
4+
5+
set_property -dict [list CONFIG.Use_Byte_Write_Enable {true} CONFIG.Byte_Size {8} CONFIG.Write_Width_A {512} CONFIG.Write_Depth_A {8192} \
6+
CONFIG.Operating_Mode_A {READ_FIRST} CONFIG.Register_PortA_Output_of_Memory_Primitives {false} CONFIG.Read_Width_A {512} CONFIG.Write_Width_B {512} \
7+
CONFIG.Read_Width_B {512} CONFIG.Fill_Remaining_Memory_Locations {true}] [get_ips bram_native_1P_noOutReg_8192x512_A]
8+
9+
generate_target {all} [get_ips bram_native_1P_noOutReg_8192x512_A]

afu/lpc/lpc_afu.v

Lines changed: 4606 additions & 0 deletions
Large diffs are not rendered by default.

afu/lpc/lpc_bulk_mem.v

Lines changed: 259 additions & 0 deletions
Large diffs are not rendered by default.

afu/lpc/lpc_cmdfifo.v

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
// *!***************************************************************************
2+
// *! Copyright 2019 International Business Machines
3+
// *!
4+
// *! Licensed under the Apache License, Version 2.0 (the "License");
5+
// *! you may not use this file except in compliance with the License.
6+
// *! You may obtain a copy of the License at
7+
// *! http://www.apache.org/licenses/LICENSE-2.0
8+
// *!
9+
// *! The patent license granted to you in Section 3 of the License, as applied
10+
// *! to the "Work," hereby includes implementations of the Work in physical form.
11+
// *!
12+
// *! Unless required by applicable law or agreed to in writing, the reference design
13+
// *! distributed under the License is distributed on an "AS IS" BASIS,
14+
// *! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// *! See the License for the specific language governing permissions and
16+
// *! limitations under the License.
17+
// *!
18+
// *! The background Specification upon which this is based is managed by and available from
19+
// *! the OpenCAPI Consortium. More information can be found at https://opencapi.org.
20+
// *!***************************************************************************
21+
`timescale 1ns / 1ps
22+
// -------------------------------------------------------------------
23+
//
24+
// Title : lpc_cmdfifo.v
25+
// Function : This file contains a command buffer FIFO to "pre-fetch" a number of commands from the TLX.
26+
// More importantly, the command at the head of the FIFO can be presented and held for any number
27+
// of cycles. This differs from the TLX interface where the command is only valid for one cycle
28+
// (when cmd_valid=1) whether the AFU is ready to receive it or not. The AFU's command dispatch
29+
// logic may not be able to begin servicing the command immediately, depending on the command type
30+
// and current state of response credits or pipelined operations in progress. Therefore this command
31+
// FIFO was added to provide this behavior.
32+
//
33+
// In addition, several commands are buffered up at once. This helps absorb latency cycles in the TLX,
34+
// measured from receipt of a cmd_credit to the presentation of the next command. It also allows for
35+
// a higher performing interface by enabling back to back operation of bulk memory operations if they
36+
// are of the appropriate mix. In other words if all commands are 1 FLIT writes, there will likely be
37+
// a burst of commands started in the pipeline, then a break while the credit flow catches up. However
38+
// if the commands are a mix of reads and writes of various lengths, there will be natural pauses in
39+
// command stream while waiting for data and these pauses can be used to let the command FIFO fill up
40+
// again.
41+
//
42+
// The width of the FIFO is parameterized to make it easy to adjust to the number of TLX command
43+
// signals that are needed. The LPC does not support all OpenCAPI TL commands, so some of the TLX->AFU
44+
// interface signals are unused. Rather than capture them in the FIFO and discard them when dispatching,
45+
// resources can be conserved by ignoring them at the TLX interface. Thus the width of the FIFO is
46+
// variable to enable easy modifications as additional signals are used as functionality increases.
47+
//
48+
// Note: The depth of the FIFO is fixed, but may need to be adjusted after performance feedback from
49+
// simulation is obtained.
50+
//
51+
// -------------------------------------------------------------------
52+
// Modification History :
53+
// |Version | |Author |Description of change
54+
// |-----------| |-------- |---------------------
55+
`define lpc_cmdfifo_VERSION 12_Oct_2017 //
56+
// -------------------------------------------------------------------
57+
58+
59+
// ==============================================================================================================================
60+
// @@@ Module Declaration
61+
// ==============================================================================================================================
62+
module lpc_cmdfifo #(parameter integer WIDTH = 158) (
63+
input clock // Clock - samples & launches data on rising edge
64+
, input reset // When 1, reset registers to an empty FIFO state
65+
, input resync_credits // Reset credit counts when 1, start capturing/sending new credits on 1->0 transition
66+
, input tlx_is_ready // When 1, TLX is ready to exchange commands and responses
67+
68+
// Input into FIFO
69+
, input [WIDTH-1:0] cmd_in // Vector of command information to save
70+
, input cmd_in_valid // When 1, load 'cmd_in' into the FIFO
71+
, output cmd_credit_to_TLX // When 1, there is space in the FIFO for another command
72+
73+
// Output from FIFO
74+
, input cmd_dispatched // When 1, increment read FIFO pointer to present the next FIFO entry
75+
, output [WIDTH-1:0] cmd_out // Command information at head of FIFO
76+
, output cmd_out_valid // When 1, 'cmd_out' contains valid information
77+
78+
// Error conditions
79+
, output fifo_overflow // When 1, FIFO was full when another 'cmd_valid' arrived
80+
) ;
81+
82+
83+
// ==============================================================================================================================
84+
// @@@ Implement FIFO
85+
// ==============================================================================================================================
86+
87+
reg [WIDTH-1:0] cmdfifo [7:0]; // 8 row array
88+
reg [2:0] wrptr; // Write pointer into array, points to next free entry
89+
reg [2:0] rdptr; // Read pointer from array, points to oldest valid entry
90+
reg [7:0] cmdfifo_val; // 1=associated entry is used, 0=associated entry is open and can be overwritten
91+
92+
// Manage write pointer
93+
always @(posedge(clock))
94+
begin
95+
if (reset == 1'b1)
96+
wrptr <= 3'b000; // Initialize to location 0
97+
else if (cmd_in_valid == 1'b1 && wrptr != 3'b111)
98+
wrptr <= wrptr + 3'b001; // Add an entry, so increment
99+
else if (cmd_in_valid == 1'b1 && wrptr == 3'b111)
100+
wrptr <= 3'b000; // Add an entry, but wrap around to increment
101+
else
102+
wrptr <= wrptr; // Hold value, nothing to load
103+
end
104+
105+
// Manage read pointer.
106+
always @(posedge(clock))
107+
begin
108+
if (reset == 1'b1)
109+
rdptr <= 3'b000; // Initialize to location 0
110+
else if (cmd_dispatched == 1'b1 && rdptr != 3'b111)
111+
rdptr <= rdptr + 3'b001; // Move to next location, this one is complete
112+
else if (cmd_dispatched == 1'b1 && rdptr == 3'b111)
113+
rdptr <= 3'b000; // Move to next location, but wrap around
114+
else
115+
rdptr <= rdptr; // Hold value, no operation or operation is still in progress
116+
end
117+
118+
// Manage valid indicator
119+
always @(posedge(clock))
120+
begin
121+
if (reset == 1'b1)
122+
cmdfifo_val <= 8'h00; // Initialize to all 0, all rows are free
123+
else if (cmd_in_valid == 1'b1 && cmd_dispatched == 1'b0)
124+
cmdfifo_val <= cmdfifo_val | (8'h01 << wrptr); // When loading, set wrptr bit to 1
125+
else if (cmd_in_valid == 1'b0 && cmd_dispatched == 1'b1)
126+
cmdfifo_val <= cmdfifo_val & ~(8'h01 << rdptr); // When done, set rdptr bit to 0
127+
else if (cmd_in_valid == 1'b1 && cmd_dispatched == 1'b1)
128+
cmdfifo_val <= (cmdfifo_val | (8'h01 << wrptr)) & ~(8'h01 << rdptr); // Both set and clear a bit
129+
else
130+
cmdfifo_val <= cmdfifo_val; // Hold value if neither bit is set
131+
end
132+
133+
// Manage row contents
134+
// Note: Contents of array row will be 'X' until written the first time, but this should be OK.
135+
always @(posedge(clock))
136+
if (cmd_in_valid) cmdfifo[wrptr] <= cmd_in; // Use code format recommended by Vivado
137+
// cmdfifo[wrptr] <= (cmd_in_valid == 1'b1) ? cmd_in : cmdfifo[wrptr]; // (Equivalent logically to above) Load or hold array row
138+
139+
// Manage data output and valid. If valid is not set, drive 0's which should decode to NOP.
140+
// Note: In order to enable 1 cmd presented each cycle in pipeline mode, cannot register cmd_out or cmd_out_valid
141+
assign cmd_out_valid = cmdfifo_val[rdptr];
142+
assign cmd_out = (cmdfifo_val[rdptr] == 1'b1) ? cmdfifo[rdptr] : {WIDTH{1'b0}};
143+
144+
145+
// Check for overflow
146+
assign fifo_overflow = (cmd_in_valid == 1'b1 && cmdfifo_val == 8'hFF) ? 1'b1 : 1'b0;
147+
148+
149+
// After resync_credits falls (1->0) delay sending credits for a number of cycles, giving time for the other side to
150+
// get ready to receive them. There might be a difference in propagation cycles of resync_credits from CFG to the
151+
// various destinations due to fan out or internal register buffering for timing closure.
152+
reg [7:0] resync_credits_dly_q; // Use delay chain to hold off sending credits
153+
always @(posedge(clock))
154+
begin
155+
resync_credits_dly_q[7] <= (reset | resync_credits); // Hold off if got either reset or resync_credits signal
156+
resync_credits_dly_q[6:0] <= resync_credits_dly_q[7:1];
157+
end
158+
wire ok_to_send_credits;
159+
assign ok_to_send_credits = ~(|resync_credits_dly_q); // Set bit only when all bits in delay chain are 0 (| is OR Reduce operator)
160+
161+
// Generate a pulse for each free entry in the FIFO, which is used as 'cmd_credit' back to the TLX
162+
// a) At reset or resync_credits when the FIFO is empty, send 'number of FIFO entries' pulses as initial credits
163+
// b) After initial credits have been given, pulse once each time a command is removed from the FIFO
164+
// Special case: When command is removed while there are still initial credits being issued, don't lose a credit.
165+
// NOTE: Because this logic manages initial cmd credits, set 'afu_tlx_cmd_initial_credit' to 0.
166+
reg [3:0] initial_credits;
167+
always @(posedge(clock))
168+
begin
169+
if (reset == 1'b1 || resync_credits == 1'b1)
170+
initial_credits <= 4'b1000; // Initialize to number of FIFO entries
171+
// initial_credits <= 4'b1001; // Initialize to number of FIFO entries (use this to force 'fifo_overflow' during testing)
172+
else if (tlx_is_ready == 1'b0)
173+
initial_credits <= initial_credits; // While TLX is still initializing, keep credits but don't send them
174+
else if (cmd_dispatched == 1'b1 && initial_credits > 4'b0000)
175+
initial_credits <= initial_credits; // If cmd is removed from FIFO before initial credits are issued, hold off on decrementing.
176+
else if (initial_credits > 4'b0000 && ok_to_send_credits == 1'b1)
177+
initial_credits <= initial_credits - 4'b0001; // Decrement 'number of FIFO entries' times, not counting cycles when cmd is removed from FIFO.
178+
else
179+
initial_credits <= initial_credits; // Hold at 0 when it reaches 0. From here on, only removing cmd from FIFO issues credits.
180+
end
181+
182+
//assign cmd_credit_to_TLX = (tlx_is_ready == 1'b1 && (cmd_dispatched == 1'b1 || initial_credits != 4'b0000)) ? 1'b1 : 1'b0;
183+
// To meet timing, register cmd_credit_to_TLX before sending to the TLX. A one cycle delay shouldn't hurt anything except increase the
184+
// latency in the TLX->CFF->TLX command credit loop by a cycle.
185+
reg cmd_credit_to_TLX_q;
186+
always @(posedge(clock))
187+
if (reset == 1'b1 || resync_credits == 1'b1) // Stop sending credits on either reset or resync_credits
188+
cmd_credit_to_TLX_q <= 1'b0;
189+
else
190+
cmd_credit_to_TLX_q <= (tlx_is_ready == 1'b1 &&
191+
(cmd_dispatched == 1'b1 || (initial_credits > 4'b0000 && ok_to_send_credits == 1'b1))
192+
) ? 1'b1 : 1'b0;
193+
assign cmd_credit_to_TLX = cmd_credit_to_TLX_q;
194+
195+
endmodule

0 commit comments

Comments
 (0)