Initial commit

This commit is contained in:
2026-02-27 09:47:31 +01:00
parent ddde38deca
commit e7c1016ea0
14 changed files with 132181 additions and 0 deletions

199
LICENSE Normal file
View File

@@ -0,0 +1,199 @@
CERN Open Hardware Licence Version 2 - Permissive
Preamble
CERN has developed this licence to promote collaboration among
hardware designers and to provide a legal tool which supports the
freedom to use, study, modify, share and distribute hardware designs
and products based on those designs. Version 2 of the CERN Open
Hardware Licence comes in three variants: this licence, CERN-OHL-P
(permissive); and two reciprocal licences: CERN-OHL-W (weakly
reciprocal) and CERN-OHL-S (strongly reciprocal).
The CERN-OHL-P is copyright CERN 2020. Anyone is welcome to use it, in
unmodified form only.
Use of this Licence does not imply any endorsement by CERN of any
Licensor or their designs nor does it imply any involvement by CERN in
their development.
1 Definitions
1.1 'Licence' means this CERN-OHL-P.
1.2 'Source' means information such as design materials or digital
code which can be applied to Make or test a Product or to
prepare a Product for use, Conveyance or sale, regardless of its
medium or how it is expressed. It may include Notices.
1.3 'Covered Source' means Source that is explicitly made available
under this Licence.
1.4 'Product' means any device, component, work or physical object,
whether in finished or intermediate form, arising from the use,
application or processing of Covered Source.
1.5 'Make' means to create or configure something, whether by
manufacture, assembly, compiling, loading or applying Covered
Source or another Product or otherwise.
1.6 'Notice' means copyright, acknowledgement and trademark notices,
references to the location of any Notices, modification notices
(subsection 3.3(b)) and all notices that refer to this Licence
and to the disclaimer of warranties that are included in the
Covered Source.
1.7 'Licensee' or 'You' means any person exercising rights under
this Licence.
1.8 'Licensor' means a person who creates Source or modifies Covered
Source and subsequently Conveys the resulting Covered Source
under the terms and conditions of this Licence. A person may be
a Licensee and a Licensor at the same time.
1.9 'Convey' means to communicate to the public or distribute.
2 Applicability
2.1 This Licence governs the use, copying, modification, Conveying
of Covered Source and Products, and the Making of Products. By
exercising any right granted under this Licence, You irrevocably
accept these terms and conditions.
2.2 This Licence is granted by the Licensor directly to You, and
shall apply worldwide and without limitation in time.
2.3 You shall not attempt to restrict by contract or otherwise the
rights granted under this Licence to other Licensees.
2.4 This Licence is not intended to restrict fair use, fair dealing,
or any other similar right.
3 Copying, Modifying and Conveying Covered Source
3.1 You may copy and Convey verbatim copies of Covered Source, in
any medium, provided You retain all Notices.
3.2 You may modify Covered Source, other than Notices.
You may only delete Notices if they are no longer applicable to
the corresponding Covered Source as modified by You and You may
add additional Notices applicable to Your modifications.
3.3 You may Convey modified Covered Source (with the effect that You
shall also become a Licensor) provided that You:
a) retain Notices as required in subsection 3.2; and
b) add a Notice to the modified Covered Source stating that You
have modified it, with the date and brief description of how
You have modified it.
3.4 You may Convey Covered Source or modified Covered Source under
licence terms which differ from the terms of this Licence
provided that You:
a) comply at all times with subsection 3.3; and
b) provide a copy of this Licence to anyone to whom You
Convey Covered Source or modified Covered Source.
4 Making and Conveying Products
You may Make Products, and/or Convey them, provided that You ensure
that the recipient of the Product has access to any Notices applicable
to the Product.
5 DISCLAIMER AND LIABILITY
5.1 DISCLAIMER OF WARRANTY -- The Covered Source and any Products
are provided 'as is' and any express or implied warranties,
including, but not limited to, implied warranties of
merchantability, of satisfactory quality, non-infringement of
third party rights, and fitness for a particular purpose or use
are disclaimed in respect of any Source or Product to the
maximum extent permitted by law. The Licensor makes no
representation that any Source or Product does not or will not
infringe any patent, copyright, trade secret or other
proprietary right. The entire risk as to the use, quality, and
performance of any Source or Product shall be with You and not
the Licensor. This disclaimer of warranty is an essential part
of this Licence and a condition for the grant of any rights
granted under this Licence.
5.2 EXCLUSION AND LIMITATION OF LIABILITY -- The Licensor shall, to
the maximum extent permitted by law, have no liability for
direct, indirect, special, incidental, consequential, exemplary,
punitive or other damages of any character including, without
limitation, procurement of substitute goods or services, loss of
use, data or profits, or business interruption, however caused
and on any theory of contract, warranty, tort (including
negligence), product liability or otherwise, arising in any way
in relation to the Covered Source, modified Covered Source
and/or the Making or Conveyance of a Product, even if advised of
the possibility of such damages, and You shall hold the
Licensor(s) free and harmless from any liability, costs,
damages, fees and expenses, including claims by third parties,
in relation to such use.
6 Patents
6.1 Subject to the terms and conditions of this Licence, each
Licensor hereby grants to You a perpetual, worldwide,
non-exclusive, no-charge, royalty-free, irrevocable (except as
stated in this section 6, or where terminated by the Licensor
for cause) patent licence to Make, have Made, use, offer to
sell, sell, import, and otherwise transfer the Covered Source
and Products, where such licence applies only to those patent
claims licensable by such Licensor that are necessarily
infringed by exercising rights under the Covered Source as
Conveyed by that Licensor.
6.2 If You institute patent litigation against any entity (including
a cross-claim or counterclaim in a lawsuit) alleging that the
Covered Source or a Product constitutes direct or contributory
patent infringement, or You seek any declaration that a patent
licensed to You under this Licence is invalid or unenforceable
then any rights granted to You under this Licence shall
terminate as of the date such process is initiated.
7 General
7.1 If any provisions of this Licence are or subsequently become
invalid or unenforceable for any reason, the remaining
provisions shall remain effective.
7.2 You shall not use any of the name (including acronyms and
abbreviations), image, or logo by which the Licensor or CERN is
known, except where needed to comply with section 3, or where
the use is otherwise allowed by law. Any such permitted use
shall be factual and shall not be made so as to suggest any kind
of endorsement or implication of involvement by the Licensor or
its personnel.
7.3 CERN may publish updated versions and variants of this Licence
which it considers to be in the spirit of this version, but may
differ in detail to address new problems or concerns. New
versions will be published with a unique version number and a
variant identifier specifying the variant. If the Licensor has
specified that a given variant applies to the Covered Source
without specifying a version, You may treat that Covered Source
as being released under any version of the CERN-OHL with that
variant. If no variant is specified, the Covered Source shall be
treated as being released under CERN-OHL-S. The Licensor may
also specify that the Covered Source is subject to a specific
version of the CERN-OHL or any later version in which case You
may apply this or any later version of CERN-OHL with the same
variant identifier published by CERN.
7.4 This Licence shall not be enforceable except by a Licensor
acting as such, and third party beneficiary rights are
specifically excluded.

