blob: 77a9e2aeee2d86bfbd5a38962703c864e069fc3f [file] [log] [blame]
`timescale 1ns / 1ps
`include "include.v"
module neuron #(parameter layerNo=0,
neuronNo=0,
numWeight=784,
dataWidth=16,
sigmoidSize=5,
weightIntWidth=1,
actType="sigmoid",
biasFile="b_1_0.mif",
weightFile="w_1_0.mif")
(
input clk,
input rst,
input [dataWidth-1:0] myinput,
input myinputValid,
output[dataWidth-1:0] out,
output reg outvalid
);
parameter addressWidth = $clog2(numWeight);
reg wen;
wire ren;
reg [addressWidth-1:0] w_addr;
reg [addressWidth:0] r_addr;//read address has to reach until numWeight hence width is 1 bit more
reg [dataWidth-1:0] w_in;
wire [dataWidth-1:0] w_out;
reg [2*dataWidth-1:0] mul;
reg [2*dataWidth-1:0] sum;
reg [2*dataWidth-1:0] bias;
reg [31:0] biasReg[0:0];
reg weight_valid;
reg mult_valid;
wire mux_valid;
reg sigValid;
wire [2*dataWidth:0] comboAdd;
wire [2*dataWidth:0] BiasAdd;
reg [dataWidth-1:0] myinputd;
reg muxValid_d;
reg muxValid_f;
reg addr=0;
//Loading weight values into the momory
// always @(posedge clk)
// begin
// if(rst)
// begin
// w_addr <= {addressWidth{1'b1}};
// wen <=0;
// end
// else if(weightValid & (config_layer_num==layerNo) & (config_neuron_num==neuronNo))
// begin
// w_in <= weightValue;
// w_addr <= w_addr + 1;
// wen <= 1;
// end
// else
// wen <= 0;
// end
assign mux_valid = mult_valid;
assign comboAdd = mul + sum;
assign BiasAdd = bias + sum;
assign ren = myinputValid;
`ifdef pretrained
initial
begin
$readmemb(biasFile,biasReg);
end
always @(posedge clk)
begin
bias <= {biasReg[addr][dataWidth-1:0],{dataWidth{1'b0}}};
end
// `else
// always @(posedge clk)
// begin
// if(biasValid & (config_layer_num==layerNo) & (config_neuron_num==neuronNo))
// begin
// bias <= {biasValue[dataWidth-1:0],{dataWidth{1'b0}}};
// end
// end
`endif
always @(posedge clk)
begin
if(rst|outvalid)
r_addr <= 0;
else if(myinputValid)
r_addr <= r_addr + 1;
end
always @(posedge clk)
begin
mul <= $signed(myinputd) * $signed(w_out);
end
always @(posedge clk)
begin
if(rst|outvalid)
sum <= 0;
else if((r_addr == numWeight) & muxValid_f)
begin
if(!bias[2*dataWidth-1] &!sum[2*dataWidth-1] & BiasAdd[2*dataWidth-1]) //If bias and sum are positive and after adding bias to sum, if sign bit becomes 1, saturate
begin
sum[2*dataWidth-1] <= 1'b0;
sum[2*dataWidth-2:0] <= {2*dataWidth-1{1'b1}};
end
else if(bias[2*dataWidth-1] & sum[2*dataWidth-1] & !BiasAdd[2*dataWidth-1]) //If bias and sum are negative and after addition if sign bit is 0, saturate
begin
sum[2*dataWidth-1] <= 1'b1;
sum[2*dataWidth-2:0] <= {2*dataWidth-1{1'b0}};
end
else
sum <= BiasAdd;
end
else if(mux_valid)
begin
if(!mul[2*dataWidth-1] & !sum[2*dataWidth-1] & comboAdd[2*dataWidth-1])
begin
sum[2*dataWidth-1] <= 1'b0;
sum[2*dataWidth-2:0] <= {2*dataWidth-1{1'b1}};
end
else if(mul[2*dataWidth-1] & sum[2*dataWidth-1] & !comboAdd[2*dataWidth-1])
begin
sum[2*dataWidth-1] <= 1'b1;
sum[2*dataWidth-2:0] <= {2*dataWidth-1{1'b0}};
end
else
sum <= comboAdd;
end
end
always @(posedge clk)
begin
myinputd <= myinput;
weight_valid <= myinputValid;
mult_valid <= myinputValid;
mult_valid <= weight_valid;
sigValid <= ((r_addr == numWeight) & muxValid_f) ? 1'b1 : 1'b0;
outvalid <= sigValid;
muxValid_d <= mux_valid;
muxValid_f <= !mux_valid & muxValid_d;
end
//Instantiation of Memory for Weights
Weight_Memory #(.numWeight(numWeight),.neuronNo(neuronNo),.layerNo(layerNo),.addressWidth(addressWidth),.dataWidth(dataWidth),.weightFile(weightFile)) WM(
.clk(clk),
.wen(wen),
.ren(ren),
.wadd(w_addr),
.radd(r_addr),
.win(w_in),
.wout(w_out)
);
generate
if(actType == "sigmoid")
begin:siginst
//Instantiation of ROM for sigmoid
Sig_ROM #(.inWidth(sigmoidSize),.dataWidth(dataWidth)) s1(
.clk(clk),
.x(sum[2*dataWidth-1-:sigmoidSize]),
.out(out)
);
end
else
begin:ReLUinst
ReLU #(.dataWidth(dataWidth),.weightIntWidth(weightIntWidth)) s1 (
.clk(clk),
.x(sum),
.out(out)
);
end
endgenerate
`ifdef DEBUG
always @(posedge clk)
begin
if(outvalid)
$display(neuronNo,,,,"%b",out);
end
`endif
endmodule