CHISEL 点滴积累 之五

本文介绍了一个使用Chisel硬件描述语言实现的简单有限状态机(FSM),该状态机用于控制类似Knight Rider电视节目中汽车灯效果的LED。文章详细展示了如何在Chisel中设计FSM,包括慢速时钟生成、复位信号处理和LED闪烁控制。
/*
 * Simple FSM example including slow frequency tick generation and
 * reset handling with a top level Chisel component.
 * 
 * This code is part of the Chisel examples.
 * 
 * Copyright: 2015, Technical University of Denmark, DTU Compute
 * Author: Martin Schoeberl (martin@jopdesign.com)
 * License: Simplified BSD License
 * 
 * A simple finite state machine (FSM) that drives LEDs like
 * on the lights on the Knight Rider car.
 * 
 */

package simple

import chisel3._
import chisel3.util._

/**
 * Do some fancy blinking.
  *
  * TODO: find out the new way to have a reset signal
 */
class KnightRider(resetSignal: Bool = null, frequ: Int)
 //调用的时候我们发现,这里参数也可以非常数
    extends Module(_reset = resetSignal) {
    // extends Module {
  val io = IO(new Bundle {
    val led = Output(Bits(6.W))
  })

  val goLeft :: goRight :: Nil = Enum(2)

  val stateReg = RegInit(goLeft) //寄存器初始化
  val ledReg = RegInit(1.U(6.W)) //定义6位寄存器,初始数值是1 

  val tick = Module(new Tick(frequ)) // frequ 初始化

  // Update FSM state and registers only with low frequency tick
  when(tick.io.tick === 1.U) {
    // State change one tick earlier
    when(ledReg(4) === 1.U) {
      stateReg := goRight
    }.elsewhen(ledReg(1) === 1.U) { //提前修改方向
      stateReg := goLeft
    }

    when(stateReg === goLeft) {
      ledReg := ledReg << 1  // 移位寄存器
    }.otherwise {
      ledReg := ledReg >> 1  // 移位寄存器
    }

  }

  io.led := ledReg   
}

/**
 * Generate a 6 Hz tick to drive the FSM.
 */
class Tick(frequ: Int) extends Module {
  val io = IO(new Bundle {
    val tick = Output(Bits(1.W))
  })
  val CNT_MAX = (frequ / 6 - 1).asUInt()

  val r1 = RegInit(0.U(32.W))  

  val limit = r1 === CNT_MAX  // 边界
  val tick = limit           // 边界作为 时钟滴答 

  r1 := r1 + 1.U
  when(limit) {
    r1 := 0.U
  }

  io.tick := tick
}

/**
 * This is a reset "generator". However, this works ONLY
 * in an FPGA when registers are reset to 0 on FPGA configuration.
 *
 * However, as we do not have a chance to specify register power up
 * attributes, this is a fragile solution (did not work for 2 or 3
 * bit wide counters).
 */
class ResetGen() extends Module {
  val io = IO(new Bundle {
    val resetOut = Output(Bool())
  })

  val cnt = Reg(UInt(4.W))  // 声明一个寄存器但是没有赋值

  when(cnt =/= 15.U) {
    cnt := cnt + 1.U
    io.resetOut := true.B //给Bool类型赋值的方法。
  }.otherwise {
    cnt := cnt // this should not be needed, but without it the gen. code is wrong
    io.resetOut := false.B // false.B
  }
}


/**
 * Top level to connect the button to the reset.
 */
class KnightTop extends Module {
  val io = IO(new Bundle {
    val btn = Input(UInt(4.W))
    val led = Output(Bits(6.W))
  })

  // Invert the reset button and two flip-flop input synchronization
  val manReset = (~io.btn(3)).toBool   //转换成Bool类型
  val syncBtn = RegNext(RegNext(manReset)) //RegNext是延迟一级寄存器的意思

  val resGen = Module(new ResetGen()) //生成一个复位模块

  // Manual or generated reset
  val resetVal = syncBtn || resGen.io.resetOut

  // DE2-115 has a 50 MHz clock
  val knight = Module(new KnightRider(resetVal, 50000000))
  // 调用的时候我们发现,这里参数也可以非常数,resetVal


