一、前言
????????本文利用verilog語言完成頻率計(jì)實(shí)驗(yàn),由于是第一次發(fā)文,文章格式以及描述語言請諒解,內(nèi)容僅供參考,煩請各路大神指正。
二、模塊
- 數(shù)碼管動態(tài)顯示模塊
- 分頻模塊
- 頻率測試模塊
- 頂層調(diào)用模塊
三、主要代碼
?1、數(shù)碼管動態(tài)顯示模塊
module seg_led(
?? ?input clk,
?? ?input rst_n,
?? ?input [19:0] ?? ??? ?data,//6個數(shù)碼管最高顯示999999,需要20位
?? ?input [5:0] ?? ??? ?point,//小數(shù)點(diǎn)
?? ?input ?? ??? ??? ??? ?sign,//負(fù)號
?? ?input ?? ??? ??? ??? ?en,
?? ?output reg [7:0]?? ?seg_data,//數(shù)碼管顯示的筆畫值
?? ?output reg [5:0] ?? ?seg_sel
);wire [3:0] data0;//個位
wire [3:0] data1;//十位
wire [3:0] data2;//百位
wire [3:0] data3;//千位
wire [3:0] data4;//萬位
wire [3:0] data5;//十萬位reg [3:0] ?? ?clk_cnt;
reg ?? ??? ??? ?dri_clk;
reg [23:0] ?? ?num;
reg [12:0]?? ?cnt0;
reg ?? ??? ??? ?flag;
reg [2:0] ?? ?cnt_sel;
reg [3:0] ?? ?num_disp;
reg ?? ??? ??? ?dot_disp;parameter CLK_DIVIDE = 4'd10;
parameter MCNT = 13'd5_000;assign data0 = data%4'd10;//每個數(shù)碼管取模運(yùn)算
assign data1 = data/4'd10%4'd10;
assign data2 = data/7'd100%4'd10;
assign data3 = data/10'd1000%4'd10;
assign data4 = data/14'd10000%4'd10;
assign data5 = data/17'd100000;always@(posedge clk or negedge rst_n)begin
?? ?if(!rst_n)begin
?? ??? ?clk_cnt <= 4'b0;
?? ??? ?dri_clk <= 1'b1;
?? ?end
?? ?else if(clk_cnt == CLK_DIVIDE/2-1'b1)begin
?? ??? ?clk_cnt <= 4'b0;
?? ??? ?dri_clk <= ~dri_clk;
?? ?end
?? ?else begin
?? ??? ?clk_cnt <= clk_cnt + 1'b1;
?? ??? ?dri_clk <= dri_clk;
?? ?end
endalways@(posedge dri_clk or negedge rst_n)begin
?? ?if(!rst_n)
?? ??? ?num <= 24'd0;
?? ?else begin
?? ??? ??? ?if(data5||point[5])begin
?? ??? ??? ??? ?num[23:20]<=data5;
?? ??? ??? ??? ?num[19:16]<=data4;
?? ??? ??? ??? ?num[15:12]<=data3;
?? ??? ??? ??? ?num[11:8]<=data2;
?? ??? ??? ??? ?num[7:4]<=data1;
?? ??? ??? ??? ?num[3:0]<=data0;
?? ??? ?end
?? ??? ?else begin
?? ??? ??? ??? ?if(data4||point[4])begin
?? ??? ??? ??? ??? ?num[19:0]<={data4,data3,data2,data1,data0};
?? ??? ??? ??? ?if(sign)
?? ??? ??? ??? ??? ?num[23:20]<=4'd11;
?? ??? ??? ??? ?else
?? ??? ??? ??? ??? ?num[23:20]<=4'd10;
?? ??? ??? ?end
?? ??? ??? ?else begin
?? ??? ??? ??? ??? ?if(data3||point[3])begin
?? ??? ??? ??? ??? ??? ?num[15:0]<={data3,data2,data1,data0};
?? ??? ??? ??? ??? ??? ?num[23:20]<=4'd10;
?? ??? ??? ??? ??? ?if(sign)
?? ??? ??? ??? ??? ??? ?num[19:16]<=4'd11;
?? ??? ??? ??? ??? ?else
?? ??? ??? ??? ??? ??? ?num[19:16]<=4'd10;
?? ??? ??? ??? ?end?? ?
?? ??? ??? ??? ?else begin
?? ??? ??? ??? ??? ??? ?if(data2||point[2])begin
?? ??? ??? ??? ??? ??? ??? ?num[11:0]<={data2,data1,data0};
?? ??? ??? ??? ??? ??? ??? ?num[23:16]<={2{4'd10}};
?? ??? ??? ??? ??? ??? ?if(sign)
?? ??? ??? ??? ??? ??? ??? ?num[15:12]<=4'd11;
?? ??? ??? ??? ??? ??? ?else
?? ??? ??? ??? ??? ??? ??? ?num[15:12]<=4'd10;
?? ??? ??? ??? ??? ?end
?? ??? ??? ??? ??? ?else begin
?? ??? ??? ??? ??? ??? ??? ?if(data1||point[1])begin
?? ??? ??? ??? ??? ??? ??? ??? ?num[7:0]<={data1,data0};
?? ??? ??? ??? ??? ??? ??? ??? ?num[23:12]<={3{4'd10}};
?? ??? ??? ??? ??? ??? ??? ?if(sign)
?? ??? ??? ??? ??? ??? ??? ??? ?num[11:8]<=4'd11;
?? ??? ??? ??? ??? ??? ??? ?else
?? ??? ??? ??? ??? ??? ??? ??? ?num[11:8]<=4'd10;
?? ??? ??? ??? ??? ??? ?end
?? ??? ??? ??? ??? ??? ?else begin
?? ??? ??? ??? ??? ??? ??? ??? ?num[3:0]<={data2,data1,data0};
?? ??? ??? ??? ??? ??? ??? ??? ?num[23:8]<={4{4'd10}};
?? ??? ??? ??? ??? ??? ??? ?if(sign)
?? ??? ??? ??? ??? ??? ??? ??? ?num[7:4]<=4'd11;
?? ??? ??? ??? ??? ??? ??? ?else
?? ??? ??? ??? ??? ??? ??? ??? ?num[7:4]<=4'd10;
?? ??? ??? ??? ??? ??? ?end
?? ??? ??? ??? ??? ?end
?? ??? ??? ??? ?end
?? ??? ??? ?end
?? ??? ?end
?? ?end
endalways@(posedge dri_clk or negedge rst_n)begin
?? ?if(!rst_n)begin
?? ??? ?cnt0 <= 13'b0;
?? ??? ?flag <= 1'b0;
?? ?end
?? ?else if(cnt0 == MCNT - 1)begin
?? ??? ?cnt0 ?<= 13'b0;
?? ??? ?flag <= 1'b1;
?? ?end
?? ?else begin
?? ??? ?cnt0 ?<= cnt0 + 13'b1;
?? ??? ?flag <= 1'b0;
?? ?end?? ?
endalways@(posedge dri_clk or negedge rst_n)begin
?? ?if(!rst_n)
?? ??? ?cnt_sel <= 3'b0;
?? ?else if(flag)
?? ?begin
?? ??? ?if(cnt_sel < 3'd5)
?? ??? ??? ?cnt_sel <= cnt_sel + 1'b1;
?? ??? ?else
?? ??? ??? ?cnt_sel <= 3'b0;
?? ?end
?? ?else
?? ??? ?cnt_sel <= cnt_sel;
endalways@(posedge dri_clk or negedge rst_n)
begin
?? ?if(!rst_n)
?? ??? ?begin
?? ??? ??? ?seg_sel <= 6'b11_1111;
?? ??? ??? ?num_disp <= 4'b0;
?? ??? ??? ?dot_disp <= 1'b0;
?? ??? ?end
?? ?else?
?? ??? ?begin
?? ??? ??? ?if (en)
?? ??? ??? ??? ?begin
?? ??? ??? ??? ??? ?case(cnt_sel)
?? ??? ??? ??? ??? ??? ?3'd0 :begin
?? ??? ??? ??? ??? ??? ?seg_sel <= 6'b11_1110;
?? ??? ??? ??? ??? ??? ?num_disp <= num[3:0];
?? ??? ??? ??? ??? ??? ?dot_disp <= ~point[0];
?? ??? ??? ??? ??? ??? ?end
?? ??? ??? ??? ??? ??? ?3'd1 :begin
?? ??? ??? ??? ??? ??? ?seg_sel <= 6'b11_1101;
?? ??? ??? ??? ??? ??? ?num_disp <= num[7:4];
?? ??? ??? ??? ??? ??? ?dot_disp <= ~point[1];
?? ??? ??? ??? ??? ??? ?end
?? ??? ??? ??? ??? ??? ?3'd2 :begin
?? ??? ??? ??? ??? ??? ?seg_sel <= 6'b11_1011;
?? ??? ??? ??? ??? ??? ?num_disp <= num[11:8];
?? ??? ??? ??? ??? ??? ?dot_disp <= ~point[2];
?? ??? ??? ??? ??? ??? ?end
?? ??? ??? ??? ??? ??? ?3'd3 :begin
?? ??? ??? ??? ??? ??? ?seg_sel <= 6'b11_0111;
?? ??? ??? ??? ??? ??? ?num_disp <= num[15:12];
?? ??? ??? ??? ??? ??? ?dot_disp <= ~point[3];
?? ??? ??? ??? ??? ??? ?end
?? ??? ??? ??? ??? ??? ?3'd4 :begin
?? ??? ??? ??? ??? ??? ?seg_sel <= 6'b10_1111;
?? ??? ??? ??? ??? ??? ?num_disp <= num[19:16];
?? ??? ??? ??? ??? ??? ?dot_disp <= ~point[4];
?? ??? ??? ??? ??? ??? ?end
?? ??? ??? ??? ??? ??? ?3'd5 :begin
?? ??? ??? ??? ??? ??? ?seg_sel <= 6'b01_1111;
?? ??? ??? ??? ??? ??? ?num_disp <= num[23:20];
?? ??? ??? ??? ??? ??? ?dot_disp <= ~point[5];
?? ??? ??? ??? ??? ??? ?end
?? ??? ??? ??? ??? ??? ?default :begin
?? ??? ??? ??? ??? ??? ?seg_sel <= 6'b11_1111;
?? ??? ??? ??? ??? ??? ?num_disp <= 4'b0;
?? ??? ??? ??? ??? ??? ?dot_disp <= 1'b1;
?? ??? ??? ??? ??? ??? ?end
?? ??? ??? ??? ??? ?endcase
?? ??? ??? ??? ?end
?? ??? ??? ?else begin
?? ??? ??? ??? ?seg_sel <= 6'b11_1111;
?? ??? ??? ??? ?num_disp <= 4'b0;
?? ??? ??? ??? ?dot_disp <= 1'b1;
?? ??? ??? ?end
?? ??? ?end
endalways@(posedge dri_clk or negedge rst_n)
begin
?? ?if(!rst_n)
?? ??? ?seg_data <= 8'hc0;
?? ?else?
?? ??? ?begin
?? ??? ??? ?case(num_disp)
?? ??? ??? ??? ?4'd0 : seg_data <= {dot_disp,7'b100_0000};
?? ??? ??? ??? ?4'd1 : seg_data <= {dot_disp,7'b111_1001};
?? ??? ??? ??? ?4'd2 : seg_data <= {dot_disp,7'b010_0100};
?? ??? ??? ??? ?4'd3 : seg_data <= {dot_disp,7'b011_0000};
?? ??? ??? ??? ?4'd4 : seg_data <= {dot_disp,7'b001_1001};
?? ??? ??? ??? ?4'd5 : seg_data <= {dot_disp,7'b001_0010};
?? ??? ??? ??? ?4'd6 : seg_data <= {dot_disp,7'b000_0010};
?? ??? ??? ??? ?4'd7 : seg_data <= {dot_disp,7'b111_1000};
?? ??? ??? ??? ?4'd8 : seg_data <= {dot_disp,7'b000_0000};
?? ??? ??? ??? ?4'd9 : seg_data <= {dot_disp,7'b001_0000};
?? ??? ??? ??? ?4'd10 : seg_data <= {8'b1111_1111};
?? ??? ??? ??? ?4'd11 : seg_data <= {8'b1011_1111};
?? ??? ??? ?default:
?? ??? ??? ??? ?seg_data<={dot_disp,7'b100_0000};
?? ??? ??? ?endcase
?? ??? ?end
end
?? ?
endmodule
?2、頻率測試模塊
module cymometer(?? ?
?? ?input clk,
?? ?input rst_n,
?? ?input clk_fx,
?? ?output reg [31:0]?? ?fre
);
?
parameter TIME_SYS = 20;
parameter TIME_GATE = 500_000_000;
localparam N = TIME_GATE /?? ?TIME_SYS;
reg gate;
reg [31:0] cnt_gate;
reg [31:0] cnt_fx;
?
wire gate_n;
?
assign gate_n = ~gate;
always @(posedge clk or negedge rst_n)begin?? ?
?? ?if(!rst_n)begin
?? ??? ?cnt_gate <=0;
?? ??? ?gate <=0;
?? ?end?? ?
?? ?else begin
?? ??? ?if(cnt_gate == N-1)begin
?? ??? ??? ?cnt_gate <= 0;
?? ??? ??? ?gate <= ~gate;
?? ??? ?end?? ?
?? ??? ?else
?? ??? ?cnt_gate<=cnt_gate+1;
?? ?end
end?
always @(posedge clk_fx or negedge rst_n)begin?? ?
?? ?if(!rst_n)
?? ??? ?cnt_fx <= 0;
?? ?else if(gate)
?? ??? ?cnt_fx <= cnt_fx + 1;
?? ?else
?? ??? ?cnt_fx <= 0;
end
?
always @(posedge gate_n or negedge rst_n)begin?? ?
?? ?if(!rst_n)
?? ??? ?fre <= 0;
?? ?else?
?? ??? ?fre <= 1000_000_000/TIME_GATE * cnt_fx;?? ?
end
?? ?
endmodule
?3、分頻模塊
module test_div(
?? ?input clk, ? ? ?
?? ?input rst_n, ? ? ??
?? ?output reg div_clk
);reg [9:0]clk_cnt;?
parameter CLK_DIVIDE = 7'd100;?always @(posedge clk or negedge rst_n)begin
?? ?if(!rst_n) begin
? ? ? clk_cnt <= 10'd0;
? ? ? div_clk <= 1'b0;
? ?end
? ?else if(clk_cnt == CLK_DIVIDE/2 - 1'd1)begin
? ? ? clk_cnt <= 10'd0;
? ? ? div_clk <= ~div_clk;
? ?end
? ?else begin
?? ??? ?clk_cnt <= clk_cnt + 1'b1;
?? ??? ?div_clk <= div_clk;
? ?end
endendmodule
四、總結(jié)
????????通過以上代碼,最后完成頂層調(diào)用模塊,再分配引腳,即可完成實(shí)驗(yàn)。
????????分頻模塊對系統(tǒng)時鐘進(jìn)行100分頻(500KHZ)輸入給頻率測量模塊,通過周期測量法在數(shù)碼管中顯示5000000。(自己產(chǎn)生頻率自己測量)
五、圖片
?
?文章來源:http://www.zghlxwxcb.cn/news/detail-735844.html
????????由于本人初學(xué)fgpa有很多困難并未解決,代碼雖然可以運(yùn)行但可能并不是最優(yōu),本文僅用于記錄自己的學(xué)習(xí)歷程以及實(shí)驗(yàn)總結(jié),煩請各位指正以及交流,歡迎各位私信交流。文章來源地址http://www.zghlxwxcb.cn/news/detail-735844.html
到了這里,關(guān)于FPGA(verilog)頻率計(jì)實(shí)驗(yàn)——學(xué)習(xí)歷程①的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!