CHISEL点滴积累 2

 

 

 

module Alu1(
  input  [1:0] io_fn,
  input  [3:0] io_a,  
  input  [3:0] io_b,  
  output reg  [3:0] io_result 
);

always @ (*)
case (io_fn)
0 : io_result = io_a + io_b ;
1 : io_result = io_a - io_b ;
2 : io_result = io_a | io_b ;
3 : io_result = io_a & io_b ;
endcase 

endmodule

 

 

 

 


module Alu2( // @[:@3.2]
  input  [1:0] io_fn, // @[:@6.4]
  input  [3:0] io_a, // @[:@6.4]
  input  [3:0] io_b, // @[:@6.4]
  output [3:0] io_result // @[:@6.4]
);
  wire  _T_16; // @[Conditional.scala 37:30:@10.4]
  wire [4:0] _T_17; // @[Alu.scala 19:22:@12.6]
  wire [3:0] _T_18; // @[Alu.scala 19:22:@13.6]
  wire  _T_20; // @[Conditional.scala 37:30:@17.6]
  wire [4:0] _T_21; // @[Alu.scala 20:22:@19.8]
  wire [4:0] _T_22; // @[Alu.scala 20:22:@20.8]
  wire [3:0] _T_23; // @[Alu.scala 20:22:@21.8]
  wire  _T_25; // @[Conditional.scala 37:30:@25.8]
  wire [3:0] _T_26; // @[Alu.scala 21:22:@27.10]
  wire  _T_28; // @[Conditional.scala 37:30:@31.10]
  wire [3:0] _T_29; // @[Alu.scala 22:22:@33.12]
  wire [3:0] _GEN_0; // @[Conditional.scala 39:67:@32.10]
  wire [3:0] _GEN_1; // @[Conditional.scala 39:67:@26.8]
  wire [3:0] _GEN_2; // @[Conditional.scala 39:67:@18.6]
  assign _T_16 = 2'h0 == io_fn; // @[Conditional.scala 37:30:@10.4]
  assign _T_17 = io_a + io_b; // @[Alu.scala 19:22:@12.6]
  assign _T_18 = _T_17[3:0]; // @[Alu.scala 19:22:@13.6]
  assign _T_20 = 2'h1 == io_fn; // @[Conditional.scala 37:30:@17.6]
  assign _T_21 = io_a - io_b; // @[Alu.scala 20:22:@19.8]
  assign _T_22 = $unsigned(_T_21); // @[Alu.scala 20:22:@20.8]
  assign _T_23 = _T_22[3:0]; // @[Alu.scala 20:22:@21.8]
  assign _T_25 = 2'h2 == io_fn; // @[Conditional.scala 37:30:@25.8]
  assign _T_26 = io_a | io_b; // @[Alu.scala 21:22:@27.10]
  assign _T_28 = 2'h3 == io_fn; // @[Conditional.scala 37:30:@31.10]
  assign _T_29 = io_a & io_b; // @[Alu.scala 22:22:@33.12]
  assign _GEN_0 = _T_28 ? _T_29 : 4'h0; // @[Conditional.scala 39:67:@32.10]
  assign _GEN_1 = _T_25 ? _T_26 : _GEN_0; // @[Conditional.scala 39:67:@26.8]
  assign _GEN_2 = _T_20 ? _T_23 : _GEN_1; // @[Conditional.scala 39:67:@18.6]
  assign io_result = _T_16 ? _T_18 : _GEN_2; // @[Alu.scala 24:11:@36.4]
endmodule

module AluTop( // @[:@38.2]
  input        clock, // @[:@39.4]
  input        reset, // @[:@40.4]
  input  [9:0] io_sw, // @[:@41.4]
  output [9:0] io_led // @[:@41.4]
);
  wire [1:0] alu_io_fn; // @[Alu.scala 32:18:@43.4]
  wire [3:0] alu_io_a; // @[Alu.scala 32:18:@43.4]
  wire [3:0] alu_io_b; // @[Alu.scala 32:18:@43.4]
  wire [3:0] alu_io_result; // @[Alu.scala 32:18:@43.4]
  Alu alu ( // @[Alu.scala 32:18:@43.4]
    .io_fn(alu_io_fn),
    .io_a(alu_io_a),
    .io_b(alu_io_b),
    .io_result(alu_io_result)
  );
  assign io_led = {{6'd0}, alu_io_result}; // @[Alu.scala 36:8:@52.4]
  assign alu_io_fn = io_sw[1:0]; // @[Alu.scala 33:11:@47.4]
  assign alu_io_a = io_sw[5:2]; // @[Alu.scala 34:10:@49.4]
  assign alu_io_b = io_sw[9:6]; // @[Alu.scala 35:10:@51.4]
endmodule

 

 

上述两端代码,实现同样功能,其中Alu2是由chisel生成的。看上去使用了一层一层的选择器,似乎能占用更多资源。

我用Quartus综合的结果结果正好相反: 手写的Alu1和生成的Alu2分别生成了 17个LUT 和16个LUT。

也就是说CHISEL 生成的看似繁琐的代码反而更高效!本来我是想看看可能效率低一些没想到剧情反转了。

 

 

附录:一下部分是chisel代码,我们可以看到switch部分几乎跟verilog的case语句完全一样的表达。

 

   

package simple 

import chisel3._
import chisel3.util._

class Alu extends Module {
val io = IO (new Bundle{
val fn = Input(UInt(2.W))
val a = Input(UInt(4.W))
val b = Input(UInt(4.W))
val result = Output(UInt(4.W))})
val fn = io.fn ;
val a = io.a ;
val b = io.b;

val result = Wire(UInt(4.W))
result := 0.U
switch (fn){
is (0.U) {result := a+b }
is (1.U) {result := a-b }
is (2.U) {result := a|b }
is (3.U) {result := a&b }
}
io.result := result 
}

class AluTop extends Module {
val io= IO(new Bundle{
val sw = Input(UInt(10.W)) 
val led=Output(UInt(10.W))})

val alu = Module (new Alu ())
alu.io.fn := io.sw(1,0)
alu.io.a := io.sw(5,2)
alu.io.b := io.sw(9,6)
io.led := alu.io.result
}

object AluMain extends App {
println("Generating  the ALU hardware ");
chisel3.Driver.execute(Array("--target-dir","generated"),()=>new AluTop()) 
}




 

又改写了一下代码,实验了一下:

package simple1 

import chisel3._
import chisel3.util._

class Alu extends Module {
val io = IO (new Bundle{
val fn = Input(UInt(2.W))
val a = Input(UInt(4.W))
val b = Input(UInt(4.W))
val result = Output(UInt(4.W))})

val fn = io.fn ;
val a = io.a ;
val b = io.b ;

val and_result = io.a & b ;
val or_result  = a | b ;
val add_result = a + b ; 
val sub_result = a - b ; 

val result = Wire(UInt(4.W));
result := 1.U;
switch (fn){
is (3.U) {result := and_result };
is (2.U) {result := or_result };
is (0.U) {result := add_result };
is (1.U) {result := io.a - io.b   };
}
io.result := result ;
}

里面加了些分号,没有任何影响。也定义了一些中间变量。实验发现scala语法还是比较宽松的。

另外,如果package 后面是跟simple1,则要生成代码用下面命令。

sbt  "runMain simple1.AluMain"

虽然命令行里面没有simple的字样,但是这个scala文件还是在simple目录下。依然能被找到。

可见命令行里面可以不体现出来文件夹以及文件名,但是必须体现出来package的名称。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值