  io.led <> knight.io.led //这里为什么不适用 := 来赋值
}

object KnightMain extends App {
  chisel3.Driver.execute(Array("--target-dir", "generated"), () => new KnightTop())
}


 

module ResetGen( // @[:@3.2]
  input   clock, // @[:@4.4]
  output  io_resetOut // @[:@6.4]
);
  reg [3:0] cnt; // @[KnightRider.scala 95:16:@8.4]
  reg [31:0] _RAND_0;
  wire  _T_9; // @[KnightRider.scala 97:12:@9.4]
  wire [4:0] _T_11; // @[KnightRider.scala 98:16:@11.6]
  wire [3:0] _T_12; // @[KnightRider.scala 98:16:@12.6]
  assign _T_9 = cnt != 4'hf; // @[KnightRider.scala 97:12:@9.4]
  assign _T_11 = cnt + 4'h1; // @[KnightRider.scala 98:16:@11.6]
  assign _T_12 = _T_11[3:0]; // @[KnightRider.scala 98:16:@12.6]
  assign io_resetOut = cnt != 4'hf; // @[KnightRider.scala 99:17:@14.6 KnightRider.scala 102:17:@18.6]
`ifdef RANDOMIZE_GARBAGE_ASSIGN
`define RANDOMIZE
`endif
`ifdef RANDOMIZE_INVALID_ASSIGN
`define RANDOMIZE
`endif
`ifdef RANDOMIZE_REG_INIT
`define RANDOMIZE
`endif
`ifdef RANDOMIZE_MEM_INIT
`define RANDOMIZE
`endif
`ifdef RANDOMIZE
  integer initvar;
  initial begin
    `ifndef verilator
      #0.002 begin end
    `endif
  `ifdef RANDOMIZE_REG_INIT
  _RAND_0 = {1{$random}};
  cnt = _RAND_0[3:0];
  `endif // RANDOMIZE_REG_INIT
  end
`endif // RANDOMIZE
  always @(posedge clock) begin
    if (_T_9) begin
      cnt <= _T_12;
    end
  end
endmodule
module Tick( // @[:@21.2]
  input   clock, // @[:@22.4]
  input   reset, // @[:@23.4]
  output  io_tick // @[:@24.4]
);
  reg [31:0] r1; // @[KnightRider.scala 69:19:@26.4]
  reg [31:0] _RAND_0;
  wire  limit; // @[KnightRider.scala 71:18:@27.4]
  wire [32:0] _T_10; // @[KnightRider.scala 74:12:@28.4]
  wire [31:0] _T_11; // @[KnightRider.scala 74:12:@29.4]
  wire [31:0] _GEN_0; // @[KnightRider.scala 75:15:@31.4]
  assign limit = r1 == 32'h7f2814; // @[KnightRider.scala 71:18:@27.4]
  assign _T_10 = r1 + 32'h1; // @[KnightRider.scala 74:12:@28.4]
  assign _T_11 = _T_10[31:0]; // @[KnightRider.scala 74:12:@29.4]
  assign _GEN_0 = limit ? 32'h0 : _T_11; // @[KnightRider.scala 75:15:@31.4]
  assign io_tick = r1 == 32'h7f2814; // @[KnightRider.scala 79:11:@34.4]
`ifdef RANDOMIZE_GARBAGE_ASSIGN
`define RANDOMIZE
`endif
`ifdef RANDOMIZE_INVALID_ASSIGN
`define RANDOMIZE
`endif
`ifdef RANDOMIZE_REG_INIT
`define RANDOMIZE
`endif
`ifdef RANDOMIZE_MEM_INIT
`define RANDOMIZE
`endif
`ifdef RANDOMIZE
  integer initvar;
  initial begin
    `ifndef verilator
      #0.002 begin end
    `endif
  `ifdef RANDOMIZE_REG_INIT
  _RAND_0 = {1{$random}};
  r1 = _RAND_0[31:0];
  `endif // RANDOMIZE_REG_INIT
  end
`endif // RANDOMIZE
  always @(posedge clock) begin
    if (reset) begin
      r1 <= 32'h0;
    end else begin
      if (limit) begin
        r1 <= 32'h0;
      end else begin
        r1 <= _T_11;
      end
    end
  end
endmodule
module KnightRider( // @[:@36.2]
  input        clock, // @[:@37.4]
  input        reset, // @[:@38.4]
  output [5:0] io_led // @[:@39.4]
);
  wire  tick_clock; // @[KnightRider.scala 38:20:@43.4]
  wire  tick_reset; // @[KnightRider.scala 38:20:@43.4]
  wire  tick_io_tick; // @[KnightRider.scala 38:20:@43.4]
  reg  stateReg; // @[KnightRider.scala 35:25:@41.4]
  reg [31:0] _RAND_0;
  reg [5:0] ledReg; // @[KnightRider.scala 36:23:@42.4]
  reg [31:0] _RAND_1;
  wire  _T_11; // @[KnightRider.scala 41:21:@46.4]
  wire  _T_12; // @[KnightRider.scala 44:16:@48.6]
  wire  _T_15; // @[KnightRider.scala 46:22:@54.8]
  wire  _GEN_0; // @[KnightRider.scala 46:35:@56.8]
  wire  _GEN_1; // @[KnightRider.scala 44:29:@50.6]
  wire  _T_18; // @[KnightRider.scala 50:19:@59.6]
  wire [6:0] _GEN_5; // @[KnightRider.scala 51:24:@61.8]
  wire [6:0] _T_19; // @[KnightRider.scala 51:24:@61.8]
  wire [4:0] _T_20; // @[KnightRider.scala 53:24:@65.8]
  wire [6:0] _GEN_2; // @[KnightRider.scala 50:31:@60.6]
  wire  _GEN_3; // @[KnightRider.scala 41:30:@47.4]
  wire [6:0] _GEN_4; // @[KnightRider.scala 41:30:@47.4]
  Tick tick ( // @[KnightRider.scala 38:20:@43.4]
    .clock(tick_clock),
    .reset(tick_reset),
    .io_tick(tick_io_tick)
  );
  assign _T_11 = tick_io_tick; // @[KnightRider.scala 41:21:@46.4]
  assign _T_12 = ledReg[4]; // @[KnightRider.scala 44:16:@48.6]
  assign _T_15 = ledReg[1]; // @[KnightRider.scala 46:22:@54.8]
  assign _GEN_0 = _T_15 ? 1'h0 : stateReg; // @[KnightRider.scala 46:35:@56.8]
  assign _GEN_1 = _T_12 ? 1'h1 : _GEN_0; // @[KnightRider.scala 44:29:@50.6]
  assign _T_18 = stateReg == 1'h0; // @[KnightRider.scala 50:19:@59.6]
  assign _GEN_5 = {{1'd0}, ledReg}; // @[KnightRider.scala 51:24:@61.8]
  assign _T_19 = _GEN_5 << 1; // @[KnightRider.scala 51:24:@61.8]
  assign _T_20 = ledReg[5:1]; // @[KnightRider.scala 53:24:@65.8]
  assign _GEN_2 = _T_18 ? _T_19 : {{2'd0}, _T_20}; // @[KnightRider.scala 50:31:@60.6]
  assign _GEN_3 = _T_11 ? _GEN_1 : stateReg; // @[KnightRider.scala 41:30:@47.4]
  assign _GEN_4 = _T_11 ? _GEN_2 : {{1'd0}, ledReg}; // @[KnightRider.scala 41:30:@47.4]
  assign io_led = ledReg; // @[KnightRider.scala 57:10:@69.4]
  assign tick_clock = clock; // @[:@44.4]
  assign tick_reset = reset; // @[:@45.4]
`ifdef RANDOMIZE_GARBAGE_ASSIGN
`define RANDOMIZE
`endif
`ifdef RANDOMIZE_INVALID_ASSIGN
`define RANDOMIZE
`endif
`ifdef RANDOMIZE_REG_INIT
`define RANDOMIZE
`endif
`ifdef RANDOMIZE_MEM_INIT
`define RANDOMIZE
`endif
`ifdef RANDOMIZE
  integer initvar;
  initial begin
    `ifndef verilator
      #0.002 begin end
    `endif
  `ifdef RANDOMIZE_REG_INIT
  _RAND_0 = {1{$random}};
  stateReg = _RAND_0[0:0];
  `endif // RANDOMIZE_REG_INIT
  `ifdef RANDOMIZE_REG_INIT
  _RAND_1 = {1{$random}};
  ledReg = _RAND_1[5:0];
  `endif // RANDOMIZE_REG_INIT
  end
`endif // RANDOMIZE
  always @(posedge clock) begin
    if (reset) begin
      stateReg <= 1'h0;
    end else begin
      if (_T_11) begin
        if (_T_12) begin
          stateReg <= 1'h1;
        end else begin
          if (_T_15) begin
            stateReg <= 1'h0;
          end
        end
      end
    end
    if (reset) begin
      ledReg <= 6'h1;
    end else begin
      ledReg <= _GEN_4[5:0];
    end
  end
endmodule
module KnightTop( // @[:@71.2]
  input        clock, // @[:@72.4]
  input        reset, // @[:@73.4]
  input  [3:0] io_btn, // @[:@74.4]
  output [5:0] io_led // @[:@74.4]
);
  wire  resGen_clock; // @[KnightRider.scala 120:22:@83.4]
  wire  resGen_io_resetOut; // @[KnightRider.scala 120:22:@83.4]
  wire  knight_clock; // @[KnightRider.scala 126:22:@87.4]
  wire  knight_reset; // @[KnightRider.scala 126:22:@87.4]
  wire [5:0] knight_io_led; // @[KnightRider.scala 126:22:@87.4]
  wire  _T_9; // @[KnightRider.scala 117:26:@76.4]
  reg  _T_12; // @[KnightRider.scala 118:32:@79.4]
  reg [31:0] _RAND_0;
  reg  syncBtn; // @[KnightRider.scala 118:24:@81.4]
  reg [31:0] _RAND_1;
  ResetGen resGen ( // @[KnightRider.scala 120:22:@83.4]
    .clock(resGen_clock),
    .io_resetOut(resGen_io_resetOut)
  );
  KnightRider knight ( // @[KnightRider.scala 126:22:@87.4]
    .clock(knight_clock),
    .reset(knight_reset),
    .io_led(knight_io_led)
  );
  assign _T_9 = io_btn[3]; // @[KnightRider.scala 117:26:@76.4]
  assign io_led = knight_io_led; // @[KnightRider.scala 128:10:@90.4]
  assign resGen_clock = clock; // @[:@84.4]
  assign knight_clock = clock; // @[:@88.4]
  assign knight_reset = syncBtn | resGen_io_resetOut; // @[:@89.4]
`ifdef RANDOMIZE_GARBAGE_ASSIGN
`define RANDOMIZE
`endif
`ifdef RANDOMIZE_INVALID_ASSIGN
`define RANDOMIZE
`endif
`ifdef RANDOMIZE_REG_INIT
`define RANDOMIZE
`endif
`ifdef RANDOMIZE_MEM_INIT
`define RANDOMIZE
`endif
`ifdef RANDOMIZE
  integer initvar;
  initial begin
    `ifndef verilator
      #0.002 begin end
    `endif
  `ifdef RANDOMIZE_REG_INIT
  _RAND_0 = {1{$random}};
  _T_12 = _RAND_0[0:0];
  `endif // RANDOMIZE_REG_INIT
  `ifdef RANDOMIZE_REG_INIT
  _RAND_1 = {1{$random}};
  syncBtn = _RAND_1[0:0];
  `endif // RANDOMIZE_REG_INIT
  end
`endif // RANDOMIZE
  always @(posedge clock) begin
    _T_12 <= ~ _T_9;
    syncBtn <= _T_12;
  end
endmodule

 

总结:

1,参数可以在调用的时候赋给变量数值,其实就相当于端口了,这是VERILOG中做不到的。

2,class KnightRider(resetSignal: Bool = null, frequ: Int) extends Module(_reset = resetSignal)

这里的_reset是指示复位信号是resetSignal这个参数

3,val goLeft :: goRight :: Nil = Enum(2)  这是定义了一个枚举类型。

 

 

 

 

 

 

 

 

 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值