mirror of
git://projects.qi-hardware.com/nn-usb-fpga.git
synced 2025-01-10 06:00:14 +02:00
331 lines
9.7 KiB
Verilog
331 lines
9.7 KiB
Verilog
|
|
// REG OFFSET 1000h
|
|
//reg0(32bit)W 0h
|
|
//reg1(32bit)W 4h
|
|
//reg2(32bit)W 8h
|
|
//reg3(32bit)W Ch
|
|
//reg4(32bit)W 10h
|
|
//error(16bit)R 14h
|
|
//status(16bit)R 16h
|
|
//mt_rnd(32bit)R 18h
|
|
//max_lev(8bit)W 1Ch
|
|
//control(8bit)W 1Dh
|
|
//max_com(16bit)W 1Eh
|
|
|
|
|
|
`timescale 1ns / 1ps
|
|
module ehw(clk, sram_data, addr, nwe, ncs, noe, reset, led,
|
|
irq_pin);
|
|
|
|
parameter B = (7);
|
|
|
|
input clk, addr, nwe, ncs, noe, reset;
|
|
inout [B:0] sram_data;
|
|
output led;
|
|
output irq_pin;
|
|
|
|
// synchronize signals
|
|
reg sncs, snwe;
|
|
reg [12:0] buffer_addr;
|
|
reg [B:0] buffer_data;
|
|
wire led;
|
|
|
|
// bram-cpu interfaz
|
|
reg we;
|
|
reg w_st=0;
|
|
reg [B:0] wdBus;
|
|
reg [B:0] rdBus;
|
|
wire [12:0] addr;
|
|
reg [7:0] bae;
|
|
|
|
|
|
// bram-evalfit interfaz
|
|
wire we_eval, en_ev;
|
|
wire [63:0] ev_do;
|
|
wire [63:0] ev_di;
|
|
wire [63:0] ev_do_aux;
|
|
wire [63:0] ev_di_aux;
|
|
|
|
// Interconnection
|
|
wire [31:0] mt_rnd;
|
|
wire [31:0] reg0;
|
|
wire [31:0] reg1;
|
|
wire [31:0] reg2;
|
|
wire [31:0] reg3;
|
|
wire [31:0] reg4;
|
|
wire [15:0] status;
|
|
wire [15:0] status_aux;
|
|
wire [15:0] error;
|
|
wire [8:0] evalfit_addr;
|
|
|
|
wire en_fit;
|
|
wire [15:0] max_com;
|
|
wire [3:0] max_lev;
|
|
wire [7:0] control;
|
|
|
|
reg [7:0] reg_bank [31:0];
|
|
wire enReg;
|
|
wire [4:0] address;
|
|
|
|
// Test : LED blinking
|
|
reg [25:0] counter;
|
|
always @(posedge clk) begin
|
|
if (~reset)
|
|
counter <= {25{1'b0}};
|
|
else
|
|
counter <= counter + 1;
|
|
end
|
|
assign led = counter[24];
|
|
|
|
// Data Bus direction control
|
|
wire T = ~noe | ncs;
|
|
assign sram_data = T?8'bZ:rdBus;
|
|
|
|
// synchronize assignment
|
|
always @(negedge clk)
|
|
begin
|
|
sncs <= ncs;
|
|
snwe <= nwe;
|
|
buffer_data <= sram_data;
|
|
buffer_addr <= addr;
|
|
end
|
|
|
|
// write access cpu to bram
|
|
always @(posedge clk)
|
|
if(~reset) {w_st, we, wdBus} <= 0;
|
|
else begin
|
|
wdBus <= buffer_data;
|
|
case (w_st)
|
|
0: begin
|
|
we <= 0;
|
|
if(sncs | snwe) w_st <= 1;
|
|
end
|
|
1: begin
|
|
if(~(sncs | snwe)) begin
|
|
we <= 1;
|
|
w_st <= 0;
|
|
end
|
|
else we <= 0;
|
|
end
|
|
endcase
|
|
end
|
|
|
|
|
|
// Address Decoder
|
|
// We have 2 memory blocks 1: 512 x 64 bits memory 32kb = 4kB 0000 - 0FFF buffer_addr[12] = 0
|
|
// 2: Register Bank 1000 - 101F buffer_addr[12] = 1
|
|
|
|
// SIE has an eight bits data bus, this module generate the required signals to create a 64 bits word.
|
|
always @(buffer_addr)
|
|
begin
|
|
if(~buffer_addr[12]) begin
|
|
case (buffer_addr[2:0])
|
|
0: bae <= 8'h01;
|
|
1: bae <= 8'h02;
|
|
2: bae <= 8'h04;
|
|
3: bae <= 8'h08;
|
|
4: bae <= 8'h10;
|
|
5: bae <= 8'h20;
|
|
6: bae <= 8'h40;
|
|
7: bae <= 8'h80;
|
|
endcase
|
|
end
|
|
else
|
|
bae <= 8'h00;
|
|
end
|
|
wire en1, en2; // enable memory signals
|
|
assign en0 = bae[0] | bae[1] | bae[2] | bae[3];
|
|
assign en1 = bae[4] | bae[5] | bae[6] | bae[7];
|
|
|
|
reg[31:0] DIA_Aux;
|
|
always @ (posedge clk) begin
|
|
if (bae[0]) DIA_Aux[7:0] = wdBus[7:0];
|
|
if (bae[1]) DIA_Aux[15:8] = wdBus[7:0];
|
|
if (bae[2]) DIA_Aux[23:16] = wdBus[7:0];
|
|
if (bae[3]) DIA_Aux[31:24] = wdBus[7:0];
|
|
if (bae[4]) DIA_Aux[7:0] = wdBus[7:0];
|
|
if (bae[5]) DIA_Aux[15:8] = wdBus[7:0];
|
|
if (bae[6]) DIA_Aux[23:16] = wdBus[7:0];
|
|
if (bae[7]) DIA_Aux[31:24] = wdBus[7:0];
|
|
end
|
|
|
|
reg [2:0] state, nextstate; //FSM for write in 32bit mode to memory
|
|
wire we0, we1;
|
|
wire nreset;
|
|
assign nreset = ~reset;
|
|
parameter S0 = 3'b000;
|
|
parameter S1 = 3'b001;
|
|
parameter S2 = 3'b010;
|
|
|
|
always @ (posedge clk, posedge nreset)
|
|
if (nreset) state <= S0;
|
|
else state <= nextstate;
|
|
// next state logic
|
|
always@(*)
|
|
case (state)
|
|
S0:if (bae[3]&we) nextstate = S1;
|
|
else
|
|
if (bae[7]&we) nextstate = S2;
|
|
else nextstate = S0;
|
|
S1: nextstate = S0;
|
|
S2: nextstate = S0;
|
|
default: nextstate = S0;
|
|
endcase
|
|
// output logic
|
|
assign we0 = (state == S1);
|
|
assign we1 = (state == S2);
|
|
|
|
// Read control
|
|
reg [7:0] MemDOA;
|
|
wire [63:0] DOA_Aux;
|
|
|
|
always @(posedge clk)
|
|
if(~reset)begin
|
|
rdBus = 8'h00;
|
|
end
|
|
else begin
|
|
if(enReg)
|
|
rdBus = reg_bank[address];
|
|
else
|
|
rdBus = MemDOA[7:0];
|
|
end
|
|
// memory output mux
|
|
always @(buffer_addr[2:0])
|
|
case (buffer_addr[2:0])
|
|
0 : MemDOA = DOA_Aux[7:0];
|
|
1 : MemDOA = DOA_Aux[15:8];
|
|
2 : MemDOA = DOA_Aux[23:16];
|
|
3 : MemDOA = DOA_Aux[31:24];
|
|
4 : MemDOA = DOA_Aux[39:32];
|
|
5 : MemDOA = DOA_Aux[47:40];
|
|
6 : MemDOA = DOA_Aux[55:48];
|
|
7 : MemDOA = DOA_Aux[63:56];
|
|
default: MemDOA = 8'h00;
|
|
endcase
|
|
|
|
// Store Inputs
|
|
always @(posedge clk)
|
|
begin
|
|
if(enReg) begin
|
|
reg_bank[0] = reg0[7:0];
|
|
reg_bank[1] = reg0[15:8];
|
|
reg_bank[2] = reg0[23:16];
|
|
reg_bank[3] = reg0[31:24];
|
|
reg_bank[4] = reg1[7:0];
|
|
reg_bank[5] = reg1[15:8];
|
|
reg_bank[6] = reg1[23:16];
|
|
reg_bank[7] = reg1[31:24];
|
|
reg_bank[8] = reg2[7:0];
|
|
reg_bank[9] = reg2[15:8];
|
|
reg_bank[10] = reg2[23:16];
|
|
reg_bank[11] = reg2[31:24];
|
|
reg_bank[12] = reg3[7:0];
|
|
reg_bank[13] = reg3[15:8];
|
|
reg_bank[14] = reg3[23:16];
|
|
reg_bank[15] = reg3[31:24];
|
|
reg_bank[16] = reg4[7:0];
|
|
reg_bank[17] = reg4[15:8];
|
|
reg_bank[18] = reg4[23:16];
|
|
reg_bank[19] = reg4[31:24];
|
|
reg_bank[20] = error[7:0];
|
|
reg_bank[21] = error[15:8];
|
|
reg_bank[22] = status[7:0];
|
|
reg_bank[23] = status[15:8];
|
|
reg_bank[24] = mt_rnd[7:0];
|
|
reg_bank[25] = mt_rnd[15:8];
|
|
reg_bank[26] = mt_rnd[23:16];
|
|
reg_bank[27] = mt_rnd[31:24];
|
|
end
|
|
end
|
|
|
|
assign address[4:0] = buffer_addr[4:0];
|
|
assign enReg = buffer_addr[12];
|
|
// assign reg0[7:0] = reg_bank[0];
|
|
// assign reg0[15:8] = reg_bank[1];
|
|
// assign reg0[23:16] = reg_bank[2];
|
|
// assign reg0[31:24] = reg_bank[3];
|
|
// assign reg1[7:0] = reg_bank[4];
|
|
// assign reg1[15:8] = reg_bank[5];
|
|
// assign reg1[23:16] = reg_bank[6];
|
|
// assign reg1[31:24] = reg_bank[7];
|
|
// assign reg2[7:0] = reg_bank[8];
|
|
// assign reg2[15:8] = reg_bank[9];
|
|
// assign reg2[23:16] = reg_bank[10];
|
|
// assign reg2[31:24] = reg_bank[11];
|
|
// assign reg3[7:0] = reg_bank[12];
|
|
// assign reg3[15:8] = reg_bank[13];
|
|
// assign reg3[23:16] = reg_bank[14];
|
|
// assign reg3[31:24] = reg_bank[15];
|
|
// assign reg4[7:0] = reg_bank[16];
|
|
// assign reg4[15:8] = reg_bank[17];
|
|
// assign reg4[23:16] = reg_bank[18];
|
|
// assign reg4[31:24] = reg_bank[19];
|
|
assign max_lev[3:0] = reg_bank[28][3:0];
|
|
assign control[7:0] = reg_bank[29];
|
|
assign max_com[7:0] = reg_bank[30];
|
|
assign max_com[15:8] = reg_bank[31];
|
|
// Write control
|
|
always @(negedge clk)
|
|
if(we & enReg) begin
|
|
case (address)
|
|
// 0: reg_bank[0] = wdBus;
|
|
// 1: reg_bank[1] = wdBus;
|
|
// 2: reg_bank[2] = wdBus;
|
|
// 3: reg_bank[3] = wdBus;
|
|
// 4: reg_bank[4] = wdBus;
|
|
// 5: reg_bank[5] = wdBus;
|
|
// 6: reg_bank[6] = wdBus;
|
|
// 7: reg_bank[7] = wdBus;
|
|
// 8: reg_bank[8] = wdBus;
|
|
// 9: reg_bank[9] = wdBus;
|
|
// 10: reg_bank[10] = wdBus;
|
|
// 11: reg_bank[11] = wdBus;
|
|
// 12: reg_bank[12] = wdBus;
|
|
// 13: reg_bank[13] = wdBus;
|
|
// 14: reg_bank[14] = wdBus;
|
|
// 15: reg_bank[15] = wdBus;
|
|
// 16: reg_bank[16] = wdBus;
|
|
// 17: reg_bank[17] = wdBus;
|
|
// 18: reg_bank[18] = wdBus;
|
|
// 19: reg_bank[19] = wdBus;
|
|
28: reg_bank[28] = wdBus;
|
|
29: reg_bank[29] = wdBus;
|
|
30: reg_bank[30] = wdBus;
|
|
31: reg_bank[31] = wdBus;
|
|
endcase
|
|
end
|
|
assign irq_pin = 0;
|
|
//assign ev_do_aux = {ev_do[7:0], ev_do[15:8], ev_do[23:16], ev_do[31:24], ev_do[39:32], ev_do[47:40], ev_do[55:48], ev_do[63:56]};
|
|
//assign ev_di = {ev_di_aux[7:0], ev_di_aux[15:8], ev_di_aux[23:16], ev_di_aux[31:24], ev_di_aux[39:32], ev_di_aux[47:40], ev_di_aux[55:48], ev_di_aux[63:56]};
|
|
assign ev_do_aux[63:32] = ev_do[31:0];
|
|
assign ev_do_aux[31:16] = ev_do[47:32];
|
|
assign ev_do_aux[15:0] = ev_do[63:48];
|
|
|
|
assign ev_di[63:32] = ev_di_aux[31:0]; //Endianess adjust for 32-bit level data
|
|
assign ev_di[31:16] = ev_di_aux[47:32]; //endianess adjust for 16-bit LUT
|
|
assign ev_di[7:0] = ev_di_aux[63:56]; //endianess adjust for 8-bit VARS
|
|
assign ev_di[15:8] = ev_di_aux[55:48]; //endianess adjust for 8-bit VARS
|
|
|
|
|
|
assign status[14:0] = status_aux[14:0];
|
|
|
|
RAMB16_S36_S36 #(.INIT_00(256'hABCDEF00_00000000_00000000_00000000_00000000_00000000_00000000_76543210) )
|
|
mem0 ( .CLKA(clk), .ENA(en0), .SSRA(1'b0), .ADDRA(buffer_addr[11:3]), .WEA(we0), .DIA(DIA_Aux[31:0]), .DIPA(1'b0), .DOA(DOA_Aux[31:0]),
|
|
.CLKB(clk), .ENB(en_ev), .SSRB(1'b0), .ADDRB(evalfit_addr), .WEB(we_eval), .DIB(ev_do_aux[31:0]), .DIPB(1'b0), .DOB(ev_di_aux[31:0]));
|
|
|
|
RAMB16_S36_S36 #(.INIT_00(256'hCE5A4000_00000000_00000000_00000000_00000000_00000000_00000000_78111300) )
|
|
mem1( .CLKA(clk), .ENA(en1), .SSRA(1'b0), .ADDRA(buffer_addr[11:3]), .WEA(we1), .DIA(DIA_Aux[31:0]), .DIPA(0'b0), .DOA(DOA_Aux[63:32]),
|
|
.CLKB(clk), .ENB(en_ev), .SSRB(1'b0), .ADDRB(evalfit_addr), .WEB(we_eval), .DIB(ev_do_aux[63:32]), .DIPB(0'b0), .DOB(ev_di_aux[63:32]));
|
|
|
|
// evalfit_peripheral
|
|
evalfit_peripheral evalfit( .clk(clk), .reset(control[7]), .habilita(control[6]), .maxcombs(max_com), .nivel_max(max_lev),
|
|
.peripheral_mem_in(ev_di), .peripheral_mem_en(en_ev), .peripheral_mem_out(ev_do), .peripheral_mem_we(we_eval),
|
|
.peripheral_mem_addr(evalfit_addr), .evalfit3_estado(status_aux[15:0]), .errores(error),
|
|
.fin_ack(status[15]), .reg0_s(reg0), .reg1_s(reg1), .reg2_s(reg2), .reg3_s(reg3), .reg4_s(reg4));
|
|
|
|
// MersenneTwister
|
|
mt_mem random( .clk(clk), .ena(1'b1), .resetn(reset), .random(mt_rnd));
|
|
|
|
endmodule
|
|
|