137 lines
5.1 KiB
Plaintext
137 lines
5.1 KiB
Plaintext
|
/*************************************************************************
|
||
|
*
|
||
|
* This file is part of ACT dataflow neuro library
|
||
|
*
|
||
|
* Copyright (c) 2022 University of Groningen - Ole Richter
|
||
|
* Copyright (c) 2022 University of Groningen - Michele Mastella
|
||
|
* Copyright (c) 2022 University of Groningen - Hugh Greatorex
|
||
|
* Copyright (c) 2022 University of Groningen - Madison Cotteret
|
||
|
*
|
||
|
*
|
||
|
* This source describes Open Hardware and is licensed under the CERN-OHL-W v2 or later
|
||
|
*
|
||
|
* You may redistribute and modify this documentation and make products
|
||
|
* using it under the terms of the CERN-OHL-W v2 (https:/cern.ch/cern-ohl).
|
||
|
* This documentation is distributed WITHOUT ANY EXPRESS OR IMPLIED
|
||
|
* WARRANTY, INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY
|
||
|
* AND FITNESS FOR A PARTICULAR PURPOSE. Please see the CERN-OHL-W v2
|
||
|
* for applicable conditions.
|
||
|
*
|
||
|
* Source location: https://git.web.rug.nl/bics/actlib_dataflow_neuro
|
||
|
*
|
||
|
* As per CERN-OHL-W v2 section 4.1, should You produce hardware based on
|
||
|
* these sources, You must maintain the Source Location visible in its
|
||
|
* documentation.
|
||
|
*
|
||
|
**************************************************************************
|
||
|
*/
|
||
|
import "../../dataflow_neuro/cell_lib_async.act";
|
||
|
import "../../dataflow_neuro/cell_lib_std.act";
|
||
|
import "../../dataflow_neuro/treegates.act";
|
||
|
import "../../dataflow_neuro/primitives.act";
|
||
|
import std::channel;
|
||
|
open std::channel;
|
||
|
|
||
|
// import std::func;
|
||
|
open std;
|
||
|
|
||
|
import std::data;
|
||
|
open std::data;
|
||
|
|
||
|
|
||
|
namespace tmpl {
|
||
|
namespace dataflow_neuro {
|
||
|
|
||
|
/**
|
||
|
* Bundled data (non dual rail, with req)
|
||
|
* 2
|
||
|
* quasi delay insensitive channel (dual rail).
|
||
|
* Basically a buffer with a bitwise conversion in front of it.
|
||
|
*/
|
||
|
export template<pint N, N_dly_cfg>
|
||
|
defproc bd2qdi(bd<N> in; avMx1of2<N> out; bool? dly_cfg[N_dly_cfg]; power supply; bool? reset_B) {
|
||
|
// Delay on req_in
|
||
|
bool _req;
|
||
|
delayprog<N_dly_cfg> dly(.in = in.r, .out = _req, .s = dly_cfg, .supply = supply);
|
||
|
|
||
|
// sig buff the reset signal
|
||
|
bool _reset_BX, _reset_BXX[N];
|
||
|
BUF_X4 reset_buf(.a=reset_B, .y=_reset_BX,.vdd=supply.vdd,.vss=supply.vss);
|
||
|
sigbuf<N> reset_bufarray(.in=_reset_BX, .out=_reset_BXX, .supply=supply);
|
||
|
|
||
|
// sig buff the req
|
||
|
bool _reqX, _reqXX[N];
|
||
|
BUF_X4 req_buf(.a=_req, .y=_reqX,.vdd=supply.vdd,.vss=supply.vss);
|
||
|
sigbuf<N> req_bufarray(.in=_reqX, .out=_reqXX, .supply=supply);
|
||
|
|
||
|
// bd2qdi conversion
|
||
|
// Each line goes to a t pin, its not to a f.
|
||
|
bool _inB[N];
|
||
|
INV_X1 input_invs[N];
|
||
|
(i:N:
|
||
|
input_invs[i].a = in.d[i];
|
||
|
input_invs[i].y = _inB[i];
|
||
|
input_invs[i].vss = supply.vss;
|
||
|
input_invs[i].vdd = supply.vdd;
|
||
|
)
|
||
|
|
||
|
// BUFFER
|
||
|
// Basically the buffer_s but with the validity tree ripped out
|
||
|
// and just connected to in_req instead.
|
||
|
|
||
|
// And probably need a delay on the in_ack to ensure en has time to disable
|
||
|
// before the inputs go to another state.
|
||
|
// Actually apparently no: there is a fixed, huge delay, already incurred
|
||
|
// by communicating with pads-> uC -> windows 95 and back again.
|
||
|
|
||
|
// Since the input is never invalid, also need a mechanism
|
||
|
// for the output to become invalid, when an out_ack is received.
|
||
|
|
||
|
//control
|
||
|
bool _en;
|
||
|
A_3C_RB_X4 inack_ctl(.c1=_en,.c2=_reqX,.c3=out.v,.y=in.a,.pr_B=_reset_BX,.sr_B=_reset_BX,.vdd=supply.vdd,.vss=supply.vss);
|
||
|
A_1C1P_X1 en_ctl(.c1=in.a,.p1=out.v,.y=_en,.vdd=supply.vdd,.vss=supply.vss);
|
||
|
|
||
|
//function
|
||
|
bool _out_a_BX_t[N],_out_a_BX_f[N],_out_a_B,_en_X_t[N],_en_X_f[N];
|
||
|
A_2C2N_RB_X4 f_buf_func[N];
|
||
|
A_2C2N_RB_X4 t_buf_func[N];
|
||
|
sigbuf<N> en_buf_t(.in=_en, .out=_en_X_t, .supply=supply);
|
||
|
sigbuf<N> en_buf_f(.in=_en, .out=_en_X_f, .supply=supply);
|
||
|
INV_X1 out_a_inv(.a=out.a,.y=_out_a_B, .vss = supply.vss, .vdd = supply.vdd);
|
||
|
sigbuf<N> out_a_B_buf_f(.in=_out_a_B,.out=_out_a_BX_t, .supply=supply);
|
||
|
sigbuf<N> out_a_B_buf_t(.in=_out_a_B,.out=_out_a_BX_f, .supply=supply);
|
||
|
// check if you can also do single var to array connect a=b[N]
|
||
|
// and remove them from the loop
|
||
|
(i:N:
|
||
|
f_buf_func[i].y=out.d.d[i].f;
|
||
|
t_buf_func[i].y=out.d.d[i].t;
|
||
|
f_buf_func[i].c1=_en_X_f[i];
|
||
|
t_buf_func[i].c1=_en_X_t[i];
|
||
|
f_buf_func[i].c2=_out_a_BX_f[i];
|
||
|
t_buf_func[i].c2=_out_a_BX_t[i];
|
||
|
f_buf_func[i].n1=_inB[i];
|
||
|
t_buf_func[i].n1=in.d[i];
|
||
|
f_buf_func[i].n2=_reqXX[i];
|
||
|
t_buf_func[i].n2=_reqXX[i];
|
||
|
f_buf_func[i].vdd=supply.vdd;
|
||
|
t_buf_func[i].vdd=supply.vdd;
|
||
|
f_buf_func[i].vss=supply.vss;
|
||
|
t_buf_func[i].vss=supply.vss;
|
||
|
t_buf_func[i].pr_B = _reset_BXX[i];
|
||
|
t_buf_func[i].sr_B = _reset_BXX[i];
|
||
|
f_buf_func[i].pr_B = _reset_BXX[i];
|
||
|
f_buf_func[i].sr_B = _reset_BXX[i];
|
||
|
)
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|