首先附上傳送門
Problem 105 12-hour clock
牛刀小試
用計數器設計一個帶am/pm的12小時時鐘。該計數器通過一個CLK進行計時,用ena使能信號來驅動時鐘的遞增。
reset信號將時鐘複位為12:00 AM。 信號pm為0代表AM,為1代表PM。hh、mm和ss由兩個BCD計數器構成hours(01~12), minutes(00~59) , second(00~59)。Reset信號比enable信號有更高的優先順序,即使沒有enable信號也可以進行複位操作。
下圖所示的時序圖給出了從11:59:59 AM 到12 :00 : 00 PM的變化。
Hint
需要注意的是從11:59:59 PM 到12:00:00 AM和從12:59:59 PM到01:00:00 PM的變化。
解答與解析
module top_module ( input clk, input reset, input ena, output pm, output [7:0] hh, output [7:0] mm, output [7:0] ss );
reg p; //0 is am, 1 is pm reg [7:0] h; reg [7:0] m; reg [7:0] s;
always @ (posedge clk) begin if(reset) //reset to 12:00:00 AM begin p <= 0; h <= 8h12; m <= 8h00; s <= 8h00; end else begin if(ena) begin if(s < 8h59) begin if(s[3:0] < 4h9) //s[3:0] is ones digit begin s[3:0] <= s[3:0] + 1h1; end else begin s[3:0] <= 0; //59->00 s[7:4] <= s[7:4] + 1h1; //tens digit end end else begin s <= 0; //s清零 if(m < 8h59) //m同理s begin if(m[3:0] < 4h9) begin m[3:0] <= m[3:0] + 1h1; end else begin m[3:0] <= 0; m[7:4] <= m[7:4] + 1h1; end end else begin m <= 1h0; if(h == 8h11) //AM / PM 轉換 p = !p; if(h < 8h12) begin if(h[3:0] < 4h9) h[3:0] <= h[3:0] + 1h1; else begin h[3:0] <= 4h0; h[7:4] <= h[7:4] + 1h1; end end else begin //hour 12 -> 1 h <= 1h1; end end end end end end
assign pm = p; assign hh = h; assign mm = m; assign ss = s;
endmodule
Problem 106 4-bit shift register
設計一個4bit非同步複位,擁有同步置位和使能的右移移位寄存器。
如果ena和load同時為高,load有更高的優先順序。
本題為4-bit的移位寄存器,在ena信號中所舉例子可以很好說明本題要求。q[3]q[2]q[1]q[0] ---> 0q[3]q[2]q[1]。
module top_module( input clk, input areset, // async active-high reset to zero input load, input ena, input [3:0] data, output reg [3:0] q);
always @ (posedge clk or posedge areset) begin if(areset) q <= 4b0; else if (load) q <= data; else if (ena) begin q[3:0] <= {1b0, q[3:1]}; //q[3]q[2]q[1]q[0] --> 0q[3]q[2]q[1],q[0]在移動後消失了,原先q[3]的位置變為0 end end
Problem 107 Left/right rotator
設計一個100bit的可左移或右移的移位寄存器,附帶同步置位和左移或右移的使能信號。本題中,移位寄存器在左移或右移時,不同於Problem106的補0和直接捨棄某一bit位,本題是要求在100bit內循環移動,不捨棄某一bit位同時也不補0。
比如說左移1bit,在Problem106就是補0和丟棄q[0]。而在本題中左移1bit為{q[0], q[99:1]}。
module top_module( input clk, input load, input [1:0] ena, input [99:0] data, output reg [99:0] q);
always @ (posedge clk) begin if(load) q <= data; else if (ena == 2b01) q <= {q[0], q[99:1]}; else if (ena == 2b10) q <= {q[98:0], q[99]}; else if (ena == 2b00 || ena == 2b11) q <= q; end
Problem 108 Left/right arithmetic shift by 1 or 8
設計一個64-bit帶同步置位的算術移位寄存器。該寄存器可以由amount控制來移動方向和每次移動的次數。
算術右移移位寄存器中的符號位(q [63])移位,不像是邏輯右移中進行補零的操作。而是保留符號位後再進行移位。
一個5-bit值為11000的寄存器算術右移一位後為11100, 而邏輯右移後為01100。
同樣的,一個5-bit值為01000的寄存器算術右移一位後為00100,且該寄存器邏輯右移會產生同樣的結果。
邏輯移位寄存器和算術左移移位寄存器沒有區別。
module top_module( input clk, input load, input ena, input [1:0] amount, input [63:0] data, output reg [63:0] q);
always @ (posedge clk) begin if(load) q <= data; else if (ena) begin case(amount) 2b00 : begin q <= {q[62:0], 1b0}; end
2b01: begin q <= {q[55:0], 8b0}; end
2b10: begin q <= {q[63], q[63:1]}; end
2b11: begin q <= {{8{q[63]}}, q[63-:56]}; //算術右移是用符號位填充和q的高56位 //{{8{q[63]}}, q[63-:56]} end endcase end end
Problem 109 5-bit LFSR
線性反饋移位寄存器(LFSR)是通常帶有幾個XOR門來產生下一狀態的移位寄存器。Galois LFSR是一個特殊的移位寄存器。其中帶有"tap"位的位置與輸出位XOR產生下一個值沒有"tap"位標誌的正常移位。如果"tap"位置經過仔細選擇後,LFSR將設置為最大長度。再重複之前LFSR的最大長度為2^n-1
下圖所示LFSR為在位置5和位置3包含"tap"位的5-bit最大長度LFSR。開始為位置1,輸入為0。
設計如上圖所示LFSR,複位信號使LFSR複位為1.
module top_module( input clk, input reset, // Active-high synchronous reset to 5h1 output [4:0] q ); always @ (posedge clk) begin if(reset) q <= 5b00001; else begin q[4] <= 1b0 ^ q[0]; q[3] <= q[4]; q[2] <= q[3] ^ q[0]; q[1] <= q[2]; q[0] <= q[1]; end end
推薦閱讀: