可能我學習 Verilog 的網頁寫的不好?或是 @ 概念是在做板子測試時看到故沒有放到心裡去!
昨天下午在學 repeat 語法時,該範例的波形讓我一直百思不得其解,終於在睡覺前大概知道為什麼,但就差在不確定 @ 是否有等待的作用?
雖然從結果來看,就像是 wait?
下午外出回來洗完澡,用 "Verilog @ syntax" 關鍵字查詢,終於看到一個大學的 PDF 有描述到這個語法,但我還是想要看到更官方的資料(IEEE?)。
總之,我昨天犯了一個錯誤:
明明告訴你是 posedge clk,故接下來的 code 理論上應該已經離開了 posedge clk 那個點,先不論 @ 是否會 wait,本來就應該要到下一個 poedge clk 才會再被偵測到,也就是下一個 clock cycle。
所以 96 ns 時,雖然 j = 0,但要到下一個 clock,106 ns 時才會對 buffer0 設值。
我們可以簡單用這個小程式來觀察時間點,從時間單位 10 開始,每隔 20 單位依序印出 1 和 2 當下的時間。
reg clk = 0;
always begin
#10;
clk = ~clk;
end
always @ (posedge clk) begin
$display("1", $time);
@(posedge clk) begin
$display("2", $time);
end
end
整個 repeat example 如下:
`timescale 1ns/1ns
module study;
initial begin
$dumpfile("wave.vcd");
$dumpvars(0, study);
end
reg [3:0] counter3;
initial begin
counter3 = 'b0;
repeat (11) begin
#10;
counter3 = counter3 + 1'b1;
end
end
//(3)
reg clk;
reg rstn;
reg enable;
reg [3:0] buffer[7:0];
reg [3:0] buffer7, buffer6, buffer5, buffer4, buffer3, buffer2, buffer1, buffer0;
integer j;
integer i = 0;
initial begin
clk = 0;
rstn = 1;
enable = 0;
#3;
rstn = 0;
#3;
rstn = 1;
enable = 1;
forever begin
clk <= ~clk;
#5;
end
end
always @(posedge clk or negedge rstn) begin
j = 0;
if (!rstn) begin
repeat (8) begin
buffer[j] <= 'b0;
j = j + 1;
end
i = 1;
end
else if (enable) begin
repeat (8) begin
@(posedge clk) buffer[j] <= counter3;
j = j + 1;
end
end
end
always @(buffer[7]) begin
buffer7 <= buffer[7];
end
always @(buffer[6]) begin
buffer6 <= buffer[6];
end
always @(buffer[5]) begin
buffer5 <= buffer[5];
end
always @(buffer[4]) begin
buffer4 <= buffer[4];
end
always @(buffer[3]) begin
buffer3 <= buffer[3];
end
always @(buffer[2]) begin
buffer2 <= buffer[2];
end
always @(buffer[1]) begin
buffer1 <= buffer[1];
end
always @(buffer[0]) begin
buffer0 <= buffer[0];
end
//stop the simulation
always begin
#10;
if ($time >= 1000) $finish;
end
endmodule
上面 buffer0 ~ buffer7 是為了接住 buffer[7:0] array 值用,可能是我還不會用 iverilog,無法在 GTKWave 中看到 array,故先用這種方式方便我看波形。
另一個很重要的概念是 = 雖然是阻塞賦值,可以控制流程先後順序,但這個操作應該是不佔時間,至少我從 wave 中看到,變數 i 的值是在 3 ns 時變成 1。
2023/12/18 更新
這應該是 Verilog - 2001 Standard 裡面關於 @ 的描述。
2023/12/26 更新
可以用 generate 語法來 mapping array,比宣告 buffer1 ~ buffer7 還方便。
buffer[0] 就是 test.array_buffer[0].buf。
genvar k;
generate
for (k = 0; k < 8; k = k + 1) begin: array_buffer
wire [3:0] buf;
assign buf = buffer[k];
end
endgenerate
沒有留言:
張貼留言