2014-10-06 31 views
1

我试图创建一个涉及移位寄存器的数据路径,但我希望整个事情能够在等待新输入时停顿。我看到标准库中有一个带有启用行的移位寄存器(尽管默认为true)。凿子标准库移位寄存器的行为是否对于启用行是正确的

问题是,当我尝试使用它时,编译后的verilog似乎并没有在启用低时实际阻塞移位寄存器。

考虑此凿代码:

package SR 

import Chisel._ 

class SR extends Module { 
    val io = new Bundle { 
    val in = UInt(INPUT, 8) 
    val enable = Bool(INPUT) 
    val out = UInt(OUTPUT, 8) 
    } 
    io.out:= ShiftRegister(io.in, 10, io.enable) 
} 

class SRTests(c: SR) extends Tester(c) { 
} 

object SR { 
    def main(args: Array[String]): Unit = { 
    val tutArgs = args.slice(1, args.length) 
    chiselMainTest(tutArgs,() => Module(new SR())) { 
     c => new SRTests(c) } 
    } 
} 

我得到以下的Verilog:

module SR(input clk, 
    input [7:0] io_in, 
    input io_enable, 
    output[7:0] io_out 
); 

    reg [7:0] R0; 
    reg [7:0] R1; 
    reg [7:0] R2; 
    reg [7:0] R3; 
    reg [7:0] R4; 
    reg [7:0] R5; 
    reg [7:0] R6; 
    reg [7:0] R7; 
    reg [7:0] R8; 
    reg [7:0] R9; 
    wire[7:0] T10; 

`ifndef SYNTHESIS 
    integer initvar; 
    initial begin 
    #0.002; 
    R0 = {1{$random}}; 
    R1 = {1{$random}}; 
    R2 = {1{$random}}; 
    R3 = {1{$random}}; 
    R4 = {1{$random}}; 
    R5 = {1{$random}}; 
    R6 = {1{$random}}; 
    R7 = {1{$random}}; 
    R8 = {1{$random}}; 
    R9 = {1{$random}}; 
    end 
`endif 

    assign io_out = R0; 
    assign T10 = io_enable ? io_in : R9; 

    always @(posedge clk) begin 
    R0 <= R1; 
    R1 <= R2; 
    R2 <= R3; 
    R3 <= R4; 
    R4 <= R5; 
    R5 <= R6; 
    R6 <= R7; 
    R7 <= R8; 
    R8 <= R9; 
    if(io_enable) begin 
     R9 <= io_in; 
    end 
    end 
endmodule 

好像移位寄存器只持股不动,而不是整个事情的第一个值。例如,如果你在连续的时钟周期中写入1,2,3,4,5,但只保持为1,2,3的高电平,3将被正确保持,但1和2最终会移出,整个移位寄存器将填充值3.

我希望类似凿子教程中看到的移位寄存器示例的行为。问题是我需要很长的,可参数化的移位寄存器,所以手写每个寄存器不是一种选择。我将非常感谢一个凿子代码的例子,它实现了一个带有使能行为的移位寄存器,就像在凿子教程中看到的一样,但参数设置的长度不同,就像在标准库中看到的一样。

回答

0

你可以看到的src/main /斯卡拉/ ChiselUtil.scala的ShiftRegister的源代码在Chisel库:

object ShiftRegister 
{ 
    def apply[T <: Data](in: T, n: Int, en: Bool = Bool(true)): T = 
    { 
    // The order of tests reflects the expected use cases. 
    if (n == 1) { 
     RegEnable(in, en) 
    } else if (n != 0) { 
     RegNext(apply(in, n-1, en)) 
    } else { 
     in 
    } 
    } 
} 

这是创造RegNexts的递归链,但与基本情况建立一个RegEnable。例如:

RegNext(RegNext(RegNext(RegEnable(in, en)))) 

您可以在代码复制到你的hello world,重命名它像object MyShiftRegister的东西,然后修改循环,以满足您的需求。

我知道你在寻找的是:

} else if (n != 0) { 
    RegEnable(apply(in, n-1, en), en) 
} ... 

作为一般的策略,我建议写出来的代码是什么样子“非滚”,然后想想怎么“包起来“转换为简洁且可参数化的Scala代码。

+1

好的,谢谢,我会试试看。这个实现的目的是什么:RegNext(RegNext(RegNext(RegEnable(in,en))))?另外,移位寄存器代码最近是否改变了if else else case?我以为我最后一次看到它,它只有if和else(现在是else if)。这仅仅是说,如果n作为移位寄存器的参数只是作为输出传入,那么它没有意义。 – user3704133 2014-10-09 03:23:30

+0

我没有写凿子,所以我不知道他们对它做了什么改变,或者他们为什么做这些改变。凿子谷歌组可能是“设计意图”等问题的更好论坛。 – Chris 2014-10-09 05:29:53

相关问题