79
constrs/default.xdc Normal file
View File

@@ -0,0 +1,79 @@
# Controller clock
create_clock -period 10.000 -name CLK -waveform {0.000 5.000} [get_ports CLK]
set_clock_latency 0.500 [all_clocks]
set_property PACKAGE_PIN AF11 [get_ports AEROUT_ADDR_T[0]]
set_property IOSTANDARD LVCMOS33 [get_ports AEROUT_ADDR_T[0]]
set_property PACKAGE_PIN AG11 [get_ports AEROUT_ADDR_F[0]]
set_property IOSTANDARD LVCMOS33 [get_ports AEROUT_ADDR_F[0]]
set_property PACKAGE_PIN AH12 [get_ports AEROUT_ADDR_T[1]]
set_property IOSTANDARD LVCMOS33 [get_ports AEROUT_ADDR_T[1]]
set_property PACKAGE_PIN J11 [get_ports AEROUT_ADDR_F[1]]
set_property IOSTANDARD LVCMOS33 [get_ports AEROUT_ADDR_F[1]]
set_property PACKAGE_PIN J10 [get_ports AEROUT_ADDR_T[2]]
set_property IOSTANDARD LVCMOS33 [get_ports AEROUT_ADDR_T[2]]
set_property PACKAGE_PIN K13 [get_ports AEROUT_ADDR_F[2]]
set_property IOSTANDARD LVCMOS33 [get_ports AEROUT_ADDR_F[2]]
set_property PACKAGE_PIN K12 [get_ports AEROUT_ADDR_T[3]]
set_property IOSTANDARD LVCMOS33 [get_ports AEROUT_ADDR_T[3]]
set_property PACKAGE_PIN H11 [get_ports AEROUT_ADDR_F[3]]
set_property IOSTANDARD LVCMOS33 [get_ports AEROUT_ADDR_F[3]]
set_property PACKAGE_PIN G10 [get_ports AEROUT_ADDR_T[4]]
set_property IOSTANDARD LVCMOS33 [get_ports AEROUT_ADDR_T[4]]
set_property PACKAGE_PIN F12 [get_ports AEROUT_ADDR_F[4]]
set_property IOSTANDARD LVCMOS33 [get_ports AEROUT_ADDR_F[4]]
set_property PACKAGE_PIN AC12 [get_ports AEROUT_ADDR_T[5]]
set_property IOSTANDARD LVCMOS33 [get_ports AEROUT_ADDR_T[5]]
set_property PACKAGE_PIN AD12 [get_ports AEROUT_ADDR_F[5]]
set_property IOSTANDARD LVCMOS33 [get_ports AEROUT_ADDR_F[5]]
set_property PACKAGE_PIN AE10 [get_ports AEROUT_ADDR_T[6]]
set_property IOSTANDARD LVCMOS33 [get_ports AEROUT_ADDR_T[6]]
set_property PACKAGE_PIN AF10 [get_ports AEROUT_ADDR_F[6]]
set_property IOSTANDARD LVCMOS33 [get_ports AEROUT_ADDR_F[6]]
set_property PACKAGE_PIN AD11 [get_ports AEROUT_ADDR_T[7]]
set_property IOSTANDARD LVCMOS33 [get_ports AEROUT_ADDR_T[7]]
set_property PACKAGE_PIN AD10 [get_ports AEROUT_ADDR_F[7]]
set_property IOSTANDARD LVCMOS33 [get_ports AEROUT_ADDR_F[7]]
set_property PACKAGE_PIN AA11 [get_ports AEROUT_ADDR_T[8]]
set_property IOSTANDARD LVCMOS33 [get_ports AEROUT_ADDR_T[8]]
set_property PACKAGE_PIN AA10 [get_ports AEROUT_ADDR_F[8]]
set_property IOSTANDARD LVCMOS33 [get_ports AEROUT_ADDR_F[8]]
set_property PACKAGE_PIN AE12 [get_ports AEROUT_ACK]
set_property IOSTANDARD LVCMOS33 [get_ports AEROUT_ACK]
set_property PACKAGE_PIN C3 [get_ports CLK]
set_property IOSTANDARD LVCMOS18 [get_ports CLK]
set_property PACKAGE_PIN AF12 [get_ports RSTN_O]
set_property IOSTANDARD LVCMOS33 [get_ports RSTN_O]
set_property PACKAGE_PIN AH10 [get_ports AERIN_REQ]
set_property IOSTANDARD LVCMOS33 [get_ports AERIN_REQ]
set_property PACKAGE_PIN AG10 [get_ports AERIN_ACK]
set_property IOSTANDARD LVCMOS33 [get_ports AERIN_ACK]
set_property PACKAGE_PIN H12 [get_ports AERIN_ADDR[4]]
set_property IOSTANDARD LVCMOS33 [get_ports AERIN_ADDR[4]]
set_property PACKAGE_PIN E10 [get_ports AERIN_ADDR[3]]
set_property IOSTANDARD LVCMOS33 [get_ports AERIN_ADDR[3]]
set_property PACKAGE_PIN D10 [get_ports AERIN_ADDR[2]]
set_property IOSTANDARD LVCMOS33 [get_ports AERIN_ADDR[2]]
set_property PACKAGE_PIN C11 [get_ports AERIN_ADDR[1]]
set_property IOSTANDARD LVCMOS33 [get_ports AERIN_ADDR[1]]
set_property PACKAGE_PIN B10 [get_ports AERIN_ADDR[0]]
set_property IOSTANDARD LVCMOS33 [get_ports AERIN_ADDR[0]]

131074
iladata.csv Normal file

File diff suppressed because it is too large Load Diff

BIN
iladata.ila Normal file

Binary file not shown.

0
sim/mem_stim_db.sv Normal file
View File

67
sim/mem_stim_tb.sv Normal file
View File

@@ -0,0 +1,67 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 02/20/2026 02:02:47 PM
// Design Name:
// Module Name: mem_stim_tb
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
`define CLK_HALF_PERIOD 2
module mem_stim_tb(
);
logic CLK;
logic RST_N;
logic ACK;
logic [8:0] ADDR_T;
logic [8:0] ADDR_F;
wire END_SIG;
initial begin
CLK = 1'b0;
forever #(`CLK_HALF_PERIOD) CLK = ~CLK;
end
initial begin
RST_N = 1'b0;
#(4 * `CLK_HALF_PERIOD);
RST_N = 1'b1;
#(20 * `CLK_HALF_PERIOD);
end
mem_stim #(
.DATA_WIDTH(9)
) ut (
.clk(CLK),
.rst_n(RST_N),
.restart(~RST_N),
.ack(ACK),
.addr_t(ADDR_T),
.addr_f(ADDR_F),
.done(END_SIG)
);
autoack auto_ack (
.CLK(CLK),
.RST(!RST_N),
.OUTPUT_BITS_ONION_p(ADDR_T),
.OUTPUT_BITS_ONION_n(ADDR_F),
.OUTPUT_BITS_ONION_A_AO(ACK)
);
endmodule

