函数(Function)
一、简介(Introduction)
用Scala函数产生硬件的方式与VHDL/Verilog中非常不同, 原因如下:
你可以在他们内部例化寄存器、组合逻辑和模块。
你不需要使用
process
/@always
模块, 因此也不会限制你对信号声明的范围。所有事情都是通过引用传递, 这使得各种操作都便于控制。
例如你可以把总线作为变量传递到函数中, 这样函数就可以在内部读写总线。你也可以返回一个模块, 一个总线, 或是任何来自于Scala世界的东西。
二、RGA到灰度(RGB to grey)
例如, 如果想要把红/绿/蓝颜色通过系数转化为灰度, 可以用如下函数来实现:
//输入RGB色彩
val r, g, b = UInt(8 bits)
//定义灰度系数乘的函数
def coef(value: UInt, by: Float): UInt = (value * U((255 * by).toInt, 8 bits) >> 8)
//计算灰度
val gray = coef(r, 0.3f) + coef(g, 0.4f) + coef(b, 0.3f)
Verilog:
wire [7:0] _zz_gray;
wire [7:0] _zz_gray_1;
wire [15:0] _zz_gray_2;
wire [7:0] _zz_gray_3;
wire [15:0] _zz_gray_4;
wire [7:0] _zz_gray_5;
wire [15:0] _zz_gray_6;
wire [7:0] r;
wire [7:0] g;
wire [7:0] b;
wire [7:0] gray;
assign _zz_gray = (_zz_gray_1 + _zz_gray_3);
assign _zz_gray_1 = (_zz_gray_2 >>> 8);
assign _zz_gray_2 = (r * 8'h4c);
assign _zz_gray_3 = (_zz_gray_4 >>> 8);
assign _zz_gray_4 = (g * 8'h66);
assign _zz_gray_5 = (_zz_gray_6 >>> 8);
assign _zz_gray_6 = (b * 8'h4c);
assign gray = (_zz_gray + _zz_gray_5);
三、Valid和Ready负载总线(Valid Ready Payload bus)
例如, 如果你用valid
, ready
和payload
信号定义了一条简单的总线, 你可以在其中定义一些常用的函数。
case class MyBus(payloadWidth: Int) extends Bundle with IMasterSlave {
val valid = Bool()
val ready = Bool()
val payload = Bits(payloadWidth bits)
//在master模式中定义数据的方向
override def asMaster(): Unit = {
out(valid, payload)
in(ready)
}
//把that链接到this上
def <<(that: MyBus): Unit = {
this.valid := that.valid
that.ready := this.ready
this.payload := that.payload
}
//把this连接到FIFO的输入, 返回FIFO的输出
def queue(size: Int): MyBus = {
val fifo = new MyBusFifo(payloadWidth, size)
fifo.io.push << this
return fifo.io.pop
}
}
class MyBusFifo(payloadWidth: Int, depth: Int) extends Component {
val io = new Bundle {
val push = slave(MyBus(payloadWidth))
val pop = master(MyBus(payloadWidth))
}
val mem = Mem(Bits(payloadWidth bits), depth)
//...
}
Verilog:(有问题,this和that的作用还没搞懂)
wire test_io_push_valid;
wire [15:0] test_io_push_payload;
wire test_io_pop_ready;
wire test_io_push_ready;
wire test_io_pop_valid;
wire [15:0] test_io_pop_payload;
MyBusFifo test (
.io_push_valid (test_io_push_valid ), //i
.io_push_ready (test_io_push_ready ), //o
.io_push_payload (test_io_push_payload[15:0]), //i
.io_pop_valid (test_io_pop_valid ), //o
.io_pop_ready (test_io_pop_ready ), //i
.io_pop_payload (test_io_pop_payload[15:0] ) //o
);
module MyBusFifo (
input io_push_valid,
output io_push_ready,
input [15:0] io_push_payload,
output io_pop_valid,
input io_pop_ready,
output [15:0] io_pop_payload
);
reg [15:0] mem [0:7];
endmodule