1. 程式人生 > >計數器 FPGA電路實驗 作業2

計數器 FPGA電路實驗 作業2

實驗內容 1

使用Veriog - HDL 語言,DE0 FPGA 開發板 按照如下要求設計一個計數器電路 。

功能描述

在 DE0 開發板的 最右側 的 HEX LED 數碼管上,進行計數並用十進位制數進行顯示。計數器特徵如下:

只能使用一個50MHz的時鐘訊號,不要有計數器分頻的訊號作為時鐘

該計數器在電路復位後會迴圈的從0值遞增計數到最大值,計數最大值是一個迴圈變化的過程,計數器復位之後,第一次計數最大值是6,然後是7、8、9,然後計數最大值又變成6,如此往復迴圈, 計數數值變化的時間間隔是1秒 ,計數過程如下所示:

0 1 … 6 0 1 … 7 0 1 … 8 0 1 … 9 0 1 … 6 ……

人工繪製的電路結構RTL設計圖

頂層BDF圖如下:
這裡寫圖片描述
1.div模組為分頻器用於將50MHz時鐘訊號分頻產生1s時鐘訊號在clk_div輸出。
2.count模組為產生符合技術要求的計數器。
3.decoder_hex模組為4-7譯碼器,譯碼使在數碼管上顯示對應字元。
div模組人工繪製的RTL圖:
這裡寫圖片描述

Quartus掃描生成的電路RTL圖

這裡寫圖片描述

計數器的計數值的SignalTap截圖

這裡寫圖片描述

實驗程式碼

