/*
* 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) 这是定义了一个枚举类型。
本文介绍了一个使用Chisel硬件描述语言实现的简单有限状态机(FSM),该状态机用于控制类似Knight Rider电视节目中汽车灯效果的LED。文章详细展示了如何在Chisel中设计FSM,包括慢速时钟生成、复位信号处理和LED闪烁控制。
1726

被折叠的 条评论
为什么被折叠?



