记录第一次练习使用SystemVerilog的logic声明
在学习状态机的编码方式,按照我个人的理解,将电路划分为输入方程,状态方程,输出方程。时序电路的设计,大多都是遵循这三个方程来进行。
在输出方程里,有两种描述方法:
// 输出方程:方案一 assign sm_out = ( current_state == state_C ); // 输出方程:方案二 always @ * begin case ( current_state ) state_C : sm_out = 1; default: sm_out = 0; endcase end
如果使用verilog编码,那么方案一的sm_out,需要定义为wire;方案二的sm_out需要定义为reg。不然在Quartus Prime里编译报错。其实我只是想看看两种方法生成的状态机是否真的一样,就是把书上的代码验证一下。然后就想起来了logic的声明,想到了就试试。最终测试的代码如下:
1 // 摩尔状态机 2 module moore_state_machine 3 ( 4 input logic clk, 5 input logic reset_n, 6 7 input logic sm_input, 8 output logic sm_out 9 ); 10 11 reg [1:0] current_state; 12 reg [1:0] next_state; 13 14 parameter state_A = 2'b00, state_B = 2'b01, state_C = 2'b10; 15 16 // 输入方程 17 always @ (posedge clk, negedge reset_n) 18 begin 19 if(reset_n == 0) 20 current_state <= state_A; 21 else 22 current_state <= next_state; 23 end 24 25 // 状态方程 26 always @ (sm_input, current_state) 27 begin 28 case (current_state) 29 state_A: 30 begin 31 if(sm_input == 0) next_state = state_A; 32 else next_state = state_B; 33 end 34 35 state_B: 36 begin 37 if(sm_input == 0) next_state = state_B; 38 else next_state = state_C; 39 end 40 41 state_C: 42 begin 43 if(sm_input == 0) next_state = state_C; 44 else next_state = state_A; 45 end 46 47 default: next_state = state_A; 48 endcase 49 end 50 51 52 // 输出方程 53 //assign sm_out = ( current_state == state_C ); 54 always @ * 55 begin 56 case ( current_state ) 57 state_C : sm_out = 1; 58 default: sm_out = 0; 59 endcase 60 end 61 endmodule
在logic声明下,输出方程的两种方案可以随意切换了。编程语言在不断的进步,很多改进都是为了更方便使用,而这种易用性,常常也是提升编程效率的关键。
最后,展示一下状态机的状态转换图:
数字电路,学起来真的比模拟电路快。
仿真的代码如下:
1 // Verilog Test Bench template for design : moore_state_machine 2 // Simulation tool : Questa Intel FPGA (Verilog) 3 4 `timescale 1 ns/ 10 ps 5 module moore_state_machine_vlg_tst(); 6 reg clk; 7 reg reset_n; 8 reg sm_input; 9 // wires 10 wire sm_out; 11 12 moore_state_machine DUT ( 13 .clk(clk), 14 .reset_n(reset_n), 15 .sm_input(sm_input), 16 .sm_out(sm_out) 17 ); 18 19 initial 20 begin 21 clk = 0; 22 reset_n = 0; 23 sm_input = 0; 24 $display("Running testbench"); 25 end 26 27 always 28 begin 29 #5 clk = ~clk; 30 end 31 32 initial 33 begin 34 #5 reset_n = 1; 35 #10 sm_input = 1; 36 #100 sm_input = 0; 37 #100 sm_input = 1; 38 #100 sm_input = 0; 39 #100 $stop; 40 end 41 endmodule
仿真的输出波形如下:
在Quartus中的RTL Viewer如下,感觉很简洁,根本看不出来啥内容,但是双击黄色的方框,是可以打开状态机图的。
Questa里看Schematic,如下图所示,稍微清晰了一点: