2013-03-04 96 views
2

這是我的第一篇文章,所以我希望我正確地做到了這一點。我試圖在BASYS2板上的四位數七段顯示器上輸出「4 3 2 1」。我已檢查確保0啓用信號,並且我已正確映射端口。我相信這個錯誤在我的多路複用邏輯中,因爲我只能顯示一個數字。我是Verilog的新手(我習慣於C),並希望得到任何建議。由於Basys2上的七段多路複用

`timescale 1ns/1ps 

module main (clock, AN0, AN1, AN2, AN3, CA, CB, CC, CD, CE, CF, CG, CDP); 


//USED FOR SEVEN SEG 
input clock; 

output AN0, AN1, AN2, AN3, CA, CB, CC, CD, CE, CF, CG, CDP; 

reg [7:0] cathodedata; //cathode data 
reg [3:0] anodedata; //anode data 
reg [2:0] digit = 1; 
reg [6:0] data; 
reg setdp; 
reg [19:0] counter = 0; 

assign CA = cathodedata [7]; 
assign CB = cathodedata [6]; 
assign CC = cathodedata [5]; 
assign CD = cathodedata [4]; 
assign CE = cathodedata [3]; 
assign CF = cathodedata [2]; 
assign CG = cathodedata [1]; 
assign CDP = cathodedata [0]; 
assign AN3 = anodedata [3]; 
assign AN2 = anodedata [2]; 
assign AN1 = anodedata [1]; 
assign AN0 = anodedata [0]; 
//USED FOR SEVEN SEG 

    //Multiplexing 
    //Board Clock: 50MHz 
    //p = t*f 
    //t = 16ms 
    //p = 16ms * 50*10^6 = 800,000 cycles 
    //200,000 cycles for each digit 
    //Refreshed every 16ms (~60Hz) 

[email protected](negedge clock) 
begin 
    if (digit == 1) 
     begin 
      if (counter == 200_000) 
       begin 
        digit = 2; 
       end 
      else 
       begin 
       counter = counter + 1; 
       data = 4; 
       end 
     end 
    else if (digit == 2) 
     begin 
      if (counter == 400_000) 
       begin 
        digit = 3; 
       end 
      else 
       begin 
        counter = counter + 1; 
        data = 3; 
       end 
     end 
    else if (digit == 3) 
     begin 
      if (counter == 600_000) 
       begin 
        digit = 4; 
       end 
      else 
       begin 
        counter = counter + 1; 
        data = 2; 
       end 
     end 
    else if (digit == 4) 
     begin 
      if (counter == 800_000) 
       begin 
        digit = 1; 
        counter = 0; 
       end 
      else 
       begin 
        counter = counter + 1; 
        data = 1; 
       end 
     end 
end 


always @ (*) 
begin 

    case (data) 
     6'd0: cathodedata = 8'b00000011; //0 
     6'd1: cathodedata = 8'b10011111; //1 
     6'd2: cathodedata = 8'b00100101; //2 
     6'd3: cathodedata = 8'b00001101; //3 
     6'd4: cathodedata = 8'b10011001; //4 
     6'd5: cathodedata = 8'b01001001; //5 
     6'd6: cathodedata = 8'b01000001; //6 
     6'd7: cathodedata = 8'b00011111; //7 
     6'd8: cathodedata = 8'b00000001; //8 
     6'd9: cathodedata = 8'b00001001; //9 
     6'd10: cathodedata = 8'b00010001; //A 
     6'd11: cathodedata = 8'b11000001; //B 
     6'd12: cathodedata = 8'b01100011; //C 
     6'd13: cathodedata = 8'b10000101; //D 
     6'd14: cathodedata = 8'b00100001; //E 
     6'd15: cathodedata = 8'b01110001; //F 
     default: cathodedata = 8'b11111111; //default all off 
    endcase 

    if (setdp == 1) //decimal point 
     cathodedata = cathodedata & 8'hFE; 

    case(digit) 
     0: anodedata = 4'b1111; //all OFF 
     4: anodedata = 4'b1110; //AN0 
     3: anodedata = 4'b1101; //AN1 
     2: anodedata = 4'b1011; //AN2 
     1: anodedata = 4'b0111; //AN3 
     default: 
     anodedata = 4'b1111; //all OFF 
    endcase 

end 
endmodule 
+2

您是否在波形模擬器中檢查過? – Tim 2013-03-04 03:53:26

+0

是的。我的結果如預期。每個陽極使能信號在預期時爲低電平,並且在此期間存在正確的陰極數據。當我將文件下載到我的FPGA電路板(Basys2)時,我在AN3處看到「8」大約半秒,然後是穩定的「4」。 AN2,AN1和AN0全部保持關閉。 – BlueSolrac 2013-03-04 05:23:55

+1

調試時,更容易咬掉較小的塊並單獨測試它們以縮小問題可能出現的位置。這是一個消除的過程。 – N8TRO 2013-03-04 07:34:51

回答

2

我也在使用basys2並尋找7段驅動程序。 Nathan G的代碼不適合我(使用系統verilog也許?),但是我發現這篇文章:http://simplefpga.blogspot.co.uk/2012/12/scrolling-or-moving-text-using-7.html?showComment=1362783256904#c5783969326158067433,並且我將它打包到我自己的end.The修改後的代碼如下。它應該(雖然我還沒有完全檢查解碼)四個十六進制值,並顯示在7段。在我的例子我的主板現在說 'FAAF'(因爲得到這個工作是FAF)從Digilent的網站採取

UCF文件:

# Pin assignment for DispCtl 
# Connected to Basys2 onBoard 7seg display 
NET "seg<0>" LOC = "L14"; # Bank = 1, Signal name = CA 
NET "seg<1>" LOC = "H12"; # Bank = 1, Signal name = CB 
NET "seg<2>" LOC = "N14"; # Bank = 1, Signal name = CC 
NET "seg<3>" LOC = "N11"; # Bank = 2, Signal name = CD 
NET "seg<4>" LOC = "P12"; # Bank = 2, Signal name = CE 
NET "seg<5>" LOC = "L13"; # Bank = 1, Signal name = CF 
NET "seg<6>" LOC = "M12"; # Bank = 1, Signal name = CG 

NET "dp" LOC = "N13"; # Bank = 1, Signal name = DP 

NET "an<3>" LOC = "K14"; # Bank = 1, Signal name = AN3 
NET "an<2>" LOC = "M13"; # Bank = 1, Signal name = AN2 
NET "an<1>" LOC = "J12"; # Bank = 1, Signal name = AN1 
NET "an<0>" LOC = "F12"; # Bank = 1, Signal name = AN0 

頂級模塊具有這樣的:

module top_level(  

//clock input 
input CLK, 

output [7:0] seg, 
output dp, 
output [3:0] an 

);  

scrolling_name scrolling_name(
.clock(CLK), 
.reset(RESET), 
.a(seg[0]), 
.b(seg[1]), 
.c(seg[2]), 
.d(seg[3]), 
.e(seg[4]), 
.f(seg[5]), 
.g(seg[6]), 
.dp(dp), 
.an(an), 
//.XPosition(XPosition), 
//.YPosition(YPosition) 
.XPosition(8'hFA), 
.YPosition(8'hAF) 
); 

endmodule 

和我從鏈接中的傢伙拿到的文件是:

`timescale 1ns/1ps 

module scrolling_name(
input clock, 
input reset, 
output a, 
output b, 
output c, 
output d, 
output e, 
output f, 
output g, 
output dp, 
output [3:0] an, 
input [7:0] XPosition, 
input [7:0] YPosition 
); 

reg [28:0] ticker; //to hold a count of 50M 
wire click; 
reg [3:0] fourth, third, second, first; // registers to hold the LED values 

always @ (posedge clock or posedge reset) //always block for the ticker 
begin 
if(reset) 
ticker <= 0; 
else if(ticker == 50000000) //reset after 1 second 
ticker <= 0; 
else 
ticker <= ticker + 1; 
end 

reg [3:0] clickcount; //register to hold the count upto 9. That is why a 4 bit  register is used. 3 bit would not have been enough. 

assign click = ((ticker == 50000000)?1'b1:1'b0); //click every second 

always @ (posedge click or posedge reset) 
begin 
if(reset) 
    clickcount <= 0; 
else if(clickcount == 8) 
    clickcount <= 0; 
    else 
    clickcount <= clickcount + 1; 

end 

[email protected](posedge clock) 
begin 
fourth = XPosition[7:4]; 
third = XPosition[3:0]; 

second = YPosition[7:4]; 
first = YPosition[3:0]; 
end 

//see my other post on explanation of LED multiplexing. 

localparam N = 18; 

reg [N-1:0]count; 

always @ (posedge clock or posedge reset) 
begin 
    if (reset) 
    count <= 0; 
    else 
    count <= count + 1; 
end 

reg [6:0]sseg; 
reg [3:0]an_temp; 

always @ (*) 
begin 
    case(count[N-1:N-2]) 

    2'b00 : 
    begin 
    sseg = first; 
    an_temp = 4'b1110; 
    end 

    2'b01: 
    begin 
    sseg = second; 
    an_temp = 4'b1101; 
    end 

    2'b10: 
    begin 
    sseg = third; 
    an_temp = 4'b1011; 
    end 

    2'b11: 
    begin 
    sseg = fourth; 
    an_temp = 4'b0111; 
    end 
    endcase 
end 
assign an = an_temp; 

reg [6:0] sseg_temp; 

always @ (*) 
begin 
    case(sseg) 
    0 : sseg_temp = 7'b1000000; //to display 0 
    1 : sseg_temp = 7'b1001111; //to display 1 
    2 : sseg_temp = 7'b0100100; //to display 2 
    3 : sseg_temp = 7'b0110000; //to display 3 
    4 : sseg_temp = 7'b0011001; //to display 4 
    5 : sseg_temp = 7'b0010010; //to display 5 
    6 : sseg_temp = 7'b0000011; //to display 6 
    7 : sseg_temp = 7'b1111000; //to display 7 
    8 : sseg_temp = 7'b0000000; //to display 8 
    9 : sseg_temp = 7'b0011000; //to display 9 
    10 : sseg_temp = 7'b0001000; //to display A 
    11 : sseg_temp = 7'b0000011; //to display B 
    12 : sseg_temp = 7'b1000110; //to display C 
    13 : sseg_temp = 7'b0100001; //to display D 
    14 : sseg_temp = 7'b0000110; //to display E 
    15 : sseg_temp = 7'b0001110; //to display F 

default : sseg_temp = 7'b1111111; //blank 
endcase 
end 

assign {g, f, e, d, c, b, a} = sseg_temp; 
assign dp = 1'b1; 

endmodule 

請原諒這個可怕的格式化/縮進 - 他的,我的組合,並添加四個空間來獲取堆棧溢出,將其識別爲代碼。我沒有時間讓事情變得很不幸。如果你願意的話,我可以將所有這些都捆綁在一起,並放在保管箱中。

Nathan

+0

我剛剛運行我的代碼,我修復了一個小錯誤。 (我的端口聲明是錯誤的)如果你的工作,那很好。但我會考慮重新組織代碼的佈局,使其更具可讀性。 – N8TRO 2013-03-09 00:16:04

+0

@Nathan G - 是的,港口聲明是突然出現的錯誤之一......但最終這些細分市場一直保持空白。真的不知道爲什麼,而且我有點急,所以我只是繼續前進。也許真的很基本,像針腳分配。我猜如果原始海報發現我的代碼有用,我會在幾天/有空的時候清理它。 – 2013-03-09 00:36:04

+0

夥計們,謝謝你們的代碼。我感覺真的很愚蠢。我的代碼其實很好。我的UCF不正確。我有時鐘映射到RCCLK(C8),而不是MCLK(B8)。衛生署!我確實學到了更多關於verilog檢查你的兩個代碼的知識。我也喜歡你發現的滾動文本例子,因爲我可能會在未來實現它。 – BlueSolrac 2013-03-10 23:04:13

-1

迎你到底有:

always @(*) begin 
... 
    if (setdp == 1) //decimal point 
    cathodedata = cathodedata & 8'hFE; 

always @*意味着一個組合塊,即無觸發器分手循環等。你的模擬器可能沒有抓住這一點,但我希望它在合成中有實際問題。

基本上你有陰極數據驅動自己。

always @(*) begin 
... 
    if (setdp == 1) //decimal point 
    cathodedata_mask = cathodedata & 8'hFE; 
    else 
    cathodedata_mask = cathodedata; 
+0

我認爲我不同意他的代碼會導致綜合問題,我非常肯定我之前使用過這樣的構造。 '陰極數據'已經由前面的case語句設置,所以我認爲這基本上就像在case語句的輸出上放置一個多路複用器,並將case語句的輸出驅動到一個輸入,並驅動輸出案例陳述以'FE'結尾到另一個港口。輸出線將被命名爲'cathodedata'。 – Tim 2013-03-06 21:12:49

+0

我看到你的觀點@Tim,陰極數據總是在此之前分配。我想我會避免這樣編碼。 – Morgan 2013-03-06 22:10:31

3

這裏是我的寵物項目之一的修改版本:

我會像替換此。它應該按照您的想法完成:在4dig7seg顯示屏上顯示4 3 2 1。我使用Amani GTX CPLD對其進行了測試,它應該乾淨地轉移到您的主板上。

我喜歡把項目分成單獨的模塊來保持組織。頂層模塊將板載時鐘作爲輸入,並將14個信號輸出到四位七段串行顯示器。 確保引腳分配正確。

module SevenSeg(clk, odig, onum, col, ap); 

input clk;   // 50 MHz oscillator 
output [3:0] odig; // selected digit output 
output [7:0] onum; // selected display output 
output col = 1; // turns the colon off 
output ap = 1; // turns the apostrophe off 

wire clock;  // divided oscillator to slow the display output 

parameter a = 8'b11111110; // low means on, high means off 
parameter b = 8'b11111101; // these are just parameters 
parameter c = 8'b11111011; // defining each of the 
parameter d = 8'b11110111; // seven segments 
parameter e = 8'b11101111; // making life easier 
parameter f = 8'b11011111; 
parameter g = 8'b10111111; 
parameter dp = 8'b01111111; 

parameter off = 8'b11111111; 

parameter one = b & c;    // parameters for outputs 
parameter two = a & b & d & e & g; 
parameter three = a & b & c & d & g; 
parameter four = b & c & f & g; 


    wire [7:0] port1 = one; // This is set up so these can change dynamically... 
    wire [7:0] port2 = two; // ... if so desired.  
    wire [7:0] port3 = three; 
    wire [7:0] port4 = four; 


slowclk m1(clk, clock); // divides clk by 500, for 50 MHz in, 100 kHz out 

digitize m2(clock, port1, port2, port3, port4, odig, onum); // rotates the digit outputs 

endmodule 

接下來,我有一個簡單的時鐘分頻器。 個案計數= 500可以修改爲將您的時鐘分爲您喜歡的任何頻率。輸出在大約120Hz到大約2MHz範圍內應該看起來很好。

module slowclk(clk, clock); 

input clk; 
output reg clock; 
integer count; 

always @(posedge clk) 
case(count)  
500: begin clock <= clock + 1; count <= 0; end // Change 500 to any divisor you like 
default: count <= count + 1; 
endcase 
endmodule 

接着我們來旋轉數字。請注意,如果您在「相同」時間更改陽極和陰極,相鄰區段會有小的泄漏電流,從而導致「鬼影」效應。

module digitize(clock, num1, num2, num3, num4, odig, onum); 

input wire clock; 
input [7:0] num1; // rightmost digit 
input [7:0] num2; 
input [7:0] num3; 
input [7:0] num4; // leftmost digit 

output reg [3:0] odig; 
output reg [7:0] onum; 

parameter [7:0] off = 8'b11111111; 

reg [3:0] dstate; 

always @(posedge clock) 
case(dstate) 
0:begin odig <= 4'b0001; dstate <= 1; end 
1:begin onum <= num1; dstate <= 2; end 
2:begin onum <= off;  dstate <= 3; end // off states prevent 'ghosting' 
3:begin odig <= 4'b0010; dstate <= 4; end // when changing output digit 
4:begin onum <= num2; dstate <= 5; end 
5:begin onum <= off;  dstate <= 6; end 
6:begin odig <= 4'b0100; dstate <= 7; end 
7:begin onum <= num3; dstate <= 8; end 
8:begin onum <= off;  dstate <= 9; end 
9:begin odig <= 4'b1000; dstate <= 10; end 
10:begin onum <= num4; dstate <= 11; end 
11:begin onum <= off;  dstate <= 0; end 
default: dstate <= 0; 
endcase 
endmodule