Verilog always语句练习题
本文章为练习Verilog语言,做个笔记,方便之后复习查阅,如有错误,欢迎斧正。
题目1:
Build an AND gate using both an assign statement and a combinational always block. (Since assign statements and combinational always blocks function identically, there is no way to enforce that you’re using both methods. But you’re here for practice, right?..)
我的解答:
// synthesis verilog_input_version verilog_2001
module top_module(
input a,
input b,
output wire out_assign,
output reg out_alwaysblock
);
assign out_assign = a & b;
always@(*)
out_alwaysblock = a & b;
endmodule
题目2:
Build an XOR gate three ways, using an assign statement, a combinational always block, and a clocked always block. Note that the clocked always block produces a different circuit from the other two: There is a flip-flop so the output is delayed.
我的解答:
// synthesis verilog_input_version verilog_2001
module top_module(
input clk,
input a,
input b,
output wire out_assign,
output reg out_always_comb,
output reg out_always_ff );
assign out_assign = a ^ b;
always @(*)
out_always_comb = a ^ b;
always @(posedge clk)
out_always_ff <= a ^ b;
endmodule
题目3:
Build a 2-to-1 mux that chooses between a and b. Choose b if both sel_b1 and sel_b2 are true. Otherwise, choose a. Do the same twice, once using assign statements and once using a procedural if statement.
我的解答:
module top_module(
input a,
input b,
input sel_b1,
input sel_b2,
output wire out_assign,
output reg out_always );
assign out_assign = (sel_b1 & sel_b2) ? b : a;
always @(*)
begin
if((sel_b1 == 1'b1) && (sel_b2 == 1'b1))
out_always <= b;
else
out_always <= a;
end
endmodule
题目4:
The following code contains incorrect behaviour that creates a latch. Fix the bugs so that you will shut off the computer only if it’s really overheated, and stop driving if you’ve arrived at your destination or you need to refuel.
我的修正代码:
// synthesis verilog_input_version verilog_2001
module top_module (
input cpu_overheated,
output reg shut_off_computer,
input arrived,
input gas_tank_empty,
output reg keep_driving ); //
always @(*) begin
if (cpu_overheated)
shut_off_computer = 1;
end
always @(*) begin
if (~arrived)
keep_driving = ~gas_tank_empty;
end
endmodule
题目5:
Case statements are more convenient than if statements if there are a large number of cases. So, in this exercise, create a 6-to-1 multiplexer. When sel is between 0 and 5, choose the corresponding data input. Otherwise, output 0. The data inputs and outputs are all 4 bits wide.
我的解答:
module top_module (
input [2:0] sel,
input [3:0] data0,
input [3:0] data1,
input [3:0] data2,
input [3:0] data3,
input [3:0] data4,
input [3:0] data5,
output reg [3:0] out );//
always@(*) begin // This is a combinational circuit
case(sel)
3'b000 : out = data0;
3'b001 : out = data1;
3'b010 : out = data2;
3'b011 : out = data3;
3'b100 : out = data4;
3'b101 : out = data5;
default : out = 4'b0000;
endcase
end
endmodule
题目6:
A priority encoder is a combinational circuit that, when given an input bit vector, outputs the position of the first 1 bit in the vector. For example, a 8-bit priority encoder given the input 8’b10010000 would output 3’d4, because bit[4] is first bit that is high.
Build a 4-bit priority encoder. For this problem, if none of the input bits are high (i.e., input is zero), output zero. Note that a 4-bit number has 16 possible combinations.
思考:四位数字有十六个组合,从第0位开始算。
我的解答:
module top_module (
input [3:0] in,
output reg [1:0] pos );
always@(*)
begin
case(in)
4'h2: pos = 2'd1;
4'h4: pos = 2'd2;
4'h6: pos = 2'd1;
4'h8: pos = 2'd3;
4'ha: pos = 2'd1;
4'hc: pos = 2'd2;
4'he: pos = 2'd1;
default: pos = 2'd0;
endcase
end
endmodule
官方solution:
module top_module (
input [3:0] in,
output reg [1:0] pos
);
always @(*) begin // Combinational always block
case (in)
4'h0: pos = 2'h0; // I like hexadecimal because it saves typing.
4'h1: pos = 2'h0;
4'h2: pos = 2'h1;
4'h3: pos = 2'h0;
4'h4: pos = 2'h2;
4'h5: pos = 2'h0;
4'h6: pos = 2'h1;
4'h7: pos = 2'h0;
4'h8: pos = 2'h3;
4'h9: pos = 2'h0;
4'ha: pos = 2'h1;
4'hb: pos = 2'h0;
4'hc: pos = 2'h2;
4'hd: pos = 2'h0;
4'he: pos = 2'h1;
4'hf: pos = 2'h0;
default: pos = 2'b0; // Default case is not strictly necessary because all 16 combinations are covered.
endcase
end
// There is an easier way to code this. See the next problem (always_casez).
endmodule
题目7:
A case statement behaves as though each item is checked sequentially (in reality, it does something more like generating a giant truth table then making gates). Notice how there are certain inputs (e.g., 4’b1111) that will match more than one case item. The first match is chosen (so 4’b1111 matches the first item, out = 0, but not any of the later ones).
There is also a similar casex that treats both x and z as don’t-care. I don’t see much purpose to using it over casez.
The digit ? is a synonym for z. so 2’bz0 is the same as 2’b?0
我的解答:
module top_module (
input [7:0] in,
output reg [2:0] pos );
always @(*) begin
casez(in)
8'bzzzz_zzz1: pos = 3'd0;
8'bzzzz_zz1z: pos = 3'd1;
8'bzzzz_z1zz: pos = 3'd2;
8'bzzzz_1zzz: pos = 3'd3;
8'bzzz1_zzzz: pos = 3'd4;
8'bzz1z_zzzz: pos = 3'd5;
8'bz1zz_zzzz: pos = 3'd6;
8'b1zzz_zzzz: pos = 3'd7;
default: pos = 3'd0;
endcase
end
endmodule
题目8:
Suppose you’re building a circuit to process scancodes from a PS/2 keyboard for a game. Given the last two bytes of scancodes received, you need to indicate whether one of the arrow keys on the keyboard have been pressed. This involves a fairly simple mapping, which can be implemented as a case statement (or if-elseif) with four cases.
Scancode [15:0] Arrow key
16’he06b left arrow
16’he072 down arrow
16’he074 right arrow
16’he075 up arrow
Anything else none
我的解答:
module top_module (
input [15:0] scancode,
output reg left,
output reg down,
output reg right,
output reg up );
always @(*)
begin
up = 1'b0; down = 1'b0; left = 1'b0; right = 1'b0;
if(scancode == 16'he06b)
left <= 1'b1;
else if(scancode == 16'he074)
right <= 1'b1;
else if(scancode == 16'he072)
down <= 1'b1;
else if(scancode == 16'he075)
up <= 1'b1;
else
begin
up <= 1'b0;
down <= 1'b0;
left <= 1'b0;
right <= 1'b0;
end
end
endmodule