163
sim/olla_testack.sv Normal file
View File

@@ -0,0 +1,163 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 02/16/2026 08:28:02 PM
// Design Name:
// Module Name: olla_testack
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module autoack (
input logic CLK,
input logic RST,
input logic [8:0] OUTPUT_BITS_ONION_p,
input logic [8:0] OUTPUT_BITS_ONION_n,
output logic OUTPUT_BITS_ONION_A_AO
);
//---------------------------------------------------------
// Local Parameters
//---------------------------------------------------------
localparam int COUNTER_WIDTH = 27;
// Örnek: CLK = 25 MHz ise 25,000,000 çevrim 1 saniyedir.
// localparam int ONE_SEC_LIMIT = 25_000_000 - 1;
localparam int ONE_SEC_LIMIT = 5 - 1;
//---------------------------------------------------------
// Internal Signals
//---------------------------------------------------------
// FSM State Definitions
typedef enum logic [3:0] {
S_WAIT_DATA_BLANK, // Faz 1: Veri hatlarının ve ACK'nin 0 olmasını bekle.
S_DATA_LATCH, // Faz 2: Veri geldi, veriyi/adresi yakala.
S_TIMER_START, // LED zamanlayıcısını başlat (Sayacı sıfırla).
S_TIMER_WAIT, // LED açıkken 1 saniye bekle (ON Time).
S_LED_BLANK_WAIT, // LED kapalıyken 1 saniye bekle (OFF Time).
S_SEND_ACK, // Faz 3: ACK'yi '1' yap.
S_WAIT_DATA_BLANK_LOW, // Faz 4: Göndericinin veri hatlarını '0' çekmesini bekle.
S_ACK_LOW // Faz 5: ACK'yi '0' yap ve S_WAIT_DATA_BLANK'e dön.
} state_t;
state_t state, next_state;
logic [COUNTER_WIDTH-1:0] counter_reg;
//---------------------------------------------------------
// 1. Dual-Rail Veri Kontrolü
//---------------------------------------------------------
// 'data_arrived' sinyali: Data hatlarından herhangi biri '1' ise veri gelmiştir.
logic data_arrived;
assign data_arrived = |OUTPUT_BITS_ONION_p | |OUTPUT_BITS_ONION_n;
// 'data_is_blank' sinyali: Tüm data hatları '0' ise hat boş/temizdir.
logic data_is_blank;
assign data_is_blank = ~data_arrived;
//---------------------------------------------------------
// 2. Sequential Logic: Counter Register
//---------------------------------------------------------
always_ff @(posedge CLK)
begin
if (RST) begin
counter_reg <= '0;
end
else begin
// Counter Logic: Increments in S_TIMER_WAIT (LED ON time)
// OR S_LED_BLANK_WAIT (LED OFF time)
if (state == S_TIMER_WAIT || state == S_LED_BLANK_WAIT) begin
if (counter_reg == ONE_SEC_LIMIT)
counter_reg <= '0;
else
counter_reg <= counter_reg + 1;
end
// Reset counter when a new timer sequence starts
else if (state == S_TIMER_START)
counter_reg <= '0;
// Reset counter in other states if it's not already 0 (safety)
else if (counter_reg != '0 && state != S_TIMER_WAIT && state != S_LED_BLANK_WAIT)
counter_reg <= '0;
end
end
//---------------------------------------------------------
// 3. Sequential Logic: State Register
//---------------------------------------------------------
always_ff @(posedge CLK)
begin
if (RST) state <= S_WAIT_DATA_BLANK;
else state <= next_state;
end
//----------------------------------------------------------
// 4. Combinational Logic: Next State Determination (FSM)
//----------------------------------------------------------
always_comb begin
next_state = state;
case (state)
S_WAIT_DATA_BLANK: // Faz 1: Hatların boş olmasını bekle
if (data_arrived) // Veri geldiğinde (Dual-rail sinyalleri 0'dan farklı)
next_state = S_DATA_LATCH;
S_DATA_LATCH: // Faz 2: Veri geldi, zamanlayıcıyı başlat
next_state = S_TIMER_START;
S_TIMER_START: // LED ON süresini başlatmak için sayacı sıfırla
next_state = S_TIMER_WAIT;
S_TIMER_WAIT: // LED açıkken 1 saniye bekle
if (counter_reg == ONE_SEC_LIMIT)
next_state = S_LED_BLANK_WAIT; // LED'i söndürme süresine geç
S_LED_BLANK_WAIT: // LED kapalıyken 1 saniye bekle (Blink süresi)
if (counter_reg == ONE_SEC_LIMIT)
next_state = S_SEND_ACK; // ACK gönderme döngüsüne geç
S_SEND_ACK: // Faz 3: ACK'yi '1' yap
next_state = S_WAIT_DATA_BLANK_LOW;
S_WAIT_DATA_BLANK_LOW: // Faz 4: Göndericinin veri hatlarını '0' çekmesini bekle
if (data_is_blank) // Veri hatları boşaldı (tümü '0')
next_state = S_ACK_LOW;
S_ACK_LOW: // Faz 5: ACK'yi '0' yap
next_state = S_WAIT_DATA_BLANK;
default:
next_state = S_WAIT_DATA_BLANK;
endcase
end
//-----------------------------------------------------------
// 5. Combinational Logic: Output Generation
//-----------------------------------------------------------
always_comb begin
// Default değerler
OUTPUT_BITS_ONION_A_AO = 1'b0;
case (state)
S_SEND_ACK, S_WAIT_DATA_BLANK_LOW:
OUTPUT_BITS_ONION_A_AO = 1'b1;
default: ;
endcase
end
endmodule

65
sim/stimulus_gen_tb.sv Normal file
View File

@@ -0,0 +1,65 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 02/16/2026 05:49:17 PM
// Design Name:
// Module Name: stimulus_gen_tb
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
`define CLK_HALF_PERIOD 2
module stimulus_gen_tb(
);
logic CLK;
logic RST;
logic ACK;
logic REQ;
logic [4:0] ADDR;
wire END_SIG;
initial begin
CLK = 1'b0;
forever #(`CLK_HALF_PERIOD) CLK = ~CLK;
end
initial begin
RST = 1'b1;
#(4 * `CLK_HALF_PERIOD);
RST = 1'b0;
#(20 * `CLK_HALF_PERIOD);
end
always_ff @(posedge CLK)
begin
if (REQ) begin
ACK <= 1'b1;
end else begin
ACK <= 1'b0;
end
end
stimulus_gen #() ut (
.CLK_I(CLK),
.RST_I(RST),
.REQ_O(REQ),
.ACK_I(ACK),
.ADDR_O(ADDR),
.END_O(END_SIG)
);
endmodule

