跟著教程寫了幾種方法,才發現自己寫的雖然能實現,但比較繁瑣。教程有三種方法: 1.移位法,每次左移一位,相比我自己寫的,優點是不用把每一種情況都寫出來。但是需要考慮左移到最後一位時需要自己再寫個賦值語句重新回到第一位。 2.位拼接法,迴圈左移,每一次都把最後一位放到第一位,其他六位左移一位,剋服了移 ...
跟著教程寫了幾種方法,才發現自己寫的雖然能實現,但比較繁瑣。教程有三種方法:
1.移位法,每次左移一位,相比我自己寫的,優點是不用把每一種情況都寫出來。但是需要考慮左移到最後一位時需要自己再寫個賦值語句重新回到第一位。
2.位拼接法,迴圈左移,每一次都把最後一位放到第一位,其他六位左移一位,剋服了移位法的問題,簡化了代碼。
3.調用已有模塊法,調用4-16解碼器剛好可以實現流水燈,需要額外的counter作為解碼器的輸入。
- 移位法
module led_run1( //移位法
clk,
reset,
led
);
input clk;
input reset;
output reg [7:0]led;
reg [5:0]counter1;
always@( posedge clk or negedge reset )begin
if( reset == 1'd0)
counter1 <= 1'd0;
else if(counter1 == 4 ) 這兩個雖然賦值語句一樣,但是不能把判斷語句合併。
counter1 <=1'd0;
else
counter1 <= counter1 + 1'd1;
end
always@(posedge clk or negedge reset) begin
if( reset == 1'd0)
led <= 8'b0000_0001;
else if(counter1 == 4 )begin
if(led == 8'b1000_0000)
led <= 8'b0000_0001; //最後一位的處理
else
led <= led << 1'd1 ; //註意左移幾位的語法,應該怎麼寫
end
end
endmodule
- 位拼接法
module led_run2( //位拼接法
clk,
reset,
led
);
input clk;
input reset;
output reg [7:0]led;
reg [5:0]counter1;
always@( posedge clk or negedge reset )begin
if( reset == 1'd0)
counter1 <= 1'd0;
else if(counter1 == 4 )
counter1 <=1'd0;
else
counter1 <= counter1 + 1'd1;
end
always@(posedge clk or negedge reset) begin
if( reset == 1'd0)
led <= 8'b0000_0001;
else if(counter1 == 4 )begin
led <= {led[6:0],led[7]}; //位拼接的語法,十分註意
end
end
endmodule
- 調用模塊法
module led_run4( //調用模塊4-16解碼器法
clk,
reset,
led
);
input clk;
input reset;
output wire [15:0]led;
reg [2:0]counter1;
reg [3:0]counter4; 一個用來計數,一個用來解碼
always@( posedge clk or negedge reset )begin
if( reset == 1'd0)
counter1 <= 1'd0;
else if(counter1 == 4 )
counter1 <=1'd0;
else
counter1 <= counter1 + 1'd1;
end
always@(posedge clk or negedge reset) begin
if( reset == 1'd0)
counter4 <= 8'd1;
else if(counter1 == 4 )begin
counter4 <= counter4 + 1'b1;
end
end
decoder_4_16 decoder_4_16_run( //調用的方法類似於模擬時的例化,存儲電路與組合邏輯電路相結合。
.a(counter4[3]),
.b(counter4[2]),
.c(counter4[1]),
.d(counter4[0]),
.out(led)
);
endmodule
註意:
1.左移/右移的語法:led=led << n / led=led >> n
2.位拼接的語法:led={led[6:0],led[7]} 註意花括弧,中括弧,數組表達方式。定義時中括弧放名字前,引用時放名字後。逗號隔開位。
3.一個testbench可以用來測試驗證多個模塊,需要修改的是tb裡面例化的模塊名,激勵如果一樣可以不修改。(testbench差不多就是個激勵產生器用來驗證性能)
4.在工程中創建的design sources的源文件的路徑為:.srcs->sources->new->xx.v
5.時序電路自少需要一個計數器來控制開發板時鐘信號和我們實際需要的周期信號的關係。但是不是說只能有一個,可以根據需求增加。
6.報錯:ordered port connections cannot be mixed with named port connections 目標埠連接不能與命名埠連接混合
原因:最後一個變數後面加了逗號,刪掉即可。
7.調用子模塊的方式:
7.1把子模塊的文件複製到當前工程的design源文件目錄下,路徑上面有寫。
7.2在vivado中添加該文件進design sources,作為子模塊。
7.3在頂層文件(即要調用該子文件的文件)調用子模塊,方式是類似於testbench的例化。註意,在子模塊(底層)中定義了輸出為reg型,在頂層應該定義輸出為wire型。
效果