## 函数(Function) ### 一、简介(Introduction) 用Scala函数产生硬件的方式与VHDL/Verilog中非常不同, 原因如下: + 你可以在他们内部例化寄存器、组合逻辑和模块。 + 你不需要使用`process`/`@always`模块, 因此也不会限制你对信号声明的范围。 + 所有事情都是通过引用传递, 这使得各种操作都便于控制。
例如你可以把总线作为变量传递到函数中, 这样函数就可以在内部读写总线。你也可以返回一个模块, 一个总线, 或是任何来自于Scala世界的东西。 ### 二、RGA到灰度(RGB to grey) 例如, 如果想要把红/绿/蓝颜色通过系数转化为灰度, 可以用如下函数来实现: ```Scala //输入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: ```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`信号定义了一条简单的总线, 你可以在其中定义一些常用的函数。 ```Scala 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的作用还没搞懂) ```Verilog 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 ```