首先附上传送门
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
推荐阅读: