一些Verilog的小東西
常用小模塊
- 奇數次分頻
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.
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.
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
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
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語言,但是要注意返回值就是他的名字(,剩下的都是輸入
結語
先用來應付一下考查課,順便查漏補缺一下自己的Verilog基礎
距離 頻率計發佈到現在才4個月,最近博客的閱讀量又翻了翻…但是如果csdn再不對verilog進行markdown支持的話,就搬遷到簡書了,謝謝大家