******************分頻器程式碼******************
module
div(
clk , // clock reset, CNTVAL, // counter value clk_div); // overflow input clk; input reset; output [32-1:0] CNTVAL; output clk_div; parameter MAX_VAL = 50_000_000; //50MHz下為1s reg [32-1:0] CNTVAL; reg clk_div; always @ (posedge clk) begin if (!reset) begin CNTVAL <= 0; end
else begin if(CNTVAL >= MAX_VAL) CNTVAL <= 0; else CNTVAL <= CNTVAL + 1'b1; end end always @ (CNTVAL) begin if(CNTVAL == MAX_VAL) clk_div = 1'b1; else clk_div = 1'b0; end endmodule
******************計數器程式碼******************
module count(
    clk,
    cnt,
    OV);
input clk,rst;
output reg[3:0] cnt;
output OV;
reg[1:0] state,next_state;
reg[3:0] cnt_temp;
parameter s0=2'b00,s1=2'b01,s2=2'b11,s3=2'b10;

[email protected]( next_state or rst)
begin
    if(rst)
        begin
        state=s0;
        cnt=0;
        end
    else
        begin
        state=next_state;
        cnt=cnt_temp;
        end
end

[email protected](posedge clk)
begin
    if(state == s0 && cnt == 0)
    begin
    cnt_temp=0;
    next_state=s0;
    end
    case(state)
    s0:begin
        if(cnt_temp>=6)
            begin
            cnt_temp=0;
            next_state=s1;
            end
        else
            begin
            cnt_temp=cnt_temp+1;
            end
        end
    s1:begin
        if(cnt_temp>=7)
            begin
            cnt_temp=0;
            next_state=s2;
            end 
        else
            begin
            cnt_temp=cnt_temp+1;
            end
       end
    s2:begin
        if(cnt_temp>=8)
            begin
            cnt_temp=0;
            next_state=s3;
            end 
        else
            begin
            cnt_temp=cnt_temp+1;
            end
       end
    s3:begin
        if(cnt_temp>=9)
            begin
            cnt_temp=0;
            next_state=s0;
            end
        else
            begin
            cnt_temp=cnt_temp+1;
            end
        end
    default:begin
        next_state=s0;
        cnt_temp=0;
        end
    endcase
end
endmodule
******************數碼管譯碼器程式碼******************
module decoder_hex(
    data_in,
    EN,
    data_out);
input [3:0] data_in ;
input EN ;
output [6:0] data_out ;
reg [6:0] data_out ;

always @(data_in or EN )
begin
        data_out = 7'b1111111;
if (EN == 1)
    case (data_in)
        4'b0000: data_out = 7'b1000000; // 0
        4'b0001: data_out = 7'b1111001; // 1
        4'b0010: data_out = 7'b0100100; // 2
        4'b0011: data_out = 7'b0110000; // 3
        4'b0100: data_out = 7'b0011001; // 4
        4'b0101: data_out = 7'b0010010; // 5
        4'b0110: data_out = 7'b0000011; // 6
        4'b0111: data_out = 7'b1111000; // 7
        4'b1000: data_out = 7'b0000000; // 8
        4'b1001: data_out = 7'b0011000; // 9
        4'b1010: data_out = 7'b0001000; // A
        4'b1011: data_out = 7'b0000011; // b
        4'b1100: data_out = 7'b1000110; // c
        4'b1101: data_out = 7'b0100001; // d
        4'b1110: data_out = 7'b0000110; // E
        4'b1111: data_out = 7'b0001110; // F
        default: data_out = 7'b1111111; //不顯示
    endcase
end
endmodule

計數過程連結

===================================================

實驗內容 2

功能描述

在 DE0 開發板的 從左到右 的 4個HEX LED 數碼管上,進行計數並用十進位制數進行顯示。計數器特徵如下

只能使用一個50MHz的時鐘訊號,不要有計數器分頻的訊號作為時鐘
系統復位後全部HEX LED熄滅
左1 LED,顯示 0、1、2 ~6 ,然後熄滅
左2 LED,顯示 0、1、2 ~7 ,然後熄滅
左3 LED,顯示 0、1、2 ~8 ,然後熄滅
最右側 LED,顯示 0、1、2 ~9 ,然後熄滅
然後再開始左1 LED, 顯示 0、1、2~6 如此一直迴圈。
所有情況下,計數數值變化的時間間隔是1秒

人工繪製的電路結構RTL設計圖

頂層BDF圖如下:
這裡寫圖片描述
1.div模組為分頻器用於將50MHz時鐘訊號分頻產生1s時鐘訊號在clk_div輸出。
2.count模組為產生符合技術要求的計數器。
3.decoder_hex模組為4-7譯碼器,譯碼使在數碼管上顯示對應字元。
4.select模組OV端輸出訊號分別使能四個譯碼器,產生移位效果。
select模組人工繪製的RTL圖:
這裡寫圖片描述

Quartus掃描生成的電路RTL圖

這裡寫圖片描述
Quartus掃描生成的電路select模組RTL圖:
這裡寫圖片描述
狀態機的狀態轉移圖和表示式:
這裡寫圖片描述

計數器的計數值的SignalTap截圖

這裡寫圖片描述

實驗程式碼

******************分頻器程式碼******************
module div(
    clk   ,   // clock
    reset,
    CNTVAL,   // counter value
    clk_div);  // overflow
input clk;
input reset; 
output [32-1:0] CNTVAL;
output clk_div;
parameter MAX_VAL = 50_000_000;  //50MHz下為1s
reg [32-1:0] CNTVAL;
reg clk_div;
always @ (posedge clk) 
begin
  if (!reset) 
  begin
    CNTVAL <= 0;
  end
  else
  begin
    if(CNTVAL >= MAX_VAL)
      CNTVAL <= 0;
    else
      CNTVAL <= CNTVAL + 1'b1;  
  end
end
always @ (CNTVAL) begin
  if(CNTVAL == MAX_VAL)
    clk_div = 1'b1;
  else
    clk_div = 1'b0;
end
endmodule
******************計數器程式碼******************
module count(
    clk,
    cnt,
    OV);
input clk,rst;
output reg[3:0] cnt;
output OV;
reg[1:0] state,next_state;
reg[3:0] cnt_temp;
parameter s0=2'b00,s1=2'b01,s2=2'b11,s3=2'b10;

[email protected]( next_state or rst)
begin
    if(rst)
        begin
        state=s0;
        cnt=0;
        end
    else
        begin
        state=next_state;
        cnt=cnt_temp;
        end
end

[email protected](posedge clk)
begin
    if(state == s0 && cnt == 0)
    begin
    cnt_temp=0;
    next_state=s0;
    end
    case(state)
    s0:begin
        if(cnt_temp>=6)
            begin
            cnt_temp=0;
            next_state=s1;
            end
        else
            begin
            cnt_temp=cnt_temp+1;
            end
        end
    s1:begin
        if(cnt_temp>=7)
            begin
            cnt_temp=0;
            next_state=s2;
            end 
        else
            begin
            cnt_temp=cnt_temp+1;
            end
       end
    s2:begin
        if(cnt_temp>=8)
            begin
            cnt_temp=0;
            next_state=s3;
            end 
        else
            begin
            cnt_temp=cnt_temp+1;
            end
       end
    s3:begin
        if(cnt_temp>=9)
            begin
            cnt_temp=0;
            next_state=s0;
            end
        else
            begin
            cnt_temp=cnt_temp+1;
            end
        end
    default:begin
        next_state=s0;
        cnt_temp=0;
        end
    endcase
end
endmodule
******************數碼管譯碼器程式碼******************
module decoder_hex(
    data_in,
    EN,
    data_out);
input [3:0] data_in ;
input EN ;
output [6:0] data_out ;
reg [6:0] data_out ;

always @(data_in or EN )
begin
        data_out = 7'b1111111;
if (EN == 1)
    case (data_in)
        4'b0000: data_out = 7'b1000000; // 0
        4'b0001: data_out = 7'b1111001; // 1
        4'b0010: data_out = 7'b0100100; // 2
        4'b0011: data_out = 7'b0110000; // 3
        4'b0100: data_out = 7'b0011001; // 4
        4'b0101: data_out = 7'b0010010; // 5
        4'b0110: data_out = 7'b0000011; // 6
        4'b0111: data_out = 7'b1111000; // 7
        4'b1000: data_out = 7'b0000000; // 8
        4'b1001: data_out = 7'b0011000; // 9
        4'b1010: data_out = 7'b0001000; // A
        4'b1011: data_out = 7'b0000011; // b
        4'b1100: data_out = 7'b1000110; // c
        4'b1101: data_out = 7'b0100001; // d
        4'b1110: data_out = 7'b0000110; // E
        4'b1111: data_out = 7'b0001110; // F
        default: data_out = 7'b1111111; //不顯示
    endcase
end
endmodule
******************選擇器程式碼******************
module select(
    IN          ,
    RESET       ,
    OV          );  
input   IN;
input   RESET;
output  OV;
parameter ST_INIT = 4'b0000;
parameter ST_0 = 4'b0001;
parameter ST_1 = 4'b0010;
parameter ST_2 = 4'b0100;
parameter ST_3 = 4'b1000;

reg[3:0] OV_temp;
reg[3:0] OV;

[email protected](RESET)
begin
    if(RESET)
        begin
        OV<=ST_INIT;
        end
    else
        begin
        OV<=OV_temp;
        end
end

always @ (posedge IN) begin
  case (OV_temp)
    ST_0 :begin if(IN==1) OV_temp <= ST_1 ; else OV_temp <= ST_0; end
    ST_1 :begin if(IN==1) OV_temp <= ST_2 ; else OV_temp <= ST_1; end
    ST_2 :begin if(IN==1) OV_temp <= ST_3 ; else OV_temp <= ST_2; end
    ST_3 :begin if(IN==1) OV_temp <= ST_0 ; else OV_temp <= ST_3; end
  endcase
end
endmodule

計數過程連結