一些Verilog的小东西 [TOC]
常用小模块
奇数次分频
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
未完待续
状态机 这里给两种比较常见的写法 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的区别
$display 相当于c语言的printf,一旦程序触发到就立即显示
$monitor 一直以一个格式在追踪某几个变量或者表达式的变化
一个程序里面只能有一个monitor在跑
$strobe 用于观察非阻塞赋值 ,在所在的always块结束后才会改变
task 和function的区别 这里也是给上一个功能一样,但是分别用task和function实现的代码
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
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语言,但是要注意返回值就是他的名字(,剩下的都是输入
如果你觉得有丶收获的话