verilog for循环_HDLBits:在线学习 Verilog (二十四 · Problem 115-119)
首先附上傳送門:
Rule90 - HDLBits?hdlbits.01xz.net這部分包括 More Circuits 欄目三道題目,該欄目歸納了使用時序邏輯生成對應輸出的題目。
Problem 115 Rule90
牛刀小試
Rule90 是一道根據一些有趣的規則來生成一維序列的題目。
規則很簡單。一維序列中元素有 1,0 兩種狀態,分別對應開,關狀態。
在每個時鐘邊沿到來時刻,元素的下一個狀態為元素相鄰兩個元素的異或。
下表更詳細地給出了跳變的規則,(可以視為狀態轉移表),元素下一個狀態可以視作輸出,輸入為元素本身的狀態與相應兩個相鄰元素的當前狀態。
by the way,本題題目中的 Rule90 來自于上表中的 next state 這一列: 01011010 = 8'd90。
對于需要實現的電路,創建一個擁有 512 個元素的序列 (q[511:0]),每個時鐘周期按照上述規則變換。load 信號有效時,序列更新 data 信號值為初始值。另外假設所有邊界的值為 0 (q[-1] 以及 q[512])
解答與分析
module top_module(input clk,input load,input [511:0] data,output reg[511:0] q ); int i;always @(posedge clk ) beginif(load)q <= data;else beginq[0] <= q[1] ^ 0;q[511] <= 0 ^ q[510];for(i = 1; i<511;i=i+1)q[i] <= q[i - 1] ^ q[i + 1]; endend endmodule解答中單列了兩種特殊情況,q[0] 以及 q[511] ,因為他們的左側或者右側元素并不存在,題目中將其設定為 0.
除此之外的情況,使用 for 循環,狀態轉移當前狀態左右鄰居值的異或結果,其中左鄰居指的是高位,右鄰居指的是低位,是一種大端格式。
其實也可以不單列出特殊情況,比如本題的參考解答(原作者實在厲害,在下佩服)
module top_module(input clk,input load,input [511:0] data,output reg [511:0] q);always @(posedge clk) beginif (load)q <= data; // Load the DFFs with a value.else begin// At each clock, the DFF storing each bit position becomes the XOR of its left neighbour// and its right neighbour. Since the operation is the same for every// bit position, it can be written as a single operation on vectors.// The shifts are accomplished using part select and concatenation operators.// left right// neighbour neighbourq <= q[511:1] ^ {q[510:0], 1'b0} ;endend endmodule異或左右鄰居矩陣,左右鄰居矩陣分別是原矩陣右移或者左移并補零得到,十分簡練。
Problem 116 Rule110
牛刀小試
Rule110 還是一道根據有趣的規則來生成一維序列的題目,比如用于:
https://en.wikipedia.org/wiki/Turing_completeness?en.wikipedia.org規則:一維序列中元素有 1,0 兩種狀態,分別對應開,關狀態。
在每個時鐘邊沿到來時刻,元素的下一個狀態取決于元素本身的狀態與前后兩個相鄰元素的當前狀態。下表詳細地給出了跳變的規則。
題目中的 Rule110 來自于上表中的 next state 這一列: 01101110= 8'd110。
對于需要實現的電路,創建一個擁有 512 個元素的序列 (q[511:0]),每個時鐘周期按照上述規則變換。load 信號有效時,序列更新 data 信號值為初始值。另外假設所有邊界的值為 0 (q[-1] q[512])
解答與分析
本題與上一題的區別在于沒有給出具體的此態生成關系,比如上一題中的異或。所以我們首先需要找出狀態轉移規則。我們把上述的狀態轉移表轉換為一個真值表來尋找轉換規則,真值表對應的是三個輸入信號:left,center,right,一個輸出信號:next_state。
根據卡諾圖可以得到:OUT = Center ^ Right + (Center · ~Left )
找到轉移關系后,后續的解答就和上一題相同。
module top_module(input clk,input load,input [511:0] data,output reg[511:0] q ); int i;always @(posedge clk ) beginif(load)q <= data;else beginq[0] <= q[0];q[511] <= (q[511] ^ q[510] )|| ( q[510] );for(i = 1; i<511;i=i+1)q[i] <= (q[i] ^ q[i - 1] )|| (!q[i+1] & q[i-1]); endend endmoduleProblem 117 Conwaylift/conway's game of life 16x16
牛刀小試
作為前兩題的升級版,本題的變換工作在一個二維矩陣上,是一個二維序列生成器。
游戲規則如下:元素的下一個狀態取決于當前狀態九宮格中的 8 個鄰居元素中 1 的個數,當鄰居有 n 個 1 時:
- 0-1 ,元素變為 0
- 2 ,元素保持不變
- 3 ,元素變為 1
- 4+ ,元素變為 0
方便做題起見,本題中的這個二維矩陣設定為 16x16,廣義上可以是無限的。
為了讓事情變得更加有趣,這個16x16 矩陣的邊界進行循環處理,回卷到對邊,打個比方,上邊界的上一行為下邊界,左邊界的左一列為右邊界。
上下邊界回卷示意,左右邊界同理所以對元素 (0,0) 來說,共有 8 個鄰居 : (15,1), (15,0), (15,15), (0,1), (0,15), (1,1), (1,0) 以及 (1,15)。
這個 16x16 矩陣表示為 256bit 長度的向量 q,其中 q[15:0] 代表第一行,q[31:16] 代表第二行,以此類推。
HDLBit 支持使用 SystemVerilog,所以你也可以使用二維向量表示這個矩陣。load 信號有效時,更新 q 信號值為初始值 data, q 每個周期變換一次。
解答與分析
module top_module(input clk,input load,input [255:0] data,output [255:0] q ); reg [15:0] q_2d [15:0]; //2-d qwire [2:0] nghbr_num [255:0];int idx_i_d,idx_i_u,idx_j_r,idx_j_l,i,j;//count num of neighboursalways@(*) beginfor(i = 0 ; i < 16 ; i = i + 1) beginfor(j = 0 ; j < 16 ; j = j + 1) beginidx_i_u = (i == 0) ? i-1+16 :i-1; //up idxidx_i_d = (i == 15)? i+1-16 :i+1; //down idxidx_j_l = (j == 0) ? j-1+16 :j-1; //left idxidx_j_r = (j == 15)? j+1-16 :j+1; //right idxnghbr_num[i*16+j] = q_2d[idx_i_u][idx_j_l] + q_2d[idx_i_u][j ] + q_2d[idx_i_u][idx_j_r]+ q_2d[i ][idx_j_l] + q_2d[i ][idx_j_r]+ q_2d[idx_i_d][idx_j_l] + q_2d[idx_i_d][j ] + q_2d[idx_i_d][idx_j_r];endendend//next state transform base on num of neighboursalways @(posedge clk) beginif(load) begin:initfor(i = 0 ; i < 16 ; i = i + 1) beginfor(j = 0 ; j < 16 ; j = j + 1) beginq_2d[i][j] <= data[i*16+j];endendendelse begin:set_valfor(i = 0 ; i < 16 ; i = i + 1) beginfor(j = 0 ; j < 16 ; j = j + 1) beginif(nghbr_num[i*16+j] < 2)q_2d[i][j] <= 1'b0;else if (nghbr_num[i*16+j] > 3)q_2d[i][j] <= 1'b0;else if (nghbr_num[i*16+j] == 3)q_2d[i][j] <= 1'b1;elseq_2d[i][j] <= q_2d[i][j];endendendend//outputalways@(*) beginfor(i = 0 ; i < 16 ; i = i + 1) beginfor(j = 0 ; j < 16 ; j = j + 1) beginq[i*16+j] = q_2d[i][j];endendendendmodule本題筆者采用一分為 2 的思路:
- 統計矩陣中每個元素的 8 -相鄰元素中 1 的個數
- 根據相鄰元素中的 1 的個數,決定元素下一狀態的值
使用組合邏輯,采用相加的方式計算相鄰元素中 1 的個數,使用一個 256 長的序列來記錄每個元素相鄰元素中 1 的個數,最大為 8 個,所以每個元素使用 3 bit 來記錄。
wire [2:0] nghbr_num [255:0];在統計時,需要處理邊界繞回的的特殊情況。對于邊界上的元素,根據繞回的規則確立邊界。需要特殊處理的是第一/最后一行/列。在編寫 Verilog 代碼時,可以對這幾種情況分別確立邊界。
因為不想代表顯得太冗長,這里引入了 4 個整形變量 idx_i_d, idx_i_u, idx_j_r, idx_j_l ,在不同的情況下,來確立四條邊界。
idx_i_u = (i == 0) ? i-1+16 :i-1; //up idx idx_i_d = (i == 15)? i+1-16 :i+1; //down idx idx_j_l = (j == 0) ? j-1+16 :j-1; //left idx idx_j_r = (j == 15)? j+1-16 :j+1; //right idx使用時序邏輯,根據統計的結果,決定下一周期元素的值。
輸出最終結果時,將二維信號重新轉換為一維信號,Verilog 不支持直接在一維/二維信號之間賦值。
從下一題開始將進入一個漫長的狀態機欄目,我們將討論多道學習狀態機的題目。
Problem 118 Simple FSM1 / Fsm1
牛刀小試
圖中是一個有兩個狀態的摩爾型狀態機。有一個輸入信號與一個輸出信號。本題中需要實現圖中的狀態機,注意復位后狀態為 B,復位采用異步復位。
解答與分析
module top_module (input clk,input in,input areset,output out );// -----實現狀態機 endmodule這里我們學習標準答案中的表示,采用三段式的寫法來描述這個簡單的狀態機。三段式狀態機雖然代碼會長一些,但能夠更方便地修改,并更清晰地表達狀態機的跳變與輸出規則。
使用參數來表示每個狀態。
// Give state names and assignments. I'm lazy, so I like to use decimal numbers.// It doesn't really matter what assignment is used, as long as they're unique.parameter A=0, B=1;reg state; // Ensure state and next are big enough to hold the state encoding.reg next;// A finite state machine is usually coded in three parts:// State transition logic// State flip-flops// Output logic// It is sometimes possible to combine one or more of these blobs of code// together, but be careful: Some blobs are combinational circuits, while some// are clocked (DFFs).三段式分別指
- 狀態跳轉邏輯
- 狀態觸發器實現
- 輸出邏輯
狀態跳轉邏輯,根據輸入信號以及當前狀態確定狀態的次態。
// Combinational always block for state transition logic. Given the current state and inputs,// what should be next state be?// Combinational always block: Use blocking assignments.always@(*) begincase (state)A: next = in ? A : B;B: next = in ? B : A;endcaseend狀態觸發器實現,在時鐘邊沿實現狀態寄存器的跳變以及狀態復位
// Edge-triggered always block (DFFs) for state flip-flops. Asynchronous reset.always @(posedge clk, posedge areset) beginif (areset) state <= B; // Reset to state Belse state <= next; // Otherwise, cause the state to transitionend輸出邏輯,根據當前狀態實現輸出
// Combinational output logic. In this problem, an assign statement is the simplest.// In more complex circuits, a combinational always block may be more suitable.assign out = (state==B);Problem 119 Simple FSM1 / Fsm1s
牛刀小試
實現一個和上一題相同,但采用同步復位的狀態機。
和上一題只是復位的方式不同,這里不再贅述實現代碼了。
總結
以上是生活随笔為你收集整理的verilog for循环_HDLBits:在线学习 Verilog (二十四 · Problem 115-119)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: jdbc不能识别别名_Spark基础:读
- 下一篇: 单页面axios_Axios封装之取消重