0%

一些Verilog的小东西

一些Verilog的小东西

[TOC]

常用小模块

  1. 奇数次分频
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

module fdiv5(input clk,output k_or,k1,k2);
reg [2:0] c1,c2;
reg M1,M2;

always @ (posedge clk )
begin
if(c1 == 4) c1<=0 ; else c1<=c1+1;
if(c1 == 1) M1<=~M1; else if(c1 ==3) M1<=~M1;
end
always @ (negedge clk )
begin
if(c2 == 4) c2<=0; else c2 <=c2+1;
if(c2 == 1) M2<=~M2 ; else if (c2 == 3) M2<=~M2;
end

assign k1 = M1; assign k2=M2;
assign k_or = k1|k2;

endmodule
  1. 未完待续

状态机

这里给两种比较常见的写法
a.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
module fsm(
input x,
input rst,
input clk,

output reg [1:0] y
);
parameter state_A = 3'd0 , state_B = 3'd1 ,
state_C = 3'd2 , state_D = 3'd3 ,
state_E = 3'd4 ;
reg [2:0] state;

always @(posedge clk or posedge rst)
begin
if(rst)
begin
state <= state_A;
y <= 2'b00;
end
else
case(state)
state_A : begin
if(!x) state <= state_B; else state <= state_C;
y <= 2'b00;
end
state_B : begin
if(!x) state <= state_D; else state <= state_C;
y <= 2'b00;
end
state_C : begin
if(!x) state <= state_E; else state <= state_B;
y <= 2'b00;
end
state_D : begin
if(!x) state <= state_D; else state <= state_C;
y <= 2'b01;
end
state_E : begin
if(!x) state <= state_B; else state <= state_E;
y <= 2'b10;
end
default : begin
state <= state_A; y <= 2'b00;
end
endcase
end

endmodule

b.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
module fsm2(
input [3:0] row,
input srow,
input reset,
input clk,
output reg [3:0] col
);

parameter S0 = 3'd0 , S1 = 3'd1 ,
S2 = 3'd2 , S3 = 3'd3 ,
S4 = 3'd4 , S5 = 3'd5 ;

reg [3:0] current_state , next_state;

always @(posedge clk or posedge reset)
begin
if(reset)
current_state <= S0;
else
current_state <= next_state;
end

always @(*)
begin
case(current_state)
S0:begin
next_state = (srow==1'b1) ? S1 : S0;
col = 4'd15;
end
S1:begin
next_state = (row==4'd0) ? S2 : S5;
col = 4'd1;
end
S2:begin
next_state =(row==4'd0) ? S3 : S5;
col = 4'd2;
end
S3:begin
next_state = (row==4'd0) ? S4 : S5;
col = 4'd3;
end
S4:begin
next_state = (row==4'd0) ? S0 : S5;
col = 4'd4;
end
S5:begin
next_state = S5;
col = 4'd5;
end
endcase
end

endmodule

懂的人自然都懂.建议用quartus写,然后看看RTL会贴心地给出状态描述图

仿真的 $display $monitor $strobe的区别

  1. $display
    相当于c语言的printf,一旦程序触发到就立即显示

  2. $monitor
    一直以一个格式在追踪某几个变量或者表达式的变化

    一个程序里面只能有一个monitor在跑

  3. $strobe
    用于观察非阻塞赋值,在所在的always块结束后才会改变

task 和function的区别

这里也是给上一个功能一样,但是分别用task和function实现的代码

  1. task_test

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    module task_test(data_in,data_out); 

    output reg [3:0] data_out;
    input [3:0] data_in;

    task BCD2Access3;
    output [3:0] data_out;
    input [3:0] data_in;

    data_out = data_in + 4'd3;
    endtask


    always @(data_in)
    begin
    if(data_in >= 4'd10) data_out = 4'b0000;
    else BCD2Access3(data_out,data_in);
    end

    endmodule
  2. function_test

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    module function_test(data_in,data_out); 

    output reg [3:0] data_out;
    input [3:0] data_in;

    function BCD2Access3;
    input [3:0] data_in;
    BCD2Access3 = data_in + 4'd3;
    endfunction


    always @(data_in)
    begin
    if(data_in >= 4'd10) data_out = 4'b0000;
    else data_out = BCD2Access3(data_in);
    end

    endmodule

务必要注意两点:
1. task可以有很多输入输出,但是例化的顺序和task里面写的input,output顺序是一致的,不能搞反
2. function虽说看起来很C语言,但是要注意返回值就是他的名字(,剩下的都是输入

如果你觉得有丶收获的话