70
sim/top_interface_tb.sv Normal file
View File

@@ -0,0 +1,70 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 02/16/2026 07:33:07 PM
// Design Name:
// Module Name: top_interface_tb
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
`define CLK_HALF_PERIOD 2
module top_interface_tb(
);
logic CLK;
logic RSTN;
logic AERIN_REQ;
logic AERIN_ACK;
logic [4:0] AERIN_ADDR;
logic AEROUT_ACK;
logic [8:0] AEROUT_ADDR_T;
logic [8:0] AEROUT_ADDR_F;
initial begin
CLK = 1'b0;
forever #(`CLK_HALF_PERIOD) CLK = ~CLK;
end
assign RST = !RSTN;
top_interface #() ut (
.CLK(CLK),
.RSTN_O(RSTN),
.AERIN_REQ(AERIN_REQ),
.AERIN_ADDR(AERIN_ADDR),
.AERIN_ACK(AERIN_ACK),
.AEROUT_ACK(AEROUT_ACK),
.AEROUT_ADDR_T(AEROUT_ADDR_T),
.AEROUT_ADDR_F(AEROUT_ADDR_F)
);
autoack auto_ack (
.CLK(CLK),
.RST(RST),
.OUTPUT_BITS_ONION_p(AEROUT_ADDR_T),
.OUTPUT_BITS_ONION_n(AEROUT_ADDR_F),
.OUTPUT_BITS_ONION_A_AO(AEROUT_ACK)
);
stimulus_gen #() stim (
.CLK_I(CLK),
.RST_I(RST),
.REQ_O(AERIN_REQ),
.ACK_I(AERIN_ACK),
.ADDR_O(AERIN_ADDR)
);
endmodule

