File size: 5,662 Bytes
e4cdd5f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// ============================================================================
// Neuron Core with STDP Learning
// ============================================================================
//
// Copyright 2026 Henry Arthur Shulayev Barnes / Catalyst Neuromorphic Ltd
// Company No. 17054540 — UK Patent Application No. 2602902.6
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ============================================================================

module neuron_core_stdp #(
    parameter NUM_NEURONS  = 4,
    parameter DATA_WIDTH   = 16,
    parameter THRESHOLD    = 16'd1000,
    parameter LEAK_RATE    = 16'd2,
    parameter WEIGHT_INIT  = 16'd100,
    parameter WEIGHT_MAX   = 16'd800,
    parameter LEARN_RATE   = 8'd3
)(
    input  wire                    clk,
    input  wire                    rst_n,
    input  wire                    enable,
    input  wire                    learn_enable,

    input  wire signed [DATA_WIDTH-1:0] ext_input_0,
    input  wire signed [DATA_WIDTH-1:0] ext_input_1,
    input  wire signed [DATA_WIDTH-1:0] ext_input_2,
    input  wire signed [DATA_WIDTH-1:0] ext_input_3,

    output wire [NUM_NEURONS-1:0] spikes,

    output wire [DATA_WIDTH-1:0] membrane_0,
    output wire [DATA_WIDTH-1:0] membrane_1,
    output wire [DATA_WIDTH-1:0] membrane_2,
    output wire [DATA_WIDTH-1:0] membrane_3,

    output wire signed [DATA_WIDTH-1:0] w_out_01, w_out_02, w_out_03,
    output wire signed [DATA_WIDTH-1:0] w_out_10, w_out_12, w_out_13,
    output wire signed [DATA_WIDTH-1:0] w_out_20, w_out_21, w_out_23,
    output wire signed [DATA_WIDTH-1:0] w_out_30, w_out_31, w_out_32
);

    wire signed [DATA_WIDTH-1:0] syn_current [0:3][0:3];
    wire signed [DATA_WIDTH-1:0] syn_weight  [0:3][0:3];
    wire signed [DATA_WIDTH-1:0] total_input [0:3];

    wire signed [DATA_WIDTH-1:0] ext_inputs [0:3];
    assign ext_inputs[0] = ext_input_0;
    assign ext_inputs[1] = ext_input_1;
    assign ext_inputs[2] = ext_input_2;
    assign ext_inputs[3] = ext_input_3;

    genvar src, dst;
    generate
        for (src = 0; src < NUM_NEURONS; src = src + 1) begin : syn_src
            for (dst = 0; dst < NUM_NEURONS; dst = dst + 1) begin : syn_dst
                if (src != dst) begin : real_syn
                    stdp_synapse #(
                        .DATA_WIDTH  (DATA_WIDTH),
                        .WEIGHT_INIT (WEIGHT_INIT),
                        .WEIGHT_MAX  (WEIGHT_MAX),
                        .LEARN_RATE  (LEARN_RATE)
                    ) syn_inst (
                        .clk           (clk),
                        .rst_n         (rst_n),
                        .learn_enable  (learn_enable),
                        .pre_spike     (spikes[src]),
                        .post_spike    (spikes[dst]),
                        .weight        (syn_weight[src][dst]),
                        .post_current  (syn_current[src][dst]),
                        .pre_trace_out (),
                        .post_trace_out()
                    );
                end else begin : no_self
                    assign syn_current[src][dst] = 0;
                    assign syn_weight[src][dst]  = 0;
                end
            end
        end
    endgenerate

    assign total_input[0] = ext_inputs[0] + syn_current[0][0] + syn_current[1][0] + syn_current[2][0] + syn_current[3][0];
    assign total_input[1] = ext_inputs[1] + syn_current[0][1] + syn_current[1][1] + syn_current[2][1] + syn_current[3][1];
    assign total_input[2] = ext_inputs[2] + syn_current[0][2] + syn_current[1][2] + syn_current[2][2] + syn_current[3][2];
    assign total_input[3] = ext_inputs[3] + syn_current[0][3] + syn_current[1][3] + syn_current[2][3] + syn_current[3][3];

    generate
        for (dst = 0; dst < NUM_NEURONS; dst = dst + 1) begin : neurons
            lif_neuron #(
                .DATA_WIDTH (DATA_WIDTH),
                .THRESHOLD  (THRESHOLD),
                .LEAK_RATE  (LEAK_RATE)
            ) neuron_inst (
                .clk            (clk),
                .rst_n          (rst_n),
                .enable         (enable),
                .synaptic_input (total_input[dst]),
                .spike          (spikes[dst]),
                .membrane_pot   ()
            );
        end
    endgenerate

    assign membrane_0 = neurons[0].neuron_inst.membrane_pot;
    assign membrane_1 = neurons[1].neuron_inst.membrane_pot;
    assign membrane_2 = neurons[2].neuron_inst.membrane_pot;
    assign membrane_3 = neurons[3].neuron_inst.membrane_pot;

    assign w_out_01 = syn_weight[0][1];
    assign w_out_02 = syn_weight[0][2];
    assign w_out_03 = syn_weight[0][3];
    assign w_out_10 = syn_weight[1][0];
    assign w_out_12 = syn_weight[1][2];
    assign w_out_13 = syn_weight[1][3];
    assign w_out_20 = syn_weight[2][0];
    assign w_out_21 = syn_weight[2][1];
    assign w_out_23 = syn_weight[2][3];
    assign w_out_30 = syn_weight[3][0];
    assign w_out_31 = syn_weight[3][1];
    assign w_out_32 = syn_weight[3][2];

endmodule