i'm very new with scala and Chisel. I tried to create a Shiftregister example with dynamic size, but i'm not sure if the following code is correct. It would be nice if someone could review it:
import Chisel._
class Shiftregister(length: Int) extends Module {
val io = new Bundle {
val clk = UInt(INPUT, 1)
val load = UInt(INPUT, 1) // 1 read from s_data_in, 0 read from p_data_in
val s_data_in = UInt(INPUT, 1)
val s_data_out = UInt(OUTPUT, 1)
val p_data_in = UInt(INPUT, length)
val p_data_out = UInt(OUTPUT, length)
}
val bitfield = Reg(init = UInt(length))
when (io.load.toBool()) {
bitfield := Cat(io.s_data_in, bitfield(length, 1))
}
.otherwise {
bitfield := io.p_data_in
}
io.p_data_out := Reg(next = bitfield)
io.s_data_out := Reg(next = bitfield(0))
}
class ShiftregisterTest(c: Shiftregister) extends Tester(c, Array(c.io)) {
defTests {
true
}
}
object Shiftregister {
def main(args: Array[String]): Unit = {
chiselMainTest(Array[String]("--backend", "c", "--genHarness", "--v"), () => Module(new Shiftregister(16))){c => new ShiftregisterTest(c)}
}
}
I tried to create an equivalent of the following VHDL code:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY shiftregister IS
GENERIC(
length: positive
);
PORT(
clk: IN STD_LOGIC;
load: IN STD_LOGIC; -- 1 read from s_data_in, 0 read from p_data_in
s_data_in: IN STD_LOGIC := '0';
s_data_out: OUT STD_LOGIC;
p_data_in: IN STD_LOGIC_VECTOR(length-1 DOWNTO 0) := (others => '0');
p_data_out: OUT STD_LOGIC_VECTOR(length-1 DOWNTO 0)
);
END ENTITY shiftregister;
ARCHITECTURE synthesis OF shiftregister IS
SIGNAL bitfield: STD_LOGIC_VECTOR(length-1 DOWNTO 0);
BEGIN
PROCESS (clk) IS
BEGIN
IF RISING_EDGE(clk) THEN
IF load = '0' THEN
bitfield <= p_data_in;
ELSE
bitfield(length-1 DOWNTO 0) <= s_data_in & bitfield(length-1 DOWNTO 1);
END IF;
END IF;
END PROCESS;
p_data_out <= bitfield;
s_data_out <= bitfield(0);
END ARCHITECTURE synthesis;
Here are my comments:
First, "clk" is unnecessary, as clock is implicit in Chisel.
Second, you should probably be using Bool() instead of UInt(width=1) for some of your signals.
val load = Bool(INPUT)
Although that's admittedly a stylistic opinion, but it prevents from needing to do the .toBool cast later.
Third, this line does not do what you are intending:
val bitfield = Reg(init = UInt(length))
That is creating a register that is initialized on reset to a UInt() of value "length". Instead, to create a register of width "length" do this:
val bitfield = Reg(outType=UInt(width=length))
You can also just use
val bitfield = Reg(UInt(width=length))
As the default parameter to Reg() is the "type" of register you want to create. However, IMO, that can be a bit ambiguous. If you want to initialize the register to 0, then do the following:
val bitfield = Reg(init = UInt(0, length))