154
src/mem_stim.sv Normal file
View File

@@ -0,0 +1,154 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 02/17/2026 05:28:09 PM
// Design Name:
// Module Name: mem_stim
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module mem_stim #(
parameter int DATA_WIDTH = 9,
parameter string MEM_FILE = "stim.mem",
parameter int MAX_EVENTS = 1024
)(
input logic clk,
input logic rst_n,
input logic restart,
input logic ack,
output logic [DATA_WIDTH-1:0] addr_t,
output logic [DATA_WIDTH-1:0] addr_f,
output logic done
);
typedef enum logic [2:0] {
S_LOAD,
S_WAIT,
S_SEND,
S_WAIT_ACK_HIGH,
S_WAIT_ACK_LOW,
S_DONE
} state_t;
state_t state;
logic [31-DATA_WIDTH:0] delay_counter;
wire [31:0] mem_data;
wire [DATA_WIDTH-1:0] event_addr;
wire [31-DATA_WIDTH:0] DELAY_LIMIT;
reg [11:0] mem_addr;
wire test;
assign test = (mem_data != 32'hFFFF_FFFF);
always_ff @(posedge clk or negedge rst_n)
begin
if (!rst_n || restart) begin
state <= S_LOAD;
delay_counter <= {32-DATA_WIDTH{1'b0}};
addr_t <= {DATA_WIDTH{1'b0}};
addr_f <= {DATA_WIDTH{1'b0}};
done <= 1'b0;
mem_addr <= 12'b0;
end else begin
delay_counter <= delay_counter + 1;
case (state)
S_LOAD: begin
addr_t <= {DATA_WIDTH{1'b0}};
addr_f <= {DATA_WIDTH{1'b0}};
done <= 1'b0;
if (mem_addr < MAX_EVENTS) begin
state <= S_WAIT;
end else begin
state <= S_DONE;
end
end
S_WAIT: begin
if (mem_data == 32'hFFFF_FFFF)
state <= S_DONE;
else if (delay_counter >= DELAY_LIMIT)
state <= S_SEND;
end
S_SEND: begin
addr_t <= event_addr;
addr_f <= ~event_addr;
state <= S_WAIT_ACK_HIGH;
end
S_WAIT_ACK_HIGH: begin
if (ack) begin
state <= S_WAIT_ACK_LOW;
addr_t <= {DATA_WIDTH{1'b0}};
addr_f <= {DATA_WIDTH{1'b0}};
end
end
S_WAIT_ACK_LOW: begin
if (!ack) begin
mem_addr <= mem_addr + 1;
state <= S_LOAD;
end
end
S_DONE: begin
done <= 1'b1;
end
endcase
end
end
assign event_addr = mem_data[DATA_WIDTH-1:0];
assign DELAY_LIMIT = mem_data[31:DATA_WIDTH];
BRAM_stim #(.MEM_FILE(MEM_FILE)) mem (
.clk(clk),
.A(mem_addr),
.Q(mem_data)
);
endmodule
module BRAM_stim #(
parameter string MEM_FILE = "stim.mem"
)(
input logic clk,
input logic [11:0] A,
output logic [31:0] Q
);
reg [31:0] BRAM_stim[4095:0];
reg [31:0] Qr;
assign Q = Qr;
initial begin
for (int i = 0; i < 4096; i++) begin
BRAM_stim[i] = 32'b0;
end
$readmemh(MEM_FILE, BRAM_stim);
end
always @(posedge clk) begin
Qr <= BRAM_stim[A];
end
endmodule

80
src/olla_in.sv Normal file
View File

@@ -0,0 +1,80 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 02/16/2026 04:05:38 PM
// Design Name:
// Module Name: olla_in
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module olla_in(
input logic CLK_I,
input logic RST_I,
input logic AERIN_REQ,
output logic AERIN_ACK
);
localparam int COUNTER_WIDTH = 27;
localparam int COUNTER_LIMIT = 25 - 1;
typedef enum logic [1:0] {
S_WAIT_REQ,
S_TIMER_WAIT,
S_SEND_ACK
} state_t;
state_t state, next_state;
logic [COUNTER_WIDTH-1:0] counter_reg;
always_ff @(posedge CLK_I)
begin
if (RST_I) state <= S_WAIT_REQ;
else state <= next_state;
end
always_ff @(posedge CLK_I)
begin
if (RST_I) begin
counter_reg <= '0;
end
else begin
if (state == S_TIMER_WAIT) begin
if (counter_reg == COUNTER_LIMIT)
counter_reg <= '0;
else
counter_reg <= counter_reg + 1;
end
else
counter_reg <= '0;
end
end
always_comb begin
case (state)
S_WAIT_REQ: if (AERIN_REQ) next_state = S_TIMER_WAIT;
else next_state = S_WAIT_REQ;
S_TIMER_WAIT: if (counter_reg == COUNTER_LIMIT) next_state = S_SEND_ACK;
else next_state = S_TIMER_WAIT;
S_SEND_ACK: next_state = S_WAIT_REQ;
default: next_state = S_WAIT_REQ;
endcase
end
assign AERIN_ACK = (state == S_SEND_ACK) ? 1'b1 : 1'b0;
endmodule

3
src/stim.mem Normal file
View File

@@ -0,0 +1,3 @@
000000f0
0000f050
ffffffff

125
src/stimulus_gen.sv Normal file
View File

@@ -0,0 +1,125 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 02/16/2026 05:08:08 PM
// Design Name:
// Module Name: stimulus_gen
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module stimulus_gen(
input logic CLK_I,
input logic RST_I,
input logic ACK_I,
output logic REQ_O,
output logic END_O,
output logic [4:0] ADDR_O
);
typedef enum logic [2:0] {
S_IDLE,
S_SEND_REQ,
S_WAIT_ACK_HIGH,
S_WAIT_ACK_LOW,
S_WAIT_DELAY,
S_END
} state_t;
state_t state, next_state;
logic [4:0] neuron_counter;
logic [7:0] event_counter;
logic [27:0] delay_counter;
localparam int DELAY_LIMIT = 270;
localparam int EVENT_LIMIT = 5;
assign END_O = state == S_END;
always_ff @(posedge CLK_I)
begin
if (RST_I) state <= S_IDLE;
else state <= next_state;
end
always_comb
begin
case (state)
S_IDLE: next_state = S_SEND_REQ;
S_SEND_REQ: if (ACK_I) next_state = S_WAIT_ACK_LOW;
else next_state = S_WAIT_ACK_HIGH;
S_WAIT_ACK_HIGH: if (ACK_I) next_state = S_WAIT_ACK_LOW;
else next_state = S_WAIT_ACK_HIGH;
S_WAIT_ACK_LOW: if (!ACK_I) next_state = S_WAIT_DELAY;
else next_state = S_WAIT_ACK_LOW;
S_WAIT_DELAY: if (ADDR_O == 5'd31 && event_counter == EVENT_LIMIT) next_state = S_END;
else if (delay_counter == DELAY_LIMIT) next_state = S_IDLE;
else next_state = S_WAIT_DELAY;
S_END: next_state = S_END;
default: next_state = S_IDLE;
endcase
end
always_ff @(posedge CLK_I)
begin
if (RST_I) begin
REQ_O <= 1'b0;
ADDR_O <= 5'b0;
event_counter <= 8'b0;
delay_counter <= 28'd0;
neuron_counter <= 5'd0;
end
else begin
case (state)
S_SEND_REQ: begin
REQ_O <= 1'b1;
end
S_WAIT_ACK_HIGH: begin
// Wait for receiver to acknowledge
if (ACK_I) begin
REQ_O <= 1'b0; // drop REQ
end
end
S_WAIT_ACK_LOW: begin
// Wait until ACK drops again (handshake complete)
if (!ACK_I) begin
event_counter <= event_counter + 1'b1;
delay_counter <= 28'd0;
end
end
S_WAIT_DELAY: begin
// Optional delay between events (prevents back-to-back firing)
if (event_counter == EVENT_LIMIT) begin
if (ADDR_O < 6'd31) begin
ADDR_O <= ADDR_O + 1'b1;
event_counter <= 8'd0;
end
end
if (delay_counter == DELAY_LIMIT) begin
delay_counter <= 28'd0;
end else begin
delay_counter <= delay_counter + 1'b1;
end
end
endcase
end
end
endmodule

102
src/top_interface.sv Normal file
View File

@@ -0,0 +1,102 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 02/16/2026 05:01:17 PM
// Design Name:
// Module Name: top_interface
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module top_interface(
input logic CLK,
output logic RSTN_O,
input logic AERIN_REQ,
input logic [4:0] AERIN_ADDR,
output logic AERIN_ACK,
input logic AEROUT_ACK,
output logic [8:0] AEROUT_ADDR_T,
output logic [8:0] AEROUT_ADDR_F
);
wire [4:0] AERIN_ADDR_debug;
wire [8:0] AEROUT_ADDR_T_debug;
wire [8:0] AEROUT_ADDR_F_debug;
wire AEROUT_ACK_debug, AERIN_REQ_debug, AERIN_ACK_debug;
wire RST;
wire END_SIG;
wire AERIN_REQ_N, AERIN_ACK_N;
localparam int RESET_LIMIT = 27;
assign AERIN_REQ_N = !AERIN_REQ;
assign AERIN_REQ_DEBUG = AERIN_REQ;
assign AERIN_ACK_DEBUG = !AERIN_ACK_N;
assign AERIN_ACK = AERIN_ACK_DEBUG;
assign AEROUT_ACK_debug = AEROUT_ACK;
logic [ 27:0] reset_counter = 28'd0;
always_ff @(posedge CLK)
begin
if (reset_counter != RESET_LIMIT) begin
reset_counter <= reset_counter + 1;
end else if (END_SIG) begin
reset_counter <= 25'd0;
end
end
assign RSTN_O = !RST;
assign RST = (reset_counter != RESET_LIMIT) ? 1'b1 : 1'b0;
mem_stim #(
.DATA_WIDTH(5),
.MEM_FILE("./stim.mem"),
.MAX_EVENTS(1024)
) stim (
.clk(CLK_I),
.rst_n(!RST),
.restart(RST),
.ack(AEROUT_ACK),
.addr_t(AEROUT_ADDR_T_debug),
.addr_f(AEROUT_ADDR_F_debug),
.done(END_SIG)
);
assign AEROUT_ADDR_T = AEROUT_ADDR_T_debug;
assign AEROUT_ADDR_F = AEROUT_ADDR_F_debug;
assign AERIN_ADDR_debug = AERIN_ADDR;
olla_in #() AER_interface (
.CLK_I(CLK),
.RST_I(RST),
.AERIN_REQ(AERIN_REQ_N),
.AERIN_ACK(AERIN_ACK_N)
);
ila_0 ila (
.clk(CLK),
.probe0(RST),
.probe1(AEROUT_ACK_debug),
.probe2(AEROUT_ADDR_T_debug),
.probe3(AEROUT_ADDR_F_debug),
.probe4(AERIN_REQ_debug),
.probe5(AERIN_ACK_debug),
.probe6(AERIN_ADDR_debug)
);
endmodule